| @@ -55,7 +55,7 @@ ALL_LIBS += $(MODULEDIR)/carla_engine_plugin.a | |||
| ALL_LIBS += $(MODULEDIR)/carla_plugin.a | |||
| ALL_LIBS += $(MODULEDIR)/jackbridge.a | |||
| ALL_LIBS += $(MODULEDIR)/native-plugins.a | |||
| ALL_LIBS += $(MODULEDIR)/juce_core.a | |||
| ALL_LIBS += $(MODULEDIR)/juce_audio_graph.a | |||
| ALL_LIBS += $(MODULEDIR)/lilv.a | |||
| ALL_LIBS += $(MODULEDIR)/rtmempool.a | |||
| @@ -149,7 +149,7 @@ theme: libs | |||
| # Binaries (posix32) | |||
| LIBS_POSIX32 = $(MODULEDIR)/jackbridge.posix32.a | |||
| LIBS_POSIX32 += $(MODULEDIR)/juce_core.posix32.a | |||
| LIBS_POSIX32 += $(MODULEDIR)/juce_audio_graph.posix32.a | |||
| LIBS_POSIX32 += $(MODULEDIR)/lilv.posix32.a | |||
| LIBS_POSIX32 += $(MODULEDIR)/rtmempool.posix32.a | |||
| @@ -161,7 +161,7 @@ posix32: $(LIBS_POSIX32) | |||
| # Binaries (posix64) | |||
| LIBS_POSIX64 = $(MODULEDIR)/jackbridge.posix64.a | |||
| LIBS_POSIX64 += $(MODULEDIR)/juce_core.posix64.a | |||
| LIBS_POSIX64 += $(MODULEDIR)/juce_audio_graph.posix64.a | |||
| LIBS_POSIX64 += $(MODULEDIR)/lilv.posix64.a | |||
| LIBS_POSIX64 += $(MODULEDIR)/rtmempool.posix64.a | |||
| @@ -177,7 +177,7 @@ LIBS_WIN32 = $(MODULEDIR)/jackbridge.win32.a | |||
| else | |||
| LIBS_WIN32 = $(MODULEDIR)/jackbridge.win32e.a | |||
| endif | |||
| LIBS_WIN32 += $(MODULEDIR)/juce_core.win32.a | |||
| LIBS_WIN32 += $(MODULEDIR)/juce_audio_graph.win32.a | |||
| LIBS_WIN32 += $(MODULEDIR)/lilv.win32.a | |||
| LIBS_WIN32 += $(MODULEDIR)/rtmempool.win32.a | |||
| @@ -193,7 +193,7 @@ LIBS_WIN64 = $(MODULEDIR)/jackbridge.win64.a | |||
| else | |||
| LIBS_WIN64 = $(MODULEDIR)/jackbridge.win64e.a | |||
| endif | |||
| LIBS_WIN64 += $(MODULEDIR)/juce_core.win64.a | |||
| LIBS_WIN64 += $(MODULEDIR)/juce_audio_graph.win64.a | |||
| LIBS_WIN64 += $(MODULEDIR)/lilv.win64.a | |||
| LIBS_WIN64 += $(MODULEDIR)/rtmempool.win64.a | |||
| @@ -24,7 +24,7 @@ | |||
| struct CarlaOscData; | |||
| #endif | |||
| namespace juce { | |||
| namespace juce2 { | |||
| class MemoryOutputStream; | |||
| class XmlDocument; | |||
| } | |||
| @@ -1134,12 +1134,12 @@ protected: | |||
| /*! | |||
| * Common save project function for main engine and plugin. | |||
| */ | |||
| void saveProjectInternal(juce::MemoryOutputStream& outStrm) const; | |||
| void saveProjectInternal(juce2::MemoryOutputStream& outStrm) const; | |||
| /*! | |||
| * Common load project function for main engine and plugin. | |||
| */ | |||
| bool loadProjectInternal(juce::XmlDocument& xmlDoc); | |||
| bool loadProjectInternal(juce2::XmlDocument& xmlDoc); | |||
| #ifndef BUILD_BRIDGE | |||
| // ------------------------------------------------------------------- | |||
| @@ -18,7 +18,7 @@ | |||
| #include "CarlaHost.h" | |||
| #include "CarlaString.hpp" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| namespace CB = CarlaBackend; | |||
| @@ -106,7 +106,7 @@ const char* carla_get_library_filename() | |||
| if (ret.isEmpty()) | |||
| { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| ret = File(File::getSpecialLocation(File::currentExecutableFile)).getFullPathName().toRawUTF8(); | |||
| } | |||
| @@ -121,7 +121,7 @@ const char* carla_get_library_folder() | |||
| if (ret.isEmpty()) | |||
| { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| ret = File(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()).getFullPathName().toRawUTF8(); | |||
| } | |||
| @@ -27,13 +27,12 @@ | |||
| #include "CarlaBackendUtils.hpp" | |||
| #include "CarlaBase64Utils.hpp" | |||
| #ifndef BUILD_BRIDGE | |||
| #ifdef BUILD_BRIDGE | |||
| # include "juce_audio_graph/juce_audio_graph.h" | |||
| #else | |||
| # include "CarlaLogThread.hpp" | |||
| #endif | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| namespace CB = CarlaBackend; | |||
| using CB::EngineOptions; | |||
| @@ -145,7 +144,7 @@ static void carla_engine_init_common() | |||
| gStandalone.engine->setFileCallback(gStandalone.fileCallback, gStandalone.fileCallbackPtr); | |||
| #ifdef BUILD_BRIDGE | |||
| using juce::File; | |||
| using juce2::File; | |||
| File juceBinaryDir(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()); | |||
| /* | |||
| @@ -29,8 +29,7 @@ | |||
| #include "CarlaOscUtils.hpp" | |||
| #include "CarlaString.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| namespace CB = CarlaBackend; | |||
| @@ -268,7 +267,7 @@ protected: | |||
| } | |||
| else | |||
| { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| if (carla_is_engine_running()) | |||
| carla_engine_close(); | |||
| @@ -513,7 +513,7 @@ const char* carla_get_supported_file_extensions() | |||
| #if 0 | |||
| // Audio files | |||
| { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| AudioFormatManager afm; | |||
| afm.registerBasicFormats(); | |||
| @@ -553,7 +553,6 @@ void carla_set_process_name(const char* name) | |||
| carla_debug("carla_set_process_name(\"%s\")", name); | |||
| CarlaThread::setCurrentThreadName(name); | |||
| juce::Thread::setCurrentThreadName(name); | |||
| } | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| @@ -694,7 +693,7 @@ const char* carla_get_library_filename() | |||
| if (ret.isEmpty()) | |||
| { | |||
| using juce::File; | |||
| using juce2::File; | |||
| ret = File(File::getSpecialLocation(File::currentExecutableFile)).getFullPathName().toRawUTF8(); | |||
| } | |||
| @@ -709,7 +708,7 @@ const char* carla_get_library_folder() | |||
| if (ret.isEmpty()) | |||
| { | |||
| using juce::File; | |||
| using juce2::File; | |||
| ret = File(File::getSpecialLocation(File::currentExecutableFile).getParentDirectory()).getFullPathName().toRawUTF8(); | |||
| } | |||
| @@ -26,7 +26,7 @@ STANDALONE_LIBS = $(MODULEDIR)/carla_engine.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/carla_plugin.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/jackbridge.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/juce_core.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/juce_audio_graph.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/lilv.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/native-plugins.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/rtmempool.a | |||
| @@ -42,7 +42,7 @@ endif | |||
| STANDALONE_LIBS += $(MODULEDIR)/rtaudio.a | |||
| STANDALONE_LIBS += $(MODULEDIR)/rtmidi.a | |||
| UTILS_LIBS += $(MODULEDIR)/juce_core.a | |||
| UTILS_LIBS += $(MODULEDIR)/juce_audio_graph.a | |||
| UTILS_LIBS += $(MODULEDIR)/lilv.a | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| @@ -35,18 +35,16 @@ | |||
| #include "jackbridge/JackBridge.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| using juce::Array; | |||
| using juce::CharPointer_UTF8; | |||
| using juce::File; | |||
| using juce::MemoryOutputStream; | |||
| using juce::ScopedPointer; | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce::XmlDocument; | |||
| using juce::XmlElement; | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce2::Array; | |||
| using juce2::CharPointer_UTF8; | |||
| using juce2::File; | |||
| using juce2::MemoryOutputStream; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| using juce2::XmlDocument; | |||
| using juce2::XmlElement; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -1674,7 +1672,7 @@ void CarlaEngine::setPluginPeaks(const uint pluginId, float const inPeaks[2], fl | |||
| pluginData.outsPeak[1] = outPeaks[1]; | |||
| } | |||
| void CarlaEngine::saveProjectInternal(juce::MemoryOutputStream& outStream) const | |||
| void CarlaEngine::saveProjectInternal(juce2::MemoryOutputStream& outStream) const | |||
| { | |||
| // send initial prepareForSave first, giving time for bridges to act | |||
| for (uint i=0; i < pData->curPluginCount; ++i) | |||
| @@ -1876,7 +1874,7 @@ static String findBinaryInCustomPath(const char* const searchPath, const char* c | |||
| return String(); | |||
| } | |||
| bool CarlaEngine::loadProjectInternal(juce::XmlDocument& xmlDoc) | |||
| bool CarlaEngine::loadProjectInternal(juce2::XmlDocument& xmlDoc) | |||
| { | |||
| ScopedPointer<XmlElement> xmlElement(xmlDoc.getDocumentElement(true)); | |||
| CARLA_SAFE_ASSERT_RETURN_ERR(xmlElement != nullptr, "Failed to parse project file"); | |||
| @@ -31,17 +31,15 @@ | |||
| # include <xmmintrin.h> | |||
| #endif | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| // must be last | |||
| #include "jackbridge/JackBridge.hpp" | |||
| using juce::File; | |||
| using juce::MemoryBlock; | |||
| using juce::String; | |||
| using juce::Time; | |||
| using juce::Thread; | |||
| using juce2::File; | |||
| using juce2::MemoryBlock; | |||
| using juce2::String; | |||
| using juce2::Time; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -79,13 +77,13 @@ private: | |||
| // ------------------------------------------------------------------- | |||
| class CarlaEngineBridge : public CarlaEngine, | |||
| private Thread, | |||
| private CarlaThread, | |||
| private LatencyChangedCallback | |||
| { | |||
| public: | |||
| CarlaEngineBridge(const char* const audioPoolBaseName, const char* const rtClientBaseName, const char* const nonRtClientBaseName, const char* const nonRtServerBaseName) | |||
| : CarlaEngine(), | |||
| Thread("CarlaEngineBridge"), | |||
| CarlaThread("CarlaEngineBridge"), | |||
| fShmAudioPool(), | |||
| fShmRtClientControl(), | |||
| fShmNonRtClientControl(), | |||
| @@ -207,7 +205,8 @@ public: | |||
| fShmNonRtServerControl.commitWrite(); | |||
| } | |||
| startThread(Thread::realtimeAudioPriority); | |||
| // TODO | |||
| startThread(/*Thread::realtimeAudioPriority*/); | |||
| return true; | |||
| } | |||
| @@ -564,7 +563,7 @@ public: | |||
| if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 30000 && ! wasFirstIdle) | |||
| { | |||
| carla_stderr("Did not receive ping message from server for 30 secs, closing..."); | |||
| threadShouldExit(); | |||
| signalThreadShouldExit(); | |||
| callback(ENGINE_CALLBACK_QUIT, 0, 0, 0, 0.0f, nullptr); | |||
| } | |||
| } | |||
| @@ -955,7 +954,7 @@ protected: | |||
| bool quitReceived = false; | |||
| for (; ! threadShouldExit();) | |||
| for (; ! shouldThreadExit();) | |||
| { | |||
| const BridgeRtClientControl::WaitHelper helper(fShmRtClientControl); | |||
| @@ -34,14 +34,13 @@ | |||
| #include "CarlaHost.h" | |||
| #include "CarlaNative.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| using juce::File; | |||
| using juce::MemoryOutputStream; | |||
| using juce::String; | |||
| using juce::XmlDocument; | |||
| using juce::XmlElement; | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce2::File; | |||
| using juce2::MemoryOutputStream; | |||
| using juce2::String; | |||
| using juce2::XmlDocument; | |||
| using juce2::XmlElement; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -25,16 +25,15 @@ | |||
| #include <ctime> | |||
| #include "juce_core/juce_core.h" | |||
| using juce::CharPointer_UTF8; | |||
| using juce::File; | |||
| using juce::MemoryOutputStream; | |||
| using juce::Result; | |||
| using juce::ScopedPointer; | |||
| using juce::String; | |||
| using juce::XmlDocument; | |||
| using juce::XmlElement; | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce2::CharPointer_UTF8; | |||
| using juce2::File; | |||
| using juce2::MemoryOutputStream; | |||
| using juce2::Result; | |||
| using juce2::String; | |||
| using juce2::XmlDocument; | |||
| using juce2::XmlElement; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -30,14 +30,15 @@ | |||
| #include <ctime> | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| // --------------------------------------------------------------------------------------------------------------------- | |||
| using juce::ChildProcess; | |||
| using juce::File; | |||
| using juce::ScopedPointer; | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce::Time; | |||
| using juce2::ChildProcess; | |||
| using juce2::File; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| using juce2::Time; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -171,7 +172,7 @@ protected: | |||
| arguments.add(fLabel); | |||
| // uniqueId | |||
| arguments.add(String(static_cast<juce::int64>(kPlugin->getUniqueId()))); | |||
| arguments.add(String(static_cast<juce2::int64>(kPlugin->getUniqueId()))); | |||
| bool started; | |||
| @@ -27,10 +27,9 @@ | |||
| # include "CarlaThread.hpp" | |||
| #endif | |||
| using juce::ChildProcess; | |||
| using juce::ScopedPointer; | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce2::ChildProcess; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| #define CARLA_PLUGIN_DSSI_OSC_CHECK_OSC_TYPES(/* argc, types, */ argcToCompare, typesToCompare) \ | |||
| /* check argument count */ \ | |||
| @@ -22,7 +22,7 @@ | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #include <fluidsynth.h> | |||
| @@ -32,8 +32,8 @@ | |||
| #define FLUID_DEFAULT_POLYPHONY 64 | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -34,12 +34,11 @@ | |||
| // ------------------------------------------------------------------------------------------------------------------- | |||
| using juce::ChildProcess; | |||
| using juce::File; | |||
| using juce::ScopedPointer; | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce::Time; | |||
| using juce2::ChildProcess; | |||
| using juce2::File; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| using juce2::Time; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -37,12 +37,12 @@ extern "C" { | |||
| #include "rtmempool/rtmempool-lv2.h" | |||
| } | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #include <string> | |||
| #include <vector> | |||
| using juce::File; | |||
| using juce2::File; | |||
| #define URI_CARLA_ATOM_WORKER "http://kxstudio.sf.net/ns/carla/atomWorker" | |||
| @@ -31,7 +31,7 @@ | |||
| #include "CarlaBackendUtils.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| // ----------------------------------------------------------------------- | |||
| @@ -198,9 +198,9 @@ public: | |||
| // ----------------------------------------------------------------------- | |||
| using juce::File; | |||
| using juce::SharedResourcePointer; | |||
| using juce::StringArray; | |||
| using juce2::File; | |||
| using juce2::SharedResourcePointer; | |||
| using juce2::StringArray; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -461,7 +461,7 @@ public: | |||
| if (programList.size() == MAX_MIDI_CHANNELS) | |||
| { | |||
| uint8_t channel = 0; | |||
| for (juce::String *it=programList.begin(), *end=programList.end(); it != end; ++it) | |||
| for (juce2::String *it=programList.begin(), *end=programList.end(); it != end; ++it) | |||
| { | |||
| const int index(it->getIntValue()); | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugin | |||
| * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -21,11 +21,11 @@ | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaNative.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce::jmax; | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce2::jmax; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| CARLA_EXTERN_C | |||
| std::size_t carla_getNativePluginCount() noexcept; | |||
| @@ -27,8 +27,7 @@ | |||
| #include "CarlaLv2Utils.hpp" | |||
| #include "CarlaUtils.h" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| // --------------------------------------------------------------------------------------------------------------------- | |||
| // -Weffc++ compat ext widget | |||
| @@ -109,7 +108,7 @@ public: | |||
| setCallback(_engine_callback, this); | |||
| using juce::File; | |||
| using juce2::File; | |||
| const File pluginFile(File::getSpecialLocation(File::currentExecutableFile).withFileExtension("xml")); | |||
| if (! loadProject(pluginFile.getFullPathName().toRawUTF8())) | |||
| @@ -825,7 +824,7 @@ const LV2_Descriptor* lv2_descriptor(uint32_t index) | |||
| if (ret.isEmpty()) | |||
| { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| const File file(File::getSpecialLocation(File::currentExecutableFile).withFileExtension("ttl")); | |||
| ret = String("file://" + file.getFullPathName()).toRawUTF8(); | |||
| } | |||
| @@ -853,7 +852,7 @@ const LV2UI_Descriptor* lv2ui_descriptor(uint32_t index) | |||
| if (ret.isEmpty()) | |||
| { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| const File file(File::getSpecialLocation(File::currentExecutableFile).getSiblingFile("ext-ui")); | |||
| ret = String("file://" + file.getFullPathName()).toRawUTF8(); | |||
| } | |||
| @@ -36,17 +36,16 @@ | |||
| #include "jackbridge/JackBridge.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using CarlaBackend::CarlaEngine; | |||
| using CarlaBackend::EngineCallbackOpcode; | |||
| using CarlaBackend::EngineCallbackOpcode2Str; | |||
| using CarlaBackend::runMainLoopOnce; | |||
| using juce::CharPointer_UTF8; | |||
| using juce::File; | |||
| using juce::String; | |||
| using juce2::CharPointer_UTF8; | |||
| using juce2::File; | |||
| using juce2::String; | |||
| // ------------------------------------------------------------------------- | |||
| @@ -43,11 +43,11 @@ LIBS_win64 = $(MODULEDIR)/jackbridge.win64e.a | |||
| endif | |||
| LINK_FLAGS += $(JACKBRIDGE_LIBS) | |||
| LIBS_native += $(MODULEDIR)/juce_core.a | |||
| LIBS_posix32 += $(MODULEDIR)/juce_core.posix32.a | |||
| LIBS_posix64 += $(MODULEDIR)/juce_core.posix64.a | |||
| LIBS_win32 += $(MODULEDIR)/juce_core.win32.a | |||
| LIBS_win64 += $(MODULEDIR)/juce_core.win64.a | |||
| LIBS_native += $(MODULEDIR)/juce_audio_graph.a | |||
| LIBS_posix32 += $(MODULEDIR)/juce_audio_graph.posix32.a | |||
| LIBS_posix64 += $(MODULEDIR)/juce_audio_graph.posix64.a | |||
| LIBS_win32 += $(MODULEDIR)/juce_audio_graph.win32.a | |||
| LIBS_win64 += $(MODULEDIR)/juce_audio_graph.win64.a | |||
| LINK_FLAGS += $(JUCE_CORE_LIBS) | |||
| LIBS_native += $(MODULEDIR)/lilv.a | |||
| @@ -21,15 +21,14 @@ | |||
| #include "CarlaMIDI.h" | |||
| #include "LinkedList.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #include <string> | |||
| #include <vector> | |||
| #define URI_CARLA_ATOM_WORKER "http://kxstudio.sf.net/ns/carla/atomWorker" | |||
| using juce::File; | |||
| using juce2::File; | |||
| CARLA_BRIDGE_START_NAMESPACE | |||
| @@ -129,7 +129,7 @@ ui_lv2-windows: $(BINDIR)/$(MODULENAME)-lv2-windows.exe | |||
| # Common libs | |||
| LIBS = \ | |||
| $(MODULEDIR)/juce_core.a \ | |||
| $(MODULEDIR)/juce_audio_graph.a \ | |||
| $(MODULEDIR)/lilv.a | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| @@ -59,11 +59,11 @@ endif | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| LIBS_native = $(MODULEDIR)/juce_core.a | |||
| LIBS_posix32 = $(MODULEDIR)/juce_core.posix32.a | |||
| LIBS_posix64 = $(MODULEDIR)/juce_core.posix64.a | |||
| LIBS_win32 = $(MODULEDIR)/juce_core.win32.a | |||
| LIBS_win64 = $(MODULEDIR)/juce_core.win64.a | |||
| LIBS_native = $(MODULEDIR)/juce_audio_graph.a | |||
| LIBS_posix32 = $(MODULEDIR)/juce_audio_graph.posix32.a | |||
| LIBS_posix64 = $(MODULEDIR)/juce_audio_graph.posix64.a | |||
| LIBS_win32 = $(MODULEDIR)/juce_audio_graph.win32.a | |||
| LIBS_win64 = $(MODULEDIR)/juce_audio_graph.win64.a | |||
| LINK_FLAGS += $(JUCE_CORE_LIBS) | |||
| LIBS_native += $(MODULEDIR)/lilv.a | |||
| @@ -45,14 +45,13 @@ | |||
| #include <iostream> | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #define DISCOVERY_OUT(x, y) std::cout << "\ncarla-discovery::" << x << "::" << y << std::endl; | |||
| using juce::CharPointer_UTF8; | |||
| using juce::File; | |||
| using juce::StringArray; | |||
| using juce2::CharPointer_UTF8; | |||
| using juce2::File; | |||
| using juce2::StringArray; | |||
| CARLA_BACKEND_USE_NAMESPACE | |||
| @@ -984,7 +983,7 @@ static void do_lv2_check(const char* const bundle, const bool doInit) | |||
| Lilv::Plugin lilvPlugin(lilv_plugins_get(lilvPlugins, it)); | |||
| if (const char* const uri = lilvPlugin.get_uri().as_string()) | |||
| URIs.addIfNotAlreadyThere(juce::String(uri)); | |||
| URIs.addIfNotAlreadyThere(juce2::String(uri)); | |||
| } | |||
| if (URIs.size() == 0) | |||
| @@ -1436,7 +1435,7 @@ static void do_vst_check(lib_t& libHandle, const bool doInit) | |||
| static void do_fluidsynth_check(const char* const filename, const bool doInit) | |||
| { | |||
| #ifdef HAVE_FLUIDSYNTH | |||
| const juce::String jfilename = juce::String(CharPointer_UTF8(filename)); | |||
| const juce2::String jfilename = juce2::String(CharPointer_UTF8(filename)); | |||
| const File file(jfilename); | |||
| if (! file.existsAsFile()) | |||
| @@ -1526,7 +1525,7 @@ static void do_fluidsynth_check(const char* const filename, const bool doInit) | |||
| static void do_linuxsampler_check(const char* const filename, const char* const stype, const bool doInit) | |||
| { | |||
| #ifdef HAVE_LINUXSAMPLER | |||
| const juce::String jfilename = juce::String(CharPointer_UTF8(filename)); | |||
| const juce2::String jfilename = juce2::String(CharPointer_UTF8(filename)); | |||
| const File file(jfilename); | |||
| if (! file.existsAsFile()) | |||
| @@ -22,9 +22,8 @@ endif | |||
| # ---------------------------------------------------------------------------------------------------------------------- | |||
| BUILD_C_FLAGS += -I$(CWD) -I$(CWD)/includes | |||
| BUILD_CXX_FLAGS += -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils | |||
| LINK_FLAGS += $(MODULEDIR)/juce_core.a | |||
| LINK_FLAGS += $(JUCE_CORE_LIBS) | |||
| BUILD_CXX_FLAGS += -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/utils | |||
| LINK_FLAGS += -lpthread -lrt | |||
| # ---------------------------------------------------------------------------------------------------------------------- | |||
| @@ -16,12 +16,12 @@ | |||
| */ | |||
| #include "libjack.hpp" | |||
| #include <sys/prctl.h> | |||
| #include "CarlaThread.hpp" | |||
| using juce::Thread; | |||
| using juce::Time; | |||
| #include <signal.h> | |||
| #include <sys/prctl.h> | |||
| #include <sys/time.h> | |||
| typedef int (*CarlaInterposedCallback)(int, void*); | |||
| @@ -34,9 +34,16 @@ int jack_carla_interposed_action(int, int, void*) | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| static int64_t getCurrentTimeMilliseconds() noexcept | |||
| { | |||
| struct timeval tv; | |||
| gettimeofday (&tv, nullptr); | |||
| return ((int64_t) tv.tv_sec) * 1000 + tv.tv_usec / 1000; | |||
| } | |||
| // --------------------------------------------------------------------------------------------------------------------- | |||
| class CarlaJackRealtimeThread : public Thread | |||
| class CarlaJackRealtimeThread : public CarlaThread | |||
| { | |||
| public: | |||
| struct Callback { | |||
| @@ -46,7 +53,7 @@ public: | |||
| }; | |||
| CarlaJackRealtimeThread(Callback* const callback) | |||
| : Thread("CarlaJackRealtimeThread"), | |||
| : CarlaThread("CarlaJackRealtimeThread"), | |||
| fCallback(callback) {} | |||
| protected: | |||
| @@ -63,7 +70,7 @@ private: | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| class CarlaJackNonRealtimeThread : public Thread | |||
| class CarlaJackNonRealtimeThread : public CarlaThread | |||
| { | |||
| public: | |||
| struct Callback { | |||
| @@ -73,7 +80,7 @@ public: | |||
| }; | |||
| CarlaJackNonRealtimeThread(Callback* const callback) | |||
| : Thread("CarlaJackNonRealtimeThread"), | |||
| : CarlaThread("CarlaJackNonRealtimeThread"), | |||
| fCallback(callback) {} | |||
| protected: | |||
| @@ -380,7 +387,7 @@ bool CarlaJackAppClient::initSharedMemmory() | |||
| // tell backend we're live | |||
| const CarlaMutexLocker _cml(fShmNonRtServerControl.mutex); | |||
| fLastPingTime = Time::currentTimeMillis(); | |||
| fLastPingTime = getCurrentTimeMilliseconds(); | |||
| CARLA_SAFE_ASSERT(fLastPingTime > 0); | |||
| // ready! | |||
| @@ -855,7 +862,7 @@ bool CarlaJackAppClient::handleNonRtData() | |||
| #endif | |||
| if (opcode != kPluginBridgeNonRtClientNull && opcode != kPluginBridgeNonRtClientPingOnOff && fLastPingTime > 0) | |||
| fLastPingTime = Time::currentTimeMillis(); | |||
| fLastPingTime = getCurrentTimeMilliseconds(); | |||
| switch (opcode) | |||
| { | |||
| @@ -872,7 +879,7 @@ bool CarlaJackAppClient::handleNonRtData() | |||
| case kPluginBridgeNonRtClientPingOnOff: { | |||
| const uint32_t onOff(fShmNonRtClientControl.readBool()); | |||
| fLastPingTime = onOff ? Time::currentTimeMillis() : -1; | |||
| fLastPingTime = onOff ? getCurrentTimeMilliseconds() : -1; | |||
| } break; | |||
| case kPluginBridgeNonRtClientActivate: | |||
| @@ -968,7 +975,7 @@ void CarlaJackAppClient::runRealtimeThread() | |||
| bool quitReceived = false; | |||
| for (; ! fRealtimeThread.threadShouldExit();) | |||
| for (; ! fRealtimeThread.shouldThreadExit();) | |||
| { | |||
| if (handleRtData()) | |||
| { | |||
| @@ -1003,15 +1010,16 @@ void CarlaJackAppClient::runNonRealtimeThread() | |||
| fMidiOutBuffers[i].isInput = false; | |||
| } | |||
| fRealtimeThread.startThread(Thread::realtimeAudioPriority); | |||
| // TODO | |||
| fRealtimeThread.startThread(/*Thread::realtimeAudioPriority*/); | |||
| fLastPingTime = Time::currentTimeMillis(); | |||
| fLastPingTime = getCurrentTimeMilliseconds(); | |||
| carla_stdout("Carla Jack Client Ready!"); | |||
| bool quitReceived = false, | |||
| timedOut = false; | |||
| for (; ! fNonRealtimeThread.threadShouldExit();) | |||
| for (; ! fNonRealtimeThread.shouldThreadExit();) | |||
| { | |||
| carla_msleep(50); | |||
| @@ -1023,7 +1031,7 @@ void CarlaJackAppClient::runNonRealtimeThread() | |||
| break; | |||
| /* | |||
| if (fLastPingTime > 0 && Time::currentTimeMillis() > fLastPingTime + 30000) | |||
| if (fLastPingTime > 0 && getCurrentTimeMilliseconds() > fLastPingTime + 30000) | |||
| { | |||
| carla_stderr("Did not receive ping message from server for 30 secs, closing..."); | |||
| @@ -28,9 +28,6 @@ | |||
| #include "CarlaMutex.hpp" | |||
| #include "LinkedList.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #if 0 | |||
| #include <jack/jack.h> | |||
| #include <jack/midiport.h> | |||
| @@ -15,7 +15,6 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // need to include this first | |||
| #include "libjack.hpp" | |||
| CARLA_BACKEND_USE_NAMESPACE | |||
| @@ -15,7 +15,6 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // need to include this first | |||
| #include "libjack.hpp" | |||
| CARLA_BACKEND_USE_NAMESPACE | |||
| @@ -15,7 +15,6 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // need to include this first | |||
| #include "libjack.hpp" | |||
| CARLA_BACKEND_USE_NAMESPACE | |||
| @@ -15,7 +15,6 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| // need to include this first | |||
| #include "libjack.hpp" | |||
| CARLA_BACKEND_USE_NAMESPACE | |||
| @@ -20,6 +20,8 @@ | |||
| This is safe for the case of one read thread and one write thread. | |||
| */ | |||
| #define USE_MLOCK | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #ifdef USE_MLOCK | |||
| @@ -9,7 +9,7 @@ | |||
| all: | |||
| clean: | |||
| $(MAKE) clean -C juce_core | |||
| $(MAKE) clean -C juce_audio_graph | |||
| $(MAKE) clean -C lilv | |||
| $(MAKE) clean -C rtaudio | |||
| $(MAKE) clean -C rtmempool | |||
| @@ -31,8 +31,6 @@ | |||
| #ifndef JUCE_AUDIOSAMPLEBUFFER_H_INCLUDED | |||
| #define JUCE_AUDIOSAMPLEBUFFER_H_INCLUDED | |||
| #include "CarlaMathUtils.hpp" | |||
| //============================================================================== | |||
| /** | |||
| A multi-channel buffer of floating point audio samples. | |||
| @@ -89,12 +89,8 @@ bool NamedValueSet::isEmpty() const noexcept | |||
| static const var& getNullVarRef() noexcept | |||
| { | |||
| #if JUCE_ALLOW_STATIC_NULL_VARIABLES | |||
| return var::null; | |||
| #else | |||
| static var nullVar; | |||
| return nullVar; | |||
| #endif | |||
| } | |||
| const var& NamedValueSet::operator[] (const Identifier& name) const noexcept | |||
| @@ -76,11 +76,6 @@ public: | |||
| /** Destructor. */ | |||
| ~var() noexcept; | |||
| #if JUCE_ALLOW_STATIC_NULL_VARIABLES | |||
| /** A static var object that can be used where you need an empty variant object. */ | |||
| static const var null; | |||
| #endif | |||
| var (const var& valueToCopy); | |||
| var (int value) noexcept; | |||
| var (int64 value) noexcept; | |||
| @@ -0,0 +1,168 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| DirectoryIterator::DirectoryIterator (const File& directory, bool recursive, | |||
| const String& pattern, const int type) | |||
| : wildCards (parseWildcards (pattern)), | |||
| fileFinder (directory, (recursive || wildCards.size() > 1) ? "*" : pattern), | |||
| wildCard (pattern), | |||
| path (File::addTrailingSeparator (directory.getFullPathName())), | |||
| index (-1), | |||
| totalNumFiles (-1), | |||
| whatToLookFor (type), | |||
| isRecursive (recursive), | |||
| hasBeenAdvanced (false) | |||
| { | |||
| // you have to specify the type of files you're looking for! | |||
| jassert ((type & (File::findFiles | File::findDirectories)) != 0); | |||
| jassert (type > 0 && type <= 7); | |||
| } | |||
| DirectoryIterator::~DirectoryIterator() | |||
| { | |||
| } | |||
| StringArray DirectoryIterator::parseWildcards (const String& pattern) | |||
| { | |||
| StringArray s; | |||
| s.addTokens (pattern, ";,", "\"'"); | |||
| s.trim(); | |||
| s.removeEmptyStrings(); | |||
| return s; | |||
| } | |||
| bool DirectoryIterator::fileMatches (const StringArray& wildCards, const String& filename) | |||
| { | |||
| for (int i = 0; i < wildCards.size(); ++i) | |||
| if (filename.matchesWildcard (wildCards[i], ! File::areFileNamesCaseSensitive())) | |||
| return true; | |||
| return false; | |||
| } | |||
| bool DirectoryIterator::next() | |||
| { | |||
| return next (nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); | |||
| } | |||
| bool DirectoryIterator::next (bool* const isDirResult, bool* const isHiddenResult, int64* const fileSize, | |||
| Time* const modTime, Time* const creationTime, bool* const isReadOnly) | |||
| { | |||
| for (;;) | |||
| { | |||
| hasBeenAdvanced = true; | |||
| if (subIterator != nullptr) | |||
| { | |||
| if (subIterator->next (isDirResult, isHiddenResult, fileSize, modTime, creationTime, isReadOnly)) | |||
| return true; | |||
| subIterator = nullptr; | |||
| } | |||
| String filename; | |||
| bool isDirectory, isHidden = false, shouldContinue = false; | |||
| while (fileFinder.next (filename, &isDirectory, | |||
| (isHiddenResult != nullptr || (whatToLookFor & File::ignoreHiddenFiles) != 0) ? &isHidden : nullptr, | |||
| fileSize, modTime, creationTime, isReadOnly)) | |||
| { | |||
| ++index; | |||
| if (! filename.containsOnly (".")) | |||
| { | |||
| bool matches = false; | |||
| if (isDirectory) | |||
| { | |||
| if (isRecursive && ((whatToLookFor & File::ignoreHiddenFiles) == 0 || ! isHidden)) | |||
| subIterator = new DirectoryIterator (File::createFileWithoutCheckingPath (path + filename), | |||
| true, wildCard, whatToLookFor); | |||
| matches = (whatToLookFor & File::findDirectories) != 0; | |||
| } | |||
| else | |||
| { | |||
| matches = (whatToLookFor & File::findFiles) != 0; | |||
| } | |||
| // if we're not relying on the OS iterator to do the wildcard match, do it now.. | |||
| if (matches && (isRecursive || wildCards.size() > 1)) | |||
| matches = fileMatches (wildCards, filename); | |||
| if (matches && (whatToLookFor & File::ignoreHiddenFiles) != 0) | |||
| matches = ! isHidden; | |||
| if (matches) | |||
| { | |||
| currentFile = File::createFileWithoutCheckingPath (path + filename); | |||
| if (isHiddenResult != nullptr) *isHiddenResult = isHidden; | |||
| if (isDirResult != nullptr) *isDirResult = isDirectory; | |||
| return true; | |||
| } | |||
| if (subIterator != nullptr) | |||
| { | |||
| shouldContinue = true; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| if (! shouldContinue) | |||
| return false; | |||
| } | |||
| } | |||
| const File& DirectoryIterator::getFile() const | |||
| { | |||
| if (subIterator != nullptr && subIterator->hasBeenAdvanced) | |||
| return subIterator->getFile(); | |||
| // You need to call DirectoryIterator::next() before asking it for the file that it found! | |||
| jassert (hasBeenAdvanced); | |||
| return currentFile; | |||
| } | |||
| float DirectoryIterator::getEstimatedProgress() const | |||
| { | |||
| if (totalNumFiles < 0) | |||
| totalNumFiles = File (path).getNumberOfChildFiles (File::findFilesAndDirectories); | |||
| if (totalNumFiles <= 0) | |||
| return 0.0f; | |||
| const float detailedIndex = (subIterator != nullptr) ? index + subIterator->getEstimatedProgress() | |||
| : (float) index; | |||
| return detailedIndex / totalNumFiles; | |||
| } | |||
| @@ -0,0 +1,159 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_DIRECTORYITERATOR_H_INCLUDED | |||
| #define JUCE_DIRECTORYITERATOR_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| Searches through the files in a directory, returning each file that is found. | |||
| A DirectoryIterator will search through a directory and its subdirectories using | |||
| a wildcard filepattern match. | |||
| If you may be scanning a large number of files, it's usually smarter to use this | |||
| class than File::findChildFiles() because it allows you to stop at any time, rather | |||
| than having to wait for the entire scan to finish before getting the results. | |||
| It also provides an estimate of its progress, using a (highly inaccurate!) algorithm. | |||
| */ | |||
| class JUCE_API DirectoryIterator | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a DirectoryIterator for a given directory. | |||
| After creating one of these, call its next() method to get the | |||
| first file - e.g. @code | |||
| DirectoryIterator iter (File ("/animals/mooses"), true, "*.moose"); | |||
| while (iter.next()) | |||
| { | |||
| File theFileItFound (iter.getFile()); | |||
| ... etc | |||
| } | |||
| @endcode | |||
| @param directory the directory to search in | |||
| @param isRecursive whether all the subdirectories should also be searched | |||
| @param wildCard the file pattern to match. This may contain multiple patterns | |||
| separated by a semi-colon or comma, e.g. "*.jpg;*.png" | |||
| @param whatToLookFor a value from the File::TypesOfFileToFind enum, specifying | |||
| whether to look for files, directories, or both. | |||
| */ | |||
| DirectoryIterator (const File& directory, | |||
| bool isRecursive, | |||
| const String& wildCard = "*", | |||
| int whatToLookFor = File::findFiles); | |||
| /** Destructor. */ | |||
| ~DirectoryIterator(); | |||
| /** Moves the iterator along to the next file. | |||
| @returns true if a file was found (you can then use getFile() to see what it was) - or | |||
| false if there are no more matching files. | |||
| */ | |||
| bool next(); | |||
| /** Moves the iterator along to the next file, and returns various properties of that file. | |||
| If you need to find out details about the file, it's more efficient to call this method than | |||
| to call the normal next() method and then find out the details afterwards. | |||
| All the parameters are optional, so pass null pointers for any items that you're not | |||
| interested in. | |||
| @returns true if a file was found (you can then use getFile() to see what it was) - or | |||
| false if there are no more matching files. If it returns false, then none of the | |||
| parameters will be filled-in. | |||
| */ | |||
| bool next (bool* isDirectory, | |||
| bool* isHidden, | |||
| int64* fileSize, | |||
| Time* modTime, | |||
| Time* creationTime, | |||
| bool* isReadOnly); | |||
| /** Returns the file that the iterator is currently pointing at. | |||
| The result of this call is only valid after a call to next() has returned true. | |||
| */ | |||
| const File& getFile() const; | |||
| /** Returns a guess of how far through the search the iterator has got. | |||
| @returns a value 0.0 to 1.0 to show the progress, although this won't be | |||
| very accurate. | |||
| */ | |||
| float getEstimatedProgress() const; | |||
| private: | |||
| //============================================================================== | |||
| class NativeIterator | |||
| { | |||
| public: | |||
| NativeIterator (const File& directory, const String& wildCard); | |||
| ~NativeIterator(); | |||
| bool next (String& filenameFound, | |||
| bool* isDirectory, bool* isHidden, int64* fileSize, | |||
| Time* modTime, Time* creationTime, bool* isReadOnly); | |||
| class Pimpl; | |||
| private: | |||
| friend class DirectoryIterator; | |||
| ScopedPointer<Pimpl> pimpl; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeIterator) | |||
| }; | |||
| StringArray wildCards; | |||
| NativeIterator fileFinder; | |||
| String wildCard, path; | |||
| int index; | |||
| mutable int totalNumFiles; | |||
| const int whatToLookFor; | |||
| const bool isRecursive; | |||
| bool hasBeenAdvanced; | |||
| ScopedPointer<DirectoryIterator> subIterator; | |||
| File currentFile; | |||
| static StringArray parseWildcards (const String& pattern); | |||
| static bool fileMatches (const StringArray& wildCards, const String& filename); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DirectoryIterator) | |||
| }; | |||
| #endif // JUCE_DIRECTORYITERATOR_H_INCLUDED | |||
| @@ -742,41 +742,6 @@ public: | |||
| /** The user's home folder. This is the same as using File ("~"). */ | |||
| userHomeDirectory, | |||
| /** The user's default documents folder. On Windows, this might be the user's | |||
| "My Documents" folder. On the Mac it'll be their "Documents" folder. Linux | |||
| doesn't tend to have one of these, so it might just return their home folder. | |||
| */ | |||
| userDocumentsDirectory, | |||
| /** The folder that contains the user's desktop objects. */ | |||
| userDesktopDirectory, | |||
| /** The most likely place where a user might store their music files. */ | |||
| userMusicDirectory, | |||
| /** The most likely place where a user might store their movie files. */ | |||
| userMoviesDirectory, | |||
| /** The most likely place where a user might store their picture files. */ | |||
| userPicturesDirectory, | |||
| /** The folder in which applications store their persistent user-specific settings. | |||
| On Windows, this might be "\Documents and Settings\username\Application Data". | |||
| On the Mac, it might be "~/Library". If you're going to store your settings in here, | |||
| always create your own sub-folder to put them in, to avoid making a mess. | |||
| */ | |||
| userApplicationDataDirectory, | |||
| /** An equivalent of the userApplicationDataDirectory folder that is shared by all users | |||
| of the computer, rather than just the current user. | |||
| On the Mac it'll be "/Library", on Windows, it could be something like | |||
| "\Documents and Settings\All Users\Application Data". | |||
| Depending on the setup, this folder may be read-only. | |||
| */ | |||
| commonApplicationDataDirectory, | |||
| /** A place to put documents which are shared by all users of the machine. | |||
| On Windows this may be somewhere like "C:\Users\Public\Documents", on OSX it | |||
| will be something like "/Users/Shared". Other OSes may have no such concept | |||
| @@ -812,17 +777,10 @@ public: | |||
| */ | |||
| currentApplicationFile, | |||
| /** Returns the file that was invoked to launch this executable. | |||
| This may differ from currentExecutableFile if the app was started from e.g. a link - this | |||
| will return the name of the link that was used, whereas currentExecutableFile will return | |||
| the actual location of the target executable. | |||
| */ | |||
| invokedExecutableFile, | |||
| /** In a plugin, this will return the path of the host executable. */ | |||
| hostApplicationPath, | |||
| #if JUCE_WINDOWS | |||
| #ifdef CARLA_OS_WIN | |||
| /** On a Windows machine, returns the location of the Windows/System32 folder. */ | |||
| windowsSystemDirectory, | |||
| #endif | |||
| @@ -925,7 +883,7 @@ public: | |||
| */ | |||
| File getLinkedTarget() const; | |||
| #if JUCE_WINDOWS | |||
| #ifdef CARLA_OS_WIN | |||
| /** Windows ONLY - Creates a win32 .LNK shortcut file that links to this file. */ | |||
| bool createShortcut (const String& description, const File& linkFileToCreate) const; | |||
| @@ -0,0 +1,136 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| int64 juce_fileSetPosition (void* handle, int64 pos); | |||
| //============================================================================== | |||
| FileOutputStream::FileOutputStream (const File& f, const size_t bufferSizeToUse) | |||
| : file (f), | |||
| fileHandle (nullptr), | |||
| status (Result::ok()), | |||
| currentPosition (0), | |||
| bufferSize (bufferSizeToUse), | |||
| bytesInBuffer (0), | |||
| buffer (jmax (bufferSizeToUse, (size_t) 16)) | |||
| { | |||
| openHandle(); | |||
| } | |||
| FileOutputStream::~FileOutputStream() | |||
| { | |||
| flushBuffer(); | |||
| closeHandle(); | |||
| } | |||
| int64 FileOutputStream::getPosition() | |||
| { | |||
| return currentPosition; | |||
| } | |||
| bool FileOutputStream::setPosition (int64 newPosition) | |||
| { | |||
| if (newPosition != currentPosition) | |||
| { | |||
| flushBuffer(); | |||
| currentPosition = juce_fileSetPosition (fileHandle, newPosition); | |||
| } | |||
| return newPosition == currentPosition; | |||
| } | |||
| bool FileOutputStream::flushBuffer() | |||
| { | |||
| bool ok = true; | |||
| if (bytesInBuffer > 0) | |||
| { | |||
| ok = (writeInternal (buffer, bytesInBuffer) == (ssize_t) bytesInBuffer); | |||
| bytesInBuffer = 0; | |||
| } | |||
| return ok; | |||
| } | |||
| void FileOutputStream::flush() | |||
| { | |||
| flushBuffer(); | |||
| flushInternal(); | |||
| } | |||
| bool FileOutputStream::write (const void* const src, const size_t numBytes) | |||
| { | |||
| jassert (src != nullptr && ((ssize_t) numBytes) >= 0); | |||
| if (bytesInBuffer + numBytes < bufferSize) | |||
| { | |||
| memcpy (buffer + bytesInBuffer, src, numBytes); | |||
| bytesInBuffer += numBytes; | |||
| currentPosition += (int64) numBytes; | |||
| } | |||
| else | |||
| { | |||
| if (! flushBuffer()) | |||
| return false; | |||
| if (numBytes < bufferSize) | |||
| { | |||
| memcpy (buffer + bytesInBuffer, src, numBytes); | |||
| bytesInBuffer += numBytes; | |||
| currentPosition += (int64) numBytes; | |||
| } | |||
| else | |||
| { | |||
| const ssize_t bytesWritten = writeInternal (src, numBytes); | |||
| if (bytesWritten < 0) | |||
| return false; | |||
| currentPosition += (int64) bytesWritten; | |||
| return bytesWritten == (ssize_t) numBytes; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| bool FileOutputStream::writeRepeatedByte (uint8 byte, size_t numBytes) | |||
| { | |||
| jassert (((ssize_t) numBytes) >= 0); | |||
| if (bytesInBuffer + numBytes < bufferSize) | |||
| { | |||
| memset (buffer + bytesInBuffer, byte, numBytes); | |||
| bytesInBuffer += numBytes; | |||
| currentPosition += (int64) numBytes; | |||
| return true; | |||
| } | |||
| return OutputStream::writeRepeatedByte (byte, numBytes); | |||
| } | |||
| @@ -0,0 +1,122 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_FILEOUTPUTSTREAM_H_INCLUDED | |||
| #define JUCE_FILEOUTPUTSTREAM_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| An output stream that writes into a local file. | |||
| @see OutputStream, FileInputStream, File::createOutputStream | |||
| */ | |||
| class JUCE_API FileOutputStream : public OutputStream | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a FileOutputStream. | |||
| If the file doesn't exist, it will first be created. If the file can't be | |||
| created or opened (for example, because the parent directory of the file | |||
| does not exist), the failedToOpen() method will return true. | |||
| If the file already exists when opened, the stream's write-position will | |||
| be set to the end of the file. To overwrite an existing file, | |||
| use File::deleteFile() before opening the stream, or use setPosition(0) | |||
| after it's opened (although this won't truncate the file). | |||
| Destroying a FileOutputStream object does not force the operating system | |||
| to write the buffered data to disk immediately. If this is required you | |||
| should call flush() before triggering the destructor. | |||
| @see TemporaryFile | |||
| */ | |||
| FileOutputStream (const File& fileToWriteTo, | |||
| size_t bufferSizeToUse = 16384); | |||
| /** Destructor. */ | |||
| ~FileOutputStream(); | |||
| //============================================================================== | |||
| /** Returns the file that this stream is writing to. | |||
| */ | |||
| const File& getFile() const { return file; } | |||
| /** Returns the status of the file stream. | |||
| The result will be ok if the file opened successfully. If an error occurs while | |||
| opening or writing to the file, this will contain an error message. | |||
| */ | |||
| const Result& getStatus() const noexcept { return status; } | |||
| /** Returns true if the stream couldn't be opened for some reason. | |||
| @see getResult() | |||
| */ | |||
| bool failedToOpen() const noexcept { return status.failed(); } | |||
| /** Returns true if the stream opened without problems. | |||
| @see getResult() | |||
| */ | |||
| bool openedOk() const noexcept { return status.wasOk(); } | |||
| /** Attempts to truncate the file to the current write position. | |||
| To truncate a file to a specific size, first use setPosition() to seek to the | |||
| appropriate location, and then call this method. | |||
| */ | |||
| Result truncate(); | |||
| //============================================================================== | |||
| void flush() override; | |||
| int64 getPosition() override; | |||
| bool setPosition (int64) override; | |||
| bool write (const void*, size_t) override; | |||
| bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override; | |||
| private: | |||
| //============================================================================== | |||
| File file; | |||
| void* fileHandle; | |||
| Result status; | |||
| int64 currentPosition; | |||
| size_t bufferSize, bytesInBuffer; | |||
| HeapBlock<char> buffer; | |||
| void openHandle(); | |||
| void closeHandle(); | |||
| void flushInternal(); | |||
| bool flushBuffer(); | |||
| int64 setPositionInternal (int64); | |||
| ssize_t writeInternal (const void*, size_t); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileOutputStream) | |||
| }; | |||
| #endif // JUCE_FILEOUTPUTSTREAM_H_INCLUDED | |||
| @@ -91,7 +91,7 @@ bool TemporaryFile::overwriteTargetFileWithTemporary() const | |||
| if (temporaryFile.replaceFileIn (targetFile)) | |||
| return true; | |||
| Thread::sleep (100); | |||
| carla_msleep (100); | |||
| } | |||
| } | |||
| else | |||
| @@ -112,7 +112,7 @@ bool TemporaryFile::deleteTemporaryFile() const | |||
| if (temporaryFile.deleteFile()) | |||
| return true; | |||
| Thread::sleep (50); | |||
| carla_msleep (50); | |||
| } | |||
| return false; | |||
| @@ -19,9 +19,28 @@ | |||
| #include "juce_audio_graph.h" | |||
| #include <locale> | |||
| #include <ctime> | |||
| #include <cctype> | |||
| #include <cstdarg> | |||
| #include <iostream> | |||
| #include <sys/time.h> | |||
| #ifdef CARLA_OS_WIN | |||
| #include <mmsystem.h> | |||
| #include <shlobj.h> | |||
| #else | |||
| #include <dlfcn.h> | |||
| #include <fcntl.h> | |||
| #include <pwd.h> | |||
| #include <signal.h> | |||
| #include <sys/stat.h> | |||
| #include <sys/wait.h> | |||
| #ifdef CARLA_OS_MAC | |||
| #else | |||
| #include <dirent.h> | |||
| #include <fnmatch.h> | |||
| #endif | |||
| #endif | |||
| // #include <wctype.h> | |||
| @@ -29,18 +48,87 @@ | |||
| namespace juce2 | |||
| { | |||
| #ifdef CARLA_OS_WIN | |||
| static Result getResultForLastError() | |||
| { | |||
| TCHAR messageBuffer [256] = { 0 }; | |||
| FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, | |||
| nullptr, GetLastError(), MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), | |||
| messageBuffer, (DWORD) numElementsInArray (messageBuffer) - 1, nullptr); | |||
| return Result::fail (String (messageBuffer)); | |||
| } | |||
| static int64 juce_fileSetPosition (void* handle, int64 pos) | |||
| { | |||
| LARGE_INTEGER li; | |||
| li.QuadPart = pos; | |||
| li.LowPart = SetFilePointer ((HANDLE) handle, (LONG) li.LowPart, &li.HighPart, FILE_BEGIN); // (returns -1 if it fails) | |||
| return li.QuadPart; | |||
| } | |||
| static void* currentModuleHandle = nullptr; | |||
| void* JUCE_CALLTYPE Process::getCurrentModuleInstanceHandle() noexcept | |||
| { | |||
| if (currentModuleHandle == nullptr) | |||
| currentModuleHandle = GetModuleHandleA (nullptr); | |||
| return currentModuleHandle; | |||
| } | |||
| #else | |||
| static Result getResultForErrno() | |||
| { | |||
| return Result::fail (String (strerror (errno))); | |||
| } | |||
| static int getFD (void* handle) noexcept { return (int) (pointer_sized_int) handle; } | |||
| static void* fdToVoidPointer (int fd) noexcept { return (void*) (pointer_sized_int) fd; } | |||
| static int64 juce_fileSetPosition (void* handle, int64 pos) | |||
| { | |||
| if (handle != 0 && lseek (getFD (handle), pos, SEEK_SET) == pos) | |||
| return pos; | |||
| return -1; | |||
| } | |||
| #endif | |||
| #include "memory/juce_MemoryBlock.cpp" | |||
| #include "text/juce_CharacterFunctions.cpp" | |||
| #include "text/juce_String.cpp" | |||
| // #include "streams/juce_InputStream.cpp" | |||
| // #include "streams/juce_OutputStream.cpp" | |||
| //#include "containers/juce_NamedValueSet.cpp" | |||
| //#include "containers/juce_Variant.cpp" | |||
| #include "files/juce_DirectoryIterator.cpp" | |||
| #include "files/juce_File.cpp" | |||
| #include "files/juce_TemporaryFile.cpp" | |||
| #include "midi/juce_MidiBuffer.cpp" | |||
| #include "midi/juce_MidiMessage.cpp" | |||
| #include "maths/juce_Random.cpp" | |||
| #include "misc/juce_Result.cpp" | |||
| #include "processors/juce_AudioProcessor.cpp" | |||
| #include "processors/juce_AudioProcessorGraph.cpp" | |||
| //#include "processors/juce_AudioProcessorGraph.cpp" | |||
| #include "streams/juce_FileInputSource.cpp" | |||
| #include "streams/juce_FileInputStream.cpp" | |||
| #include "streams/juce_FileOutputStream.cpp" | |||
| #include "streams/juce_InputStream.cpp" | |||
| #include "streams/juce_MemoryOutputStream.cpp" | |||
| #include "streams/juce_OutputStream.cpp" | |||
| #include "text/juce_Identifier.cpp" | |||
| #include "text/juce_StringArray.cpp" | |||
| #include "text/juce_StringPool.cpp" | |||
| #include "threads/juce_ChildProcess.cpp" | |||
| #include "time/juce_Time.cpp" | |||
| #include "xml/juce_XmlElement.cpp" | |||
| #include "xml/juce_XmlDocument.cpp" | |||
| @@ -19,9 +19,9 @@ | |||
| #ifndef JUCE_AUDIO_GRAPH_H_INCLUDED | |||
| #define JUCE_AUDIO_GRAPH_H_INCLUDED | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "CarlaMutex.hpp" | |||
| #include "distrho/extra/ScopedPointer.hpp" | |||
| #include <algorithm> | |||
| @@ -144,6 +144,10 @@ class XmlElement; | |||
| #include "text/juce_Identifier.h" | |||
| #include "text/juce_NewLine.h" | |||
| #include "threads/juce_ScopedLock.h" | |||
| #include "threads/juce_SpinLock.h" | |||
| #include "memory/juce_SharedResourcePointer.h" | |||
| #include "containers/juce_LinkedListPointer.h" | |||
| #include "containers/juce_OwnedArray.h" | |||
| #include "containers/juce_ReferenceCountedArray.h" | |||
| @@ -156,13 +160,19 @@ class XmlElement; | |||
| #include "streams/juce_OutputStream.h" | |||
| #include "streams/juce_MemoryOutputStream.h" | |||
| #include "maths/juce_Random.h" | |||
| #include "misc/juce_Result.h" | |||
| #include "text/juce_StringPool.h" | |||
| #include "time/juce_Time.h" | |||
| #include "files/juce_File.h" | |||
| #include "files/juce_DirectoryIterator.h" | |||
| #include "files/juce_TemporaryFile.h" | |||
| #include "streams/juce_FileInputStream.h" | |||
| #include "streams/juce_FileInputSource.h" | |||
| #include "streams/juce_FileOutputStream.h" | |||
| #include "buffers/juce_AudioSampleBuffer.h" | |||
| #include "midi/juce_MidiBuffer.h" | |||
| @@ -173,6 +183,9 @@ class AudioProcessor; | |||
| #include "processors/juce_AudioProcessor.h" | |||
| #include "processors/juce_AudioProcessorGraph.h" | |||
| #include "threads/juce_ChildProcess.h" | |||
| #include "threads/juce_Process.h" | |||
| #include "xml/juce_XmlElement.h" | |||
| #include "xml/juce_XmlDocument.h" | |||
| @@ -0,0 +1,163 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| Random::Random (const int64 seedValue) noexcept : seed (seedValue) | |||
| { | |||
| } | |||
| Random::Random() : seed (1) | |||
| { | |||
| setSeedRandomly(); | |||
| } | |||
| Random::~Random() noexcept | |||
| { | |||
| } | |||
| void Random::setSeed (const int64 newSeed) noexcept | |||
| { | |||
| seed = newSeed; | |||
| } | |||
| void Random::combineSeed (const int64 seedValue) noexcept | |||
| { | |||
| seed ^= nextInt64() ^ seedValue; | |||
| } | |||
| void Random::setSeedRandomly() | |||
| { | |||
| static int64 globalSeed = 0; | |||
| combineSeed (globalSeed ^ (int64) (pointer_sized_int) this); | |||
| #if 0 | |||
| combineSeed (Time::getMillisecondCounter()); | |||
| combineSeed (Time::getHighResolutionTicks()); | |||
| combineSeed (Time::getHighResolutionTicksPerSecond()); | |||
| #endif | |||
| combineSeed (Time::currentTimeMillis()); | |||
| globalSeed ^= seed; | |||
| } | |||
| Random& Random::getSystemRandom() noexcept | |||
| { | |||
| static Random sysRand; | |||
| return sysRand; | |||
| } | |||
| //============================================================================== | |||
| int Random::nextInt() noexcept | |||
| { | |||
| seed = (seed * 0x5deece66dLL + 11) & 0xffffffffffffLL; | |||
| return (int) (seed >> 16); | |||
| } | |||
| int Random::nextInt (const int maxValue) noexcept | |||
| { | |||
| jassert (maxValue > 0); | |||
| return (int) ((((unsigned int) nextInt()) * (uint64) maxValue) >> 32); | |||
| } | |||
| #if 0 | |||
| int Random::nextInt (Range<int> range) noexcept | |||
| { | |||
| return range.getStart() + nextInt (range.getLength()); | |||
| } | |||
| #endif | |||
| int64 Random::nextInt64() noexcept | |||
| { | |||
| return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt(); | |||
| } | |||
| bool Random::nextBool() noexcept | |||
| { | |||
| return (nextInt() & 0x40000000) != 0; | |||
| } | |||
| float Random::nextFloat() noexcept | |||
| { | |||
| return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0f); | |||
| } | |||
| double Random::nextDouble() noexcept | |||
| { | |||
| return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0); | |||
| } | |||
| #if 0 | |||
| BigInteger Random::nextLargeNumber (const BigInteger& maximumValue) | |||
| { | |||
| BigInteger n; | |||
| do | |||
| { | |||
| fillBitsRandomly (n, 0, maximumValue.getHighestBit() + 1); | |||
| } | |||
| while (n >= maximumValue); | |||
| return n; | |||
| } | |||
| void Random::fillBitsRandomly (void* const buffer, size_t bytes) | |||
| { | |||
| int* d = static_cast<int*> (buffer); | |||
| for (; bytes >= sizeof (int); bytes -= sizeof (int)) | |||
| *d++ = nextInt(); | |||
| if (bytes > 0) | |||
| { | |||
| const int lastBytes = nextInt(); | |||
| memcpy (d, &lastBytes, bytes); | |||
| } | |||
| } | |||
| void Random::fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits) | |||
| { | |||
| arrayToChange.setBit (startBit + numBits - 1, true); // to force the array to pre-allocate space | |||
| while ((startBit & 31) != 0 && numBits > 0) | |||
| { | |||
| arrayToChange.setBit (startBit++, nextBool()); | |||
| --numBits; | |||
| } | |||
| while (numBits >= 32) | |||
| { | |||
| arrayToChange.setBitRangeAsInt (startBit, 32, (unsigned int) nextInt()); | |||
| startBit += 32; | |||
| numBits -= 32; | |||
| } | |||
| while (--numBits >= 0) | |||
| arrayToChange.setBit (startBit + numBits, nextBool()); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,149 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_RANDOM_H_INCLUDED | |||
| #define JUCE_RANDOM_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| A random number generator. | |||
| You can create a Random object and use it to generate a sequence of random numbers. | |||
| */ | |||
| class JUCE_API Random | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a Random object based on a seed value. | |||
| For a given seed value, the subsequent numbers generated by this object | |||
| will be predictable, so a good idea is to set this value based | |||
| on the time, e.g. | |||
| new Random (Time::currentTimeMillis()) | |||
| */ | |||
| explicit Random (int64 seedValue) noexcept; | |||
| /** Creates a Random object using a random seed value. | |||
| Internally, this calls setSeedRandomly() to randomise the seed. | |||
| */ | |||
| Random(); | |||
| /** Destructor. */ | |||
| ~Random() noexcept; | |||
| /** Returns the next random 32 bit integer. | |||
| @returns a random integer from the full range 0x80000000 to 0x7fffffff | |||
| */ | |||
| int nextInt() noexcept; | |||
| /** Returns the next random number, limited to a given range. | |||
| The maxValue parameter may not be negative, or zero. | |||
| @returns a random integer between 0 (inclusive) and maxValue (exclusive). | |||
| */ | |||
| int nextInt (int maxValue) noexcept; | |||
| #if 0 | |||
| /** Returns the next random number, limited to a given range. | |||
| @returns a random integer between the range start (inclusive) and its end (exclusive). | |||
| */ | |||
| int nextInt (Range<int> range) noexcept; | |||
| #endif | |||
| /** Returns the next 64-bit random number. | |||
| @returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff | |||
| */ | |||
| int64 nextInt64() noexcept; | |||
| /** Returns the next random floating-point number. | |||
| @returns a random value in the range 0 (inclusive) to 1.0 (exclusive) | |||
| */ | |||
| float nextFloat() noexcept; | |||
| /** Returns the next random floating-point number. | |||
| @returns a random value in the range 0 (inclusive) to 1.0 (exclusive) | |||
| */ | |||
| double nextDouble() noexcept; | |||
| /** Returns the next random boolean value. */ | |||
| bool nextBool() noexcept; | |||
| #if 0 | |||
| /** Returns a BigInteger containing a random number. | |||
| @returns a random value in the range 0 to (maximumValue - 1). | |||
| */ | |||
| BigInteger nextLargeNumber (const BigInteger& maximumValue); | |||
| /** Fills a block of memory with random values. */ | |||
| void fillBitsRandomly (void* bufferToFill, size_t sizeInBytes); | |||
| /** Sets a range of bits in a BigInteger to random values. */ | |||
| void fillBitsRandomly (BigInteger& arrayToChange, int startBit, int numBits); | |||
| #endif | |||
| //============================================================================== | |||
| /** Resets this Random object to a given seed value. */ | |||
| void setSeed (int64 newSeed) noexcept; | |||
| /** Returns the RNG's current seed. */ | |||
| int64 getSeed() const noexcept { return seed; } | |||
| /** Merges this object's seed with another value. | |||
| This sets the seed to be a value created by combining the current seed and this | |||
| new value. | |||
| */ | |||
| void combineSeed (int64 seedValue) noexcept; | |||
| /** Reseeds this generator using a value generated from various semi-random system | |||
| properties like the current time, etc. | |||
| Because this function convolves the time with the last seed value, calling | |||
| it repeatedly will increase the randomness of the final result. | |||
| */ | |||
| void setSeedRandomly(); | |||
| /** The overhead of creating a new Random object is fairly small, but if you want to avoid | |||
| it, you can call this method to get a global shared Random object. | |||
| It's not thread-safe though, so threads should use their own Random object, otherwise | |||
| you run the risk of your random numbers becoming.. erm.. randomly corrupted.. | |||
| */ | |||
| static Random& getSystemRandom() noexcept; | |||
| private: | |||
| //============================================================================== | |||
| int64 seed; | |||
| JUCE_LEAK_DETECTOR (Random) | |||
| }; | |||
| #endif // JUCE_RANDOM_H_INCLUDED | |||
| @@ -110,7 +110,7 @@ inline void writeUnaligned (void* dstPtr, Type value) noexcept | |||
| #if (JUCE_COMPILER_SUPPORTS_ARC && defined (__OBJC__)) || DOXYGEN | |||
| #define JUCE_AUTORELEASEPOOL @autoreleasepool | |||
| #else | |||
| #define JUCE_AUTORELEASEPOOL const juce::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__); | |||
| #define JUCE_AUTORELEASEPOOL const juce2::ScopedAutoReleasePool JUCE_JOIN_MACRO (autoReleasePool_, __LINE__); | |||
| #endif | |||
| #else | |||
| @@ -0,0 +1,168 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED | |||
| #define JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| A smart-pointer that automatically creates and manages the lifetime of a | |||
| shared static instance of a class. | |||
| The SharedObjectType template type indicates the class to use for the shared | |||
| object - the only requirements on this class are that it must have a public | |||
| default constructor and destructor. | |||
| The SharedResourcePointer offers a pattern that differs from using a singleton or | |||
| static instance of an object, because it uses reference-counting to make sure that | |||
| the underlying shared object is automatically created/destroyed according to the | |||
| number of SharedResourcePointer objects that exist. When the last one is deleted, | |||
| the underlying object is also immediately destroyed. This allows you to use scoping | |||
| to manage the lifetime of a shared resource. | |||
| Note: the construction/deletion of the shared object must not involve any | |||
| code that makes recursive calls to a SharedResourcePointer, or you'll cause | |||
| a deadlock. | |||
| Example: | |||
| @code | |||
| // An example of a class that contains the shared data you want to use. | |||
| struct MySharedData | |||
| { | |||
| // There's no need to ever create an instance of this class directly yourself, | |||
| // but it does need a public constructor that does the initialisation. | |||
| MySharedData() | |||
| { | |||
| sharedStuff = generateHeavyweightStuff(); | |||
| } | |||
| Array<SomeKindOfData> sharedStuff; | |||
| }; | |||
| struct DataUserClass | |||
| { | |||
| DataUserClass() | |||
| { | |||
| // Multiple instances of the DataUserClass will all have the same | |||
| // shared common instance of MySharedData referenced by their sharedData | |||
| // member variables. | |||
| useSharedStuff (sharedData->sharedStuff); | |||
| } | |||
| // By keeping this pointer as a member variable, the shared resource | |||
| // is guaranteed to be available for as long as the DataUserClass object. | |||
| SharedResourcePointer<MySharedData> sharedData; | |||
| }; | |||
| @endcode | |||
| */ | |||
| template <typename SharedObjectType> | |||
| class SharedResourcePointer | |||
| { | |||
| public: | |||
| /** Creates an instance of the shared object. | |||
| If other SharedResourcePointer objects for this type already exist, then | |||
| this one will simply point to the same shared object that they are already | |||
| using. Otherwise, if this is the first SharedResourcePointer to be created, | |||
| then a shared object will be created automatically. | |||
| */ | |||
| SharedResourcePointer() | |||
| { | |||
| initialise(); | |||
| } | |||
| SharedResourcePointer (const SharedResourcePointer&) | |||
| { | |||
| initialise(); | |||
| } | |||
| /** Destructor. | |||
| If no other SharedResourcePointer objects exist, this will also delete | |||
| the shared object to which it refers. | |||
| */ | |||
| ~SharedResourcePointer() | |||
| { | |||
| SharedObjectHolder& holder = getSharedObjectHolder(); | |||
| const SpinLock::ScopedLockType sl (holder.lock); | |||
| if (--(holder.refCount) == 0) | |||
| holder.sharedInstance = nullptr; | |||
| } | |||
| /** Returns the shared object. */ | |||
| operator SharedObjectType*() const noexcept { return sharedObject; } | |||
| /** Returns the shared object. */ | |||
| SharedObjectType& get() const noexcept { return *sharedObject; } | |||
| /** Returns the object that this pointer references. | |||
| The pointer returned may be a nullptr, of course. | |||
| */ | |||
| SharedObjectType& getObject() const noexcept { return *sharedObject; } | |||
| SharedObjectType* operator->() const noexcept { return sharedObject; } | |||
| private: | |||
| struct SharedObjectHolder : public ReferenceCountedObject | |||
| { | |||
| SpinLock lock; | |||
| ScopedPointer<SharedObjectType> sharedInstance; | |||
| int refCount; | |||
| }; | |||
| static SharedObjectHolder& getSharedObjectHolder() noexcept | |||
| { | |||
| static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { 0 }; | |||
| return *reinterpret_cast<SharedObjectHolder*> (holder); | |||
| } | |||
| SharedObjectType* sharedObject; | |||
| void initialise() | |||
| { | |||
| SharedObjectHolder& holder = getSharedObjectHolder(); | |||
| const SpinLock::ScopedLockType sl (holder.lock); | |||
| if (++(holder.refCount) == 1) | |||
| holder.sharedInstance = new SharedObjectType(); | |||
| sharedObject = holder.sharedInstance; | |||
| } | |||
| // There's no need to assign to a SharedResourcePointer because every | |||
| // instance of the class is exactly the same! | |||
| SharedResourcePointer& operator= (const SharedResourcePointer&) JUCE_DELETED_FUNCTION; | |||
| JUCE_LEAK_DETECTOR (SharedResourcePointer) | |||
| }; | |||
| #endif // JUCE_SHAREDRESOURCEPOINTER_H_INCLUDED | |||
| @@ -47,6 +47,7 @@ InputStream* FileInputSource::createInputStreamFor (const String& relatedItemPat | |||
| return file.getSiblingFile (relatedItemPath).createInputStream(); | |||
| } | |||
| #if 0 | |||
| int64 FileInputSource::hashCode() const | |||
| { | |||
| int64 h = file.hashCode(); | |||
| @@ -56,3 +57,4 @@ int64 FileInputSource::hashCode() const | |||
| return h; | |||
| } | |||
| #endif | |||
| @@ -84,3 +84,69 @@ bool FileInputStream::setPosition (int64 pos) | |||
| return currentPosition == pos; | |||
| } | |||
| #ifdef CARLA_OS_WIN | |||
| FileInputStream::~FileInputStream() | |||
| { | |||
| CloseHandle ((HANDLE) fileHandle); | |||
| } | |||
| void FileInputStream::openHandle() | |||
| { | |||
| HANDLE h = CreateFile (file.getFullPathName().toUTF8(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, | |||
| OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, 0); | |||
| if (h != INVALID_HANDLE_VALUE) | |||
| fileHandle = (void*) h; | |||
| else | |||
| status = getResultForLastError(); | |||
| } | |||
| size_t FileInputStream::readInternal (void* buffer, size_t numBytes) | |||
| { | |||
| if (fileHandle != 0) | |||
| { | |||
| DWORD actualNum = 0; | |||
| if (! ReadFile ((HANDLE) fileHandle, buffer, (DWORD) numBytes, &actualNum, 0)) | |||
| status = getResultForLastError(); | |||
| return (size_t) actualNum; | |||
| } | |||
| return 0; | |||
| } | |||
| #else | |||
| FileInputStream::~FileInputStream() | |||
| { | |||
| if (fileHandle != 0) | |||
| close (getFD (fileHandle)); | |||
| } | |||
| void FileInputStream::openHandle() | |||
| { | |||
| const int f = open (file.getFullPathName().toUTF8(), O_RDONLY, 00644); | |||
| if (f != -1) | |||
| fileHandle = fdToVoidPointer (f); | |||
| else | |||
| status = getResultForErrno(); | |||
| } | |||
| size_t FileInputStream::readInternal (void* const buffer, const size_t numBytes) | |||
| { | |||
| ssize_t result = 0; | |||
| if (fileHandle != 0) | |||
| { | |||
| result = ::read (getFD (fileHandle), buffer, numBytes); | |||
| if (result < 0) | |||
| { | |||
| status = getResultForErrno(); | |||
| result = 0; | |||
| } | |||
| } | |||
| return (size_t) result; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,255 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| int64 juce_fileSetPosition (void* handle, int64 pos); | |||
| //============================================================================== | |||
| FileOutputStream::FileOutputStream (const File& f, const size_t bufferSizeToUse) | |||
| : file (f), | |||
| fileHandle (nullptr), | |||
| status (Result::ok()), | |||
| currentPosition (0), | |||
| bufferSize (bufferSizeToUse), | |||
| bytesInBuffer (0), | |||
| buffer (jmax (bufferSizeToUse, (size_t) 16)) | |||
| { | |||
| openHandle(); | |||
| } | |||
| FileOutputStream::~FileOutputStream() | |||
| { | |||
| flushBuffer(); | |||
| closeHandle(); | |||
| } | |||
| int64 FileOutputStream::getPosition() | |||
| { | |||
| return currentPosition; | |||
| } | |||
| bool FileOutputStream::setPosition (int64 newPosition) | |||
| { | |||
| if (newPosition != currentPosition) | |||
| { | |||
| flushBuffer(); | |||
| currentPosition = juce_fileSetPosition (fileHandle, newPosition); | |||
| } | |||
| return newPosition == currentPosition; | |||
| } | |||
| bool FileOutputStream::flushBuffer() | |||
| { | |||
| bool ok = true; | |||
| if (bytesInBuffer > 0) | |||
| { | |||
| ok = (writeInternal (buffer, bytesInBuffer) == (ssize_t) bytesInBuffer); | |||
| bytesInBuffer = 0; | |||
| } | |||
| return ok; | |||
| } | |||
| void FileOutputStream::flush() | |||
| { | |||
| flushBuffer(); | |||
| flushInternal(); | |||
| } | |||
| bool FileOutputStream::write (const void* const src, const size_t numBytes) | |||
| { | |||
| jassert (src != nullptr && ((ssize_t) numBytes) >= 0); | |||
| if (bytesInBuffer + numBytes < bufferSize) | |||
| { | |||
| memcpy (buffer + bytesInBuffer, src, numBytes); | |||
| bytesInBuffer += numBytes; | |||
| currentPosition += (int64) numBytes; | |||
| } | |||
| else | |||
| { | |||
| if (! flushBuffer()) | |||
| return false; | |||
| if (numBytes < bufferSize) | |||
| { | |||
| memcpy (buffer + bytesInBuffer, src, numBytes); | |||
| bytesInBuffer += numBytes; | |||
| currentPosition += (int64) numBytes; | |||
| } | |||
| else | |||
| { | |||
| const ssize_t bytesWritten = writeInternal (src, numBytes); | |||
| if (bytesWritten < 0) | |||
| return false; | |||
| currentPosition += (int64) bytesWritten; | |||
| return bytesWritten == (ssize_t) numBytes; | |||
| } | |||
| } | |||
| return true; | |||
| } | |||
| bool FileOutputStream::writeRepeatedByte (uint8 byte, size_t numBytes) | |||
| { | |||
| jassert (((ssize_t) numBytes) >= 0); | |||
| if (bytesInBuffer + numBytes < bufferSize) | |||
| { | |||
| memset (buffer + bytesInBuffer, byte, numBytes); | |||
| bytesInBuffer += numBytes; | |||
| currentPosition += (int64) numBytes; | |||
| return true; | |||
| } | |||
| return OutputStream::writeRepeatedByte (byte, numBytes); | |||
| } | |||
| #ifdef CARLA_OS_WIN | |||
| void FileOutputStream::openHandle() | |||
| { | |||
| HANDLE h = CreateFile (file.getFullPathName().toUTF8(), GENERIC_WRITE, FILE_SHARE_READ, 0, | |||
| OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0); | |||
| if (h != INVALID_HANDLE_VALUE) | |||
| { | |||
| LARGE_INTEGER li; | |||
| li.QuadPart = 0; | |||
| li.LowPart = SetFilePointer (h, 0, &li.HighPart, FILE_END); | |||
| if (li.LowPart != INVALID_SET_FILE_POINTER) | |||
| { | |||
| fileHandle = (void*) h; | |||
| currentPosition = li.QuadPart; | |||
| return; | |||
| } | |||
| } | |||
| status = getResultForLastError(); | |||
| } | |||
| void FileOutputStream::closeHandle() | |||
| { | |||
| CloseHandle ((HANDLE) fileHandle); | |||
| } | |||
| ssize_t FileOutputStream::writeInternal (const void* bufferToWrite, size_t numBytes) | |||
| { | |||
| if (fileHandle != nullptr) | |||
| { | |||
| DWORD actualNum = 0; | |||
| if (! WriteFile ((HANDLE) fileHandle, bufferToWrite, (DWORD) numBytes, &actualNum, 0)) | |||
| status = getResultForLastError(); | |||
| return (ssize_t) actualNum; | |||
| } | |||
| return 0; | |||
| } | |||
| void FileOutputStream::flushInternal() | |||
| { | |||
| if (fileHandle != nullptr) | |||
| if (! FlushFileBuffers ((HANDLE) fileHandle)) | |||
| status = getResultForLastError(); | |||
| } | |||
| #else | |||
| void FileOutputStream::openHandle() | |||
| { | |||
| if (file.exists()) | |||
| { | |||
| const int f = open (file.getFullPathName().toUTF8(), O_RDWR, 00644); | |||
| if (f != -1) | |||
| { | |||
| currentPosition = lseek (f, 0, SEEK_END); | |||
| if (currentPosition >= 0) | |||
| { | |||
| fileHandle = fdToVoidPointer (f); | |||
| } | |||
| else | |||
| { | |||
| status = getResultForErrno(); | |||
| close (f); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| status = getResultForErrno(); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| const int f = open (file.getFullPathName().toUTF8(), O_RDWR + O_CREAT, 00644); | |||
| if (f != -1) | |||
| fileHandle = fdToVoidPointer (f); | |||
| else | |||
| status = getResultForErrno(); | |||
| } | |||
| } | |||
| void FileOutputStream::closeHandle() | |||
| { | |||
| if (fileHandle != 0) | |||
| { | |||
| close (getFD (fileHandle)); | |||
| fileHandle = 0; | |||
| } | |||
| } | |||
| ssize_t FileOutputStream::writeInternal (const void* const data, const size_t numBytes) | |||
| { | |||
| ssize_t result = 0; | |||
| if (fileHandle != 0) | |||
| { | |||
| result = ::write (getFD (fileHandle), data, numBytes); | |||
| if (result == -1) | |||
| status = getResultForErrno(); | |||
| } | |||
| return result; | |||
| } | |||
| void FileOutputStream::flushInternal() | |||
| { | |||
| if (fileHandle != 0) | |||
| { | |||
| if (fsync (getFD (fileHandle)) == -1) | |||
| status = getResultForErrno(); | |||
| } | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,122 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_FILEOUTPUTSTREAM_H_INCLUDED | |||
| #define JUCE_FILEOUTPUTSTREAM_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| An output stream that writes into a local file. | |||
| @see OutputStream, FileInputStream, File::createOutputStream | |||
| */ | |||
| class JUCE_API FileOutputStream : public OutputStream | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a FileOutputStream. | |||
| If the file doesn't exist, it will first be created. If the file can't be | |||
| created or opened (for example, because the parent directory of the file | |||
| does not exist), the failedToOpen() method will return true. | |||
| If the file already exists when opened, the stream's write-position will | |||
| be set to the end of the file. To overwrite an existing file, | |||
| use File::deleteFile() before opening the stream, or use setPosition(0) | |||
| after it's opened (although this won't truncate the file). | |||
| Destroying a FileOutputStream object does not force the operating system | |||
| to write the buffered data to disk immediately. If this is required you | |||
| should call flush() before triggering the destructor. | |||
| @see TemporaryFile | |||
| */ | |||
| FileOutputStream (const File& fileToWriteTo, | |||
| size_t bufferSizeToUse = 16384); | |||
| /** Destructor. */ | |||
| ~FileOutputStream(); | |||
| //============================================================================== | |||
| /** Returns the file that this stream is writing to. | |||
| */ | |||
| const File& getFile() const { return file; } | |||
| /** Returns the status of the file stream. | |||
| The result will be ok if the file opened successfully. If an error occurs while | |||
| opening or writing to the file, this will contain an error message. | |||
| */ | |||
| const Result& getStatus() const noexcept { return status; } | |||
| /** Returns true if the stream couldn't be opened for some reason. | |||
| @see getResult() | |||
| */ | |||
| bool failedToOpen() const noexcept { return status.failed(); } | |||
| /** Returns true if the stream opened without problems. | |||
| @see getResult() | |||
| */ | |||
| bool openedOk() const noexcept { return status.wasOk(); } | |||
| /** Attempts to truncate the file to the current write position. | |||
| To truncate a file to a specific size, first use setPosition() to seek to the | |||
| appropriate location, and then call this method. | |||
| */ | |||
| Result truncate(); | |||
| //============================================================================== | |||
| void flush() override; | |||
| int64 getPosition() override; | |||
| bool setPosition (int64) override; | |||
| bool write (const void*, size_t) override; | |||
| bool writeRepeatedByte (uint8 byte, size_t numTimesToRepeat) override; | |||
| private: | |||
| //============================================================================== | |||
| File file; | |||
| void* fileHandle; | |||
| Result status; | |||
| int64 currentPosition; | |||
| size_t bufferSize, bytesInBuffer; | |||
| HeapBlock<char> buffer; | |||
| void openHandle(); | |||
| void closeHandle(); | |||
| void flushInternal(); | |||
| bool flushBuffer(); | |||
| int64 setPositionInternal (int64); | |||
| ssize_t writeInternal (const void*, size_t); | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FileOutputStream) | |||
| }; | |||
| #endif // JUCE_FILEOUTPUTSTREAM_H_INCLUDED | |||
| @@ -66,10 +66,11 @@ public: | |||
| */ | |||
| virtual InputStream* createInputStreamFor (const String& relatedItemPath) = 0; | |||
| #if 0 | |||
| /** Returns a hash code that uniquely represents this item. | |||
| */ | |||
| virtual int64 hashCode() const = 0; | |||
| #endif | |||
| private: | |||
| //============================================================================== | |||
| @@ -176,16 +176,7 @@ bool OutputStream::writeDoubleBigEndian (double value) | |||
| bool OutputStream::writeString (const String& text) | |||
| { | |||
| #if (JUCE_STRING_UTF_TYPE == 8) | |||
| return write (text.toRawUTF8(), text.getNumBytesAsUTF8() + 1); | |||
| #else | |||
| // (This avoids using toUTF8() to prevent the memory bloat that it would leave behind | |||
| // if lots of large, persistent strings were to be written to streams). | |||
| const size_t numBytes = text.getNumBytesAsUTF8() + 1; | |||
| HeapBlock<char> temp (numBytes); | |||
| text.copyToUTF8 (temp, numBytes); | |||
| return write (temp, numBytes); | |||
| #endif | |||
| } | |||
| bool OutputStream::writeText (const String& text, const bool asUTF16, | |||
| @@ -476,11 +476,8 @@ public: | |||
| /** Parses this string as a 64-bit integer. */ | |||
| int64 getIntValue64() const noexcept | |||
| { | |||
| #if JUCE_LINUX || JUCE_ANDROID || JUCE_MINGW | |||
| return atoll (data); | |||
| #elif JUCE_WINDOWS | |||
| return _atoi64 (data); | |||
| #else | |||
| #if 0 | |||
| return CharacterFunctions::getIntValue <int64, CharPointer_UTF8> (*this); | |||
| #endif | |||
| } | |||
| @@ -42,7 +42,7 @@ juce_wchar CharacterFunctions::toLowerCase (const juce_wchar character) noexcept | |||
| bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept | |||
| { | |||
| #if JUCE_WINDOWS | |||
| #ifdef CARLA_OS_WIN | |||
| return iswupper ((wint_t) character) != 0; | |||
| #else | |||
| return toLowerCase (character) != character; | |||
| @@ -51,7 +51,7 @@ bool CharacterFunctions::isUpperCase (const juce_wchar character) noexcept | |||
| bool CharacterFunctions::isLowerCase (const juce_wchar character) noexcept | |||
| { | |||
| #if JUCE_WINDOWS | |||
| #ifdef CARLA_OS_WIN | |||
| return iswlower ((wint_t) character) != 0; | |||
| #else | |||
| return toUpperCase (character) != character; | |||
| @@ -729,6 +729,11 @@ String& String::operator+= (const char ch) | |||
| return operator+= (asString); | |||
| } | |||
| String& String::operator+= (const juce_wchar ch) | |||
| { | |||
| return operator+= (charToString(ch)); | |||
| } | |||
| namespace StringHelpers | |||
| { | |||
| template <typename T> | |||
| @@ -754,6 +759,10 @@ JUCE_API String JUCE_CALLTYPE operator+ (String s1, const String& s2) | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String s1, const char* const s2) { return s1 += s2; } | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String s1, const char s2) { return s1 += s2; } | |||
| JUCE_API String JUCE_CALLTYPE operator+ (const juce_wchar s1, const String& s2) { return String::charToString (s1) + s2; } | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String s1, const juce_wchar s2) { return s1 += s2; } | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const juce_wchar s2) { return s1 += s2; } | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const char s2) { return s1 += s2; } | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const char* const s2) { return s1 += s2; } | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& s1, const String& s2) { return s1 += s2; } | |||
| @@ -1723,6 +1732,43 @@ bool String::containsNonWhitespaceChars() const noexcept | |||
| return false; | |||
| } | |||
| //===================================================================================================================== | |||
| static String getStringFromWindows1252Codepage (const char* data, size_t num) | |||
| { | |||
| HeapBlock<char> unicode (num + 1); | |||
| for (size_t i = 0; i < num; ++i) | |||
| unicode[i] = CharacterFunctions::getUnicodeCharFromWindows1252Codepage ((uint8) data[i]); | |||
| unicode[num] = 0; | |||
| return CharPointer_UTF8 (unicode); | |||
| } | |||
| String String::createStringFromData (const void* const unknownData, int size) | |||
| { | |||
| const uint8* const data = static_cast<const uint8*> (unknownData); | |||
| if (size <= 0 || data == nullptr) | |||
| return String(); | |||
| if (size == 1) | |||
| return charToString ((juce_wchar) data[0]); | |||
| const char* start = (const char*) data; | |||
| if (size >= 3 && CharPointer_UTF8::isByteOrderMark (data)) | |||
| { | |||
| start += 3; | |||
| size -= 3; | |||
| } | |||
| if (CharPointer_UTF8::isValidString (start, size)) | |||
| return String (CharPointer_UTF8 (start), | |||
| CharPointer_UTF8 (start + size)); | |||
| return getStringFromWindows1252Codepage (start, (size_t) size); | |||
| } | |||
| // Note! The format parameter here MUST NOT be a reference, otherwise MS's va_start macro fails to work (but still compiles). | |||
| String String::formatted (const String pf, ... ) | |||
| { | |||
| @@ -115,18 +115,7 @@ public: | |||
| /** Destructor. */ | |||
| ~String() noexcept; | |||
| /** This is the character encoding type used internally to store the string. | |||
| By setting the value of JUCE_STRING_UTF_TYPE to 8, 16, or 32, you can change the | |||
| internal storage format of the String class. UTF-8 uses the least space (if your strings | |||
| contain few extended characters), but call operator[] involves iterating the string to find | |||
| the required index. UTF-32 provides instant random access to its characters, but uses 4 bytes | |||
| per character to store them. UTF-16 uses more space than UTF-8 and is also slow to index, | |||
| but is the native wchar_t format used in Windows. | |||
| It doesn't matter too much which format you pick, because the toUTF8(), toUTF16() and | |||
| toUTF32() methods let you access the string's content in any of the other formats. | |||
| */ | |||
| /** This is the character encoding type used internally to store the string. */ | |||
| typedef CharPointer_UTF8 CharPointerType; | |||
| //============================================================================== | |||
| @@ -168,6 +157,8 @@ public: | |||
| String& operator+= (uint64 numberToAppend); | |||
| /** Appends a character at the end of this string. */ | |||
| String& operator+= (char characterToAppend); | |||
| /** Appends a character at the end of this string. */ | |||
| String& operator+= (juce_wchar characterToAppend); | |||
| /** Appends a string to the end of this one. | |||
| @@ -807,6 +798,16 @@ public: | |||
| */ | |||
| String paddedRight (juce_wchar padCharacter, int minimumLength) const; | |||
| /** Creates a string from data in an unknown format. | |||
| This looks at some binary data and tries to guess whether it's Unicode | |||
| or 8-bit characters, then returns a string that represents it correctly. | |||
| Should be able to handle Unicode endianness correctly, by looking at | |||
| the first two bytes. | |||
| */ | |||
| static String createStringFromData (const void* data, int size); | |||
| /** Creates a String from a printf-style parameter list. | |||
| I don't like this method. I don't use it myself, and I recommend avoiding it and | |||
| @@ -1103,6 +1104,8 @@ private: | |||
| JUCE_API String JUCE_CALLTYPE operator+ (const char* string1, const String& string2); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API String JUCE_CALLTYPE operator+ (char string1, const String& string2); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API String JUCE_CALLTYPE operator+ (juce_wchar string1, const String& string2); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String string1, const String& string2); | |||
| @@ -1110,10 +1113,14 @@ JUCE_API String JUCE_CALLTYPE operator+ (String string1, const String& string2); | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String string1, const char* string2); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String string1, char characterToAppend); | |||
| /** Concatenates two strings. */ | |||
| JUCE_API String JUCE_CALLTYPE operator+ (String string1, juce_wchar characterToAppend); | |||
| //============================================================================== | |||
| /** Appends a character at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, char characterToAppend); | |||
| /** Appends a character at the end of a string. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, juce_wchar characterToAppend); | |||
| /** Appends a string to the end of the first one. */ | |||
| JUCE_API String& JUCE_CALLTYPE operator<< (String& string1, const char* string2); | |||
| @@ -64,16 +64,6 @@ StringArray::StringArray (const char* const* initialStrings, int numberOfStrings | |||
| strings.addArray (initialStrings, numberOfStrings); | |||
| } | |||
| StringArray::StringArray (const wchar_t* const* initialStrings) | |||
| { | |||
| strings.addNullTerminatedArray (initialStrings); | |||
| } | |||
| StringArray::StringArray (const wchar_t* const* initialStrings, int numberOfStrings) | |||
| { | |||
| strings.addArray (initialStrings, numberOfStrings); | |||
| } | |||
| StringArray& StringArray::operator= (const StringArray& other) | |||
| { | |||
| strings = other.strings; | |||
| @@ -75,19 +75,6 @@ public: | |||
| */ | |||
| explicit StringArray (const char* const* strings); | |||
| /** Creates a copy of a null-terminated array of string literals. | |||
| Each item from the array passed-in is added, until it encounters a null pointer, | |||
| at which point it stops. | |||
| */ | |||
| explicit StringArray (const wchar_t* const* strings); | |||
| /** Creates a copy of an array of string literals. | |||
| @param strings an array of strings to add. Null pointers in the array will be | |||
| treated as empty strings | |||
| @param numberOfStrings how many items there are in the array | |||
| */ | |||
| StringArray (const wchar_t* const* strings, int numberOfStrings); | |||
| #if JUCE_COMPILER_SUPPORTS_INITIALIZER_LISTS | |||
| StringArray (const std::initializer_list<const char*>& strings); | |||
| #endif | |||
| @@ -108,7 +108,7 @@ String StringPool::getPooledString (const char* const newString) | |||
| if (newString == nullptr || *newString == 0) | |||
| return String(); | |||
| const ScopedLock sl (lock); | |||
| const CarlaRecursiveMutexLocker sl (lock); | |||
| garbageCollectIfNeeded(); | |||
| return addPooledString (strings, CharPointer_UTF8 (newString)); | |||
| } | |||
| @@ -118,7 +118,7 @@ String StringPool::getPooledString (String::CharPointerType start, String::CharP | |||
| if (start.isEmpty() || start == end) | |||
| return String(); | |||
| const ScopedLock sl (lock); | |||
| const CarlaRecursiveMutexLocker sl (lock); | |||
| garbageCollectIfNeeded(); | |||
| return addPooledString (strings, StartEndString (start, end)); | |||
| } | |||
| @@ -128,7 +128,7 @@ String StringPool::getPooledString (StringRef newString) | |||
| if (newString.isEmpty()) | |||
| return String(); | |||
| const ScopedLock sl (lock); | |||
| const CarlaRecursiveMutexLocker sl (lock); | |||
| garbageCollectIfNeeded(); | |||
| return addPooledString (strings, newString.text); | |||
| } | |||
| @@ -138,7 +138,7 @@ String StringPool::getPooledString (const String& newString) | |||
| if (newString.isEmpty()) | |||
| return String(); | |||
| const ScopedLock sl (lock); | |||
| const CarlaRecursiveMutexLocker sl (lock); | |||
| garbageCollectIfNeeded(); | |||
| return addPooledString (strings, newString); | |||
| } | |||
| @@ -152,7 +152,7 @@ void StringPool::garbageCollectIfNeeded() | |||
| void StringPool::garbageCollect() | |||
| { | |||
| const ScopedLock sl (lock); | |||
| const CarlaRecursiveMutexLocker sl (lock); | |||
| for (int i = strings.size(); --i >= 0;) | |||
| if (strings.getReference(i).getReferenceCount() == 1) | |||
| @@ -0,0 +1,399 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #define JUCE_USE_VFORK 1 | |||
| #ifdef CARLA_OS_WIN | |||
| //===================================================================================================================== | |||
| class ChildProcess::ActiveProcess | |||
| { | |||
| public: | |||
| ActiveProcess (const String& command, int streamFlags) | |||
| : ok (false), readPipe (0), writePipe (0) | |||
| { | |||
| SECURITY_ATTRIBUTES securityAtts; | |||
| carla_zeroStruct(securityAtts); | |||
| securityAtts.nLength = sizeof (securityAtts); | |||
| securityAtts.bInheritHandle = TRUE; | |||
| if (CreatePipe (&readPipe, &writePipe, &securityAtts, 0) | |||
| && SetHandleInformation (readPipe, HANDLE_FLAG_INHERIT, 0)) | |||
| { | |||
| STARTUPINFO startupInfo; | |||
| carla_zeroStruct(startupInfo); | |||
| startupInfo.cb = sizeof (startupInfo); | |||
| startupInfo.hStdOutput = (streamFlags & wantStdOut) != 0 ? writePipe : 0; | |||
| startupInfo.hStdError = (streamFlags & wantStdErr) != 0 ? writePipe : 0; | |||
| startupInfo.dwFlags = STARTF_USESTDHANDLES; | |||
| ok = CreateProcess (nullptr, const_cast<LPSTR>(command.toRawUTF8()), | |||
| nullptr, nullptr, TRUE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, | |||
| nullptr, nullptr, &startupInfo, &processInfo) != FALSE; | |||
| } | |||
| } | |||
| ~ActiveProcess() | |||
| { | |||
| if (ok) | |||
| { | |||
| CloseHandle (processInfo.hThread); | |||
| CloseHandle (processInfo.hProcess); | |||
| } | |||
| if (readPipe != 0) | |||
| CloseHandle (readPipe); | |||
| if (writePipe != 0) | |||
| CloseHandle (writePipe); | |||
| } | |||
| bool isRunning() const noexcept | |||
| { | |||
| return WaitForSingleObject (processInfo.hProcess, 0) != WAIT_OBJECT_0; | |||
| } | |||
| int read (void* dest, int numNeeded) const noexcept | |||
| { | |||
| int total = 0; | |||
| while (ok && numNeeded > 0) | |||
| { | |||
| DWORD available = 0; | |||
| if (! PeekNamedPipe ((HANDLE) readPipe, nullptr, 0, nullptr, &available, nullptr)) | |||
| break; | |||
| const int numToDo = jmin ((int) available, numNeeded); | |||
| if (available == 0) | |||
| { | |||
| if (! isRunning()) | |||
| break; | |||
| Sleep(0); | |||
| } | |||
| else | |||
| { | |||
| DWORD numRead = 0; | |||
| if (! ReadFile ((HANDLE) readPipe, dest, numToDo, &numRead, nullptr)) | |||
| break; | |||
| total += numRead; | |||
| dest = addBytesToPointer (dest, numRead); | |||
| numNeeded -= numRead; | |||
| } | |||
| } | |||
| return total; | |||
| } | |||
| bool killProcess() const noexcept | |||
| { | |||
| return TerminateProcess (processInfo.hProcess, 0) != FALSE; | |||
| } | |||
| uint32 getExitCode() const noexcept | |||
| { | |||
| DWORD exitCode = 0; | |||
| GetExitCodeProcess (processInfo.hProcess, &exitCode); | |||
| return (uint32) exitCode; | |||
| } | |||
| int getPID() const noexcept | |||
| { | |||
| return 0; | |||
| } | |||
| bool ok; | |||
| private: | |||
| HANDLE readPipe, writePipe; | |||
| PROCESS_INFORMATION processInfo; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess) | |||
| }; | |||
| #else | |||
| class ChildProcess::ActiveProcess | |||
| { | |||
| public: | |||
| ActiveProcess (const StringArray& arguments, int streamFlags) | |||
| : childPID (0), pipeHandle (0), readHandle (0) | |||
| { | |||
| String exe (arguments[0].unquoted()); | |||
| // Looks like you're trying to launch a non-existent exe or a folder (perhaps on OSX | |||
| // you're trying to launch the .app folder rather than the actual binary inside it?) | |||
| jassert (File::getCurrentWorkingDirectory().getChildFile (exe).existsAsFile() | |||
| || ! exe.containsChar (File::separator)); | |||
| int pipeHandles[2] = { 0 }; | |||
| if (pipe (pipeHandles) == 0) | |||
| { | |||
| Array<char*> argv; | |||
| for (int i = 0; i < arguments.size(); ++i) | |||
| if (arguments[i].isNotEmpty()) | |||
| argv.add (const_cast<char*> (arguments[i].toRawUTF8())); | |||
| argv.add (nullptr); | |||
| #if JUCE_USE_VFORK | |||
| const pid_t result = vfork(); | |||
| #else | |||
| const pid_t result = fork(); | |||
| #endif | |||
| if (result < 0) | |||
| { | |||
| close (pipeHandles[0]); | |||
| close (pipeHandles[1]); | |||
| } | |||
| else if (result == 0) | |||
| { | |||
| #if ! JUCE_USE_VFORK | |||
| // we're the child process.. | |||
| close (pipeHandles[0]); // close the read handle | |||
| if ((streamFlags & wantStdOut) != 0) | |||
| dup2 (pipeHandles[1], STDOUT_FILENO); // turns the pipe into stdout | |||
| else | |||
| dup2 (open ("/dev/null", O_WRONLY), STDOUT_FILENO); | |||
| if ((streamFlags & wantStdErr) != 0) | |||
| dup2 (pipeHandles[1], STDERR_FILENO); | |||
| else | |||
| dup2 (open ("/dev/null", O_WRONLY), STDERR_FILENO); | |||
| close (pipeHandles[1]); | |||
| #endif | |||
| if (execvp (exe.toRawUTF8(), argv.getRawDataPointer())) | |||
| _exit (-1); | |||
| } | |||
| else | |||
| { | |||
| // we're the parent process.. | |||
| childPID = result; | |||
| pipeHandle = pipeHandles[0]; | |||
| close (pipeHandles[1]); // close the write handle | |||
| } | |||
| // FIXME | |||
| (void)streamFlags; | |||
| } | |||
| } | |||
| ~ActiveProcess() | |||
| { | |||
| if (readHandle != 0) | |||
| fclose (readHandle); | |||
| if (pipeHandle != 0) | |||
| close (pipeHandle); | |||
| } | |||
| bool isRunning() const noexcept | |||
| { | |||
| if (childPID != 0) | |||
| { | |||
| int childState; | |||
| const int pid = waitpid (childPID, &childState, WNOHANG); | |||
| return pid == 0 || ! (WIFEXITED (childState) || WIFSIGNALED (childState)); | |||
| } | |||
| return false; | |||
| } | |||
| int read (void* const dest, const int numBytes) noexcept | |||
| { | |||
| jassert (dest != nullptr); | |||
| #ifdef fdopen | |||
| #error // the zlib headers define this function as NULL! | |||
| #endif | |||
| if (readHandle == 0 && childPID != 0) | |||
| readHandle = fdopen (pipeHandle, "r"); | |||
| if (readHandle != 0) | |||
| return (int) fread (dest, 1, (size_t) numBytes, readHandle); | |||
| return 0; | |||
| } | |||
| bool killProcess() const noexcept | |||
| { | |||
| return ::kill (childPID, SIGKILL) == 0; | |||
| } | |||
| uint32 getExitCode() const noexcept | |||
| { | |||
| if (childPID != 0) | |||
| { | |||
| int childState = 0; | |||
| const int pid = waitpid (childPID, &childState, WNOHANG); | |||
| if (pid >= 0 && WIFEXITED (childState)) | |||
| return WEXITSTATUS (childState); | |||
| } | |||
| return 0; | |||
| } | |||
| int getPID() const noexcept | |||
| { | |||
| return childPID; | |||
| } | |||
| int childPID; | |||
| private: | |||
| int pipeHandle; | |||
| FILE* readHandle; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess) | |||
| }; | |||
| #endif | |||
| //===================================================================================================================== | |||
| ChildProcess::ChildProcess() {} | |||
| ChildProcess::~ChildProcess() {} | |||
| bool ChildProcess::isRunning() const | |||
| { | |||
| return activeProcess != nullptr && activeProcess->isRunning(); | |||
| } | |||
| int ChildProcess::readProcessOutput (void* dest, int numBytes) | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->read (dest, numBytes) : 0; | |||
| } | |||
| bool ChildProcess::kill() | |||
| { | |||
| return activeProcess == nullptr || activeProcess->killProcess(); | |||
| } | |||
| uint32 ChildProcess::getExitCode() const | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->getExitCode() : 0; | |||
| } | |||
| bool ChildProcess::waitForProcessToFinish (const int timeoutMs) const | |||
| { | |||
| const uint32 timeoutTime = Time::getMillisecondCounter() + (uint32) timeoutMs; | |||
| do | |||
| { | |||
| if (! isRunning()) | |||
| return true; | |||
| } | |||
| while (timeoutMs < 0 || Time::getMillisecondCounter() < timeoutTime); | |||
| return false; | |||
| } | |||
| String ChildProcess::readAllProcessOutput() | |||
| { | |||
| MemoryOutputStream result; | |||
| for (;;) | |||
| { | |||
| char buffer [512]; | |||
| const int num = readProcessOutput (buffer, sizeof (buffer)); | |||
| if (num <= 0) | |||
| break; | |||
| result.write (buffer, (size_t) num); | |||
| } | |||
| return result.toString(); | |||
| } | |||
| uint32 ChildProcess::getPID() const noexcept | |||
| { | |||
| return activeProcess != nullptr ? activeProcess->getPID() : 0; | |||
| } | |||
| //===================================================================================================================== | |||
| #ifdef CARLA_OS_WIN | |||
| bool ChildProcess::start (const String& command, int streamFlags) | |||
| { | |||
| activeProcess = new ActiveProcess (command, streamFlags); | |||
| if (! activeProcess->ok) | |||
| activeProcess = nullptr; | |||
| return activeProcess != nullptr; | |||
| } | |||
| bool ChildProcess::start (const StringArray& args, int streamFlags) | |||
| { | |||
| String escaped; | |||
| for (int i = 0; i < args.size(); ++i) | |||
| { | |||
| String arg (args[i]); | |||
| #if 0 // FIXME | |||
| // If there are spaces, surround it with quotes. If there are quotes, | |||
| // replace them with \" so that CommandLineToArgv will correctly parse them. | |||
| if (arg.containsAnyOf ("\" ")) | |||
| arg = arg.replace ("\"", "\\\"").quoted(); | |||
| #endif | |||
| escaped << arg << ' '; | |||
| } | |||
| return start (escaped.trim(), streamFlags); | |||
| } | |||
| #else | |||
| bool ChildProcess::start (const String& command, int streamFlags) | |||
| { | |||
| return start (StringArray::fromTokens (command, true), streamFlags); | |||
| } | |||
| bool ChildProcess::start (const StringArray& args, int streamFlags) | |||
| { | |||
| if (args.size() == 0) | |||
| return false; | |||
| activeProcess = new ActiveProcess (args, streamFlags); | |||
| if (activeProcess->childPID == 0) | |||
| activeProcess = nullptr; | |||
| return activeProcess != nullptr; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,122 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_CHILDPROCESS_H_INCLUDED | |||
| #define JUCE_CHILDPROCESS_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| Launches and monitors a child process. | |||
| This class lets you launch an executable, and read its output. You can also | |||
| use it to check whether the child process has finished. | |||
| */ | |||
| class JUCE_API ChildProcess | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a process object. | |||
| To actually launch the process, use start(). | |||
| */ | |||
| ChildProcess(); | |||
| /** Destructor. | |||
| Note that deleting this object won't terminate the child process. | |||
| */ | |||
| ~ChildProcess(); | |||
| /** These flags are used by the start() methods. */ | |||
| enum StreamFlags | |||
| { | |||
| wantStdOut = 1, | |||
| wantStdErr = 2 | |||
| }; | |||
| /** Attempts to launch a child process command. | |||
| The command should be the name of the executable file, followed by any arguments | |||
| that are required. | |||
| If the process has already been launched, this will launch it again. If a problem | |||
| occurs, the method will return false. | |||
| The streamFlags is a combinations of values to indicate which of the child's output | |||
| streams should be read and returned by readProcessOutput(). | |||
| */ | |||
| bool start (const String& command, int streamFlags = wantStdOut | wantStdErr); | |||
| /** Attempts to launch a child process command. | |||
| The first argument should be the name of the executable file, followed by any other | |||
| arguments that are needed. | |||
| If the process has already been launched, this will launch it again. If a problem | |||
| occurs, the method will return false. | |||
| The streamFlags is a combinations of values to indicate which of the child's output | |||
| streams should be read and returned by readProcessOutput(). | |||
| */ | |||
| bool start (const StringArray& arguments, int streamFlags = wantStdOut | wantStdErr); | |||
| /** Returns true if the child process is alive. */ | |||
| bool isRunning() const; | |||
| /** Attempts to read some output from the child process. | |||
| This will attempt to read up to the given number of bytes of data from the | |||
| process. It returns the number of bytes that were actually read. | |||
| */ | |||
| int readProcessOutput (void* destBuffer, int numBytesToRead); | |||
| /** Blocks until the process has finished, and then returns its complete output | |||
| as a string. | |||
| */ | |||
| String readAllProcessOutput(); | |||
| /** Blocks until the process is no longer running. */ | |||
| bool waitForProcessToFinish (int timeoutMs) const; | |||
| /** If the process has finished, this returns its exit code. */ | |||
| uint32 getExitCode() const; | |||
| /** Attempts to kill the child process. | |||
| Returns true if it succeeded. Trying to read from the process after calling this may | |||
| result in undefined behaviour. | |||
| */ | |||
| bool kill(); | |||
| uint32 getPID() const noexcept; | |||
| private: | |||
| //============================================================================== | |||
| class ActiveProcess; | |||
| ScopedPointer<ActiveProcess> activeProcess; | |||
| JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ChildProcess) | |||
| }; | |||
| #endif // JUCE_CHILDPROCESS_H_INCLUDED | |||
| @@ -0,0 +1,164 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_PROCESS_H_INCLUDED | |||
| #define JUCE_PROCESS_H_INCLUDED | |||
| //============================================================================== | |||
| /** Represents the current executable's process. | |||
| This contains methods for controlling the current application at the | |||
| process-level. | |||
| @see Thread, JUCEApplicationBase | |||
| */ | |||
| class JUCE_API Process | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| enum ProcessPriority | |||
| { | |||
| LowPriority = 0, | |||
| NormalPriority = 1, | |||
| HighPriority = 2, | |||
| RealtimePriority = 3 | |||
| }; | |||
| /** Changes the current process's priority. | |||
| @param priority the process priority, where | |||
| 0=low, 1=normal, 2=high, 3=realtime | |||
| */ | |||
| static void JUCE_CALLTYPE setPriority (const ProcessPriority priority); | |||
| /** Kills the current process immediately. | |||
| This is an emergency process terminator that kills the application | |||
| immediately - it's intended only for use only when something goes | |||
| horribly wrong. | |||
| @see JUCEApplicationBase::quit | |||
| */ | |||
| static void JUCE_CALLTYPE terminate(); | |||
| //============================================================================== | |||
| /** Returns true if this application process is the one that the user is | |||
| currently using. | |||
| */ | |||
| static bool JUCE_CALLTYPE isForegroundProcess(); | |||
| /** Attempts to make the current process the active one. | |||
| (This is not possible on some platforms). | |||
| */ | |||
| static void JUCE_CALLTYPE makeForegroundProcess(); | |||
| /** Hides the application (on an OS that supports this, e.g. OSX) */ | |||
| static void JUCE_CALLTYPE hide(); | |||
| //============================================================================== | |||
| /** Raises the current process's privilege level. | |||
| Does nothing if this isn't supported by the current OS, or if process | |||
| privilege level is fixed. | |||
| */ | |||
| static void JUCE_CALLTYPE raisePrivilege(); | |||
| /** Lowers the current process's privilege level. | |||
| Does nothing if this isn't supported by the current OS, or if process | |||
| privilege level is fixed. | |||
| */ | |||
| static void JUCE_CALLTYPE lowerPrivilege(); | |||
| //============================================================================== | |||
| /** Returns true if this process is being hosted by a debugger. */ | |||
| static bool JUCE_CALLTYPE isRunningUnderDebugger() noexcept; | |||
| //============================================================================== | |||
| /** Tries to launch the OS's default reader application for a given file or URL. */ | |||
| static bool JUCE_CALLTYPE openDocument (const String& documentURL, const String& parameters); | |||
| /** Tries to launch the OS's default email application to let the user create a message. */ | |||
| static bool JUCE_CALLTYPE openEmailWithAttachments (const String& targetEmailAddress, | |||
| const String& emailSubject, | |||
| const String& bodyText, | |||
| const StringArray& filesToAttach); | |||
| #ifdef CARLA_OS_WIN | |||
| //============================================================================== | |||
| /** WINDOWS ONLY - This returns the HINSTANCE of the current module. | |||
| The return type is a void* to avoid being dependent on windows.h - just cast | |||
| it to a HINSTANCE to use it. | |||
| In a normal JUCE application, this will be automatically set to the module | |||
| handle of the executable. | |||
| If you've built a DLL and plan to use any JUCE messaging or windowing classes, | |||
| you'll need to make sure you call the setCurrentModuleInstanceHandle() | |||
| to provide the correct module handle in your DllMain() function, because | |||
| the system relies on the correct instance handle when opening windows. | |||
| */ | |||
| static void* JUCE_CALLTYPE getCurrentModuleInstanceHandle() noexcept; | |||
| /** WINDOWS ONLY - Sets a new module handle to be used by the library. | |||
| The parameter type is a void* to avoid being dependent on windows.h, but it actually | |||
| expects a HINSTANCE value. | |||
| @see getCurrentModuleInstanceHandle() | |||
| */ | |||
| static void JUCE_CALLTYPE setCurrentModuleInstanceHandle (void* newHandle) noexcept; | |||
| #endif | |||
| #if JUCE_MAC || DOXYGEN | |||
| //============================================================================== | |||
| /** OSX ONLY - Shows or hides the OSX dock icon for this app. */ | |||
| static void setDockIconVisible (bool isVisible); | |||
| #endif | |||
| #if JUCE_MAC || JUCE_LINUX || DOXYGEN | |||
| //============================================================================== | |||
| /** UNIX ONLY - Attempts to use setrlimit to change the maximum number of file | |||
| handles that the app can open. Pass 0 or less as the parameter to mean | |||
| 'infinite'. Returns true if it succeeds. | |||
| */ | |||
| static bool setMaxNumberOfFileHandles (int maxNumberOfFiles) noexcept; | |||
| #endif | |||
| private: | |||
| Process(); | |||
| JUCE_DECLARE_NON_COPYABLE (Process) | |||
| }; | |||
| #endif // JUCE_PROCESS_H_INCLUDED | |||
| @@ -0,0 +1,239 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_SCOPEDLOCK_H_INCLUDED | |||
| #define JUCE_SCOPEDLOCK_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| Automatically locks and unlocks a mutex object. | |||
| Use one of these as a local variable to provide RAII-based locking of a mutex. | |||
| The templated class could be a CriticalSection, SpinLock, or anything else that | |||
| provides enter() and exit() methods. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ...do some stuff... | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see GenericScopedUnlock, CriticalSection, SpinLock, ScopedLock, ScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedLock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a GenericScopedLock. | |||
| As soon as it is created, this will acquire the lock, and when the GenericScopedLock | |||
| object is deleted, the lock will be released. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedLock (const LockType& lock) noexcept : lock_ (lock) { lock.enter(); } | |||
| /** Destructor. | |||
| The lock will be released when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, otherwise there are | |||
| no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedLock() noexcept { lock_.exit(); } | |||
| private: | |||
| //============================================================================== | |||
| const LockType& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedLock) | |||
| }; | |||
| //============================================================================== | |||
| /** | |||
| Automatically unlocks and re-locks a mutex object. | |||
| This is the reverse of a GenericScopedLock object - instead of locking the mutex | |||
| for the lifetime of this object, it unlocks it. | |||
| Make sure you don't try to unlock mutexes that aren't actually locked! | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedLock<CriticalSection> myScopedLock (myCriticalSection); | |||
| // myCriticalSection is now locked | |||
| ... do some stuff with it locked .. | |||
| while (xyz) | |||
| { | |||
| ... do some stuff with it locked .. | |||
| const GenericScopedUnlock<CriticalSection> unlocker (myCriticalSection); | |||
| // myCriticalSection is now unlocked for the remainder of this block, | |||
| // and re-locked at the end. | |||
| ...do some stuff with it unlocked ... | |||
| } | |||
| // myCriticalSection gets unlocked here. | |||
| } | |||
| @endcode | |||
| @see GenericScopedLock, CriticalSection, ScopedLock, ScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedUnlock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a GenericScopedUnlock. | |||
| As soon as it is created, this will unlock the CriticalSection, and | |||
| when the ScopedLock object is deleted, the CriticalSection will | |||
| be re-locked. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedUnlock (const LockType& lock) noexcept : lock_ (lock) { lock.exit(); } | |||
| /** Destructor. | |||
| The CriticalSection will be unlocked when the destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedUnlock() noexcept { lock_.enter(); } | |||
| private: | |||
| //============================================================================== | |||
| const LockType& lock_; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedUnlock) | |||
| }; | |||
| //============================================================================== | |||
| /** | |||
| Automatically locks and unlocks a mutex object. | |||
| Use one of these as a local variable to provide RAII-based locking of a mutex. | |||
| The templated class could be a CriticalSection, SpinLock, or anything else that | |||
| provides enter() and exit() methods. | |||
| e.g. @code | |||
| CriticalSection myCriticalSection; | |||
| for (;;) | |||
| { | |||
| const GenericScopedTryLock<CriticalSection> myScopedTryLock (myCriticalSection); | |||
| // Unlike using a ScopedLock, this may fail to actually get the lock, so you | |||
| // should test this with the isLocked() method before doing your thread-unsafe | |||
| // action.. | |||
| if (myScopedTryLock.isLocked()) | |||
| { | |||
| ...do some stuff... | |||
| } | |||
| else | |||
| { | |||
| ..our attempt at locking failed because another thread had already locked it.. | |||
| } | |||
| // myCriticalSection gets unlocked here (if it was locked) | |||
| } | |||
| @endcode | |||
| @see CriticalSection::tryEnter, GenericScopedLock, GenericScopedUnlock | |||
| */ | |||
| template <class LockType> | |||
| class GenericScopedTryLock | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a GenericScopedTryLock. | |||
| As soon as it is created, this will attempt to acquire the lock, and when the | |||
| GenericScopedTryLock is deleted, the lock will be released (if the lock was | |||
| successfully acquired). | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! Best just to use it | |||
| as a local stack object, rather than creating one with the new() operator. | |||
| */ | |||
| inline explicit GenericScopedTryLock (const LockType& lock) noexcept | |||
| : lock_ (lock), lockWasSuccessful (lock.tryEnter()) {} | |||
| /** Destructor. | |||
| The mutex will be unlocked (if it had been successfully locked) when the | |||
| destructor is called. | |||
| Make sure this object is created and deleted by the same thread, | |||
| otherwise there are no guarantees what will happen! | |||
| */ | |||
| inline ~GenericScopedTryLock() noexcept { if (lockWasSuccessful) lock_.exit(); } | |||
| /** Returns true if the mutex was successfully locked. */ | |||
| bool isLocked() const noexcept { return lockWasSuccessful; } | |||
| private: | |||
| //============================================================================== | |||
| const LockType& lock_; | |||
| const bool lockWasSuccessful; | |||
| JUCE_DECLARE_NON_COPYABLE (GenericScopedTryLock) | |||
| }; | |||
| #endif // JUCE_SCOPEDLOCK_H_INCLUDED | |||
| @@ -0,0 +1,110 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_SPINLOCK_H_INCLUDED | |||
| #define JUCE_SPINLOCK_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| A simple spin-lock class that can be used as a simple, low-overhead mutex for | |||
| uncontended situations. | |||
| Note that unlike a CriticalSection, this type of lock is not re-entrant, and may | |||
| be less efficient when used it a highly contended situation, but it's very small and | |||
| requires almost no initialisation. | |||
| It's most appropriate for simple situations where you're only going to hold the | |||
| lock for a very brief time. | |||
| @see CriticalSection | |||
| */ | |||
| class JUCE_API SpinLock | |||
| { | |||
| public: | |||
| inline SpinLock() noexcept {} | |||
| inline ~SpinLock() noexcept {} | |||
| /** Acquires the lock. | |||
| This will block until the lock has been successfully acquired by this thread. | |||
| Note that a SpinLock is NOT re-entrant, and is not smart enough to know whether the | |||
| caller thread already has the lock - so if a thread tries to acquire a lock that it | |||
| already holds, this method will never return! | |||
| It's strongly recommended that you never call this method directly - instead use the | |||
| ScopedLockType class to manage the locking using an RAII pattern instead. | |||
| */ | |||
| void enter() const noexcept | |||
| { | |||
| if (! tryEnter()) | |||
| { | |||
| for (int i = 20; --i >= 0;) | |||
| if (tryEnter()) | |||
| return; | |||
| while (! tryEnter()) | |||
| { | |||
| #ifdef CARLA_OS_WIN | |||
| Sleep (0); | |||
| #else | |||
| sched_yield(); | |||
| #endif | |||
| } | |||
| } | |||
| } | |||
| /** Attempts to acquire the lock, returning true if this was successful. */ | |||
| inline bool tryEnter() const noexcept | |||
| { | |||
| return lock.compareAndSetBool (1, 0); | |||
| } | |||
| /** Releases the lock. */ | |||
| inline void exit() const noexcept | |||
| { | |||
| jassert (lock.value == 1); // Agh! Releasing a lock that isn't currently held! | |||
| lock = 0; | |||
| } | |||
| //============================================================================== | |||
| /** Provides the type of scoped lock to use for locking a SpinLock. */ | |||
| typedef GenericScopedLock <SpinLock> ScopedLockType; | |||
| /** Provides the type of scoped unlocker to use with a SpinLock. */ | |||
| typedef GenericScopedUnlock <SpinLock> ScopedUnlockType; | |||
| private: | |||
| //============================================================================== | |||
| mutable Atomic<int> lock; | |||
| JUCE_DECLARE_NON_COPYABLE (SpinLock) | |||
| }; | |||
| #endif // JUCE_SPINLOCK_H_INCLUDED | |||
| @@ -0,0 +1,631 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| namespace TimeHelpers | |||
| { | |||
| #if 0 | |||
| static std::tm millisToLocal (int64 millis) noexcept | |||
| { | |||
| #if JUCE_WINDOWS && JUCE_MINGW | |||
| time_t now = (time_t) (millis / 1000); | |||
| return *localtime (&now); | |||
| #elif JUCE_WINDOWS | |||
| std::tm result; | |||
| millis /= 1000; | |||
| if (_localtime64_s (&result, &millis) != 0) | |||
| zerostruct (result); | |||
| return result; | |||
| #else | |||
| std::tm result; | |||
| time_t now = (time_t) (millis / 1000); | |||
| if (localtime_r (&now, &result) == nullptr) | |||
| zerostruct (result); | |||
| return result; | |||
| #endif | |||
| } | |||
| static std::tm millisToUTC (int64 millis) noexcept | |||
| { | |||
| #if JUCE_WINDOWS && JUCE_MINGW | |||
| time_t now = (time_t) (millis / 1000); | |||
| return *gmtime (&now); | |||
| #elif JUCE_WINDOWS | |||
| std::tm result; | |||
| millis /= 1000; | |||
| if (_gmtime64_s (&result, &millis) != 0) | |||
| zerostruct (result); | |||
| return result; | |||
| #else | |||
| std::tm result; | |||
| time_t now = (time_t) (millis / 1000); | |||
| if (gmtime_r (&now, &result) == nullptr) | |||
| zerostruct (result); | |||
| return result; | |||
| #endif | |||
| } | |||
| static int getUTCOffsetSeconds (const int64 millis) noexcept | |||
| { | |||
| std::tm utc = millisToUTC (millis); | |||
| utc.tm_isdst = -1; // Treat this UTC time as local to find the offset | |||
| return (int) ((millis / 1000) - (int64) mktime (&utc)); | |||
| } | |||
| static int extendedModulo (const int64 value, const int modulo) noexcept | |||
| { | |||
| return (int) (value >= 0 ? (value % modulo) | |||
| : (value - ((value / modulo) + 1) * modulo)); | |||
| } | |||
| static inline String formatString (const String& format, const std::tm* const tm) | |||
| { | |||
| #if JUCE_ANDROID | |||
| typedef CharPointer_UTF8 StringType; | |||
| #elif JUCE_WINDOWS | |||
| typedef CharPointer_UTF16 StringType; | |||
| #else | |||
| typedef CharPointer_UTF32 StringType; | |||
| #endif | |||
| #ifdef JUCE_MSVC | |||
| if (tm->tm_year < -1900 || tm->tm_year > 8099) | |||
| return String(); // Visual Studio's library can only handle 0 -> 9999 AD | |||
| #endif | |||
| for (size_t bufferSize = 256; ; bufferSize += 256) | |||
| { | |||
| HeapBlock<StringType::CharType> buffer (bufferSize); | |||
| const size_t numChars = | |||
| #if JUCE_ANDROID | |||
| strftime (buffer, bufferSize - 1, format.toUTF8(), tm); | |||
| #elif JUCE_WINDOWS | |||
| wcsftime (buffer, bufferSize - 1, format.toWideCharPointer(), tm); | |||
| #else | |||
| wcsftime (buffer, bufferSize - 1, format.toUTF32(), tm); | |||
| #endif | |||
| if (numChars > 0 || format.isEmpty()) | |||
| return String (StringType (buffer), | |||
| StringType (buffer) + (int) numChars); | |||
| } | |||
| } | |||
| //============================================================================== | |||
| static inline bool isLeapYear (int year) noexcept | |||
| { | |||
| return (year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0)); | |||
| } | |||
| static inline int daysFromJan1 (int year, int month) noexcept | |||
| { | |||
| const short dayOfYear[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, | |||
| 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; | |||
| return dayOfYear [(isLeapYear (year) ? 12 : 0) + month]; | |||
| } | |||
| static inline int64 daysFromYear0 (int year) noexcept | |||
| { | |||
| --year; | |||
| return 365 * year + (year / 400) - (year / 100) + (year / 4); | |||
| } | |||
| static inline int64 daysFrom1970 (int year) noexcept | |||
| { | |||
| return daysFromYear0 (year) - daysFromYear0 (1970); | |||
| } | |||
| static inline int64 daysFrom1970 (int year, int month) noexcept | |||
| { | |||
| if (month > 11) | |||
| { | |||
| year += month / 12; | |||
| month %= 12; | |||
| } | |||
| else if (month < 0) | |||
| { | |||
| const int numYears = (11 - month) / 12; | |||
| year -= numYears; | |||
| month += 12 * numYears; | |||
| } | |||
| return daysFrom1970 (year) + daysFromJan1 (year, month); | |||
| } | |||
| // There's no posix function that does a UTC version of mktime, | |||
| // so annoyingly we need to implement this manually.. | |||
| static inline int64 mktime_utc (const std::tm& t) noexcept | |||
| { | |||
| return 24 * 3600 * (daysFrom1970 (t.tm_year + 1900, t.tm_mon) + (t.tm_mday - 1)) | |||
| + 3600 * t.tm_hour | |||
| + 60 * t.tm_min | |||
| + t.tm_sec; | |||
| } | |||
| #endif | |||
| static uint32 lastMSCounterValue = 0; | |||
| } | |||
| //============================================================================== | |||
| Time::Time() noexcept : millisSinceEpoch (0) | |||
| { | |||
| } | |||
| Time::Time (const Time& other) noexcept : millisSinceEpoch (other.millisSinceEpoch) | |||
| { | |||
| } | |||
| Time::Time (const int64 ms) noexcept : millisSinceEpoch (ms) | |||
| { | |||
| } | |||
| #if 0 | |||
| Time::Time (const int year, | |||
| const int month, | |||
| const int day, | |||
| const int hours, | |||
| const int minutes, | |||
| const int seconds, | |||
| const int milliseconds, | |||
| const bool useLocalTime) noexcept | |||
| { | |||
| std::tm t; | |||
| t.tm_year = year - 1900; | |||
| t.tm_mon = month; | |||
| t.tm_mday = day; | |||
| t.tm_hour = hours; | |||
| t.tm_min = minutes; | |||
| t.tm_sec = seconds; | |||
| t.tm_isdst = -1; | |||
| millisSinceEpoch = 1000 * (useLocalTime ? (int64) mktime (&t) | |||
| : TimeHelpers::mktime_utc (t)) | |||
| + milliseconds; | |||
| } | |||
| #endif | |||
| Time::~Time() noexcept | |||
| { | |||
| } | |||
| Time& Time::operator= (const Time& other) noexcept | |||
| { | |||
| millisSinceEpoch = other.millisSinceEpoch; | |||
| return *this; | |||
| } | |||
| //============================================================================== | |||
| int64 Time::currentTimeMillis() noexcept | |||
| { | |||
| struct timeval tv; | |||
| gettimeofday (&tv, nullptr); | |||
| return ((int64) tv.tv_sec) * 1000 + tv.tv_usec / 1000; | |||
| } | |||
| #if 0 | |||
| Time JUCE_CALLTYPE Time::getCurrentTime() noexcept | |||
| { | |||
| return Time (currentTimeMillis()); | |||
| } | |||
| #endif | |||
| //============================================================================== | |||
| static uint32 juce_millisecondsSinceStartup() noexcept | |||
| { | |||
| #ifdef CARLA_OS_WIN | |||
| return (uint32) timeGetTime(); | |||
| #else | |||
| timespec t; | |||
| clock_gettime (CLOCK_MONOTONIC, &t); | |||
| return (uint32) (t.tv_sec * 1000 + t.tv_nsec / 1000000); | |||
| #endif | |||
| } | |||
| uint32 Time::getMillisecondCounter() noexcept | |||
| { | |||
| const uint32 now = juce_millisecondsSinceStartup(); | |||
| if (now < TimeHelpers::lastMSCounterValue) | |||
| { | |||
| // in multi-threaded apps this might be called concurrently, so | |||
| // make sure that our last counter value only increases and doesn't | |||
| // go backwards.. | |||
| if (now < TimeHelpers::lastMSCounterValue - 1000) | |||
| TimeHelpers::lastMSCounterValue = now; | |||
| } | |||
| else | |||
| { | |||
| TimeHelpers::lastMSCounterValue = now; | |||
| } | |||
| return now; | |||
| } | |||
| uint32 Time::getApproximateMillisecondCounter() noexcept | |||
| { | |||
| if (TimeHelpers::lastMSCounterValue == 0) | |||
| getMillisecondCounter(); | |||
| return TimeHelpers::lastMSCounterValue; | |||
| } | |||
| #if 0 | |||
| void Time::waitForMillisecondCounter (const uint32 targetTime) noexcept | |||
| { | |||
| for (;;) | |||
| { | |||
| const uint32 now = getMillisecondCounter(); | |||
| if (now >= targetTime) | |||
| break; | |||
| const int toWait = (int) (targetTime - now); | |||
| if (toWait > 2) | |||
| { | |||
| Thread::sleep (jmin (20, toWait >> 1)); | |||
| } | |||
| else | |||
| { | |||
| // xxx should consider using mutex_pause on the mac as it apparently | |||
| // makes it seem less like a spinlock and avoids lowering the thread pri. | |||
| for (int i = 10; --i >= 0;) | |||
| Thread::yield(); | |||
| } | |||
| } | |||
| } | |||
| //============================================================================== | |||
| double Time::highResolutionTicksToSeconds (const int64 ticks) noexcept | |||
| { | |||
| return ticks / (double) getHighResolutionTicksPerSecond(); | |||
| } | |||
| int64 Time::secondsToHighResolutionTicks (const double seconds) noexcept | |||
| { | |||
| return (int64) (seconds * (double) getHighResolutionTicksPerSecond()); | |||
| } | |||
| //============================================================================== | |||
| String Time::toString (const bool includeDate, | |||
| const bool includeTime, | |||
| const bool includeSeconds, | |||
| const bool use24HourClock) const noexcept | |||
| { | |||
| String result; | |||
| if (includeDate) | |||
| { | |||
| result << getDayOfMonth() << ' ' | |||
| << getMonthName (true) << ' ' | |||
| << getYear(); | |||
| if (includeTime) | |||
| result << ' '; | |||
| } | |||
| if (includeTime) | |||
| { | |||
| const int mins = getMinutes(); | |||
| result << (use24HourClock ? getHours() : getHoursInAmPmFormat()) | |||
| << (mins < 10 ? ":0" : ":") << mins; | |||
| if (includeSeconds) | |||
| { | |||
| const int secs = getSeconds(); | |||
| result << (secs < 10 ? ":0" : ":") << secs; | |||
| } | |||
| if (! use24HourClock) | |||
| result << (isAfternoon() ? "pm" : "am"); | |||
| } | |||
| return result.trimEnd(); | |||
| } | |||
| String Time::formatted (const String& format) const | |||
| { | |||
| std::tm t (TimeHelpers::millisToLocal (millisSinceEpoch)); | |||
| return TimeHelpers::formatString (format, &t); | |||
| } | |||
| //============================================================================== | |||
| int Time::getYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_year + 1900; } | |||
| int Time::getMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mon; } | |||
| int Time::getDayOfYear() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_yday; } | |||
| int Time::getDayOfMonth() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_mday; } | |||
| int Time::getDayOfWeek() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_wday; } | |||
| int Time::getHours() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_hour; } | |||
| int Time::getMinutes() const noexcept { return TimeHelpers::millisToLocal (millisSinceEpoch).tm_min; } | |||
| int Time::getSeconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch / 1000, 60); } | |||
| int Time::getMilliseconds() const noexcept { return TimeHelpers::extendedModulo (millisSinceEpoch, 1000); } | |||
| int Time::getHoursInAmPmFormat() const noexcept | |||
| { | |||
| const int hours = getHours(); | |||
| if (hours == 0) return 12; | |||
| if (hours <= 12) return hours; | |||
| return hours - 12; | |||
| } | |||
| bool Time::isAfternoon() const noexcept | |||
| { | |||
| return getHours() >= 12; | |||
| } | |||
| bool Time::isDaylightSavingTime() const noexcept | |||
| { | |||
| return TimeHelpers::millisToLocal (millisSinceEpoch).tm_isdst != 0; | |||
| } | |||
| String Time::getTimeZone() const noexcept | |||
| { | |||
| String zone[2]; | |||
| #if JUCE_WINDOWS | |||
| #if JUCE_MSVC || JUCE_CLANG | |||
| _tzset(); | |||
| for (int i = 0; i < 2; ++i) | |||
| { | |||
| char name[128] = { 0 }; | |||
| size_t length; | |||
| _get_tzname (&length, name, 127, i); | |||
| zone[i] = name; | |||
| } | |||
| #else | |||
| #warning "Can't find a replacement for tzset on mingw - ideas welcome!" | |||
| #endif | |||
| #else | |||
| tzset(); | |||
| const char** const zonePtr = (const char**) tzname; | |||
| zone[0] = zonePtr[0]; | |||
| zone[1] = zonePtr[1]; | |||
| #endif | |||
| if (isDaylightSavingTime()) | |||
| { | |||
| zone[0] = zone[1]; | |||
| if (zone[0].length() > 3 | |||
| && zone[0].containsIgnoreCase ("daylight") | |||
| && zone[0].contains ("GMT")) | |||
| zone[0] = "BST"; | |||
| } | |||
| return zone[0].substring (0, 3); | |||
| } | |||
| int Time::getUTCOffsetSeconds() const noexcept | |||
| { | |||
| return TimeHelpers::getUTCOffsetSeconds (millisSinceEpoch); | |||
| } | |||
| String Time::getUTCOffsetString (bool includeSemiColon) const | |||
| { | |||
| if (int seconds = getUTCOffsetSeconds()) | |||
| { | |||
| const int minutes = seconds / 60; | |||
| return String::formatted (includeSemiColon ? "%+03d:%02d" | |||
| : "%+03d%02d", | |||
| minutes / 60, | |||
| minutes % 60); | |||
| } | |||
| return "Z"; | |||
| } | |||
| String Time::toISO8601 (bool includeDividerCharacters) const | |||
| { | |||
| return String::formatted (includeDividerCharacters ? "%04d-%02d-%02dT%02d:%02d:%06.03f" | |||
| : "%04d%02d%02dT%02d%02d%06.03f", | |||
| getYear(), | |||
| getMonth() + 1, | |||
| getDayOfMonth(), | |||
| getHours(), | |||
| getMinutes(), | |||
| getSeconds() + getMilliseconds() / 1000.0) | |||
| + getUTCOffsetString (includeDividerCharacters); | |||
| } | |||
| static int parseFixedSizeIntAndSkip (String::CharPointerType& t, int numChars, char charToSkip) noexcept | |||
| { | |||
| int n = 0; | |||
| for (int i = numChars; --i >= 0;) | |||
| { | |||
| const int digit = (int) (*t - '0'); | |||
| if (! isPositiveAndBelow (digit, 10)) | |||
| return -1; | |||
| ++t; | |||
| n = n * 10 + digit; | |||
| } | |||
| if (charToSkip != 0 && *t == (juce_wchar) charToSkip) | |||
| ++t; | |||
| return n; | |||
| } | |||
| Time Time::fromISO8601 (StringRef iso) noexcept | |||
| { | |||
| String::CharPointerType t = iso.text; | |||
| const int year = parseFixedSizeIntAndSkip (t, 4, '-'); | |||
| if (year < 0) | |||
| return Time(); | |||
| const int month = parseFixedSizeIntAndSkip (t, 2, '-'); | |||
| if (month < 0) | |||
| return Time(); | |||
| const int day = parseFixedSizeIntAndSkip (t, 2, 0); | |||
| if (day < 0) | |||
| return Time(); | |||
| int hours = 0, minutes = 0, milliseconds = 0; | |||
| if (*t == 'T') | |||
| { | |||
| ++t; | |||
| hours = parseFixedSizeIntAndSkip (t, 2, ':'); | |||
| if (hours < 0) | |||
| return Time(); | |||
| minutes = parseFixedSizeIntAndSkip (t, 2, ':'); | |||
| if (minutes < 0) | |||
| return Time(); | |||
| milliseconds = (int) (1000.0 * CharacterFunctions::readDoubleValue (t)); | |||
| } | |||
| const juce_wchar nextChar = t.getAndAdvance(); | |||
| if (nextChar == '-' || nextChar == '+') | |||
| { | |||
| const int offsetHours = parseFixedSizeIntAndSkip (t, 2, ':'); | |||
| if (offsetHours < 0) | |||
| return Time(); | |||
| const int offsetMinutes = parseFixedSizeIntAndSkip (t, 2, 0); | |||
| if (offsetMinutes < 0) | |||
| return Time(); | |||
| const int offsetMs = (offsetHours * 60 + offsetMinutes) * 60 * 1000; | |||
| milliseconds += nextChar == '-' ? offsetMs : -offsetMs; // NB: this seems backwards but is correct! | |||
| } | |||
| else if (nextChar != 0 && nextChar != 'Z') | |||
| { | |||
| return Time(); | |||
| } | |||
| return Time (year, month - 1, day, hours, minutes, 0, milliseconds, false); | |||
| } | |||
| String Time::getMonthName (const bool threeLetterVersion) const | |||
| { | |||
| return getMonthName (getMonth(), threeLetterVersion); | |||
| } | |||
| String Time::getWeekdayName (const bool threeLetterVersion) const | |||
| { | |||
| return getWeekdayName (getDayOfWeek(), threeLetterVersion); | |||
| } | |||
| static const char* const shortMonthNames[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; | |||
| static const char* const longMonthNames[] = { "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" }; | |||
| String Time::getMonthName (int monthNumber, const bool threeLetterVersion) | |||
| { | |||
| monthNumber %= 12; | |||
| return TRANS (threeLetterVersion ? shortMonthNames [monthNumber] | |||
| : longMonthNames [monthNumber]); | |||
| } | |||
| String Time::getWeekdayName (int day, const bool threeLetterVersion) | |||
| { | |||
| static const char* const shortDayNames[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; | |||
| static const char* const longDayNames[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; | |||
| day %= 7; | |||
| return TRANS (threeLetterVersion ? shortDayNames [day] | |||
| : longDayNames [day]); | |||
| } | |||
| //============================================================================== | |||
| Time& Time::operator+= (RelativeTime delta) noexcept { millisSinceEpoch += delta.inMilliseconds(); return *this; } | |||
| Time& Time::operator-= (RelativeTime delta) noexcept { millisSinceEpoch -= delta.inMilliseconds(); return *this; } | |||
| Time operator+ (Time time, RelativeTime delta) noexcept { Time t (time); return t += delta; } | |||
| Time operator- (Time time, RelativeTime delta) noexcept { Time t (time); return t -= delta; } | |||
| Time operator+ (RelativeTime delta, Time time) noexcept { Time t (time); return t += delta; } | |||
| const RelativeTime operator- (Time time1, Time time2) noexcept { return RelativeTime::milliseconds (time1.toMilliseconds() - time2.toMilliseconds()); } | |||
| bool operator== (Time time1, Time time2) noexcept { return time1.toMilliseconds() == time2.toMilliseconds(); } | |||
| bool operator!= (Time time1, Time time2) noexcept { return time1.toMilliseconds() != time2.toMilliseconds(); } | |||
| bool operator< (Time time1, Time time2) noexcept { return time1.toMilliseconds() < time2.toMilliseconds(); } | |||
| bool operator> (Time time1, Time time2) noexcept { return time1.toMilliseconds() > time2.toMilliseconds(); } | |||
| bool operator<= (Time time1, Time time2) noexcept { return time1.toMilliseconds() <= time2.toMilliseconds(); } | |||
| bool operator>= (Time time1, Time time2) noexcept { return time1.toMilliseconds() >= time2.toMilliseconds(); } | |||
| static int getMonthNumberForCompileDate (const String& m) noexcept | |||
| { | |||
| for (int i = 0; i < 12; ++i) | |||
| if (m.equalsIgnoreCase (shortMonthNames[i])) | |||
| return i; | |||
| // If you hit this because your compiler has an unusual __DATE__ | |||
| // format, let us know so we can add support for it! | |||
| jassertfalse; | |||
| return 0; | |||
| } | |||
| Time Time::getCompilationDate() | |||
| { | |||
| StringArray dateTokens, timeTokens; | |||
| dateTokens.addTokens (__DATE__, true); | |||
| dateTokens.removeEmptyStrings (true); | |||
| timeTokens.addTokens (__TIME__, ":", StringRef()); | |||
| return Time (dateTokens[2].getIntValue(), | |||
| getMonthNumberForCompileDate (dateTokens[0]), | |||
| dateTokens[1].getIntValue(), | |||
| timeTokens[0].getIntValue(), | |||
| timeTokens[1].getIntValue()); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,401 @@ | |||
| /* | |||
| ============================================================================== | |||
| This file is part of the JUCE library. | |||
| Copyright (c) 2016 - ROLI Ltd. | |||
| Permission is granted to use this software under the terms of the ISC license | |||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | |||
| Permission to use, copy, modify, and/or distribute this software for any | |||
| purpose with or without fee is hereby granted, provided that the above | |||
| copyright notice and this permission notice appear in all copies. | |||
| THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD | |||
| TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND | |||
| FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, | |||
| OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF | |||
| USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER | |||
| TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE | |||
| OF THIS SOFTWARE. | |||
| ----------------------------------------------------------------------------- | |||
| To release a closed-source product which uses other parts of JUCE not | |||
| licensed under the ISC terms, commercial licenses are available: visit | |||
| www.juce.com for more information. | |||
| ============================================================================== | |||
| */ | |||
| #ifndef JUCE_TIME_H_INCLUDED | |||
| #define JUCE_TIME_H_INCLUDED | |||
| //============================================================================== | |||
| /** | |||
| Holds an absolute date and time. | |||
| Internally, the time is stored at millisecond precision. | |||
| @see RelativeTime | |||
| */ | |||
| class JUCE_API Time | |||
| { | |||
| public: | |||
| //============================================================================== | |||
| /** Creates a Time object. | |||
| This default constructor creates a time of midnight Jan 1st 1970 UTC, (which is | |||
| represented internally as 0ms). | |||
| To create a time object representing the current time, use getCurrentTime(). | |||
| @see getCurrentTime | |||
| */ | |||
| Time() noexcept; | |||
| /** Creates a time based on a number of milliseconds. | |||
| To create a time object set to the current time, use getCurrentTime(). | |||
| @param millisecondsSinceEpoch the number of milliseconds since the unix | |||
| 'epoch' (midnight Jan 1st 1970 UTC). | |||
| @see getCurrentTime, currentTimeMillis | |||
| */ | |||
| explicit Time (int64 millisecondsSinceEpoch) noexcept; | |||
| /** Creates a time from a set of date components. | |||
| @param year the year, in 4-digit format, e.g. 2004 | |||
| @param month the month, in the range 0 to 11 | |||
| @param day the day of the month, in the range 1 to 31 | |||
| @param hours hours in 24-hour clock format, 0 to 23 | |||
| @param minutes minutes 0 to 59 | |||
| @param seconds seconds 0 to 59 | |||
| @param milliseconds milliseconds 0 to 999 | |||
| @param useLocalTime if true, assume input is in this machine's local timezone | |||
| if false, assume input is in UTC. | |||
| */ | |||
| Time (int year, | |||
| int month, | |||
| int day, | |||
| int hours, | |||
| int minutes, | |||
| int seconds = 0, | |||
| int milliseconds = 0, | |||
| bool useLocalTime = true) noexcept; | |||
| /** Creates a copy of another Time object. */ | |||
| Time (const Time& other) noexcept; | |||
| /** Destructor. */ | |||
| ~Time() noexcept; | |||
| /** Copies this time from another one. */ | |||
| Time& operator= (const Time& other) noexcept; | |||
| //============================================================================== | |||
| /** Returns a Time object that is set to the current system time. | |||
| This may not be monotonic, as the system time can change at any moment. | |||
| You should therefore not use this method for measuring time intervals. | |||
| @see currentTimeMillis | |||
| */ | |||
| static Time JUCE_CALLTYPE getCurrentTime() noexcept; | |||
| /** Returns the time as a number of milliseconds. | |||
| @returns the number of milliseconds this Time object represents, since | |||
| midnight Jan 1st 1970 UTC. | |||
| @see getMilliseconds | |||
| */ | |||
| int64 toMilliseconds() const noexcept { return millisSinceEpoch; } | |||
| /** Returns the year (in this machine's local timezone). | |||
| A 4-digit format is used, e.g. 2004. | |||
| */ | |||
| int getYear() const noexcept; | |||
| /** Returns the number of the month (in this machine's local timezone). | |||
| The value returned is in the range 0 to 11. | |||
| @see getMonthName | |||
| */ | |||
| int getMonth() const noexcept; | |||
| /** Returns the name of the month (in this machine's local timezone). | |||
| @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false | |||
| it'll return the long form, e.g. "January" | |||
| @see getMonth | |||
| */ | |||
| String getMonthName (bool threeLetterVersion) const; | |||
| /** Returns the day of the month (in this machine's local timezone). | |||
| The value returned is in the range 1 to 31. | |||
| */ | |||
| int getDayOfMonth() const noexcept; | |||
| /** Returns the number of the day of the week (in this machine's local timezone). | |||
| The value returned is in the range 0 to 6 (0 = sunday, 1 = monday, etc). | |||
| */ | |||
| int getDayOfWeek() const noexcept; | |||
| /** Returns the number of the day of the year (in this machine's local timezone). | |||
| The value returned is in the range 0 to 365. | |||
| */ | |||
| int getDayOfYear() const noexcept; | |||
| /** Returns the name of the weekday (in this machine's local timezone). | |||
| @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if | |||
| false, it'll return the full version, e.g. "Tuesday". | |||
| */ | |||
| String getWeekdayName (bool threeLetterVersion) const; | |||
| /** Returns the number of hours since midnight (in this machine's local timezone). | |||
| This is in 24-hour clock format, in the range 0 to 23. | |||
| @see getHoursInAmPmFormat, isAfternoon | |||
| */ | |||
| int getHours() const noexcept; | |||
| /** Returns true if the time is in the afternoon (in this machine's local timezone). | |||
| @returns true for "PM", false for "AM". | |||
| @see getHoursInAmPmFormat, getHours | |||
| */ | |||
| bool isAfternoon() const noexcept; | |||
| /** Returns the hours in 12-hour clock format (in this machine's local timezone). | |||
| This will return a value 1 to 12 - use isAfternoon() to find out | |||
| whether this is in the afternoon or morning. | |||
| @see getHours, isAfternoon | |||
| */ | |||
| int getHoursInAmPmFormat() const noexcept; | |||
| /** Returns the number of minutes, 0 to 59 (in this machine's local timezone). */ | |||
| int getMinutes() const noexcept; | |||
| /** Returns the number of seconds, 0 to 59. */ | |||
| int getSeconds() const noexcept; | |||
| /** Returns the number of milliseconds, 0 to 999. | |||
| Unlike toMilliseconds(), this just returns the position within the | |||
| current second rather than the total number since the epoch. | |||
| @see toMilliseconds | |||
| */ | |||
| int getMilliseconds() const noexcept; | |||
| /** Returns true if the local timezone uses a daylight saving correction. */ | |||
| bool isDaylightSavingTime() const noexcept; | |||
| //============================================================================== | |||
| /** Returns a 3-character string to indicate the local timezone. */ | |||
| String getTimeZone() const noexcept; | |||
| /** Returns the local timezone offset from UTC in seconds. */ | |||
| int getUTCOffsetSeconds() const noexcept; | |||
| /** Returns a string to indicate the offset of the local timezone from UTC. | |||
| @returns "+XX:XX", "-XX:XX" or "Z" | |||
| @param includeDividerCharacters whether to include or omit the ":" divider in the string | |||
| */ | |||
| String getUTCOffsetString (bool includeDividerCharacters) const; | |||
| //============================================================================== | |||
| /** Returns a string version of this date and time, using this machine's local timezone. | |||
| For a more powerful way of formatting the date and time, see the formatted() method. | |||
| @param includeDate whether to include the date in the string | |||
| @param includeTime whether to include the time in the string | |||
| @param includeSeconds if the time is being included, this provides an option not to include | |||
| the seconds in it | |||
| @param use24HourClock if the time is being included, sets whether to use am/pm or 24 | |||
| hour notation. | |||
| @see formatted | |||
| */ | |||
| String toString (bool includeDate, | |||
| bool includeTime, | |||
| bool includeSeconds = true, | |||
| bool use24HourClock = false) const noexcept; | |||
| /** Converts this date/time to a string with a user-defined format. | |||
| This uses the C strftime() function to format this time as a string. To save you | |||
| looking it up, these are the escape codes that strftime uses (other codes might | |||
| work on some platforms and not others, but these are the common ones): | |||
| - %a is replaced by the locale's abbreviated weekday name. | |||
| - %A is replaced by the locale's full weekday name. | |||
| - %b is replaced by the locale's abbreviated month name. | |||
| - %B is replaced by the locale's full month name. | |||
| - %c is replaced by the locale's appropriate date and time representation. | |||
| - %d is replaced by the day of the month as a decimal number [01,31]. | |||
| - %H is replaced by the hour (24-hour clock) as a decimal number [00,23]. | |||
| - %I is replaced by the hour (12-hour clock) as a decimal number [01,12]. | |||
| - %j is replaced by the day of the year as a decimal number [001,366]. | |||
| - %m is replaced by the month as a decimal number [01,12]. | |||
| - %M is replaced by the minute as a decimal number [00,59]. | |||
| - %p is replaced by the locale's equivalent of either a.m. or p.m. | |||
| - %S is replaced by the second as a decimal number [00,61]. | |||
| - %U is replaced by the week number of the year (Sunday as the first day of the week) as a decimal number [00,53]. | |||
| - %w is replaced by the weekday as a decimal number [0,6], with 0 representing Sunday. | |||
| - %W is replaced by the week number of the year (Monday as the first day of the week) as a decimal number [00,53]. All days in a new year preceding the first Monday are considered to be in week 0. | |||
| - %x is replaced by the locale's appropriate date representation. | |||
| - %X is replaced by the locale's appropriate time representation. | |||
| - %y is replaced by the year without century as a decimal number [00,99]. | |||
| - %Y is replaced by the year with century as a decimal number. | |||
| - %Z is replaced by the timezone name or abbreviation, or by no bytes if no timezone information exists. | |||
| - %% is replaced by %. | |||
| @see toString | |||
| */ | |||
| String formatted (const String& format) const; | |||
| //============================================================================== | |||
| /** Returns a fully described string of this date and time in ISO-8601 format | |||
| (using the local timezone). | |||
| @param includeDividerCharacters whether to include or omit the "-" and ":" | |||
| dividers in the string | |||
| */ | |||
| String toISO8601 (bool includeDividerCharacters) const; | |||
| /** Parses an ISO-8601 string and returns it as a Time. */ | |||
| static Time fromISO8601 (StringRef iso8601) noexcept; | |||
| //============================================================================== | |||
| /** Tries to set the computer's clock. | |||
| @returns true if this succeeds, although depending on the system, the | |||
| application might not have sufficient privileges to do this. | |||
| */ | |||
| bool setSystemTimeToThisTime() const; | |||
| //============================================================================== | |||
| /** Returns the name of a day of the week. | |||
| @param dayNumber the day, 0 to 6 (0 = sunday, 1 = monday, etc) | |||
| @param threeLetterVersion if true, it'll return a 3-letter abbreviation, e.g. "Tue"; if | |||
| false, it'll return the full version, e.g. "Tuesday". | |||
| */ | |||
| static String getWeekdayName (int dayNumber, bool threeLetterVersion); | |||
| /** Returns the name of one of the months. | |||
| @param monthNumber the month, 0 to 11 | |||
| @param threeLetterVersion if true, it'll be a 3-letter abbreviation, e.g. "Jan"; if false | |||
| it'll return the long form, e.g. "January" | |||
| */ | |||
| static String getMonthName (int monthNumber, bool threeLetterVersion); | |||
| //============================================================================== | |||
| // Static methods for getting system timers directly.. | |||
| /** Returns the current system time. | |||
| Returns the number of milliseconds since midnight Jan 1st 1970 UTC. | |||
| Should be accurate to within a few millisecs, depending on platform, | |||
| hardware, etc. | |||
| */ | |||
| static int64 currentTimeMillis() noexcept; | |||
| /** Returns the number of millisecs since a fixed event (usually system startup). | |||
| This returns a monotonically increasing value which it unaffected by changes to the | |||
| system clock. It should be accurate to within a few millisecs, depending on platform, | |||
| hardware, etc. | |||
| Being a 32-bit return value, it will of course wrap back to 0 after 2^32 seconds of | |||
| uptime, so be careful to take that into account. If you need a 64-bit time, you can | |||
| use currentTimeMillis() instead. | |||
| @see getApproximateMillisecondCounter | |||
| */ | |||
| static uint32 getMillisecondCounter() noexcept; | |||
| /** Returns the number of millisecs since a fixed event (usually system startup). | |||
| This has the same function as getMillisecondCounter(), but returns a more accurate | |||
| value, using a higher-resolution timer if one is available. | |||
| @see getMillisecondCounter | |||
| */ | |||
| static double getMillisecondCounterHiRes() noexcept; | |||
| /** Waits until the getMillisecondCounter() reaches a given value. | |||
| This will make the thread sleep as efficiently as it can while it's waiting. | |||
| */ | |||
| static void waitForMillisecondCounter (uint32 targetTime) noexcept; | |||
| /** Less-accurate but faster version of getMillisecondCounter(). | |||
| This will return the last value that getMillisecondCounter() returned, so doesn't | |||
| need to make a system call, but is less accurate - it shouldn't be more than | |||
| 100ms away from the correct time, though, so is still accurate enough for a | |||
| lot of purposes. | |||
| @see getMillisecondCounter | |||
| */ | |||
| static uint32 getApproximateMillisecondCounter() noexcept; | |||
| //============================================================================== | |||
| // High-resolution timers.. | |||
| /** Returns the current high-resolution counter's tick-count. | |||
| This is a similar idea to getMillisecondCounter(), but with a higher | |||
| resolution. | |||
| @see getHighResolutionTicksPerSecond, highResolutionTicksToSeconds, | |||
| secondsToHighResolutionTicks | |||
| */ | |||
| static int64 getHighResolutionTicks() noexcept; | |||
| /** Returns the resolution of the high-resolution counter in ticks per second. | |||
| @see getHighResolutionTicks, highResolutionTicksToSeconds, | |||
| secondsToHighResolutionTicks | |||
| */ | |||
| static int64 getHighResolutionTicksPerSecond() noexcept; | |||
| /** Converts a number of high-resolution ticks into seconds. | |||
| @see getHighResolutionTicks, getHighResolutionTicksPerSecond, | |||
| secondsToHighResolutionTicks | |||
| */ | |||
| static double highResolutionTicksToSeconds (int64 ticks) noexcept; | |||
| /** Converts a number seconds into high-resolution ticks. | |||
| @see getHighResolutionTicks, getHighResolutionTicksPerSecond, | |||
| highResolutionTicksToSeconds | |||
| */ | |||
| static int64 secondsToHighResolutionTicks (double seconds) noexcept; | |||
| /** Returns a Time based on the value of the __DATE__ macro when this module was compiled */ | |||
| static Time getCompilationDate(); | |||
| private: | |||
| //============================================================================== | |||
| int64 millisSinceEpoch; | |||
| }; | |||
| //============================================================================== | |||
| /** Compares two Time objects. */ | |||
| JUCE_API bool operator== (Time time1, Time time2) noexcept; | |||
| /** Compares two Time objects. */ | |||
| JUCE_API bool operator!= (Time time1, Time time2) noexcept; | |||
| /** Compares two Time objects. */ | |||
| JUCE_API bool operator< (Time time1, Time time2) noexcept; | |||
| /** Compares two Time objects. */ | |||
| JUCE_API bool operator<= (Time time1, Time time2) noexcept; | |||
| /** Compares two Time objects. */ | |||
| JUCE_API bool operator> (Time time1, Time time2) noexcept; | |||
| /** Compares two Time objects. */ | |||
| JUCE_API bool operator>= (Time time1, Time time2) noexcept; | |||
| #endif // JUCE_TIME_H_INCLUDED | |||
| @@ -124,29 +124,17 @@ XmlElement* XmlDocument::getDocumentElement (const bool onlyReadOuterDocumentEle | |||
| MemoryOutputStream data; | |||
| data.writeFromInputStream (*in, onlyReadOuterDocumentElement ? 8192 : -1); | |||
| #if JUCE_STRING_UTF_TYPE == 8 | |||
| if (data.getDataSize() > 2) | |||
| { | |||
| data.writeByte (0); | |||
| const char* text = static_cast<const char*> (data.getData()); | |||
| if (CharPointer_UTF16::isByteOrderMarkBigEndian (text) | |||
| || CharPointer_UTF16::isByteOrderMarkLittleEndian (text)) | |||
| { | |||
| originalText = data.toString(); | |||
| } | |||
| else | |||
| { | |||
| if (CharPointer_UTF8::isByteOrderMark (text)) | |||
| text += 3; | |||
| if (CharPointer_UTF8::isByteOrderMark (text)) | |||
| text += 3; | |||
| // parse the input buffer directly to avoid copying it all to a string.. | |||
| return parseDocumentElement (String::CharPointerType (text), onlyReadOuterDocumentElement); | |||
| } | |||
| // parse the input buffer directly to avoid copying it all to a string.. | |||
| return parseDocumentElement (String::CharPointerType (text), onlyReadOuterDocumentElement); | |||
| } | |||
| #else | |||
| originalText = data.toString(); | |||
| #endif | |||
| } | |||
| } | |||
| @@ -734,9 +722,7 @@ void XmlDocument::readEntity (String& result) | |||
| return; | |||
| } | |||
| #if 0 // FIXME | |||
| result << (juce_wchar) charCode; | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| @@ -53,7 +53,7 @@ | |||
| */ | |||
| #define forEachXmlChildElement(parentXmlElement, childElementVariableName) \ | |||
| \ | |||
| for (juce::XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \ | |||
| for (juce2::XmlElement* childElementVariableName = (parentXmlElement).getFirstChildElement(); \ | |||
| childElementVariableName != nullptr; \ | |||
| childElementVariableName = childElementVariableName->getNextElement()) | |||
| @@ -82,7 +82,7 @@ | |||
| */ | |||
| #define forEachXmlChildElementWithTagName(parentXmlElement, childElementVariableName, requiredTagName) \ | |||
| \ | |||
| for (juce::XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \ | |||
| for (juce2::XmlElement* childElementVariableName = (parentXmlElement).getChildByName (requiredTagName); \ | |||
| childElementVariableName != nullptr; \ | |||
| childElementVariableName = childElementVariableName->getNextElementWithTagName (requiredTagName)) | |||
| @@ -22,7 +22,7 @@ | |||
| #include "CarlaMutex.hpp" | |||
| #include "CarlaString.hpp" | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -20,10 +20,9 @@ | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaNativeExtUI.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce::roundToIntAccurate; | |||
| using juce2::roundToIntAccurate; | |||
| // ----------------------------------------------------------------------- | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-3bandeq/DistrhoArtwork3BandEQ.cpp" | |||
| #include "distrho-3bandeq/DistrhoPlugin3BandEQ.cpp" | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-3bandsplitter/DistrhoArtwork3BandSplitter.cpp" | |||
| #include "distrho-3bandsplitter/DistrhoPlugin3BandSplitter.cpp" | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-kars/DistrhoArtworkKars.cpp" | |||
| #include "distrho-kars/DistrhoPluginKars.cpp" | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-nekobi/DistrhoArtworkNekobi.cpp" | |||
| #include "distrho-nekobi/DistrhoPluginNekobi.cpp" | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-pingpongpan/DistrhoArtworkPingPongPan.cpp" | |||
| #include "distrho-pingpongpan/DistrhoPluginPingPongPan.cpp" | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -15,6 +15,7 @@ | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-prom/DistrhoPluginProM.cpp" | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-vectorjuice/VectorJuicePlugin.cpp" | |||
| #ifdef HAVE_DGL | |||
| @@ -1,6 +1,6 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * Copyright (C) 2012-2017 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| @@ -23,6 +23,8 @@ | |||
| # define DISTRHO_PLUGIN_HAS_UI 0 | |||
| #endif | |||
| #include "CarlaJuceUtils.hpp" | |||
| // Plugin Code | |||
| #include "distrho-wobblejuice/WobbleJuiceArtwork.cpp" | |||
| #include "distrho-wobblejuice/WobbleJuicePlugin.cpp" | |||
| @@ -18,8 +18,7 @@ | |||
| #include "CarlaNative.hpp" | |||
| #include "midi-base.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #if 0 | |||
| // ----------------------------------------------------------------------- | |||
| @@ -143,7 +142,7 @@ private: | |||
| { | |||
| fMidiOut.clear(); | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| const String jfilename = String(CharPointer_UTF8(filename)); | |||
| File file(jfilename); | |||
| @@ -17,15 +17,13 @@ | |||
| #include "CarlaNativeExtUI.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "distrho/extra/ScopedPointer.hpp" | |||
| #include "zita-at1/jclient.cc" | |||
| #include "zita-at1/retuner.cc" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce::roundToIntAccurate; | |||
| using juce2::roundToIntAccurate; | |||
| using namespace AT1; | |||
| @@ -17,7 +17,6 @@ | |||
| #include "CarlaNativeExtUI.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "distrho/extra/ScopedPointer.hpp" | |||
| #include "zita-bls1/hp3filt.cc" | |||
| #include "zita-bls1/jclient.cc" | |||
| @@ -17,7 +17,6 @@ | |||
| #include "CarlaNativeExtUI.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "distrho/extra/ScopedPointer.hpp" | |||
| #include "zita-rev1/jclient.cc" | |||
| #include "zita-rev1/pareq.cc" | |||
| @@ -45,10 +45,9 @@ | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce::roundToIntAccurate; | |||
| using juce2::roundToIntAccurate; | |||
| using namespace zyncarla; | |||
| @@ -21,7 +21,6 @@ | |||
| #include "LinkedList.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "distrho/extra/ScopedPointer.hpp" | |||
| #include <ctime> | |||
| #include <set> | |||
| @@ -50,10 +49,9 @@ | |||
| # pragma GCC diagnostic pop | |||
| #endif | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| using juce::roundToIntAccurate; | |||
| using juce2::roundToIntAccurate; | |||
| using namespace zyncarla; | |||
| @@ -50,7 +50,7 @@ endif | |||
| LIBS = $(MODULEDIR)/carla_engine_plugin.a | |||
| LIBS += $(MODULEDIR)/carla_plugin.a | |||
| LIBS += $(MODULEDIR)/jackbridge.a | |||
| LIBS += $(MODULEDIR)/juce_core.a | |||
| LIBS += $(MODULEDIR)/juce_audio_graph.a | |||
| LIBS += $(MODULEDIR)/lilv.a | |||
| LIBS += $(MODULEDIR)/native-plugins.a | |||
| LIBS += $(MODULEDIR)/rtmempool.a | |||
| @@ -18,8 +18,7 @@ | |||
| #define CARLA_NATIVE_PLUGIN_LV2 | |||
| #include "carla-base.cpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #include "lv2/atom.h" | |||
| #include "lv2/buf-size.h" | |||
| @@ -45,9 +44,9 @@ | |||
| # define PLUGIN_EXT ".so" | |||
| #endif | |||
| using juce::String; | |||
| using juce::StringArray; | |||
| using juce::juce_wchar; | |||
| using juce2::String; | |||
| using juce2::StringArray; | |||
| using juce2::juce_wchar; | |||
| // ----------------------------------------------------------------------- | |||
| // Converts a parameter name to an LV2 compatible symbol | |||
| @@ -24,8 +24,7 @@ | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| #include "vestige/aeffectx.h" | |||
| #define effFlagsProgramChunks (1 << 5) | |||
| @@ -73,8 +72,8 @@ public: | |||
| fHost.uiParentId = 0; | |||
| // find resource dir | |||
| using juce::File; | |||
| using juce::String; | |||
| using juce2::File; | |||
| using juce2::String; | |||
| File curExe = File::getSpecialLocation(File::currentExecutableFile).getLinkedTarget(); | |||
| File resDir = curExe.getSiblingFile("carla-resources"); | |||
| @@ -22,8 +22,8 @@ | |||
| #include "CarlaUtils.hpp" | |||
| #if defined(CARLA_OS_WIN) | |||
| # include "AppConfig.h" | |||
| # include "juce_core/juce_core.h" | |||
| # include "CarlaJuceUtils.hpp" | |||
| # include "juce_audio_graph/juce_audio_graph.h" | |||
| #elif defined(HAVE_LIBMAGIC) | |||
| # include <magic.h> | |||
| #endif | |||
| @@ -76,9 +76,8 @@ BinaryType getBinaryTypeFromFile(const char* const filename) | |||
| return BINARY_NATIVE; | |||
| #if defined(CARLA_OS_WIN) | |||
| using juce::File; | |||
| using juce::FileInputStream; | |||
| using juce::ScopedPointer; | |||
| using juce2::File; | |||
| using juce2::FileInputStream; | |||
| ScopedPointer<FileInputStream> stream(File(filename).createInputStream()); | |||
| CARLA_SAFE_ASSERT_RETURN(stream != nullptr || stream->failedToOpen(), BINARY_NATIVE); | |||
| @@ -17,8 +17,7 @@ | |||
| #include "CarlaDssiUtils.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| // -------------------------------------------------------------------------------------------------------------------- | |||
| @@ -29,7 +28,7 @@ const char* find_dssi_ui(const char* const filename, const char* const label) no | |||
| carla_debug("find_dssi_ui(\"%s\", \"%s\")", filename, label); | |||
| try { | |||
| using namespace juce; | |||
| using namespace juce2; | |||
| String guiFilename; | |||
| String pluginDir(String(filename).upToLastOccurrenceOf(".", false, false)); | |||
| @@ -18,8 +18,15 @@ | |||
| #ifndef CARLA_JUCE_UTILS_HPP_INCLUDED | |||
| #define CARLA_JUCE_UTILS_HPP_INCLUDED | |||
| #define DISTRHO_LEAK_DETECTOR_HPP_INCLUDED | |||
| #define DISTRHO_SCOPED_POINTER_HPP_INCLUDED | |||
| #define DISTRHO_LEAK_DETECTOR CARLA_LEAK_DETECTOR | |||
| #define DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR | |||
| #include "CarlaUtils.hpp" | |||
| #include <algorithm> | |||
| /** A good old-fashioned C macro concatenation helper. | |||
| This combines two items (which may themselves be macros) into a single string, | |||
| avoiding the pitfalls of the ## macro operator. | |||
| @@ -138,6 +145,184 @@ private: | |||
| } | |||
| }; | |||
| //===================================================================================================================== | |||
| /** | |||
| This class holds a pointer which is automatically deleted when this object goes | |||
| out of scope. | |||
| Once a pointer has been passed to a ScopedPointer, it will make sure that the pointer | |||
| gets deleted when the ScopedPointer is deleted. Using the ScopedPointer on the stack or | |||
| as member variables is a good way to use RAII to avoid accidentally leaking dynamically | |||
| created objects. | |||
| A ScopedPointer can be used in pretty much the same way that you'd use a normal pointer | |||
| to an object. If you use the assignment operator to assign a different object to a | |||
| ScopedPointer, the old one will be automatically deleted. | |||
| A const ScopedPointer is guaranteed not to lose ownership of its object or change the | |||
| object to which it points during its lifetime. This means that making a copy of a const | |||
| ScopedPointer is impossible, as that would involve the new copy taking ownership from the | |||
| old one. | |||
| If you need to get a pointer out of a ScopedPointer without it being deleted, you | |||
| can use the release() method. | |||
| Something to note is the main difference between this class and the std::auto_ptr class, | |||
| which is that ScopedPointer provides a cast-to-object operator, wheras std::auto_ptr | |||
| requires that you always call get() to retrieve the pointer. The advantages of providing | |||
| the cast is that you don't need to call get(), so can use the ScopedPointer in pretty much | |||
| exactly the same way as a raw pointer. The disadvantage is that the compiler is free to | |||
| use the cast in unexpected and sometimes dangerous ways - in particular, it becomes difficult | |||
| to return a ScopedPointer as the result of a function. To avoid this causing errors, | |||
| ScopedPointer contains an overloaded constructor that should cause a syntax error in these | |||
| circumstances, but it does mean that instead of returning a ScopedPointer from a function, | |||
| you'd need to return a raw pointer (or use a std::auto_ptr instead). | |||
| */ | |||
| template<class ObjectType> | |||
| class ScopedPointer | |||
| { | |||
| public: | |||
| //================================================================================================================= | |||
| /** Creates a ScopedPointer containing a null pointer. */ | |||
| ScopedPointer() noexcept | |||
| : object(nullptr) {} | |||
| /** Creates a ScopedPointer that owns the specified object. */ | |||
| ScopedPointer(ObjectType* const objectToTakePossessionOf) noexcept | |||
| : object(objectToTakePossessionOf) {} | |||
| /** Creates a ScopedPointer that takes its pointer from another ScopedPointer. | |||
| Because a pointer can only belong to one ScopedPointer, this transfers | |||
| the pointer from the other object to this one, and the other object is reset to | |||
| be a null pointer. | |||
| */ | |||
| ScopedPointer(ScopedPointer& objectToTransferFrom) noexcept | |||
| : object(objectToTransferFrom.object) | |||
| { | |||
| objectToTransferFrom.object = nullptr; | |||
| } | |||
| /** Destructor. | |||
| This will delete the object that this ScopedPointer currently refers to. | |||
| */ | |||
| ~ScopedPointer() | |||
| { | |||
| delete object; | |||
| } | |||
| /** Changes this ScopedPointer to point to a new object. | |||
| Because a pointer can only belong to one ScopedPointer, this transfers | |||
| the pointer from the other object to this one, and the other object is reset to | |||
| be a null pointer. | |||
| If this ScopedPointer already points to an object, that object | |||
| will first be deleted. | |||
| */ | |||
| ScopedPointer& operator=(ScopedPointer& objectToTransferFrom) | |||
| { | |||
| if (this != objectToTransferFrom.getAddress()) | |||
| { | |||
| // Two ScopedPointers should never be able to refer to the same object - if | |||
| // this happens, you must have done something dodgy! | |||
| CARLA_SAFE_ASSERT_RETURN(object == nullptr || object != objectToTransferFrom.object, *this); | |||
| ObjectType* const oldObject = object; | |||
| object = objectToTransferFrom.object; | |||
| objectToTransferFrom.object = nullptr; | |||
| delete oldObject; | |||
| } | |||
| return *this; | |||
| } | |||
| /** Changes this ScopedPointer to point to a new object. | |||
| If this ScopedPointer already points to an object, that object | |||
| will first be deleted. | |||
| The pointer that you pass in may be a nullptr. | |||
| */ | |||
| ScopedPointer& operator=(ObjectType* const newObjectToTakePossessionOf) | |||
| { | |||
| if (object != newObjectToTakePossessionOf) | |||
| { | |||
| ObjectType* const oldObject = object; | |||
| object = newObjectToTakePossessionOf; | |||
| delete oldObject; | |||
| } | |||
| return *this; | |||
| } | |||
| //================================================================================================================= | |||
| /** Returns the object that this ScopedPointer refers to. */ | |||
| operator ObjectType*() const noexcept { return object; } | |||
| /** Returns the object that this ScopedPointer refers to. */ | |||
| ObjectType* get() const noexcept { return object; } | |||
| /** Returns the object that this ScopedPointer refers to. */ | |||
| ObjectType& operator*() const noexcept { return *object; } | |||
| /** Lets you access methods and properties of the object that this ScopedPointer refers to. */ | |||
| ObjectType* operator->() const noexcept { return object; } | |||
| //================================================================================================================= | |||
| /** Removes the current object from this ScopedPointer without deleting it. | |||
| This will return the current object, and set the ScopedPointer to a null pointer. | |||
| */ | |||
| ObjectType* release() noexcept { ObjectType* const o = object; object = nullptr; return o; } | |||
| //================================================================================================================= | |||
| /** Swaps this object with that of another ScopedPointer. | |||
| The two objects simply exchange their pointers. | |||
| */ | |||
| void swapWith(ScopedPointer<ObjectType>& other) noexcept | |||
| { | |||
| // Two ScopedPointers should never be able to refer to the same object - if | |||
| // this happens, you must have done something dodgy! | |||
| CARLA_SAFE_ASSERT_RETURN(object != other.object || this == other.getAddress() || object == nullptr,); | |||
| std::swap(object, other.object); | |||
| } | |||
| private: | |||
| //================================================================================================================= | |||
| ObjectType* object; | |||
| // (Required as an alternative to the overloaded & operator). | |||
| const ScopedPointer* getAddress() const noexcept { return this; } | |||
| #ifdef CARLA_PROPER_CPP11_SUPPORT | |||
| ScopedPointer(const ScopedPointer&) = delete; | |||
| ScopedPointer& operator=(const ScopedPointer&) = delete; | |||
| #else | |||
| ScopedPointer(const ScopedPointer&); | |||
| ScopedPointer& operator=(const ScopedPointer&); | |||
| #endif | |||
| }; | |||
| //===================================================================================================================== | |||
| /** Compares a ScopedPointer with another pointer. | |||
| This can be handy for checking whether this is a null pointer. | |||
| */ | |||
| template<class ObjectType> | |||
| bool operator==(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept | |||
| { | |||
| return static_cast<ObjectType*>(pointer1) == pointer2; | |||
| } | |||
| /** Compares a ScopedPointer with another pointer. | |||
| This can be handy for checking whether this is a null pointer. | |||
| */ | |||
| template<class ObjectType> | |||
| bool operator!=(const ScopedPointer<ObjectType>& pointer1, ObjectType* const pointer2) noexcept | |||
| { | |||
| return static_cast<ObjectType*>(pointer1) != pointer2; | |||
| } | |||
| //===================================================================================================================== | |||
| /** | |||
| Helper class providing an RAII-based mechanism for temporarily setting and | |||
| @@ -82,8 +82,7 @@ | |||
| #ifdef USE_QT | |||
| # include <QtCore/QStringList> | |||
| #else | |||
| # include "AppConfig.h" | |||
| # include "juce_core/juce_core.h" | |||
| # include "juce_audio_graph/juce_audio_graph.h" | |||
| #endif | |||
| // used for scalepoint sorting | |||
| @@ -659,7 +658,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets) | |||
| rdfDescriptor->UniqueID = uniqueId; | |||
| } | |||
| #else | |||
| const juce::String replaceURI(replaceNode.as_uri()); | |||
| const juce2::String replaceURI(replaceNode.as_uri()); | |||
| if (replaceURI.startsWith("urn:")) | |||
| { | |||
| @@ -1199,13 +1198,13 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets) | |||
| rdfDescriptor->PresetCount = static_cast<uint32_t>(presetListURIs.count()); | |||
| #else | |||
| juce::StringArray presetListURIs; | |||
| juce2::StringArray presetListURIs; | |||
| LILV_FOREACH(nodes, it, presetNodes) | |||
| { | |||
| Lilv::Node presetNode(presetNodes.get(it)); | |||
| juce::String presetURI(presetNode.as_uri()); | |||
| juce2::String presetURI(presetNode.as_uri()); | |||
| if (presetURI.trim().isNotEmpty()) | |||
| presetListURIs.addIfNotAlreadyThere(presetURI); | |||
| @@ -1246,7 +1245,7 @@ const LV2_RDF_Descriptor* lv2_rdf_new(const LV2_URI uri, const bool loadPresets) | |||
| #ifdef USE_QT | |||
| const int index(presetListURIs.indexOf(QString(presetURI))); | |||
| #else | |||
| const int index(presetListURIs.indexOf(juce::String(presetURI))); | |||
| const int index(presetListURIs.indexOf(juce2::String(presetURI))); | |||
| #endif | |||
| CARLA_SAFE_ASSERT_CONTINUE(index >= 0 && index < static_cast<int>(rdfDescriptor->PresetCount)); | |||
| @@ -36,8 +36,7 @@ | |||
| #include <fcntl.h> | |||
| #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) | |||
| # include "AppConfig.h" | |||
| # include "juce_core/juce_core.h" | |||
| # include "juce_audio_graph/juce_audio_graph.h" | |||
| #else | |||
| # include <cerrno> | |||
| # include <signal.h> | |||
| @@ -99,7 +98,7 @@ static inline | |||
| uint32_t getMillisecondCounter() noexcept | |||
| { | |||
| #if defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN) | |||
| return juce::Time::getMillisecondCounter(); | |||
| return juce2::Time::getMillisecondCounter(); | |||
| #else | |||
| uint32_t now; | |||
| timespec t; | |||
| @@ -132,7 +131,7 @@ bool startProcess(const char* const argv[], PROCESS_INFORMATION* const processIn | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(processInfo != nullptr, false); | |||
| using juce::String; | |||
| using juce2::String; | |||
| String command; | |||
| @@ -140,23 +139,25 @@ bool startProcess(const char* const argv[], PROCESS_INFORMATION* const processIn | |||
| { | |||
| String arg(argv[i]); | |||
| #if 0 // FIXME | |||
| // If there are spaces, surround it with quotes. If there are quotes, | |||
| // replace them with \" so that CommandLineToArgv will correctly parse them. | |||
| if (arg.containsAnyOf("\" ")) | |||
| arg = arg.replace("\"", "\\\"").quoted(); | |||
| #endif | |||
| command << arg << ' '; | |||
| } | |||
| command = command.trim(); | |||
| STARTUPINFOW startupInfo; | |||
| STARTUPINFO startupInfo; | |||
| carla_zeroStruct(startupInfo); | |||
| startupInfo.cb = sizeof(STARTUPINFOW); | |||
| startupInfo.cb = sizeof(startupInfo); | |||
| return CreateProcessW(nullptr, const_cast<LPWSTR>(command.toWideCharPointer()), | |||
| nullptr, nullptr, FALSE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, | |||
| nullptr, nullptr, &startupInfo, processInfo) != FALSE; | |||
| return CreateProcess(nullptr, const_cast<LPSTR>(command.toRawUTF8()), | |||
| nullptr, nullptr, FALSE, CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT, | |||
| nullptr, nullptr, &startupInfo, processInfo) != FALSE; | |||
| } | |||
| static inline | |||
| @@ -23,9 +23,9 @@ | |||
| #include <string> | |||
| using juce::MemoryOutputStream; | |||
| using juce::String; | |||
| using juce::XmlElement; | |||
| using juce2::MemoryOutputStream; | |||
| using juce2::String; | |||
| using juce2::XmlElement; | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -509,7 +509,7 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const | |||
| case PLUGIN_LADSPA: | |||
| infoXml << " <Binary>" << xmlSafeString(binary, true) << "</Binary>\n"; | |||
| infoXml << " <Label>" << xmlSafeString(label, true) << "</Label>\n"; | |||
| infoXml << " <UniqueID>" << juce::int64(uniqueId) << "</UniqueID>\n"; | |||
| infoXml << " <UniqueID>" << juce2::int64(uniqueId) << "</UniqueID>\n"; | |||
| break; | |||
| case PLUGIN_DSSI: | |||
| infoXml << " <Binary>" << xmlSafeString(binary, true) << "</Binary>\n"; | |||
| @@ -520,7 +520,7 @@ void CarlaStateSave::dumpToMemoryStream(MemoryOutputStream& content) const | |||
| break; | |||
| case PLUGIN_VST2: | |||
| infoXml << " <Binary>" << xmlSafeString(binary, true) << "</Binary>\n"; | |||
| infoXml << " <UniqueID>" << juce::int64(uniqueId) << "</UniqueID>\n"; | |||
| infoXml << " <UniqueID>" << juce2::int64(uniqueId) << "</UniqueID>\n"; | |||
| break; | |||
| case PLUGIN_GIG: | |||
| case PLUGIN_SF2: | |||
| @@ -21,8 +21,7 @@ | |||
| #include "CarlaBackend.h" | |||
| #include "LinkedList.hpp" | |||
| #include "AppConfig.h" | |||
| #include "juce_core/juce_core.h" | |||
| #include "juce_audio_graph/juce_audio_graph.h" | |||
| CARLA_BACKEND_START_NAMESPACE | |||
| @@ -94,16 +93,16 @@ struct CarlaStateSave { | |||
| ~CarlaStateSave() noexcept; | |||
| void clear() noexcept; | |||
| bool fillFromXmlElement(const juce::XmlElement* const xmlElement); | |||
| void dumpToMemoryStream(juce::MemoryOutputStream& stream) const; | |||
| bool fillFromXmlElement(const juce2::XmlElement* const xmlElement); | |||
| void dumpToMemoryStream(juce2::MemoryOutputStream& stream) const; | |||
| CARLA_DECLARE_NON_COPY_STRUCT(CarlaStateSave) | |||
| }; | |||
| static inline | |||
| juce::String xmlSafeString(const char* const cstring, const bool toXml) | |||
| juce2::String xmlSafeString(const char* const cstring, const bool toXml) | |||
| { | |||
| juce::String newString = juce::String(juce::CharPointer_UTF8(cstring)); | |||
| juce2::String newString = juce2::String(juce2::CharPointer_UTF8(cstring)); | |||
| if (toXml) | |||
| return newString.replace("&","&").replace("<","<").replace(">",">").replace("'","'").replace("\"","""); | |||
| @@ -112,9 +111,9 @@ juce::String xmlSafeString(const char* const cstring, const bool toXml) | |||
| } | |||
| static inline | |||
| juce::String xmlSafeString(const juce::String& string, const bool toXml) | |||
| juce2::String xmlSafeString(const juce2::String& string, const bool toXml) | |||
| { | |||
| juce::String newString(string); | |||
| juce2::String newString(string); | |||
| if (toXml) | |||
| return newString.replace("&","&").replace("<","<").replace(">",">").replace("'","'").replace("\"","""); | |||
| @@ -18,8 +18,8 @@ | |||
| #ifndef CARLA_STRING_HPP_INCLUDED | |||
| #define CARLA_STRING_HPP_INCLUDED | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include <algorithm> | |||