| @@ -79,7 +79,10 @@ ifeq ($(UNIX),true) | |||
| STANDALONE_FLAGS += -lmagic | |||
| endif | |||
| UTILS_FLAGS = $(JUCE_CORE_LIBS) | |||
| UTILS_FLAGS = $(JUCE_CORE_LIBS) | |||
| ifneq ($(HAIKU),true) | |||
| UTILS_FLAGS += -lpthread | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| @@ -20,9 +20,6 @@ | |||
| #ifdef BUILD_BRIDGE | |||
| # error This file should not be compiled if building bridge | |||
| #endif | |||
| #ifdef CARLA_OS_WIN | |||
| # error This file should not be compiled for Windows | |||
| #endif | |||
| #include "CarlaEngineInternal.hpp" | |||
| #include "CarlaPlugin.hpp" | |||
| @@ -1418,10 +1415,12 @@ protected: | |||
| CarlaString path(pHost->resourceDir); | |||
| if (kIsPatchbay) | |||
| path += "/carla-plugin-patchbay"; | |||
| path += CARLA_OS_SEP_STR "carla-plugin-patchbay"; | |||
| else | |||
| path += "/carla-plugin"; | |||
| path += CARLA_OS_SEP_STR "carla-plugin"; | |||
| #ifdef CARLA_OS_WIN | |||
| path += ".exe"; | |||
| #endif | |||
| carla_stdout("Trying to start carla-plugin using \"%s\"", path.buffer()); | |||
| fUiServer.setData(path, pData->sampleRate, pHost->uiName); | |||
| @@ -1463,6 +1462,7 @@ protected: | |||
| const CarlaMutexLocker cml(fUiServer.getLock()); | |||
| const ScopedLocale csl; | |||
| #ifndef CARLA_OS_WIN // FIXME | |||
| // send transport | |||
| fUiServer.writeAndFixMsg("transport"); | |||
| fUiServer.writeMsg(timeInfo.playing ? "true\n" : "false\n"); | |||
| @@ -1482,6 +1482,7 @@ protected: | |||
| } | |||
| fUiServer.flush(); | |||
| #endif | |||
| // send peaks and param outputs for all plugins | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| @@ -20,23 +20,17 @@ OBJS = \ | |||
| CarlaEngineThread.cpp.o | |||
| OBJSa = $(OBJS) \ | |||
| CarlaEngineJack.cpp.o | |||
| CarlaEngineJack.cpp.o \ | |||
| CarlaEngineNative.cpp.o | |||
| ifeq ($(MACOS_OR_WIN32),true) | |||
| OBJSa += \ | |||
| CarlaEngineJuce.cpp.o | |||
| OBJSa += CarlaEngineJuce.cpp.o | |||
| else | |||
| OBJSa += \ | |||
| CarlaEngineRtAudio.cpp.o | |||
| OBJSa += CarlaEngineRtAudio.cpp.o | |||
| endif | |||
| ifneq ($(WIN32),true) | |||
| OBJSa += \ | |||
| CarlaEngineNative.cpp.o | |||
| OBJSp = $(OBJS) \ | |||
| CarlaEngineNative.cpp.exp.o | |||
| endif | |||
| TARGETS = \ | |||
| ../carla_engine.a \ | |||
| @@ -50,7 +50,7 @@ class CarlaApplication(object): | |||
| QApplication.addLibraryPath(CWD) | |||
| # Needed for local wine build | |||
| if WINDOWS and CWD.endswith("source"): | |||
| if WINDOWS and (CWD.endswith("source") or os.getenv("CXFREEZE") is not None): | |||
| QApplication.addLibraryPath("C:\\Python34\\Lib\\site-packages\\PyQt5\\plugins") | |||
| # Use binary dir as library path (except in Windows) | |||
| @@ -401,7 +401,7 @@ private: | |||
| // ------------------------------ Plugin Checks ----------------------------- | |||
| static void do_ladspa_check(void*& libHandle, const char* const filename, const bool doInit) | |||
| static void do_ladspa_check(lib_t& libHandle, const char* const filename, const bool doInit) | |||
| { | |||
| LADSPA_Descriptor_Function descFn = lib_symbol<LADSPA_Descriptor_Function>(libHandle, "ladspa_descriptor"); | |||
| @@ -634,7 +634,7 @@ static void do_ladspa_check(void*& libHandle, const char* const filename, const | |||
| } | |||
| } | |||
| static void do_dssi_check(void*& libHandle, const char* const filename, const bool doInit) | |||
| static void do_dssi_check(lib_t& libHandle, const char* const filename, const bool doInit) | |||
| { | |||
| DSSI_Descriptor_Function descFn = lib_symbol<DSSI_Descriptor_Function>(libHandle, "dssi_descriptor"); | |||
| @@ -984,7 +984,7 @@ static void do_lv2_check(const char* const bundle, const bool doInit) | |||
| if (doInit) | |||
| { | |||
| // test if DLL is loadable, twice | |||
| void* const libHandle1 = lib_open(rdfDescriptor->Binary); | |||
| const lib_t libHandle1 = lib_open(rdfDescriptor->Binary); | |||
| if (libHandle1 == nullptr) | |||
| { | |||
| @@ -995,7 +995,7 @@ static void do_lv2_check(const char* const bundle, const bool doInit) | |||
| lib_close(libHandle1); | |||
| void* const libHandle2 = lib_open(rdfDescriptor->Binary); | |||
| const lib_t libHandle2 = lib_open(rdfDescriptor->Binary); | |||
| if (libHandle2 == nullptr) | |||
| { | |||
| @@ -1142,7 +1142,7 @@ static void do_lv2_check(const char* const bundle, const bool doInit) | |||
| } | |||
| #ifndef CARLA_OS_MAC | |||
| static void do_vst_check(void*& libHandle, const bool doInit) | |||
| static void do_vst_check(lib_t& libHandle, const bool doInit) | |||
| { | |||
| VST_Function vstFn = lib_symbol<VST_Function>(libHandle, "VSTPluginMain"); | |||
| @@ -16,11 +16,6 @@ | |||
| # | |||
| # For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Global) | |||
| from sys import argv | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| # Imports (Custom Stuff) | |||
| @@ -35,9 +30,9 @@ class ExternalUI(object): | |||
| self.fQuitReceived = False | |||
| if len(argv) > 1: | |||
| self.fSampleRate = float(argv[1]) | |||
| self.fUiName = argv[2] | |||
| if len(sys.argv) > 1: | |||
| self.fSampleRate = float(sys.argv[1]) | |||
| self.fUiName = sys.argv[2] | |||
| self.fPipeClient = gCarla.utils.pipe_client_new(lambda s,msg: self.msgCallback(msg)) | |||
| else: | |||
| self.fSampleRate = 44100.0 | |||
| @@ -48,10 +43,7 @@ class ExternalUI(object): | |||
| # Public methods | |||
| def ready(self): | |||
| if self.fPipeClient is not None: | |||
| # send empty line (just newline char) | |||
| self.send([""]) | |||
| else: | |||
| if self.fPipeClient is None: | |||
| # testing, show UI only | |||
| self.uiShow() | |||
| @@ -65,12 +57,14 @@ class ExternalUI(object): | |||
| gCarla.utils.pipe_client_idle(self.fPipeClient) | |||
| def closeExternalUI(self): | |||
| if self.fPipeClient is None: | |||
| return | |||
| if not self.fQuitReceived: | |||
| self.send(["exiting"]) | |||
| if self.fPipeClient is not None: | |||
| gCarla.utils.pipe_client_destroy(self.fPipeClient) | |||
| self.fPipeClient = None | |||
| gCarla.utils.pipe_client_destroy(self.fPipeClient) | |||
| self.fPipeClient = None | |||
| # ------------------------------------------------------------------- | |||
| # Host DSP State | |||
| @@ -176,7 +170,7 @@ class ExternalUI(object): | |||
| if self.fPipeClient is None: | |||
| return "" | |||
| return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 50) | |||
| return gCarla.utils.pipe_client_readlineblock(self.fPipeClient, 5000) | |||
| def send(self, lines): | |||
| if self.fPipeClient is None or len(lines) == 0: | |||
| @@ -184,21 +178,25 @@ class ExternalUI(object): | |||
| gCarla.utils.pipe_client_lock(self.fPipeClient) | |||
| for line in lines: | |||
| if line is None: | |||
| line2 = "(null)" | |||
| elif isinstance(line, str): | |||
| line2 = line.replace("\n", "\r") | |||
| elif isinstance(line, bool): | |||
| line2 = "true" if line else "false" | |||
| elif isinstance(line, int): | |||
| line2 = "%i" % line | |||
| elif isinstance(line, float): | |||
| line2 = "%.10f" % line | |||
| else: | |||
| print("unknown data type to send:", type(line)) | |||
| return | |||
| gCarla.utils.pipe_client_write_msg(self.fPipeClient, line2 + "\n") | |||
| # this must never fail, we need to unlock at the end | |||
| try: | |||
| for line in lines: | |||
| if line is None: | |||
| line2 = "(null)" | |||
| elif isinstance(line, str): | |||
| line2 = line.replace("\n", "\r") | |||
| elif isinstance(line, bool): | |||
| line2 = "true" if line else "false" | |||
| elif isinstance(line, int): | |||
| line2 = "%i" % line | |||
| elif isinstance(line, float): | |||
| line2 = "%.10f" % line | |||
| else: | |||
| print("unknown data type to send:", type(line)) | |||
| return | |||
| gCarla.utils.pipe_client_write_msg(self.fPipeClient, line2 + "\n") | |||
| except: | |||
| pass | |||
| gCarla.utils.pipe_client_flush_and_unlock(self.fPipeClient) | |||
| @@ -140,7 +140,7 @@ typedef int (__cdecl *jacksym_set_property_change_callback)(jack_client_t*, Jac | |||
| // ----------------------------------------------------------------------------- | |||
| struct JackBridge { | |||
| void* lib; | |||
| lib_t lib; | |||
| jacksym_get_version get_version_ptr; | |||
| jacksym_get_version_string get_version_string_ptr; | |||
| @@ -57,14 +57,12 @@ OBJS += \ | |||
| audio-file.cpp.o \ | |||
| midi-file.cpp.o | |||
| ifneq ($(WIN32),true) | |||
| # -------------------------------------------------------------- | |||
| # External-UI plugins | |||
| OBJS += \ | |||
| bigmeter.cpp.o \ | |||
| notes.cpp.o | |||
| endif | |||
| # -------------------------------------------------------------- | |||
| # ZynAddSubFX | |||
| @@ -32,14 +32,12 @@ extern void carla_register_native_plugin_audiofile(void); | |||
| // MIDI File | |||
| extern void carla_register_native_plugin_midifile(void); | |||
| #ifndef CARLA_OS_WIN | |||
| // Carla | |||
| extern void carla_register_native_plugin_carla(void); | |||
| // External-UI plugins | |||
| extern void carla_register_native_plugin_bigmeter(void); | |||
| extern void carla_register_native_plugin_notes(void); | |||
| #endif | |||
| #ifdef WANT_ZYNADDSUBFX | |||
| // ZynAddSubFX | |||
| @@ -66,14 +64,12 @@ void carla_register_all_plugins(void) | |||
| // MIDI File | |||
| carla_register_native_plugin_midifile(); | |||
| #ifndef CARLA_OS_WIN | |||
| // Carla | |||
| carla_register_native_plugin_carla(); | |||
| // External-UI plugins | |||
| carla_register_native_plugin_bigmeter(); | |||
| carla_register_native_plugin_notes(); | |||
| #endif | |||
| #ifdef WANT_ZYNADDSUBFX | |||
| // ZynAddSubFX | |||
| @@ -17,10 +17,6 @@ | |||
| #include "CarlaDefines.h" | |||
| #ifdef CARLA_OS_WIN | |||
| # error This file should not be compiled for Windows | |||
| #endif | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaNativeExtUI.hpp" | |||
| @@ -34,7 +30,7 @@ class BigMeterPlugin : public NativePluginAndUiClass | |||
| { | |||
| public: | |||
| BigMeterPlugin(const NativeHostDescriptor* const host) | |||
| : NativePluginAndUiClass(host, "/bigmeter-ui"), | |||
| : NativePluginAndUiClass(host, CARLA_OS_SEP_STR "bigmeter-ui"), | |||
| fColor(1), | |||
| fStyle(1), | |||
| fOutLeft(0.0f), | |||
| @@ -17,10 +17,6 @@ | |||
| #include "CarlaDefines.h" | |||
| #ifdef CARLA_OS_WIN | |||
| # error This file should not be compiled for Windows | |||
| #endif | |||
| #include "CarlaNativeExtUI.hpp" | |||
| // ----------------------------------------------------------------------- | |||
| @@ -29,7 +25,7 @@ class NotesPlugin : public NativePluginAndUiClass | |||
| { | |||
| public: | |||
| NotesPlugin(const NativeHostDescriptor* const host) | |||
| : NativePluginAndUiClass(host, "/notes-ui"), | |||
| : NativePluginAndUiClass(host, CARLA_OS_SEP_STR "notes-ui"), | |||
| fCurPage(1), | |||
| leakDetector_NotesPlugin() {} | |||
| @@ -117,6 +117,12 @@ class CarlaMiniW(ExternalUI, HostWindow): | |||
| # Custom callback | |||
| def msgCallback(self, msg): | |||
| try: | |||
| self.msgCallback2(msg) | |||
| except: | |||
| print("msgCallback error, skipped for", msg) | |||
| def msgCallback2(self, msg): | |||
| msg = charPtrToString(msg) | |||
| #if not msg: | |||
| @@ -60,7 +60,7 @@ struct OverlappedEvent { | |||
| }; | |||
| static inline | |||
| ssize_t ReadFileNonBlock(const HANDLE pipeh, const HANDLE cancelh, void* buf, size_t numBytes) | |||
| ssize_t ReadFileNonBlock(const HANDLE pipeh, const HANDLE cancelh, void* const buf, const std::size_t numBytes) | |||
| { | |||
| DWORD dsize; | |||
| OverlappedEvent over; | |||
| @@ -68,17 +68,47 @@ ssize_t ReadFileNonBlock(const HANDLE pipeh, const HANDLE cancelh, void* buf, si | |||
| if (::ReadFile(pipeh, buf, numBytes, &dsize, &over.over) != FALSE) | |||
| return static_cast<ssize_t>(dsize); | |||
| if (GetLastError() == ERROR_IO_PENDING) | |||
| if (::GetLastError() == ERROR_IO_PENDING) | |||
| { | |||
| HANDLE handles[] = { over.over.hEvent, cancelh }; | |||
| if (WaitForMultipleObjects(2, handles, FALSE, 0) != WAIT_OBJECT_0) | |||
| if (::WaitForMultipleObjects(2, handles, FALSE, 0) != WAIT_OBJECT_0) | |||
| { | |||
| CancelIo(pipeh); | |||
| ::CancelIo(pipeh); | |||
| return -1; | |||
| } | |||
| if (GetOverlappedResult(pipeh, &over.over, &dsize, FALSE) != FALSE) | |||
| if (::GetOverlappedResult(pipeh, &over.over, &dsize, FALSE) != FALSE) | |||
| return static_cast<ssize_t>(dsize); | |||
| } | |||
| return -1; | |||
| } | |||
| static inline | |||
| ssize_t WriteFileNonBlock(const HANDLE pipeh, const HANDLE cancelh, const void* const buf, const std::size_t numBytes) | |||
| { | |||
| DWORD dsize; | |||
| if (::WriteFile(pipeh, buf, numBytes, &dsize, nullptr) != FALSE) | |||
| return static_cast<ssize_t>(dsize); | |||
| return -1; | |||
| //DWORD dsize; | |||
| OverlappedEvent over; | |||
| if (::WriteFile(pipeh, buf, numBytes, &dsize, &over.over) != FALSE) | |||
| return static_cast<ssize_t>(dsize); | |||
| if (::GetLastError() == ERROR_IO_PENDING) | |||
| { | |||
| HANDLE handles[] = { over.over.hEvent, cancelh }; | |||
| if (::WaitForMultipleObjects(2, handles, FALSE, 0) != WAIT_OBJECT_0) | |||
| { | |||
| ::CancelIo(pipeh); | |||
| return -1; | |||
| } | |||
| if (::GetOverlappedResult(pipeh, &over.over, &dsize, FALSE) != FALSE) | |||
| return static_cast<ssize_t>(dsize); | |||
| } | |||
| @@ -113,12 +143,12 @@ bool startProcess(const char* const argv[], PROCESS_INFORMATION& processInfo) | |||
| STARTUPINFOW startupInfo; | |||
| carla_zeroStruct(startupInfo); | |||
| //# if 1 | |||
| # if 0 | |||
| startupInfo.hStdInput = INVALID_HANDLE_VALUE; | |||
| startupInfo.hStdOutput = INVALID_HANDLE_VALUE; | |||
| startupInfo.hStdError = INVALID_HANDLE_VALUE; | |||
| startupInfo.dwFlags = STARTF_USESTDHANDLES; | |||
| //# endif | |||
| # endif | |||
| startupInfo.cb = sizeof(STARTUPINFOW); | |||
| return CreateProcessW(nullptr, const_cast<LPWSTR>(command.toWideCharPointer()), | |||
| @@ -798,13 +828,17 @@ bool CarlaPipeCommon::writeMsgBuffer(const char* const msg, const std::size_t si | |||
| CARLA_SAFE_ASSERT_RETURN(pData->pipeSend != INVALID_PIPE_VALUE, false); | |||
| ssize_t ret; | |||
| try { | |||
| #ifdef CARLA_OS_WIN | |||
| return (::WriteFile(pData->pipeSend, msg, size, nullptr, nullptr) != FALSE); | |||
| ret = ::WriteFileNonBlock(pData->pipeSend, pData->cancelEvent, msg, size); | |||
| #else | |||
| return (::write(pData->pipeSend, msg, size) == static_cast<ssize_t>(size)); | |||
| ret = ::write(pData->pipeSend, msg, size); | |||
| #endif | |||
| } CARLA_SAFE_EXCEPTION_RETURN("CarlaPipeCommon::writeMsgBuffer", false); | |||
| return (ret == static_cast<ssize_t>(size)); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||