mirror of
https://github.com/autc04/Retro68.git
synced 2025-08-09 20:25:29 +00:00
LaunchAPPLServer: refactoring
This commit is contained in:
@@ -55,8 +55,8 @@ public:
|
|||||||
virtual void flushWrite() override;
|
virtual void flushWrite() override;
|
||||||
|
|
||||||
|
|
||||||
virtual bool readyToWrite() { return packetsToSend.empty() && underlying().readyToWrite(); }
|
virtual bool readyToWrite() const override { return packetsToSend.empty() && underlying().readyToWrite(); }
|
||||||
bool allDataArrived() { return packetsToSend.empty() && sentPackets.empty() && underlying().readyToWrite(); }
|
virtual bool allDataArrived() const override { return packetsToSend.empty() && sentPackets.empty() && underlying().readyToWrite(); }
|
||||||
|
|
||||||
unsigned getFailedReceiveCount() const { return failedReceiveCount; }
|
unsigned getFailedReceiveCount() const { return failedReceiveCount; }
|
||||||
unsigned getFailedSendCount() const { return failedSendCount; }
|
unsigned getFailedSendCount() const { return failedSendCount; }
|
||||||
|
@@ -27,8 +27,10 @@ public:
|
|||||||
virtual void flushWrite() {}
|
virtual void flushWrite() {}
|
||||||
long read(void *p, size_t n);
|
long read(void *p, size_t n);
|
||||||
|
|
||||||
virtual bool readyToWrite() { return true; }
|
virtual bool readyToWrite() const { return true; }
|
||||||
bool readyToRead() { return !buffer_.empty(); }
|
bool readyToRead() const { return !buffer_.empty(); }
|
||||||
|
|
||||||
|
virtual bool allDataArrived() const { return true; }
|
||||||
protected:
|
protected:
|
||||||
void notifyReceive(const uint8_t* p, size_t n);
|
void notifyReceive(const uint8_t* p, size_t n);
|
||||||
void notifyReset();
|
void notifyReset();
|
||||||
|
@@ -68,9 +68,36 @@ struct Prefs
|
|||||||
};
|
};
|
||||||
|
|
||||||
Prefs gPrefs;
|
Prefs gPrefs;
|
||||||
|
|
||||||
|
void WritePrefs()
|
||||||
|
{
|
||||||
|
short refNum;
|
||||||
|
Create("\pLaunchAPPLServer Preferences", 0, 'R68L', 'LAPR');
|
||||||
|
if(OpenDF("\pLaunchAPPLServer Preferences", 0, &refNum) == noErr)
|
||||||
|
{
|
||||||
|
long count = sizeof(gPrefs);
|
||||||
|
FSWrite(refNum, &count, &gPrefs);
|
||||||
|
FSClose(refNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReadPrefs()
|
||||||
|
{
|
||||||
|
short refNum;
|
||||||
|
if(OpenDF("\pLaunchAPPLServer Preferences", 0, &refNum) == noErr)
|
||||||
|
{
|
||||||
|
long count = sizeof(gPrefs);
|
||||||
|
gPrefs.version = -1;
|
||||||
|
FSRead(refNum, &count, &gPrefs);
|
||||||
|
if(gPrefs.version != Prefs::currentVersion)
|
||||||
|
gPrefs = Prefs();
|
||||||
|
FSClose(refNum);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool gQuitting = false;
|
bool gQuitting = false;
|
||||||
|
|
||||||
void SetBaud(long baud);
|
void ConnectionChanged();
|
||||||
|
|
||||||
void ShowAboutBox()
|
void ShowAboutBox()
|
||||||
{
|
{
|
||||||
@@ -197,27 +224,79 @@ void DoMenuCommand(long menuCommand)
|
|||||||
{
|
{
|
||||||
GetMenuItemText(GetMenu(menuID), menuItem, str);
|
GetMenuItemText(GetMenu(menuID), menuItem, str);
|
||||||
StringToNum(str, &gPrefs.baud);
|
StringToNum(str, &gPrefs.baud);
|
||||||
SetBaud(gPrefs.baud);
|
|
||||||
}
|
}
|
||||||
|
ConnectionChanged();
|
||||||
}
|
}
|
||||||
HiliteMenu(0);
|
HiliteMenu(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<StatusDisplay> statusDisplay;
|
std::unique_ptr<StatusDisplay> statusDisplay;
|
||||||
|
|
||||||
|
class ConnectionProvider
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
StreamListener *listener;
|
||||||
|
public:
|
||||||
|
void setListener(StreamListener *l) { listener = l; }
|
||||||
|
|
||||||
|
virtual Stream* getStream() = 0;
|
||||||
|
virtual void idle() {}
|
||||||
|
virtual void suspend() {}
|
||||||
|
virtual void resume() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SerialConnectionProvider : public ConnectionProvider
|
||||||
|
{
|
||||||
|
struct Streams
|
||||||
|
{
|
||||||
|
MacSerialStream serialStream;
|
||||||
|
ReliableStream reliableStream;
|
||||||
|
|
||||||
|
Streams()
|
||||||
|
: serialStream(gPrefs.port, gPrefs.baud)
|
||||||
|
, reliableStream(&serialStream)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::unique_ptr<Streams> streams = std::make_unique<Streams>();
|
||||||
|
public:
|
||||||
|
virtual Stream* getStream()
|
||||||
|
{
|
||||||
|
return streams ? &streams->reliableStream : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void idle()
|
||||||
|
{
|
||||||
|
if(streams)
|
||||||
|
{
|
||||||
|
streams->reliableStream.setListener(listener);
|
||||||
|
streams->serialStream.idle();
|
||||||
|
statusDisplay->SetErrorCount(streams->reliableStream.getFailedReceiveCount()
|
||||||
|
+ streams->reliableStream.getFailedSendCount());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
virtual void suspend()
|
||||||
|
{
|
||||||
|
streams.reset();
|
||||||
|
}
|
||||||
|
virtual void resume()
|
||||||
|
{
|
||||||
|
if(!streams)
|
||||||
|
streams = std::make_unique<Streams>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<ConnectionProvider> connection;
|
||||||
|
|
||||||
class LaunchServer : public StreamListener
|
class LaunchServer : public StreamListener
|
||||||
{
|
{
|
||||||
Stream* stream;
|
|
||||||
|
|
||||||
uint32_t dataSize, rsrcSize;
|
uint32_t dataSize, rsrcSize;
|
||||||
uint32_t remainingSize;
|
uint32_t remainingSize;
|
||||||
short refNum;
|
short refNum;
|
||||||
public:
|
short outRefNum;
|
||||||
LaunchServer(Stream* stream) : stream(stream)
|
long outSize, outSizeRemaining;
|
||||||
{
|
std::unique_ptr<AppLauncher> appLauncher;
|
||||||
stream->setListener(this);
|
int nullEventCounter = 0;
|
||||||
}
|
|
||||||
|
|
||||||
enum class State
|
enum class State
|
||||||
{
|
{
|
||||||
@@ -234,6 +313,8 @@ public:
|
|||||||
|
|
||||||
OSType type, creator;
|
OSType type, creator;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
void onReset()
|
void onReset()
|
||||||
{
|
{
|
||||||
statusDisplay->SetStatus(AppStatus::ready, 0, 0);
|
statusDisplay->SetStatus(AppStatus::ready, 0, 0);
|
||||||
@@ -318,43 +399,122 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void idle()
|
||||||
|
{
|
||||||
|
++nullEventCounter;
|
||||||
|
connection->idle();
|
||||||
|
|
||||||
|
if(state == State::launch)
|
||||||
|
{
|
||||||
|
connection->suspend();
|
||||||
|
UnloadSeg((void*) &MacSerialStream::unloadSegDummy);
|
||||||
|
gPrefs.inSubLaunch = true;
|
||||||
|
WritePrefs();
|
||||||
|
|
||||||
|
if(command == RemoteCommand::upgradeLauncher)
|
||||||
|
{
|
||||||
|
if(creator == 'R68L' && type == 'APPL')
|
||||||
|
{
|
||||||
|
FSDelete("\pLaunchAPPLServer.old", 0);
|
||||||
|
Rename(LMGetCurApName(), 0, "\pLaunchAPPLServer.old");
|
||||||
|
Rename("\pRetro68App", 0, LMGetCurApName());
|
||||||
|
|
||||||
|
LaunchParamBlockRec lpb;
|
||||||
|
memset(&lpb, 0, sizeof(lpb));
|
||||||
|
lpb.reserved1 = (unsigned long) LMGetCurApName();
|
||||||
|
lpb.reserved2 = 0;
|
||||||
|
OSErr err = LaunchApplication(&lpb);
|
||||||
|
ExitToShell();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == 'MPST')
|
||||||
|
appLauncher = CreateToolLauncher();
|
||||||
|
else
|
||||||
|
appLauncher = CreateAppLauncher();
|
||||||
|
|
||||||
|
bool launched = appLauncher->Launch("\pRetro68App");
|
||||||
|
gPrefs.inSubLaunch = false;
|
||||||
|
WritePrefs();
|
||||||
|
|
||||||
|
if(launched)
|
||||||
|
{
|
||||||
|
state = State::wait;
|
||||||
|
nullEventCounter = 0;
|
||||||
|
|
||||||
|
statusDisplay->SetStatus(AppStatus::running, 0, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
state = State::command;
|
||||||
|
connection->resume();
|
||||||
|
statusDisplay->SetStatus(AppStatus::ready, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(state == State::wait && nullEventCounter > 3)
|
||||||
|
{
|
||||||
|
if(!appLauncher->IsRunning("\pRetro68App"))
|
||||||
|
{
|
||||||
|
appLauncher.reset();
|
||||||
|
UnloadSeg((void*) &CreateAppLauncher);
|
||||||
|
UnloadSeg((void*) &CreateToolLauncher);
|
||||||
|
connection->resume();
|
||||||
|
StartResponding();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(state == State::respond)
|
||||||
|
{
|
||||||
|
Stream *stream = connection->getStream();
|
||||||
|
while(outSizeRemaining && stream->readyToWrite())
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
long count = outSizeRemaining > 1024 ? 1024 : outSizeRemaining;
|
||||||
|
FSRead(outRefNum, &count, buf);
|
||||||
|
stream->write(buf, count);
|
||||||
|
outSizeRemaining -= count;
|
||||||
|
}
|
||||||
|
statusDisplay->SetStatus(AppStatus::uploading, outSize - outSizeRemaining, outSize);
|
||||||
|
|
||||||
|
if(outSizeRemaining == 0)
|
||||||
|
{
|
||||||
|
FSClose(outRefNum);
|
||||||
|
}
|
||||||
|
if(outSizeRemaining == 0 && stream->allDataArrived())
|
||||||
|
{
|
||||||
|
state = State::command;
|
||||||
|
statusDisplay->SetStatus(AppStatus::ready, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void StartResponding()
|
||||||
|
{
|
||||||
|
Stream *stream = connection->getStream();
|
||||||
|
|
||||||
|
state = State::respond;
|
||||||
|
uint32_t zero = 0;
|
||||||
|
stream->write(&zero, 4);
|
||||||
|
|
||||||
|
OpenDF("\pout", 0, &outRefNum);
|
||||||
|
GetEOF(outRefNum, &outSize);
|
||||||
|
outSizeRemaining = outSize;
|
||||||
|
statusDisplay->SetStatus(AppStatus::uploading, 0, outSize);
|
||||||
|
|
||||||
|
stream->write(&outSize, 4);
|
||||||
|
stream->flushWrite();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
short outRefNum;
|
LaunchServer server;
|
||||||
long outSize, outSizeRemaining;
|
|
||||||
MacSerialStream *gSerialStream;
|
|
||||||
int nullEventCounter = 0;
|
|
||||||
|
|
||||||
void SetBaud(long baud)
|
void ConnectionChanged()
|
||||||
{
|
{
|
||||||
gSerialStream->setBaud(baud);
|
connection = std::make_unique<SerialConnectionProvider>();
|
||||||
}
|
connection->setListener(&server);
|
||||||
|
server.onReset();
|
||||||
void StartResponding(LaunchServer& server, ReliableStream& rStream)
|
|
||||||
{
|
|
||||||
server.state = LaunchServer::State::respond;
|
|
||||||
uint32_t zero = 0;
|
|
||||||
rStream.write(&zero, 4);
|
|
||||||
|
|
||||||
OpenDF("\pout", 0, &outRefNum);
|
|
||||||
GetEOF(outRefNum, &outSize);
|
|
||||||
outSizeRemaining = outSize;
|
|
||||||
statusDisplay->SetStatus(AppStatus::uploading, 0, outSize);
|
|
||||||
|
|
||||||
rStream.write(&outSize, 4);
|
|
||||||
rStream.flushWrite();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WritePrefs()
|
|
||||||
{
|
|
||||||
short refNum;
|
|
||||||
Create("\pLaunchAPPLServer Preferences", 0, 'R68L', 'LAPR');
|
|
||||||
if(OpenDF("\pLaunchAPPLServer Preferences", 0, &refNum) == noErr)
|
|
||||||
{
|
|
||||||
long count = sizeof(gPrefs);
|
|
||||||
FSWrite(refNum, &count, &gPrefs);
|
|
||||||
FSClose(refNum);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pascal OSErr aeRun (const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
|
pascal OSErr aeRun (const AppleEvent *theAppleEvent, AppleEvent *reply, long handlerRefcon)
|
||||||
@@ -379,9 +539,8 @@ int main()
|
|||||||
{
|
{
|
||||||
// default stack size is 8KB on B&W macs
|
// default stack size is 8KB on B&W macs
|
||||||
// and 24 KB on Color macs.
|
// and 24 KB on Color macs.
|
||||||
// 8KB seems to be not quite enough,
|
// 8KB is too little as soon as we allocate a buffer on the stack.
|
||||||
// so increase stack size by 8KB.
|
// To allow that, increae stack size: SetApplLimit(GetApplLimit() - 8192);
|
||||||
SetApplLimit(GetApplLimit() - 8192);
|
|
||||||
MaxApplZone();
|
MaxApplZone();
|
||||||
#if !TARGET_API_MAC_CARBON
|
#if !TARGET_API_MAC_CARBON
|
||||||
InitGraf(&qd.thePort);
|
InitGraf(&qd.thePort);
|
||||||
@@ -440,38 +599,13 @@ int main()
|
|||||||
|
|
||||||
statusDisplay = std::make_unique<StatusDisplay>();
|
statusDisplay = std::make_unique<StatusDisplay>();
|
||||||
|
|
||||||
{
|
ReadPrefs();
|
||||||
short refNum;
|
ConnectionChanged();
|
||||||
if(OpenDF("\pLaunchAPPLServer Preferences", 0, &refNum) == noErr)
|
|
||||||
{
|
|
||||||
long count = sizeof(gPrefs);
|
|
||||||
gPrefs.version = -1;
|
|
||||||
FSRead(refNum, &count, &gPrefs);
|
|
||||||
if(gPrefs.version != Prefs::currentVersion)
|
|
||||||
gPrefs = Prefs();
|
|
||||||
FSClose(refNum);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
MacSerialStream stream(gPrefs.port, gPrefs.baud);
|
|
||||||
gSerialStream = &stream;
|
|
||||||
|
|
||||||
//#define SIMULATE_ERRORS
|
|
||||||
#ifdef SIMULATE_ERRORS
|
|
||||||
UnreliableStream uStream(stream);
|
|
||||||
ReliableStream rStream(&uStream);
|
|
||||||
#else
|
|
||||||
ReliableStream rStream(&stream);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LaunchServer server(&rStream);
|
|
||||||
|
|
||||||
std::unique_ptr<AppLauncher> appLauncher;
|
|
||||||
|
|
||||||
if(gPrefs.inSubLaunch)
|
if(gPrefs.inSubLaunch)
|
||||||
{
|
{
|
||||||
gPrefs.inSubLaunch = false;
|
gPrefs.inSubLaunch = false;
|
||||||
StartResponding(server, rStream);
|
server.StartResponding();
|
||||||
}
|
}
|
||||||
|
|
||||||
while(!gQuitting)
|
while(!gQuitting)
|
||||||
@@ -537,97 +671,9 @@ int main()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
nullEventCounter++;
|
|
||||||
|
|
||||||
if(server.state != LaunchServer::State::wait)
|
server.idle();
|
||||||
{
|
|
||||||
stream.idle();
|
|
||||||
statusDisplay->SetErrorCount(rStream.getFailedReceiveCount() + rStream.getFailedSendCount());
|
|
||||||
}
|
|
||||||
statusDisplay->Idle();
|
statusDisplay->Idle();
|
||||||
|
|
||||||
if(server.state == LaunchServer::State::launch)
|
|
||||||
{
|
|
||||||
gSerialStream->close();
|
|
||||||
UnloadSeg((void*) &MacSerialStream::unloadSegDummy);
|
|
||||||
gPrefs.inSubLaunch = true;
|
|
||||||
WritePrefs();
|
|
||||||
|
|
||||||
if(server.command == RemoteCommand::upgradeLauncher)
|
|
||||||
{
|
|
||||||
if(server.creator == 'R68L' && server.type == 'APPL')
|
|
||||||
{
|
|
||||||
FSDelete("\pLaunchAPPLServer.old", 0);
|
|
||||||
Rename(LMGetCurApName(), 0, "\pLaunchAPPLServer.old");
|
|
||||||
Rename("\pRetro68App", 0, LMGetCurApName());
|
|
||||||
|
|
||||||
LaunchParamBlockRec lpb;
|
|
||||||
memset(&lpb, 0, sizeof(lpb));
|
|
||||||
lpb.reserved1 = (unsigned long) LMGetCurApName();
|
|
||||||
lpb.reserved2 = 0;
|
|
||||||
OSErr err = LaunchApplication(&lpb);
|
|
||||||
ExitToShell();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(server.type == 'MPST')
|
|
||||||
appLauncher = CreateToolLauncher();
|
|
||||||
else
|
|
||||||
appLauncher = CreateAppLauncher();
|
|
||||||
|
|
||||||
bool launched = appLauncher->Launch("\pRetro68App");
|
|
||||||
gPrefs.inSubLaunch = false;
|
|
||||||
WritePrefs();
|
|
||||||
|
|
||||||
if(launched)
|
|
||||||
{
|
|
||||||
server.state = LaunchServer::State::wait;
|
|
||||||
nullEventCounter = 0;
|
|
||||||
|
|
||||||
statusDisplay->SetStatus(AppStatus::running, 0, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
server.state = LaunchServer::State::command;
|
|
||||||
gSerialStream->open();
|
|
||||||
statusDisplay->SetStatus(AppStatus::ready, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(server.state == LaunchServer::State::wait && nullEventCounter > 3)
|
|
||||||
{
|
|
||||||
if(!appLauncher->IsRunning("\pRetro68App"))
|
|
||||||
{
|
|
||||||
appLauncher.reset();
|
|
||||||
UnloadSeg((void*) &CreateAppLauncher);
|
|
||||||
UnloadSeg((void*) &CreateToolLauncher);
|
|
||||||
gSerialStream->open();
|
|
||||||
StartResponding(server, rStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(server.state == LaunchServer::State::respond)
|
|
||||||
{
|
|
||||||
while(outSizeRemaining && rStream.readyToWrite())
|
|
||||||
{
|
|
||||||
char buf[1024];
|
|
||||||
long count = outSizeRemaining > 1024 ? 1024 : outSizeRemaining;
|
|
||||||
FSRead(outRefNum, &count, buf);
|
|
||||||
rStream.write(buf, count);
|
|
||||||
outSizeRemaining -= count;
|
|
||||||
}
|
|
||||||
statusDisplay->SetStatus(AppStatus::uploading, outSize - outSizeRemaining, outSize);
|
|
||||||
|
|
||||||
if(outSizeRemaining == 0)
|
|
||||||
{
|
|
||||||
FSClose(outRefNum);
|
|
||||||
}
|
|
||||||
if(outSizeRemaining == 0 && rStream.allDataArrived())
|
|
||||||
{
|
|
||||||
server.state = LaunchServer::State::command;
|
|
||||||
statusDisplay->SetStatus(AppStatus::ready, 0, 0);
|
|
||||||
rStream.reset(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WritePrefs();
|
WritePrefs();
|
||||||
|
@@ -21,7 +21,7 @@ class StatusDisplay
|
|||||||
long startTime;
|
long startTime;
|
||||||
long speed = -1;
|
long speed = -1;
|
||||||
long timeRemaining = -1;
|
long timeRemaining = -1;
|
||||||
int errorCount;
|
int errorCount = -1;
|
||||||
|
|
||||||
RgnHandle background;
|
RgnHandle background;
|
||||||
Rect statusRect;
|
Rect statusRect;
|
||||||
|
Reference in New Issue
Block a user