Browse Source

Update to latest juce; Use juce gui on separate thread; Misc stuff

tags/1.9.4
falkTX 11 years ago
parent
commit
6b259a0a98
100 changed files with 3564 additions and 1521 deletions
  1. +9
    -5
      source/Makefile.mk
  2. +7
    -1
      source/backend/CarlaHost.hpp
  3. +120
    -65
      source/backend/standalone/CarlaStandalone.cpp
  4. +7
    -6
      source/backend/standalone/Makefile
  5. +21
    -11
      source/bridges/CarlaBridgePlugin.cpp
  6. +9
    -10
      source/bridges/Makefile
  7. +2
    -2
      source/carla_database.py
  8. +2
    -2
      source/carla_patchbay.py
  9. +1
    -1
      source/carla_style.py
  10. +1
    -1
      source/includes/CarlaDefines.hpp
  11. +10
    -11
      source/modules/carla_native/vex-fx.cpp
  12. +11
    -13
      source/modules/carla_native/vex-synth.cpp
  13. +22
    -8
      source/modules/carla_native/vex/PeggyViewComponent.h
  14. +2
    -2
      source/modules/distrho/dgl/Base.hpp
  15. +3
    -12
      source/modules/distrho/dgl/Makefile
  16. +1
    -1
      source/modules/distrho/src/DistrhoDefines.h
  17. +3
    -0
      source/modules/jackbridge/JackBridge1.cpp
  18. +18
    -0
      source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
  19. +8
    -0
      source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
  20. +1
    -1
      source/modules/juce_audio_basics/effects/juce_Decibels.h
  21. +1
    -1
      source/modules/juce_audio_basics/juce_module_info
  22. +47
    -105
      source/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp
  23. +7
    -12
      source/modules/juce_audio_basics/midi/juce_MidiBuffer.h
  24. +28
    -26
      source/modules/juce_audio_basics/midi/juce_MidiFile.cpp
  25. +22
    -17
      source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp
  26. +16
    -11
      source/modules/juce_audio_basics/midi/juce_MidiMessage.h
  27. +1
    -1
      source/modules/juce_audio_devices/juce_module_info
  28. +85
    -61
      source/modules/juce_audio_devices/native/juce_ios_Audio.cpp
  29. +18
    -54
      source/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm
  30. +34
    -40
      source/modules/juce_audio_devices/native/juce_win32_ASIO.cpp
  31. +5
    -8
      source/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp
  32. +2
    -2
      source/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp
  33. +4
    -6
      source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp
  34. +5
    -10
      source/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp
  35. +2
    -7
      source/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp
  36. +18
    -20
      source/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp
  37. +17
    -19
      source/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp
  38. +7
    -14
      source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
  39. +7
    -4
      source/modules/juce_audio_formats/format/juce_AudioFormat.cpp
  40. +10
    -5
      source/modules/juce_audio_formats/format/juce_AudioFormat.h
  41. +12
    -12
      source/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp
  42. +3
    -3
      source/modules/juce_audio_formats/format/juce_AudioFormatWriter.h
  43. +1
    -1
      source/modules/juce_audio_formats/juce_module_info
  44. +3
    -1
      source/modules/juce_audio_processors/format/juce_AudioPluginFormat.h
  45. +7
    -19
      source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp
  46. +2
    -0
      source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h
  47. +1
    -1
      source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h
  48. +35
    -51
      source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
  49. +10
    -12
      source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp
  50. +10
    -10
      source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h
  51. +43
    -37
      source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
  52. +2
    -2
      source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h
  53. +1
    -1
      source/modules/juce_audio_processors/juce_module_info
  54. +57
    -41
      source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
  55. +6
    -6
      source/modules/juce_audio_processors/processors/juce_AudioProcessor.h
  56. +7
    -2
      source/modules/juce_audio_processors/processors/juce_PluginDescription.cpp
  57. +20
    -19
      source/modules/juce_audio_processors/processors/juce_PluginDescription.h
  58. +39
    -7
      source/modules/juce_core/containers/juce_Array.h
  59. +66
    -7
      source/modules/juce_core/containers/juce_DynamicObject.cpp
  60. +26
    -12
      source/modules/juce_core/containers/juce_DynamicObject.h
  61. +1
    -1
      source/modules/juce_core/containers/juce_NamedValueSet.h
  62. +21
    -4
      source/modules/juce_core/containers/juce_OwnedArray.h
  63. +42
    -28
      source/modules/juce_core/containers/juce_ReferenceCountedArray.h
  64. +5
    -4
      source/modules/juce_core/containers/juce_SortedSet.h
  65. +1
    -1
      source/modules/juce_core/containers/juce_SparseSet.h
  66. +197
    -132
      source/modules/juce_core/containers/juce_Variant.cpp
  67. +64
    -35
      source/modules/juce_core/containers/juce_Variant.h
  68. +11
    -17
      source/modules/juce_core/files/juce_File.cpp
  69. +5
    -2
      source/modules/juce_core/files/juce_File.h
  70. +98
    -77
      source/modules/juce_core/javascript/juce_JSON.cpp
  71. +7
    -1
      source/modules/juce_core/javascript/juce_JSON.h
  72. +1683
    -0
      source/modules/juce_core/javascript/juce_Javascript.cpp
  73. +106
    -0
      source/modules/juce_core/javascript/juce_Javascript.h
  74. +6
    -3
      source/modules/juce_core/juce_core.cpp
  75. +2
    -1
      source/modules/juce_core/juce_core.h
  76. +2
    -2
      source/modules/juce_core/juce_module_info
  77. +6
    -0
      source/modules/juce_core/maths/juce_BigInteger.cpp
  78. +6
    -1
      source/modules/juce_core/maths/juce_BigInteger.h
  79. +6
    -0
      source/modules/juce_core/maths/juce_MathsFunctions.h
  80. +7
    -2
      source/modules/juce_core/maths/juce_Random.cpp
  81. +5
    -0
      source/modules/juce_core/maths/juce_Random.h
  82. +15
    -11
      source/modules/juce_core/memory/juce_MemoryBlock.cpp
  83. +19
    -1
      source/modules/juce_core/misc/juce_Uuid.cpp
  84. +10
    -4
      source/modules/juce_core/misc/juce_Uuid.h
  85. +33
    -23
      source/modules/juce_core/native/java/JuceAppActivity.java
  86. +1
    -1
      source/modules/juce_core/native/juce_BasicNativeHeaders.h
  87. +2
    -140
      source/modules/juce_core/native/juce_android_Files.cpp
  88. +1
    -1
      source/modules/juce_core/native/juce_android_JNIHelpers.h
  89. +153
    -0
      source/modules/juce_core/native/juce_linux_CommonFile.cpp
  90. +9
    -143
      source/modules/juce_core/native/juce_linux_Files.cpp
  91. +24
    -35
      source/modules/juce_core/native/juce_linux_Network.cpp
  92. +17
    -8
      source/modules/juce_core/native/juce_mac_Files.mm
  93. +5
    -0
      source/modules/juce_core/native/juce_mac_Network.mm
  94. +16
    -7
      source/modules/juce_core/native/juce_posix_SharedCode.h
  95. +9
    -4
      source/modules/juce_core/native/juce_win32_Files.cpp
  96. +8
    -7
      source/modules/juce_core/native/juce_win32_Threads.cpp
  97. +1
    -1
      source/modules/juce_core/network/juce_URL.cpp
  98. +1
    -1
      source/modules/juce_core/network/juce_URL.h
  99. +1
    -2
      source/modules/juce_core/streams/juce_InputStream.cpp
  100. +13
    -2
      source/modules/juce_core/streams/juce_OutputStream.cpp

+ 9
- 5
source/Makefile.mk View File

@@ -4,8 +4,6 @@
# Created by falkTX
#

# libx11-dev libxext-dev libxinerama-dev libfreetype6-dev libxcursor-dev

# --------------------------------------------------------------
# Modify to enable/disable specific features

@@ -107,7 +105,6 @@ endif
# Check for optional libs (required by backend or bridges)

HAVE_FFMPEG = $(shell pkg-config --exists libavcodec libavformat libavutil && pkg-config --max-version=1.9 libavcodec && echo true)
HAVE_OPENGL = $(shell pkg-config --exists gl && echo true)

ifeq ($(LINUX),true)
HAVE_ALSA = $(shell pkg-config --exists alsa && echo true)
@@ -116,6 +113,9 @@ HAVE_GTK3 = $(shell pkg-config --exists gtk+-3.0 && echo true)
HAVE_PULSEAUDIO = $(shell pkg-config --exists libpulse-simple && echo true)
HAVE_QT4 = $(shell pkg-config --exists QtCore QtGui && echo true)
HAVE_QT5 = $(shell pkg-config --exists Qt5Core Qt5Gui Qt5Widgets && echo true)
HAVE_OPENGL = $(shell pkg-config --exists gl && echo true)
else
HAVE_OPENGL = true
endif

ifeq ($(CARLA_SAMPLERS_SUPPORT),true)
@@ -138,8 +138,10 @@ ifeq ($(HAIKU),true)
endif

ifeq ($(LINUX),true)
# JUCE_AUDIO_DEVICES_FLAGS = $(shell pkg-config --cflags alsa)
# JUCE_AUDIO_DEVICES_LIBS = $(shell pkg-config --libs alsa)
ifeq ($(HAVE_OPENGL),true)
DGL_FLAGS = $(shell pkg-config --cflags gl x11)
DGL_LIBS = $(shell pkg-config --libs gl x11)
endif
JUCE_CORE_LIBS = -lrt -ldl -lpthread
JUCE_EVENTS_FLAGS = $(shell pkg-config --cflags x11)
JUCE_EVENTS_LIBS = $(shell pkg-config --libs x11)
@@ -150,6 +152,7 @@ JUCE_GUI_BASICS_LIBS = $(shell pkg-config --libs x11 xinerama xext xcursor)
endif

ifeq ($(MACOS),true)
DGL_LIBS = -framework OpenGL -framework Cocoa
JUCE_AUDIO_BASICS_LIBS = -framework Accelerate
JUCE_AUDIO_DEVICES_LIBS = -framework CoreAudio -framework CoreMIDI -framework DiscRecording
JUCE_AUDIO_FORMATS_LIBS = -framework CoreAudio -framework CoreMIDI -framework QuartzCore -framework AudioToolbox
@@ -159,6 +162,7 @@ JUCE_GUI_BASICS_LIBS = -framework Cocoa -framework Carbon -framework QuartzCo
endif

ifeq ($(WIN32),true)
DGL_LIBS = -lopengl32 -lgdi32
JUCE_AUDIO_DEVICES_LIBS = -lwinmm -lole32
JUCE_CORE_LIBS = -luuid -lwsock32 -lwininet -lversion -lole32 -lws2_32 -loleaut32 -limm32 -lcomdlg32 -lshlwapi -lrpcrt4 -lwinmm
JUCE_EVENTS_LIBS = -lole32


+ 7
- 1
source/backend/CarlaHost.hpp View File

@@ -293,6 +293,13 @@ CARLA_EXPORT const CarlaNativePluginInfo* carla_get_internal_plugin_info(unsigne
*/
CARLA_EXPORT bool carla_engine_init(const char* driverName, const char* clientName);

#ifdef BUILD_BRIDGE
/*!
* Initialize the engine in bridged mode.
*/
CARLA_EXPORT bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName);
#endif

/*!
* Close the running engine.\n
* This function always closes the engine even if it returns false.\n
@@ -724,7 +731,6 @@ CARLA_EXPORT void carla_nsm_reply_save();
#ifdef BUILD_BRIDGE
using CarlaBackend::CarlaEngine;
CARLA_EXPORT CarlaEngine* carla_get_standalone_engine();
CARLA_EXPORT bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName);
#endif

/**@}*/


+ 120
- 65
source/backend/standalone/CarlaStandalone.cpp View File

@@ -41,7 +41,52 @@ using CB::CallbackFunc;
using CB::EngineOptions;
using CB::EngineTimeInfo;

using juce::MessageManager;
//using juce::MessageManager;

using namespace juce;

// -----------------------------------------------------------------------
// Juce Message Thread

class JuceMessageThread : public Thread
{
public:
JuceMessageThread()
: Thread("JuceMessageThread"),
fInitialised(false)
{
startThread(7);

while (! fInitialised)
sleep(1);
}

~JuceMessageThread()
{
signalThreadShouldExit();
JUCEApplication::quit();
waitForThreadToExit(5000);
clearSingletonInstance();
}

void run()
{
initialiseJuce_GUI();
fInitialised = true;

MessageManager::getInstance()->setCurrentThreadAsMessageThread();

while ((! threadShouldExit()) && MessageManager::getInstance()->runDispatchLoopUntil(250))
{}
}

juce_DeclareSingleton(JuceMessageThread, false);

private:
bool fInitialised;
};

juce_ImplementSingleton(JuceMessageThread)

// -------------------------------------------------------------------------------------------------------------------
// Single, standalone engine
@@ -61,14 +106,33 @@ struct CarlaBackendStandalone {
~CarlaBackendStandalone()
{
CARLA_ASSERT(engine == nullptr);
CARLA_ASSERT(MessageManager::getInstanceWithoutCreating() == nullptr);
//CARLA_ASSERT(MessageManager::getInstanceWithoutCreating() == nullptr);
}

#if 1
void init()
{
JUCE_AUTORELEASEPOOL

initialiseJuce_GUI();
JuceMessageThread::getInstance();
}

void idle() {}

void close()
{
JUCE_AUTORELEASEPOOL

JuceMessageThread::deleteInstance();
shutdownJuce_GUI();
}
#else
void init()
{
juce::initialiseJuce_GUI();

if (MessageManager* const mgr = MessageManager::getInstanceWithoutCreating())
if (MessageManager* const mgr = MessageManager::getInstance())
mgr->setCurrentThreadAsMessageThread();
}

@@ -85,6 +149,7 @@ struct CarlaBackendStandalone {

juce::shutdownJuce_GUI();
}
#endif

CARLA_DECLARE_NON_COPY_STRUCT(CarlaBackendStandalone)
};
@@ -333,19 +398,6 @@ bool carla_engine_init(const char* driverName, const char* clientName)
return false;
}

#if 0 //def DEBUG
static bool firstInit = true;

if (firstInit)
{
firstInit = false;

if (gStandalone.callback != nullptr)
gStandalone.callback(gStandalone.callbackPtr, CB::CALLBACK_DEBUG, 0, 0, 0, 0.0f,
"Debug builds don't use this, please check the console instead.");
}
#endif

#ifdef Q_OS_WIN
carla_setenv("WINEASIO_CLIENT_NAME", clientName);
#endif
@@ -422,6 +474,58 @@ bool carla_engine_init(const char* driverName, const char* clientName)
}
}

#ifdef BUILD_BRIDGE
bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName)
{
CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(controlBaseName != nullptr && controlBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
carla_debug("carla_engine_init_bridge(\"%s\", %s, %s)", audioBaseName, controlBaseName, clientName);

if (gStandalone.engine != nullptr)
{
carla_stderr2("Engine is already running");
gStandalone.lastError = "Engine is already running";
return false;
}

gStandalone.engine = CarlaEngine::newBridge(audioBaseName, controlBaseName);

if (gStandalone.engine == nullptr)
{
carla_stderr2("The seleted audio driver is not available!");
gStandalone.lastError = "The seleted audio driver is not available!";
return false;
}

if (gStandalone.callback != nullptr)
gStandalone.engine->setCallback(gStandalone.callback, gStandalone.callbackPtr);

gStandalone.engine->setOption(CB::OPTION_PROCESS_MODE, CB::PROCESS_MODE_BRIDGE, nullptr);
gStandalone.engine->setOption(CB::OPTION_TRANSPORT_MODE, CB::TRANSPORT_MODE_BRIDGE, nullptr);
gStandalone.engine->setOption(CB::OPTION_FORCE_STEREO, false, nullptr);
gStandalone.engine->setOption(CB::OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr);
gStandalone.engine->setOption(CB::OPTION_PREFER_UI_BRIDGES, false, nullptr);
//gStandalone.engine->setOption(CB::OPTION_UIS_ALWAYS_ON_TOP, gStandalone.options.uisAlwaysOnTop ? 1 : 0, nullptr);
//gStandalone.engine->setOption(CB::OPTION_MAX_PARAMETERS, static_cast<int>(gStandalone.options.maxParameters), nullptr);
//gStandalone.engine->setOption(CB::OPTION_UI_BRIDGES_TIMEOUT, static_cast<int>(gStandalone.options.uiBridgesTimeout), nullptr);

if (gStandalone.engine->init(clientName))
{
gStandalone.lastError = "no error";
gStandalone.init();
return true;
}
else
{
gStandalone.lastError = gStandalone.engine->getLastError();
delete gStandalone.engine;
gStandalone.engine = nullptr;
return false;
}
}
#endif

bool carla_engine_close()
{
carla_debug("carla_engine_close()");
@@ -2120,53 +2224,4 @@ CarlaEngine* carla_get_standalone_engine()
{
return gStandalone.engine;
}

bool carla_engine_init_bridge(const char* audioBaseName, const char* controlBaseName, const char* clientName)
{
CARLA_SAFE_ASSERT_RETURN(gStandalone.engine == nullptr, false);
CARLA_SAFE_ASSERT_RETURN(audioBaseName != nullptr && audioBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(controlBaseName != nullptr && controlBaseName[0] != '\0', false);
CARLA_SAFE_ASSERT_RETURN(clientName != nullptr && clientName[0] != '\0', false);
carla_debug("carla_engine_init_bridge(\"%s\", \"%s\", \"%s\")", audioBaseName, controlBaseName, clientName);

gStandalone.engine = CarlaEngine::newBridge(audioBaseName, controlBaseName);

if (gStandalone.engine == nullptr)
{
carla_stderr2("The seleted audio driver is not available!");
gStandalone.lastError = "The seleted audio driver is not available!";
return false;
}

if (gStandalone.callback != nullptr)
gStandalone.engine->setCallback(gStandalone.callback, gStandalone.callbackPtr);

gStandalone.engine->setOption(CB::OPTION_PROCESS_MODE, CB::PROCESS_MODE_BRIDGE, nullptr);
gStandalone.engine->setOption(CB::OPTION_TRANSPORT_MODE, CB::TRANSPORT_MODE_BRIDGE, nullptr);
gStandalone.engine->setOption(CB::OPTION_PREFER_PLUGIN_BRIDGES, false, nullptr);
gStandalone.engine->setOption(CB::OPTION_PREFER_UI_BRIDGES, false, nullptr);

// TODO - read from environment
#if 0
gStandalone.engine->setOption(CB::OPTION_FORCE_STEREO, gStandalone.options.forceStereo ? 1 : 0, nullptr);
# ifdef WANT_DSSI
gStandalone.engine->setOption(CB::OPTION_USE_DSSI_VST_CHUNKS, gStandalone.options.useDssiVstChunks ? 1 : 0, nullptr);
# endif
gStandalone.engine->setOption(CB::OPTION_MAX_PARAMETERS, static_cast<int>(gStandalone.options.maxParameters), nullptr);
#endif

if (gStandalone.engine->init(clientName))
{
gStandalone.lastError = "no error";
gStandalone.init();
return true;
}
else
{
gStandalone.lastError = gStandalone.engine->getLastError();
delete gStandalone.engine;
gStandalone.engine = nullptr;
return false;
}
}
#endif

+ 7
- 6
source/backend/standalone/Makefile View File

@@ -13,6 +13,9 @@ BUILD_CXX_FLAGS += $(shell pkg-config --cflags liblo)
# --------------------------------------------------------------
# Common

LIBS = ../libcarla_engine.a
LIBS += ../libcarla_plugin.a

LINK_FLAGS += $(shell pkg-config --libs liblo)
LINK_FLAGS += -lpthread

@@ -65,10 +68,6 @@ ifeq ($(HAVE_MF_DEPS),true)
LINK_FLAGS += $(shell pkg-config --libs smf)
endif

ifeq ($(HAVE_OPENGL),true)
LINK_FLAGS += $(shell pkg-config --libs gl)
endif

ifeq ($(HAVE_ZYN_DEPS),true)
LINK_FLAGS += $(shell pkg-config --libs fftw3 mxml zlib)
ifeq ($(HAVE_ZYN_UI_DEPS),true)
@@ -76,10 +75,12 @@ LINK_FLAGS += $(shell pkg-config --libs ntk_images ntk)
endif
endif

ifeq ($(HAVE_OPENGL),true)
LINK_FLAGS += $(DGL_LIBS)
endif

# --------------------------------------------------------------

LIBS = ../libcarla_engine.a
LIBS += ../libcarla_plugin.a
LIBS += ../../modules/carla_native.a
LIBS += ../../modules/juce_audio_basics.a
LIBS += ../../modules/juce_core.a


+ 21
- 11
source/bridges/CarlaBridgePlugin.cpp View File

@@ -38,7 +38,7 @@ static volatile bool gCloseNow = false;
static volatile bool gSaveNow = false;

#ifdef CARLA_OS_WIN
BOOL WINAPI closeSignalHandler(DWORD dwCtrlType)
BOOL WINAPI winSignalHandler(DWORD dwCtrlType)
{
if (dwCtrlType == CTRL_C_EVENT)
{
@@ -62,7 +62,7 @@ static void saveSignalHandler(int)
void initSignalHandler()
{
#ifdef CARLA_OS_WIN
SetConsoleCtrlHandler(closeSignalHandler, TRUE);
SetConsoleCtrlHandler(winSignalHandler, TRUE);
#elif defined(CARLA_OS_LINUX) || defined(CARLA_OS_HAIKU)
struct sigaction sint;
struct sigaction sterm;
@@ -106,7 +106,7 @@ public:
fEngine(nullptr),
fPlugin(nullptr)
{
CARLA_ASSERT(driverName != nullptr);
CARLA_ASSERT(driverName != nullptr && driverName[0] != '\0');
carla_debug("CarlaPluginClient::CarlaPluginClient(%s, \"%s\", %s, %s)", bool2str(useBridge), driverName, audioBaseName, controlBaseName);

carla_set_engine_callback(callback, this);
@@ -124,6 +124,8 @@ public:
carla_engine_init_bridge(audioBaseName, controlBaseName, driverName);
else
carla_engine_init("JACK", driverName);

fEngine = carla_get_standalone_engine();
}

~CarlaPluginClient() override
@@ -133,17 +135,20 @@ public:
carla_engine_close();
}

bool isOk() const noexcept
{
return (fEngine != nullptr);
}

void oscInit(const char* const url)
{
CarlaBridgeClient::oscInit(url);

fEngine = carla_get_standalone_engine();
fEngine->setOscBridgeData(&fOscData);
}

void ready(const bool doSaveLoad)
{
fEngine = carla_get_standalone_engine();
fPlugin = fEngine->getPlugin(0);

if (doSaveLoad)
@@ -164,7 +169,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(fEngine != nullptr,);
CARLA_SAFE_ASSERT_RETURN(fPlugin != nullptr,);

fEngine->idle();
carla_engine_idle();
CarlaBridgeClient::oscIdle();

if (gSaveNow)
@@ -483,7 +488,7 @@ int main(int argc, char* argv[])
// Setup args

const bool useBridge = (argc == 7);
const bool useOsc = std::strcmp(oscUrl, "null");
const bool useOsc = (std::strcmp(oscUrl, "null") != 0 && std::strcmp(oscUrl, "(null)") != 0 && std::strcmp(oscUrl, "NULL") != 0);

if (std::strcmp(name, "(none)") == 0)
name = nullptr;
@@ -496,6 +501,7 @@ int main(int argc, char* argv[])

if (useBridge)
{
CARLA_SAFE_ASSERT_RETURN(std::strlen(argv[6]) == 6*2, 1);
std::strncpy(bridgeBaseAudioName, argv[6], 6);
std::strncpy(bridgeBaseControlName, argv[6]+6, 6);
bridgeBaseAudioName[6] = '\0';
@@ -524,10 +530,7 @@ int main(int argc, char* argv[])
CarlaString clientName((name != nullptr) ? name : label);

if (clientName.isEmpty())
{
File file(filename);
clientName = file.getFileNameWithoutExtension().toRawUTF8();
}
clientName = File(filename).getFileNameWithoutExtension().toRawUTF8();

// ---------------------------------------------------------------------
// Set extraStuff
@@ -548,6 +551,12 @@ int main(int argc, char* argv[])

CarlaPluginClient client(useBridge, (const char*)clientName, bridgeBaseAudioName, bridgeBaseControlName);

if (! client.isOk())
{
carla_stderr("Failed to init engine, error was:\n%s", carla_get_last_error());
return 1;
}

// ---------------------------------------------------------------------
// Init OSC

@@ -585,6 +594,7 @@ int main(int argc, char* argv[])
client.ready(!useOsc);
client.exec();

carla_set_engine_about_to_close();
carla_remove_plugin(0);

ret = 0;


+ 9
- 10
source/bridges/Makefile View File

@@ -51,21 +51,20 @@ endif
WIN_BUILD_FLAGS = $(BUILD_PLUGIN_FLAGS) -DJACKBRIDGE_EXPORT
WIN_32BIT_FLAGS = $(32BIT_FLAGS)
WIN_64BIT_FLAGS = $(64BIT_FLAGS)
WIN_LINK_FLAGS = $(LINK_PLUGIN_FLAGS) $(EXTRA_LIBS) -mwindows -lwinspool -lole32 -luuid -limm32 -lshell32 -lws2_32 -L../modules
WIN_LINK_FLAGS = $(LINK_PLUGIN_FLAGS) -L../modules

# --------------------------------------------------------------
# Plugin bridges (Native)

NATIVE_BUILD_FLAGS = $(POSIX_BUILD_FLAGS)
NATIVE_BUILD_FLAGS += -DWANT_NATIVE
NATIVE_BUILD_FLAGS = $(POSIX_BUILD_FLAGS) -DWANT_NATIVE
NATIVE_LINK_FLAGS = $(POSIX_LINK_FLAGS)

NATIVE_LINK_FLAGS += $(JUCE_AUDIO_BASICS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_CORE_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_EVENTS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_GRAPHICS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_GUI_BASICS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_AUDIO_BASICS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_CORE_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_DATA_STRUCTURES_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_EVENTS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_GRAPHICS_LIBS)
NATIVE_LINK_FLAGS += $(JUCE_GUI_BASICS_LIBS)

ifeq ($(HAVE_FLUIDSYNTH),true)
NATIVE_BUILD_FLAGS += -DWANT_FLUIDSYNTH
@@ -95,7 +94,7 @@ endif

ifeq ($(HAVE_OPENGL),true)
NATIVE_BUILD_FLAGS += -DWANT_OPENGL
NATIVE_LINK_FLAGS += $(shell pkg-config --libs gl)
NATIVE_LINK_FLAGS += $(DGL_LIBS)
endif

ifeq ($(HAVE_ZYN_DEPS),true)


+ 2
- 2
source/carla_database.py View File

@@ -400,7 +400,7 @@ class SearchPluginsThread(QThread):
self.fContinueChecking = True
self.fCurCount = 0
pluginCount = 0
settingsDB = QSettings("falkTX", "CarlaPlugins")
settingsDB = QSettings("falkTX", "CarlaPlugins2")

if self.fCheckLADSPA: pluginCount += 1
if self.fCheckDSSI: pluginCount += 1
@@ -1417,7 +1417,7 @@ class PluginDatabaseW(QDialog):
self.fLastTableIndex += 1

def _reAddPlugins(self):
settingsDB = QSettings("falkTX", "CarlaPlugins")
settingsDB = QSettings("falkTX", "CarlaPlugins2")

for x in range(self.ui.tableWidget.rowCount()):
self.ui.tableWidget.removeRow(0)


+ 2
- 2
source/carla_patchbay.py View File

@@ -86,7 +86,7 @@ class CarlaPatchbayW(QGraphicsView):

patchcanvas.setOptions(pOptions)
patchcanvas.setFeatures(pFeatures)
patchcanvas.init("Carla", self.scene, CanvasCallback, False)
patchcanvas.init("Carla2", self.scene, CanvasCallback, False)

tryCanvasSize = parent.fSavedSettings[CARLA_KEY_CANVAS_SIZE].split("x")

@@ -368,7 +368,7 @@ class CarlaPatchbayW(QGraphicsView):

patchcanvas.setOptions(pOptions)
patchcanvas.setFeatures(pFeatures)
patchcanvas.init("Carla", self.scene, CanvasCallback, False)
patchcanvas.init("Carla2", self.scene, CanvasCallback, False)

if Carla.host.is_engine_running():
Carla.host.patchbay_refresh()


+ 1
- 1
source/carla_style.py View File

@@ -35,7 +35,7 @@ from carla_shared import *
# ------------------------------------------------------------------------------------------------------------

class CarlaApplication(object):
def __init__(self, appName = "Carla"):
def __init__(self, appName = "Carla2"):
object.__init__(self)

if os.path.exists(os.path.join(CWD, "modules", "theme")):


+ 1
- 1
source/includes/CarlaDefines.hpp View File

@@ -47,7 +47,7 @@
// Check for C++11 support
#if defined(HAVE_CPP11_SUPPORT)
# define CARLA_PROPER_CPP11_SUPPORT
#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
#elif defined(__GNUC__) && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
# define CARLA_PROPER_CPP11_SUPPORT
# if (__GNUC__ * 100 + __GNUC_MINOR__) < 407


+ 10
- 11
source/modules/carla_native/vex-fx.cpp View File

@@ -39,22 +39,17 @@ public:
{
setVisible(false);
setAlwaysOnTop(true);
setDropShadowEnabled(false);
setOpaque(true);
//setResizable(false, false);
//setUsingNativeTitleBar(false);
setResizable(false, false);
setUsingNativeTitleBar(true);
}

void show(Component* const comp)
{
fClosed = false;

const int width = comp->getWidth();
const int height = comp->getHeight()+getTitleBarHeight();

centreWithSize(width, height);
setContentNonOwned(comp, false);
setSize(width, height);
centreWithSize(comp->getWidth(), comp->getHeight());
setContentNonOwned(comp, true);

if (! isOnDesktop())
addToDesktop();
@@ -389,6 +384,8 @@ protected:

void uiShow(const bool show) override
{
MessageManagerLock mmLock;

if (show)
{
if (fWindow == nullptr)
@@ -399,8 +396,8 @@ protected:

if (fView == nullptr)
{
fView = new PeggyViewComponent(1, fSettings, this);
fView->setSize(207, 320);
fView = new PeggyViewComponent(fSettings, this, true);
fView->setSize(202, 275);
}

fWindow->show(fView);
@@ -431,6 +428,7 @@ protected:
if (fView == nullptr)
return;

MessageManagerLock mmLock;
fView->update();
}

@@ -447,6 +445,7 @@ protected:
if (fWindow == nullptr)
return;

MessageManagerLock mmLock;
fWindow->setName(uiName);
}



+ 11
- 13
source/modules/carla_native/vex-synth.cpp View File

@@ -76,22 +76,17 @@ public:
{
setVisible(false);
setAlwaysOnTop(true);
setDropShadowEnabled(false);
setOpaque(true);
//setResizable(false, false);
//setUsingNativeTitleBar(false);
setResizable(false, false);
setUsingNativeTitleBar(true);
}

void show(Component* const comp)
{
fClosed = false;

const int width = comp->getWidth();
const int height = comp->getHeight()+getTitleBarHeight();

centreWithSize(width, height);
setContentNonOwned(comp, false);
setSize(width, height);
centreWithSize(comp->getWidth(), comp->getHeight());
setContentNonOwned(comp, true);

if (! isOnDesktop())
addToDesktop();
@@ -121,7 +116,7 @@ protected:
}

private:
bool fClosed;
volatile bool fClosed;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HelperWindow2)
};
@@ -301,11 +296,11 @@ public:
TB6->setClickingTogglesState(true);
TB6->setToggleState(false, dontSendNotification);

addChildComponent(p1 = new PeggyViewComponent(1, arpSet1, this));
addChildComponent(p1 = new PeggyViewComponent(arpSet1, this));
p1->setLookAndFeel(&mlaf);
addChildComponent(p2 = new PeggyViewComponent(2, arpSet2, this));
addChildComponent(p2 = new PeggyViewComponent(arpSet2, this));
p2->setLookAndFeel(&mlaf);
addChildComponent(p3 = new PeggyViewComponent(3, arpSet3, this));
addChildComponent(p3 = new PeggyViewComponent(arpSet3, this));
p3->setLookAndFeel(&mlaf);

setSize(800,500);
@@ -1081,6 +1076,8 @@ protected:

void uiShow(const bool show) override
{
MessageManagerLock mmLock;

if (show)
{
if (fWindow == nullptr)
@@ -1208,6 +1205,7 @@ protected:
if (fWindow == nullptr)
return;

MessageManagerLock mmLock;
fWindow->setName(uiName);
}



+ 22
- 8
source/modules/carla_native/vex/PeggyViewComponent.h View File

@@ -39,6 +39,7 @@
#include "gui/BoolGridComponent.h"
#include "gui/SliderFieldComponent.h"
#include "lookandfeel/MyLookAndFeel.h"
class PeggyViewComponent : public Component,
public ChangeListener,
@@ -54,10 +55,10 @@ public:
virtual void arpParameterChanged(const uint32_t id) = 0;
};
PeggyViewComponent(const int partID, VexArpSettings& arpSet, Callback* const callback)
: fPart(partID),
fArpSettings(arpSet),
fCallback(callback)
PeggyViewComponent(VexArpSettings& arpSet, Callback* const callback, const bool isStandalone = false)
: fArpSettings(arpSet),
fCallback(callback),
fIsStandalone(isStandalone)
{
addAndMakeVisible(boolGrid = new BoolGridComponent());
boolGrid->addChangeListener(this);
@@ -134,6 +135,12 @@ public:
onOffBtn->addListener(this);
onOffBtn->setClickingTogglesState(true);
if (isStandalone)
{
static MyLookAndFeel mlaf;
setLookAndFeel(&mlaf);
}
update();
}
@@ -163,10 +170,17 @@ public:
g.setGradientFill(ColourGradient(Colour(0xffffffff), 0.0f, 0.0f,
Colour(0xff888899), (float)getWidth(), (float)getHeight(), false));
g.fillRect(0,0,getWidth() - 5, getHeight() - 5);
if (fIsStandalone)
{
g.fillRect(0, 0, getWidth(), getHeight());
}
else
{
g.fillRect(0, 0, getWidth() - 5, getHeight() - 5);
g.setColour(Colours::black);
g.drawRect(0,0,getWidth() - 5, getHeight() - 5);
g.setColour(Colours::black);
g.drawRect(0, 0, getWidth() - 5, getHeight() - 5);
}
}
void changeListenerCallback(ChangeBroadcaster* caller) override
@@ -244,9 +258,9 @@ public:
}
private:
const int fPart;
VexArpSettings& fArpSettings;
Callback* const fCallback;
const bool fIsStandalone;
ScopedPointer<BoolGridComponent> boolGrid;
ScopedPointer<SliderFieldComponent> sliderField;


+ 2
- 2
source/modules/distrho/dgl/Base.hpp View File

@@ -29,7 +29,7 @@

#if defined(HAVE_CPP11_SUPPORT)
# define PROPER_CPP11_SUPPORT
#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
#elif defined(__GNUC__) && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
# define PROPER_CPP11_SUPPORT
# if (__GNUC__ * 100 + __GNUC_MINOR__) < 407
@@ -40,7 +40,7 @@

#ifndef PROPER_CPP11_SUPPORT
# define override
# define noexcept
# define noexcept throw()
# define nullptr (0)
#endif



+ 3
- 12
source/modules/distrho/dgl/Makefile View File

@@ -8,8 +8,9 @@ include ../../../Makefile.mk

# --------------------------------------------------------------

BUILD_C_FLAGS += -I.
BUILD_CXX_FLAGS += -I.
BUILD_C_FLAGS += $(DGL_FLAGS) -I.
BUILD_CXX_FLAGS += $(DGL_FLAGS) -I.
LINK_FLAGS += $(DGL_LIBS)

OBJS = \
src/App.cpp.o \
@@ -71,22 +72,12 @@ OBJS_win64 = \
src/Widget.cpp.win64.o \
src/Window.cpp.win64.o

ifeq ($(LINUX),true)
BASE_FLAGS += $(shell pkg-config --cflags gl x11)
LINK_FLAGS += $(shell pkg-config --libs gl x11)
endif

ifeq ($(MACOS),true)
LINK_FLAGS += -framework OpenGL -framework Cocoa
OBJS += src/pugl/pugl_osx_extended.m.o
OBJS_posix32 += src/pugl/pugl_osx_extended.m.posix32.o
OBJS_posix64 += src/pugl/pugl_osx_extended.m.posix64.o
endif

ifeq ($(WIN32),true)
LINK_FLAGS += -lopengl32 -lgdi32
endif

# --------------------------------------------------------------

all: ../../dgl.a


+ 1
- 1
source/modules/distrho/src/DistrhoDefines.h View File

@@ -85,7 +85,7 @@

#if defined(HAVE_CPP11_SUPPORT)
# define PROPER_CPP11_SUPPORT
#elif defined(__GNUC__) && defined(__GXX_EXPERIMENTAL_CXX0X__)
#elif defined(__GNUC__) && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__))
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
# define PROPER_CPP11_SUPPORT
# if (__GNUC__ * 100 + __GNUC_MINOR__) < 407


+ 3
- 0
source/modules/jackbridge/JackBridge1.cpp View File

@@ -457,7 +457,10 @@ struct JackBridge {
~JackBridge()
{
if (lib != nullptr)
{
lib_close(lib);
lib = nullptr;
}
}
};



+ 18
- 0
source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp View File

@@ -251,6 +251,15 @@ void JUCE_CALLTYPE FloatVectorOperations::multiply (float* dest, float multiplie
#endif
}
void FloatVectorOperations::negate (float* dest, const float* src, int num) noexcept
{
#if JUCE_USE_VDSP_FRAMEWORK
vDSP_vneg ((float*) src, 1, dest, 1, (vDSP_Length) num);
#else
copyWithMultiply (dest, src, -1.0f, num);
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, const int* src, float multiplier, int num) noexcept
{
#if JUCE_USE_SSE_INTRINSICS
@@ -332,3 +341,12 @@ float JUCE_CALLTYPE FloatVectorOperations::findMaximum (const float* src, int nu
return juce::findMaximum (src, num);
#endif
}
void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept
{
#if JUCE_USE_SSE_INTRINSICS
if (FloatVectorHelpers::isSSE2Available())
_MM_SET_FLUSH_ZERO_MODE (shouldEnable ? _MM_FLUSH_ZERO_ON : _MM_FLUSH_ZERO_OFF);
#endif
(void) shouldEnable;
}

+ 8
- 0
source/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h View File

@@ -62,6 +62,9 @@ public:
/** Multiplies each of the destination values by a fixed multiplier. */
static void JUCE_CALLTYPE multiply (float* dest, float multiplier, int numValues) noexcept;
/** Copies a source vector to a destination, negating each value. */
static void JUCE_CALLTYPE negate (float* dest, const float* src, int numValues) noexcept;
/** Converts a stream of integers to floats, multiplying each one by the given multiplier. */
static void JUCE_CALLTYPE convertFixedToFloat (float* dest, const int* src, float multiplier, int numValues) noexcept;
@@ -73,6 +76,11 @@ public:
/** Finds the maximum value in the given array. */
static float JUCE_CALLTYPE findMaximum (const float* src, int numValues) noexcept;
/** On Intel CPUs, this method enables or disables the SSE flush-to-zero mode.
Effectively, this is a wrapper around a call to _MM_SET_FLUSH_ZERO_MODE
*/
static void JUCE_CALLTYPE enableFlushToZeroMode (bool shouldEnable) noexcept;
};


+ 1
- 1
source/modules/juce_audio_basics/effects/juce_Decibels.h View File

@@ -43,7 +43,7 @@ public:
static Type decibelsToGain (const Type decibels,
const Type minusInfinityDb = (Type) defaultMinusInfinitydB)
{
return decibels > minusInfinityDb ? powf ((Type) 10.0, decibels * (Type) 0.05)
return decibels > minusInfinityDb ? std::pow ((Type) 10.0, decibels * (Type) 0.05)
: Type();
}


+ 1
- 1
source/modules/juce_audio_basics/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_audio_basics",
"name": "JUCE audio and midi data classes",
"version": "2.1.3",
"version": "2.1.6",
"description": "Classes for audio buffer manipulation, midi message handling, synthesis, etc",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 47
- 105
source/modules/juce_audio_basics/midi/juce_MidiBuffer.cpp View File

@@ -26,17 +26,17 @@ namespace MidiBufferHelpers
{
inline int getEventTime (const void* const d) noexcept
{
return *static_cast <const int*> (d);
return *static_cast<const int32*> (d);
}
inline uint16 getEventDataSize (const void* const d) noexcept
{
return *reinterpret_cast <const uint16*> (static_cast <const char*> (d) + sizeof (int));
return *reinterpret_cast<const uint16*> (static_cast<const char*> (d) + sizeof (int32));
}
inline uint16 getEventTotalSize (const void* const d) noexcept
{
return getEventDataSize (d) + sizeof (int) + sizeof (uint16);
return getEventDataSize (d) + sizeof (int32) + sizeof (uint16);
}
static int findActualEventLength (const uint8* const data, const int maxBytes) noexcept
@@ -67,68 +67,44 @@ namespace MidiBufferHelpers
return size;
}
}
//==============================================================================
MidiBuffer::MidiBuffer() noexcept
: bytesUsed (0)
{
}
static uint8* findEventAfter (uint8* d, uint8* endData, const int samplePosition) noexcept
{
while (d < endData && getEventTime (d) <= samplePosition)
d += getEventTotalSize (d);
MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept
: bytesUsed (0)
{
addEvent (message, 0);
return d;
}
}
MidiBuffer::MidiBuffer (const MidiBuffer& other) noexcept
: data (other.data),
bytesUsed (other.bytesUsed)
{
}
//==============================================================================
MidiBuffer::MidiBuffer() noexcept {}
MidiBuffer::~MidiBuffer() {}
MidiBuffer::MidiBuffer (const MidiBuffer& other) noexcept : data (other.data) {}
MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) noexcept
{
bytesUsed = other.bytesUsed;
data = other.data;
return *this;
}
void MidiBuffer::swapWith (MidiBuffer& other) noexcept
{
data.swapWith (other.data);
std::swap (bytesUsed, other.bytesUsed);
}
MidiBuffer::~MidiBuffer()
{
}
inline uint8* MidiBuffer::getData() const noexcept
MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept
{
return static_cast <uint8*> (data.getData());
addEvent (message, 0);
}
void MidiBuffer::clear() noexcept
{
bytesUsed = 0;
}
void MidiBuffer::swapWith (MidiBuffer& other) noexcept { data.swapWith (other.data); }
void MidiBuffer::clear() noexcept { data.clearQuick(); }
void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated (minimumNumBytes); }
bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; }
void MidiBuffer::clear (const int startSample, const int numSamples)
{
uint8* const start = findEventAfter (getData(), startSample - 1);
uint8* const end = findEventAfter (start, startSample + numSamples - 1);
if (end > start)
{
const int bytesToMove = bytesUsed - (int) (end - getData());
uint8* const start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1);
uint8* const end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1);
if (bytesToMove > 0)
memmove (start, end, (size_t) bytesToMove);
bytesUsed -= (int) (end - start);
}
data.removeRange (start - data.begin(), end - data.begin());
}
void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber)
@@ -138,27 +114,19 @@ void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber)
void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const int sampleNumber)
{
const int numBytes = MidiBufferHelpers::findActualEventLength (static_cast <const uint8*> (newData), maxBytes);
const int numBytes = MidiBufferHelpers::findActualEventLength (static_cast<const uint8*> (newData), maxBytes);
if (numBytes > 0)
{
size_t spaceNeeded = (size_t) bytesUsed + (size_t) numBytes + sizeof (int) + sizeof (uint16);
data.ensureSize ((spaceNeeded + spaceNeeded / 2 + 8) & ~(size_t) 7);
uint8* d = findEventAfter (getData(), sampleNumber);
const int bytesToMove = bytesUsed - (int) (d - getData());
const size_t newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16);
const int offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin());
if (bytesToMove > 0)
memmove (d + numBytes + sizeof (int) + sizeof (uint16), d, (size_t) bytesToMove);
data.insertMultiple (offset, 0, newItemSize);
*reinterpret_cast <int*> (d) = sampleNumber;
d += sizeof (int);
*reinterpret_cast <uint16*> (d) = (uint16) numBytes;
d += sizeof (uint16);
memcpy (d, newData, (size_t) numBytes);
bytesUsed += sizeof (int) + sizeof (uint16) + (size_t) numBytes;
uint8* const d = data.begin() + offset;
*reinterpret_cast<int32*> (d) = sampleNumber;
*reinterpret_cast<uint16*> (d + 4) = (uint16) numBytes;
memcpy (d + 6, newData, (size_t) numBytes);
}
}
@@ -180,45 +148,30 @@ void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
}
}
void MidiBuffer::ensureSize (size_t minimumNumBytes)
{
data.ensureSize (minimumNumBytes);
}
bool MidiBuffer::isEmpty() const noexcept
{
return bytesUsed == 0;
}
int MidiBuffer::getNumEvents() const noexcept
{
int n = 0;
const uint8* d = getData();
const uint8* const end = d + bytesUsed;
const uint8* const end = data.end();
while (d < end)
{
for (const uint8* d = data.begin(); d < end; ++n)
d += MidiBufferHelpers::getEventTotalSize (d);
++n;
}
return n;
}
int MidiBuffer::getFirstEventTime() const noexcept
{
return bytesUsed > 0 ? MidiBufferHelpers::getEventTime (data.getData()) : 0;
return data.size() > 0 ? MidiBufferHelpers::getEventTime (data.begin()) : 0;
}
int MidiBuffer::getLastEventTime() const noexcept
{
if (bytesUsed == 0)
if (data.size() == 0)
return 0;
const uint8* d = getData();
const uint8* const endData = d + bytesUsed;
const uint8* const endData = data.end();
for (;;)
for (const uint8* d = data.begin();;)
{
const uint8* const nextOne = d + MidiBufferHelpers::getEventTotalSize (d);
@@ -229,19 +182,9 @@ int MidiBuffer::getLastEventTime() const noexcept
}
}
uint8* MidiBuffer::findEventAfter (uint8* d, const int samplePosition) const noexcept
{
const uint8* const endData = getData() + bytesUsed;
while (d < endData && MidiBufferHelpers::getEventTime (d) <= samplePosition)
d += MidiBufferHelpers::getEventTotalSize (d);
return d;
}
//==============================================================================
MidiBuffer::Iterator::Iterator (const MidiBuffer& b) noexcept
: buffer (b), data (b.getData())
: buffer (b), data (b.data.begin())
{
}
@@ -251,8 +194,8 @@ MidiBuffer::Iterator::~Iterator() noexcept
void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) noexcept
{
data = buffer.getData();
const uint8* dataEnd = data + buffer.bytesUsed;
data = buffer.data.begin();
const uint8* const dataEnd = buffer.data.end();
while (data < dataEnd && MidiBufferHelpers::getEventTime (data) < samplePosition)
data += MidiBufferHelpers::getEventTotalSize (data);
@@ -260,27 +203,26 @@ void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) noex
bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, int& samplePosition) noexcept
{
if (data >= buffer.getData() + buffer.bytesUsed)
if (data >= buffer.data.end())
return false;
samplePosition = MidiBufferHelpers::getEventTime (data);
numBytes = MidiBufferHelpers::getEventDataSize (data);
data += sizeof (int) + sizeof (uint16);
midiData = data;
data += numBytes;
const int itemSize = MidiBufferHelpers::getEventDataSize (data);
numBytes = itemSize;
midiData = data + sizeof (int32) + sizeof (uint16);
data += sizeof (int32) + sizeof (uint16) + itemSize;
return true;
}
bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept
{
if (data >= buffer.getData() + buffer.bytesUsed)
if (data >= buffer.data.end())
return false;
samplePosition = MidiBufferHelpers::getEventTime (data);
const int numBytes = MidiBufferHelpers::getEventDataSize (data);
data += sizeof (int) + sizeof (uint16);
result = MidiMessage (data, numBytes, samplePosition);
result = MidiMessage (data + sizeof (int32) + sizeof (uint16), numBytes, samplePosition);
data += numBytes;
return true;


+ 7
- 12
source/modules/juce_audio_basics/midi/juce_MidiBuffer.h View File

@@ -71,7 +71,6 @@ public:
void clear (int start, int numSamples);
/** Returns true if the buffer is empty.
To actually retrieve the events, use a MidiBuffer::Iterator object
*/
bool isEmpty() const noexcept;
@@ -137,13 +136,11 @@ public:
int sampleDeltaToAdd);
/** Returns the sample number of the first event in the buffer.
If the buffer's empty, this will just return 0.
*/
int getFirstEventTime() const noexcept;
/** Returns the sample number of the last event in the buffer.
If the buffer's empty, this will just return 0.
*/
int getLastEventTime() const noexcept;
@@ -154,7 +151,7 @@ public:
This is a quick operation, because no memory allocating or copying is done, it
just swaps the internal state of the two buffers.
*/
void swapWith (MidiBuffer& other) noexcept;
void swapWith (MidiBuffer&) noexcept;
/** Preallocates some memory for the buffer to use.
This helps to avoid needing to reallocate space when the buffer has messages
@@ -222,15 +219,13 @@ public:
JUCE_DECLARE_NON_COPYABLE (Iterator)
};
private:
//==============================================================================
friend class MidiBuffer::Iterator;
MemoryBlock data;
int bytesUsed;
uint8* getData() const noexcept;
uint8* findEventAfter (uint8*, int samplePosition) const noexcept;
/** The raw data holding this buffer.
Obviously access to this data is provided at your own risk. Its internal format could
change in future, so don't write code that relies on it!
*/
Array<uint8> data;
private:
JUCE_LEAK_DETECTOR (MidiBuffer)
};


+ 28
- 26
source/modules/juce_audio_basics/midi/juce_MidiFile.cpp View File

@@ -372,46 +372,48 @@ void MidiFile::writeTrack (OutputStream& mainOut, const int trackNum)
int lastTick = 0;
uint8 lastStatusByte = 0;
bool endOfTrackEventWritten = false;
for (int i = 0; i < ms.getNumEvents(); ++i)
{
const MidiMessage& mm = ms.getEventPointer(i)->message;
if (! mm.isEndOfTrackMetaEvent())
{
const int tick = roundToInt (mm.getTimeStamp());
const int delta = jmax (0, tick - lastTick);
MidiFileHelpers::writeVariableLengthInt (out, (uint32) delta);
lastTick = tick;
if (mm.isEndOfTrackMetaEvent())
endOfTrackEventWritten = true;
const uint8* data = mm.getRawData();
int dataSize = mm.getRawDataSize();
const int tick = roundToInt (mm.getTimeStamp());
const int delta = jmax (0, tick - lastTick);
MidiFileHelpers::writeVariableLengthInt (out, (uint32) delta);
lastTick = tick;
const uint8 statusByte = data[0];
const uint8* data = mm.getRawData();
int dataSize = mm.getRawDataSize();
if (statusByte == lastStatusByte
&& (statusByte & 0xf0) != 0xf0
&& dataSize > 1
&& i > 0)
{
++data;
--dataSize;
}
else if (statusByte == 0xf0) // Write sysex message with length bytes.
{
out.writeByte ((char) statusByte);
const uint8 statusByte = data[0];
++data;
--dataSize;
if (statusByte == lastStatusByte
&& (statusByte & 0xf0) != 0xf0
&& dataSize > 1
&& i > 0)
{
++data;
--dataSize;
}
else if (statusByte == 0xf0) // Write sysex message with length bytes.
{
out.writeByte ((char) statusByte);
MidiFileHelpers::writeVariableLengthInt (out, (uint32) dataSize);
}
++data;
--dataSize;
out.write (data, (size_t) dataSize);
lastStatusByte = statusByte;
MidiFileHelpers::writeVariableLengthInt (out, (uint32) dataSize);
}
out.write (data, (size_t) dataSize);
lastStatusByte = statusByte;
}
if (! endOfTrackEventWritten)
{
out.writeByte (0); // (tick delta)
const MidiMessage m (MidiMessage::endOfTrack());


+ 22
- 17
source/modules/juce_audio_basics/midi/juce_MidiMessage.cpp View File

@@ -777,22 +777,19 @@ MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, const int
++powerOfTwo;
}
const uint8 d[] = { 0xff, 0x58, 0x04, (uint8) numerator,
(uint8) powerOfTwo, 1, 96 };
const uint8 d[] = { 0xff, 0x58, 0x04, (uint8) numerator, (uint8) powerOfTwo, 1, 96 };
return MidiMessage (d, 7, 0.0);
}
MidiMessage MidiMessage::midiChannelMetaEvent (const int channel) noexcept
{
const uint8 d[] = { 0xff, 0x20, 0x01, (uint8) jlimit (0, 0xff, channel - 1) };
return MidiMessage (d, 4, 0.0);
}
bool MidiMessage::isKeySignatureMetaEvent() const noexcept
{
return getMetaEventType() == 89;
return getMetaEventType() == 0x59;
}
int MidiMessage::getKeySignatureNumberOfSharpsOrFlats() const noexcept
@@ -805,6 +802,14 @@ bool MidiMessage::isKeySignatureMajorKey() const noexcept
return getMetaEventData()[1] == 0;
}
MidiMessage MidiMessage::keySignatureMetaEvent (int numberOfSharpsOrFlats, bool isMinorKey)
{
jassert (numberOfSharpsOrFlats >= -7 && numberOfSharpsOrFlats <= 7);
const uint8 d[] = { 0xff, 0x59, 0x02, (uint8) numberOfSharpsOrFlats, isMinorKey ? (uint8) 1 : (uint8) 0 };
return MidiMessage (d, 5, 0.0);
}
MidiMessage MidiMessage::endOfTrack() noexcept
{
return MidiMessage (0xff, 0x2f, 0, 0.0);
@@ -958,9 +963,9 @@ double MidiMessage::getMidiNoteInHertz (int noteNumber, const double frequencyOf
return frequencyOfA * pow (2.0, (noteNumber - 69) / 12.0);
}
String MidiMessage::getGMInstrumentName (const int n)
const char* MidiMessage::getGMInstrumentName (const int n)
{
const char* names[] =
static const char* names[] =
{
"Acoustic Grand Piano", "Bright Acoustic Piano", "Electric Grand Piano", "Honky-tonk Piano",
"Electric Piano 1", "Electric Piano 2", "Harpsichord", "Clavinet", "Celesta", "Glockenspiel",
@@ -987,12 +992,12 @@ String MidiMessage::getGMInstrumentName (const int n)
"Applause", "Gunshot"
};
return isPositiveAndBelow (n, (int) 128) ? names[n] : (const char*) 0;
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
}
String MidiMessage::getGMInstrumentBankName (const int n)
const char* MidiMessage::getGMInstrumentBankName (const int n)
{
const char* names[] =
static const char* names[] =
{
"Piano", "Chromatic Percussion", "Organ", "Guitar",
"Bass", "Strings", "Ensemble", "Brass",
@@ -1000,12 +1005,12 @@ String MidiMessage::getGMInstrumentBankName (const int n)
"Synth Effects", "Ethnic", "Percussive", "Sound Effects"
};
return isPositiveAndBelow (n, (int) 16) ? names[n] : (const char*) 0;
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
}
String MidiMessage::getRhythmInstrumentName (const int n)
const char* MidiMessage::getRhythmInstrumentName (const int n)
{
const char* names[] =
static const char* names[] =
{
"Acoustic Bass Drum", "Bass Drum 1", "Side Stick", "Acoustic Snare",
"Hand Clap", "Electric Snare", "Low Floor Tom", "Closed Hi-Hat", "High Floor Tom",
@@ -1018,12 +1023,12 @@ String MidiMessage::getRhythmInstrumentName (const int n)
"Mute Triangle", "Open Triangle"
};
return (n >= 35 && n <= 81) ? names [n - 35] : (const char*) nullptr;
return (n >= 35 && n <= 81) ? names [n - 35] : nullptr;
}
String MidiMessage::getControllerName (const int n)
const char* MidiMessage::getControllerName (const int n)
{
const char* names[] =
static const char* names[] =
{
"Bank Select", "Modulation Wheel (coarse)", "Breath controller (coarse)",
0, "Foot Pedal (coarse)", "Portamento Time (coarse)",
@@ -1049,5 +1054,5 @@ String MidiMessage::getControllerName (const int n)
"Poly Operation"
};
return isPositiveAndBelow (n, (int) 128) ? names[n] : (const char*) nullptr;
return isPositiveAndBelow (n, numElementsInArray (names)) ? names[n] : nullptr;
}

+ 16
- 11
source/modules/juce_audio_basics/midi/juce_MidiMessage.h View File

@@ -622,6 +622,14 @@ public:
*/
bool isKeySignatureMajorKey() const noexcept;
/** Creates a key-signature meta-event.
@param numberOfSharpsOrFlats if positive, this indicates the number of sharps
in the key; if negative, the number of flats
@param isMinorKey if true, the key is minor; if false, it is major
@see isKeySignatureMetaEvent
*/
static MidiMessage keySignatureMetaEvent (int numberOfSharpsOrFlats, bool isMinorKey);
//==============================================================================
/** Returns true if this is a 'channel' meta-event.
@@ -881,30 +889,27 @@ public:
*/
static double getMidiNoteInHertz (int noteNumber, const double frequencyOfA = 440.0) noexcept;
/** Returns the standard name of a GM instrument.
/** Returns the standard name of a GM instrument, or nullptr if unknown for this index.
@param midiInstrumentNumber the program number 0 to 127
@see getProgramChangeNumber
*/
static String getGMInstrumentName (int midiInstrumentNumber);
/** Returns the name of a bank of GM instruments.
static const char* getGMInstrumentName (int midiInstrumentNumber);
/** Returns the name of a bank of GM instruments, or nullptr if unknown for this bank number.
@param midiBankNumber the bank, 0 to 15
*/
static String getGMInstrumentBankName (int midiBankNumber);
/** Returns the standard name of a channel 10 percussion sound.
static const char* getGMInstrumentBankName (int midiBankNumber);
/** Returns the standard name of a channel 10 percussion sound, or nullptr if unknown for this note number.
@param midiNoteNumber the key number, 35 to 81
*/
static String getRhythmInstrumentName (int midiNoteNumber);
/** Returns the name of a controller type number.
static const char* getRhythmInstrumentName (int midiNoteNumber);
/** Returns the name of a controller type number, or nullptr if unknown for this controller number.
@see getControllerNumber
*/
static String getControllerName (int controllerNumber);
static const char* getControllerName (int controllerNumber);
private:
//==============================================================================


+ 1
- 1
source/modules/juce_audio_devices/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_audio_devices",
"name": "JUCE audio and midi I/O device classes",
"version": "2.1.3",
"version": "2.1.6",
"description": "Classes to play and record from audio and midi i/o devices.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 85
- 61
source/modules/juce_audio_devices/native/juce_ios_Audio.cpp View File

@@ -67,17 +67,16 @@ public:
return s;
}
int getNumSampleRates() { return 1; }
double getSampleRate (int index) { return sampleRate; }
int getNumSampleRates() { return jmax (1, sampleRates.size()); }
double getSampleRate (int index) { return sampleRates.size() > 0 ? sampleRates [index] : sampleRate; }
int getNumBufferSizesAvailable() { return 6; }
int getBufferSizeSamples (int index) { return 1 << (jlimit (0, 5, index) + 6); }
int getDefaultBufferSize() { return 1024; }
String open (const BigInteger& inputChannels,
const BigInteger& outputChannels,
double sampleRate,
int bufferSize)
String open (const BigInteger& inputChannelsWanted,
const BigInteger& outputChannelsWanted,
double targetSampleRate, int bufferSize)
{
close();
@@ -86,29 +85,26 @@ public:
// xxx set up channel mapping
activeOutputChans = outputChannels;
activeOutputChans = outputChannelsWanted;
activeOutputChans.setRange (2, activeOutputChans.getHighestBit(), false);
numOutputChannels = activeOutputChans.countNumberOfSetBits();
monoOutputChannelNumber = activeOutputChans.findNextSetBit (0);
activeInputChans = inputChannels;
activeInputChans = inputChannelsWanted;
activeInputChans.setRange (2, activeInputChans.getHighestBit(), false);
numInputChannels = activeInputChans.countNumberOfSetBits();
monoInputChannelNumber = activeInputChans.findNextSetBit (0);
AudioSessionSetActive (true);
UInt32 audioCategory = (numInputChannels > 0 && audioInputIsAvailable) ? kAudioSessionCategory_PlayAndRecord
: kAudioSessionCategory_MediaPlayback;
AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof (audioCategory), &audioCategory);
if (audioCategory == kAudioSessionCategory_PlayAndRecord)
if (numInputChannels > 0 && audioInputIsAvailable)
{
setSessionUInt32Property (kAudioSessionProperty_AudioCategory, kAudioSessionCategory_PlayAndRecord);
setSessionUInt32Property (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput, 1);
}
else
{
// (note: mustn't set this until after the audio category property has been set)
UInt32 allowBluetoothInput = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryEnableBluetoothInput,
sizeof (allowBluetoothInput), &allowBluetoothInput);
setSessionUInt32Property (kAudioSessionProperty_AudioCategory, kAudioSessionCategory_MediaPlayback);
}
AudioSessionAddPropertyListener (kAudioSessionProperty_AudioRouteChange, routingChangedStatic, this);
@@ -116,9 +112,11 @@ public:
fixAudioRouteIfSetToReceiver();
updateDeviceInfo();
Float32 bufferDuration = preferredBufferSize / sampleRate;
AudioSessionSetProperty (kAudioSessionProperty_PreferredHardwareIOBufferDuration, sizeof (bufferDuration), &bufferDuration);
actualBufferSize = preferredBufferSize;
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, targetSampleRate);
updateSampleRates();
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareIOBufferDuration, preferredBufferSize / sampleRate);
updateCurrentBufferSize();
prepareFloatBuffers (actualBufferSize);
@@ -134,6 +132,9 @@ public:
if (isRunning)
{
isRunning = false;
setSessionUInt32Property (kAudioSessionProperty_AudioCategory, kAudioSessionCategory_MediaPlayback);
AudioSessionRemovePropertyListenerWithUserData (kAudioSessionProperty_AudioRouteChange, routingChangedStatic, this);
AudioSessionSetActive (false);
@@ -193,6 +194,7 @@ private:
//==================================================================================================
CriticalSection callbackLock;
Float64 sampleRate;
Array<Float64> sampleRates;
int numInputChannels, numOutputChannels;
int preferredBufferSize, actualBufferSize;
bool isRunning;
@@ -239,7 +241,7 @@ private:
if (callback != nullptr)
{
// This shouldn't ever get triggered, but please let me know if it does!
jassert (numFrames <= floatData.getNumSamples());
jassert ((int) numFrames <= floatData.getNumSamples());
if (audioInputIsAvailable && numInputChannels > 0)
{
@@ -309,11 +311,47 @@ private:
void updateDeviceInfo()
{
UInt32 size = sizeof (sampleRate);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareSampleRate, &size, &sampleRate);
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, sampleRate);
getSessionProperty (kAudioSessionProperty_AudioInputAvailable, audioInputIsAvailable);
}
void updateSampleRates()
{
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, sampleRate);
sampleRates.clear();
sampleRates.add (sampleRate);
const int commonSampleRates[] = { 8000, 16000, 22050, 32000, 44100, 48000 };
for (int i = 0; i < numElementsInArray (commonSampleRates); ++i)
{
Float64 rate = (Float64) commonSampleRates[i];
if (rate != sampleRate)
{
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, rate);
Float64 actualSampleRate = 0.0;
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, actualSampleRate);
if (actualSampleRate == rate)
sampleRates.add (actualSampleRate);
}
}
DefaultElementComparator<Float64> comparator;
sampleRates.sort (comparator);
size = sizeof (audioInputIsAvailable);
AudioSessionGetProperty (kAudioSessionProperty_AudioInputAvailable, &size, &audioInputIsAvailable);
setSessionFloat64Property (kAudioSessionProperty_PreferredHardwareSampleRate, sampleRate);
getSessionProperty (kAudioSessionProperty_CurrentHardwareSampleRate, sampleRate);
}
void updateCurrentBufferSize()
{
Float32 bufferDuration = sampleRate > 0 ? (Float32) (preferredBufferSize / sampleRate) : 0.0f;
getSessionProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, bufferDuration);
actualBufferSize = (int) (sampleRate * bufferDuration + 0.5);
}
void routingChanged (const void* propertyValue)
@@ -349,11 +387,7 @@ private:
UInt32 formatSize = sizeof (format);
AudioUnitGetProperty (audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &format, &formatSize);
Float32 bufferDuration = preferredBufferSize / sampleRate;
UInt32 bufferDurationSize = sizeof (bufferDuration);
AudioSessionGetProperty (kAudioSessionProperty_CurrentHardwareIOBufferDuration, &bufferDurationSize, &bufferDuration);
actualBufferSize = (int) (sampleRate * bufferDuration + 0.5);
updateCurrentBufferSize();
AudioOutputUnitStart (audioUnit);
}
}
@@ -424,9 +458,9 @@ private:
format.mFormatID = kAudioFormatLinearPCM;
format.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked | kAudioFormatFlagsNativeEndian;
format.mBitsPerChannel = 8 * sizeof (short);
format.mChannelsPerFrame = numChannels;
format.mChannelsPerFrame = (UInt32) numChannels;
format.mFramesPerPacket = 1;
format.mBytesPerFrame = format.mBytesPerPacket = numChannels * sizeof (short);
format.mBytesPerFrame = format.mBytesPerPacket = (UInt32) numChannels * sizeof (short);
}
bool createAudioUnit()
@@ -486,23 +520,29 @@ private:
static void fixAudioRouteIfSetToReceiver()
{
CFStringRef audioRoute = 0;
UInt32 propertySize = sizeof (audioRoute);
if (AudioSessionGetProperty (kAudioSessionProperty_AudioRoute, &propertySize, &audioRoute) == noErr)
if (getSessionProperty (kAudioSessionProperty_AudioRoute, audioRoute) == noErr)
{
NSString* route = (NSString*) audioRoute;
//DBG ("audio route: " + nsStringToJuce (route));
if ([route hasPrefix: @"Receiver"])
{
UInt32 audioRouteOverride = kAudioSessionOverrideAudioRoute_Speaker;
AudioSessionSetProperty (kAudioSessionProperty_OverrideAudioRoute, sizeof (audioRouteOverride), &audioRouteOverride);
}
setSessionUInt32Property (kAudioSessionProperty_OverrideAudioRoute, kAudioSessionOverrideAudioRoute_Speaker);
CFRelease (audioRoute);
}
}
template <typename Type>
static OSStatus getSessionProperty (AudioSessionPropertyID propID, Type& result) noexcept
{
UInt32 valueSize = sizeof (result);
return AudioSessionGetProperty (propID, &valueSize, &result);
}
static void setSessionUInt32Property (AudioSessionPropertyID propID, UInt32 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
static void setSessionFloat64Property (AudioSessionPropertyID propID, Float64 v) noexcept { AudioSessionSetProperty (propID, sizeof (v), &v); }
JUCE_DECLARE_NON_COPYABLE (iOSAudioIODevice)
};
@@ -511,31 +551,15 @@ private:
class iOSAudioIODeviceType : public AudioIODeviceType
{
public:
iOSAudioIODeviceType() : AudioIODeviceType ("iOS Audio")
{
}
iOSAudioIODeviceType() : AudioIODeviceType ("iOS Audio") {}
void scanForDevices() {}
StringArray getDeviceNames (bool /*wantInputNames*/) const { return StringArray ("iOS Audio"); }
int getDefaultDeviceIndex (bool /*forInput*/) const { return 0; }
int getIndexOfDevice (AudioIODevice* d, bool /*asInput*/) const { return d != nullptr ? 0 : -1; }
bool hasSeparateInputsAndOutputs() const { return false; }
StringArray getDeviceNames (bool wantInputNames) const
{
return StringArray ("iOS Audio");
}
int getDefaultDeviceIndex (bool forInput) const
{
return 0;
}
int getIndexOfDevice (AudioIODevice* device, bool asInput) const
{
return device != nullptr ? 0 : -1;
}
bool hasSeparateInputsAndOutputs() const { return false; }
AudioIODevice* createDevice (const String& outputDeviceName,
const String& inputDeviceName)
AudioIODevice* createDevice (const String& outputDeviceName, const String& inputDeviceName)
{
if (outputDeviceName.isNotEmpty() || inputDeviceName.isNotEmpty())
return new iOSAudioIODevice (outputDeviceName.isNotEmpty() ? outputDeviceName


+ 18
- 54
source/modules/juce_audio_devices/native/juce_mac_AudioCDBurner.mm View File

@@ -48,8 +48,8 @@ struct AudioTrackProducerClass : public ObjCClass <NSObject>
struct AudioSourceHolder
{
AudioSourceHolder (AudioSource* source_, int numFrames)
: source (source_), readPosition (0), lengthInFrames (numFrames)
AudioSourceHolder (AudioSource* s, int numFrames)
: source (s), readPosition (0), lengthInFrames (numFrames)
{
}
@@ -125,15 +125,9 @@ private:
source->source->getNextAudioBlock (info);
typedef AudioData::Pointer <AudioData::Int16,
AudioData::LittleEndian,
AudioData::Interleaved,
AudioData::NonConst> CDSampleFormat;
typedef AudioData::Pointer <AudioData::Int16, AudioData::LittleEndian, AudioData::Interleaved, AudioData::NonConst> CDSampleFormat;
typedef AudioData::Pointer <AudioData::Float32, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceSampleFormat;
typedef AudioData::Pointer <AudioData::Float32,
AudioData::NativeEndian,
AudioData::NonInterleaved,
AudioData::Const> SourceSampleFormat;
CDSampleFormat left (buffer, 2);
left.convertSamples (SourceSampleFormat (tempBuffer.getSampleData (0)), numSamples);
CDSampleFormat right (buffer + 2, 2);
@@ -166,8 +160,8 @@ private:
struct OpenDiskDevice
{
OpenDiskDevice (DRDevice* device_)
: device (device_),
OpenDiskDevice (DRDevice* d)
: device (d),
tracks ([[NSMutableArray alloc] init]),
underrunProtection (true)
{
@@ -254,9 +248,8 @@ struct OpenDiskDevice
NSString* err = (NSString*) [[[burn status] objectForKey: DRErrorStatusKey]
objectForKey: DRErrorStatusErrorStringKey];
if ([err length] > 0)
return CharPointer_UTF8 ([err UTF8String]);
return nsStringToJuce (err);
}
[device releaseMediaReservation];
@@ -273,12 +266,9 @@ struct OpenDiskDevice
class AudioCDBurner::Pimpl : public Timer
{
public:
Pimpl (AudioCDBurner& owner_, const int deviceIndex)
: device (0), owner (owner_)
Pimpl (AudioCDBurner& b, int deviceIndex) : owner (b)
{
DRDevice* dev = [[DRDevice devices] objectAtIndex: deviceIndex];
if (dev != nil)
if (DRDevice* dev = [[DRDevice devices] objectAtIndex: deviceIndex])
{
device = new OpenDiskDevice (dev);
lastState = getDiskState();
@@ -307,7 +297,6 @@ public:
if ([device->device isValid])
{
NSDictionary* status = [device->device status];
NSString* state = [status objectForKey: DRDeviceMediaStateKey];
if ([state isEqualTo: DRDeviceMediaStateNone])
@@ -322,8 +311,8 @@ public:
{
if ([[[status objectForKey: DRDeviceMediaInfoKey] objectForKey: DRDeviceMediaBlocksFreeKey] intValue] > 0)
return writableDiskPresent;
else
return readOnlyDiskPresent;
return readOnlyDiskPresent;
}
}
@@ -337,14 +326,8 @@ public:
Array<int> results;
if ([device->device isValid])
{
NSArray* speeds = [[[device->device status] objectForKey: DRDeviceMediaInfoKey] objectForKey: DRDeviceBurnSpeedsKey];
for (unsigned int i = 0; i < [speeds count]; ++i)
{
const int kbPerSec = [[speeds objectAtIndex: i] intValue];
results.add (kbPerSec / kilobytesPerSecond1x);
}
}
for (id kbPerSec in [[[device->device status] objectForKey: DRDeviceMediaInfoKey] objectForKey: DRDeviceBurnSpeedsKey])
results.add ([kbPerSec intValue] / kilobytesPerSecond1x);
return results;
}
@@ -385,40 +368,21 @@ AudioCDBurner::~AudioCDBurner()
AudioCDBurner* AudioCDBurner::openDevice (const int deviceIndex)
{
ScopedPointer <AudioCDBurner> b (new AudioCDBurner (deviceIndex));
ScopedPointer<AudioCDBurner> b (new AudioCDBurner (deviceIndex));
if (b->pimpl->device == nil)
b = 0;
b = nullptr;
return b.release();
}
namespace
{
NSArray* findDiskBurnerDevices()
{
NSMutableArray* results = [NSMutableArray array];
NSArray* devs = [DRDevice devices];
for (int i = 0; i < [devs count]; ++i)
{
NSDictionary* dic = [[devs objectAtIndex: i] info];
NSString* name = [dic valueForKey: DRDeviceProductNameKey];
if (name != nil)
[results addObject: name];
}
return results;
}
}
StringArray AudioCDBurner::findAvailableDevices()
{
NSArray* names = findDiskBurnerDevices();
StringArray s;
for (unsigned int i = 0; i < [names count]; ++i)
s.add (CharPointer_UTF8 ([[names objectAtIndex: i] UTF8String]));
for (NSDictionary* dic in [DRDevice devices])
if (NSString* name = [dic valueForKey: DRDeviceProductNameKey])
s.add (nsStringToJuce (name));
return s;
}


+ 34
- 40
source/modules/juce_audio_devices/native/juce_win32_ASIO.cpp View File

@@ -1362,7 +1362,39 @@ private:
static long JUCE_ASIOCALLBACK asioMessagesCallback (long selector, long value, void*, double*)
{
return ASIOAudioIODevice::asioMessagesCallback (selector, value, deviceIndex);
switch (selector)
{
case kAsioSelectorSupported:
if (value == kAsioResetRequest || value == kAsioEngineVersion || value == kAsioResyncRequest
|| value == kAsioLatenciesChanged || value == kAsioSupportsInputMonitor)
return 1;
break;
case kAsioBufferSizeChange: JUCE_ASIO_LOG ("kAsioBufferSizeChange"); return sendResetRequest (deviceIndex);
case kAsioResetRequest: JUCE_ASIO_LOG ("kAsioResetRequest"); return sendResetRequest (deviceIndex);
case kAsioResyncRequest: JUCE_ASIO_LOG ("kAsioResyncRequest"); return sendResetRequest (deviceIndex);
case kAsioLatenciesChanged: JUCE_ASIO_LOG ("kAsioLatenciesChanged"); return 1;
case kAsioEngineVersion: return 2;
case kAsioSupportsTimeInfo:
case kAsioSupportsTimeCode:
return 0;
}
return 0;
}
static void JUCE_ASIOCALLBACK sampleRateChangedCallback (ASIOSampleRate)
{
sendResetRequest (deviceIndex);
}
static long sendResetRequest (int deviceIndex)
{
if (currentASIODev[deviceIndex] != nullptr)
currentASIODev[deviceIndex]->resetRequest();
return 1;
}
static void setCallbacks (ASIOCallbacks& callbacks)
@@ -1370,56 +1402,18 @@ private:
callbacks.bufferSwitch = &bufferSwitchCallback;
callbacks.asioMessage = &asioMessagesCallback;
callbacks.bufferSwitchTimeInfo = &bufferSwitchTimeInfoCallback;
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
}
};
void setCallbackFunctions()
{
callbacks.sampleRateDidChange = &sampleRateChangedCallback;
if (currentASIODev[0] == this) ASIOCallbackFunctions<0>::setCallbacks (callbacks);
else if (currentASIODev[1] == this) ASIOCallbackFunctions<1>::setCallbacks (callbacks);
else if (currentASIODev[2] == this) ASIOCallbackFunctions<2>::setCallbacks (callbacks);
else jassertfalse;
}
//==============================================================================
static long asioMessagesCallback (long selector, long value, const int deviceIndex)
{
switch (selector)
{
case kAsioSelectorSupported:
if (value == kAsioResetRequest || value == kAsioEngineVersion || value == kAsioResyncRequest
|| value == kAsioLatenciesChanged || value == kAsioSupportsInputMonitor)
return 1;
break;
case kAsioBufferSizeChange: JUCE_ASIO_LOG ("kAsioBufferSizeChange"); return sendResetRequest (deviceIndex);
case kAsioResetRequest: JUCE_ASIO_LOG ("kAsioResetRequest"); return sendResetRequest (deviceIndex);
case kAsioResyncRequest: JUCE_ASIO_LOG ("kAsioResyncRequest"); return sendResetRequest (deviceIndex);
case kAsioLatenciesChanged: JUCE_ASIO_LOG ("kAsioLatenciesChanged"); return 1;
case kAsioEngineVersion: return 2;
case kAsioSupportsTimeInfo:
case kAsioSupportsTimeCode:
return 0;
}
return 0;
}
static long sendResetRequest (int deviceIndex)
{
if (currentASIODev[deviceIndex] != nullptr)
currentASIODev[deviceIndex]->resetRequest();
return 1;
}
static void JUCE_ASIOCALLBACK sampleRateChangedCallback (ASIOSampleRate)
{
}
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ASIOAudioIODevice)
};


+ 5
- 8
source/modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp View File

@@ -22,9 +22,7 @@
==============================================================================
*/
//==============================================================================
static const char* const aiffFormatName = "AIFF file";
static const char* const aiffExtensions[] = { ".aiff", ".aif", 0 };
//==============================================================================
const char* const AiffAudioFormat::appleOneShot = "apple one shot";
@@ -101,7 +99,7 @@ namespace AiffFileHelpers
if (values.getAllKeys().contains ("MidiUnityNote", true))
{
block.setSize ((sizeof (InstChunk) + 3) & ~(size_t) 3, true);
InstChunk& inst = *static_cast <InstChunk*> (block.getData());
InstChunk& inst = *static_cast<InstChunk*> (block.getData());
inst.baseNote = getValue8 (values, "MidiUnityNote", "60");
inst.detune = getValue8 (values, "Detune", "0");
@@ -220,7 +218,7 @@ namespace AiffFileHelpers
StringArray tagsArray;
int bytesLeft = (int) mb.getSize();
const char* data = static_cast <const char*> (mb.getData());
const char* data = static_cast<const char*> (mb.getData());
while (bytesLeft > 0)
{
@@ -365,7 +363,7 @@ class AiffAudioFormatReader : public AudioFormatReader
{
public:
AiffAudioFormatReader (InputStream* in)
: AudioFormatReader (in, TRANS (aiffFormatName))
: AudioFormatReader (in, aiffFormatName)
{
using namespace AiffFileHelpers;
@@ -611,7 +609,7 @@ public:
AiffAudioFormatWriter (OutputStream* out, double rate,
unsigned int numChans, unsigned int bits,
const StringPairArray& metadataValues)
: AudioFormatWriter (out, TRANS (aiffFormatName), rate, numChans, bits),
: AudioFormatWriter (out, aiffFormatName, rate, numChans, bits),
lengthInSamples (0),
bytesWritten (0),
writeFailed (false)
@@ -879,8 +877,7 @@ private:
};
//==============================================================================
AiffAudioFormat::AiffAudioFormat()
: AudioFormat (TRANS (aiffFormatName), StringArray (aiffExtensions))
AiffAudioFormat::AiffAudioFormat() : AudioFormat (aiffFormatName, ".aiff .aif")
{
}


+ 2
- 2
source/modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp View File

@@ -327,7 +327,7 @@ class CoreAudioReader : public AudioFormatReader
{
public:
CoreAudioReader (InputStream* const inp)
: AudioFormatReader (inp, TRANS (coreAudioFormatName)),
: AudioFormatReader (inp, coreAudioFormatName),
ok (false), lastReadPosition (0)
{
usesFloatingPointData = true;
@@ -487,7 +487,7 @@ private:
//==============================================================================
CoreAudioFormat::CoreAudioFormat()
: AudioFormat (TRANS (coreAudioFormatName), findFileExtensionsForCoreAudioCodecs())
: AudioFormat (coreAudioFormatName, findFileExtensionsForCoreAudioCodecs())
{
}


+ 4
- 6
source/modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp View File

@@ -83,16 +83,14 @@ namespace FlacNamespace
//==============================================================================
static const char* const flacFormatName = "FLAC file";
static const char* const flacExtensions[] = { ".flac", 0 };
//==============================================================================
class FlacReader : public AudioFormatReader
{
public:
//==============================================================================
FlacReader (InputStream* const in)
: AudioFormatReader (in, TRANS (flacFormatName)),
: AudioFormatReader (in, flacFormatName),
reservoir (2, 0),
reservoirStart (0),
samplesInReservoir (0),
@@ -313,7 +311,7 @@ class FlacWriter : public AudioFormatWriter
{
public:
FlacWriter (OutputStream* const out, double rate, uint32 numChans, uint32 bits, int qualityOptionIndex)
: AudioFormatWriter (out, TRANS (flacFormatName), rate, numChans, bits)
: AudioFormatWriter (out, flacFormatName, rate, numChans, bits)
{
using namespace FlacNamespace;
encoder = FLAC__stream_encoder_new();
@@ -478,7 +476,7 @@ private:
//==============================================================================
FlacAudioFormat::FlacAudioFormat()
: AudioFormat (TRANS (flacFormatName), StringArray (flacExtensions))
: AudioFormat (flacFormatName, ".flac")
{
}
@@ -538,7 +536,7 @@ AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
StringArray FlacAudioFormat::getQualityOptions()
{
const char* options[] = { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)", 0 };
static const char* options[] = { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)", 0 };
return StringArray (options);
}


+ 5
- 10
source/modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp View File

@@ -147,12 +147,9 @@ private:
};
//==============================================================================
static const char* const lameFormatName = "MP3 file";
static const char* const lameExtensions[] = { ".mp3", nullptr };
LAMEEncoderAudioFormat::LAMEEncoderAudioFormat (const File& lameApplication)
: AudioFormat (TRANS (lameFormatName), StringArray (lameExtensions)),
lameApp (lameApplication)
: AudioFormat ("MP3 file", ".mp3"),
lameApp (lameApplication)
{
}
@@ -183,11 +180,9 @@ bool LAMEEncoderAudioFormat::isCompressed() { return true; }
StringArray LAMEEncoderAudioFormat::getQualityOptions()
{
const char* vbrOptions[] = { "VBR quality 0 (best)", "VBR quality 1", "VBR quality 2", "VBR quality 3",
"VBR quality 4 (normal)", "VBR quality 5", "VBR quality 6", "VBR quality 7", "VBR quality 8",
"VBR quality 9 (smallest)",
nullptr };
static const char* vbrOptions[] = { "VBR quality 0 (best)", "VBR quality 1", "VBR quality 2", "VBR quality 3",
"VBR quality 4 (normal)", "VBR quality 5", "VBR quality 6", "VBR quality 7",
"VBR quality 8", "VBR quality 9 (smallest)", nullptr };
StringArray opts (vbrOptions);
const int cbrRates[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };


+ 2
- 7
source/modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp View File

@@ -2929,14 +2929,13 @@ private:
//==============================================================================
static const char* const mp3FormatName = "MP3 file";
static const char* const mp3Extensions[] = { ".mp3", nullptr };
//==============================================================================
class MP3Reader : public AudioFormatReader
{
public:
MP3Reader (InputStream* const in)
: AudioFormatReader (in, TRANS (mp3FormatName)),
: AudioFormatReader (in, mp3FormatName),
stream (*in), currentPosition (0),
decodedStart (0), decodedEnd (0)
{
@@ -2953,7 +2952,6 @@ public:
}
}
//==============================================================================
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
int64 startSampleInFile, int numSamples) override
{
@@ -3109,10 +3107,7 @@ private:
}
//==============================================================================
MP3AudioFormat::MP3AudioFormat()
: AudioFormat (MP3Decoder::mp3FormatName, StringArray (MP3Decoder::mp3Extensions))
{}
MP3AudioFormat::MP3AudioFormat() : AudioFormat (MP3Decoder::mp3FormatName, ".mp3") {}
MP3AudioFormat::~MP3AudioFormat() {}
Array<int> MP3AudioFormat::getPossibleSampleRates() { return Array<int>(); }


+ 18
- 20
source/modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp View File

@@ -89,7 +89,6 @@ namespace OggVorbisNamespace
//==============================================================================
static const char* const oggFormatName = "Ogg-Vorbis file";
static const char* const oggExtensions[] = { ".ogg", 0 };
const char* const OggVorbisAudioFormat::encoderName = "encoder";
const char* const OggVorbisAudioFormat::id3title = "id3title";
@@ -106,7 +105,7 @@ class OggReader : public AudioFormatReader
{
public:
OggReader (InputStream* const inp)
: AudioFormatReader (inp, TRANS (oggFormatName)),
: AudioFormatReader (inp, oggFormatName),
reservoir (2, 4096),
reservoirStart (0),
samplesInReservoir (0)
@@ -115,10 +114,10 @@ public:
sampleRate = 0;
usesFloatingPointData = true;
callbacks.read_func = &oggReadCallback;
callbacks.seek_func = &oggSeekCallback;
callbacks.read_func = &oggReadCallback;
callbacks.seek_func = &oggSeekCallback;
callbacks.close_func = &oggCloseCallback;
callbacks.tell_func = &oggTellCallback;
callbacks.tell_func = &oggTellCallback;
const int err = ov_open_callbacks (input, &ovFile, 0, 0, callbacks);
@@ -222,12 +221,12 @@ public:
//==============================================================================
static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource)
{
return (size_t) (static_cast <InputStream*> (datasource)->read (ptr, (int) (size * nmemb))) / size;
return (size_t) (static_cast<InputStream*> (datasource)->read (ptr, (int) (size * nmemb))) / size;
}
static int oggSeekCallback (void* datasource, OggVorbisNamespace::ogg_int64_t offset, int whence)
{
InputStream* const in = static_cast <InputStream*> (datasource);
InputStream* const in = static_cast<InputStream*> (datasource);
if (whence == SEEK_CUR)
offset += in->getPosition();
@@ -245,7 +244,7 @@ public:
static long oggTellCallback (void* datasource)
{
return (long) static_cast <InputStream*> (datasource)->getPosition();
return (long) static_cast<InputStream*> (datasource)->getPosition();
}
private:
@@ -267,7 +266,7 @@ public:
const unsigned int bitsPerSample_,
const int qualityIndex,
const StringPairArray& metadata)
: AudioFormatWriter (out, TRANS (oggFormatName), sampleRate_, numChannels_, bitsPerSample_),
: AudioFormatWriter (out, oggFormatName, sampleRate_, numChannels_, bitsPerSample_),
ok (false)
{
using namespace OggVorbisNamespace;
@@ -279,13 +278,13 @@ public:
{
vorbis_comment_init (&vc);
addMetadata (metadata, OggVorbisAudioFormat::encoderName, "ENCODER");
addMetadata (metadata, OggVorbisAudioFormat::id3title, "TITLE");
addMetadata (metadata, OggVorbisAudioFormat::id3artist, "ARTIST");
addMetadata (metadata, OggVorbisAudioFormat::id3album, "ALBUM");
addMetadata (metadata, OggVorbisAudioFormat::id3comment, "COMMENT");
addMetadata (metadata, OggVorbisAudioFormat::id3date, "DATE");
addMetadata (metadata, OggVorbisAudioFormat::id3genre, "GENRE");
addMetadata (metadata, OggVorbisAudioFormat::encoderName, "ENCODER");
addMetadata (metadata, OggVorbisAudioFormat::id3title, "TITLE");
addMetadata (metadata, OggVorbisAudioFormat::id3artist, "ARTIST");
addMetadata (metadata, OggVorbisAudioFormat::id3album, "ALBUM");
addMetadata (metadata, OggVorbisAudioFormat::id3comment, "COMMENT");
addMetadata (metadata, OggVorbisAudioFormat::id3date, "DATE");
addMetadata (metadata, OggVorbisAudioFormat::id3genre, "GENRE");
addMetadata (metadata, OggVorbisAudioFormat::id3trackNumber, "TRACKNUMBER");
vorbis_analysis_init (&vd, &vi);
@@ -425,8 +424,7 @@ private:
//==============================================================================
OggVorbisAudioFormat::OggVorbisAudioFormat()
: AudioFormat (TRANS (oggFormatName), StringArray (oggExtensions))
OggVorbisAudioFormat::OggVorbisAudioFormat() : AudioFormat (oggFormatName, ".ogg")
{
}
@@ -481,8 +479,8 @@ AudioFormatWriter* OggVorbisAudioFormat::createWriterFor (OutputStream* out,
StringArray OggVorbisAudioFormat::getQualityOptions()
{
const char* options[] = { "64 kbps", "80 kbps", "96 kbps", "112 kbps", "128 kbps", "160 kbps",
"192 kbps", "224 kbps", "256 kbps", "320 kbps", "500 kbps", 0 };
static const char* options[] = { "64 kbps", "80 kbps", "96 kbps", "112 kbps", "128 kbps", "160 kbps",
"192 kbps", "224 kbps", "256 kbps", "320 kbps", "500 kbps", 0 };
return StringArray (options);
}


+ 17
- 19
source/modules/juce_audio_formats/codecs/juce_QuickTimeAudioFormat.cpp View File

@@ -66,14 +66,13 @@ namespace juce
bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle);
static const char* const quickTimeFormatName = "QuickTime file";
static const char* const quickTimeExtensions[] = { ".mov", ".mp3", ".mp4", ".m4a", 0 };
//==============================================================================
class QTAudioReader : public AudioFormatReader
{
public:
QTAudioReader (InputStream* const input_, const int trackNum_)
: AudioFormatReader (input_, TRANS (quickTimeFormatName)),
: AudioFormatReader (input_, quickTimeFormatName),
ok (false),
movie (0),
trackNum (trackNum_),
@@ -133,31 +132,31 @@ public:
trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame
/ GetMediaTimeScale (media);
OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor);
MovieAudioExtractionBegin (movie, 0, &extractor);
unsigned long output_layout_size;
err = MovieAudioExtractionGetPropertyInfo (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
0, &output_layout_size, 0);
OSStatus err = MovieAudioExtractionGetPropertyInfo (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
0, &output_layout_size, 0);
if (err != noErr)
return;
HeapBlock <AudioChannelLayout> qt_audio_channel_layout;
qt_audio_channel_layout.calloc (output_layout_size, 1);
err = MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
output_layout_size, qt_audio_channel_layout, 0);
MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
output_layout_size, qt_audio_channel_layout, 0);
qt_audio_channel_layout[0].mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
err = MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
output_layout_size,
qt_audio_channel_layout);
MovieAudioExtractionSetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
output_layout_size,
qt_audio_channel_layout);
err = MovieAudioExtractionGetProperty (extractor,
kQTPropertyClass_MovieAudioExtraction_Audio,
@@ -349,8 +348,7 @@ private:
//==============================================================================
QuickTimeAudioFormat::QuickTimeAudioFormat()
: AudioFormat (TRANS (quickTimeFormatName), StringArray (quickTimeExtensions))
QuickTimeAudioFormat::QuickTimeAudioFormat() : AudioFormat (quickTimeFormatName, ".mov .mp3 .mp4 .m4a")
{
}
@@ -368,7 +366,7 @@ bool QuickTimeAudioFormat::canDoMono() { return true; }
AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream,
const bool deleteStreamIfOpeningFails)
{
ScopedPointer <QTAudioReader> r (new QTAudioReader (sourceStream, 0));
ScopedPointer<QTAudioReader> r (new QTAudioReader (sourceStream, 0));
if (r->ok)
return r.release();


+ 7
- 14
source/modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp View File

@@ -23,7 +23,6 @@
*/
static const char* const wavFormatName = "WAV file";
static const char* const wavExtensions[] = { ".wav", ".bwf", 0 };
//==============================================================================
const char* const WavAudioFormat::bwavDescription = "bwav description";
@@ -225,7 +224,7 @@ namespace WavFileHelpers
{
data.setSize (roundUpSize (sizeof (SMPLChunk) + (size_t) (numLoops - 1) * sizeof (SampleLoop)), true);
SMPLChunk* const s = static_cast <SMPLChunk*> (data.getData());
SMPLChunk* const s = static_cast<SMPLChunk*> (data.getData());
s->manufacturer = getValue (values, "Manufacturer", "0");
s->product = getValue (values, "Product", "0");
@@ -293,7 +292,7 @@ namespace WavFileHelpers
if (keys.contains ("LowNote", true) && keys.contains ("HighNote", true))
{
data.setSize (8, true);
InstChunk* const inst = static_cast <InstChunk*> (data.getData());
InstChunk* const inst = static_cast<InstChunk*> (data.getData());
inst->baseNote = getValue (values, "MidiUnityNote", "60");
inst->detune = getValue (values, "Detune", "0");
@@ -356,7 +355,7 @@ namespace WavFileHelpers
{
data.setSize (roundUpSize (sizeof (CueChunk) + (size_t) (numCues - 1) * sizeof (Cue)), true);
CueChunk* const c = static_cast <CueChunk*> (data.getData());
CueChunk* const c = static_cast<CueChunk*> (data.getData());
c->numCues = ByteOrder::swapIfBigEndian ((uint32) numCues);
@@ -605,7 +604,7 @@ class WavAudioFormatReader : public AudioFormatReader
{
public:
WavAudioFormatReader (InputStream* const in)
: AudioFormatReader (in, TRANS (wavFormatName)),
: AudioFormatReader (in, wavFormatName),
bwavChunkStart (0),
bwavSize (0),
dataLength (0),
@@ -900,7 +899,7 @@ public:
WavAudioFormatWriter (OutputStream* const out, const double rate,
const unsigned int numChans, const unsigned int bits,
const StringPairArray& metadataValues)
: AudioFormatWriter (out, TRANS (wavFormatName), rate, numChans, bits),
: AudioFormatWriter (out, wavFormatName, rate, numChans, bits),
lengthInSamples (0),
bytesWritten (0),
writeFailed (false)
@@ -1197,14 +1196,8 @@ private:
};
//==============================================================================
WavAudioFormat::WavAudioFormat()
: AudioFormat (TRANS (wavFormatName), StringArray (wavExtensions))
{
}
WavAudioFormat::~WavAudioFormat()
{
}
WavAudioFormat::WavAudioFormat() : AudioFormat (wavFormatName, ".wav .bwf") {}
WavAudioFormat::~WavAudioFormat() {}
Array<int> WavAudioFormat::getPossibleSampleRates()
{


+ 7
- 4
source/modules/juce_audio_formats/format/juce_AudioFormat.cpp View File

@@ -22,9 +22,13 @@
==============================================================================
*/
AudioFormat::AudioFormat (const String& name, const StringArray& extensions)
: formatName (name),
fileExtensions (extensions)
AudioFormat::AudioFormat (String name, StringArray extensions)
: formatName (name), fileExtensions (extensions)
{
}
AudioFormat::AudioFormat (StringRef name, StringRef extensions)
: formatName (name.text), fileExtensions (StringArray::fromTokens (extensions, false))
{
}
@@ -32,7 +36,6 @@ AudioFormat::~AudioFormat()
{
}
//==============================================================================
bool AudioFormat::canHandleFile (const File& f)
{
for (int i = 0; i < fileExtensions.size(); ++i)


+ 10
- 5
source/modules/juce_audio_formats/format/juce_AudioFormat.h View File

@@ -42,7 +42,6 @@ public:
//==============================================================================
/** Returns the name of this format.
e.g. "WAV file" or "AIFF file"
*/
const String& getFormatName() const;
@@ -157,11 +156,17 @@ protected:
/** Creates an AudioFormat object.
@param formatName this sets the value that will be returned by getFormatName()
@param fileExtensions a zero-terminated list of file extensions - this is what will
be returned by getFileExtension()
@param fileExtensions an array of file extensions - these will be returned by getFileExtensions()
*/
AudioFormat (String formatName, StringArray fileExtensions);
/** Creates an AudioFormat object.
@param formatName this sets the value that will be returned by getFormatName()
@param fileExtensions a whitespace-separated list of file extensions - these will
be returned by getFileExtensions()
*/
AudioFormat (const String& formatName,
const StringArray& fileExtensions);
AudioFormat (StringRef formatName, StringRef fileExtensions);
private:
//==============================================================================


+ 12
- 12
source/modules/juce_audio_formats/format/juce_AudioFormatWriter.cpp View File

@@ -127,7 +127,7 @@ bool AudioFormatWriter::writeFromAudioSource (AudioSource& source, int numSample
return true;
}
bool AudioFormatWriter::writeFromFloatArrays (const float** channels, int numSourceChannels, int numSamples)
bool AudioFormatWriter::writeFromFloatArrays (const float* const* channels, int numSourceChannels, int numSamples)
{
if (numSamples <= 0)
return true;
@@ -170,7 +170,7 @@ bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& sou
jassert (startSample >= 0 && startSample + numSamples <= source.getNumSamples() && numSourceChannels > 0);
if (startSample == 0)
return writeFromFloatArrays ((const float**) source.getArrayOfChannels(), numSourceChannels, numSamples);
return writeFromFloatArrays (source.getArrayOfChannels(), numSourceChannels, numSamples);
const float* chans [256];
jassert ((int) numChannels < numElementsInArray (chans));
@@ -184,12 +184,11 @@ bool AudioFormatWriter::writeFromAudioSampleBuffer (const AudioSampleBuffer& sou
}
//==============================================================================
class AudioFormatWriter::ThreadedWriter::Buffer : public AbstractFifo,
private TimeSliceClient
class AudioFormatWriter::ThreadedWriter::Buffer : private TimeSliceClient
{
public:
Buffer (TimeSliceThread& tst, AudioFormatWriter* w, int channels, int numSamples)
: AbstractFifo (numSamples),
: fifo (numSamples),
buffer (channels, numSamples),
timeSliceThread (tst),
writer (w),
@@ -209,7 +208,7 @@ public:
{}
}
bool write (const float** data, int numSamples)
bool write (const float* const* data, int numSamples)
{
if (numSamples <= 0 || ! isRunning)
return true;
@@ -217,7 +216,7 @@ public:
jassert (timeSliceThread.isThreadRunning()); // you need to get your thread running before pumping data into this!
int start1, size1, start2, size2;
prepareToWrite (numSamples, start1, size1, start2, size2);
fifo.prepareToWrite (numSamples, start1, size1, start2, size2);
if (size1 + size2 < numSamples)
return false;
@@ -228,7 +227,7 @@ public:
buffer.copyFrom (i, start2, data[i] + size1, size2);
}
finishedWrite (size1 + size2);
fifo.finishedWrite (size1 + size2);
timeSliceThread.notify();
return true;
}
@@ -240,10 +239,10 @@ public:
int writePendingData()
{
const int numToDo = getTotalSize() / 4;
const int numToDo = fifo.getTotalSize() / 4;
int start1, size1, start2, size2;
prepareToRead (numToDo, start1, size1, start2, size2);
fifo.prepareToRead (numToDo, start1, size1, start2, size2);
if (size1 <= 0)
return 10;
@@ -266,7 +265,7 @@ public:
samplesWritten += size2;
}
finishedRead (size1 + size2);
fifo.finishedRead (size1 + size2);
return 0;
}
@@ -281,6 +280,7 @@ public:
}
private:
AbstractFifo fifo;
AudioSampleBuffer buffer;
TimeSliceThread& timeSliceThread;
ScopedPointer<AudioFormatWriter> writer;
@@ -301,7 +301,7 @@ AudioFormatWriter::ThreadedWriter::~ThreadedWriter()
{
}
bool AudioFormatWriter::ThreadedWriter::write (const float** data, int numSamples)
bool AudioFormatWriter::ThreadedWriter::write (const float* const* data, int numSamples)
{
return buffer->write (data, numSamples);
}


+ 3
- 3
source/modules/juce_audio_formats/format/juce_AudioFormatWriter.h View File

@@ -128,7 +128,7 @@ public:
int startSample, int numSamples);
/** Writes some samples from a set of float data channels. */
bool writeFromFloatArrays (const float** channels, int numChannels, int numSamples);
bool writeFromFloatArrays (const float* const* channels, int numChannels, int numSamples);
//==============================================================================
/** Returns the sample rate being used. */
@@ -177,7 +177,7 @@ public:
The data must be an array containing the same number of channels as the
AudioFormatWriter object is using. None of these channels can be null.
*/
bool write (const float** data, int numSamples);
bool write (const float* const* data, int numSamples);
class JUCE_API IncomingDataReceiver
{
@@ -229,7 +229,7 @@ protected:
typedef AudioData::Pointer <DestSampleType, DestEndianness, AudioData::Interleaved, AudioData::NonConst> DestType;
typedef AudioData::Pointer <SourceSampleType, AudioData::NativeEndian, AudioData::NonInterleaved, AudioData::Const> SourceType;
static void write (void* destData, int numDestChannels, const int** source,
static void write (void* destData, int numDestChannels, const int* const* source,
int numSamples, const int sourceOffset = 0) noexcept
{
for (int i = 0; i < numDestChannels; ++i)


+ 1
- 1
source/modules/juce_audio_formats/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_audio_formats",
"name": "JUCE audio file format codecs",
"version": "2.1.3",
"version": "2.1.6",
"description": "Classes for reading and writing various audio file formats.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 3
- 1
source/modules/juce_audio_processors/format/juce_AudioPluginFormat.h View File

@@ -60,7 +60,9 @@ public:
/** Tries to recreate a type from a previously generated PluginDescription.
@see PluginDescription::createInstance
*/
virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) = 0;
virtual AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc,
double initialSampleRate,
int initialBufferSize) = 0;
/** Should do a quick check to see if this file or directory might be a plugin of
this format.


+ 7
- 19
source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp View File

@@ -74,28 +74,16 @@ void AudioPluginFormatManager::addFormat (AudioPluginFormat* const format)
formats.add (format);
}
AudioPluginInstance* AudioPluginFormatManager::createPluginInstance (const PluginDescription& description,
String& errorMessage) const
AudioPluginInstance* AudioPluginFormatManager::createPluginInstance (const PluginDescription& description, double rate,
int blockSize, String& errorMessage) const
{
AudioPluginInstance* result = nullptr;
for (int i = 0; i < formats.size(); ++i)
{
result = formats.getUnchecked(i)->createInstanceFromDescription (description);
if (result != nullptr)
break;
}
if (result == nullptr)
{
if (! doesPluginStillExist (description))
errorMessage = TRANS ("This plug-in file no longer exists");
else
errorMessage = TRANS ("This plug-in failed to load correctly");
}
if (AudioPluginInstance* result = formats.getUnchecked(i)->createInstanceFromDescription (description, rate, blockSize))
return result;
return result;
errorMessage = doesPluginStillExist (description) ? TRANS ("This plug-in failed to load correctly")
: TRANS ("This plug-in file no longer exists");
return nullptr;
}
bool AudioPluginFormatManager::doesPluginStillExist (const PluginDescription& description) const


+ 2
- 0
source/modules/juce_audio_processors/format/juce_AudioPluginFormatManager.h View File

@@ -77,6 +77,8 @@ public:
errorMessage string.
*/
AudioPluginInstance* createPluginInstance (const PluginDescription& description,
double initialSampleRate,
int initialBufferSize,
String& errorMessage) const;
/** Checks that the file or component for this plugin actually still exists.


+ 1
- 1
source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.h View File

@@ -38,7 +38,7 @@ public:
//==============================================================================
String getName() const override { return "AudioUnit"; }
void findAllTypesForFile (OwnedArray <PluginDescription>&, const String& fileOrIdentifier) override;
AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc) override;
AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc, double, int) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;


+ 35
- 51
source/modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm View File

@@ -331,14 +331,15 @@ public:
}
}
void initialise()
void initialise (double rate, int blockSize)
{
refreshParameterList();
updateNumChannels();
producesMidiMessages = canProduceMidiOutput();
setPluginCallbacks();
setPlayConfigDetails (numInputBusChannels * numInputBusses,
numOutputBusChannels * numOutputBusses, 0, 0);
numOutputBusChannels * numOutputBusses,
rate, blockSize);
setLatencySamples (0);
}
@@ -777,26 +778,18 @@ public:
void setCurrentProgramStateInformation (const void* data, int sizeInBytes) override
{
CFReadStreamRef stream = CFReadStreamCreateWithBytesNoCopy (kCFAllocatorDefault,
(const UInt8*) data,
sizeInBytes,
kCFAllocatorNull);
CFReadStreamRef stream = CFReadStreamCreateWithBytesNoCopy (kCFAllocatorDefault, (const UInt8*) data,
sizeInBytes, kCFAllocatorNull);
CFReadStreamOpen (stream);
CFPropertyListFormat format = kCFPropertyListBinaryFormat_v1_0;
CFPropertyListRef propertyList = CFPropertyListCreateFromStream (kCFAllocatorDefault,
stream,
0,
kCFPropertyListImmutable,
&format,
0);
CFPropertyListRef propertyList = CFPropertyListCreateFromStream (kCFAllocatorDefault, stream, 0,
kCFPropertyListImmutable, &format, 0);
CFRelease (stream);
if (propertyList != 0)
{
AudioUnitSetProperty (audioUnit,
kAudioUnitProperty_ClassInfo,
kAudioUnitScope_Global,
AudioUnitSetProperty (audioUnit, kAudioUnitProperty_ClassInfo, kAudioUnitScope_Global,
0, &propertyList, sizeof (propertyList));
sendAllParametersChangedEvents();
@@ -1004,11 +997,11 @@ private:
}
}
static void eventListenerCallback (void* userData, void*, const AudioUnitEvent* event,
static void eventListenerCallback (void* userRef, void*, const AudioUnitEvent* event,
UInt64, AudioUnitParameterValue value)
{
jassert (event != nullptr);
static_cast <AudioUnitPluginInstance*> (userData)->eventCallback (*event, value);
static_cast<AudioUnitPluginInstance*> (userRef)->eventCallback (*event, value);
}
//==============================================================================
@@ -1053,9 +1046,7 @@ private:
for (UInt32 i = 0; i < pktlist->numPackets; ++i)
{
midiConcatenator.pushMidiData (packet->data, (int) packet->length,
time, (void*) nullptr, *this);
midiConcatenator.pushMidiData (packet->data, (int) packet->length, time, (void*) nullptr, *this);
packet = MIDIPacketNext (packet);
}
}
@@ -1148,40 +1139,39 @@ private:
}
//==============================================================================
static OSStatus renderGetInputCallback (void* inRefCon, AudioUnitRenderActionFlags* ioActionFlags,
static OSStatus renderGetInputCallback (void* hostRef, AudioUnitRenderActionFlags* ioActionFlags,
const AudioTimeStamp* inTimeStamp, UInt32 inBusNumber,
UInt32 inNumberFrames, AudioBufferList* ioData)
{
return static_cast <AudioUnitPluginInstance*> (inRefCon)
return static_cast<AudioUnitPluginInstance*> (hostRef)
->renderGetInput (ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, ioData);
}
static OSStatus renderMidiOutputCallback (void* userData, const AudioTimeStamp* timeStamp, UInt32 midiOutNum,
static OSStatus renderMidiOutputCallback (void* hostRef, const AudioTimeStamp* timeStamp, UInt32 midiOutNum,
const struct MIDIPacketList* pktlist)
{
return static_cast <AudioUnitPluginInstance*> (userData)->renderMidiOutput (pktlist);
return static_cast<AudioUnitPluginInstance*> (hostRef)->renderMidiOutput (pktlist);
}
static OSStatus getBeatAndTempoCallback (void* inHostUserData, Float64* outCurrentBeat, Float64* outCurrentTempo)
static OSStatus getBeatAndTempoCallback (void* hostRef, Float64* outCurrentBeat, Float64* outCurrentTempo)
{
return static_cast <AudioUnitPluginInstance*> (inHostUserData)
->getBeatAndTempo (outCurrentBeat, outCurrentTempo);
return static_cast<AudioUnitPluginInstance*> (hostRef)->getBeatAndTempo (outCurrentBeat, outCurrentTempo);
}
static OSStatus getMusicalTimeLocationCallback (void* inHostUserData, UInt32* outDeltaSampleOffsetToNextBeat,
static OSStatus getMusicalTimeLocationCallback (void* hostRef, UInt32* outDeltaSampleOffsetToNextBeat,
Float32* outTimeSig_Numerator, UInt32* outTimeSig_Denominator,
Float64* outCurrentMeasureDownBeat)
{
return static_cast <AudioUnitPluginInstance*> (inHostUserData)
return static_cast<AudioUnitPluginInstance*> (hostRef)
->getMusicalTimeLocation (outDeltaSampleOffsetToNextBeat, outTimeSig_Numerator,
outTimeSig_Denominator, outCurrentMeasureDownBeat);
}
static OSStatus getTransportStateCallback (void* inHostUserData, Boolean* outIsPlaying, Boolean* outTransportStateChanged,
static OSStatus getTransportStateCallback (void* hostRef, Boolean* outIsPlaying, Boolean* outTransportStateChanged,
Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling,
Float64* outCycleStartBeat, Float64* outCycleEndBeat)
{
return static_cast <AudioUnitPluginInstance*> (inHostUserData)
return static_cast<AudioUnitPluginInstance*> (hostRef)
->getTransportState (outIsPlaying, outTransportStateChanged, outCurrentSampleInTimeLine,
outIsCycling, outCycleStartBeat, outCycleEndBeat);
}
@@ -1211,7 +1201,7 @@ private:
void updateNumChannels()
{
numInputBusses = getElementCount (kAudioUnitScope_Input);
numInputBusses = getElementCount (kAudioUnitScope_Input);
numOutputBusses = getElementCount (kAudioUnitScope_Output);
AUChannelInfo supportedChannels [128];
@@ -1299,7 +1289,7 @@ class AudioUnitPluginWindowCocoa : public AudioProcessorEditor,
public Timer
{
public:
AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& p, const bool createGenericViewIfNeeded)
AudioUnitPluginWindowCocoa (AudioUnitPluginInstance& p, bool createGenericViewIfNeeded)
: AudioProcessorEditor (&p),
plugin (p)
{
@@ -1510,17 +1500,14 @@ private:
class InnerWrapperComponent : public CarbonViewWrapperComponent
{
public:
InnerWrapperComponent (AudioUnitPluginWindowCarbon& owner_)
: owner (owner_)
{
}
InnerWrapperComponent (AudioUnitPluginWindowCarbon& w) : owner (w) {}
~InnerWrapperComponent()
{
deleteWindow();
}
HIViewRef attachView (WindowRef windowRef, HIViewRef rootView)
HIViewRef attachView (WindowRef windowRef, HIViewRef rootView) override
{
JUCE_AU_LOG ("Opening AU GUI: " + owner.plugin.getName());
@@ -1545,7 +1532,7 @@ private:
return pluginView;
}
void removeView (HIViewRef)
void removeView (HIViewRef) override
{
owner.closeViewComponent();
}
@@ -1569,7 +1556,7 @@ AudioProcessorEditor* AudioUnitPluginInstance::createEditor()
{
ScopedPointer<AudioProcessorEditor> w (new AudioUnitPluginWindowCocoa (*this, false));
if (! static_cast <AudioUnitPluginWindowCocoa*> (w.get())->isValid())
if (! static_cast<AudioUnitPluginWindowCocoa*> (w.get())->isValid())
w = nullptr;
#if JUCE_SUPPORT_CARBON
@@ -1577,7 +1564,7 @@ AudioProcessorEditor* AudioUnitPluginInstance::createEditor()
{
w = new AudioUnitPluginWindowCarbon (*this);
if (! static_cast <AudioUnitPluginWindowCarbon*> (w.get())->isValid())
if (! static_cast<AudioUnitPluginWindowCarbon*> (w.get())->isValid())
w = nullptr;
}
#endif
@@ -1611,9 +1598,9 @@ void AudioUnitPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>&
try
{
ScopedPointer <AudioPluginInstance> createdInstance (createInstanceFromDescription (desc));
ScopedPointer<AudioPluginInstance> createdInstance (createInstanceFromDescription (desc, 44100.0, 512));
if (AudioUnitPluginInstance* const auInstance = dynamic_cast <AudioUnitPluginInstance*> (createdInstance.get()))
if (AudioUnitPluginInstance* auInstance = dynamic_cast<AudioUnitPluginInstance*> (createdInstance.get()))
results.add (new PluginDescription (auInstance->getPluginDescription()));
}
catch (...)
@@ -1622,15 +1609,15 @@ void AudioUnitPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>&
}
}
AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc)
AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const PluginDescription& desc, double rate, int blockSize)
{
if (fileMightContainThisPluginType (desc.fileOrIdentifier))
{
ScopedPointer <AudioUnitPluginInstance> result (new AudioUnitPluginInstance (desc.fileOrIdentifier));
ScopedPointer<AudioUnitPluginInstance> result (new AudioUnitPluginInstance (desc.fileOrIdentifier));
if (result->audioUnit != nullptr)
{
result->initialise();
result->initialise (rate, blockSize);
return result.release();
}
}
@@ -1638,8 +1625,7 @@ AudioPluginInstance* AudioUnitPluginFormat::createInstanceFromDescription (const
return nullptr;
}
StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearchPath& /*directoriesToSearch*/,
const bool /*recursive*/)
StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearchPath&, bool /*recursive*/)
{
StringArray result;
AudioComponent comp = nullptr;
@@ -1662,9 +1648,7 @@ StringArray AudioUnitPluginFormat::searchPathsForPlugins (const FileSearchPath&
|| desc.componentType == kAudioUnitType_Generator
|| desc.componentType == kAudioUnitType_Panner)
{
const String s (AudioUnitFormatHelpers::createPluginIdentifier (desc));
DBG (s);
result.add (s);
result.add (AudioUnitFormatHelpers::createPluginIdentifier (desc));
}
}


+ 10
- 12
source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp View File

@@ -167,8 +167,10 @@ public:
handle = nullptr;
}
void initialise()
void initialise (double initialSampleRate, int initialBlockSize)
{
setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
if (initialised || plugin == nullptr || handle == nullptr)
return;
@@ -199,9 +201,7 @@ public:
for (int i = 0; i < parameters.size(); ++i)
plugin->connect_port (handle, parameters[i], &(parameterValues[i].scaled));
setPlayConfigDetails (inputs.size(), outputs.size(),
getSampleRate() > 0 ? getSampleRate() : 44100.0f,
getBlockSize() > 0 ? getBlockSize() : 512);
setPlayConfigDetails (inputs.size(), outputs.size(), initialSampleRate, initialBlockSize);
setCurrentProgram (0);
setLatencySamples (0);
@@ -257,12 +257,9 @@ public:
//==============================================================================
void prepareToPlay (double newSampleRate, int samplesPerBlockExpected)
{
setPlayConfigDetails (inputs.size(), outputs.size(),
newSampleRate, samplesPerBlockExpected);
setLatencySamples (0);
initialise();
initialise (newSampleRate, samplesPerBlockExpected);
if (initialised)
{
@@ -584,12 +581,12 @@ void LADSPAPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& re
desc.fileOrIdentifier = fileOrIdentifier;
desc.uid = 0;
ScopedPointer<LADSPAPluginInstance> instance (dynamic_cast <LADSPAPluginInstance*> (createInstanceFromDescription (desc)));
ScopedPointer<LADSPAPluginInstance> instance (dynamic_cast<LADSPAPluginInstance*> (createInstanceFromDescription (desc, 44100.0, 512)));
if (instance == nullptr || ! instance->isValid())
return;
instance->initialise();
instance->initialise (44100.0, 512);
instance->fillInPluginDescription (desc);
@@ -613,7 +610,8 @@ void LADSPAPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& re
}
}
AudioPluginInstance* LADSPAPluginFormat::createInstanceFromDescription (const PluginDescription& desc)
AudioPluginInstance* LADSPAPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
double sampleRate, int blockSize)
{
ScopedPointer<LADSPAPluginInstance> result;
@@ -633,7 +631,7 @@ AudioPluginInstance* LADSPAPluginFormat::createInstanceFromDescription (const Pl
result = new LADSPAPluginInstance (module);
if (result->plugin != nullptr && result->isValid())
result->initialise();
result->initialise (sampleRate, blockSize);
else
result = nullptr;
}


+ 10
- 10
source/modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.h View File

@@ -36,16 +36,16 @@ public:
~LADSPAPluginFormat();
//==============================================================================
String getName() const { return "LADSPA"; }
void findAllTypesForFile (OwnedArray <PluginDescription>&, const String& fileOrIdentifier);
AudioPluginInstance* createInstanceFromDescription (const PluginDescription& desc);
bool fileMightContainThisPluginType (const String& fileOrIdentifier);
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier);
bool pluginNeedsRescanning (const PluginDescription&);
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive);
bool doesPluginStillExist (const PluginDescription&);
FileSearchPath getDefaultLocationsToSearch();
bool canScanForPlugins() const { return true; }
String getName() const override { return "LADSPA"; }
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
AudioPluginInstance* createInstanceFromDescription (const PluginDescription&, double, int) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;
StringArray searchPathsForPlugins (const FileSearchPath&, bool recursive) override;
bool doesPluginStillExist (const PluginDescription&) override;
FileSearchPath getDefaultLocationsToSearch() override;
bool canScanForPlugins() const override { return true; }
private:
void recursiveFileSearch (StringArray&, const File&, bool recursive);


+ 43
- 37
source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp View File

@@ -32,7 +32,7 @@
#if JUCE_MAC
static bool makeFSRefFromPath (FSRef* destFSRef, const String& path)
{
return FSPathMakeRef (reinterpret_cast <const UInt8*> (path.toRawUTF8()), destFSRef, 0) == noErr;
return FSPathMakeRef (reinterpret_cast<const UInt8*> (path.toRawUTF8()), destFSRef, 0) == noErr;
}
#endif
@@ -378,7 +378,7 @@ public:
JUCE_VST_LOG ("Attempting to load VST: " + file.getFullPathName());
ScopedPointer <ModuleHandle> m (new ModuleHandle (file));
ScopedPointer<ModuleHandle> m (new ModuleHandle (file));
if (! m->open())
m = nullptr;
@@ -389,10 +389,8 @@ public:
}
//==============================================================================
ModuleHandle (const File& file_)
: file (file_),
moduleMain (nullptr),
customMain (nullptr)
ModuleHandle (const File& f)
: file (f), moduleMain (nullptr), customMain (nullptr)
#if JUCE_MAC
#if JUCE_PPC
, fragId (0)
@@ -403,10 +401,10 @@ public:
getActiveModules().add (this);
#if JUCE_WINDOWS || JUCE_LINUX
fullParentDirectoryPathName = file_.getParentDirectory().getFullPathName();
fullParentDirectoryPathName = f.getParentDirectory().getFullPathName();
#elif JUCE_MAC
FSRef ref;
makeFSRefFromPath (&ref, file_.getParentDirectory().getFullPathName());
makeFSRefFromPath (&ref, f.getParentDirectory().getFullPathName());
FSGetCatalogInfo (&ref, kFSCatInfoNone, 0, 0, &parentDirFSSpec, 0);
#endif
}
@@ -828,7 +826,7 @@ public:
desc.isInstrument = (effect != nullptr && (effect->flags & effFlagsIsSynth) != 0);
}
void initialise()
void initialise (double initialSampleRate, int initialBlockSize)
{
if (initialised || effect == nullptr)
return;
@@ -844,6 +842,9 @@ public:
JUCE_VST_LOG ("Initialising VST: " + module->pluginName);
initialised = true;
setPlayConfigDetails (effect->numInputs, effect->numOutputs,
initialSampleRate, initialBlockSize);
dispatch (effIdentify, 0, 0, 0, 0);
if (getSampleRate() > 0)
@@ -922,7 +923,7 @@ public:
vstHostTime.samplePos = 0;
vstHostTime.flags = kVstNanosValid | kVstAutomationWriting | kVstAutomationReading;
initialise();
initialise (rate, samplesPerBlockExpected);
if (initialised)
{
@@ -1185,7 +1186,9 @@ public:
}
//==============================================================================
int getNumPrograms() override { return effect != nullptr ? effect->numPrograms : 0; }
int getNumPrograms() override { return effect != nullptr ? jmax (0, effect->numPrograms) : 0; }
// NB: some plugs return negative numbers from this function.
int getCurrentProgram() override { return (int) dispatch (effGetProgram, 0, 0, 0, 0); }
void setCurrentProgram (int newIndex) override
@@ -1196,18 +1199,17 @@ public:
const String getProgramName (int index) override
{
if (index == getCurrentProgram())
return getCurrentProgramName();
if (effect != nullptr)
if (index >= 0)
{
char nm [256] = { 0 };
if (index == getCurrentProgram())
return getCurrentProgramName();
if (dispatch (effGetProgramNameIndexed,
jlimit (0, getNumPrograms(), index),
-1, nm, 0) != 0)
if (effect != nullptr)
{
return String (CharPointer_UTF8 (nm)).trim();
char nm[264] = { 0 };
if (dispatch (effGetProgramNameIndexed, jlimit (0, getNumPrograms(), index), -1, nm, 0) != 0)
return String (CharPointer_UTF8 (nm)).trim();
}
}
@@ -1216,7 +1218,7 @@ public:
void changeProgramName (int index, const String& newName) override
{
if (index == getCurrentProgram())
if (index >= 0 && index == getCurrentProgram())
{
if (getNumPrograms() > 0 && newName != getCurrentProgramName())
dispatch (effSetProgramName, 0, 0, (void*) newName.substring (0, 24).toRawUTF8(), 0.0f);
@@ -1717,7 +1719,7 @@ private:
const int index = getCurrentProgram();
if (programNames[index].isEmpty())
if (index >= 0 && programNames[index].isEmpty())
{
while (programNames.size() < index)
programNames.add (String::empty);
@@ -2571,10 +2573,10 @@ private:
};
friend class InnerWrapperComponent;
ScopedPointer <InnerWrapperComponent> innerWrapper;
ScopedPointer<InnerWrapperComponent> innerWrapper;
#else
ScopedPointer <NSViewComponent> innerWrapper;
ScopedPointer<NSViewComponent> innerWrapper;
#endif
void resized() override
@@ -2611,16 +2613,20 @@ VSTPluginFormat::~VSTPluginFormat() {}
static VSTPluginInstance* createAndUpdateDesc (VSTPluginFormat& format, PluginDescription& desc)
{
if (VSTPluginInstance* instance = dynamic_cast <VSTPluginInstance*> (format.createInstanceFromDescription (desc)))
if (AudioPluginInstance* p = format.createInstanceFromDescription (desc, 44100.0, 512))
{
#if JUCE_MAC
if (instance->module->resFileId != 0)
UseResFile (instance->module->resFileId);
#endif
if (VSTPluginInstance* instance = dynamic_cast<VSTPluginInstance*> (p))
{
#if JUCE_MAC
if (instance->module->resFileId != 0)
UseResFile (instance->module->resFileId);
#endif
instance->fillInPluginDescription (desc);
instance->fillInPluginDescription (desc);
return instance;
}
return instance;
jassertfalse;
}
return nullptr;
@@ -2667,6 +2673,7 @@ void VSTPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& resul
{
jassert (desc.uid == uid);
desc.name = shellEffectName;
desc.hasSharedContainer = true;
if (! arrayContainsPlugin (results, desc))
results.add (new PluginDescription (desc));
@@ -2675,9 +2682,10 @@ void VSTPluginFormat::findAllTypesForFile (OwnedArray <PluginDescription>& resul
}
}
AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const PluginDescription& desc)
AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const PluginDescription& desc,
double sampleRate, int blockSize)
{
ScopedPointer <VSTPluginInstance> result;
ScopedPointer<VSTPluginInstance> result;
if (fileMightContainThisPluginType (desc.fileOrIdentifier))
{
@@ -2686,9 +2694,7 @@ AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const Plugi
const File previousWorkingDirectory (File::getCurrentWorkingDirectory());
file.getParentDirectory().setAsCurrentWorkingDirectory();
const ModuleHandle::Ptr module (ModuleHandle::findOrCreateModule (file));
if (module != nullptr)
if (ModuleHandle::Ptr module = ModuleHandle::findOrCreateModule (file))
{
shellUIDToCreate = desc.uid;
@@ -2697,7 +2703,7 @@ AudioPluginInstance* VSTPluginFormat::createInstanceFromDescription (const Plugi
if (result->effect != nullptr)
{
result->effect->resvd2 = (VstIntPtr) (pointer_sized_int) (VSTPluginInstance*) result;
result->initialise();
result->initialise (sampleRate, blockSize);
}
else
{


+ 2
- 2
source/modules/juce_audio_processors/format_types/juce_VSTPluginFormat.h View File

@@ -86,8 +86,8 @@ public:
//==============================================================================
String getName() const override { return "VST"; }
void findAllTypesForFile (OwnedArray <PluginDescription>&, const String& fileOrIdentifier) override;
AudioPluginInstance* createInstanceFromDescription (const PluginDescription&) override;
void findAllTypesForFile (OwnedArray<PluginDescription>&, const String& fileOrIdentifier) override;
AudioPluginInstance* createInstanceFromDescription (const PluginDescription&, double, int) override;
bool fileMightContainThisPluginType (const String& fileOrIdentifier) override;
String getNameOfPluginFromIdentifier (const String& fileOrIdentifier) override;
bool pluginNeedsRescanning (const PluginDescription&) override;


+ 1
- 1
source/modules/juce_audio_processors/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_audio_processors",
"name": "JUCE audio plugin hosting classes",
"version": "2.1.3",
"version": "2.1.6",
"description": "Classes for loading and playing VST, AU, or internally-generated audio processors.",
"website": "http://www.juce.com/juce",
"license": "GPL/Commercial",


+ 57
- 41
source/modules/juce_audio_processors/processors/juce_AudioProcessor.cpp View File

@@ -55,7 +55,7 @@ AudioProcessor::~AudioProcessor()
#endif
}
void AudioProcessor::setPlayHead (AudioPlayHead* const newPlayHead) noexcept
void AudioProcessor::setPlayHead (AudioPlayHead* const newPlayHead)
{
playHead = newPlayHead;
}
@@ -139,44 +139,59 @@ AudioProcessorListener* AudioProcessor::getListenerLocked (const int index) cons
void AudioProcessor::sendParamChangeMessageToListeners (const int parameterIndex, const float newValue)
{
jassert (isPositiveAndBelow (parameterIndex, getNumParameters()));
for (int i = listeners.size(); --i >= 0;)
if (AudioProcessorListener* l = getListenerLocked (i))
l->audioProcessorParameterChanged (this, parameterIndex, newValue);
if (isPositiveAndBelow (parameterIndex, getNumParameters()))
{
for (int i = listeners.size(); --i >= 0;)
if (AudioProcessorListener* l = getListenerLocked (i))
l->audioProcessorParameterChanged (this, parameterIndex, newValue);
}
else
{
jassertfalse; // called with an out-of-range parameter index!
}
}
void AudioProcessor::beginParameterChangeGesture (int parameterIndex)
{
jassert (isPositiveAndBelow (parameterIndex, getNumParameters()));
#if JUCE_DEBUG
// This means you've called beginParameterChangeGesture twice in succession without a matching
// call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it.
jassert (! changingParams [parameterIndex]);
changingParams.setBit (parameterIndex);
#endif
for (int i = listeners.size(); --i >= 0;)
if (AudioProcessorListener* l = getListenerLocked (i))
l->audioProcessorParameterChangeGestureBegin (this, parameterIndex);
if (isPositiveAndBelow (parameterIndex, getNumParameters()))
{
#if JUCE_DEBUG
// This means you've called beginParameterChangeGesture twice in succession without a matching
// call to endParameterChangeGesture. That might be fine in most hosts, but better to avoid doing it.
jassert (! changingParams [parameterIndex]);
changingParams.setBit (parameterIndex);
#endif
for (int i = listeners.size(); --i >= 0;)
if (AudioProcessorListener* l = getListenerLocked (i))
l->audioProcessorParameterChangeGestureBegin (this, parameterIndex);
}
else
{
jassertfalse; // called with an out-of-range parameter index!
}
}
void AudioProcessor::endParameterChangeGesture (int parameterIndex)
{
jassert (isPositiveAndBelow (parameterIndex, getNumParameters()));
#if JUCE_DEBUG
// This means you've called endParameterChangeGesture without having previously called
// endParameterChangeGesture. That might be fine in most hosts, but better to keep the
// calls matched correctly.
jassert (changingParams [parameterIndex]);
changingParams.clearBit (parameterIndex);
#endif
for (int i = listeners.size(); --i >= 0;)
if (AudioProcessorListener* l = getListenerLocked (i))
l->audioProcessorParameterChangeGestureEnd (this, parameterIndex);
if (isPositiveAndBelow (parameterIndex, getNumParameters()))
{
#if JUCE_DEBUG
// This means you've called endParameterChangeGesture without having previously called
// endParameterChangeGesture. That might be fine in most hosts, but better to keep the
// calls matched correctly.
jassert (changingParams [parameterIndex]);
changingParams.clearBit (parameterIndex);
#endif
for (int i = listeners.size(); --i >= 0;)
if (AudioProcessorListener* l = getListenerLocked (i))
l->audioProcessorParameterChangeGestureEnd (this, parameterIndex);
}
else
{
jassertfalse; // called with an out-of-range parameter index!
}
}
void AudioProcessor::updateHostDisplay()
@@ -247,16 +262,17 @@ const uint32 magicXmlNumber = 0x21324356;
void AudioProcessor::copyXmlToBinary (const XmlElement& xml, juce::MemoryBlock& destData)
{
const String xmlString (xml.createDocument (String::empty, true, false));
const size_t stringLength = xmlString.getNumBytesAsUTF8();
destData.setSize (stringLength + 9);
uint32* const d = static_cast<uint32*> (destData.getData());
d[0] = ByteOrder::swapIfBigEndian ((const uint32) magicXmlNumber);
d[1] = ByteOrder::swapIfBigEndian ((const uint32) stringLength);
{
MemoryOutputStream out (destData, false);
out.writeInt (magicXmlNumber);
out.writeInt (0);
xml.writeToStream (out, String::empty, true, false);
out.writeByte (0);
}
xmlString.copyToUTF8 ((CharPointer_UTF8::CharType*) (d + 2), stringLength + 1);
// go back and write the string length..
static_cast<uint32*> (destData.getData())[1]
= ByteOrder::swapIfBigEndian ((uint32) destData.getSize() - 9);
}
XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeInBytes)
@@ -276,7 +292,7 @@ XmlElement* AudioProcessor::getXmlFromBinary (const void* data, const int sizeIn
//==============================================================================
void AudioProcessorListener::audioProcessorParameterChangeGestureBegin (AudioProcessor*, int) {}
void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {}
void AudioProcessorListener::audioProcessorParameterChangeGestureEnd (AudioProcessor*, int) {}
//==============================================================================
bool AudioPlayHead::CurrentPositionInfo::operator== (const CurrentPositionInfo& other) const noexcept


+ 6
- 6
source/modules/juce_audio_processors/processors/juce_AudioProcessor.h View File

@@ -596,7 +596,7 @@ public:
The processor will not take ownership of the object, so the caller must delete it when
it is no longer being used.
*/
void setPlayHead (AudioPlayHead* newPlayHead) noexcept;
virtual void setPlayHead (AudioPlayHead* newPlayHead);
//==============================================================================
/** This is called by the processor to specify its details before being played. */
@@ -625,10 +625,6 @@ public:
*/
WrapperType wrapperType;
/** @internal */
static void JUCE_CALLTYPE setTypeOfNextNewPlugin (WrapperType);
protected:
//==============================================================================
/** Helper function that just converts an xml element into a binary blob.
@@ -648,6 +644,10 @@ protected:
*/
static XmlElement* getXmlFromBinary (const void* data, int sizeInBytes);
/** @internal */
static void JUCE_CALLTYPE setTypeOfNextNewPlugin (WrapperType);
protected:
/** @internal */
AudioPlayHead* playHead;
@@ -655,7 +655,7 @@ protected:
void sendParamChangeMessageToListeners (int parameterIndex, float newValue);
private:
Array <AudioProcessorListener*> listeners;
Array<AudioProcessorListener*> listeners;
Component::SafePointer<AudioProcessorEditor> activeEditor;
double sampleRate;
int blockSize, numInputChannels, numOutputChannels, latencySamples;


+ 7
- 2
source/modules/juce_audio_processors/processors/juce_PluginDescription.cpp View File

@@ -26,7 +26,8 @@ PluginDescription::PluginDescription()
: uid (0),
isInstrument (false),
numInputChannels (0),
numOutputChannels (0)
numOutputChannels (0),
hasSharedContainer (false)
{
}
@@ -46,7 +47,8 @@ PluginDescription::PluginDescription (const PluginDescription& other)
uid (other.uid),
isInstrument (other.isInstrument),
numInputChannels (other.numInputChannels),
numOutputChannels (other.numOutputChannels)
numOutputChannels (other.numOutputChannels),
hasSharedContainer (other.hasSharedContainer)
{
}
@@ -64,6 +66,7 @@ PluginDescription& PluginDescription::operator= (const PluginDescription& other)
lastFileModTime = other.lastFileModTime;
numInputChannels = other.numInputChannels;
numOutputChannels = other.numOutputChannels;
hasSharedContainer = other.hasSharedContainer;
return *this;
}
@@ -99,6 +102,7 @@ XmlElement* PluginDescription::createXml() const
e->setAttribute ("fileTime", String::toHexString (lastFileModTime.toMilliseconds()));
e->setAttribute ("numInputs", numInputChannels);
e->setAttribute ("numOutputs", numOutputChannels);
e->setAttribute ("isShell", hasSharedContainer);
return e;
}
@@ -119,6 +123,7 @@ bool PluginDescription::loadFromXml (const XmlElement& xml)
lastFileModTime = Time (xml.getStringAttribute ("fileTime").getHexValue64());
numInputChannels = xml.getIntAttribute ("numInputs");
numOutputChannels = xml.getIntAttribute ("numOutputs");
hasSharedContainer = xml.getBoolAttribute ("isShell", false);
return true;
}


+ 20
- 19
source/modules/juce_audio_processors/processors/juce_PluginDescription.h View File

@@ -28,9 +28,9 @@
//==============================================================================
/**
A small class to represent some facts about a particular type of plugin.
A small class to represent some facts about a particular type of plug-in.
This class is for storing and managing the details about a plugin without
This class is for storing and managing the details about a plug-in without
actually having to load an instance of it.
A KnownPluginList contains a list of PluginDescription objects.
@@ -47,21 +47,19 @@ public:
~PluginDescription();
//==============================================================================
/** The name of the plugin. */
/** The name of the plug-in. */
String name;
/** A more descriptive name for the plugin.
This may be the same as the 'name' field, but some plugins may provide an
/** A more descriptive name for the plug-in.
This may be the same as the 'name' field, but some plug-ins may provide an
alternative name.
*/
String descriptiveName;
/** The plugin format, e.g. "VST", "AudioUnit", etc.
*/
/** The plug-in format, e.g. "VST", "AudioUnit", etc. */
String pluginFormatName;
/** A category, such as "Dynamics", "Reverbs", etc.
*/
/** A category, such as "Dynamics", "Reverbs", etc. */
String category;
/** The manufacturer. */
@@ -70,20 +68,20 @@ public:
/** The version. This string doesn't have any particular format. */
String version;
/** Either the file containing the plugin module, or some other unique way
/** Either the file containing the plug-in module, or some other unique way
of identifying it.
E.g. for an AU, this would be an ID string that the component manager
could use to retrieve the plugin. For a VST, it's the file path.
could use to retrieve the plug-in. For a VST, it's the file path.
*/
String fileOrIdentifier;
/** The last time the plugin file was changed.
This is handy when scanning for new or changed plugins.
/** The last time the plug-in file was changed.
This is handy when scanning for new or changed plug-ins.
*/
Time lastFileModTime;
/** A unique ID for the plugin.
/** A unique ID for the plug-in.
Note that this might not be unique between formats, e.g. a VST and some
other format might actually have the same id.
@@ -92,7 +90,7 @@ public:
*/
int uid;
/** True if the plugin identifies itself as a synthesiser. */
/** True if the plug-in identifies itself as a synthesiser. */
bool isInstrument;
/** The number of inputs. */
@@ -101,10 +99,13 @@ public:
/** The number of outputs. */
int numOutputChannels;
/** Returns true if the two descriptions refer the the same plugin.
/** True if the plug-in is part of a multi-type container, e.g. a VST Shell. */
bool hasSharedContainer;
/** Returns true if the two descriptions refer the the same plug-in.
This isn't quite as simple as them just having the same file (because of
shell plugins).
shell plug-ins).
*/
bool isDuplicateOf (const PluginDescription& other) const;
@@ -113,7 +114,7 @@ public:
plugin again.
This contains less info than the XML encoding, and is independent of the
plugin's file location, so can be used to store a plugin ID for use
plug-in's file location, so can be used to store a plug-in ID for use
across different machines.
*/
String createIdentifierString() const;
@@ -128,7 +129,7 @@ public:
/** Reloads the info in this structure from an XML record that was previously
saved with createXML().
Returns true if the XML was a valid plugin description.
Returns true if the XML was a valid plug-in description.
*/
bool loadFromXml (const XmlElement& xml);


+ 39
- 7
source/modules/juce_core/containers/juce_Array.h View File

@@ -85,7 +85,7 @@ public:
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
Array (Array<ElementType, TypeOfCriticalSectionToUse>&& other) noexcept
: data (static_cast <ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data)),
: data (static_cast<ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data)),
numUsed (other.numUsed)
{
other.numUsed = 0;
@@ -143,7 +143,7 @@ public:
Array& operator= (Array&& other) noexcept
{
const ScopedLockType lock (getLock());
data = static_cast <ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data);
data = static_cast<ArrayAllocationBase<ElementType, TypeOfCriticalSectionToUse>&&> (other.data);
numUsed = other.numUsed;
other.numUsed = 0;
return *this;
@@ -279,8 +279,14 @@ public:
inline ElementType getFirst() const
{
const ScopedLockType lock (getLock());
return (numUsed > 0) ? data.elements [0]
: ElementType();
if (numUsed > 0)
{
jassert (data.elements != nullptr);
return data.elements[0];
}
return ElementType();
}
/** Returns the last element in the array, or a default value if the array is empty.
@@ -290,8 +296,14 @@ public:
inline ElementType getLast() const
{
const ScopedLockType lock (getLock());
return (numUsed > 0) ? data.elements [numUsed - 1]
: ElementType();
if (numUsed > 0)
{
jassert (data.elements != nullptr);
return data.elements[numUsed - 1];
}
return ElementType();
}
/** Returns a pointer to the actual array data.
@@ -317,6 +329,11 @@ public:
*/
inline ElementType* end() const noexcept
{
#if JUCE_DEBUG
if (data.elements == nullptr || numUsed <= 0) // (to keep static analysers happy)
return data.elements;
#endif
return data.elements + numUsed;
}
@@ -366,13 +383,27 @@ public:
@param newElement the new object to add to the array
@see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
*/
void add (ParameterType newElement)
void add (const ElementType& newElement)
{
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + 1);
new (data.elements + numUsed++) ElementType (newElement);
}
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
/** Appends a new element at the end of the array.
@param newElement the new object to add to the array
@see set, insert, addIfNotAlreadyThere, addSorted, addUsingDefaultSort, addArray
*/
void add (ElementType&& newElement)
{
const ScopedLockType lock (getLock());
data.ensureAllocatedSize (numUsed + 1);
new (data.elements + numUsed++) ElementType (static_cast<ElementType&&> (newElement));
}
#endif
/** Inserts a new element into the array at a given position.
If the index is less than 0 or greater than the size of the array, the
@@ -519,6 +550,7 @@ public:
if (isPositiveAndBelow (indexToChange, numUsed))
{
jassert (data.elements != nullptr);
data.elements [indexToChange] = newValue;
}
else if (indexToChange >= 0)


+ 66
- 7
source/modules/juce_core/containers/juce_DynamicObject.cpp View File

@@ -60,20 +60,79 @@ bool DynamicObject::hasMethod (const Identifier& methodName) const
return getProperty (methodName).isMethod();
}
var DynamicObject::invokeMethod (const Identifier& methodName,
const var* parameters,
int numParameters)
var DynamicObject::invokeMethod (Identifier method, const var::NativeFunctionArgs& args)
{
return properties [methodName].invokeMethod (this, parameters, numParameters);
if (var::NativeFunction function = properties [method].getNativeFunction())
return function (args);
return var();
}
void DynamicObject::setMethod (const Identifier& name,
var::MethodFunction methodFunction)
void DynamicObject::setMethod (Identifier name, var::NativeFunction function)
{
properties.set (name, var (methodFunction));
properties.set (name, var (function));
}
void DynamicObject::clear()
{
properties.clear();
}
DynamicObject::Ptr DynamicObject::clone()
{
DynamicObject* newCopy = new DynamicObject();
newCopy->properties = properties;
for (LinkedListPointer<NamedValueSet::NamedValue>* i = &(newCopy->properties.values);;)
{
if (NamedValueSet::NamedValue* const v = i->get())
{
v->value = v->value.clone();
i = &(v->nextListItem);
}
else
break;
}
return newCopy;
}
void DynamicObject::writeAsJSON (OutputStream& out, const int indentLevel, const bool allOnOneLine)
{
out << '{';
if (! allOnOneLine)
out << newLine;
for (LinkedListPointer<NamedValueSet::NamedValue>* i = &(properties.values);;)
{
if (NamedValueSet::NamedValue* const v = i->get())
{
if (! allOnOneLine)
JSONFormatter::writeSpaces (out, indentLevel + JSONFormatter::indentSize);
out << '"';
JSONFormatter::writeString (out, v->name);
out << "\": ";
JSONFormatter::write (out, v->value, indentLevel + JSONFormatter::indentSize, allOnOneLine);
if (v->nextListItem.get() != nullptr)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;
i = &(v->nextListItem);
}
else
break;
}
if (! allOnOneLine)
JSONFormatter::writeSpaces (out, indentLevel);
out << '}';
}

+ 26
- 12
source/modules/juce_core/containers/juce_DynamicObject.h View File

@@ -86,23 +86,16 @@ public:
This method is virtual to allow more dynamic invocation to used for objects
where the methods may not already be set as properies.
*/
virtual var invokeMethod (const Identifier& methodName,
const var* parameters,
int numParameters);
virtual var invokeMethod (Identifier methodName,
const var::NativeFunctionArgs& args);
/** Sets up a method.
/** Adds a method to the class.
This is basically the same as calling setProperty (methodName, (var::MethodFunction) myFunction), but
This is basically the same as calling setProperty (methodName, (var::NativeFunction) myFunction), but
helps to avoid accidentally invoking the wrong type of var constructor. It also makes
the code easier to read,
The compiler will probably force you to use an explicit cast your method to a (var::MethodFunction), e.g.
@code
setMethod ("doSomething", (var::MethodFunction) &MyClass::doSomething);
@endcode
*/
void setMethod (const Identifier& methodName,
var::MethodFunction methodFunction);
void setMethod (Identifier methodName, var::NativeFunction function);
//==============================================================================
/** Removes all properties and methods from the object. */
@@ -111,10 +104,31 @@ public:
/** Returns the NamedValueSet that holds the object's properties. */
NamedValueSet& getProperties() noexcept { return properties; }
//==============================================================================
/** Returns a clone of this object.
The default implementation of this method just returns a new DynamicObject
with a (deep) copy of all of its properties. Subclasses can override this to
implement their own custom copy routines.
*/
virtual Ptr clone();
//==============================================================================
/** Writes this object to a text stream in JSON format.
This method is used by JSON::toString and JSON::writeToStream, and you should
never need to call it directly, but it's virtual so that custom object types
can stringify themselves appropriately.
*/
virtual void writeAsJSON (OutputStream&, int indentLevel, bool allOnOneLine);
private:
//==============================================================================
NamedValueSet properties;
#if JUCE_CATCH_DEPRECATED_CODE_MISUSE
// These methods have been deprecated - use var::invoke instead
virtual void invokeMethod (const Identifier&, const var*, int) {}
#endif
JUCE_LEAK_DETECTOR (DynamicObject)
};


+ 1
- 1
source/modules/juce_core/containers/juce_NamedValueSet.h View File

@@ -155,7 +155,7 @@ private:
friend class LinkedListPointer<NamedValue>;
LinkedListPointer<NamedValue> values;
friend class JSONFormatter;
friend class DynamicObject;
};


+ 21
- 4
source/modules/juce_core/containers/juce_OwnedArray.h View File

@@ -166,8 +166,14 @@ public:
inline ObjectClass* getFirst() const noexcept
{
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [0]
: static_cast <ObjectClass*> (nullptr);
if (numUsed > 0)
{
jassert (data.elements != nullptr);
return data.elements [0];
}
return nullptr;
}
/** Returns a pointer to the last object in the array.
@@ -178,8 +184,14 @@ public:
inline ObjectClass* getLast() const noexcept
{
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [numUsed - 1]
: static_cast <ObjectClass*> (nullptr);
if (numUsed > 0)
{
jassert (data.elements != nullptr);
return data.elements [numUsed - 1];
}
return nullptr;
}
/** Returns a pointer to the actual array data.
@@ -205,6 +217,11 @@ public:
*/
inline ObjectClass** end() const noexcept
{
#if JUCE_DEBUG
if (data.elements == nullptr || numUsed <= 0) // (to keep static analysers happy)
return data.elements;
#endif
return data.elements + numUsed;
}


+ 42
- 28
source/modules/juce_core/containers/juce_ReferenceCountedArray.h View File

@@ -180,8 +180,14 @@ public:
inline ObjectClass* getObjectPointer (const int index) const noexcept
{
const ScopedLockType lock (getLock());
return isPositiveAndBelow (index, numUsed) ? data.elements [index]
: nullptr;
if (isPositiveAndBelow (index, numUsed))
{
jassert (data.elements != nullptr);
return data.elements [index];
}
return ObjectClassPtr();
}
/** Returns a raw pointer to the object at this index in the array, without checking
@@ -190,7 +196,7 @@ public:
inline ObjectClass* getObjectPointerUnchecked (const int index) const noexcept
{
const ScopedLockType lock (getLock());
jassert (isPositiveAndBelow (index, numUsed));
jassert (isPositiveAndBelow (index, numUsed) && data.elements != nullptr);
return data.elements [index];
}
@@ -202,8 +208,14 @@ public:
inline ObjectClassPtr getFirst() const noexcept
{
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [0]
: static_cast <ObjectClass*> (nullptr);
if (numUsed > 0)
{
jassert (data.elements != nullptr);
return data.elements [0];
}
return ObjectClassPtr();
}
/** Returns a pointer to the last object in the array.
@@ -214,8 +226,14 @@ public:
inline ObjectClassPtr getLast() const noexcept
{
const ScopedLockType lock (getLock());
return numUsed > 0 ? data.elements [numUsed - 1]
: static_cast <ObjectClass*> (nullptr);
if (numUsed > 0)
{
jassert (data.elements != nullptr);
return data.elements [numUsed - 1];
}
return ObjectClassPtr();
}
/** Returns a pointer to the actual array data.
@@ -325,35 +343,31 @@ public:
ObjectClass* insert (int indexToInsertAt,
ObjectClass* const newObject) noexcept
{
if (indexToInsertAt >= 0)
{
const ScopedLockType lock (getLock());
if (indexToInsertAt < 0)
return add (newObject);
const ScopedLockType lock (getLock());
if (indexToInsertAt > numUsed)
indexToInsertAt = numUsed;
if (indexToInsertAt > numUsed)
indexToInsertAt = numUsed;
data.ensureAllocatedSize (numUsed + 1);
jassert (data.elements != nullptr);
data.ensureAllocatedSize (numUsed + 1);
jassert (data.elements != nullptr);
ObjectClass** const e = data.elements + indexToInsertAt;
const int numToMove = numUsed - indexToInsertAt;
ObjectClass** const e = data.elements + indexToInsertAt;
const int numToMove = numUsed - indexToInsertAt;
if (numToMove > 0)
memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
if (numToMove > 0)
memmove (e + 1, e, sizeof (ObjectClass*) * (size_t) numToMove);
*e = newObject;
*e = newObject;
if (newObject != nullptr)
newObject->incReferenceCount();
if (newObject != nullptr)
newObject->incReferenceCount();
++numUsed;
++numUsed;
return newObject;
}
else
{
return add (newObject);
}
return newObject;
}
/** Appends a new object at the end of the array as long as the array doesn't


+ 5
- 4
source/modules/juce_core/containers/juce_SortedSet.h View File

@@ -122,7 +122,6 @@ public:
}
/** Removes all elements from the set without freeing the array's allocated storage.
@see clear
*/
void clearQuick() noexcept
@@ -240,7 +239,8 @@ public:
if (halfway == s)
return -1;
else if (elementToLookFor < data.getReference (halfway))
if (elementToLookFor < data.getReference (halfway))
e = halfway;
else
s = halfway;
@@ -295,7 +295,8 @@ public:
break;
}
else if (isBeforeHalfway)
if (isBeforeHalfway)
e = halfway;
else
s = halfway;
@@ -483,7 +484,7 @@ public:
private:
//==============================================================================
Array <ElementType, TypeOfCriticalSectionToUse> data;
Array<ElementType, TypeOfCriticalSectionToUse> data;
};
#if JUCE_MSVC


+ 1
- 1
source/modules/juce_core/containers/juce_SparseSet.h View File

@@ -38,7 +38,7 @@
ranges of values. It's quite a specialised class, mostly useful for things
like keeping the set of selected rows in a listbox.
The type used as a template paramter must be an integer type, such as int, short,
The type used as a template parameter must be an integer type, such as int, short,
int64, etc.
*/
template <class Type>


+ 197
- 132
source/modules/juce_core/containers/juce_Variant.cpp View File

@@ -35,7 +35,8 @@ enum VariantStreamMarkers
varMarker_String = 5,
varMarker_Int64 = 6,
varMarker_Array = 7,
varMarker_Binary = 8
varMarker_Binary = 8,
varMarker_Undefined = 9
};
//==============================================================================
@@ -53,8 +54,10 @@ public:
virtual ReferenceCountedObject* toObject (const ValueUnion&) const noexcept { return nullptr; }
virtual Array<var>* toArray (const ValueUnion&) const noexcept { return nullptr; }
virtual MemoryBlock* toBinary (const ValueUnion&) const noexcept { return nullptr; }
virtual var clone (const var& original) const { return original; }
virtual bool isVoid() const noexcept { return false; }
virtual bool isUndefined() const noexcept { return false; }
virtual bool isInt() const noexcept { return false; }
virtual bool isInt64() const noexcept { return false; }
virtual bool isBool() const noexcept { return false; }
@@ -78,9 +81,27 @@ public:
VariantType_Void() noexcept {}
static const VariantType_Void instance;
bool isVoid() const noexcept { return true; }
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept { return otherType.isVoid(); }
void writeToStream (const ValueUnion&, OutputStream& output) const { output.writeCompressedInt (0); }
bool isVoid() const noexcept override { return true; }
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
void writeToStream (const ValueUnion&, OutputStream& output) const override { output.writeCompressedInt (0); }
};
//==============================================================================
class var::VariantType_Undefined : public var::VariantType
{
public:
VariantType_Undefined() noexcept {}
static const VariantType_Undefined instance;
bool isUndefined() const noexcept override { return true; }
String toString (const ValueUnion&) const override { return "undefined"; }
bool equals (const ValueUnion&, const ValueUnion&, const VariantType& otherType) const noexcept override { return otherType.isVoid() || otherType.isUndefined(); }
void writeToStream (const ValueUnion&, OutputStream& output) const override
{
output.writeCompressedInt (1);
output.writeByte (varMarker_Undefined);
}
};
//==============================================================================
@@ -90,19 +111,19 @@ public:
VariantType_Int() noexcept {}
static const VariantType_Int instance;
int toInt (const ValueUnion& data) const noexcept { return data.intValue; };
int64 toInt64 (const ValueUnion& data) const noexcept { return (int64) data.intValue; };
double toDouble (const ValueUnion& data) const noexcept { return (double) data.intValue; }
String toString (const ValueUnion& data) const { return String (data.intValue); }
bool toBool (const ValueUnion& data) const noexcept { return data.intValue != 0; }
bool isInt() const noexcept { return true; }
int toInt (const ValueUnion& data) const noexcept override { return data.intValue; };
int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.intValue; };
double toDouble (const ValueUnion& data) const noexcept override { return (double) data.intValue; }
String toString (const ValueUnion& data) const override { return String (data.intValue); }
bool toBool (const ValueUnion& data) const noexcept override { return data.intValue != 0; }
bool isInt() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return otherType.toInt (otherData) == data.intValue;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
output.writeCompressedInt (5);
output.writeByte (varMarker_Int);
@@ -117,19 +138,19 @@ public:
VariantType_Int64() noexcept {}
static const VariantType_Int64 instance;
int toInt (const ValueUnion& data) const noexcept { return (int) data.int64Value; };
int64 toInt64 (const ValueUnion& data) const noexcept { return data.int64Value; };
double toDouble (const ValueUnion& data) const noexcept { return (double) data.int64Value; }
String toString (const ValueUnion& data) const { return String (data.int64Value); }
bool toBool (const ValueUnion& data) const noexcept { return data.int64Value != 0; }
bool isInt64() const noexcept { return true; }
int toInt (const ValueUnion& data) const noexcept override { return (int) data.int64Value; };
int64 toInt64 (const ValueUnion& data) const noexcept override { return data.int64Value; };
double toDouble (const ValueUnion& data) const noexcept override { return (double) data.int64Value; }
String toString (const ValueUnion& data) const override { return String (data.int64Value); }
bool toBool (const ValueUnion& data) const noexcept override { return data.int64Value != 0; }
bool isInt64() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return otherType.toInt64 (otherData) == data.int64Value;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
output.writeCompressedInt (9);
output.writeByte (varMarker_Int64);
@@ -144,19 +165,19 @@ public:
VariantType_Double() noexcept {}
static const VariantType_Double instance;
int toInt (const ValueUnion& data) const noexcept { return (int) data.doubleValue; };
int64 toInt64 (const ValueUnion& data) const noexcept { return (int64) data.doubleValue; };
double toDouble (const ValueUnion& data) const noexcept { return data.doubleValue; }
String toString (const ValueUnion& data) const { return String (data.doubleValue); }
bool toBool (const ValueUnion& data) const noexcept { return data.doubleValue != 0; }
bool isDouble() const noexcept { return true; }
int toInt (const ValueUnion& data) const noexcept override { return (int) data.doubleValue; };
int64 toInt64 (const ValueUnion& data) const noexcept override { return (int64) data.doubleValue; };
double toDouble (const ValueUnion& data) const noexcept override { return data.doubleValue; }
String toString (const ValueUnion& data) const override { return String (data.doubleValue); }
bool toBool (const ValueUnion& data) const noexcept override { return data.doubleValue != 0; }
bool isDouble() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return std::abs (otherType.toDouble (otherData) - data.doubleValue) < std::numeric_limits<double>::epsilon();
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
output.writeCompressedInt (9);
output.writeByte (varMarker_Double);
@@ -171,19 +192,19 @@ public:
VariantType_Bool() noexcept {}
static const VariantType_Bool instance;
int toInt (const ValueUnion& data) const noexcept { return data.boolValue ? 1 : 0; };
int64 toInt64 (const ValueUnion& data) const noexcept { return data.boolValue ? 1 : 0; };
double toDouble (const ValueUnion& data) const noexcept { return data.boolValue ? 1.0 : 0.0; }
String toString (const ValueUnion& data) const { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
bool toBool (const ValueUnion& data) const noexcept { return data.boolValue; }
bool isBool() const noexcept { return true; }
int toInt (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; };
int64 toInt64 (const ValueUnion& data) const noexcept override { return data.boolValue ? 1 : 0; };
double toDouble (const ValueUnion& data) const noexcept override { return data.boolValue ? 1.0 : 0.0; }
String toString (const ValueUnion& data) const override { return String::charToString (data.boolValue ? (juce_wchar) '1' : (juce_wchar) '0'); }
bool toBool (const ValueUnion& data) const noexcept override { return data.boolValue; }
bool isBool() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return otherType.toBool (otherData) == data.boolValue;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
output.writeCompressedInt (1);
output.writeByte (data.boolValue ? (char) varMarker_BoolTrue : (char) varMarker_BoolFalse);
@@ -197,24 +218,24 @@ public:
VariantType_String() noexcept {}
static const VariantType_String instance;
void cleanUp (ValueUnion& data) const noexcept { getString (data)-> ~String(); }
void createCopy (ValueUnion& dest, const ValueUnion& source) const { new (dest.stringValue) String (*getString (source)); }
void cleanUp (ValueUnion& data) const noexcept override { getString (data)-> ~String(); }
void createCopy (ValueUnion& dest, const ValueUnion& source) const override { new (dest.stringValue) String (*getString (source)); }
bool isString() const noexcept { return true; }
int toInt (const ValueUnion& data) const noexcept { return getString (data)->getIntValue(); };
int64 toInt64 (const ValueUnion& data) const noexcept { return getString (data)->getLargeIntValue(); };
double toDouble (const ValueUnion& data) const noexcept { return getString (data)->getDoubleValue(); }
String toString (const ValueUnion& data) const { return *getString (data); }
bool toBool (const ValueUnion& data) const noexcept { return getString (data)->getIntValue() != 0
|| getString (data)->trim().equalsIgnoreCase ("true")
|| getString (data)->trim().equalsIgnoreCase ("yes"); }
bool isString() const noexcept override { return true; }
int toInt (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue(); };
int64 toInt64 (const ValueUnion& data) const noexcept override { return getString (data)->getLargeIntValue(); };
double toDouble (const ValueUnion& data) const noexcept override { return getString (data)->getDoubleValue(); }
String toString (const ValueUnion& data) const override { return *getString (data); }
bool toBool (const ValueUnion& data) const noexcept override { return getString (data)->getIntValue() != 0
|| getString (data)->trim().equalsIgnoreCase ("true")
|| getString (data)->trim().equalsIgnoreCase ("yes"); }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return otherType.toString (otherData) == *getString (data);
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
const String* const s = getString (data);
const size_t len = s->getNumBytesAsUTF8() + 1;
@@ -237,26 +258,35 @@ public:
VariantType_Object() noexcept {}
static const VariantType_Object instance;
void cleanUp (ValueUnion& data) const noexcept { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
void cleanUp (ValueUnion& data) const noexcept override { if (data.objectValue != nullptr) data.objectValue->decReferenceCount(); }
void createCopy (ValueUnion& dest, const ValueUnion& source) const
void createCopy (ValueUnion& dest, const ValueUnion& source) const override
{
dest.objectValue = source.objectValue;
if (dest.objectValue != nullptr)
dest.objectValue->incReferenceCount();
}
String toString (const ValueUnion& data) const { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
bool toBool (const ValueUnion& data) const noexcept { return data.objectValue != 0; }
ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept { return data.objectValue; }
bool isObject() const noexcept { return true; }
String toString (const ValueUnion& data) const override { return "Object 0x" + String::toHexString ((int) (pointer_sized_int) data.objectValue); }
bool toBool (const ValueUnion& data) const noexcept override { return data.objectValue != 0; }
ReferenceCountedObject* toObject (const ValueUnion& data) const noexcept override { return data.objectValue; }
bool isObject() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return otherType.toObject (otherData) == data.objectValue;
}
void writeToStream (const ValueUnion&, OutputStream& output) const
var clone (const var& original) const override
{
if (DynamicObject* d = original.getDynamicObject())
return d->clone().get();
jassertfalse; // can only clone DynamicObjects!
return var();
}
void writeToStream (const ValueUnion&, OutputStream& output) const override
{
jassertfalse; // Can't write an object to a stream!
output.writeCompressedInt (0);
@@ -264,38 +294,67 @@ public:
};
//==============================================================================
class var::VariantType_Array : public var::VariantType
class var::VariantType_Array : public var::VariantType_Object
{
public:
VariantType_Array() noexcept {}
static const VariantType_Array instance;
void cleanUp (ValueUnion& data) const noexcept { delete data.arrayValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.arrayValue = new Array<var> (*(source.arrayValue)); }
String toString (const ValueUnion&) const override { return "[Array]"; }
ReferenceCountedObject* toObject (const ValueUnion&) const noexcept override { return nullptr; }
bool isArray() const noexcept override { return true; }
Array<var>* toArray (const ValueUnion& data) const noexcept override
{
if (RefCountedArray* a = dynamic_cast<RefCountedArray*> (data.objectValue))
return &(a->array);
String toString (const ValueUnion&) const { return "[Array]"; }
bool isArray() const noexcept { return true; }
Array<var>* toArray (const ValueUnion& data) const noexcept { return data.arrayValue; }
return nullptr;
}
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
const Array<var>* const thisArray = toArray (data);
const Array<var>* const otherArray = otherType.toArray (otherData);
return otherArray != nullptr && *otherArray == *(data.arrayValue);
return thisArray == otherArray || (thisArray != nullptr && otherArray != nullptr && *otherArray == *thisArray);
}
var clone (const var& original) const override
{
Array<var> arrayCopy;
if (const Array<var>* array = toArray (original.value))
for (int i = 0; i < array->size(); ++i)
arrayCopy.add (array->getReference(i).clone());
return var (arrayCopy);
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
MemoryOutputStream buffer (512);
const int numItems = data.arrayValue->size();
buffer.writeCompressedInt (numItems);
if (const Array<var>* array = toArray (data))
{
MemoryOutputStream buffer (512);
const int numItems = array->size();
buffer.writeCompressedInt (numItems);
for (int i = 0; i < numItems; ++i)
data.arrayValue->getReference(i).writeToStream (buffer);
for (int i = 0; i < numItems; ++i)
array->getReference(i).writeToStream (buffer);
output.writeCompressedInt (1 + (int) buffer.getDataSize());
output.writeByte (varMarker_Array);
output << buffer;
output.writeCompressedInt (1 + (int) buffer.getDataSize());
output.writeByte (varMarker_Array);
output << buffer;
}
}
struct RefCountedArray : public ReferenceCountedObject
{
RefCountedArray (const Array<var>& a) : array (a) { incReferenceCount(); }
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
RefCountedArray (Array<var>&& a) : array (static_cast<Array<var>&&> (a)) { incReferenceCount(); }
#endif
Array<var> array;
};
};
//==============================================================================
@@ -306,20 +365,20 @@ public:
static const VariantType_Binary instance;
void cleanUp (ValueUnion& data) const noexcept { delete data.binaryValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
void cleanUp (ValueUnion& data) const noexcept override { delete data.binaryValue; }
void createCopy (ValueUnion& dest, const ValueUnion& source) const override { dest.binaryValue = new MemoryBlock (*source.binaryValue); }
String toString (const ValueUnion& data) const { return data.binaryValue->toBase64Encoding(); }
bool isBinary() const noexcept { return true; }
MemoryBlock* toBinary (const ValueUnion& data) const noexcept { return data.binaryValue; }
String toString (const ValueUnion& data) const override { return data.binaryValue->toBase64Encoding(); }
bool isBinary() const noexcept override { return true; }
MemoryBlock* toBinary (const ValueUnion& data) const noexcept override { return data.binaryValue; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
const MemoryBlock* const otherBlock = otherType.toBinary (otherData);
return otherBlock != nullptr && *otherBlock == *data.binaryValue;
}
void writeToStream (const ValueUnion& data, OutputStream& output) const
void writeToStream (const ValueUnion& data, OutputStream& output) const override
{
output.writeCompressedInt (1 + (int) data.binaryValue->getSize());
output.writeByte (varMarker_Binary);
@@ -334,16 +393,16 @@ public:
VariantType_Method() noexcept {}
static const VariantType_Method instance;
String toString (const ValueUnion&) const { return "Method"; }
bool toBool (const ValueUnion& data) const noexcept { return data.methodValue != nullptr; }
bool isMethod() const noexcept { return true; }
String toString (const ValueUnion&) const override { return "Method"; }
bool toBool (const ValueUnion& data) const noexcept override { return data.methodValue != nullptr; }
bool isMethod() const noexcept override { return true; }
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept
bool equals (const ValueUnion& data, const ValueUnion& otherData, const VariantType& otherType) const noexcept override
{
return otherType.isMethod() && otherData.methodValue == data.methodValue;
}
void writeToStream (const ValueUnion&, OutputStream& output) const
void writeToStream (const ValueUnion&, OutputStream& output) const override
{
jassertfalse; // Can't write a method to a stream!
output.writeCompressedInt (0);
@@ -351,27 +410,23 @@ public:
};
//==============================================================================
const var::VariantType_Void var::VariantType_Void::instance;
const var::VariantType_Int var::VariantType_Int::instance;
const var::VariantType_Int64 var::VariantType_Int64::instance;
const var::VariantType_Bool var::VariantType_Bool::instance;
const var::VariantType_Double var::VariantType_Double::instance;
const var::VariantType_String var::VariantType_String::instance;
const var::VariantType_Object var::VariantType_Object::instance;
const var::VariantType_Array var::VariantType_Array::instance;
const var::VariantType_Binary var::VariantType_Binary::instance;
const var::VariantType_Method var::VariantType_Method::instance;
const var::VariantType_Void var::VariantType_Void::instance;
const var::VariantType_Undefined var::VariantType_Undefined::instance;
const var::VariantType_Int var::VariantType_Int::instance;
const var::VariantType_Int64 var::VariantType_Int64::instance;
const var::VariantType_Bool var::VariantType_Bool::instance;
const var::VariantType_Double var::VariantType_Double::instance;
const var::VariantType_String var::VariantType_String::instance;
const var::VariantType_Object var::VariantType_Object::instance;
const var::VariantType_Array var::VariantType_Array::instance;
const var::VariantType_Binary var::VariantType_Binary::instance;
const var::VariantType_Method var::VariantType_Method::instance;
//==============================================================================
var::var() noexcept : type (&VariantType_Void::instance)
{
}
var::~var() noexcept
{
type->cleanUp (value);
}
var::var() noexcept : type (&VariantType_Void::instance) {}
var::var (const VariantType& t) noexcept : type (&t) {}
var::~var() noexcept { type->cleanUp (value); }
const var var::null;
@@ -385,8 +440,8 @@ var::var (const int v) noexcept : type (&VariantType_Int::instance) { v
var::var (const int64 v) noexcept : type (&VariantType_Int64::instance) { value.int64Value = v; }
var::var (const bool v) noexcept : type (&VariantType_Bool::instance) { value.boolValue = v; }
var::var (const double v) noexcept : type (&VariantType_Double::instance) { value.doubleValue = v; }
var::var (MethodFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = m; }
var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.arrayValue = new Array<var> (v); }
var::var (NativeFunction m) noexcept : type (&VariantType_Method::instance) { value.methodValue = m; }
var::var (const Array<var>& v) : type (&VariantType_Array::instance) { value.objectValue = new VariantType_Array::RefCountedArray(v); }
var::var (const String& v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
var::var (const char* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
var::var (const wchar_t* const v) : type (&VariantType_String::instance) { new (value.stringValue) String (v); }
@@ -401,9 +456,11 @@ var::var (ReferenceCountedObject* const object) : type (&VariantType_Object::in
object->incReferenceCount();
}
var var::undefined() noexcept { return var (VariantType_Undefined::instance); }
//==============================================================================
bool var::isVoid() const noexcept { return type->isVoid(); }
bool var::isUndefined() const noexcept { return type->isUndefined(); }
bool var::isInt() const noexcept { return type->isInt(); }
bool var::isInt64() const noexcept { return type->isInt64(); }
bool var::isBool() const noexcept { return type->isBool(); }
@@ -443,7 +500,7 @@ var& var::operator= (const wchar_t* const v) { type->cleanUp (value); type =
var& var::operator= (const String& v) { type->cleanUp (value); type = &VariantType_String::instance; new (value.stringValue) String (v); return *this; }
var& var::operator= (const Array<var>& v) { var v2 (v); swapWith (v2); return *this; }
var& var::operator= (ReferenceCountedObject* v) { var v2 (v); swapWith (v2); return *this; }
var& var::operator= (MethodFunction v) { var v2 (v); swapWith (v2); return *this; }
var& var::operator= (NativeFunction v) { var v2 (v); swapWith (v2); return *this; }
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
var::var (var&& other) noexcept
@@ -469,6 +526,11 @@ var::var (MemoryBlock&& v) : type (&VariantType_Binary::instance)
value.binaryValue = new MemoryBlock (static_cast<MemoryBlock&&> (v));
}
var::var (Array<var>&& v) : type (&VariantType_Array::instance)
{
value.objectValue = new VariantType_Array::RefCountedArray (static_cast<Array<var>&&> (v));
}
var& var::operator= (String&& v)
{
type->cleanUp (value);
@@ -489,6 +551,11 @@ bool var::equalsWithSameType (const var& other) const noexcept
return type == other.type && equals (other);
}
bool var::hasSameTypeAs (const var& other) const noexcept
{
return type == other.type;
}
bool operator== (const var& v1, const var& v2) noexcept { return v1.equals (v2); }
bool operator!= (const var& v1, const var& v2) noexcept { return ! v1.equals (v2); }
bool operator== (const var& v1, const String& v2) { return v1.toString() == v2; }
@@ -496,6 +563,11 @@ bool operator!= (const var& v1, const String& v2) { return v1.toString
bool operator== (const var& v1, const char* const v2) { return v1.toString() == v2; }
bool operator!= (const var& v1, const char* const v2) { return v1.toString() != v2; }
//==============================================================================
var var::clone() const noexcept
{
return type->clone (*this);
}
//==============================================================================
var var::operator[] (const Identifier propertyName) const
@@ -503,7 +575,7 @@ var var::operator[] (const Identifier propertyName) const
if (DynamicObject* const o = getDynamicObject())
return o->getProperty (propertyName);
return var::null;
return var();
}
var var::operator[] (const char* const propertyName) const
@@ -519,22 +591,17 @@ var var::getProperty (const Identifier propertyName, const var& defaultReturnVal
return defaultReturnValue;
}
var var::invoke (const Identifier method, const var* arguments, int numArguments) const
var::NativeFunction var::getNativeFunction() const
{
if (DynamicObject* const o = getDynamicObject())
return o->invokeMethod (method, arguments, numArguments);
return var::null;
return isMethod() ? value.methodValue : nullptr;
}
var var::invokeMethod (DynamicObject* const target, const var* const arguments, const int numArguments) const
var var::invoke (Identifier method, const var* arguments, int numArguments) const
{
jassert (target != nullptr);
if (isMethod())
return (target->*(value.methodValue)) (arguments, numArguments);
if (DynamicObject* const o = getDynamicObject())
return o->invokeMethod (method, var::NativeFunctionArgs (*this, arguments, numArguments));
return var::null;
return var();
}
var var::call (const Identifier method) const
@@ -604,21 +671,15 @@ var& var::operator[] (int arrayIndex)
Array<var>* var::convertToArray()
{
Array<var>* array = getArray();
if (array == nullptr)
{
const Array<var> tempVar;
var v (tempVar);
array = v.value.arrayValue;
if (Array<var>* array = getArray())
return array;
if (! isVoid())
array->add (*this);
Array<var> tempVar;
if (! isVoid())
tempVar.add (*this);
swapWith (v);
}
return array;
*this = tempVar;
return getArray();
}
void var::append (const var& n)
@@ -705,5 +766,9 @@ var var::readFromStream (InputStream& input)
}
}
return var::null;
return var();
}
var::NativeFunctionArgs::NativeFunctionArgs (const var& t, const var* args, int numArgs) noexcept
: thisObject (t), arguments (args), numArguments (numArgs)
{}

+ 64
- 35
source/modules/juce_core/containers/juce_Variant.h View File

@@ -47,7 +47,21 @@ class JUCE_API var
{
public:
//==============================================================================
typedef const var (DynamicObject::*MethodFunction) (const var* arguments, int numArguments);
/** This structure is passed to a NativeFunction callback, and contains invocation
details about the function's arguments and context.
*/
struct NativeFunctionArgs
{
NativeFunctionArgs (const var& thisObject, const var* args, int numArgs) noexcept;
const var& thisObject;
const var* arguments;
int numArguments;
JUCE_DECLARE_NON_COPYABLE (NativeFunctionArgs)
};
typedef var (*NativeFunction) (const NativeFunctionArgs&);
typedef Identifier identifier;
//==============================================================================
@@ -70,7 +84,7 @@ public:
var (const String& value);
var (const Array<var>& value);
var (ReferenceCountedObject* object);
var (MethodFunction method) noexcept;
var (NativeFunction method) noexcept;
var (const void* binaryData, size_t dataSize);
var (const MemoryBlock& binaryData);
@@ -84,18 +98,22 @@ public:
var& operator= (const String& value);
var& operator= (const Array<var>& value);
var& operator= (ReferenceCountedObject* object);
var& operator= (MethodFunction method);
var& operator= (NativeFunction method);
#if JUCE_COMPILER_SUPPORTS_MOVE_SEMANTICS
var (var&& other) noexcept;
var (String&& value);
var (MemoryBlock&& binaryData);
var (Array<var>&& value);
var& operator= (var&& other) noexcept;
var& operator= (String&& value);
#endif
void swapWith (var& other) noexcept;
/** Returns a var object that can be used where you need the javascript "undefined" value. */
static var undefined() noexcept;
//==============================================================================
operator int() const noexcept;
operator int64() const noexcept;
@@ -126,6 +144,7 @@ public:
//==============================================================================
bool isVoid() const noexcept;
bool isUndefined() const noexcept;
bool isInt() const noexcept;
bool isInt64() const noexcept;
bool isBool() const noexcept;
@@ -149,6 +168,15 @@ public:
*/
bool equalsWithSameType (const var& other) const noexcept;
/** Returns true if this var has the same type as the one supplied. */
bool hasSameTypeAs (const var& other) const noexcept;
/** Returns a deep copy of this object.
For simple types this just returns a copy, but if the object contains any arrays
or DynamicObjects, they will be cloned (recursively).
*/
var clone() const noexcept;
//==============================================================================
/** If the var is an array, this returns the number of elements.
If the var isn't actually an array, this will return 0.
@@ -214,27 +242,29 @@ public:
//==============================================================================
/** If this variant is an object, this returns one of its properties. */
var operator[] (const Identifier propertyName) const;
var operator[] (Identifier propertyName) const;
/** If this variant is an object, this returns one of its properties. */
var operator[] (const char* propertyName) const;
/** If this variant is an object, this returns one of its properties, or a default
fallback value if the property is not set. */
var getProperty (const Identifier propertyName, const var& defaultReturnValue) const;
/** If this variant is an object, this invokes one of its methods with no arguments. */
var call (const Identifier method) const;
/** If this variant is an object, this invokes one of its methods with one argument. */
var call (const Identifier method, const var& arg1) const;
/** If this variant is an object, this invokes one of its methods with 2 arguments. */
var call (const Identifier method, const var& arg1, const var& arg2) const;
/** If this variant is an object, this invokes one of its methods with 3 arguments. */
var call (const Identifier method, const var& arg1, const var& arg2, const var& arg3);
/** If this variant is an object, this invokes one of its methods with 4 arguments. */
var call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const;
/** If this variant is an object, this invokes one of its methods with 5 arguments. */
var call (const Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const;
/** If this variant is an object, this invokes one of its methods with a list of arguments. */
var invoke (const Identifier method, const var* arguments, int numArguments) const;
var getProperty (Identifier propertyName, const var& defaultReturnValue) const;
/** Invokes a named method call with no arguments. */
var call (Identifier method) const;
/** Invokes a named method call with one argument. */
var call (Identifier method, const var& arg1) const;
/** Invokes a named method call with 2 arguments. */
var call (Identifier method, const var& arg1, const var& arg2) const;
/** Invokes a named method call with 3 arguments. */
var call (Identifier method, const var& arg1, const var& arg2, const var& arg3);
/** Invokes a named method call with 4 arguments. */
var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4) const;
/** Invokes a named method call with 5 arguments. */
var call (Identifier method, const var& arg1, const var& arg2, const var& arg3, const var& arg4, const var& arg5) const;
/** Invokes a named method call with a list of arguments. */
var invoke (Identifier method, const var* arguments, int numArguments) const;
/** If this object is a method, this returns the function pointer. */
NativeFunction getNativeFunction() const;
//==============================================================================
/** Writes a binary representation of this value to a stream.
@@ -252,17 +282,18 @@ public:
private:
//==============================================================================
class VariantType; friend class VariantType;
class VariantType_Void; friend class VariantType_Void;
class VariantType_Int; friend class VariantType_Int;
class VariantType_Int64; friend class VariantType_Int64;
class VariantType_Double; friend class VariantType_Double;
class VariantType_Bool; friend class VariantType_Bool;
class VariantType_String; friend class VariantType_String;
class VariantType_Object; friend class VariantType_Object;
class VariantType_Array; friend class VariantType_Array;
class VariantType_Binary; friend class VariantType_Binary;
class VariantType_Method; friend class VariantType_Method;
class VariantType; friend class VariantType;
class VariantType_Void; friend class VariantType_Void;
class VariantType_Undefined; friend class VariantType_Undefined;
class VariantType_Int; friend class VariantType_Int;
class VariantType_Int64; friend class VariantType_Int64;
class VariantType_Double; friend class VariantType_Double;
class VariantType_Bool; friend class VariantType_Bool;
class VariantType_String; friend class VariantType_String;
class VariantType_Object; friend class VariantType_Object;
class VariantType_Array; friend class VariantType_Array;
class VariantType_Binary; friend class VariantType_Binary;
class VariantType_Method; friend class VariantType_Method;
union ValueUnion
{
@@ -272,17 +303,15 @@ private:
double doubleValue;
char stringValue [sizeof (String)];
ReferenceCountedObject* objectValue;
Array<var>* arrayValue;
MemoryBlock* binaryValue;
MethodFunction methodValue;
NativeFunction methodValue;
};
const VariantType* type;
ValueUnion value;
Array<var>* convertToArray();
friend class DynamicObject;
var invokeMethod (DynamicObject*, const var*, int) const;
var (const VariantType&) noexcept;
};
/** Compares the values of two var objects, using the var::equals() comparison. */


+ 11
- 17
source/modules/juce_core/files/juce_File.cpp View File

@@ -500,10 +500,9 @@ int File::findChildFiles (Array<File>& results,
const bool searchRecursively,
const String& wildCardPattern) const
{
DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor);
int total = 0;
while (di.next())
for (DirectoryIterator di (*this, searchRecursively, wildCardPattern, whatToLookFor); di.next();)
{
results.add (di.getFile());
++total;
@@ -514,10 +513,9 @@ int File::findChildFiles (Array<File>& results,
int File::getNumberOfChildFiles (const int whatToLookFor, const String& wildCardPattern) const
{
DirectoryIterator di (*this, false, wildCardPattern, whatToLookFor);
int total = 0;
while (di.next())
for (DirectoryIterator di (*this, false, wildCardPattern, whatToLookFor); di.next();)
++total;
return total;
@@ -611,22 +609,18 @@ bool File::hasFileExtension (StringRef possibleSuffix) const
const int semicolon = possibleSuffix.text.indexOf ((juce_wchar) ';');
if (semicolon >= 0)
{
return hasFileExtension (String (possibleSuffix.text).substring (0, semicolon).trimEnd())
|| hasFileExtension ((possibleSuffix.text + (semicolon + 1)).findEndOfWhitespace());
}
else
if (fullPath.endsWithIgnoreCase (possibleSuffix))
{
if (fullPath.endsWithIgnoreCase (possibleSuffix))
{
if (possibleSuffix.text[0] == '.')
return true;
if (possibleSuffix.text[0] == '.')
return true;
const int dotPos = fullPath.length() - possibleSuffix.length() - 1;
const int dotPos = fullPath.length() - possibleSuffix.length() - 1;
if (dotPos >= 0)
return fullPath [dotPos] == '.';
}
if (dotPos >= 0)
return fullPath [dotPos] == '.';
}
return false;


+ 5
- 2
source/modules/juce_core/files/juce_File.h View File

@@ -353,8 +353,11 @@ public:
*/
bool isHidden() const;
/** If this file is a link, this returns the file that it points to.
If this file isn't actually link, it'll just return itself.
/** Returns true if this file is a link or alias that can be followed using getLinkedTarget(). */
bool isLink() const;
/** If this file is a link or alias, this returns the file that it points to.
If the file isn't actually link, it'll just return itself.
*/
File getLinkedTarget() const;


source/modules/juce_core/json/juce_JSON.cpp → source/modules/juce_core/javascript/juce_JSON.cpp View File

@@ -43,6 +43,63 @@ public:
return createFail ("Expected '{' or '['", &t);
}
static Result parseString (const juce_wchar quoteChar, String::CharPointerType& t, var& result)
{
MemoryOutputStream buffer (256);
for (;;)
{
juce_wchar c = t.getAndAdvance();
if (c == quoteChar)
break;
if (c == '\\')
{
c = t.getAndAdvance();
switch (c)
{
case '"':
case '\'':
case '\\':
case '/': break;
case 'a': c = '\a'; break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'u':
{
c = 0;
for (int i = 4; --i >= 0;)
{
const int digitValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
if (digitValue < 0)
return createFail ("Syntax error in unicode escape sequence");
c = (juce_wchar) ((c << 4) + digitValue);
}
break;
}
}
}
if (c == 0)
return createFail ("Unexpected end-of-input in string constant");
buffer.appendUTF8Char (c);
}
result = buffer.toUTF8();
return Result::ok();
}
private:
static Result parseAny (String::CharPointerType& t, var& result)
{
@@ -53,7 +110,8 @@ private:
{
case '{': t = t2; return parseObject (t, result);
case '[': t = t2; return parseArray (t, result);
case '"': t = t2; return parseString (t, result);
case '"': t = t2; return parseString ('"', t, result);
case '\'': t = t2; return parseString ('\'', t, result);
case '-':
t2 = t2.findEndOfWhitespace();
@@ -180,7 +238,7 @@ private:
if (c == '"')
{
var propertyNameVar;
Result r (parseString (t, propertyNameVar));
Result r (parseString ('"', t, propertyNameVar));
if (r.failed())
return r;
@@ -264,61 +322,6 @@ private:
return Result::ok();
}
static Result parseString (String::CharPointerType& t, var& result)
{
MemoryOutputStream buffer (256);
for (;;)
{
juce_wchar c = t.getAndAdvance();
if (c == '"')
break;
if (c == '\\')
{
c = t.getAndAdvance();
switch (c)
{
case '"':
case '\\':
case '/': break;
case 'b': c = '\b'; break;
case 'f': c = '\f'; break;
case 'n': c = '\n'; break;
case 'r': c = '\r'; break;
case 't': c = '\t'; break;
case 'u':
{
c = 0;
for (int i = 4; --i >= 0;)
{
const int digitValue = CharacterFunctions::getHexDigitValue (t.getAndAdvance());
if (digitValue < 0)
return createFail ("Syntax error in unicode escape sequence");
c = (juce_wchar) ((c << 4) + digitValue);
}
break;
}
}
}
if (c == 0)
return createFail ("Unexpected end-of-input in string constant");
buffer.appendUTF8Char (c);
}
result = buffer.toUTF8();
return Result::ok();
}
};
//==============================================================================
@@ -338,6 +341,10 @@ public:
{
out << "null";
}
else if (v.isUndefined())
{
out << "undefined";
}
else if (v.isBool())
{
out << (static_cast<bool> (v) ? "true" : "false");
@@ -348,8 +355,8 @@ public:
}
else if (v.isObject())
{
if (DynamicObject* const object = v.getDynamicObject())
writeObject (out, *object, indentLevel, allOnOneLine);
if (DynamicObject* object = v.getDynamicObject())
object->writeAsJSON (out, indentLevel, allOnOneLine);
else
jassertfalse; // Only DynamicObjects can be converted to JSON!
}
@@ -379,6 +386,7 @@ public:
case '\"': out << "\\\""; break;
case '\\': out << "\\\\"; break;
case '\a': out << "\\a"; break;
case '\b': out << "\\b"; break;
case '\f': out << "\\f"; break;
case '\t': out << "\\t"; break;
@@ -421,34 +429,38 @@ public:
const int indentLevel, const bool allOnOneLine)
{
out << '[';
if (! allOnOneLine)
out << newLine;
for (int i = 0; i < array.size(); ++i)
if (array.size() > 0)
{
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
out << newLine;
if (i < array.size() - 1)
for (int i = 0; i < array.size(); ++i)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
if (! allOnOneLine)
writeSpaces (out, indentLevel + indentSize);
write (out, array.getReference(i), indentLevel + indentSize, allOnOneLine);
if (i < array.size() - 1)
{
if (allOnOneLine)
out << ", ";
else
out << ',' << newLine;
}
else if (! allOnOneLine)
out << newLine;
}
else if (! allOnOneLine)
out << newLine;
}
if (! allOnOneLine)
writeSpaces (out, indentLevel);
if (! allOnOneLine)
writeSpaces (out, indentLevel);
}
out << ']';
}
static void writeObject (OutputStream& out, DynamicObject& object,
/* static void writeObject (OutputStream& out, DynamicObject& object,
const int indentLevel, const bool allOnOneLine)
{
NamedValueSet& props = object.getProperties();
@@ -491,7 +503,7 @@ public:
writeSpaces (out, indentLevel);
out << '}';
}
}*/
enum { indentSize = 2 };
};
@@ -541,6 +553,15 @@ String JSON::escapeString (StringRef s)
return mo.toString();
}
Result JSON::parseQuotedString (String::CharPointerType& t, var& result)
{
const juce_wchar quote = t.getAndAdvance();
if (quote == '"' || quote == '\'')
return JSONParser::parseString (quote, t, result);
return Result::fail ("Not a quoted string!");
}
//==============================================================================
//==============================================================================

source/modules/juce_core/json/juce_JSON.h → source/modules/juce_core/javascript/juce_JSON.h View File

@@ -106,9 +106,15 @@ public:
/** Returns a version of a string with any extended characters escaped. */
static String escapeString (StringRef);
/** Parses a quoted string in JSON format, returning the un-escaped result in the
result parameter, and an error message in case the content was illegal.
This advances the text parameter, leaving it positioned after the closing quote.
*/
static Result parseQuotedString (String::CharPointerType& text, var& result);
private:
//==============================================================================
JSON(); // This class can't be instantiated - just use its static methods.
JSON() JUCE_DELETED_FUNCTION; // This class can't be instantiated - just use its static methods.
};

+ 1683
- 0
source/modules/juce_core/javascript/juce_Javascript.cpp
File diff suppressed because it is too large
View File


+ 106
- 0
source/modules/juce_core/javascript/juce_Javascript.h View File

@@ -0,0 +1,106 @@
/*
==============================================================================
This file is part of the juce_core module of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
NO EVENT SHALL THE AUTHOR 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.
------------------------------------------------------------------------------
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
using any other modules, be sure to check that you also comply with their license.
For more details, visit www.juce.com
==============================================================================
*/
/**
A simple javascript interpreter!
It's not fully standards-compliant, and won't be as fast as the fancy JIT-compiled
engines that you get in browsers, but this is an extremely compact, low-overhead javascript
interpreter, which is integrated with the juce var and DynamicObject classes. If you need
a few simple bits of scripting in your app, and want to be able to easily let the JS
work with native objects defined as DynamicObject subclasses, then this might do the job.
To use, simply create an instance of this class and call execute() to run your code.
Variables that the script sets can be retrieved with evaluate(), and if you need to provide
native objects for the script to use, you can add them with registerNativeObject().
One caveat: Because the values and objects that the engine works with are DynamicObject
and var objects, they use reference-counting rather than garbage-collection, so if your
script creates complex connections between objects, you run the risk of creating cyclic
dependencies and hence leaking.
*/
class JavascriptEngine
{
public:
/** Creates an instance of the engine.
This creates a root namespace and defines some basic Object, String, Array
and Math library methods.
*/
JavascriptEngine();
/** Destructor. */
~JavascriptEngine();
/** Attempts to parse and run a block of javascript code.
If there's a parse or execution error, the error description is returned in
the result.
You can specify a maximum time for which the program is allowed to run, and
it'll return with an error message if this time is exceeded.
*/
Result execute (const String& javascriptCode);
/** Attempts to parse and run a javascript expression, and returns the result.
If there's a syntax error, or the expression can't be evaluated, the return value
will be var::undefined(). The errorMessage parameter gives you a way to find out
any parsing errors.
You can specify a maximum time for which the program is allowed to run, and
it'll return with an error message if this time is exceeded.
*/
var evaluate (const String& javascriptCode,
Result* errorMessage = nullptr);
/** Calls a function in the root namespace, and returns the result.
The function arguments are passed in the same format as used by native
methods in the var class.
*/
var callFunction (Identifier function,
const var::NativeFunctionArgs& args,
Result* errorMessage = nullptr);
/** Adds a native object to the root namespace.
The object passed-in is reference-counted, and will be retained by the
engine until the engine is deleted. The name must be a simple JS identifier,
without any dots.
*/
void registerNativeObject (Identifier objectName, DynamicObject* object);
/** This value indicates how long a call to one of the evaluate methods is permitted
to run before timing-out and failing.
The default value is a number of seconds, but you can change this to whatever value
suits your application.
*/
RelativeTime maximumExecutionTime;
private:
struct RootObject;
ReferenceCountedObjectPtr<RootObject> root;
void prepareTimeout() const;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JavascriptEngine)
};

+ 6
- 3
source/modules/juce_core/juce_core.cpp View File

@@ -110,7 +110,6 @@ namespace juce
{
#include "containers/juce_AbstractFifo.cpp"
#include "containers/juce_DynamicObject.cpp"
#include "containers/juce_NamedValueSet.cpp"
#include "containers/juce_PropertySet.cpp"
#include "containers/juce_Variant.cpp"
@@ -120,7 +119,9 @@ namespace juce
#include "files/juce_FileOutputStream.cpp"
#include "files/juce_FileSearchPath.cpp"
#include "files/juce_TemporaryFile.cpp"
#include "json/juce_JSON.cpp"
#include "javascript/juce_JSON.cpp"
#include "javascript/juce_Javascript.cpp"
#include "containers/juce_DynamicObject.cpp"
#include "logging/juce_FileLogger.cpp"
#include "logging/juce_Logger.cpp"
#include "maths/juce_BigInteger.cpp"
@@ -139,13 +140,13 @@ namespace juce
#include "streams/juce_InputStream.cpp"
#include "streams/juce_MemoryInputStream.cpp"
#include "streams/juce_MemoryOutputStream.cpp"
#include "streams/juce_OutputStream.cpp"
#include "streams/juce_SubregionStream.cpp"
#include "system/juce_SystemStats.cpp"
#include "text/juce_CharacterFunctions.cpp"
#include "text/juce_Identifier.cpp"
#include "text/juce_LocalisedStrings.cpp"
#include "text/juce_String.cpp"
#include "streams/juce_OutputStream.cpp"
#include "text/juce_StringArray.cpp"
#include "text/juce_StringPairArray.cpp"
#include "text/juce_StringPool.cpp"
@@ -198,6 +199,7 @@ namespace juce
//==============================================================================
#elif JUCE_LINUX
#include "native/juce_linux_CommonFile.cpp"
#include "native/juce_linux_Files.cpp"
#include "native/juce_linux_Network.cpp"
#include "native/juce_linux_SystemStats.cpp"
@@ -205,6 +207,7 @@ namespace juce
//==============================================================================
#elif JUCE_ANDROID
#include "native/juce_linux_CommonFile.cpp"
#include "native/juce_android_Files.cpp"
#include "native/juce_android_Misc.cpp"
#include "native/juce_android_Network.cpp"


+ 2
- 1
source/modules/juce_core/juce_core.h View File

@@ -234,7 +234,8 @@ extern JUCE_API void JUCE_CALLTYPE logAssertion (const char* file, int line) noe
#include "files/juce_TemporaryFile.h"
#include "streams/juce_FileInputSource.h"
#include "logging/juce_FileLogger.h"
#include "json/juce_JSON.h"
#include "javascript/juce_JSON.h"
#include "javascript/juce_Javascript.h"
#include "maths/juce_BigInteger.h"
#include "maths/juce_Expression.h"
#include "maths/juce_Random.h"


+ 2
- 2
source/modules/juce_core/juce_module_info View File

@@ -1,7 +1,7 @@
{
"id": "juce_core",
"name": "JUCE core classes",
"version": "2.1.3",
"version": "2.1.6",
"description": "The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.",
"website": "http://www.juce.com/juce",
"license": "ISC Permissive",
@@ -25,7 +25,7 @@
"logging/*",
"system/*",
"xml/*",
"json/*",
"javascript/*",
"zip/*",
"unit_tests/*",
"misc/*",


+ 6
- 0
source/modules/juce_core/maths/juce_BigInteger.cpp View File

@@ -157,6 +157,12 @@ int BigInteger::toInteger() const noexcept
return negative ? -n : n;
}
int64 BigInteger::toInt64() const noexcept
{
const int64 n = (((int64) (values[1] & 0x7fffffff)) << 32) | values[0];
return negative ? -n : n;
}
BigInteger BigInteger::getBitRange (int startBit, int numBits) const
{
BigInteger r;


+ 6
- 1
source/modules/juce_core/maths/juce_BigInteger.h View File

@@ -94,11 +94,16 @@ public:
/** Returns true if the value is 1. */
bool isOne() const noexcept;
/** Attempts to get the lowest bits of the value as an integer.
/** Attempts to get the lowest 32 bits of the value as an integer.
If the value is bigger than the integer limits, this will return only the lower bits.
*/
int toInteger() const noexcept;
/** Attempts to get the lowest 64 bits of the value as an integer.
If the value is bigger than the integer limits, this will return only the lower bits.
*/
int64 toInt64() const noexcept;
//==============================================================================
/** Resets the value to 0. */
void clear();


+ 6
- 0
source/modules/juce_core/maths/juce_MathsFunctions.h View File

@@ -295,6 +295,12 @@ inline int64 abs64 (const int64 n) noexcept
return (n >= 0) ? n : -n;
}
#if JUCE_MSVC && ! defined (DOXYGEN) // The MSVC libraries omit these functions for some reason...
template<typename Type> Type asinh (Type x) noexcept { return std::log (x + std::sqrt (x * x + (Type) 1)); }
template<typename Type> Type acosh (Type x) noexcept { return std::log (x + std::sqrt (x * x - (Type) 1)); }
template<typename Type> Type atanh (Type x) noexcept { return (std::log (x + (Type) 1) - std::log (((Type) 1) - x)) / (Type) 2; }
#endif
//==============================================================================
/** A predefined value for Pi, at double-precision.
@see float_Pi


+ 7
- 2
source/modules/juce_core/maths/juce_Random.cpp View File

@@ -81,6 +81,11 @@ int Random::nextInt (const int maxValue) noexcept
return (int) ((((unsigned int) nextInt()) * (uint64) maxValue) >> 32);
}
int Random::nextInt (Range<int> range) noexcept
{
return range.getStart() + nextInt (range.getLength());
}
int64 Random::nextInt64() noexcept
{
return (((int64) nextInt()) << 32) | (int64) (uint64) (uint32) nextInt();
@@ -93,12 +98,12 @@ bool Random::nextBool() noexcept
float Random::nextFloat() noexcept
{
return static_cast <uint32> (nextInt()) / (float) 0xffffffff;
return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0f);
}
double Random::nextDouble() noexcept
{
return static_cast <uint32> (nextInt()) / (double) 0xffffffff;
return static_cast<uint32> (nextInt()) / (std::numeric_limits<uint32>::max() + 1.0);
}
BigInteger Random::nextLargeNumber (const BigInteger& maximumValue)


+ 5
- 0
source/modules/juce_core/maths/juce_Random.h View File

@@ -69,6 +69,11 @@ public:
*/
int nextInt (int maxValue) noexcept;
/** 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;
/** Returns the next 64-bit random number.
@returns a random integer from the full range 0x8000000000000000 to 0x7fffffffffffffff
*/


+ 15
- 11
source/modules/juce_core/memory/juce_MemoryBlock.cpp View File

@@ -265,7 +265,7 @@ void MemoryBlock::copyTo (void* const dst, int offset, size_t num) const noexcep
String MemoryBlock::toString() const
{
return String (CharPointer_UTF8 (data), size);
return String::fromUTF8 (data, size);
}
//==============================================================================
@@ -352,7 +352,7 @@ void MemoryBlock::loadFromHexString (StringRef hex)
}
//==============================================================================
static const char* const base64EncodingTable = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
static const char base64EncodingTable[] = ".ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+";
String MemoryBlock::toBase64Encoding() const
{
@@ -373,9 +373,16 @@ String MemoryBlock::toBase64Encoding() const
return destString;
}
static const char base64DecodingTable[] =
{
63, 0, 0, 0, 0, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 0, 0, 0, 0, 0, 0, 0,
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
0, 0, 0, 0, 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52
};
bool MemoryBlock::fromBase64Encoding (StringRef s)
{
String::CharPointerType dot (CharacterFunctions::find (s.text, CharPointer_ASCII (".")));
String::CharPointerType dot (CharacterFunctions::find (s.text, (juce_wchar) '.'));
if (dot.isEmpty())
return false;
@@ -389,19 +396,16 @@ bool MemoryBlock::fromBase64Encoding (StringRef s)
for (;;)
{
const char c = (char) srcChars.getAndAdvance();
int c = (int) srcChars.getAndAdvance();
if (c == 0)
return true;
for (int j = 0; j < 64; ++j)
c -= 43;
if (isPositiveAndBelow (c, numElementsInArray (base64DecodingTable)))
{
if (base64EncodingTable[j] == c)
{
setBitRange ((size_t) pos, 6, j);
pos += 6;
break;
}
setBitRange ((size_t) pos, 6, base64DecodingTable [c]);
pos += 6;
}
}
}

+ 19
- 1
source/modules/juce_core/misc/juce_Uuid.cpp View File

@@ -33,6 +33,10 @@ Uuid::Uuid()
for (size_t i = 0; i < sizeof (uuid); ++i)
uuid[i] = (uint8) (r.nextInt (256));
// To make it RFC 4122 compliant, need to force a few bits...
uuid[6] = (uuid[6] & 0x0f) | 0x40;
uuid[8] = (uuid[8] & 0x3f) | 0x80;
}
Uuid::~Uuid() noexcept {}
@@ -65,9 +69,23 @@ bool Uuid::isNull() const noexcept
return true;
}
String Uuid::getHexRegion (int start, int length) const
{
return String::toHexString (uuid + start, length, 0);
}
String Uuid::toString() const
{
return String::toHexString (uuid, sizeof (uuid), 0);
return getHexRegion (0, 16);
}
String Uuid::toDashedString() const
{
return getHexRegion (0, 4)
+ "-" + getHexRegion (4, 2)
+ "-" + getHexRegion (6, 2)
+ "-" + getHexRegion (8, 2)
+ "-" + getHexRegion (10, 6);
}
Uuid::Uuid (const String& uuidString)


+ 10
- 4
source/modules/juce_core/misc/juce_Uuid.h View File

@@ -34,9 +34,9 @@
/**
A universally unique 128-bit identifier.
This class generates very random unique numbers based on the system time
and MAC addresses if any are available. It's extremely unlikely that two identical
UUIDs would ever be created by chance.
This class generates very random unique numbers. It's vanishingly unlikely
that two identical UUIDs would ever be created by chance. The values are
formatted to meet the RFC 4122 version 4 standard.
The class includes methods for saving the ID as a string or as raw binary data.
*/
@@ -44,7 +44,7 @@ class JUCE_API Uuid
{
public:
//==============================================================================
/** Creates a new unique ID. */
/** Creates a new unique ID, compliant with RFC 4122 version 4. */
Uuid();
/** Destructor. */
@@ -76,6 +76,11 @@ public:
*/
String toString() const;
/** Returns a stringified version of this UUID, separating it into sections with dashes.
@returns a string in the format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
*/
String toDashedString() const;
/** Creates an ID from an encoded string version.
@see toString
*/
@@ -107,6 +112,7 @@ public:
private:
//==============================================================================
uint8 uuid[16];
String getHexRegion (int, int) const;
JUCE_LEAK_DETECTOR (Uuid)
};


+ 33
- 23
source/modules/juce_core/native/java/JuceAppActivity.java View File

@@ -142,9 +142,9 @@ public final class JuceAppActivity extends Activity
//==============================================================================
private ViewHolder viewHolder;
public final ComponentPeerView createNewView (boolean opaque)
public final ComponentPeerView createNewView (boolean opaque, long host)
{
ComponentPeerView v = new ComponentPeerView (this, opaque);
ComponentPeerView v = new ComponentPeerView (this, opaque, host);
viewHolder.addView (v);
return v;
}
@@ -312,9 +312,10 @@ public final class JuceAppActivity extends Activity
public final class ComponentPeerView extends ViewGroup
implements View.OnFocusChangeListener
{
public ComponentPeerView (Context context, boolean opaque_)
public ComponentPeerView (Context context, boolean opaque_, long host)
{
super (context);
this.host = host;
setWillNotDraw (false);
opaque = opaque_;
@@ -325,13 +326,12 @@ public final class JuceAppActivity extends Activity
}
//==============================================================================
private native void handlePaint (Canvas canvas);
private native void handlePaint (long host, Canvas canvas);
@Override
public void draw (Canvas canvas)
public void onDraw (Canvas canvas)
{
super.draw (canvas);
handlePaint (canvas);
handlePaint (host, canvas);
}
@Override
@@ -341,11 +341,12 @@ public final class JuceAppActivity extends Activity
}
private boolean opaque;
private long host;
//==============================================================================
private native void handleMouseDown (int index, float x, float y, long time);
private native void handleMouseDrag (int index, float x, float y, long time);
private native void handleMouseUp (int index, float x, float y, long time);
private native void handleMouseDown (long host, int index, float x, float y, long time);
private native void handleMouseDrag (long host, int index, float x, float y, long time);
private native void handleMouseUp (long host, int index, float x, float y, long time);
@Override
public boolean onTouchEvent (MotionEvent event)
@@ -356,19 +357,19 @@ public final class JuceAppActivity extends Activity
switch (action & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
handleMouseDown (event.getPointerId(0), event.getX(), event.getY(), time);
handleMouseDown (host, event.getPointerId(0), event.getX(), event.getY(), time);
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
handleMouseUp (event.getPointerId(0), event.getX(), event.getY(), time);
handleMouseUp (host, event.getPointerId(0), event.getX(), event.getY(), time);
return true;
case MotionEvent.ACTION_MOVE:
{
int n = event.getPointerCount();
for (int i = 0; i < n; ++i)
handleMouseDrag (event.getPointerId(i), event.getX(i), event.getY(i), time);
handleMouseDrag (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
return true;
}
@@ -376,14 +377,14 @@ public final class JuceAppActivity extends Activity
case MotionEvent.ACTION_POINTER_UP:
{
int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
handleMouseUp (event.getPointerId(i), event.getX(i), event.getY(i), time);
handleMouseUp (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
return true;
}
case MotionEvent.ACTION_POINTER_DOWN:
{
int i = (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
handleMouseDown (event.getPointerId(i), event.getX(i), event.getY(i), time);
handleMouseDown (host, event.getPointerId(i), event.getX(i), event.getY(i), time);
return true;
}
@@ -395,8 +396,8 @@ public final class JuceAppActivity extends Activity
}
//==============================================================================
private native void handleKeyDown (int keycode, int textchar);
private native void handleKeyUp (int keycode, int textchar);
private native void handleKeyDown (long host, int keycode, int textchar);
private native void handleKeyUp (long host, int keycode, int textchar);
public void showKeyboard (boolean shouldShow)
{
@@ -414,14 +415,23 @@ public final class JuceAppActivity extends Activity
@Override
public boolean onKeyDown (int keyCode, KeyEvent event)
{
handleKeyDown (keyCode, event.getUnicodeChar());
switch (keyCode)
{
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
return super.onKeyDown (keyCode, event);
default: break;
}
handleKeyDown (host, keyCode, event.getUnicodeChar());
return true;
}
@Override
public boolean onKeyUp (int keyCode, KeyEvent event)
{
handleKeyUp (keyCode, event.getUnicodeChar());
handleKeyUp (host, keyCode, event.getUnicodeChar());
return true;
}
@@ -445,7 +455,7 @@ public final class JuceAppActivity extends Activity
protected void onSizeChanged (int w, int h, int oldw, int oldh)
{
super.onSizeChanged (w, h, oldw, oldh);
viewSizeChanged();
viewSizeChanged (host);
}
@Override
@@ -455,16 +465,16 @@ public final class JuceAppActivity extends Activity
requestTransparentRegion (getChildAt (i));
}
private native void viewSizeChanged();
private native void viewSizeChanged (long host);
@Override
public void onFocusChange (View v, boolean hasFocus)
{
if (v == this)
focusChanged (hasFocus);
focusChanged (host, hasFocus);
}
private native void focusChanged (boolean hasFocus);
private native void focusChanged (long host, boolean hasFocus);
public void setViewName (String newName) {}


+ 1
- 1
source/modules/juce_core/native/juce_BasicNativeHeaders.h View File

@@ -94,7 +94,7 @@
#define _UNICODE 1
#define UNICODE 1
#ifndef _WIN32_IE
#define _WIN32_IE 0x0400
#define _WIN32_IE 0x0500
#endif
#include <windows.h>


+ 2
- 140
source/modules/juce_core/native/juce_android_Files.cpp View File

@@ -26,34 +26,6 @@
==============================================================================
*/
bool File::copyInternal (const File& dest) const
{
FileInputStream in (*this);
if (dest.deleteFile())
{
{
FileOutputStream out (dest);
if (out.failedToOpen())
return false;
if (out.writeFromInputStream (in, -1) == getSize())
return true;
}
dest.deleteFile();
}
return false;
}
void File::findFileSystemRoots (Array<File>& destArray)
{
destArray.add (File ("/"));
}
//==============================================================================
bool File::isOnCDRomDrive() const
{
return false;
@@ -69,35 +41,11 @@ bool File::isOnRemovableDrive() const
return false;
}
bool File::isHidden() const
{
return getFileName().startsWithChar ('.');
}
//==============================================================================
namespace
{
File juce_readlink (const String& file, const File& defaultFile)
{
const int size = 8192;
HeapBlock<char> buffer;
buffer.malloc (size + 4);
const size_t numBytes = readlink (file.toUTF8(), buffer, size);
if (numBytes > 0 && numBytes <= size)
return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes));
return defaultFile;
}
}
File File::getLinkedTarget() const
String File::getVersion() const
{
return juce_readlink (getFullPathName().toUTF8(), *this);
return String::empty;
}
//==============================================================================
File File::getSpecialLocation (const SpecialLocationType type)
{
switch (type)
@@ -135,101 +83,15 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File::nonexistent;
}
//==============================================================================
String File::getVersion() const
{
return String::empty;
}
//==============================================================================
bool File::moveToTrash() const
{
if (! exists())
return true;
// TODO
return false;
}
//==============================================================================
class DirectoryIterator::NativeIterator::Pimpl
{
public:
Pimpl (const File& directory, const String& wildCard_)
: parentDir (File::addTrailingSeparator (directory.getFullPathName())),
wildCard (wildCard_),
dir (opendir (directory.getFullPathName().toUTF8()))
{
}
~Pimpl()
{
if (dir != 0)
closedir (dir);
}
bool next (String& filenameFound,
bool* const isDir, bool* const isHidden, int64* const fileSize,
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
if (dir != 0)
{
const char* wildcardUTF8 = nullptr;
for (;;)
{
struct dirent* const de = readdir (dir);
if (de == nullptr)
break;
if (wildcardUTF8 == nullptr)
wildcardUTF8 = wildCard.toUTF8();
if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
{
filenameFound = CharPointer_UTF8 (de->d_name);
updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
if (isHidden != 0)
*isHidden = filenameFound.startsWithChar ('.');
return true;
}
}
}
return false;
}
private:
String parentDir, wildCard;
DIR* dir;
JUCE_DECLARE_NON_COPYABLE (Pimpl)
};
DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
: pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
}
DirectoryIterator::NativeIterator::~NativeIterator()
{
}
bool DirectoryIterator::NativeIterator::next (String& filenameFound,
bool* const isDir, bool* const isHidden, int64* const fileSize,
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
//==============================================================================
JUCE_API bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String& parameters)
{
const LocalRef<jstring> t (javaString (fileName));


+ 1
- 1
source/modules/juce_core/native/juce_android_JNIHelpers.h View File

@@ -349,7 +349,7 @@ extern ThreadLocalJNIEnvHolder threadLocalJNIEnvHolder;
//==============================================================================
#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD) \
METHOD (createNewView, "createNewView", "(Z)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \
METHOD (createNewView, "createNewView", "(ZJ)L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;") \
METHOD (deleteView, "deleteView", "(L" JUCE_ANDROID_ACTIVITY_CLASSPATH "$ComponentPeerView;)V") \
METHOD (postMessage, "postMessage", "(J)V") \
METHOD (finish, "finish", "()V") \


+ 153
- 0
source/modules/juce_core/native/juce_linux_CommonFile.cpp View File

@@ -0,0 +1,153 @@
/*
==============================================================================
This file is part of the juce_core module of the JUCE library.
Copyright (c) 2013 - Raw Material Software Ltd.
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 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN
NO EVENT SHALL THE AUTHOR 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.
------------------------------------------------------------------------------
NOTE! This permissive ISC license applies ONLY to files within the juce_core module!
All other JUCE modules are covered by a dual GPL/commercial license, so if you are
using any other modules, be sure to check that you also comply with their license.
For more details, visit www.juce.com
==============================================================================
*/
bool File::copyInternal (const File& dest) const
{
FileInputStream in (*this);
if (dest.deleteFile())
{
{
FileOutputStream out (dest);
if (out.failedToOpen())
return false;
if (out.writeFromInputStream (in, -1) == getSize())
return true;
}
dest.deleteFile();
}
return false;
}
void File::findFileSystemRoots (Array<File>& destArray)
{
destArray.add (File ("/"));
}
bool File::isHidden() const
{
return getFileName().startsWithChar ('.');
}
static String getLinkedFile (StringRef file)
{
HeapBlock<char> buffer (8194);
const int numBytes = (int) readlink (file.text, buffer, 8192);
return String::fromUTF8 (buffer, jmax (0, numBytes));
};
bool File::isLink() const
{
return getLinkedFile (getFullPathName()).isNotEmpty();
}
File File::getLinkedTarget() const
{
String f (getLinkedFile (getFullPathName()));
if (f.isNotEmpty())
return getSiblingFile (f);
return *this;
}
//==============================================================================
class DirectoryIterator::NativeIterator::Pimpl
{
public:
Pimpl (const File& directory, const String& wc)
: parentDir (File::addTrailingSeparator (directory.getFullPathName())),
wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8()))
{
}
~Pimpl()
{
if (dir != nullptr)
closedir (dir);
}
bool next (String& filenameFound,
bool* const isDir, bool* const isHidden, int64* const fileSize,
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
if (dir != nullptr)
{
const char* wildcardUTF8 = nullptr;
for (;;)
{
struct dirent* const de = readdir (dir);
if (de == nullptr)
break;
if (wildcardUTF8 == nullptr)
wildcardUTF8 = wildCard.toUTF8();
if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
{
filenameFound = CharPointer_UTF8 (de->d_name);
updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
if (isHidden != nullptr)
*isHidden = filenameFound.startsWithChar ('.');
return true;
}
}
}
return false;
}
private:
String parentDir, wildCard;
DIR* dir;
JUCE_DECLARE_NON_COPYABLE (Pimpl)
};
DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
: pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
}
DirectoryIterator::NativeIterator::~NativeIterator() {}
bool DirectoryIterator::NativeIterator::next (String& filenameFound,
bool* isDir, bool* isHidden, int64* fileSize,
Time* modTime, Time* creationTime, bool* isReadOnly)
{
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}

+ 9
- 143
source/modules/juce_core/native/juce_linux_Files.cpp View File

@@ -34,35 +34,6 @@ enum
U_SMB_SUPER_MAGIC = 0x517B // linux/smb_fs.h
};
//==============================================================================
bool File::copyInternal (const File& dest) const
{
FileInputStream in (*this);
if (dest.deleteFile())
{
{
FileOutputStream out (dest);
if (out.failedToOpen())
return false;
if (out.writeFromInputStream (in, -1) == getSize())
return true;
}
dest.deleteFile();
}
return false;
}
void File::findFileSystemRoots (Array<File>& destArray)
{
destArray.add (File ("/"));
}
//==============================================================================
bool File::isOnCDRomDrive() const
{
struct statfs buf;
@@ -85,11 +56,7 @@ bool File::isOnHardDisk() const
case U_SMB_SUPER_MAGIC: // Network Samba
return false;
default:
// Assume anything else is a hard-disk (but note it could
// be a RAM disk. There isn't a good way of determining
// this for sure)
return true;
default: break;
}
}
@@ -103,32 +70,9 @@ bool File::isOnRemovableDrive() const
return false;
}
bool File::isHidden() const
{
return getFileName().startsWithChar ('.');
}
//==============================================================================
namespace
{
File juce_readlink (const String& file, const File& defaultFile)
{
const size_t size = 8192;
HeapBlock<char> buffer;
buffer.malloc (size + 4);
const size_t numBytes = readlink (file.toUTF8(), buffer, size);
if (numBytes > 0 && numBytes <= size)
return File (file).getSiblingFile (String::fromUTF8 (buffer, (int) numBytes));
return defaultFile;
}
}
File File::getLinkedTarget() const
String File::getVersion() const
{
return juce_readlink (getFullPathName().toUTF8(), *this);
return String::empty; // xxx not yet implemented
}
//==============================================================================
@@ -209,7 +153,10 @@ File File::getSpecialLocation (const SpecialLocationType type)
return juce_getExecutableFile();
case hostApplicationPath:
return juce_readlink ("/proc/self/exe", juce_getExecutableFile());
{
const File f ("/proc/self/exe");
return f.isLink() ? f.getLinkedTarget() : juce_getExecutableFile();
}
default:
jassertfalse; // unknown type?
@@ -219,12 +166,6 @@ File File::getSpecialLocation (const SpecialLocationType type)
return File::nonexistent;
}
//==============================================================================
String File::getVersion() const
{
return String::empty; // xxx not yet implemented
}
//==============================================================================
bool File::moveToTrash() const
{
@@ -243,81 +184,6 @@ bool File::moveToTrash() const
getFileExtension()));
}
//==============================================================================
class DirectoryIterator::NativeIterator::Pimpl
{
public:
Pimpl (const File& directory, const String& wc)
: parentDir (File::addTrailingSeparator (directory.getFullPathName())),
wildCard (wc), dir (opendir (directory.getFullPathName().toUTF8()))
{
}
~Pimpl()
{
if (dir != nullptr)
closedir (dir);
}
bool next (String& filenameFound,
bool* const isDir, bool* const isHidden, int64* const fileSize,
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
if (dir != nullptr)
{
const char* wildcardUTF8 = nullptr;
for (;;)
{
struct dirent* const de = readdir (dir);
if (de == nullptr)
break;
if (wildcardUTF8 == nullptr)
wildcardUTF8 = wildCard.toUTF8();
if (fnmatch (wildcardUTF8, de->d_name, FNM_CASEFOLD) == 0)
{
filenameFound = CharPointer_UTF8 (de->d_name);
updateStatInfoForFile (parentDir + filenameFound, isDir, fileSize, modTime, creationTime, isReadOnly);
if (isHidden != nullptr)
*isHidden = filenameFound.startsWithChar ('.');
return true;
}
}
}
return false;
}
private:
String parentDir, wildCard;
DIR* dir;
JUCE_DECLARE_NON_COPYABLE (Pimpl)
};
DirectoryIterator::NativeIterator::NativeIterator (const File& directory, const String& wildCard)
: pimpl (new DirectoryIterator::NativeIterator::Pimpl (directory, wildCard))
{
}
DirectoryIterator::NativeIterator::~NativeIterator()
{
}
bool DirectoryIterator::NativeIterator::next (String& filenameFound,
bool* const isDir, bool* const isHidden, int64* const fileSize,
Time* const modTime, Time* const creationTime, bool* const isReadOnly)
{
return pimpl->next (filenameFound, isDir, isHidden, fileSize, modTime, creationTime, isReadOnly);
}
//==============================================================================
static bool isFileExecutable (const String& filename)
{
@@ -340,8 +206,8 @@ bool Process::openDocument (const String& fileName, const String& parameters)
|| ! isFileExecutable (fileName))
{
// create a command that tries to launch a bunch of likely browsers
const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
"google-chrome", "chromium-browser", "opera", "konqueror" };
static const char* const browserNames[] = { "xdg-open", "/etc/alternatives/x-www-browser", "firefox", "mozilla",
"google-chrome", "chromium-browser", "opera", "konqueror" };
StringArray cmdLines;
for (int i = 0; i < numElementsInArray (browserNames); ++i)


+ 24
- 35
source/modules/juce_core/native/juce_linux_Network.cpp View File

@@ -126,6 +126,7 @@ public:
const int bytesRead = jmax (0, (int) recv (socketHandle, buffer, bytesToRead, MSG_WAITALL));
if (bytesRead == 0)
finished = true;
position += bytesRead;
return bytesRead;
}
@@ -249,7 +250,8 @@ private:
const MemoryBlock requestHeader (createRequestHeader (hostName, hostPort, proxyName, proxyPort,
hostPath, address, headers, postData, isPost));
if (! sendHeader (socketHandle, requestHeader, timeOutTime, progressCallback, progressCallbackContext))
if (! sendHeader (socketHandle, requestHeader, timeOutTime,
progressCallback, progressCallbackContext))
{
closeSocket();
return;
@@ -257,6 +259,7 @@ private:
}
String responseHeader (readResponse (socketHandle, timeOutTime));
position = 0;
if (responseHeader.isNotEmpty())
{
@@ -270,7 +273,8 @@ private:
String location (findHeaderItem (headerLines, "Location:"));
if (statusCode >= 300 && statusCode < 400 && location.isNotEmpty())
if (statusCode >= 300 && statusCode < 400
&& location.isNotEmpty() && location != address)
{
if (! location.startsWithIgnoreCase ("http://"))
location = "http://" + location;
@@ -293,44 +297,32 @@ private:
}
//==============================================================================
static String readResponse (const int socketHandle, const uint32 timeOutTime)
String readResponse (const int socketHandle, const uint32 timeOutTime)
{
int bytesRead = 0, numConsecutiveLFs = 0;
MemoryBlock buffer (1024, true);
int numConsecutiveLFs = 0;
MemoryOutputStream buffer;
while (numConsecutiveLFs < 2 && bytesRead < 32768
&& Time::getMillisecondCounter() <= timeOutTime)
while (numConsecutiveLFs < 2
&& buffer.getDataSize() < 32768
&& Time::getMillisecondCounter() <= timeOutTime
&& ! (finished || isError()))
{
fd_set readbits;
FD_ZERO (&readbits);
FD_SET (socketHandle, &readbits);
struct timeval tv;
tv.tv_sec = jmax (1, (int) (timeOutTime - Time::getMillisecondCounter()) / 1000);
tv.tv_usec = 0;
if (select (socketHandle + 1, &readbits, 0, 0, &tv) <= 0)
return String::empty; // (timeout)
buffer.ensureSize (bytesRead + 8, true);
char* const dest = (char*) buffer.getData() + bytesRead;
if (recv (socketHandle, dest, 1, 0) == -1)
char c = 0;
if (read (&c, 1) != 1)
return String::empty;
const char lastByte = *dest;
++bytesRead;
buffer.writeByte (c);
if (lastByte == '\n')
if (c == '\n')
++numConsecutiveLFs;
else if (lastByte != '\r')
else if (c != '\r')
numConsecutiveLFs = 0;
}
const String header (CharPointer_UTF8 ((const char*) buffer.getData()));
const String header (buffer.toString().trimEnd());
if (header.startsWithIgnoreCase ("HTTP/"))
return header.trimEnd();
return header;
return String::empty;
}
@@ -344,9 +336,6 @@ private:
static void writeHost (MemoryOutputStream& dest, const bool isPost, const String& path, const String& host, const int port)
{
dest << (isPost ? "POST " : "GET ") << path << " HTTP/1.0\r\nHost: " << host;
if (port > 0)
dest << ':' << port;
}
static MemoryBlock createRequestHeader (const String& hostName, const int hostPort,
@@ -365,7 +354,7 @@ private:
writeValueIfNotPresent (header, userHeaders, "User-Agent:", "JUCE/" JUCE_STRINGIFY(JUCE_MAJOR_VERSION)
"." JUCE_STRINGIFY(JUCE_MINOR_VERSION)
"." JUCE_STRINGIFY(JUCE_BUILDNUMBER));
writeValueIfNotPresent (header, userHeaders, "Connection:", "Close");
writeValueIfNotPresent (header, userHeaders, "Connection:", "close");
if (isPost)
writeValueIfNotPresent (header, userHeaders, "Content-Length:", String ((int) postData.getSize()));
@@ -453,9 +442,9 @@ InputStream* URL::createNativeStream (const String& address, bool isPost, const
OpenStreamProgressCallback* progressCallback, void* progressCallbackContext,
const String& headers, const int timeOutMs, StringPairArray* responseHeaders)
{
ScopedPointer <WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
ScopedPointer<WebInputStream> wi (new WebInputStream (address, isPost, postData,
progressCallback, progressCallbackContext,
headers, timeOutMs, responseHeaders));
return wi->isError() ? nullptr : wi.release();
}

+ 17
- 8
source/modules/juce_core/native/juce_mac_Files.mm View File

@@ -101,7 +101,7 @@ namespace FileHelpers
}
#if JUCE_IOS
String getIOSSystemLocation (NSSearchPathDirectory type)
static String getIOSSystemLocation (NSSearchPathDirectory type)
{
return nsStringToJuce ([NSSearchPathForDirectoriesInDomains (type, NSUserDomainMask, YES)
objectAtIndex: 0]);
@@ -132,14 +132,14 @@ namespace FileHelpers
bool File::isOnCDRomDrive() const
{
const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", 0 };
static const char* const cdTypes[] = { "cd9660", "cdfs", "cddafs", "udf", nullptr };
return FileHelpers::isFileOnDriveType (*this, cdTypes);
}
bool File::isOnHardDisk() const
{
const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", 0 };
static const char* const nonHDTypes[] = { "nfs", "smbfs", "ramfs", nullptr };
return ! (isOnCDRomDrive() || FileHelpers::isFileOnDriveType (*this, nonHDTypes));
}
@@ -275,17 +275,25 @@ String File::getVersion() const
}
//==============================================================================
File File::getLinkedTarget() const
static NSString* getFileLink (const String& path)
{
#if JUCE_IOS || (defined (MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5)
NSString* dest = [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (getFullPathName()) error: nil];
return [[NSFileManager defaultManager] destinationOfSymbolicLinkAtPath: juceStringToNS (path) error: nil];
#else
// (the cast here avoids a deprecation warning)
NSString* dest = [((id) [NSFileManager defaultManager]) pathContentOfSymbolicLinkAtPath: juceStringToNS (getFullPathName())];
return [((id) [NSFileManager defaultManager]) pathContentOfSymbolicLinkAtPath: juceStringToNS (path)];
#endif
}
if (dest != nil)
return File (nsStringToJuce (dest));
bool File::isLink() const
{
return getFileLink (fullPath) != nil;
}
File File::getLinkedTarget() const
{
if (NSString* dest = getFileLink (fullPath))
return getSiblingFile (nsStringToJuce (dest));
return *this;
}
@@ -399,6 +407,7 @@ bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String&
NSURL* filenameAsURL = [NSURL URLWithString: juceStringToNS (fileName)];
#if JUCE_IOS
(void) parameters;
return [[UIApplication sharedApplication] openURL: filenameAsURL];
#else
NSWorkspace* workspace = [NSWorkspace sharedWorkspace];


+ 5
- 0
source/modules/juce_core/native/juce_mac_Network.mm View File

@@ -59,6 +59,11 @@ bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailA
const StringArray& filesToAttach)
{
#if JUCE_IOS
(void) targetEmailAddress;
(void) emailSubject;
(void) bodyText;
(void) filesToAttach;
//xxx probably need to use MFMailComposeViewController
jassertfalse;
return false;


+ 16
- 7
source/modules/juce_core/native/juce_posix_SharedCode.h View File

@@ -988,7 +988,7 @@ void* DynamicLibrary::getFunction (const String& functionName) noexcept
class ChildProcess::ActiveProcess
{
public:
ActiveProcess (const StringArray& arguments)
ActiveProcess (const StringArray& arguments, int streamFlags)
: childPID (0), pipeHandle (0), readHandle (0)
{
int pipeHandles[2] = { 0 };
@@ -1006,8 +1006,17 @@ public:
{
// we're the child process..
close (pipeHandles[0]); // close the read handle
dup2 (pipeHandles[1], 1); // turns the pipe into stdout
dup2 (pipeHandles[1], 2); // + stderr
if ((streamFlags | wantStdOut) != 0)
dup2 (pipeHandles[1], 1); // turns the pipe into stdout
else
close (STDOUT_FILENO);
if ((streamFlags | wantStdErr) != 0)
dup2 (pipeHandles[1], 2);
else
close (STDERR_FILENO);
close (pipeHandles[1]);
Array<char*> argv;
@@ -1082,17 +1091,17 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess)
};
bool ChildProcess::start (const String& command)
bool ChildProcess::start (const String& command, int streamFlags)
{
return start (StringArray::fromTokens (command, true));
return start (StringArray::fromTokens (command, true), streamFlags);
}
bool ChildProcess::start (const StringArray& args)
bool ChildProcess::start (const StringArray& args, int streamFlags)
{
if (args.size() == 0)
return false;
activeProcess = new ActiveProcess (args);
activeProcess = new ActiveProcess (args, streamFlags);
if (activeProcess->childPID == 0)
activeProcess = nullptr;


+ 9
- 4
source/modules/juce_core/native/juce_win32_Files.cpp View File

@@ -590,6 +590,11 @@ String File::getVersion() const
}
//==============================================================================
bool File::isLink() const
{
return hasFileExtension (".lnk");
}
File File::getLinkedTarget() const
{
File result (*this);
@@ -600,8 +605,8 @@ File File::getLinkedTarget() const
else if (! hasFileExtension (".lnk"))
return result;
ComSmartPtr <IShellLink> shellLink;
ComSmartPtr <IPersistFile> persistFile;
ComSmartPtr<IShellLink> shellLink;
ComSmartPtr<IPersistFile> persistFile;
if (SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))
&& SUCCEEDED (shellLink.QueryInterface (persistFile))
@@ -622,8 +627,8 @@ bool File::createLink (const String& description, const File& linkFileToCreate)
{
linkFileToCreate.deleteFile();
ComSmartPtr <IShellLink> shellLink;
ComSmartPtr <IPersistFile> persistFile;
ComSmartPtr<IShellLink> shellLink;
ComSmartPtr<IPersistFile> persistFile;
return SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))
&& SUCCEEDED (shellLink->SetPath (getFullPathName().toWideCharPointer()))


+ 8
- 7
source/modules/juce_core/native/juce_win32_Threads.cpp View File

@@ -444,7 +444,7 @@ void InterProcessLock::exit()
class ChildProcess::ActiveProcess
{
public:
ActiveProcess (const String& command)
ActiveProcess (const String& command, int streamFlags)
: ok (false), readPipe (0), writePipe (0)
{
SECURITY_ATTRIBUTES securityAtts = { 0 };
@@ -456,8 +456,9 @@ public:
{
STARTUPINFOW startupInfo = { 0 };
startupInfo.cb = sizeof (startupInfo);
startupInfo.hStdError = writePipe;
startupInfo.hStdOutput = writePipe;
startupInfo.hStdOutput = (streamFlags | wantStdOut) != 0 ? writePipe : 0;
startupInfo.hStdError = (streamFlags | wantStdErr) != 0 ? writePipe : 0;
startupInfo.dwFlags = STARTF_USESTDHANDLES;
ok = CreateProcess (nullptr, const_cast <LPWSTR> (command.toWideCharPointer()),
@@ -535,9 +536,9 @@ private:
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ActiveProcess)
};
bool ChildProcess::start (const String& command)
bool ChildProcess::start (const String& command, int streamFlags)
{
activeProcess = new ActiveProcess (command);
activeProcess = new ActiveProcess (command, streamFlags);
if (! activeProcess->ok)
activeProcess = nullptr;
@@ -545,9 +546,9 @@ bool ChildProcess::start (const String& command)
return activeProcess != nullptr;
}
bool ChildProcess::start (const StringArray& args)
bool ChildProcess::start (const StringArray& args, int streamFlags)
{
return start (args.joinIntoString (" "));
return start (args.joinIntoString (" "), streamFlags);
}
bool ChildProcess::isRunning() const


+ 1
- 1
source/modules/juce_core/network/juce_URL.cpp View File

@@ -292,7 +292,7 @@ URL URL::getChildURL (const String& subPath) const
//==============================================================================
bool URL::isProbablyAWebsiteURL (const String& possibleURL)
{
const char* validProtocols[] = { "http:", "ftp:", "https:" };
static const char* validProtocols[] = { "http:", "ftp:", "https:" };
for (int i = 0; i < numElementsInArray (validProtocols); ++i)
if (possibleURL.startsWithIgnoreCase (validProtocols[i]))


+ 1
- 1
source/modules/juce_core/network/juce_URL.h View File

@@ -230,7 +230,7 @@ public:
/** Attempts to open a stream that can read from this URL.
@param usePostCommand if true, it will try to do use a http 'POST' to pass
the paramters, otherwise it'll encode them into the
the parameters, otherwise it'll encode them into the
URL and do a 'GET'.
@param progressCallback if this is non-zero, it lets you supply a callback function
to keep track of the operation's progress. This can be useful


+ 1
- 2
source/modules/juce_core/streams/juce_InputStream.cpp View File

@@ -175,8 +175,7 @@ String InputStream::readString()
}
}
return String (CharPointer_UTF8 (data),
CharPointer_UTF8 (data + i));
return String::fromUTF8 (data, i);
}
String InputStream::readNextLine()


+ 13
- 2
source/modules/juce_core/streams/juce_OutputStream.cpp View File

@@ -279,14 +279,25 @@ void OutputStream::setNewLineString (const String& newLineString_)
}
//==============================================================================
template <typename IntegerType>
static void writeIntToStream (OutputStream& stream, IntegerType number)
{
char buffer [NumberToStringConverters::charsNeededForInt];
char* end = buffer + numElementsInArray (buffer);
const char* start = NumberToStringConverters::numberToString (end, number);
stream.write (start, (size_t) (end - start - 1));
}
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int number)
{
return stream << String (number);
writeIntToStream (stream, number);
return stream;
}
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const int64 number)
{
return stream << String (number);
writeIntToStream (stream, number);
return stream;
}
JUCE_API OutputStream& JUCE_CALLTYPE operator<< (OutputStream& stream, const double number)


Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save