@@ -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> | |||