From d16f1aae6bc50fd0a1abd32ba4ae949853b485ab Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Wed, 23 Jan 2019 19:41:12 +0100 Subject: [PATCH] LaunchAPPL: shared file transport --- LaunchAPPL/Client/CMakeLists.txt | 4 +- LaunchAPPL/Client/LaunchAPPL.cc | 4 +- LaunchAPPL/Client/Serial.cc | 97 +------ LaunchAPPL/Client/SharedFile.cc | 99 +++++++ LaunchAPPL/Client/SharedFile.h | 13 + LaunchAPPL/Client/StreamBasedLauncher.cc | 91 +++++++ LaunchAPPL/Client/StreamBasedLauncher.h | 26 ++ LaunchAPPL/Client/TCP.cc | 99 +------ LaunchAPPL/Common/Stream.h | 6 + LaunchAPPL/LaunchAPPL.cfg.example | 10 + LaunchAPPL/Server/AboutBox.cc | 19 ++ LaunchAPPL/Server/AboutBox.h | 19 ++ LaunchAPPL/Server/AppLauncher.cc | 19 ++ LaunchAPPL/Server/AppLauncher.h | 19 ++ LaunchAPPL/Server/CMakeLists.txt | 11 +- LaunchAPPL/Server/CarbonFileCompat.h | 19 ++ LaunchAPPL/Server/ConnectionProvider.h | 19 ++ LaunchAPPL/Server/LaunchAPPLServer.cc | 58 +++-- LaunchAPPL/Server/LaunchAPPLServer.r | 81 +++++- LaunchAPPL/Server/LaunchAPPLServer.segmap | 3 + LaunchAPPL/Server/LauncherIcon.r | 19 ++ LaunchAPPL/Server/MacSerialStream.cc | 19 ++ LaunchAPPL/Server/MacSerialStream.h | 19 ++ LaunchAPPL/Server/MacTCPStream.cc | 19 ++ LaunchAPPL/Server/MacTCPStream.h | 19 ++ .../Server/OpenTptConnectionProvider.cc | 19 ++ LaunchAPPL/Server/OpenTptConnectionProvider.h | 19 ++ LaunchAPPL/Server/OpenTptStream.cc | 19 ++ LaunchAPPL/Server/OpenTptStream.h | 19 ++ LaunchAPPL/Server/Preferences.cc | 243 ++++++++++++++++++ LaunchAPPL/Server/Preferences.h | 48 ++++ LaunchAPPL/Server/SerialConnectionProvider.cc | 19 ++ LaunchAPPL/Server/SerialConnectionProvider.h | 19 ++ LaunchAPPL/Server/SharedFileProvider.cc | 54 ++++ LaunchAPPL/Server/SharedFileProvider.h | 41 +++ LaunchAPPL/Server/SharedFileStream.cc | 137 ++++++++++ LaunchAPPL/Server/SharedFileStream.h | 43 ++++ LaunchAPPL/Server/StatusDisplay.cc | 20 +- LaunchAPPL/Server/StatusDisplay.h | 20 ++ LaunchAPPL/Server/SystemInfo.h | 20 ++ LaunchAPPL/Server/TCPConnectionProvider.cc | 20 +- LaunchAPPL/Server/TCPConnectionProvider.h | 19 ++ LaunchAPPL/Server/ToolLauncher.cc | 19 ++ LaunchAPPL/Server/Window.h | 19 ++ README.md | 1 + 45 files changed, 1416 insertions(+), 213 deletions(-) create mode 100644 LaunchAPPL/Client/SharedFile.cc create mode 100644 LaunchAPPL/Client/SharedFile.h create mode 100644 LaunchAPPL/Client/StreamBasedLauncher.cc create mode 100644 LaunchAPPL/Client/StreamBasedLauncher.h create mode 100644 LaunchAPPL/Server/Preferences.cc create mode 100644 LaunchAPPL/Server/Preferences.h create mode 100644 LaunchAPPL/Server/SharedFileProvider.cc create mode 100644 LaunchAPPL/Server/SharedFileProvider.h create mode 100644 LaunchAPPL/Server/SharedFileStream.cc create mode 100644 LaunchAPPL/Server/SharedFileStream.h diff --git a/LaunchAPPL/Client/CMakeLists.txt b/LaunchAPPL/Client/CMakeLists.txt index 900b66fcca..cc7b179f93 100644 --- a/LaunchAPPL/Client/CMakeLists.txt +++ b/LaunchAPPL/Client/CMakeLists.txt @@ -3,9 +3,11 @@ find_package(Boost COMPONENTS filesystem program_options) set(LAUNCHMETHODS Executor.h Executor.cc MiniVMac.h MiniVMac.cc - SSH.h SSH.cc + SSH.h SSH.cc + StreamBasedLauncher.h StreamBasedLauncher.cc Serial.h Serial.cc TCP.h TCP.cc + SharedFile.h SharedFile.cc ) if(APPLE) diff --git a/LaunchAPPL/Client/LaunchAPPL.cc b/LaunchAPPL/Client/LaunchAPPL.cc index e1c44937b8..8d98707286 100644 --- a/LaunchAPPL/Client/LaunchAPPL.cc +++ b/LaunchAPPL/Client/LaunchAPPL.cc @@ -22,6 +22,7 @@ #include "SSH.h" #include "Serial.h" #include "TCP.h" +#include "SharedFile.h" namespace po = boost::program_options; namespace fs = boost::filesystem; @@ -46,7 +47,8 @@ static void RegisterLaunchMethods() new Executor(), new MiniVMac(), new SSH(), new Serial(), - new TCP() + new TCP(), + new SharedFile() // #### Add new `LaunchMethod`s here. }; diff --git a/LaunchAPPL/Client/Serial.cc b/LaunchAPPL/Client/Serial.cc index 3a43d89479..9f1319723d 100644 --- a/LaunchAPPL/Client/Serial.cc +++ b/LaunchAPPL/Client/Serial.cc @@ -1,5 +1,5 @@ #include "Serial.h" -#include "Launcher.h" +#include "StreamBasedLauncher.h" #include "Utilities.h" #include "Stream.h" #include "ReliableStream.h" @@ -15,7 +15,7 @@ namespace po = boost::program_options; using namespace std::literals::chrono_literals; -class SerialStream : public Stream +class SerialStream : public WaitableStream { static const long kReadBufferSize = 4096; uint8_t readBuffer[kReadBufferSize]; @@ -25,28 +25,18 @@ public: virtual void write(const void* p, size_t n) override; - void wait(); + virtual void wait() override; SerialStream(po::variables_map &options); ~SerialStream(); }; -class SerialLauncher : public Launcher +class SerialLauncher : public StreamBasedLauncher { SerialStream stream; ReliableStream rStream; - std::vector outputBytes; - bool upgradeMode = false; public: SerialLauncher(po::variables_map& options); - virtual ~SerialLauncher(); - - virtual bool Go(int timeout = 0); - virtual void DumpOutput(); - -private: - void write(const void *p, size_t n); - size_t read(void * p, size_t n); }; @@ -128,41 +118,10 @@ void SerialStream::wait() } } - SerialLauncher::SerialLauncher(po::variables_map &options) - : Launcher(options), stream(options), rStream(&stream) + : StreamBasedLauncher(options), stream(options), rStream(&stream) { - if(options.count("upgrade-server")) - upgradeMode = true; -} - -SerialLauncher::~SerialLauncher() -{ -} - -size_t SerialLauncher::read(void *p0, size_t n) -{ - uint8_t* p = (uint8_t*)p0; - size_t gotBytes = rStream.read(p, n); - while(gotBytes < n) - { - rStream.flushWrite(); - stream.wait(); - gotBytes += rStream.read(p + gotBytes, n - gotBytes); - } - return gotBytes; -} - -void SerialLauncher::write(const void *p, size_t n) -{ - while(!rStream.readyToWrite()) - stream.wait(); - rStream.write(p, n); -} - -bool SerialLauncher::Go(int timeout) -{ - uint32_t tmp; + SetupStream(&stream, &rStream); do { @@ -175,50 +134,6 @@ bool SerialLauncher::Go(int timeout) } while(!rStream.resetResponseArrived()); std::cerr << "Connected." << std::endl; - - { - RemoteCommand cmd = upgradeMode ? RemoteCommand::upgradeLauncher : RemoteCommand::launchApp; - write(&cmd, 1); - - write(std::string(app.type).data(), 4); - write(std::string(app.creator).data(), 4); - - std::ostringstream rsrcOut; - app.resources.writeFork(rsrcOut); - std::string rsrc = rsrcOut.str(); - std::string& data = app.data; - std::cerr << "Transfering " << (data.size() + rsrc.size() + 1023) / 1024 << " KB." << std::endl; - - tmp = htonl(data.size()); - write(&tmp, 4); - tmp = htonl(rsrc.size()); - write(&tmp, 4); - - write(data.data(), data.size()); - write(rsrc.data(), rsrc.size()); - } - while(!rStream.allDataArrived()) - stream.wait(); - std::cerr << "Running Appliation..." << std::endl; - read(&tmp, 4); - uint32_t result = ntohl(tmp); - std::cerr << "Finished (result = " << result << ")." << std::endl; - - if(result == 0) - { - read(&tmp, 4); - uint32_t size = ntohl(tmp); - outputBytes.resize(size); - if(size > 0) - read(outputBytes.data(), size); - } - - return result == 0; -} - -void SerialLauncher::DumpOutput() -{ - std::cout.write(outputBytes.data(), outputBytes.size()); } void Serial::GetOptions(options_description &desc) diff --git a/LaunchAPPL/Client/SharedFile.cc b/LaunchAPPL/Client/SharedFile.cc new file mode 100644 index 0000000000..96ea07b65c --- /dev/null +++ b/LaunchAPPL/Client/SharedFile.cc @@ -0,0 +1,99 @@ +#include "SharedFile.h" +#include "StreamBasedLauncher.h" +#include "Utilities.h" +#include "Stream.h" +#include "ServerProtocol.h" +#include +#include +#include + +namespace fs = boost::filesystem; +namespace po = boost::program_options; +using namespace std::literals::chrono_literals; + +class SharedFileStream : public WaitableStream +{ + static const long kReadBufferSize = 4096; + uint8_t readBuffer[kReadBufferSize]; + fs::path shared_directory; +public: + + virtual void write(const void* p, size_t n) override; + + virtual void wait() override; + + SharedFileStream(po::variables_map &options); + ~SharedFileStream(); +}; + +class SharedFileLauncher : public StreamBasedLauncher +{ + SharedFileStream stream; +public: + SharedFileLauncher(po::variables_map& options); +}; + +SharedFileStream::SharedFileStream(po::variables_map &options) +{ + shared_directory = options["shared-directory"].as(); +} + +SharedFileStream::~SharedFileStream() +{ +} + +void SharedFileStream::write(const void* p, size_t n) +{ + if(n == 0) + return; + + { + fs::ofstream out(shared_directory / "in_channel_1", std::ios::binary); + out.write((const char*)p, n); + } + + fs::rename(shared_directory / "in_channel_1", shared_directory / "in_channel"); + + do + { + usleep(100000); + } while(fs::exists(shared_directory / "in_channel")); +} + +void SharedFileStream::wait() +{ + usleep(100000); + if(fs::exists(shared_directory / "out_channel")) + { + { + fs::ifstream in(shared_directory / "out_channel"); + + while(in.read((char*)readBuffer, sizeof(readBuffer)), in.gcount() > 0) + notifyReceive(readBuffer, in.gcount()); + } + fs::remove(shared_directory / "out_channel"); + } +} + +SharedFileLauncher::SharedFileLauncher(po::variables_map &options) + : StreamBasedLauncher(options), stream(options) +{ + SetupStream(&stream); +} + +void SharedFile::GetOptions(options_description &desc) +{ + desc.add_options() + ("shared-directory", po::value(), "Path to a directory shared with the old mac") + ; +} + +bool SharedFile::CheckOptions(variables_map &options) +{ + return options.count("shared-directory") != 0; +} + +std::unique_ptr SharedFile::MakeLauncher(variables_map &options) +{ + return std::unique_ptr(new SharedFileLauncher(options)); +} diff --git a/LaunchAPPL/Client/SharedFile.h b/LaunchAPPL/Client/SharedFile.h new file mode 100644 index 0000000000..7554c67023 --- /dev/null +++ b/LaunchAPPL/Client/SharedFile.h @@ -0,0 +1,13 @@ +#pragma once + +#include "LaunchMethod.h" + +class SharedFile : public LaunchMethod +{ +public: + virtual std::string GetName() { return "shared"; } + virtual void GetOptions(options_description& desc); + virtual bool CheckOptions(variables_map& options); + + virtual std::unique_ptr MakeLauncher(variables_map& options); +}; diff --git a/LaunchAPPL/Client/StreamBasedLauncher.cc b/LaunchAPPL/Client/StreamBasedLauncher.cc new file mode 100644 index 0000000000..d1e330087d --- /dev/null +++ b/LaunchAPPL/Client/StreamBasedLauncher.cc @@ -0,0 +1,91 @@ +#include "StreamBasedLauncher.h" +#include "Stream.h" +#include "ServerProtocol.h" +#include + +StreamBasedLauncher::StreamBasedLauncher(boost::program_options::variables_map &options) + : Launcher(options) +{ + if(options.count("upgrade-server")) + upgradeMode = true; +} + +StreamBasedLauncher::~StreamBasedLauncher() +{ +} + +void StreamBasedLauncher::SetupStream(WaitableStream* aStream, Stream* wrapped) +{ + this->stream = aStream; + this->rStream = wrapped ? wrapped : aStream; +} + +ssize_t StreamBasedLauncher::read(void *p0, size_t n) +{ + uint8_t* p = (uint8_t*)p0; + size_t gotBytes = rStream->read(p, n); + while(gotBytes < n) + { + rStream->flushWrite(); + stream->wait(); + gotBytes += rStream->read(p + gotBytes, n - gotBytes); + } + return gotBytes; +} + +void StreamBasedLauncher::write(const void *p, size_t n) +{ + while(!rStream->readyToWrite()) + stream->wait(); + rStream->write(p, n); +} + +bool StreamBasedLauncher::Go(int timeout) +{ + uint32_t tmp; + + { + RemoteCommand cmd = upgradeMode ? RemoteCommand::upgradeLauncher : RemoteCommand::launchApp; + write(&cmd, 1); + + write(std::string(app.type).data(), 4); + write(std::string(app.creator).data(), 4); + + std::ostringstream rsrcOut; + app.resources.writeFork(rsrcOut); + std::string rsrc = rsrcOut.str(); + std::string& data = app.data; + std::cerr << "Transferring " << (data.size() + rsrc.size() + 1023) / 1024 << " KB." << std::endl; + + tmp = htonl(data.size()); + write(&tmp, 4); + tmp = htonl(rsrc.size()); + write(&tmp, 4); + + write(data.data(), data.size()); + write(rsrc.data(), rsrc.size()); + } + + while(!rStream->allDataArrived()) + stream->wait(); + std::cerr << "Running Appliation..." << std::endl; + read(&tmp, 4); + uint32_t result = ntohl(tmp); + std::cerr << "Finished (result = " << result << ")." << std::endl; + + if(result == 0) + { + read(&tmp, 4); + uint32_t size = ntohl(tmp); + outputBytes.resize(size); + if(size > 0) + read(outputBytes.data(), size); + } + + return result == 0; +} + +void StreamBasedLauncher::DumpOutput() +{ + std::cout.write(outputBytes.data(), outputBytes.size()); +} diff --git a/LaunchAPPL/Client/StreamBasedLauncher.h b/LaunchAPPL/Client/StreamBasedLauncher.h new file mode 100644 index 0000000000..cda6867aad --- /dev/null +++ b/LaunchAPPL/Client/StreamBasedLauncher.h @@ -0,0 +1,26 @@ +#pragma once +#include "Launcher.h" +#include + +class Stream; +class WaitableStream; + +class StreamBasedLauncher : public Launcher +{ + WaitableStream *stream; + Stream *rStream; + std::vector outputBytes; + bool upgradeMode = false; +public: + StreamBasedLauncher(boost::program_options::variables_map& options); + virtual ~StreamBasedLauncher(); + + virtual bool Go(int timeout = 0); + virtual void DumpOutput(); + +protected: + void SetupStream(WaitableStream* aStream, Stream* wrapped = nullptr); +private: + void write(const void *p, size_t n); + ssize_t read(void * p, size_t n); +}; diff --git a/LaunchAPPL/Client/TCP.cc b/LaunchAPPL/Client/TCP.cc index dd731b0c12..00c9c592fb 100644 --- a/LaunchAPPL/Client/TCP.cc +++ b/LaunchAPPL/Client/TCP.cc @@ -1,5 +1,5 @@ #include "TCP.h" -#include "Launcher.h" +#include "StreamBasedLauncher.h" #include "Utilities.h" #include "Stream.h" #include "ServerProtocol.h" @@ -14,7 +14,7 @@ namespace po = boost::program_options; using namespace std::literals::chrono_literals; -class TCPStream : public Stream +class TCPStream : public WaitableStream { static const long kReadBufferSize = 4096; @@ -24,28 +24,17 @@ public: virtual void write(const void* p, size_t n) override; - void wait(); + virtual void wait() override; TCPStream(po::variables_map &options); ~TCPStream(); }; -class TCPLauncher : public Launcher +class TCPLauncher : public StreamBasedLauncher { TCPStream stream; - TCPStream& rStream = stream; - std::vector outputBytes; - bool upgradeMode = false; public: TCPLauncher(po::variables_map& options); - virtual ~TCPLauncher(); - - virtual bool Go(int timeout = 0); - virtual void DumpOutput(); - -private: - void write(const void *p, size_t n); - ssize_t read(void * p, size_t n); }; @@ -81,86 +70,10 @@ void TCPStream::wait() notifyReceive(readBuffer, n); } - TCPLauncher::TCPLauncher(po::variables_map &options) - : Launcher(options), stream(options) + : StreamBasedLauncher(options), stream(options) { - if(options.count("upgrade-server")) - upgradeMode = true; -} - -TCPLauncher::~TCPLauncher() -{ -} - -ssize_t TCPLauncher::read(void *p0, size_t n) -{ - uint8_t* p = (uint8_t*)p0; - size_t gotBytes = rStream.read(p, n); - while(gotBytes < n) - { - rStream.flushWrite(); - stream.wait(); - gotBytes += rStream.read(p + gotBytes, n - gotBytes); - } - return gotBytes; -} - -void TCPLauncher::write(const void *p, size_t n) -{ - while(!rStream.readyToWrite()) - stream.wait(); - rStream.write(p, n); -} - -bool TCPLauncher::Go(int timeout) -{ - uint32_t tmp; - - - { - RemoteCommand cmd = upgradeMode ? RemoteCommand::upgradeLauncher : RemoteCommand::launchApp; - write(&cmd, 1); - - write(std::string(app.type).data(), 4); - write(std::string(app.creator).data(), 4); - - std::ostringstream rsrcOut; - app.resources.writeFork(rsrcOut); - std::string rsrc = rsrcOut.str(); - std::string& data = app.data; - std::cerr << "Transfering " << (data.size() + rsrc.size() + 1023) / 1024 << " KB." << std::endl; - - tmp = htonl(data.size()); - write(&tmp, 4); - tmp = htonl(rsrc.size()); - write(&tmp, 4); - - write(data.data(), data.size()); - write(rsrc.data(), rsrc.size()); - } - while(!rStream.allDataArrived()) - stream.wait(); - std::cerr << "Running Appliation..." << std::endl; - read(&tmp, 4); - uint32_t result = ntohl(tmp); - std::cerr << "Finished (result = " << result << ")." << std::endl; - - if(result == 0) - { - read(&tmp, 4); - uint32_t size = ntohl(tmp); - outputBytes.resize(size); - if(size > 0) - read(outputBytes.data(), size); - } - - return result == 0; -} - -void TCPLauncher::DumpOutput() -{ - std::cout.write(outputBytes.data(), outputBytes.size()); + SetupStream(&stream); } void TCP::GetOptions(options_description &desc) diff --git a/LaunchAPPL/Common/Stream.h b/LaunchAPPL/Common/Stream.h index 4104b33941..2bf1bdc4c2 100644 --- a/LaunchAPPL/Common/Stream.h +++ b/LaunchAPPL/Common/Stream.h @@ -36,6 +36,12 @@ protected: void notifyReset(); }; +class WaitableStream : public Stream +{ +public: + virtual void wait() = 0; +}; + class StreamWrapper : public Stream, private StreamListener { Stream* underlying_; diff --git a/LaunchAPPL/LaunchAPPL.cfg.example b/LaunchAPPL/LaunchAPPL.cfg.example index 81de764f00..a82c192076 100644 --- a/LaunchAPPL/LaunchAPPL.cfg.example +++ b/LaunchAPPL/LaunchAPPL.cfg.example @@ -54,6 +54,16 @@ # emulator = tcp # tcp-address = 192.168.0.42 # IP address of your mac +# ########### A real Mac or emulator that can access a shared volume + + # Prerequisited: + # - LaunchAPPLServer compiled by Retro68 for your Mac or emulator + # - A volume or folder shared between your classic Mac/emulator and the computer you're running LaunchAPPL on + + # For example, this can be SheepShaver or Basilisk with their built-in shared folder support. + +# emulator = shared +# shared-directory = /path/to/some/empty/directory # ########### Mini vMac (old 68K Macs) diff --git a/LaunchAPPL/Server/AboutBox.cc b/LaunchAPPL/Server/AboutBox.cc index 2972567e2b..2278867668 100644 --- a/LaunchAPPL/Server/AboutBox.cc +++ b/LaunchAPPL/Server/AboutBox.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "AboutBox.h" #include #include diff --git a/LaunchAPPL/Server/AboutBox.h b/LaunchAPPL/Server/AboutBox.h index dcff30432d..f1443c8d3a 100644 --- a/LaunchAPPL/Server/AboutBox.h +++ b/LaunchAPPL/Server/AboutBox.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include "Window.h" diff --git a/LaunchAPPL/Server/AppLauncher.cc b/LaunchAPPL/Server/AppLauncher.cc index 62572b352c..d5b65f3e24 100644 --- a/LaunchAPPL/Server/AppLauncher.cc +++ b/LaunchAPPL/Server/AppLauncher.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "AppLauncher.h" #include diff --git a/LaunchAPPL/Server/AppLauncher.h b/LaunchAPPL/Server/AppLauncher.h index c48b2ddef8..6a2141500b 100644 --- a/LaunchAPPL/Server/AppLauncher.h +++ b/LaunchAPPL/Server/AppLauncher.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include diff --git a/LaunchAPPL/Server/CMakeLists.txt b/LaunchAPPL/Server/CMakeLists.txt index 37f313f425..c6c069944d 100644 --- a/LaunchAPPL/Server/CMakeLists.txt +++ b/LaunchAPPL/Server/CMakeLists.txt @@ -25,6 +25,13 @@ else() ) endif() +list(APPEND CONNECTION_SOURCES + SharedFileStream.h + SharedFileStream.cc + SharedFileProvider.h + SharedFileProvider.cc +) + option(LAUNCHAPPLSERVER_DEBUG_CONSOLE "Add a debug console to LaunchAPPLServer" FALSE) set(MAYBE_CONSOLE) @@ -50,6 +57,8 @@ add_application(LaunchAPPLServer AboutBox.cc ConnectionProvider.h CarbonFileCompat.h + Preferences.h + Preferences.cc ${CONNECTION_SOURCES} ) @@ -73,7 +82,7 @@ else() endif() if(CMAKE_SYSTEM_NAME MATCHES RetroPPC) - target_link_libraries(LaunchAPPLServer -lOpenTransportAppPPC -lOpenTransportLib -lOpenTptInternetLib ) + target_link_libraries(LaunchAPPLServer -lOpenTransportAppPPC -lOpenTransportLib -lOpenTptInternetLib -lNavigationLib) endif() if(FALSE) diff --git a/LaunchAPPL/Server/CarbonFileCompat.h b/LaunchAPPL/Server/CarbonFileCompat.h index 0a69114a18..1eedf1a406 100644 --- a/LaunchAPPL/Server/CarbonFileCompat.h +++ b/LaunchAPPL/Server/CarbonFileCompat.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include diff --git a/LaunchAPPL/Server/ConnectionProvider.h b/LaunchAPPL/Server/ConnectionProvider.h index e2fc3226a7..aa5aabcd3d 100644 --- a/LaunchAPPL/Server/ConnectionProvider.h +++ b/LaunchAPPL/Server/ConnectionProvider.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once class StreamListener; diff --git a/LaunchAPPL/Server/LaunchAPPLServer.cc b/LaunchAPPL/Server/LaunchAPPLServer.cc index 662cc3872b..8ceb8d25da 100644 --- a/LaunchAPPL/Server/LaunchAPPLServer.cc +++ b/LaunchAPPL/Server/LaunchAPPLServer.cc @@ -1,5 +1,5 @@ /* - Copyright 2018 Wolfgang Thaller. + Copyright 2019 Wolfgang Thaller. This file is part of Retro68. @@ -34,6 +34,7 @@ #include "AppLauncher.h" #include "StatusDisplay.h" #include "AboutBox.h" +#include "Preferences.h" #include #include @@ -48,6 +49,7 @@ #if !TARGET_CPU_68K #include "OpenTptConnectionProvider.h" #endif +#include "SharedFileProvider.h" #include "SystemInfo.h" @@ -68,33 +70,19 @@ enum kItemAbout = 1, kItemClose = 1, - kItemQuit = 3 -}; + kItemQuit = 3, -enum class Port : int -{ - modemPort = 0, - printerPort, - macTCP, - openTptTCP + kItemChooseFolder = 14 }; #if TARGET_API_MAC_CARBON -bool portsAvailable[] = { false, false, false, false }; +bool portsAvailable[] = { false, false, false, false, true }; #else -bool portsAvailable[] = { true, true, false, false }; +bool portsAvailable[] = { true, true, false, false, true }; #endif bool hasIconUtils = true; bool hasColorQD = true; - -struct Prefs -{ - const static int currentVersion = 1; - int version = currentVersion; - Port port = Port::modemPort; - long baud = 19200; - bool inSubLaunch = false; -}; +bool hasSys7StdFile = true; Prefs gPrefs; @@ -170,7 +158,9 @@ void UpdateMenus() CheckMenuItem(m, 3, gPrefs.port == Port::modemPort); SetItemEnabled(m, 4, portsAvailable[(int)Port::printerPort]); CheckMenuItem(m, 4, gPrefs.port == Port::printerPort); - for(int i = 6; i <= CountMenuItems(m); i++) + SetItemEnabled(m, 5, portsAvailable[(int)Port::sharedFiles]); + CheckMenuItem(m, 5, gPrefs.port == Port::sharedFiles); + for(int i = 7; i < kItemChooseFolder; i++) { Str255 str; long baud; @@ -250,6 +240,13 @@ void DoMenuCommand(long menuCommand) case 4: gPrefs.port = Port::printerPort; break; + case 5: + gPrefs.port = Port::sharedFiles; + break; + case kItemChooseFolder: + ChooseSharedDirectory(); + UnloadSeg((void*) &ChooseSharedDirectory); + break; default: GetMenuItemText(GetMenuHandle(menuID), menuItem, str); StringToNum(str, &gPrefs.baud); @@ -301,7 +298,7 @@ public: size_t onReceive(const uint8_t* p, size_t n) { #ifdef DEBUG_CONSOLE -// printf("Received %d bytes in state %d.\n", (int)n, (int)state); + printf("Received %d bytes in state %d.\n", (int)n, (int)state); #endif switch(state) { @@ -546,8 +543,13 @@ LaunchServer server; void ConnectionChanged() { + void *connectionSeg = connection ? connection->segmentToUnload() : nullptr; + connection.reset(); // deallocate before we create the new provider + if(connectionSeg) + UnloadSeg(connectionSeg); + bool first = true; for(;;) { @@ -582,6 +584,15 @@ void ConnectionChanged() connection = std::make_unique(statusDisplay.get());; break; #endif + case Port::sharedFiles: + if(gPrefs.sharedDirectoryPath[0] == 0) + { + ChooseSharedDirectory(); + UnloadSeg((void*) &ChooseSharedDirectory); + } + if(gPrefs.sharedDirectoryPath[0] != 0) + connection = std::make_unique(statusDisplay.get());; + break; default: ; } @@ -657,6 +668,9 @@ int main() err = Gestalt(gestaltQuickdrawVersion, &response); hasColorQD = err == noErr && response != 0; + + err = Gestalt(gestaltStandardFileAttr, &response); + hasSys7StdFile = err == noErr && (response & (1 << gestaltStandardFile58)) != 0; } } #else diff --git a/LaunchAPPL/Server/LaunchAPPLServer.r b/LaunchAPPL/Server/LaunchAPPLServer.r index 7e568394a6..df1ed94d07 100644 --- a/LaunchAPPL/Server/LaunchAPPLServer.r +++ b/LaunchAPPL/Server/LaunchAPPLServer.r @@ -1,5 +1,5 @@ /* - Copyright 2018 Wolfgang Thaller. + Copyright 2019 Wolfgang Thaller. This file is part of Retro68. @@ -22,6 +22,7 @@ #include "Windows.r" #include "MacTypes.r" #include "Finder.r" +#include "Dialogs.r" resource 'MENU' (128) { 128, textMenuProc; @@ -67,6 +68,7 @@ resource 'MENU' (131) { "OpenTransport TCP", noIcon, noKey, noMark, plain; "Modem Port", noIcon, noKey, noMark, plain; "Printer Port", noIcon, noKey, noMark, plain; + "Shared Files", noIcon, noKey, noMark, plain; "-", noIcon, noKey, noMark, plain; "9600", noIcon, noKey, noMark, plain; "19200", noIcon, noKey, check, plain; @@ -74,6 +76,8 @@ resource 'MENU' (131) { "57600", noIcon, noKey, noMark, plain; "115200", noIcon, noKey, noMark, plain; "230400", noIcon, noKey, noMark, plain; + "-", noIcon, noKey, noMark, plain; + "Choose Shared Directory...", noIcon, noKey, noMark, plain; } }; @@ -115,6 +119,7 @@ resource 'STR#' (128, purgeable) { "Listening on Printer Port..."; "Listening on TCP port 1984 (MacTCP)..."; "Listening on TCP port 1984 (OpenTransport)..."; + "Waiting for shared files..."; "Downloading Application..."; "Downloading Upgrade..."; "Running Application..."; @@ -151,7 +156,7 @@ resource 'SIZE' (-1) { notDisplayManagerAware, reserved, reserved, - 350 * 1024, + 500 * 1024, 136 * 1024 }; @@ -178,3 +183,75 @@ resource 'BNDL' (128, purgeable) { } } }; + +resource 'DLOG' (128, purgeable) +{ + {0, 0, 225, 348}, + dBoxProc, + invisible, + noGoAway, + 0x0, + 128, + "", + noAutoCenter +}; + +resource 'DITL' (128, purgeable) +{ + { + /* [1] */ + {138, 256, 156, 336}, + Button { enabled, "Open" }, + /* [2] */ + {1152, 59, 1232, 77}, + Button { enabled, "" }, + /* [3] */ + {188, 256, 206, 336}, + Button { enabled, "Cancel" }, + /* [4] */ + {39, 232, 59, 347}, + UserItem { disabled }, + /* [5] */ + {68, 256, 86, 336}, + Button { enabled, "Eject" }, + /* [6] */ + {93, 256, 111, 336}, + Button { enabled, "Drive" }, + /* [7] */ + {39, 12, 210, 230}, + UserItem { enabled }, + /* [8] */ + {39, 229, 210, 246}, + UserItem { enabled }, + /* [9] */ + {124, 252, 125, 340}, + UserItem { disabled }, + /* [10] */ + {1044, 20, 1145, 116}, + StaticText { disabled, "" }, + /* [11] */ + {163, 256, 181, 336}, + Button { enabled, "Choose" } + } +}; + +resource 'DLOG' (129, purgeable) +{ + {0, 0, 200, 344}, dBoxProc, invisible, noGoAway, 0, + 129, "", noAutoCenter +}; +resource 'DITL'(129) +{ + { + {169, 252, 189, 332}, Button { enabled, "Open" }, + {107, 252, 127, 332}, Button { enabled, "Cancel" }, + {0, 0, 0, 0}, HelpItem { disabled, HMScanhdlg {-6042}}, + {8, 235, 24, 337}, UserItem { enabled }, + {32, 252, 52, 332}, Button { enabled, "Eject" }, + {60, 252, 80, 332}, Button { enabled, "Desktop" }, + {29, 12, 193, 230}, UserItem { enabled }, + {6, 12, 25, 230}, UserItem { enabled }, + {93, 251, 94, 333}, Picture { disabled, 11 }, + {138, 252, 158, 332}, Button { enabled, "Choose" }, + } +}; diff --git a/LaunchAPPL/Server/LaunchAPPLServer.segmap b/LaunchAPPL/Server/LaunchAPPLServer.segmap index 650a119f47..2711505759 100644 --- a/LaunchAPPL/Server/LaunchAPPLServer.segmap +++ b/LaunchAPPL/Server/LaunchAPPLServer.segmap @@ -7,6 +7,9 @@ SEGMENT MacTCP */MacTCPStream.* */TCPConnectionProvider.* +SEGMENT SharedFile + */SharedFile*.* + SEGMENT Launcher */AppLauncher.* */ToolLauncher.* diff --git a/LaunchAPPL/Server/LauncherIcon.r b/LaunchAPPL/Server/LauncherIcon.r index 4fc1f9e3df..4348dcb03a 100644 --- a/LaunchAPPL/Server/LauncherIcon.r +++ b/LaunchAPPL/Server/LauncherIcon.r @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "Icons.r" resource 'icl8' (128, purgeable) { diff --git a/LaunchAPPL/Server/MacSerialStream.cc b/LaunchAPPL/Server/MacSerialStream.cc index 003533d2fb..a4da01a1e0 100644 --- a/LaunchAPPL/Server/MacSerialStream.cc +++ b/LaunchAPPL/Server/MacSerialStream.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "MacSerialStream.h" #include diff --git a/LaunchAPPL/Server/MacSerialStream.h b/LaunchAPPL/Server/MacSerialStream.h index b1641910f2..1d5178407e 100644 --- a/LaunchAPPL/Server/MacSerialStream.h +++ b/LaunchAPPL/Server/MacSerialStream.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #ifndef MACSERIALSTREAM_H_ #define MACSERIALSTREAM_H_ diff --git a/LaunchAPPL/Server/MacTCPStream.cc b/LaunchAPPL/Server/MacTCPStream.cc index 2fb8682be0..5953d553d6 100644 --- a/LaunchAPPL/Server/MacTCPStream.cc +++ b/LaunchAPPL/Server/MacTCPStream.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "MacTCPStream.h" #include #include diff --git a/LaunchAPPL/Server/MacTCPStream.h b/LaunchAPPL/Server/MacTCPStream.h index c4f81f8cf1..708c1b7d5f 100644 --- a/LaunchAPPL/Server/MacTCPStream.h +++ b/LaunchAPPL/Server/MacTCPStream.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include diff --git a/LaunchAPPL/Server/OpenTptConnectionProvider.cc b/LaunchAPPL/Server/OpenTptConnectionProvider.cc index eb31145024..e9135566b3 100644 --- a/LaunchAPPL/Server/OpenTptConnectionProvider.cc +++ b/LaunchAPPL/Server/OpenTptConnectionProvider.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "OpenTptConnectionProvider.h" #include "OpenTptStream.h" #include diff --git a/LaunchAPPL/Server/OpenTptConnectionProvider.h b/LaunchAPPL/Server/OpenTptConnectionProvider.h index 418cedfa2f..8fe0393c6e 100644 --- a/LaunchAPPL/Server/OpenTptConnectionProvider.h +++ b/LaunchAPPL/Server/OpenTptConnectionProvider.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include "ConnectionProvider.h" #include diff --git a/LaunchAPPL/Server/OpenTptStream.cc b/LaunchAPPL/Server/OpenTptStream.cc index cb91263b4d..b72c3854dc 100644 --- a/LaunchAPPL/Server/OpenTptStream.cc +++ b/LaunchAPPL/Server/OpenTptStream.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include #if TARGET_API_MAC_CARBON #define OTCARBONAPPLICATION 1 diff --git a/LaunchAPPL/Server/OpenTptStream.h b/LaunchAPPL/Server/OpenTptStream.h index 737353b1af..15cb66f877 100644 --- a/LaunchAPPL/Server/OpenTptStream.h +++ b/LaunchAPPL/Server/OpenTptStream.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include diff --git a/LaunchAPPL/Server/Preferences.cc b/LaunchAPPL/Server/Preferences.cc new file mode 100644 index 0000000000..44f48753ef --- /dev/null +++ b/LaunchAPPL/Server/Preferences.cc @@ -0,0 +1,243 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + +#include "Preferences.h" +#include +#include +#include +#include +#include +#include +#include "Window.h" +#include "SystemInfo.h" + +static void ConvertToPathName(const FSSpec& spec) +{ + Str255 buf; + unsigned char path[257]; + + CInfoPBRec ipb; + + long dirID = spec.parID; + path[0] = 0; + + while(dirID != 1) + { + ipb.dirInfo.ioCompletion = nullptr; + ipb.dirInfo.ioVRefNum = spec.vRefNum; + ipb.dirInfo.ioNamePtr = buf; + ipb.dirInfo.ioFDirIndex = -1; + ipb.dirInfo.ioDrDirID = dirID; + + PBGetCatInfoSync(&ipb); + + buf[buf[0]+1] = 0; + printf("element: %s\n", buf+1); + + if(path[0] + buf[0] + 1 > 255) + { + printf("Path length overflow.\n"); + return; + } + + path[++path[0]] = ':'; + std::reverse_copy(buf + 1, buf + 1 + buf[0], path + path[0] + 1); + path[0] += buf[0]; + + dirID = ipb.dirInfo.ioDrParID; + } + std::reverse(path + 1, path + 1 + path[0]); + path[path[0] + 1] = 0; + printf("path: %s\n", path+1); + + memcpy(gPrefs.sharedDirectoryPath, path, path[0] + 1); + WritePrefs(); +} + +#if !TARGET_CPU_68K + // TODO: need to properly link to Navigation.far.o on 68K + +static pascal void NavEventProc(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, void *callBackUD) +{ + if(callBackSelector == kNavCBEvent) + { + if(callBackParms->eventData.eventDataParms.event->what == updateEvt) + { + auto win = reinterpret_cast(callBackParms->eventData.eventDataParms.event->message); + if(auto winObject = reinterpret_cast(GetWRefCon(win))) + { + winObject->Update(); + } + } + } +} + +static bool ChooseSharedDirectoryNav(FSSpec& spec) +{ + bool success = false; + NavReplyRecord reply = {}; + NavDialogOptions options = {}; + + options.version = kNavDialogOptionsVersion; + options.location = {-1,-1}; + + auto eventProc = NewNavEventUPP(&NavEventProc); + OSErr err = NavChooseFolder(nullptr, &reply, &options, eventProc, nullptr, nullptr); + DisposeNavEventUPP(eventProc); + + if(err == noErr) + { + if(reply.validRecord) + { + long count = 0; + err = AECountItems(&reply.selection, &count); + if(err == noErr && count > 0) + { + AEKeyword keyword; + DescType actualType; + Size actualSize; + + err = AEGetNthPtr(&reply.selection, 1, typeFSS, &keyword, &actualType, + &spec, sizeof(spec), &actualSize); + + if(err == noErr) + success = true; + } + + NavDisposeReply(&reply); + } + } + return success; +} +#endif + +#if !TARGET_API_MAC_CARBON +static bool choosePressed = false; +static pascal short DlgHookProc(short item, DialogRef theDialog) +{ + if(choosePressed) + return 1; + if(item == 11) + { + choosePressed = true; + return sfHookOpenFolder; + } + + return item; +} + +static pascal Boolean FileFilterProc(CInfoPBPtr pb) +{ + return true; +} + +static bool ChooseSharedDirectory6(FSSpec& spec) +{ + SFReply reply; + auto dlgHookProc = NewDlgHookUPP(&DlgHookProc); + auto fileFilterProc = NewFileFilterUPP(&FileFilterProc); + choosePressed = false; + SFPGetFile(Point{-1,-1}, "\p", fileFilterProc, 0, nullptr, dlgHookProc, &reply, 128, nullptr); + DisposeDlgHookUPP(dlgHookProc); + DisposeFileFilterUPP(fileFilterProc); + + if(choosePressed) + { + spec.name[0] = 0; + spec.parID = LMGetCurDirStore(); + spec.vRefNum = -LMGetSFSaveDisk(); + return true; + } + return false; +} +static pascal short DlgHookYDProc(short item, DialogRef theDialog, void *yourDataPtr) +{ + if(choosePressed) + return 1; + if(item == 10) + { + choosePressed = true; + return sfHookOpenFolder; + } + + return item; +} + +static pascal Boolean FileFilterYDProc(CInfoPBPtr pb, void *yourDataPtr) +{ + return true; +} + +static bool ChooseSharedDirectory7(FSSpec& spec) +{ + StandardFileReply reply; + auto dlgHookProc = NewDlgHookYDUPP(&DlgHookYDProc); + auto fileFilterProc = NewFileFilterYDUPP(&FileFilterYDProc); + choosePressed = false; + CustomGetFile( + fileFilterProc, + 0, + nullptr, + &reply, + 129, + Point{-1,-1}, + dlgHookProc, + /*filterProc*/nullptr, + nullptr, nullptr, + nullptr); + + DisposeDlgHookYDUPP(dlgHookProc); + DisposeFileFilterYDUPP(fileFilterProc); + + if(choosePressed) + { + spec.name[0] = 0; + spec.parID = LMGetCurDirStore(); + spec.vRefNum = -LMGetSFSaveDisk(); + return true; + } + return false; +} + +#endif + +void ChooseSharedDirectory() +{ + FSSpec spec; + bool ok = false; + + +#if TARGET_API_MAC_CARBON + ok = ChooseSharedDirectoryNav(spec); +#else + +#if !TARGET_CPU_68K + if(NavServicesAvailable()) + ok = ChooseSharedDirectoryNav(spec); +#else + if(!hasSys7StdFile) + ok = ChooseSharedDirectory6(spec); +#endif + else + ok = ChooseSharedDirectory7(spec); +#endif + + if(ok) + ConvertToPathName(spec); +} diff --git a/LaunchAPPL/Server/Preferences.h b/LaunchAPPL/Server/Preferences.h new file mode 100644 index 0000000000..6bf00b0a03 --- /dev/null +++ b/LaunchAPPL/Server/Preferences.h @@ -0,0 +1,48 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + +#pragma once + +#include + +enum class Port : int +{ + modemPort = 0, + printerPort, + macTCP, + openTptTCP, + sharedFiles +}; + +struct Prefs +{ + const static int currentVersion = 2; + int version = currentVersion; + Port port = Port::modemPort; + long baud = 19200; + bool inSubLaunch = false; + Str255 sharedDirectoryPath; +}; + +extern Prefs gPrefs; + +void ChooseSharedDirectory(); + +void ReadPrefs(); +void WritePrefs(); diff --git a/LaunchAPPL/Server/SerialConnectionProvider.cc b/LaunchAPPL/Server/SerialConnectionProvider.cc index a82a181003..73b9ea23ea 100644 --- a/LaunchAPPL/Server/SerialConnectionProvider.cc +++ b/LaunchAPPL/Server/SerialConnectionProvider.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "SerialConnectionProvider.h" #include "MacSerialStream.h" #include diff --git a/LaunchAPPL/Server/SerialConnectionProvider.h b/LaunchAPPL/Server/SerialConnectionProvider.h index 260018a0ee..6ea56cfc67 100644 --- a/LaunchAPPL/Server/SerialConnectionProvider.h +++ b/LaunchAPPL/Server/SerialConnectionProvider.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include "ConnectionProvider.h" #include diff --git a/LaunchAPPL/Server/SharedFileProvider.cc b/LaunchAPPL/Server/SharedFileProvider.cc new file mode 100644 index 0000000000..cdfa8c131b --- /dev/null +++ b/LaunchAPPL/Server/SharedFileProvider.cc @@ -0,0 +1,54 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + +#include "SharedFileProvider.h" +#include "SharedFileStream.h" +#include "Preferences.h" + +SharedFileProvider::SharedFileProvider(StatusDisplay *statusDisplay) +{ + stream = std::make_unique(gPrefs.sharedDirectoryPath); +} + +SharedFileProvider::~SharedFileProvider() +{ +} + +Stream* SharedFileProvider::getStream() +{ + return stream.get(); +} + +void SharedFileProvider::idle() +{ + if(stream) + { + stream->setListener(listener); + stream->idle(); + } +} + +void SharedFileProvider::unloadSegDummy() +{ +} + +void *SharedFileProvider::segmentToUnload() +{ + return (void*) &unloadSegDummy; +} diff --git a/LaunchAPPL/Server/SharedFileProvider.h b/LaunchAPPL/Server/SharedFileProvider.h new file mode 100644 index 0000000000..50f7c5f5a4 --- /dev/null +++ b/LaunchAPPL/Server/SharedFileProvider.h @@ -0,0 +1,41 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + +#pragma once +#include "ConnectionProvider.h" +#include + +class SharedFileStream; +class StatusDisplay; + +class SharedFileProvider : public ConnectionProvider +{ + std::unique_ptr stream; + + static void unloadSegDummy(); +public: + SharedFileProvider(StatusDisplay *statusDisplay); + virtual ~SharedFileProvider(); + + virtual Stream* getStream(); + + virtual void idle(); + + virtual void* segmentToUnload(); +}; diff --git a/LaunchAPPL/Server/SharedFileStream.cc b/LaunchAPPL/Server/SharedFileStream.cc new file mode 100644 index 0000000000..7f5c5c84a1 --- /dev/null +++ b/LaunchAPPL/Server/SharedFileStream.cc @@ -0,0 +1,137 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + +#include "SharedFileStream.h" +#include +#include +#include +#include + +void SharedFileStream::MakeFileName(unsigned char *name, int i) +{ + const unsigned char *templ = "\pout_channel_"; + memcpy(name, templ, templ[0]+1); + Str31 s; + NumToString(i, s); + memcpy(name + name[0] + 1, s + 1, s[0]); + name[0] += s[0]; +} + +void SharedFileStream::write(const void* p, size_t n) +{ + Str31 name; + MakeFileName(name, outQueueTail++); + HCreate(vRefNum, dirID, name, 'R68L', 'DATA' ); + + short refNum; + OSErr err = HOpenDF(vRefNum, dirID, name, fsWrDenyPerm, &refNum); + if(err) + return; + long count = n; + FSWrite(refNum, &count, p); + FSClose(refNum); +} + +void SharedFileStream::idle() +{ + const unsigned char* in_channel = "\pin_channel"; + + static int count = 0; + if(++count % 10) + return; + short refNum; + + OSErr err = HOpenDF(vRefNum, dirID, in_channel, fsRdDenyPerm, &refNum); + if(err == 0) + { + long count, countTotal = 0; + do + { + count = kReadBufferSize; + err = FSRead(refNum, &count, &readBuffer); + countTotal += count; + if((err == noErr || err == eofErr) && count > 0) + notifyReceive(readBuffer, count); + } while(err == noErr); + FSClose(refNum); +#ifdef DEBUG_CONSOLE + printf("read %ld bytes, deleting package\n", countTotal); +#endif + + HDelete(vRefNum, dirID, in_channel); + } + + if(outQueueTail > outQueueHead) + { + const unsigned char* out_channel = "\pout_channel"; + Str31 name; + MakeFileName(name, outQueueHead); + if(HRename(vRefNum, dirID, name, out_channel) == noErr) + ++outQueueHead; + } + + if(outQueueHead == outQueueTail) + outQueueHead = outQueueTail = 1; +} + +bool SharedFileStream::allDataArrived() const +{ + return outQueueHead == outQueueTail; +} + +SharedFileStream::SharedFileStream(const unsigned char* path) +{ + Str255 str; + memcpy(str, path, path[0] + 1); + CInfoPBRec ipb; + ipb.hFileInfo.ioCompletion = nullptr; + ipb.hFileInfo.ioVRefNum = 0; + ipb.hFileInfo.ioNamePtr = str; + ipb.hFileInfo.ioFDirIndex = 0; + ipb.hFileInfo.ioDirID = 0; + + PBGetCatInfoSync(&ipb); + + dirID = ipb.hFileInfo.ioDirID; + +#ifdef DEBUG_CONSOLE + printf("dirID = %ld\n", dirID); + str[str[0]+1] = 0; + printf("name = %s\n", str + 1); +#endif + + HParamBlockRec hpb; + hpb.ioParam.ioCompletion = nullptr; + hpb.ioParam.ioVRefNum = 0; + hpb.volumeParam.ioVolIndex = -1; + memcpy(str, path, path[0] + 1); + hpb.volumeParam.ioNamePtr = str; + PBHGetVInfoSync(&hpb); + +#ifdef DEBUG_CONSOLE + str[str[0]+1] = 0; + printf("vRefNum = %d, name = %s\n", hpb.volumeParam.ioVRefNum, str + 1); +#endif + + vRefNum = hpb.volumeParam.ioVRefNum; +} + +SharedFileStream::~SharedFileStream() +{ +} diff --git a/LaunchAPPL/Server/SharedFileStream.h b/LaunchAPPL/Server/SharedFileStream.h new file mode 100644 index 0000000000..b67cf306c9 --- /dev/null +++ b/LaunchAPPL/Server/SharedFileStream.h @@ -0,0 +1,43 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + +#pragma once + +#include +#include + +class SharedFileStream : public Stream +{ + short vRefNum; + long dirID; + + int outQueueHead = 1, outQueueTail = 1; + static const long kReadBufferSize = 4096; + uint8_t readBuffer[kReadBufferSize]; + + void MakeFileName(unsigned char *name, int i); +public: + virtual void write(const void* p, size_t n) override; + virtual bool allDataArrived() const override; + + void idle(); + + SharedFileStream(const unsigned char* path); + ~SharedFileStream(); +}; diff --git a/LaunchAPPL/Server/StatusDisplay.cc b/LaunchAPPL/Server/StatusDisplay.cc index 4ef63a3580..c927421bf7 100644 --- a/LaunchAPPL/Server/StatusDisplay.cc +++ b/LaunchAPPL/Server/StatusDisplay.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "StatusDisplay.h" #include #include @@ -8,7 +27,6 @@ const short tableTop = 50; const short tableLineHeight = 20; const short tableBaseline = 15; - enum class StatusDisplay::Stat : short { heapSize, diff --git a/LaunchAPPL/Server/StatusDisplay.h b/LaunchAPPL/Server/StatusDisplay.h index d8357ee4e9..544656f311 100644 --- a/LaunchAPPL/Server/StatusDisplay.h +++ b/LaunchAPPL/Server/StatusDisplay.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include #include #include @@ -14,6 +33,7 @@ enum class AppStatus readyPrinter, readyMacTCP, readyOpenTpt, + readySharedFiles, downloading, upgrading, running, diff --git a/LaunchAPPL/Server/SystemInfo.h b/LaunchAPPL/Server/SystemInfo.h index 4f2989d7b9..fd430c7310 100644 --- a/LaunchAPPL/Server/SystemInfo.h +++ b/LaunchAPPL/Server/SystemInfo.h @@ -1,4 +1,24 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once extern bool hasColorQD; extern bool hasIconUtils; +extern bool hasSys7StdFile; diff --git a/LaunchAPPL/Server/TCPConnectionProvider.cc b/LaunchAPPL/Server/TCPConnectionProvider.cc index 68a2038778..bbc2c6adf8 100644 --- a/LaunchAPPL/Server/TCPConnectionProvider.cc +++ b/LaunchAPPL/Server/TCPConnectionProvider.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "TCPConnectionProvider.h" #include "MacTCPStream.h" #include @@ -12,7 +31,6 @@ TCPConnectionProvider::TCPConnectionProvider(StatusDisplay *statusDisplay) TCPConnectionProvider::~TCPConnectionProvider() { - } Stream* TCPConnectionProvider::getStream() diff --git a/LaunchAPPL/Server/TCPConnectionProvider.h b/LaunchAPPL/Server/TCPConnectionProvider.h index 2ff29dbd91..2dd5b1cc13 100644 --- a/LaunchAPPL/Server/TCPConnectionProvider.h +++ b/LaunchAPPL/Server/TCPConnectionProvider.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once #include "ConnectionProvider.h" #include diff --git a/LaunchAPPL/Server/ToolLauncher.cc b/LaunchAPPL/Server/ToolLauncher.cc index ba2d101f59..c29a4ca67d 100644 --- a/LaunchAPPL/Server/ToolLauncher.cc +++ b/LaunchAPPL/Server/ToolLauncher.cc @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #include "AppLauncher.h" #include diff --git a/LaunchAPPL/Server/Window.h b/LaunchAPPL/Server/Window.h index 3ecc6d107f..51d844c437 100644 --- a/LaunchAPPL/Server/Window.h +++ b/LaunchAPPL/Server/Window.h @@ -1,3 +1,22 @@ +/* + Copyright 2019 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Retro68. If not, see . +*/ + #pragma once class Window diff --git a/README.md b/README.md index 1fa5f345b8..4b83ad6a84 100644 --- a/README.md +++ b/README.md @@ -328,6 +328,7 @@ Currently, LaunchAPPL supports the following methods for launching Mac applicati * ssh - Invoke the `LaunchAPPL` tool remotely via ssh * serial - Connect to a real Mac running the `LaunchAPPLServer` application via a null modem cable * tcp - Connect to a real Mac running the `LaunchAPPLServer` application via a completely insecure TCP connection +* shared - Communicate with `LaunchAPPLServer` via files in a shared folder If you're running on a Mac that's old enough to use the `classic` or `carbon` backends, they will work out of the box, just launch an application as follows