Browse Source

Merge branch 'develop' of github.com:falkTX/Carla into develop

tags/v2.3.0-RC1
falkTX 4 years ago
parent
commit
b7ba3ca9a9
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
23 changed files with 425 additions and 156 deletions
  1. +6
    -0
      INSTALL.md
  2. +1
    -1
      data/macos/common.env
  3. +4
    -3
      data/macos/env.sh
  4. +2
    -1
      source/Makefile.mk
  5. +2
    -1
      source/backend/CarlaPlugin.hpp
  6. +52
    -10
      source/backend/engine/CarlaEngine.cpp
  7. +20
    -9
      source/backend/engine/CarlaEngineBridge.cpp
  8. +5
    -3
      source/backend/engine/CarlaEngineDummy.cpp
  9. +33
    -15
      source/backend/plugin/CarlaPluginBridge.cpp
  10. +32
    -2
      source/backend/plugin/CarlaPluginJuce.cpp
  11. +57
    -4
      source/backend/plugin/CarlaPluginLV2.cpp
  12. +1
    -0
      source/backend/plugin/CarlaPluginVST2.cpp
  13. +22
    -3
      source/bridges-plugin/CarlaBridgePlugin.cpp
  14. +9
    -0
      source/bridges-ui/CarlaBridgeFormatLV2.cpp
  15. +16
    -0
      source/discovery/carla-discovery.cpp
  16. +12
    -0
      source/frontend/widgets/racklistwidget.py
  17. +108
    -47
      source/native-plugins/audio-base.hpp
  18. +16
    -31
      source/native-plugins/audio-file.cpp
  19. +6
    -24
      source/native-plugins/midi-file.cpp
  20. +4
    -2
      source/utils/CarlaBinaryUtils.hpp
  21. +7
    -0
      source/utils/CarlaMacUtils.cpp
  22. +5
    -0
      source/utils/CarlaMacUtils.hpp
  23. +5
    -0
      source/utils/CarlaMutex.hpp

+ 6
- 0
INSTALL.md View File

@@ -1,5 +1,11 @@
# INSTALL for Carla # INSTALL for Carla


NOTE: when using MSYS2 on Windows, an additional step is necessary in order
to solve an issue with symbolic links to some dependency folders before build:
```
$ make msys2fix
```

To install Carla, simply run as usual: To install Carla, simply run as usual:
``` ```
$ make $ make


+ 1
- 1
data/macos/common.env View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash


if [ "$(uname -m)" = "arm64" ]; then
if [ "$(uname -m)" = "arm64" ] || [ "$(uname -r)" = "20.1.0" ]; then
MACOS_UNIVERSAL=1 MACOS_UNIVERSAL=1
else else
MACOS_UNIVERSAL=0 MACOS_UNIVERSAL=0


+ 4
- 3
data/macos/env.sh View File

@@ -13,7 +13,7 @@ fi


export CC=clang export CC=clang
export CXX=clang++ export CXX=clang++
export CFLAGS="-I${TARGETDIR}/carla64/include -mmacosx-version-min=${MACOS_VERSION_MIN}"
export CFLAGS="-I${TARGETDIR}/carla64/include -mmacosx-version-min=${MACOS_VERSION_MIN} -DMAC_OS_X_VERSION_MAX_ALLOWED=MAC_OS_X_VERSION_10_12"
export CFLAGS="${CFLAGS} -mtune=generic -msse -msse2" export CFLAGS="${CFLAGS} -mtune=generic -msse -msse2"
export LDFLAGS="-L${TARGETDIR}/carla64/lib -stdlib=libc++" export LDFLAGS="-L${TARGETDIR}/carla64/lib -stdlib=libc++"
unset CPPFLAGS unset CPPFLAGS
@@ -21,9 +21,10 @@ unset CPPFLAGS
if [ "${MACOS_UNIVERSAL}" -eq 1 ]; then if [ "${MACOS_UNIVERSAL}" -eq 1 ]; then
export CFLAGS="${CFLAGS} -arch x86_64 -arch arm64" export CFLAGS="${CFLAGS} -arch x86_64 -arch arm64"
export LDFLAGS="${LDFLAGS} -arch x86_64 -arch arm64" export LDFLAGS="${LDFLAGS} -arch x86_64 -arch arm64"
export MACOS_UNIVERSAL="true"
else else
export CFLAGS="${CFLAGS} -m${ARCH}"
export LDFLAGS="${LDFLAGS} -m${ARCH}"
export CFLAGS="${CFLAGS} -m64"
export LDFLAGS="${LDFLAGS} -m64"
fi fi


export CXXFLAGS="${CFLAGS} -stdlib=libc++ -Wno-unknown-pragmas -Wno-unused-private-field -Werror=auto-var-id" export CXXFLAGS="${CFLAGS} -stdlib=libc++ -Wno-unknown-pragmas -Wno-unused-private-field -Werror=auto-var-id"


+ 2
- 1
source/Makefile.mk View File

@@ -359,7 +359,8 @@ ifeq ($(shell $(PKG_CONFIG) --exists libmagic && echo true),true)
HAVE_LIBMAGIC = true HAVE_LIBMAGIC = true
else else
# old libmagic versions don't have a pkg-config file, so we need to call the compiler to test it # old libmagic versions don't have a pkg-config file, so we need to call the compiler to test it
HAVE_LIBMAGIC = $(shell echo '\#include <magic.h>' | $(CC) $(CFLAGS) -x c -w -c - -o /dev/null 2>/dev/null && echo true)
CFLAGS_WITHOUT_ARCH = $(subst -arch arm64,,$(CFLAGS))
HAVE_LIBMAGIC = $(shell echo '\#include <magic.h>' | $(CC) $(CFLAGS_WITHOUT_ARCH) -x c -w -c - -o /dev/null 2>/dev/null && echo true)
endif endif


endif endif


+ 2
- 1
source/backend/CarlaPlugin.hpp View File

@@ -964,7 +964,8 @@ public:


static CarlaPluginPtr newNative(const Initializer& init); static CarlaPluginPtr newNative(const Initializer& init);
static CarlaPluginPtr newBridge(const Initializer& init, static CarlaPluginPtr newBridge(const Initializer& init,
BinaryType btype, PluginType ptype, const char* bridgeBinary);
BinaryType btype, PluginType ptype,
const char* binaryArchName, const char* bridgeBinary);


static CarlaPluginPtr newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* rdfDescriptor); static CarlaPluginPtr newLADSPA(const Initializer& init, const LADSPA_RDF_Descriptor* rdfDescriptor);
static CarlaPluginPtr newDSSI(const Initializer& init); static CarlaPluginPtr newDSSI(const Initializer& init);


+ 52
- 10
source/backend/engine/CarlaEngine.cpp View File

@@ -44,6 +44,13 @@
#include "water/xml/XmlDocument.h" #include "water/xml/XmlDocument.h"
#include "water/xml/XmlElement.h" #include "water/xml/XmlElement.h"


#ifdef CARLA_OS_MAC
# include "CarlaMacUtils.hpp"
# if defined(CARLA_OS_64BIT) && defined(HAVE_LIBMAGIC) && ! defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
# define ADAPT_FOR_APPLE_SILLICON
# endif
#endif

#include <map> #include <map>


// FIXME Remove on 2.1 release // FIXME Remove on 2.1 release
@@ -560,12 +567,27 @@ bool CarlaEngine::addPlugin(const BinaryType btype,
bridgeBinary.clear(); bridgeBinary.clear();
} }


const bool canBeBridged = ptype != PLUGIN_INTERNAL
&& ptype != PLUGIN_DLS
&& ptype != PLUGIN_GIG
&& ptype != PLUGIN_SF2
&& ptype != PLUGIN_SFZ
&& ptype != PLUGIN_JACK;

// Prefer bridges for some specific plugins // Prefer bridges for some specific plugins
const bool preferBridges = pData->options.preferPluginBridges;
bool preferBridges = pData->options.preferPluginBridges;
const char* needsArchBridge = nullptr;


#if 0 // ndef BUILD_BRIDGE
if (! preferBridges)
#ifdef CARLA_OS_MAC
// Plugin might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
if (canBeBridged && ptype != PLUGIN_LV2 && ptype != PLUGIN_AU)
removeFileFromQuarantine(filename);
#endif

#ifndef BUILD_BRIDGE
if (canBeBridged && ! preferBridges)
{ {
# if 0
if (ptype == PLUGIN_LV2 && label != nullptr) if (ptype == PLUGIN_LV2 && label != nullptr)
{ {
if (std::strncmp(label, "http://calf.sourceforge.net/plugins/", 36) == 0 || if (std::strncmp(label, "http://calf.sourceforge.net/plugins/", 36) == 0 ||
@@ -575,19 +597,39 @@ bool CarlaEngine::addPlugin(const BinaryType btype,
preferBridges = true; preferBridges = true;
} }
} }
# endif
# ifdef ADAPT_FOR_APPLE_SILLICON
// see if this binary needs bridging
if (ptype == PLUGIN_VST2)
{
if (const char* const vst2Binary = findBinaryInBundle(filename))
{
const CarlaMagic magic;
if (const char* const output = magic.getFileDescription(vst2Binary))
{
# ifdef __aarch64__
if (std::strstr(output, "arm64") == nullptr && std::strstr(output, "x86_64") != nullptr)
needsArchBridge = "x86_64";
# else
if (std::strstr(output, "x86_64") == nullptr && std::strstr(output, "arm64") != nullptr)
needsArchBridge = "arm64";
# endif
}
}
}
else if (ptype == PLUGIN_VST3)
{
// TODO
}
# endif
} }
#endif // ! BUILD_BRIDGE #endif // ! BUILD_BRIDGE


const bool canBeBridged = ptype != PLUGIN_INTERNAL
&& ptype != PLUGIN_SF2
&& ptype != PLUGIN_SFZ
&& ptype != PLUGIN_JACK;

if (canBeBridged && (btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty())))
if (canBeBridged && (needsArchBridge || btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty())))
{ {
if (bridgeBinary.isNotEmpty()) if (bridgeBinary.isNotEmpty())
{ {
plugin = CarlaPlugin::newBridge(initializer, btype, ptype, bridgeBinary);
plugin = CarlaPlugin::newBridge(initializer, btype, ptype, needsArchBridge, bridgeBinary);
} }
else else
{ {


+ 20
- 9
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -143,49 +143,56 @@ public:


if (! fShmAudioPool.attachClient(fBaseNameAudioPool)) if (! fShmAudioPool.attachClient(fBaseNameAudioPool))
{ {
carla_stderr("Failed to attach to audio pool shared memory");
pData->close();
setLastError("Failed to attach to audio pool shared memory");
return false; return false;
} }


if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl)) if (! fShmRtClientControl.attachClient(fBaseNameRtClientControl))
{ {
pData->close();
clear(); clear();
carla_stderr("Failed to attach to rt client control shared memory");
setLastError("Failed to attach to rt client control shared memory");
return false; return false;
} }


if (! fShmRtClientControl.mapData()) if (! fShmRtClientControl.mapData())
{ {
pData->close();
clear(); clear();
carla_stderr("Failed to map rt client control shared memory");
setLastError("Failed to map rt client control shared memory");
return false; return false;
} }


if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl)) if (! fShmNonRtClientControl.attachClient(fBaseNameNonRtClientControl))
{ {
pData->close();
clear(); clear();
carla_stderr("Failed to attach to non-rt client control shared memory");
setLastError("Failed to attach to non-rt client control shared memory");
return false; return false;
} }


if (! fShmNonRtClientControl.mapData()) if (! fShmNonRtClientControl.mapData())
{ {
pData->close();
clear(); clear();
carla_stderr("Failed to map non-rt control client shared memory");
setLastError("Failed to map non-rt control client shared memory");
return false; return false;
} }


if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl)) if (! fShmNonRtServerControl.attachClient(fBaseNameNonRtServerControl))
{ {
pData->close();
clear(); clear();
carla_stderr("Failed to attach to non-rt server control shared memory");
setLastError("Failed to attach to non-rt server control shared memory");
return false; return false;
} }


if (! fShmNonRtServerControl.mapData()) if (! fShmNonRtServerControl.mapData())
{ {
pData->close();
clear(); clear();
carla_stderr("Failed to map non-rt control server shared memory");
setLastError("Failed to map non-rt control server shared memory");
return false; return false;
} }


@@ -210,7 +217,9 @@ public:
shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) || shmNonRtClientDataSize != sizeof(BridgeNonRtClientData) ||
shmNonRtServerDataSize != sizeof(BridgeNonRtServerData)) shmNonRtServerDataSize != sizeof(BridgeNonRtServerData))
{ {
carla_stderr2("CarlaEngineBridge: data size mismatch");
pData->close();
clear();
setLastError("Shared memory data size mismatch");
return false; return false;
} }


@@ -222,7 +231,9 @@ public:


if (pData->bufferSize == 0 || carla_isZero(pData->sampleRate)) if (pData->bufferSize == 0 || carla_isZero(pData->sampleRate))
{ {
carla_stderr2("CarlaEngineBridge: invalid empty state");
pData->close();
clear();
setLastError("Shared memory has invalid data");
return false; return false;
} }




+ 5
- 3
source/backend/engine/CarlaEngineDummy.cpp View File

@@ -232,9 +232,11 @@ protected:
carla_zeroFloats(audioIns[1], bufferSize); carla_zeroFloats(audioIns[1], bufferSize);
carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount); carla_zeroStructs(pData->events.in, kMaxEngineEventInternalCount);


int64_t oldTime, newTime;

while (! shouldThreadExit()) while (! shouldThreadExit())
{ {
const int64_t oldTime = getTimeInMicroseconds();
oldTime = getTimeInMicroseconds();


const PendingRtEventsRunner prt(this, bufferSize, true); const PendingRtEventsRunner prt(this, bufferSize, true);


@@ -244,7 +246,7 @@ protected:


pData->graph.process(pData, audioIns, audioOuts, bufferSize); pData->graph.process(pData, audioIns, audioOuts, bufferSize);


const int64_t newTime = getTimeInMicroseconds();
newTime = getTimeInMicroseconds();
CARLA_SAFE_ASSERT_CONTINUE(newTime >= oldTime); CARLA_SAFE_ASSERT_CONTINUE(newTime >= oldTime);


const int64_t remainingTime = cycleTime - (newTime - oldTime); const int64_t remainingTime = cycleTime - (newTime - oldTime);
@@ -267,7 +269,7 @@ protected:
std::free(audioOuts[0]); std::free(audioOuts[0]);
std::free(audioOuts[1]); std::free(audioOuts[1]);


carla_stdout("CarlaEngineDummy audio thread finished");
carla_stdout("CarlaEngineDummy audio thread finished with %u Xruns", pData->xruns);
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------


+ 33
- 15
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -91,7 +91,8 @@ public:
: CarlaThread("CarlaPluginBridgeThread"), : CarlaThread("CarlaPluginBridgeThread"),
kEngine(engine), kEngine(engine),
kPlugin(plugin), kPlugin(plugin),
fBinary(),
fBinaryArchName(),
fBridgeBinary(),
fLabel(), fLabel(),
fShmIds(), fShmIds(),
#ifndef CARLA_OS_WIN #ifndef CARLA_OS_WIN
@@ -103,18 +104,20 @@ public:
#ifndef CARLA_OS_WIN #ifndef CARLA_OS_WIN
const char* const winePrefix, const char* const winePrefix,
#endif #endif
const char* const binary,
const char* const binaryArchName,
const char* const bridgeBinary,
const char* const label, const char* const label,
const char* const shmIds) noexcept const char* const shmIds) noexcept
{ {
CARLA_SAFE_ASSERT_RETURN(binary != nullptr && binary[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(bridgeBinary != nullptr && bridgeBinary[0] != '\0',);
CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',); CARLA_SAFE_ASSERT_RETURN(shmIds != nullptr && shmIds[0] != '\0',);
CARLA_SAFE_ASSERT(! isThreadRunning()); CARLA_SAFE_ASSERT(! isThreadRunning());


#ifndef CARLA_OS_WIN #ifndef CARLA_OS_WIN
fWinePrefix = winePrefix; fWinePrefix = winePrefix;
#endif #endif
fBinary = binary;
fBinaryArchName = binaryArchName;
fBridgeBinary = bridgeBinary;
fShmIds = shmIds; fShmIds = shmIds;


if (label != nullptr) if (label != nullptr)
@@ -160,7 +163,7 @@ protected:


#ifndef CARLA_OS_WIN #ifndef CARLA_OS_WIN
// start with "wine" if needed // start with "wine" if needed
if (fBinary.endsWithIgnoreCase(".exe"))
if (fBridgeBinary.endsWithIgnoreCase(".exe"))
{ {
String wineCMD; String wineCMD;


@@ -168,7 +171,7 @@ protected:
{ {
wineCMD = options.wine.executable; wineCMD = options.wine.executable;


if (fBinary.endsWithIgnoreCase("64.exe")
if (fBridgeBinary.endsWithIgnoreCase("64.exe")
&& options.wine.executable[0] == CARLA_OS_SEP && options.wine.executable[0] == CARLA_OS_SEP
&& File(wineCMD + "64").existsAsFile()) && File(wineCMD + "64").existsAsFile())
wineCMD += "64"; wineCMD += "64";
@@ -182,8 +185,18 @@ protected:
} }
#endif #endif


// binary
arguments.add(fBinary);
#ifdef CARLA_OS_MAC
// setup binary arch
if (fBinaryArchName.isNotEmpty())
{
arguments.add("arch");
arguments.add("-arch");
arguments.add(fBinaryArchName);
}
#endif

// bridge binary
arguments.add(fBridgeBinary);


// plugin type // plugin type
arguments.add(getPluginTypeAsString(kPlugin->getType())); arguments.add(getPluginTypeAsString(kPlugin->getType()));
@@ -309,7 +322,7 @@ protected:
#endif #endif


carla_stdout("Starting plugin bridge, command is:\n%s \"%s\" \"%s\" \"%s\" " P_INT64, carla_stdout("Starting plugin bridge, command is:\n%s \"%s\" \"%s\" \"%s\" " P_INT64,
fBinary.toRawUTF8(), getPluginTypeAsString(kPlugin->getType()), filename.toRawUTF8(), fLabel.toRawUTF8(), kPlugin->getUniqueId());
fBridgeBinary.toRawUTF8(), getPluginTypeAsString(kPlugin->getType()), filename.toRawUTF8(), fLabel.toRawUTF8(), kPlugin->getUniqueId());


started = fProcess->start(arguments); started = fProcess->start(arguments);
} }
@@ -361,7 +374,8 @@ private:
CarlaEngine* const kEngine; CarlaEngine* const kEngine;
CarlaPlugin* const kPlugin; CarlaPlugin* const kPlugin;


String fBinary;
String fBinaryArchName;
String fBridgeBinary;
String fLabel; String fLabel;
String fShmIds; String fShmIds;
#ifndef CARLA_OS_WIN #ifndef CARLA_OS_WIN
@@ -2543,6 +2557,7 @@ public:
const char* const label, const char* const label,
const int64_t uniqueId, const int64_t uniqueId,
const uint options, const uint options,
const char* const binaryArchName,
const char* const bridgeBinary) const char* const bridgeBinary)
{ {
CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
@@ -2652,7 +2667,7 @@ public:
#ifndef CARLA_OS_WIN #ifndef CARLA_OS_WIN
fWinePrefix.toRawUTF8(), fWinePrefix.toRawUTF8(),
#endif #endif
bridgeBinary, label, shmIdsStr);
binaryArchName, bridgeBinary, label, shmIdsStr);
} }


if (! restartBridgeThread()) if (! restartBridgeThread())
@@ -3136,11 +3151,14 @@ CARLA_BACKEND_END_NAMESPACE
CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE


CarlaPluginPtr CarlaPlugin::newBridge(const Initializer& init, CarlaPluginPtr CarlaPlugin::newBridge(const Initializer& init,
BinaryType btype, PluginType ptype, const char* bridgeBinary)
const BinaryType btype,
const PluginType ptype,
const char* const binaryArchName,
const char* bridgeBinary)
{ {
carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\")",
carla_debug("CarlaPlugin::newBridge({%p, \"%s\", \"%s\", \"%s\"}, %s, %s, \"%s\", \"%s\")",
init.engine, init.filename, init.name, init.label, init.engine, init.filename, init.name, init.label,
BinaryType2Str(btype), PluginType2Str(ptype), bridgeBinary);
BinaryType2Str(btype), PluginType2Str(ptype), binaryArchName, bridgeBinary);


if (bridgeBinary == nullptr || bridgeBinary[0] == '\0') if (bridgeBinary == nullptr || bridgeBinary[0] == '\0')
{ {
@@ -3156,7 +3174,7 @@ CarlaPluginPtr CarlaPlugin::newBridge(const Initializer& init,


std::shared_ptr<CarlaPluginBridge> plugin(new CarlaPluginBridge(init.engine, init.id, btype, ptype)); std::shared_ptr<CarlaPluginBridge> plugin(new CarlaPluginBridge(init.engine, init.id, btype, ptype));


if (! plugin->init(plugin, init.filename, init.name, init.label, init.uniqueId, init.options, bridgeBinary))
if (! plugin->init(plugin, init.filename, init.name, init.label, init.uniqueId, init.options, binaryArchName, bridgeBinary))
return nullptr; return nullptr;


return plugin; return plugin;


+ 32
- 2
source/backend/plugin/CarlaPluginJuce.cpp View File

@@ -1378,7 +1378,28 @@ public:
fDesc.name = label; fDesc.name = label;
} }


fFormatManager.addDefaultFormats();
/**/ if (std::strcmp(format, "AU") == 0)
{
#if JUCE_PLUGINHOST_AU
fFormatManager.addFormat(new juce::AudioUnitPluginFormat());
#endif
}
else if (std::strcmp(format, "VST2") == 0)
{
#if JUCE_PLUGINHOST_VST
fFormatManager.addFormat(new juce::VSTPluginFormat());
#endif
}
else if (std::strcmp(format, "VST3") == 0)
{
#if JUCE_PLUGINHOST_VST3
fFormatManager.addFormat(new juce::VST3PluginFormat());
#endif
}
else
{
fFormatManager.addDefaultFormats();
}


{ {
juce::OwnedArray<juce::PluginDescription> pluginDescriptions; juce::OwnedArray<juce::PluginDescription> pluginDescriptions;
@@ -1389,12 +1410,18 @@ public:


for (int i = 0; i < fFormatManager.getNumFormats(); ++i) for (int i = 0; i < fFormatManager.getNumFormats(); ++i)
{ {
juce::AudioPluginFormat* const apformat = fFormatManager.getFormat(i);
CARLA_SAFE_ASSERT_CONTINUE(apformat != nullptr);

carla_debug("Trying to load '%s' plugin with format '%s'", fileOrIdentifier.toRawUTF8(), apformat->getName().toRawUTF8());

try { try {
plist.scanAndAddFile(fileOrIdentifier, true, pluginDescriptions, *fFormatManager.getFormat(i));
plist.scanAndAddFile(fileOrIdentifier, true, pluginDescriptions, *apformat);
} CARLA_SAFE_EXCEPTION_CONTINUE("scanAndAddFile") } CARLA_SAFE_EXCEPTION_CONTINUE("scanAndAddFile")


if (sac.wasTriggered()) if (sac.wasTriggered())
{ {
carla_stderr("WARNING: Caught exception while scanning file, will not load this plugin");
pluginDescriptions.clearQuick(false); pluginDescriptions.clearQuick(false);
break; break;
} }
@@ -1426,7 +1453,10 @@ public:
} CARLA_SAFE_EXCEPTION("createPluginInstance") } CARLA_SAFE_EXCEPTION("createPluginInstance")


if (sac.wasTriggered()) if (sac.wasTriggered())
{
fInstance = nullptr; fInstance = nullptr;
carla_stderr("WARNING: Caught exception while instantiating, will not load this plugin");
}
} }


if (fInstance == nullptr) if (fInstance == nullptr)


+ 57
- 4
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -41,6 +41,14 @@ extern "C" {
#include "water/files/File.h" #include "water/files/File.h"
#include "water/misc/Time.h" #include "water/misc/Time.h"


#ifdef CARLA_OS_MAC
# include "CarlaMacUtils.hpp"
# if defined(CARLA_OS_64BIT) && defined(HAVE_LIBMAGIC) && ! defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
# define ADAPT_FOR_APPLE_SILLICON
# include "CarlaBinaryUtils.hpp"
# endif
#endif

#include <string> #include <string>
#include <vector> #include <vector>


@@ -6249,7 +6257,8 @@ public:


public: public:
bool init(const CarlaPluginPtr plugin, bool init(const CarlaPluginPtr plugin,
const char* const name, const char* const uri, const uint options)
const char* const name, const char* const uri, const uint options,
const char*& needsArchBridge)
{ {
CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false); CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);


@@ -6293,9 +6302,36 @@ public:
return false; return false;
} }


#ifdef ADAPT_FOR_APPLE_SILLICON
// ---------------------------------------------------------------
// check if we can open this binary, might need a bridge

{
const CarlaMagic magic;

if (const char* const output = magic.getFileDescription(fRdfDescriptor->Binary))
{
# ifdef __aarch64__
if (std::strstr(output, "arm64") == nullptr && std::strstr(output, "x86_64") != nullptr)
needsArchBridge = "x86_64";
# else
if (std::strstr(output, "x86_64") == nullptr && std::strstr(output, "arm64") != nullptr)
needsArchBridge = "arm64";
# endif
if (needsArchBridge != nullptr)
return false;
}
}
#endif // ADAPT_FOR_APPLE_SILLICON

// --------------------------------------------------------------- // ---------------------------------------------------------------
// open DLL // open DLL


#ifdef CARLA_OS_MAC
// Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
removeFileFromQuarantine(fRdfDescriptor->Binary);
#endif

if (! pData->libOpen(fRdfDescriptor->Binary)) if (! pData->libOpen(fRdfDescriptor->Binary))
{ {
pData->engine->setLastError(pData->libError(fRdfDescriptor->Binary)); pData->engine->setLastError(pData->libError(fRdfDescriptor->Binary));
@@ -6712,6 +6748,9 @@ public:
initUi(); initUi();


return true; return true;

// might be unused
(void)needsArchBridge;
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -6961,6 +7000,11 @@ public:
// --------------------------------------------------------------- // ---------------------------------------------------------------
// open UI DLL // open UI DLL


#ifdef CARLA_OS_MAC
// Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
removeFileFromQuarantine(fUI.rdfDescriptor->Binary);
#endif

if (! pData->uiLibOpen(fUI.rdfDescriptor->Binary, canDelete)) if (! pData->uiLibOpen(fUI.rdfDescriptor->Binary, canDelete))
{ {
carla_stderr2("Could not load UI library, error was:\n%s", pData->libError(fUI.rdfDescriptor->Binary)); carla_stderr2("Could not load UI library, error was:\n%s", pData->libError(fUI.rdfDescriptor->Binary));
@@ -8103,10 +8147,19 @@ CarlaPluginPtr CarlaPlugin::newLV2(const Initializer& init)


std::shared_ptr<CarlaPluginLV2> plugin(new CarlaPluginLV2(init.engine, init.id)); std::shared_ptr<CarlaPluginLV2> plugin(new CarlaPluginLV2(init.engine, init.id));


if (! plugin->init(plugin, init.name, init.label, init.options))
return nullptr;
const char* needsArchBridge = nullptr;
if (plugin->init(plugin, init.name, init.label, init.options, needsArchBridge))
return plugin;

if (needsArchBridge != nullptr)
{
CarlaString bridgeBinary(init.engine->getOptions().binaryDir);
bridgeBinary += CARLA_OS_SEP_STR "carla-bridge-native";

return CarlaPlugin::newBridge(init, BINARY_NATIVE, PLUGIN_LV2, needsArchBridge, bridgeBinary);
}


return plugin;
return nullptr;
} }


// used in CarlaStandalone.cpp // used in CarlaStandalone.cpp


+ 1
- 0
source/backend/plugin/CarlaPluginVST2.cpp View File

@@ -17,6 +17,7 @@


#include "CarlaPluginInternal.hpp" #include "CarlaPluginInternal.hpp"
#include "CarlaEngine.hpp" #include "CarlaEngine.hpp"
#include "AppConfig.h"


#if defined(USING_JUCE) && JUCE_PLUGINHOST_VST #if defined(USING_JUCE) && JUCE_PLUGINHOST_VST
# define USE_JUCE_FOR_VST2 # define USE_JUCE_FOR_VST2


+ 22
- 3
source/bridges-plugin/CarlaBridgePlugin.cpp View File

@@ -68,6 +68,7 @@
#include "jackbridge/JackBridge.hpp" #include "jackbridge/JackBridge.hpp"


#include "water/files/File.h" #include "water/files/File.h"
#include "water/misc/Time.h"


using CarlaBackend::CarlaEngine; using CarlaBackend::CarlaEngine;
using CarlaBackend::EngineCallbackOpcode; using CarlaBackend::EngineCallbackOpcode;
@@ -238,7 +239,7 @@ public:
{ {
carla_debug("CarlaBridgePlugin::~CarlaBridgePlugin()"); carla_debug("CarlaBridgePlugin::~CarlaBridgePlugin()");


if (! fUsingExec)
if (fEngine != nullptr && ! fUsingExec)
carla_engine_close(gHostHandle); carla_engine_close(gHostHandle);
} }


@@ -281,6 +282,15 @@ public:


gIsInitiated = true; gIsInitiated = true;


const bool testing = std::getenv("CARLA_BRIDGE_TESTING") != nullptr;
int64_t timeToEnd = 0;

if (testing)
{
timeToEnd = water::Time::currentTimeMillis() + 10 * 1000;
fEngine->transportPlay();
}

#if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN)) #if defined(USING_JUCE) && (defined(CARLA_OS_MAC) || defined(CARLA_OS_WIN))
# ifndef CARLA_OS_WIN # ifndef CARLA_OS_WIN
static const int argc = 0; static const int argc = 0;
@@ -298,6 +308,8 @@ public:
# else # else
carla_msleep(5); carla_msleep(5);
# endif # endif
if (testing && timeToEnd - water::Time::currentTimeMillis() < 0)
break;
} }
#endif #endif


@@ -332,7 +344,7 @@ protected:
} }


private: private:
const CarlaEngine* fEngine;
CarlaEngine* fEngine;


#ifdef USING_JUCE #ifdef USING_JUCE
const juce::ScopedJuceInitialiser_GUI fJuceInitialiser; const juce::ScopedJuceInitialiser_GUI fJuceInitialiser;
@@ -649,7 +661,14 @@ int main(int argc, char* argv[])


if (const CarlaPluginInfo* const pluginInfo = carla_get_plugin_info(gHostHandle, 0)) if (const CarlaPluginInfo* const pluginInfo = carla_get_plugin_info(gHostHandle, 0))
{ {
if (pluginInfo->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
if (itype == CarlaBackend::PLUGIN_INTERNAL && (std::strcmp(label, "audiofile") == 0 || std::strcmp(label, "midifile") == 0))
{
if (file.exists())
carla_set_custom_data(gHostHandle, 0,
CarlaBackend::CUSTOM_DATA_TYPE_STRING,
"file", file.getFullPathName().toRawUTF8());
}
else if (pluginInfo->hints & CarlaBackend::PLUGIN_HAS_CUSTOM_UI)
{ {
#ifdef HAVE_X11 #ifdef HAVE_X11
if (std::getenv("DISPLAY") != nullptr) if (std::getenv("DISPLAY") != nullptr)


+ 9
- 0
source/bridges-ui/CarlaBridgeFormatLV2.cpp View File

@@ -25,6 +25,10 @@


#include "water/files/File.h" #include "water/files/File.h"


#ifdef CARLA_OS_MAC
# include "CarlaMacUtils.hpp"
#endif

#include <string> #include <string>
#include <vector> #include <vector>


@@ -512,6 +516,11 @@ public:
// ------------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------------
// open DLL // open DLL


#ifdef CARLA_OS_MAC
// Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
CarlaBackend::removeFileFromQuarantine(fRdfUiDescriptor->Binary);
#endif

if (! libOpen(fRdfUiDescriptor->Binary)) if (! libOpen(fRdfUiDescriptor->Binary))
{ {
carla_stderr("Failed to load UI binary, error was:\n%s", libError()); carla_stderr("Failed to load UI binary, error was:\n%s", libError());


+ 16
- 0
source/discovery/carla-discovery.cpp View File

@@ -63,6 +63,7 @@
# undef Component # undef Component
# undef MemoryBlock # undef MemoryBlock
# undef Point # undef Point
# include "CarlaMacUtils.cpp"
#endif #endif


#ifdef CARLA_OS_WIN #ifdef CARLA_OS_WIN
@@ -1753,6 +1754,21 @@ int main(int argc, char* argv[])
} }
#endif #endif


#ifdef CARLA_OS_MAC
// Plugin might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
switch (type)
{
case PLUGIN_LADSPA:
case PLUGIN_DSSI:
case PLUGIN_VST2:
case PLUGIN_VST3:
removeFileFromQuarantine(filename);
break;
default:
break;
}
#endif

switch (type) switch (type)
{ {
case PLUGIN_LADSPA: case PLUGIN_LADSPA:


+ 12
- 0
source/frontend/widgets/racklistwidget.py View File

@@ -252,6 +252,12 @@ class RackListWidget(QListWidget):
self.clearFocus() self.clearFocus()


def isDragUrlValid(self, filename): def isDragUrlValid(self, filename):
if not filename:
return False

if filename[-1] == '/':
filename = filename[:-1]

lfilename = filename.lower() lfilename = filename.lower()


if os.path.isdir(filename): if os.path.isdir(filename):
@@ -333,6 +339,12 @@ class RackListWidget(QListWidget):


filename = url.toLocalFile() filename = url.toLocalFile()


if not filename:
continue

if filename[-1] == '/':
filename = filename[:-1]

if not self.host.load_file(filename): if not self.host.load_file(filename):
CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"),
self.tr("Failed to load file"), self.tr("Failed to load file"),


+ 108
- 47
source/native-plugins/audio-base.hpp View File

@@ -97,21 +97,14 @@ struct AudioFilePool {
CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool) CARLA_DECLARE_NON_COPY_STRUCT(AudioFilePool)
}; };


class AbstractAudioPlayer
{
public:
virtual ~AbstractAudioPlayer() {}
virtual uint64_t getLastFrame() const = 0;
};

class AudioFileThread : public CarlaThread class AudioFileThread : public CarlaThread
{ {
public: public:
AudioFileThread(AbstractAudioPlayer* const player)
AudioFileThread()
: CarlaThread("AudioFileThread"), : CarlaThread("AudioFileThread"),
kPlayer(player),
fEntireFileLoaded(false), fEntireFileLoaded(false),
fLoopingMode(true), fLoopingMode(true),
fNeedsFrame(0),
fNeedsRead(false), fNeedsRead(false),
fQuitNow(true), fQuitNow(true),
fFilePtr(nullptr), fFilePtr(nullptr),
@@ -120,10 +113,9 @@ public:
fPollTempData(nullptr), fPollTempData(nullptr),
fPollTempSize(0), fPollTempSize(0),
fPool(), fPool(),
fMutex()
fMutex(),
fSignal()
{ {
CARLA_ASSERT(kPlayer != nullptr);

static bool adInitiated = false; static bool adInitiated = false;


if (! adInitiated) if (! adInitiated)
@@ -168,16 +160,19 @@ public:
if (fPollTempData == nullptr) if (fPollTempData == nullptr)
return; return;


fNeedsRead = true;
fNeedsFrame = 0;
fNeedsRead = false;
fQuitNow = false; fQuitNow = false;
startThread(); startThread();
} }


void stopNow() void stopNow()
{ {
fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
fQuitNow = true; fQuitNow = true;


fSignal.signal();
stopThread(1000); stopThread(1000);


const CarlaMutexLocker cml(fMutex); const CarlaMutexLocker cml(fMutex);
@@ -209,9 +204,14 @@ public:
fLoopingMode = on; fLoopingMode = on;
} }


void setNeedsRead() noexcept
void setNeedsRead(const uint64_t frame) noexcept
{ {
if (fEntireFileLoaded)
return;

fNeedsFrame = frame;
fNeedsRead = true; fNeedsRead = true;
fSignal.signal();
} }


bool loadFilename(const char* const filename, const uint32_t sampleRate) bool loadFilename(const char* const filename, const uint32_t sampleRate)
@@ -295,24 +295,73 @@ public:
carla_copyFloats(pool.buffer[1], fPool.buffer[1], fPool.numFrames); carla_copyFloats(pool.buffer[1], fPool.buffer[1], fPool.numFrames);
} }


bool tryPutData(AudioFilePool& pool, const uint64_t framePos, const uint32_t frames)
bool tryPutData(float* const out1, float* const out2, uint64_t framePos, const uint32_t frames)
{ {
CARLA_SAFE_ASSERT_RETURN(pool.numFrames == fPool.numFrames, false);
CARLA_SAFE_ASSERT_RETURN(fPool.numFrames != 0, false);


if (framePos >= fPool.numFrames)
return false;
if (framePos >= fNumFileFrames)
{
if (fLoopingMode)
framePos %= fNumFileFrames;
else
return false;
}

uint64_t frameDiff;
const uint64_t numFramesNearEnd = fPool.numFrames*3/4;


#if 1
const CarlaMutexLocker cml(fMutex); const CarlaMutexLocker cml(fMutex);
/*
#else
const CarlaMutexTryLocker cmtl(fMutex); const CarlaMutexTryLocker cmtl(fMutex);
if (! cmtl.wasLocked()) if (! cmtl.wasLocked())
return false;
*/
{
for (int i=0; i<5; ++i)
{
pthread_yield();
if (cmtl.tryAgain())
break;
if (i == 4)
return false;
}
}
#endif


pool.startFrame = fPool.startFrame;
if (framePos < fPool.startFrame)
{
if (fPool.startFrame + fPool.numFrames <= fNumFileFrames)
{
setNeedsRead(framePos);
return false;
}


carla_copyFloats(pool.buffer[0] + framePos, fPool.buffer[0] + framePos, frames);
carla_copyFloats(pool.buffer[1] + framePos, fPool.buffer[1] + framePos, frames);
frameDiff = framePos + (fNumFileFrames - fPool.startFrame);

if (frameDiff + frames >= fPool.numFrames)
{
setNeedsRead(framePos);
return false;
}

carla_copyFloats(out1, fPool.buffer[0] + frameDiff, frames);
carla_copyFloats(out2, fPool.buffer[1] + frameDiff, frames);
}
else
{
frameDiff = framePos - fPool.startFrame;

if (frameDiff + frames >= fPool.numFrames)
{
setNeedsRead(framePos);
return false;
}

carla_copyFloats(out1, fPool.buffer[0] + frameDiff, frames);
carla_copyFloats(out2, fPool.buffer[1] + frameDiff, frames);
}

if (frameDiff > numFramesNearEnd)
setNeedsRead(framePos + frames);


return true; return true;
} }
@@ -372,17 +421,19 @@ public:
if (fNumFileFrames == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr) if (fNumFileFrames == 0 || fFileNfo.channels == 0 || fFilePtr == nullptr)
{ {
carla_debug("R: no song loaded"); carla_debug("R: no song loaded");
fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
return; return;
} }
if (fPollTempData == nullptr) if (fPollTempData == nullptr)
{ {
carla_debug("R: nothing to poll"); carla_debug("R: nothing to poll");
fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
return; return;
} }


uint64_t lastFrame = kPlayer->getLastFrame();
uint64_t lastFrame = fNeedsFrame;
int64_t readFrameCheck; int64_t readFrameCheck;


if (lastFrame >= fNumFileFrames) if (lastFrame >= fNumFileFrames)
@@ -398,6 +449,7 @@ public:
else else
{ {
carla_debug("R: transport out of bounds"); carla_debug("R: transport out of bounds");
fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
return; return;
} }
@@ -428,6 +480,7 @@ public:
if (rv < 0) if (rv < 0)
{ {
carla_stderr("R: ad_read failed"); carla_stderr("R: ad_read failed");
fNeedsFrame = 0;
fNeedsRead = false; fNeedsRead = false;
return; return;
} }
@@ -442,36 +495,46 @@ public:
rv += ad_read(fFilePtr, fPollTempData+urv, fPollTempSize-urv); rv += ad_read(fFilePtr, fPollTempData+urv, fPollTempSize-urv);
} }


carla_debug("R: reading %li frames at frame %lu", rv, readFrameCheck);

// local copy
const uint32_t poolNumFrame = fPool.numFrames;
const int64_t fileFrames = fFileNfo.frames;
const bool isMonoFile = fFileNfo.channels == 1;
float* const pbuffer0 = fPool.buffer[0];
float* const pbuffer1 = fPool.buffer[1];
const float* const tmpbuf = fPollTempData;

// lock, and put data asap // lock, and put data asap
const CarlaMutexLocker cml(fMutex); const CarlaMutexLocker cml(fMutex);


do { do {
for (; i < fPool.numFrames && j < rv; ++j)
for (; i < poolNumFrame && j < rv; ++j)
{ {
if (fFileNfo.channels == 1)
if (isMonoFile)
{ {
fPool.buffer[0][i] = fPollTempData[j];
fPool.buffer[1][i] = fPollTempData[j];
pbuffer0[i] = pbuffer1[i] = tmpbuf[j];
i++; i++;
} }
else else
{ {
if (j % 2 == 0) if (j % 2 == 0)
{ {
fPool.buffer[0][i] = fPollTempData[j];
pbuffer0[i] = tmpbuf[j];
} }
else else
{ {
fPool.buffer[1][i] = fPollTempData[j];
i++;
pbuffer1[i] = tmpbuf[j];
++i;
} }
} }
} }


if (i >= fPool.numFrames)
if (i >= poolNumFrame) {
break; break;
}


if (rv == fFileNfo.frames)
if (rv == fileFrames)
{ {
// full file read // full file read
j = 0; j = 0;
@@ -481,14 +544,14 @@ public:
{ {
carla_debug("read break, not enough space"); carla_debug("read break, not enough space");


carla_zeroFloats(fPool.buffer[0] + i, fPool.numFrames - i);
carla_zeroFloats(fPool.buffer[1] + i, fPool.numFrames - i);
carla_zeroFloats(pbuffer0, poolNumFrame - i);
carla_zeroFloats(pbuffer1, poolNumFrame - i);
break; break;
} }


} while (i < fPool.numFrames);
} while (i < poolNumFrame);


fPool.startFrame = lastFrame;
fPool.startFrame = readFrame;
} }


fNeedsRead = false; fNeedsRead = false;
@@ -497,25 +560,22 @@ public:
protected: protected:
void run() override void run() override
{ {
const uint64_t numFramesNearEnd = fPool.numFrames*3/4;
uint64_t lastFrame;

while (! fQuitNow) while (! fQuitNow)
{ {
lastFrame = kPlayer->getLastFrame();

if (fNeedsRead || lastFrame < fPool.startFrame || lastFrame - fPool.startFrame >= numFramesNearEnd)
if (fNeedsRead)
readPoll(); readPoll();


carla_msleep(50);
if (fQuitNow)
break;

fSignal.wait();
} }
} }


private: private:
AbstractAudioPlayer* const kPlayer;

bool fEntireFileLoaded; bool fEntireFileLoaded;
bool fLoopingMode; bool fLoopingMode;
volatile uint64_t fNeedsFrame;
volatile bool fNeedsRead; volatile bool fNeedsRead;
volatile bool fQuitNow; volatile bool fQuitNow;


@@ -529,6 +589,7 @@ private:


AudioFilePool fPool; AudioFilePool fPool;
CarlaMutex fMutex; CarlaMutex fMutex;
CarlaSignal fSignal;


CARLA_DECLARE_NON_COPY_STRUCT(AudioFileThread) CARLA_DECLARE_NON_COPY_STRUCT(AudioFileThread)
}; };


+ 16
- 31
source/native-plugins/audio-file.cpp View File

@@ -41,19 +41,17 @@ static const char* const audiofilesWildcard =


// ----------------------------------------------------------------------- // -----------------------------------------------------------------------


class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>,
public AbstractAudioPlayer
class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>
{ {
public: public:
AudioFilePlugin(const NativeHostDescriptor* const host) AudioFilePlugin(const NativeHostDescriptor* const host)
: NativePluginWithMidiPrograms<FileAudio>(host, fPrograms, 2), : NativePluginWithMidiPrograms<FileAudio>(host, fPrograms, 2),
AbstractAudioPlayer(),
fLoopMode(true), fLoopMode(true),
fDoProcess(false), fDoProcess(false),
fLastFrame(0),
fWasPlayingBefore(false),
fMaxFrame(0), fMaxFrame(0),
fPool(), fPool(),
fThread(this),
fThread(),
fPrograms(hostGetFilePath("audio"), audiofilesWildcard) fPrograms(hostGetFilePath("audio"), audiofilesWildcard)
#ifndef __MOD_DEVICES__ #ifndef __MOD_DEVICES__
, fInlineDisplay() , fInlineDisplay()
@@ -67,11 +65,6 @@ public:
fPool.destroy(); fPool.destroy();
} }


uint64_t getLastFrame() const override
{
return fLastFrame;
}

protected: protected:
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Plugin parameter calls // Plugin parameter calls
@@ -126,7 +119,6 @@ protected:


fLoopMode = b; fLoopMode = b;
fThread.setLoopingMode(b); fThread.setLoopingMode(b);
fThread.setNeedsRead();
} }


void setCustomData(const char* const key, const char* const value) override void setCustomData(const char* const key, const char* const value) override
@@ -151,8 +143,7 @@ protected:


if (! fDoProcess) if (! fDoProcess)
{ {
//carla_stderr("P: no process");
fLastFrame = timePos->frame;
// carla_stderr("P: no process");
carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);
return; return;
@@ -161,23 +152,26 @@ protected:
// not playing // not playing
if (! timePos->playing) if (! timePos->playing)
{ {
//carla_stderr("P: not playing");
if (timePos->frame == 0 && fLastFrame > 0)
fThread.setNeedsRead();
// carla_stderr("P: not playing");
if (timePos->frame == 0 && fWasPlayingBefore)
fThread.setNeedsRead(timePos->frame);


fLastFrame = timePos->frame;
carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);
fWasPlayingBefore = false;
return; return;
} }
else
{
fWasPlayingBefore = true;
}


// out of reach // out of reach
if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !fLoopMode) if ((timePos->frame < fPool.startFrame || timePos->frame >= fMaxFrame) && !fLoopMode)
{ {
if (timePos->frame < fPool.startFrame) if (timePos->frame < fPool.startFrame)
fThread.setNeedsRead();
fThread.setNeedsRead(timePos->frame);


fLastFrame = timePos->frame;
carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);


@@ -236,15 +230,7 @@ protected:
} }
else else
{ {
// NOTE: timePos->frame is always >= fPool.startFrame
const uint64_t poolStartFrame = timePos->frame - fThread.getPoolStartFrame();

if (fThread.tryPutData(fPool, poolStartFrame, frames))
{
carla_copyFloats(out1, fPool.buffer[0]+poolStartFrame, frames);
carla_copyFloats(out2, fPool.buffer[1]+poolStartFrame, frames);
}
else
if (! fThread.tryPutData(out1, out2, timePos->frame, frames))
{ {
carla_zeroFloats(out1, frames); carla_zeroFloats(out1, frames);
carla_zeroFloats(out2, frames); carla_zeroFloats(out2, frames);
@@ -262,11 +248,10 @@ protected:
if (! fInlineDisplay.pending) if (! fInlineDisplay.pending)
{ {
fInlineDisplay.pending = true; fInlineDisplay.pending = true;
// FIXME this is not supposed to be here, but in some idle callback
hostQueueDrawInlineDisplay(); hostQueueDrawInlineDisplay();
} }
#endif #endif

fLastFrame = timePos->frame;
} }


// ------------------------------------------------------------------- // -------------------------------------------------------------------
@@ -411,8 +396,8 @@ protected:
private: private:
bool fLoopMode; bool fLoopMode;
bool fDoProcess; bool fDoProcess;
bool fWasPlayingBefore;


volatile uint64_t fLastFrame;
uint32_t fMaxFrame; uint32_t fMaxFrame;


AudioFilePool fPool; AudioFilePool fPool;


+ 6
- 24
source/native-plugins/midi-file.cpp View File

@@ -185,35 +185,17 @@ private:
CARLA_SAFE_ASSERT_CONTINUE(midiEventHolder != nullptr); CARLA_SAFE_ASSERT_CONTINUE(midiEventHolder != nullptr);


const MidiMessage& midiMessage(midiEventHolder->message); const MidiMessage& midiMessage(midiEventHolder->message);
//const double time(track->getEventTime(i)*sampleRate);
const int dataSize(midiMessage.getRawDataSize());


const int dataSize = midiMessage.getRawDataSize();
if (dataSize <= 0 || dataSize > MAX_EVENT_DATA_SIZE) if (dataSize <= 0 || dataSize > MAX_EVENT_DATA_SIZE)
continue; continue;
if (midiMessage.isActiveSense())
continue;
if (midiMessage.isMetaEvent())
continue;
if (midiMessage.isMidiStart())
continue;
if (midiMessage.isMidiContinue())
continue;
if (midiMessage.isMidiStop())
continue;
if (midiMessage.isMidiClock())
continue;
if (midiMessage.isSongPositionPointer())
continue;
if (midiMessage.isQuarterFrame())
continue;
if (midiMessage.isFullFrame())
continue;
if (midiMessage.isMidiMachineControlMessage())
continue;
if (midiMessage.isSysEx())

const uint8_t* const data = midiMessage.getRawData();
if (! MIDI_IS_CHANNEL_MESSAGE(data[0]))
continue; continue;


const double time(midiMessage.getTimeStamp()*sampleRate);
const double time = midiMessage.getTimeStamp() * sampleRate;
// const double time = track->getEventTime(i) * sampleRate;
CARLA_SAFE_ASSERT_CONTINUE(time >= 0.0); CARLA_SAFE_ASSERT_CONTINUE(time >= 0.0);


fMidiOut.addRaw(static_cast<uint64_t>(time), midiMessage.getRawData(), static_cast<uint8_t>(dataSize)); fMidiOut.addRaw(static_cast<uint64_t>(time), midiMessage.getRawData(), static_cast<uint8_t>(dataSize));


+ 4
- 2
source/utils/CarlaBinaryUtils.hpp View File

@@ -112,9 +112,11 @@ BinaryType getBinaryTypeFromFile(const char* const filename)
// We just assume what architectures are more important, and check for them first // We just assume what architectures are more important, and check for them first
if (std::strstr(output, "x86_64") != nullptr) if (std::strstr(output, "x86_64") != nullptr)
return BINARY_POSIX64; return BINARY_POSIX64;
if (std::strstr(output, "i386"))
if (std::strstr(output, "arm64") != nullptr)
return BINARY_POSIX64;
if (std::strstr(output, "i386") != nullptr)
return BINARY_POSIX32; return BINARY_POSIX32;
if (std::strstr(output, "ppc"))
if (std::strstr(output, "ppc") != nullptr)
return BINARY_OTHER; return BINARY_OTHER;
} }




+ 7
- 0
source/utils/CarlaMacUtils.cpp View File

@@ -20,6 +20,8 @@
#include "CarlaMacUtils.hpp" #include "CarlaMacUtils.hpp"
#include "CarlaString.hpp" #include "CarlaString.hpp"


#include <sys/xattr.h>

#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>


CARLA_BACKEND_START_NAMESPACE CARLA_BACKEND_START_NAMESPACE
@@ -54,6 +56,11 @@ const char* findBinaryInBundle(const char* const bundleDir)
return ret.buffer(); return ret.buffer();
} }


bool removeFileFromQuarantine(const char* const filename)
{
return removexattr(filename, "com.apple.quarantine", 0) == 0;
}

// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------


AutoNSAutoreleasePool::AutoNSAutoreleasePool() AutoNSAutoreleasePool::AutoNSAutoreleasePool()


+ 5
- 0
source/utils/CarlaMacUtils.hpp View File

@@ -33,6 +33,11 @@ CARLA_BACKEND_START_NAMESPACE
*/ */
const char* findBinaryInBundle(const char* const bundleDir); const char* findBinaryInBundle(const char* const bundleDir);


/*
* ...
*/
bool removeFileFromQuarantine(const char* const filename);

/* /*
* ... * ...
*/ */


+ 5
- 0
source/utils/CarlaMutex.hpp View File

@@ -325,6 +325,11 @@ public:
return !fLocked; return !fLocked;
} }


bool tryAgain() const noexcept
{
return fMutex.tryLock();
}

private: private:
const Mutex& fMutex; const Mutex& fMutex;
const bool fLocked; const bool fLocked;


Loading…
Cancel
Save