Browse Source

Merge branch 'master' of falktxgh:falkTX/Carla

tags/v1.9.11
FilipeCSnuk 6 years ago
parent
commit
baa3758159
62 changed files with 843 additions and 1131 deletions
  1. +1
    -1
      .travis/linux..install.sh
  2. +1
    -1
      .travis/linux.win32.install.sh
  3. +1
    -1
      .travis/linux.win64.install.sh
  4. +46
    -18
      INSTALL.md
  5. +1
    -3
      data/carla-single
  6. +1
    -1
      data/linux/README
  7. +0
    -54
      data/linux/build-deps.sh
  8. +0
    -2
      data/linux/common.env
  9. +0
    -29
      data/linux/patches/libgig_fix-build.patch
  10. +0
    -24
      data/linux/patches/linuxsampler_allow-no-drivers-build.patch
  11. +0
    -10
      data/linux/patches/linuxsampler_disable-ladspa-fx.patch
  12. +1
    -1
      data/macos/README
  13. +0
    -60
      data/macos/build-deps.sh
  14. +0
    -2
      data/macos/common.env
  15. +0
    -29
      data/macos/patches/libgig_fix-build.patch
  16. +0
    -24
      data/macos/patches/linuxsampler_allow-no-drivers-build.patch
  17. +0
    -10
      data/macos/patches/linuxsampler_disable-ladspa-fx.patch
  18. +1
    -1
      data/windows/README.txt
  19. +0
    -57
      data/windows/build-deps.sh
  20. +0
    -2
      data/windows/common.env
  21. +0
    -29
      data/windows/patches/libgig_fix-build.patch
  22. +0
    -24
      data/windows/patches/linuxsampler_allow-no-drivers-build.patch
  23. +0
    -10
      data/windows/patches/linuxsampler_disable-ladspa-fx.patch
  24. +0
    -13
      resources/ui/carla_settings.ui
  25. +5
    -0
      source/Makefile.mk
  26. +2
    -2
      source/backend/CarlaEngine.hpp
  27. +3
    -5
      source/backend/CarlaPlugin.hpp
  28. +2
    -2
      source/backend/CarlaStandalone.cpp
  29. +84
    -84
      source/backend/engine/CarlaEngine.cpp
  30. +0
    -6
      source/backend/engine/CarlaEngineBridge.cpp
  31. +1
    -1
      source/backend/engine/CarlaEngineData.cpp
  32. +48
    -20
      source/backend/engine/CarlaEngineGraph.cpp
  33. +3
    -2
      source/backend/engine/CarlaEngineGraph.hpp
  34. +6
    -6
      source/backend/engine/CarlaEngineInternal.cpp
  35. +5
    -3
      source/backend/engine/CarlaEngineInternal.hpp
  36. +2
    -1
      source/backend/engine/CarlaEngineNative.cpp
  37. +34
    -5
      source/backend/engine/CarlaEngineRtAudio.cpp
  38. +3
    -3
      source/backend/engine/CarlaEngineThread.cpp
  39. +0
    -5
      source/backend/plugin/CarlaPlugin.cpp
  40. +169
    -79
      source/backend/plugin/CarlaPluginBridge.cpp
  41. +15
    -16
      source/backend/plugin/CarlaPluginDSSI.cpp
  42. +0
    -3
      source/backend/plugin/CarlaPluginFluidSynth.cpp
  43. +2
    -3
      source/backend/plugin/CarlaPluginInternal.hpp
  44. +0
    -3
      source/backend/plugin/CarlaPluginJack.cpp
  45. +1
    -2
      source/backend/plugin/CarlaPluginLADSPA.cpp
  46. +14
    -32
      source/backend/plugin/CarlaPluginLV2.cpp
  47. +80
    -75
      source/backend/plugin/CarlaPluginNative.cpp
  48. +0
    -1
      source/backend/plugin/CarlaPluginSFZero.cpp
  49. +63
    -75
      source/backend/plugin/CarlaPluginVST2.cpp
  50. +2
    -7
      source/bridges-plugin/Makefile
  51. +0
    -1
      source/carla_backend.pro
  52. +6
    -9
      source/carla_database.py
  53. +2
    -2
      source/includes/CarlaNative.h
  54. +6
    -6
      source/jackbridge/Makefile
  55. +1
    -1
      source/libjack/libjack.cpp
  56. +61
    -168
      source/modules/rtaudio/RtAudio.cpp
  57. +12
    -2
      source/modules/rtaudio/RtAudio.h
  58. +23
    -0
      source/native-plugins/_data.base.cpp
  59. +120
    -84
      source/native-plugins/audio-base.hpp
  60. +11
    -7
      source/native-plugins/audio-file.cpp
  61. +1
    -1
      source/tests/Makefile
  62. +3
    -3
      source/utils/CarlaBridgeDefines.hpp

+ 1
- 1
.travis/linux..install.sh View File

@@ -3,4 +3,4 @@ sudo apt-get install -y pkg-config \
libasound2-dev libpulse-dev libmagic-dev libx11-dev libxft-dev \
libgl1-mesa-dev libglu1-mesa-dev \
liblo-static fftw3-static mxml-static zlib-static ntk-static \
fluidsynth-static linuxsampler-static
fluidsynth-static

+ 1
- 1
.travis/linux.win32.install.sh View File

@@ -3,4 +3,4 @@ sudo apt-get install -y pkg-config \

# mingw32-x-gcc mingw32-x-pkgconfig
# mingw32-x-liblo mingw32-x-fftw3 mingw32-x-mxml mingw32-x-zlib
# mingw32-x-fluidsynth mingw32-x-linuxsampler
# mingw32-x-fluidsynth

+ 1
- 1
.travis/linux.win64.install.sh View File

@@ -3,4 +3,4 @@ sudo apt-get install -y pkg-config \

# mingw64-x-gcc mingw64-x-pkgconfig
# mingw64-x-liblo mingw64-x-fftw3 mingw64-x-mxml mingw64-x-zlib
# mingw64-x-fluidsynth mingw64-x-linuxsampler
# mingw64-x-fluidsynth

+ 46
- 18
INSTALL.md View File

@@ -9,7 +9,7 @@ $ [sudo] make install
You can run it without installing, by using instead:
```
$ make
$ ./source/carla`
$ ./source/carla
```

Packagers can make use of the `PREFIX` and `DESTDIR` variable during install, like this:
@@ -19,11 +19,9 @@ $ make install PREFIX=/usr DESTDIR=./test-dir

## BUILD DEPENDENCIES

The required build dependencies are: *(devel packages of these)*
There are no required build dependencies.

- PyQt4/5 (python3 version)

Optional for extra engine features:
But if you want the frontend (which is likely), you will need PyQt4/5 (python3 version)

- libmagic (for auto-detection of binary types, needed for plugin-bridges)
- liblo (for OSC support)
@@ -32,7 +30,7 @@ Optional for extra Linux-only engine features:

- ALSA
- PulseAudio
- X11 (internal/LV2/VST2 X11 UI support)
- X11 (internal/LV2/VST X11 UI support)

Optional for extended LV2 UIs support: (Linux only)

@@ -43,20 +41,11 @@ Optional for extended LV2 UIs support: (Linux only)

Optional for extra samplers support:

- FluidSynth (SF2)
- LinuxSampler (GIG and SFZ)

Optional for extra native plugins:
- fftw3
- mxml
- zlib
- NTK
- OpenGL
- ProjectM
- FluidSynth (SF2/3)

Optional but recommended:
Optional for extra LADSPA plugin information:

- python3-rdflib (for LADSPA-RDF support)
- python3-rdflib


You can use:
@@ -64,3 +53,42 @@ You can use:
$ make features
```
To find out which dependencies are missing.


Under debian based systems, you can use this command to install all dependencies:
```
sudo apt install python3-pyqt5.qtsvg python3-rdflib pyqt5-dev-tools \
libmagic-dev liblo-dev libasound2-dev libpulse-dev libx11-dev \
libgtk2.0-dev libgtk-3-dev libqt4-dev qtbase5-dev libfluidsynth-dev
```

## BUILD BRIDGES

Carla can make use of plugin bridges to load additional plugin types.

### 32bit plugins on 64bit systems

Simply run `make posix32` after a regular Carla build, and install or run Carla locally.<br/>
This feature requires a compiler capable of building 32bit binaries.

### JACK Applications inside Carla

This is built by default on Linux systems.<br/>
Requires LD_PRELOAD support by the OS and the GCC compiler.<br/>
Does not work with clang. (if you discover why, please let me know!)

### Windows plugins (via Wine)

Requires a mingw compiler, and winegcc.

First, we build the Windows bridges using mingw, like this: (adjust as needed)
```
make win32 CC=i686-w64-mingw32-gcc CXX=i686-w64-mingw32-g++
make win64 CC=x86_64-w64-mingw32-gcc CXX=x86_64-w64-mingw32-g++
```

To finalize, we build the wine<->native bridges using winegcc:
```
make wine32
make wine64
```

+ 1
- 3
data/carla-single View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*-

# Script to start carla plugin bridges
# Copyright (C) 2015 Filipe Coelho <falktx@falktx.com>
# Copyright (C) 2015-2018 Filipe Coelho <falktx@falktx.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
@@ -210,7 +210,6 @@ LADSPA_PATH = os.getenv("LADSPA_PATH")
DSSI_PATH = os.getenv("DSSI_PATH")
LV2_PATH = os.getenv("LV2_PATH")
VST2_PATH = os.getenv("VST_PATH")
GIG_PATH = os.getenv("GIG_PATH")
SF2_PATH = os.getenv("SF2_PATH")
SFZ_PATH = os.getenv("SFZ_PATH")

@@ -218,7 +217,6 @@ if LADSPA_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_LADSPA"] = LAD
if DSSI_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_DSSI"] = DSSI_PATH
if LV2_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_LV2"] = LV2_PATH
if VST2_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_VST2"] = VST2_PATH
if GIG_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_GIG"] = GIG_PATH
if SF2_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_SF2"] = SF2_PATH
if SFZ_PATH is not None: os.environ["ENGINE_OPTION_PLUGIN_PATH_SFZ"] = SFZ_PATH



+ 1
- 1
data/linux/README View File

@@ -10,7 +10,7 @@ Features
---------

* LADSPA, DSSI, LV2 and VST plugin formats
* GIG, SF2 and SFZ sound banks
* SF2/3 and SFZ sound banks
* Internal audio and midi file player
* Automation of plugin parameters via MIDI CC
* Remote control over OSC


+ 0
- 54
data/linux/build-deps.sh View File

@@ -28,12 +28,10 @@ rm -rf file-*
rm -rf flac-*
rm -rf fltk-*
rm -rf fluidsynth-*
rm -rf libgig-*
rm -rf liblo-*
rm -rf libogg-*
rm -rf libsndfile-*
rm -rf libvorbis-*
rm -rf linuxsampler-*
rm -rf pkg-config-*
rm -rf zlib-*

@@ -208,58 +206,6 @@ if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# libgig

if [ ! -d libgig-${LIBGIG_VERSION} ]; then
wget http://download.linuxsampler.org/packages/libgig-${LIBGIG_VERSION}.tar.bz2
tar -xf libgig-${LIBGIG_VERSION}.tar.bz2
fi

if [ ! -f libgig-${LIBGIG_VERSION}/build-done ]; then
cd libgig-${LIBGIG_VERSION}
if [ ! -f patched ]; then
patch -p1 -i ../patches/libgig_fix-build.patch
touch patched
fi
./configure --enable-static --disable-shared --prefix=${PREFIX}
make ${MAKE_ARGS}
make install
touch build-done
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# linuxsampler

if [ ! -d linuxsampler-${LINUXSAMPLER_VERSION} ]; then
wget http://download.linuxsampler.org/packages/linuxsampler-${LINUXSAMPLER_VERSION}.tar.bz2
tar -xf linuxsampler-${LINUXSAMPLER_VERSION}.tar.bz2
fi

if [ ! -f linuxsampler-${LINUXSAMPLER_VERSION}/build-done ]; then
cd linuxsampler-${LINUXSAMPLER_VERSION}
if [ ! -f patched ]; then
patch -p1 -i ../patches/linuxsampler_allow-no-drivers-build.patch
patch -p1 -i ../patches/linuxsampler_disable-ladspa-fx.patch
touch patched
fi
rm -f configure
make -f Makefile.svn configure
./configure \
--enable-static --disable-shared --prefix=${PREFIX} \
--enable-signed-triang-algo=diharmonic --enable-unsigned-triang-algo=diharmonic --enable-subfragment-size=8 \
--disable-alsa-driver --disable-arts-driver --disable-jack-driver \
--disable-asio-driver --disable-midishare-driver --disable-mmemidi-driver \
--disable-coreaudio-driver --disable-coremidi-driver \
--disable-instruments-db --disable-sf2-engine
make ${MAKE_ARGS}
make install
sed -i -e "s|-llinuxsampler|-llinuxsampler -L${PREFIX}/lib/libgig -lgig -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lpthread -lm|" ${PREFIX}/lib/pkgconfig/linuxsampler.pc
touch build-done
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# glib



+ 0
- 2
data/linux/common.env View File

@@ -8,8 +8,6 @@ LIBOGG_VERSION=1.3.3
LIBVORBIS_VERSION=1.3.5
FLAC_VERSION=1.3.2
LIBSNDFILE_VERSION=1.0.28
LIBGIG_VERSION=4.0.0
LINUXSAMPLER_VERSION=2.0.0
FLUIDSYNTH_VERSION=1.1.6
MXML_VERSION=2.11
FFTW3_VERSION=3.3.7


+ 0
- 29
data/linux/patches/libgig_fix-build.patch View File

@@ -1,29 +0,0 @@
diff --git a/src/DLS.h b/src/DLS.h
index 065bfe6..6c9d76c 100644
--- a/src/DLS.h
+++ b/src/DLS.h
@@ -515,10 +515,10 @@ namespace DLS {
virtual void Save(const String& Path, progress_t* pProgress = NULL);
virtual void Save(progress_t* pProgress = NULL);
virtual ~File();
- protected:
typedef std::list<Sample*> SampleList;
typedef std::list<Instrument*> InstrumentList;
+ protected:
RIFF::File* pRIFF;
std::list<RIFF::File*> ExtensionFiles;
SampleList* pSamples;
diff --git a/src/gig.cpp b/src/gig.cpp
index 6a24f16..902e1ae 100644
--- a/src/gig.cpp
+++ b/src/gig.cpp
@@ -4181,7 +4181,7 @@ namespace {
* @param pGroup - script's new group
*/
void Script::SetGroup(ScriptGroup* pGroup) {
- if (this->pGroup = pGroup) return;
+ if (this->pGroup == pGroup) return;
if (pChunk)
pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
this->pGroup = pGroup;

+ 0
- 24
data/linux/patches/linuxsampler_allow-no-drivers-build.patch View File

@@ -1,24 +0,0 @@
--- linuxsampler-static-1.0.0+svn2356.orig/configure.ac
+++ linuxsampler-static-1.0.0+svn2356/configure.ac
@@ -556,21 +556,6 @@ if test "x$MAC_PLUGIN_INSTALL_DIR" = "x"
fi
AC_SUBST(MAC_PLUGIN_INSTALL_DIR)
-# have we found at least one MIDI input and one audio output driver ?
-if test "$have_midi_input_driver" = "false"; then
- echo "No supported MIDI input system found!"
- echo "Sorry, LinuxSampler only supports the following MIDI drivers at the moment:"
- echo "ALSA, JACK, MIDIShare, CoreMIDI, MME."
- echo "If you think you have one of those available on your system, make sure you"
- echo "also have the respective development (header) files installed."
- exit -1;
-fi
-if test "$have_audio_output_driver" = "false"; then
- echo "No supported audio output system found!"
- echo "Sorry, LinuxSampler only supports ALSA, JACK, ARTS and ASIO as audio output"
- echo "driver at the moment!"
- exit -1;
-fi

+ 0
- 10
data/linux/patches/linuxsampler_disable-ladspa-fx.patch View File

@@ -1,10 +0,0 @@
--- linuxsampler-static-1.0.0+svn2497.orig/src/effects/LadspaEffect.cpp
+++ linuxsampler-static-1.0.0+svn2497/src/effects/LadspaEffect.cpp
@@ -374,6 +374,7 @@ static String defaultLadspaDir() {
std::vector<EffectInfo*> LadspaEffect::AvailableEffects() {
std::vector<EffectInfo*> v; // will be filled in callback function _foundLadspaDll()
+ return v;
char* pcLadspaPath = getenv("LADSPA_PATH");
String ladspaDir = pcLadspaPath ? pcLadspaPath : defaultLadspaDir();

+ 1
- 1
data/macos/README View File

@@ -10,7 +10,7 @@ Features
---------

* LADSPA, DSSI, LV2 and VST plugin formats
* GIG, SF2 and SFZ sound banks
* SF2/3 and SFZ sound banks
* Internal audio and midi file player
* Automation of plugin parameters via MIDI CC
* Remote control over OSC


+ 0
- 60
data/macos/build-deps.sh View File

@@ -40,12 +40,10 @@ rm -rf fftw-*
rm -rf gettext-*
rm -rf glib-*
rm -rf libffi-*
rm -rf libgig-*
rm -rf liblo-*
rm -rf libogg-*
rm -rf libsndfile-*
rm -rf libvorbis-*
rm -rf linuxsampler-*
rm -rf mxml-*
rm -rf pkg-config-*
rm -rf pyliblo-*
@@ -229,64 +227,6 @@ if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# libgig

if [ ! -d libgig-${LIBGIG_VERSION} ]; then
curl -O http://download.linuxsampler.org/packages/libgig-${LIBGIG_VERSION}.tar.bz2
tar -xf libgig-${LIBGIG_VERSION}.tar.bz2
fi

if [ ! -f libgig-${LIBGIG_VERSION}/build-done ]; then
cd libgig-${LIBGIG_VERSION}
if [ ! -f patched ]; then
patch -p1 -i ../patches/libgig_fix-build.patch
touch patched
fi
./configure --enable-static --disable-shared --prefix=${PREFIX}
make ${MAKE_ARGS}
make install
touch build-done
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# linuxsampler

if [ ! -d linuxsampler-${LINUXSAMPLER_VERSION} ]; then
curl -O http://download.linuxsampler.org/packages/linuxsampler-${LINUXSAMPLER_VERSION}.tar.bz2
tar -xf linuxsampler-${LINUXSAMPLER_VERSION}.tar.bz2
fi

if [ ! -f linuxsampler-${LINUXSAMPLER_VERSION}/build-done ]; then
cd linuxsampler-${LINUXSAMPLER_VERSION}
if [ ! -f patched ]; then
patch -p1 -i ../patches/linuxsampler_allow-no-drivers-build.patch
patch -p1 -i ../patches/linuxsampler_disable-ladspa-fx.patch
sed -i -e "s|HAVE_AU|HAVE_VST|" src/hostplugins/Makefile.am
touch patched
fi
env PATH=/opt/local/bin:$PATH /opt/local/bin/aclocal -I /opt/local/share/aclocal
env PATH=/opt/local/bin:$PATH /opt/local/bin/glibtoolize --force --copy
env PATH=/opt/local/bin:$PATH /opt/local/bin/autoheader
env PATH=/opt/local/bin:$PATH /opt/local/bin/automake --add-missing --copy
env PATH=/opt/local/bin:$PATH /opt/local/bin/autoconf
env PATH=/opt/local/bin:$PATH ./configure \
--enable-static --disable-shared --prefix=${PREFIX} \
--enable-signed-triang-algo=diharmonic --enable-unsigned-triang-algo=diharmonic --enable-subfragment-size=8 \
--disable-alsa-driver --disable-arts-driver --disable-jack-driver \
--disable-asio-driver --disable-midishare-driver --disable-mmemidi-driver \
--disable-coreaudio-driver --disable-coremidi-driver \
--disable-instruments-db --disable-sf2-engine
env PATH=/opt/local/bin:$PATH ./scripts/generate_instrument_script_parser.sh
sed -i -e "s/bison (GNU Bison) //" config.h
env PATH=/opt/local/bin:$PATH make ${MAKE_ARGS}
make install
sed -i -e "s|-llinuxsampler|-llinuxsampler -L${PREFIX}/lib/libgig -lgig -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lpthread -lm|" ${PREFIX}/lib/pkgconfig/linuxsampler.pc
touch build-done
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# libffi



+ 0
- 2
data/macos/common.env View File

@@ -8,8 +8,6 @@ LIBOGG_VERSION=1.3.3
LIBVORBIS_VERSION=1.3.5
FLAC_VERSION=1.3.2
LIBSNDFILE_VERSION=1.0.28
LIBGIG_VERSION=4.0.0
LINUXSAMPLER_VERSION=2.0.0
LIBFFI_VERSION=3.2.1
GETTEXT_VERSION=0.18.3.2
GLIB_VERSION=2.44.1


+ 0
- 29
data/macos/patches/libgig_fix-build.patch View File

@@ -1,29 +0,0 @@
diff --git a/src/DLS.h b/src/DLS.h
index 065bfe6..6c9d76c 100644
--- a/src/DLS.h
+++ b/src/DLS.h
@@ -515,10 +515,10 @@ namespace DLS {
virtual void Save(const String& Path, progress_t* pProgress = NULL);
virtual void Save(progress_t* pProgress = NULL);
virtual ~File();
- protected:
typedef std::list<Sample*> SampleList;
typedef std::list<Instrument*> InstrumentList;
+ protected:
RIFF::File* pRIFF;
std::list<RIFF::File*> ExtensionFiles;
SampleList* pSamples;
diff --git a/src/gig.cpp b/src/gig.cpp
index 6a24f16..902e1ae 100644
--- a/src/gig.cpp
+++ b/src/gig.cpp
@@ -4181,7 +4181,7 @@ namespace {
* @param pGroup - script's new group
*/
void Script::SetGroup(ScriptGroup* pGroup) {
- if (this->pGroup = pGroup) return;
+ if (this->pGroup == pGroup) return;
if (pChunk)
pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
this->pGroup = pGroup;

+ 0
- 24
data/macos/patches/linuxsampler_allow-no-drivers-build.patch View File

@@ -1,24 +0,0 @@
--- linuxsampler-static-1.0.0+svn2356.orig/configure.ac
+++ linuxsampler-static-1.0.0+svn2356/configure.ac
@@ -556,21 +556,6 @@ if test "x$MAC_PLUGIN_INSTALL_DIR" = "x"
fi
AC_SUBST(MAC_PLUGIN_INSTALL_DIR)
-# have we found at least one MIDI input and one audio output driver ?
-if test "$have_midi_input_driver" = "false"; then
- echo "No supported MIDI input system found!"
- echo "Sorry, LinuxSampler only supports the following MIDI drivers at the moment:"
- echo "ALSA, JACK, MIDIShare, CoreMIDI, MME."
- echo "If you think you have one of those available on your system, make sure you"
- echo "also have the respective development (header) files installed."
- exit -1;
-fi
-if test "$have_audio_output_driver" = "false"; then
- echo "No supported audio output system found!"
- echo "Sorry, LinuxSampler only supports ALSA, JACK, ARTS and ASIO as audio output"
- echo "driver at the moment!"
- exit -1;
-fi

+ 0
- 10
data/macos/patches/linuxsampler_disable-ladspa-fx.patch View File

@@ -1,10 +0,0 @@
--- linuxsampler-static-1.0.0+svn2497.orig/src/effects/LadspaEffect.cpp
+++ linuxsampler-static-1.0.0+svn2497/src/effects/LadspaEffect.cpp
@@ -374,6 +374,7 @@ static String defaultLadspaDir() {
std::vector<EffectInfo*> LadspaEffect::AvailableEffects() {
std::vector<EffectInfo*> v; // will be filled in callback function _foundLadspaDll()
+ return v;
char* pcLadspaPath = getenv("LADSPA_PATH");
String ladspaDir = pcLadspaPath ? pcLadspaPath : defaultLadspaDir();

+ 1
- 1
data/windows/README.txt View File

@@ -10,7 +10,7 @@ Features
---------

* LADSPA, DSSI, LV2 and VST plugin formats
* GIG, SF2 and SFZ sound banks
* SF2/3 and SFZ sound banks
* Internal audio and midi file player
* Automation of plugin parameters via MIDI CC
* Remote control over OSC


+ 0
- 57
data/windows/build-deps.sh View File

@@ -31,12 +31,10 @@ cleanup_pkgs()
rm -rf flac-*
rm -rf fluidsynth-*
rm -rf glib-*
rm -rf libgig-*
rm -rf liblo-*
rm -rf libogg-*
rm -rf libsndfile-*
rm -rf libvorbis-*
rm -rf linuxsampler-*
rm -rf pkg-config-*
rm -rf zlib-*

@@ -245,61 +243,6 @@ if [ ! -f libsndfile-${LIBSNDFILE_VERSION}/build-done ]; then
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# libgig

if [ ! -d libgig-${LIBGIG_VERSION} ]; then
wget -c http://download.linuxsampler.org/packages/libgig-${LIBGIG_VERSION}.tar.bz2
tar -xf libgig-${LIBGIG_VERSION}.tar.bz2
fi

if [ ! -f libgig-${LIBGIG_VERSION}/build-done ]; then
cd libgig-${LIBGIG_VERSION}
if [ ! -f patched ]; then
patch -p1 -i ../patches/libgig_fix-build.patch
touch patched
fi
./configure --enable-static --disable-shared --prefix=${PREFIX} \
--target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH}
make ${MAKE_ARGS}
make install
touch build-done
cd ..
fi

# ---------------------------------------------------------------------------------------------------------------------
# linuxsampler

if [ ! -d linuxsampler-${LINUXSAMPLER_VERSION} ]; then
wget -c http://download.linuxsampler.org/packages/linuxsampler-${LINUXSAMPLER_VERSION}.tar.bz2
tar -xf linuxsampler-${LINUXSAMPLER_VERSION}.tar.bz2
fi

if [ ! -f linuxsampler-${LINUXSAMPLER_VERSION}/build-done ]; then
cd linuxsampler-${LINUXSAMPLER_VERSION}
if [ ! -f patched ]; then
patch -p1 -i ../patches/linuxsampler_allow-no-drivers-build.patch
patch -p1 -i ../patches/linuxsampler_disable-ladspa-fx.patch
sed -i -e "s|HAVE_LV2|HAVE_AU|" src/hostplugins/Makefile.am
touch patched
fi
rm -f configure
make -f Makefile.svn configure
./configure \
--enable-static --disable-shared --prefix=${PREFIX} \
--target=${MINGW_PREFIX} --host=${MINGW_PREFIX} --build=${HOST_ARCH} \
--enable-signed-triang-algo=diharmonic --enable-unsigned-triang-algo=diharmonic --enable-subfragment-size=8 \
--disable-alsa-driver --disable-arts-driver --disable-jack-driver \
--disable-asio-driver --disable-midishare-driver --disable-mmemidi-driver \
--disable-coreaudio-driver --disable-coremidi-driver \
--disable-instruments-db --disable-sf2-engine
make ${MAKE_ARGS}
make install
sed -i -e "s|-llinuxsampler|-llinuxsampler -L${PREFIX}/lib/libgig -lgig -lsndfile -lFLAC -lvorbisenc -lvorbis -logg -lm -lrpcrt4|" ${PREFIX}/lib/pkgconfig/linuxsampler.pc
touch build-done
cd ..
fi

# ------------------------------------------------------------------------------------
# glib



+ 0
- 2
data/windows/common.env View File

@@ -8,8 +8,6 @@ LIBOGG_VERSION=1.3.3
LIBVORBIS_VERSION=1.3.5
FLAC_VERSION=1.3.2
LIBSNDFILE_VERSION=1.0.28
LIBGIG_VERSION=4.0.0
LINUXSAMPLER_VERSION=2.0.0
LIBFFI_VERSION=3.2.1
GETTEXT_VERSION=0.18.3.2
GLIB_VERSION=2.22.5


+ 0
- 29
data/windows/patches/libgig_fix-build.patch View File

@@ -1,29 +0,0 @@
diff --git a/src/DLS.h b/src/DLS.h
index 065bfe6..6c9d76c 100644
--- a/src/DLS.h
+++ b/src/DLS.h
@@ -515,10 +515,10 @@ namespace DLS {
virtual void Save(const String& Path, progress_t* pProgress = NULL);
virtual void Save(progress_t* pProgress = NULL);
virtual ~File();
- protected:
typedef std::list<Sample*> SampleList;
typedef std::list<Instrument*> InstrumentList;
+ protected:
RIFF::File* pRIFF;
std::list<RIFF::File*> ExtensionFiles;
SampleList* pSamples;
diff --git a/src/gig.cpp b/src/gig.cpp
index 6a24f16..902e1ae 100644
--- a/src/gig.cpp
+++ b/src/gig.cpp
@@ -4181,7 +4181,7 @@ namespace {
* @param pGroup - script's new group
*/
void Script::SetGroup(ScriptGroup* pGroup) {
- if (this->pGroup = pGroup) return;
+ if (this->pGroup == pGroup) return;
if (pChunk)
pChunk->GetParent()->MoveSubChunk(pChunk, pGroup->pList);
this->pGroup = pGroup;

+ 0
- 24
data/windows/patches/linuxsampler_allow-no-drivers-build.patch View File

@@ -1,24 +0,0 @@
--- linuxsampler-static-1.0.0+svn2356.orig/configure.ac
+++ linuxsampler-static-1.0.0+svn2356/configure.ac
@@ -556,21 +556,6 @@ if test "x$MAC_PLUGIN_INSTALL_DIR" = "x"
fi
AC_SUBST(MAC_PLUGIN_INSTALL_DIR)
-# have we found at least one MIDI input and one audio output driver ?
-if test "$have_midi_input_driver" = "false"; then
- echo "No supported MIDI input system found!"
- echo "Sorry, LinuxSampler only supports the following MIDI drivers at the moment:"
- echo "ALSA, JACK, MIDIShare, CoreMIDI, MME."
- echo "If you think you have one of those available on your system, make sure you"
- echo "also have the respective development (header) files installed."
- exit -1;
-fi
-if test "$have_audio_output_driver" = "false"; then
- echo "No supported audio output system found!"
- echo "Sorry, LinuxSampler only supports ALSA, JACK, ARTS and ASIO as audio output"
- echo "driver at the moment!"
- exit -1;
-fi

+ 0
- 10
data/windows/patches/linuxsampler_disable-ladspa-fx.patch View File

@@ -1,10 +0,0 @@
--- linuxsampler-static-1.0.0+svn2497.orig/src/effects/LadspaEffect.cpp
+++ linuxsampler-static-1.0.0+svn2497/src/effects/LadspaEffect.cpp
@@ -374,6 +374,7 @@ static String defaultLadspaDir() {
std::vector<EffectInfo*> LadspaEffect::AvailableEffects() {
std::vector<EffectInfo*> v; // will be filled in callback function _foundLadspaDll()
+ return v;
char* pcLadspaPath = getenv("LADSPA_PATH");
String ladspaDir = pcLadspaPath ? pcLadspaPath : defaultLadspaDir();

+ 0
- 13
resources/ui/carla_settings.ui View File

@@ -1283,19 +1283,6 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="tw_paths_gig">
<layout class="QVBoxLayout" name="verticalLayout_15">
<property name="spacing">
<number>0</number>
</property>
<property name="margin">
<number>0</number>
</property>
<item>
<widget class="QListWidget" name="lw_gig"/>
</item>
</layout>
</widget>
<widget class="QWidget" name="tw_paths_sf2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">


+ 5
- 0
source/Makefile.mk View File

@@ -148,6 +148,11 @@ ifeq ($(MACOS_OLD),true)
BUILD_CXX_FLAGS = $(BASE_FLAGS) $(CXXFLAGS) -DHAVE_CPP11_SUPPORT=0
endif

ifeq ($(WIN32),true)
# Always build statically on windows
LINK_FLAGS += -static
endif

# ---------------------------------------------------------------------------------------------------------------------
# Strict test build



+ 2
- 2
source/backend/CarlaEngine.hpp View File

@@ -280,8 +280,8 @@ struct CARLA_API EngineTimeInfoBBT {

int32_t bar; //!< current bar
int32_t beat; //!< current beat-within-bar
int32_t tick; //!< current tick-within-beat
double barStartTick;
double tick; //!< current tick-within-beat
double barStartTick;

float beatsPerBar; //!< time signature "numerator"
float beatType; //!< time signature "denominator"


+ 3
- 5
source/backend/CarlaPlugin.hpp View File

@@ -807,11 +807,6 @@ public:
// -------------------------------------------------------------------
// Helper functions

/*!
* Check if the plugin can run in rack mode.
*/
bool canRunInRack() const noexcept;

/*!
* Get the plugin's engine, as passed in the constructor.
*/
@@ -940,11 +935,14 @@ protected:
// -------------------------------------------------------------------
// Internal helper functions

public:
// FIXME: remove public exception on 2.1 release
/*!
* Call LV2 restore.
*/
virtual void restoreLV2State() noexcept;

protected:
/*!
* Give plugin bridges a change to update their custom data sets.
*/


+ 2
- 2
source/backend/CarlaStandalone.cpp View File

@@ -1797,7 +1797,7 @@ const char* carla_get_host_osc_url_tcp()
{
carla_debug("carla_get_host_osc_url_tcp()");

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
if (gStandalone.engine == nullptr)
{
carla_stderr2("carla_get_host_osc_url_tcp() failed, engine is not running");
@@ -1815,7 +1815,7 @@ const char* carla_get_host_osc_url_udp()
{
carla_debug("carla_get_host_osc_url_udp()");

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
if (gStandalone.engine == nullptr)
{
carla_stderr2("carla_get_host_osc_url_udp() failed, engine is not running");


+ 84
- 84
source/backend/engine/CarlaEngine.cpp View File

@@ -40,6 +40,9 @@
#include "water/xml/XmlDocument.h"
#include "water/xml/XmlElement.h"

// FIXME Remove on 2.1 release
#include "lv2/atom.h"

using water::Array;
using water::CharPointer_UTF8;
using water::File;
@@ -282,7 +285,7 @@ void CarlaEngine::idle() noexcept
}
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
pData->osc.idle();
#endif
}
@@ -402,81 +405,15 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype,
preferBridges = true;
}
}
# if 0
else if (ptype == PLUGIN_VST2)
{
/*
char uniqueIdChars[5] = {
static_cast<char>((uniqueId & 0xFF000000) >> 24),
static_cast<char>((uniqueId & 0x00FF0000) >> 16),
static_cast<char>((uniqueId & 0x0000FF00) >> 8),
static_cast<char>((uniqueId & 0x000000FF) >> 1),
0
};
*/

/**/ if (uniqueId == 1633895765 && std::strstr(filename, "/ACE.") != nullptr)
preferBridges = true;
else if (uniqueId == 1433421876 && std::strstr(filename, "/Bazille.") != nullptr)
preferBridges = true;
else if (uniqueId == 1147754081 && std::strstr(filename, "/Diva.") != nullptr)
preferBridges = true;
else if (uniqueId == 1095583057 && std::strstr(filename, "/Filterscape.") != nullptr)
preferBridges = true;
else if (uniqueId == 1179866689 && std::strstr(filename, "/Filterscape.") != nullptr)
preferBridges = true;
else if (uniqueId == 1179865398 && std::strstr(filename, "/Filterscape.") != nullptr)
preferBridges = true;
else if (uniqueId == 1749636677 && std::strstr(filename, "/Hive.") != nullptr)
preferBridges = true;
else if (uniqueId == 1296452914 && std::strstr(filename, "/MFM2.") != nullptr)
preferBridges = true;
else if (uniqueId == 1349477487 && std::strstr(filename, "/Podolski.") != nullptr)
preferBridges = true;
else if (uniqueId == 1886548821 && std::strstr(filename, "/Presswerk.") != nullptr)
preferBridges = true;
else if (uniqueId == 1969770582 && std::strstr(filename, "/Protoverb.") != nullptr)
preferBridges = true;
else if (uniqueId == 1969771348 && std::strstr(filename, "/Satin.") != nullptr)
preferBridges = true;
else if (uniqueId == 1667388281 && std::strstr(filename, "/TripleCheese.") != nullptr)
preferBridges = true;
else if (uniqueId == 1952017974 && std::strstr(filename, "/TyrellN6.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432568113 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432568881 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432572209 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432569393 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432569649 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432571953 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1382232375 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432572721 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1432572977 && std::strstr(filename, "/Uhbik.") != nullptr)
preferBridges = true;
else if (uniqueId == 1397572658 && std::strstr(filename, "/Zebra2.") != nullptr)
preferBridges = true;
else if (uniqueId == 1397572659 && std::strstr(filename, "/Zebra2.") != nullptr)
preferBridges = true;
else if (uniqueId == 1919243824 && std::strstr(filename, "/Zebra2.") != nullptr)
preferBridges = true;
else if (uniqueId == 1397578034 && std::strstr(filename, "/Zebra2.") != nullptr)
preferBridges = true;
else if (uniqueId == 1397573722 && std::strstr(filename, "/ZebraHZ.") != nullptr)
preferBridges = true;
}
# endif
}
#endif // ! BUILD_BRIDGE

if (ptype != PLUGIN_INTERNAL && (btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty())))
const bool canBeBridged = ptype != PLUGIN_INTERNAL
&& ptype != PLUGIN_SF2
&& ptype != PLUGIN_SFZ
&& ptype != PLUGIN_JACK;

if (canBeBridged && (btype != BINARY_NATIVE || (preferBridges && bridgeBinary.isNotEmpty())))
{
if (bridgeBinary.isNotEmpty())
{
@@ -490,7 +427,9 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype,
}
else
{
#ifndef BUILD_BRIDGE
bool use16Outs;
#endif
setLastError("Invalid or unsupported plugin type");

switch (ptype)
@@ -498,10 +437,6 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype,
case PLUGIN_NONE:
break;

case PLUGIN_INTERNAL:
plugin = CarlaPlugin::newNative(initializer);
break;

case PLUGIN_LADSPA:
plugin = CarlaPlugin::newLADSPA(initializer, (const LADSPA_RDF_Descriptor*)extra);
break;
@@ -518,6 +453,11 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype,
plugin = CarlaPlugin::newVST2(initializer);
break;

#ifndef BUILD_BRIDGE
case PLUGIN_INTERNAL:
plugin = CarlaPlugin::newNative(initializer);
break;

case PLUGIN_SF2:
use16Outs = (extra != nullptr && std::strcmp((const char*)extra, "true") == 0);
plugin = CarlaPlugin::newFluidSynth(initializer, use16Outs);
@@ -530,6 +470,14 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype,
case PLUGIN_JACK:
plugin = CarlaPlugin::newJackApp(initializer);
break;
#else
case PLUGIN_INTERNAL:
case PLUGIN_SF2:
case PLUGIN_SFZ:
case PLUGIN_JACK:
setLastError("Plugin bridges cannot handle this binary");
break;
#endif
}
}

@@ -543,12 +491,7 @@ bool CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype,

/**/ if (pData->options.processMode == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
{
/**/ if (! plugin->canRunInRack())
{
setLastError("Carla's rack mode can only work with Mono or Stereo plugins, sorry!");
canRun = false;
}
else if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0)
if (plugin->getCVInCount() > 0 || plugin->getCVInCount() > 0)
{
setLastError("Carla's rack mode cannot work with plugins that have CV ports, sorry!");
canRun = false;
@@ -1620,7 +1563,7 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch
}
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
// -----------------------------------------------------------------------
// OSC Stuff

@@ -2114,6 +2057,63 @@ bool CarlaEngine::loadProjectInternal(water::XmlDocument& xmlDoc)

CARLA_SAFE_ASSERT_CONTINUE(stateSave.type != nullptr);

#ifndef BUILD_BRIDGE
// compatibility code to load projects with GIG files
// FIXME Remove on 2.1 release
if (std::strcmp(stateSave.type, "GIG") == 0)
{
if (addPlugin(PLUGIN_LV2, "", stateSave.name, "http://linuxsampler.org/plugins/linuxsampler", 0, nullptr))
{
const uint pluginId = pData->curPluginCount;

if (CarlaPlugin* const plugin = pData->plugins[pluginId].plugin)
{
callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (pData->aboutToClose)
return true;

String lsState;
lsState << "0.35\n";
lsState << "18 0 Chromatic\n";
lsState << "18 1 Drum Kits\n";
lsState << "20 0\n";
lsState << "0 1 " << stateSave.binary << "\n";
lsState << "0 0 0 0 1 0 GIG\n";

plugin->setCustomData(LV2_ATOM__String, "http://linuxsampler.org/schema#state-string", lsState.toRawUTF8(), true);
plugin->restoreLV2State();

plugin->setDryWet(stateSave.dryWet, true, true);
plugin->setVolume(stateSave.volume, true, true);
plugin->setBalanceLeft(stateSave.balanceLeft, true, true);
plugin->setBalanceRight(stateSave.balanceRight, true, true);
plugin->setPanning(stateSave.panning, true, true);
plugin->setCtrlChannel(stateSave.ctrlChannel, true, true);
plugin->setActive(stateSave.active, true, true);

++pData->curPluginCount;

plugin->setEnabled(true);
callback(ENGINE_CALLBACK_PLUGIN_ADDED, pluginId, 0, 0, 0.0f, plugin->getName());

if (pData->options.processMode == ENGINE_PROCESS_MODE_PATCHBAY)
pData->graph.addPlugin(plugin);
}
else
{
carla_stderr2("Failed to get new plugin, state will not be restored correctly\n");
}
}
else
{
carla_stderr2("Failed to load a linuxsampler LV2 plugin, GIG file won't be loaded");
}

continue;
}
#endif

const void* extraStuff = nullptr;
static const char kTrue[] = "true";



+ 0
- 6
source/backend/engine/CarlaEngineBridge.cpp View File

@@ -1405,12 +1405,6 @@ CarlaEngine* CarlaEngine::newBridge(const char* const audioPoolBaseName, const c

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

#ifdef BUILD_BRIDGE_ALTERNATIVE_ARCH
CarlaPlugin* CarlaPlugin::newNative(const CarlaPlugin::Initializer&) { return nullptr; }
CarlaPlugin* CarlaPlugin::newFileSF2(const CarlaPlugin::Initializer&, const bool) { return nullptr; }
CarlaPlugin* CarlaPlugin::newFileSFZ(const CarlaPlugin::Initializer&) { return nullptr; }
#endif

CARLA_BACKEND_END_NAMESPACE

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


+ 1
- 1
source/backend/engine/CarlaEngineData.cpp View File

@@ -297,7 +297,7 @@ EngineTimeInfoBBT::EngineTimeInfoBBT() noexcept
: valid(false),
bar(0),
beat(0),
tick(0),
tick(0.0),
barStartTick(0.0),
beatsPerBar(0.0f),
beatType(0.0f),


+ 48
- 20
source/backend/engine/CarlaEngineGraph.cpp View File

@@ -566,18 +566,20 @@ RackGraph::Buffers::Buffers() noexcept
connectedIn1(),
connectedIn2(),
connectedOut1(),
connectedOut2()
connectedOut2(),
#ifdef CARLA_PROPER_CPP11_SUPPORT
, inBuf{nullptr, nullptr},
inBuf{nullptr, nullptr},
inBufTmp{nullptr, nullptr},
outBuf{nullptr, nullptr} {}
#else
outBuf{nullptr, nullptr},
#endif
unusedBuf(nullptr)
{
#ifndef CARLA_PROPER_CPP11_SUPPORT
inBuf[0] = inBuf[1] = nullptr;
inBufTmp[0] = inBufTmp[1] = nullptr;
outBuf[0] = outBuf[1] = nullptr;
}
#endif
}

RackGraph::Buffers::~Buffers() noexcept
{
@@ -589,6 +591,7 @@ RackGraph::Buffers::~Buffers() noexcept
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }
if (unusedBuf != nullptr) { delete[] unusedBuf; unusedBuf = nullptr; }

connectedIn1.clear();
connectedIn2.clear();
@@ -606,12 +609,14 @@ void RackGraph::Buffers::setBufferSize(const uint32_t bufferSize, const bool cre
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }
if (outBuf[0] != nullptr) { delete[] outBuf[0]; outBuf[0] = nullptr; }
if (outBuf[1] != nullptr) { delete[] outBuf[1]; outBuf[1] = nullptr; }
if (unusedBuf != nullptr) { delete[] unusedBuf; unusedBuf = nullptr; }

CARLA_SAFE_ASSERT_RETURN(bufferSize > 0,);

try {
inBufTmp[0] = new float[bufferSize];
inBufTmp[1] = new float[bufferSize];
unusedBuf = new float[bufferSize];

if (createBuffers)
{
@@ -624,6 +629,7 @@ void RackGraph::Buffers::setBufferSize(const uint32_t bufferSize, const bool cre
catch(...) {
if (inBufTmp[0] != nullptr) { delete[] inBufTmp[0]; inBufTmp[0] = nullptr; }
if (inBufTmp[1] != nullptr) { delete[] inBufTmp[1]; inBufTmp[1] = nullptr; }
if (unusedBuf != nullptr) { delete[] unusedBuf; unusedBuf = nullptr; }

if (createBuffers)
{
@@ -771,24 +777,24 @@ bool RackGraph::getGroupAndPortIdFromFullName(const char* const fullPortName, ui
return extGraph.getGroupAndPortIdFromFullName(fullPortName, groupId, portId);
}

void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inBufReal[2], float* outBuf[2], const uint32_t frames)
void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inBufReal[2], float* outBufReal[2], const uint32_t frames)
{
CARLA_SAFE_ASSERT_RETURN(data != nullptr,);
CARLA_SAFE_ASSERT_RETURN(data->events.in != nullptr,);
CARLA_SAFE_ASSERT_RETURN(data->events.out != nullptr,);

// safe copy
float inBuf0[frames];
float inBuf1[frames];
const float* inBuf[2] = { inBuf0, inBuf1 };
float* const dummyBuf = audioBuffers.unusedBuf;
float* const inBuf0 = audioBuffers.inBufTmp[0];
float* const inBuf1 = audioBuffers.inBufTmp[1];

// initialize audio inputs
carla_copyFloats(inBuf0, inBufReal[0], frames);
carla_copyFloats(inBuf1, inBufReal[1], frames);

// initialize audio outputs (zero)
carla_zeroFloats(outBuf[0], frames);
carla_zeroFloats(outBuf[1], frames);
carla_zeroFloats(outBufReal[0], frames);
carla_zeroFloats(outBufReal[1], frames);

// initialize event outputs (zero)
carla_zeroStructs(data->events.out, kMaxEngineEventInternalCount);
@@ -809,12 +815,12 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB
if (processed)
{
// initialize audio inputs (from previous outputs)
carla_copyFloats(inBuf0, outBuf[0], frames);
carla_copyFloats(inBuf1, outBuf[1], frames);
carla_copyFloats(inBuf0, outBufReal[0], frames);
carla_copyFloats(inBuf1, outBufReal[1], frames);

// initialize audio outputs (zero)
carla_zeroFloats(outBuf[0], frames);
carla_zeroFloats(outBuf[1], frames);
carla_zeroFloats(outBufReal[0], frames);
carla_zeroFloats(outBufReal[1], frames);

// if plugin has no midi out, add previous events
if (oldMidiOutCount == 0 && data->events.in[0].type != kEngineEventTypeNull)
@@ -840,6 +846,28 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB
oldAudioOutCount = plugin->getAudioOutCount();
oldMidiOutCount = plugin->getMidiOutCount();

const uint32_t numInBufs = std::max(oldAudioInCount, 2U);
const uint32_t numOutBufs = std::max(oldAudioOutCount, 2U);

const float* inBuf[numInBufs];
inBuf[0] = inBuf0;
inBuf[1] = inBuf1;

float* outBuf[numOutBufs];
outBuf[0] = outBufReal[0];
outBuf[1] = outBufReal[1];

if (numInBufs > 2 || numOutBufs > 2)
{
carla_zeroFloats(dummyBuf, frames);

for (uint32_t i=2; i<numInBufs; ++i)
inBuf[i] = dummyBuf;

for (uint32_t i=2; i<numOutBufs; ++i)
outBuf[i] = dummyBuf;
}

// process
plugin->initBuffers();
plugin->process(inBuf, outBuf, nullptr, nullptr, frames);
@@ -848,14 +876,14 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB
// if plugin has no audio inputs, add input buffer
if (oldAudioInCount == 0)
{
carla_addFloats(outBuf[0], inBuf0, frames);
carla_addFloats(outBuf[1], inBuf1, frames);
carla_addFloats(outBufReal[0], inBuf0, frames);
carla_addFloats(outBufReal[1], inBuf1, frames);
}

// if plugin only has 1 output, copy it to the 2nd
if (oldAudioOutCount == 1)
{
carla_copyFloats(outBuf[1], outBuf[0], frames);
carla_copyFloats(outBufReal[1], outBufReal[0], frames);
}

// set peaks
@@ -875,8 +903,8 @@ void RackGraph::process(CarlaEngine::ProtectedData* const data, const float* inB

if (oldAudioOutCount > 0)
{
pluginData.outsPeak[0] = carla_findMaxNormalizedFloat(outBuf[0], frames);
pluginData.outsPeak[1] = carla_findMaxNormalizedFloat(outBuf[1], frames);
pluginData.outsPeak[0] = carla_findMaxNormalizedFloat(outBufReal[0], frames);
pluginData.outsPeak[1] = carla_findMaxNormalizedFloat(outBufReal[1], frames);
}
else
{


+ 3
- 2
source/backend/engine/CarlaEngineGraph.hpp View File

@@ -1,6 +1,6 @@
/*
* Carla Plugin Host
* Copyright (C) 2011-2017 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -114,6 +114,7 @@ struct RackGraph {
float* inBuf[2];
float* inBufTmp[2];
float* outBuf[2];
float* unusedBuf;
Buffers() noexcept;
~Buffers() noexcept;
void setBufferSize(const uint32_t bufferSize, const bool createBuffers) noexcept;
@@ -135,7 +136,7 @@ struct RackGraph {
bool getGroupAndPortIdFromFullName(const char* const fullPortName, uint& groupId, uint& portId) const noexcept;

// the base, where plugins run
void process(CarlaEngine::ProtectedData* const data, const float* inBufReal[2], float* outBuf[2], const uint32_t frames);
void process(CarlaEngine::ProtectedData* const data, const float* inBuf[2], float* outBuf[2], const uint32_t frames);

// extended, will call process() in the middle
void processHelper(CarlaEngine::ProtectedData* const data, const float* const* const inBuf, float* const* const outBuf, const uint32_t frames);


+ 6
- 6
source/backend/engine/CarlaEngineInternal.cpp View File

@@ -245,7 +245,7 @@ void EngineInternalTime::fillEngineTimeInfo(const uint32_t newFrames) noexcept

timeInfo.bbt.beatsPerBar = static_cast<float>(beatsPerBar);
timeInfo.bbt.beatsPerMinute = beatsPerMinute;
timeInfo.bbt.tick = static_cast<int32_t>(ticktmp);
timeInfo.bbt.tick = ticktmp;
tick = ticktmp;

if (transportMode == ENGINE_TRANSPORT_MODE_INTERNAL && timeInfo.playing)
@@ -322,7 +322,7 @@ void EngineInternalTime::fillJackTimeInfo(jack_position_t* const pos, const uint

pos->beats_per_bar = static_cast<float>(beatsPerBar);
pos->beats_per_minute = beatsPerMinute;
pos->tick = static_cast<int32_t>(ticktmp);
pos->tick = ticktmp;
tick = ticktmp;
}

@@ -418,7 +418,7 @@ void EngineNextAction::clearAndReset() noexcept

CarlaEngine::ProtectedData::ProtectedData(CarlaEngine* const engine) noexcept
: thread(engine),
#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
osc(engine),
oscData(nullptr),
#endif
@@ -473,7 +473,7 @@ CarlaEngine::ProtectedData::~ProtectedData() noexcept
bool CarlaEngine::ProtectedData::init(const char* const clientName)
{
CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(name.isEmpty(), "Invalid engine internal data (err #1)");
#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(oscData == nullptr, "Invalid engine internal data (err #2)");
#endif
CARLA_SAFE_ASSERT_RETURN_INTERNAL_ERR(events.in == nullptr, "Invalid engine internal data (err #4)");
@@ -523,7 +523,7 @@ bool CarlaEngine::ProtectedData::init(const char* const clientName)

timeInfo.clear();

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
osc.init(clientName);
# ifndef BUILD_BRIDGE
oscData = osc.getControlData();
@@ -554,7 +554,7 @@ void CarlaEngine::ProtectedData::close()
thread.stopThread(500);
nextAction.clearAndReset();

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
osc.close();
oscData = nullptr;
#endif


+ 5
- 3
source/backend/engine/CarlaEngineInternal.hpp View File

@@ -18,11 +18,13 @@
#ifndef CARLA_ENGINE_INTERNAL_HPP_INCLUDED
#define CARLA_ENGINE_INTERNAL_HPP_INCLUDED

#include "CarlaEngineOsc.hpp"
#include "CarlaEngineThread.hpp"
#include "CarlaEngineUtils.hpp"

#include "hylia/hylia.h"
#ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
# include "CarlaEngineOsc.hpp"
# include "hylia/hylia.h"
#endif

// FIXME only use CARLA_PREVENT_HEAP_ALLOCATION for structs
// maybe separate macro
@@ -207,7 +209,7 @@ struct EnginePluginData {
struct CarlaEngine::ProtectedData {
CarlaEngineThread thread;

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
CarlaEngineOsc osc;
# ifdef BUILD_BRIDGE
CarlaOscData* oscData;


+ 2
- 1
source/backend/engine/CarlaEngineNative.cpp View File

@@ -1751,7 +1751,8 @@ protected:

if (timeInfo.bbt.valid)
{
std::sprintf(tmpBuf, P_UINT64 ":%i:%i:%i\n", timeInfo.frame, timeInfo.bbt.bar, timeInfo.bbt.beat, timeInfo.bbt.tick);
std::sprintf(tmpBuf, P_UINT64 ":%i:%i:%i\n",
timeInfo.frame, timeInfo.bbt.bar, timeInfo.bbt.beat, static_cast<int>(timeInfo.bbt.tick + 0.5));
if (! fUiServer.writeMessage(tmpBuf))
return;



+ 34
- 5
source/backend/engine/CarlaEngineRtAudio.cpp View File

@@ -90,7 +90,7 @@ static const char* getRtAudioApiName(const RtAudio::Api api) noexcept
case RtAudio::UNIX_PULSE:
return "PulseAudio";
case RtAudio::UNIX_JACK:
#if defined(CARLA_OS_LINUX)
#if defined(CARLA_OS_LINUX) && defined(HAVE_ALSA)
return "JACK with ALSA-MIDI";
#elif defined(CARLA_OS_MAC)
return "JACK with CoreMidi";
@@ -128,7 +128,7 @@ static RtMidi::Api getMatchedAudioMidiAPI(const RtAudio::Api rtApi) noexcept

case RtAudio::UNIX_PULSE:
case RtAudio::UNIX_JACK:
#if defined(CARLA_OS_LINUX)
#if defined(CARLA_OS_LINUX) && defined(HAVE_ALSA)
return RtMidi::LINUX_ALSA;
#elif defined(CARLA_OS_MAC)
return RtMidi::MACOSX_CORE;
@@ -286,7 +286,8 @@ public:
fAudio.openStream(oParams.nChannels > 0 ? &oParams : nullptr,
iParams.nChannels > 0 ? &iParams : nullptr,
RTAUDIO_FLOAT32, pData->options.audioSampleRate, &bufferFrames,
carla_rtaudio_process_callback, this, &rtOptions);
carla_rtaudio_process_callback, this, &rtOptions,
carla_rtaudio_buffer_size_callback);
}
catch (const RtAudioError& e) {
setLastError(e.what());
@@ -592,8 +593,7 @@ protected:
/* */ float* const outsPtr = (float*)outputBuffer;

// assert rtaudio buffers
CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,);
CARLA_SAFE_ASSERT_RETURN(pData->bufferSize == nframes,);
CARLA_SAFE_ASSERT_RETURN(outputBuffer != nullptr,);

// set rtaudio buffers as non-interleaved
const float* inBuf[fAudioInCount];
@@ -601,6 +601,7 @@ protected:

if (fAudioInterleaved)
{
// FIXME - this looks completely wrong!
float* inBuf2[fAudioInCount];

for (uint i=0, count=fAudioInCount; i<count; ++i)
@@ -755,6 +756,28 @@ protected:
(void)streamTime; (void)status;
}

void handleBufferSizeCallback(const uint newBufferSize)
{
carla_stdout("bufferSize callback %u %u", pData->bufferSize, newBufferSize);
if (pData->bufferSize == newBufferSize)
return;

if (fAudioInCount > 0)
{
delete[] fAudioIntBufIn;
fAudioIntBufIn = new float[fAudioInCount*newBufferSize];
}

if (fAudioOutCount > 0)
{
delete[] fAudioIntBufOut;
fAudioIntBufOut = new float[fAudioOutCount*newBufferSize];
}

pData->bufferSize = newBufferSize;
bufferSizeChanged(newBufferSize);
}

void handleMidiCallback(double timeStamp, std::vector<uchar>* const message)
{
const size_t messageSize(message->size());
@@ -1056,6 +1079,12 @@ private:
return 0;
}

static bool carla_rtaudio_buffer_size_callback(unsigned int bufferSize, void* userData)
{
handlePtr->handleBufferSizeCallback(bufferSize);
return true;
}

static void carla_rtmidi_callback(double timeStamp, std::vector<uchar>* message, void* userData)
{
handlePtr->handleMidiCallback(timeStamp, message);


+ 3
- 3
source/backend/engine/CarlaEngineThread.cpp View File

@@ -1,6 +1,6 @@
/*
* Carla Plugin Host
* Copyright (C) 2011-2014 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2011-2018 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -46,7 +46,7 @@ void CarlaEngineThread::run() noexcept
#endif
carla_debug("CarlaEngineThread::run()");

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
const bool isPlugin(kEngine->getType() == kEngineTypePlugin);
#endif
float value;
@@ -63,7 +63,7 @@ void CarlaEngineThread::run() noexcept
const bool oscRegisted = false;
#endif

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
if (isPlugin)
kEngine->idleOsc();
#endif


+ 0
- 5
source/backend/plugin/CarlaPlugin.cpp View File

@@ -2411,11 +2411,6 @@ void CarlaPlugin::uiNoteOff(const uint8_t channel, const uint8_t note) noexcept
CARLA_SAFE_ASSERT_RETURN(note < MAX_MIDI_NOTE,);
}

bool CarlaPlugin::canRunInRack() const noexcept
{
return (pData->extraHints & PLUGIN_EXTRA_HINT_CAN_RUN_RACK) != 0;
}

CarlaEngine* CarlaPlugin::getEngine() const noexcept
{
return pData->engine;


+ 169
- 79
source/backend/plugin/CarlaPluginBridge.cpp View File

@@ -161,10 +161,17 @@ protected:
// start with "wine" if needed
if (fBinary.endsWithIgnoreCase(".exe"))
{
String wineCMD;

if (options.wine.executable != nullptr && options.wine.executable[0] != '\0')
arguments.add(options.wine.executable);
wineCMD = options.wine.executable;
else
arguments.add("wine");
wineCMD = "wine";

if (fBinary.endsWithIgnoreCase("64.exe"))
wineCMD += "64";

arguments.add(wineCMD);
}
#endif

@@ -260,10 +267,12 @@ protected:
if (options.wine.rtPrio)
{
carla_setenv("STAGING_SHARED_MEMORY", "1");
carla_setenv("WINE_RT_POLICY", "FF");

std::snprintf(strBuf, STR_MAX, "%i", options.wine.baseRtPrio);
carla_setenv("STAGING_RT_PRIORITY_BASE", strBuf);
carla_setenv("WINE_RT", strBuf);
carla_setenv("WINE_RT_PRIO", strBuf);

std::snprintf(strBuf, STR_MAX, "%i", options.wine.serverRtPrio);
carla_setenv("STAGING_RT_PRIORITY_SERVER", strBuf);
@@ -272,9 +281,11 @@ protected:
else
{
carla_unsetenv("STAGING_SHARED_MEMORY");
carla_unsetenv("WINE_RT_POLICY");
carla_unsetenv("STAGING_RT_PRIORITY_BASE");
carla_unsetenv("STAGING_RT_PRIORITY_SERVER");
carla_unsetenv("WINE_RT");
carla_unsetenv("WINE_RT_PRIO");
carla_unsetenv("WINE_SVR_RT");
}

@@ -901,8 +912,7 @@ public:
fTimedOut = true;
fTimedError = true;
fInitiated = false;
pData->engine->callback(ENGINE_CALLBACK_PLUGIN_UNAVAILABLE, pData->id, 0, 0, 0.0f,
"Plugin bridge has been stopped or crashed");
handleProcessStopped();
}

CarlaPlugin::idle();
@@ -1064,9 +1074,6 @@ public:
if (fInfo.mOuts > 0)
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;

if (fInfo.aIns <= 2 && fInfo.aOuts <= 2 && (fInfo.aIns == fInfo.aOuts || fInfo.aIns == 0 || fInfo.aOuts == 0))
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);

@@ -1078,7 +1085,10 @@ public:

void activate() noexcept override
{
CARLA_SAFE_ASSERT_RETURN(! fTimedError,);
if (! fBridgeThread.isThreadRunning())
{
CARLA_SAFE_ASSERT_RETURN(restartBridgeThread(),);
}

{
const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);
@@ -1824,8 +1834,17 @@ public:
fInfo.aIns = fShmNonRtServerControl.readUInt();
fInfo.aOuts = fShmNonRtServerControl.readUInt();

CARLA_SAFE_ASSERT(fInfo.aInNames == nullptr);
CARLA_SAFE_ASSERT(fInfo.aOutNames == nullptr);
if (fInfo.aInNames != nullptr)
{
delete[] fInfo.aInNames;
fInfo.aInNames = nullptr;
}

if (fInfo.aOutNames != nullptr)
{
delete[] fInfo.aOutNames;
fInfo.aOutNames = nullptr;
}

if (fInfo.aIns > 0)
{
@@ -2318,26 +2337,6 @@ public:
return false;
}

// ---------------------------------------------------------------
// initial values

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion);
fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION);

fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup);
fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());

fShmNonRtClientControl.commitWrite();

// testing dummy message
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
fShmRtClientControl.commitWrite();

#ifndef CARLA_OS_WIN
// ---------------------------------------------------------------
// set wine prefix
@@ -2380,58 +2379,10 @@ public:
fWinePrefix.toRawUTF8(),
#endif
bridgeBinary, label, shmIdsStr);
fBridgeThread.startThread();
}

// ---------------------------------------------------------------
// wait for bridge to start

fInitiated = false;
fLastPongTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPongTime > 0);

static bool sFirstInit = true;

int64_t timeoutEnd = 5000;

if (sFirstInit)
timeoutEnd *= 2;
#ifndef CARLA_OS_WIN
if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
timeoutEnd *= 2;
#endif
sFirstInit = false;

const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;

for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
{
pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (needsEngineIdle)
pData->engine->idle();

idle();

if (fInitiated)
break;
if (pData->engine->isAboutToClose())
break;

carla_msleep(20);
}

fLastPongTime = -1;

if (fInitError || ! fInitiated)
{
fBridgeThread.stopThread(6000);

if (! fInitError)
pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n(or the plugin crashed on initialization?)");

if (! restartBridgeThread())
return false;
}

// ---------------------------------------------------------------
// register client
@@ -2578,6 +2529,24 @@ private:

BridgeParamInfo* fParams;

void handleProcessStopped() noexcept
{
const bool wasActive = pData->active;
pData->active = false;

if (wasActive)
{
#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
if (pData->engine->isOscControlRegistered())
pData->engine->oscSend_control_set_parameter_value(pData->id, PARAMETER_ACTIVE, 0.0f);
pData->engine->callback(ENGINE_CALLBACK_PARAMETER_VALUE_CHANGED, pData->id, PARAMETER_ACTIVE, 0, 0.0f, nullptr);
#endif
}

if (pData->hints & PLUGIN_HAS_CUSTOM_UI)
pData->engine->callback(ENGINE_CALLBACK_UI_STATE_CHANGED, pData->id, 0, 0, 0.0f, nullptr);
}

void resizeAudioPool(const uint32_t bufferSize)
{
fShmAudioPool.resize(bufferSize, fInfo.aIns+fInfo.aOuts, fInfo.cvIns+fInfo.cvOuts);
@@ -2601,6 +2570,127 @@ private:
carla_stderr2("waitForClient(%s) timed out", action);
}

bool restartBridgeThread()
{
fInitiated = false;
fInitError = false;
fTimedError = false;

// reset memory
fShmRtClientControl.data->procFlags = 0;
carla_zeroStruct(fShmRtClientControl.data->timeInfo);
carla_zeroBytes(fShmRtClientControl.data->midiOut, kBridgeRtClientDataMidiOutSize);

fShmRtClientControl.clearData();
fShmNonRtClientControl.clearData();
fShmNonRtServerControl.clearData();

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientVersion);
fShmNonRtClientControl.writeUInt(CARLA_PLUGIN_BRIDGE_API_VERSION);

fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtClientData)));
fShmNonRtClientControl.writeUInt(static_cast<uint32_t>(sizeof(BridgeNonRtServerData)));

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientInitialSetup);
fShmNonRtClientControl.writeUInt(pData->engine->getBufferSize());
fShmNonRtClientControl.writeDouble(pData->engine->getSampleRate());

fShmNonRtClientControl.commitWrite();

if (fShmAudioPool.dataSize != 0)
{
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientSetAudioPool);
fShmRtClientControl.writeULong(static_cast<uint64_t>(fShmAudioPool.dataSize));
fShmRtClientControl.commitWrite();
}
else
{
// testing dummy message
fShmRtClientControl.writeOpcode(kPluginBridgeRtClientNull);
fShmRtClientControl.commitWrite();
}

fBridgeThread.startThread();

fLastPongTime = Time::currentTimeMillis();
CARLA_SAFE_ASSERT(fLastPongTime > 0);

static bool sFirstInit = true;

int64_t timeoutEnd = 5000;

if (sFirstInit)
timeoutEnd *= 2;
#ifndef CARLA_OS_WIN
if (fBinaryType == BINARY_WIN32 || fBinaryType == BINARY_WIN64)
timeoutEnd *= 2;
#endif
sFirstInit = false;

const bool needsEngineIdle = pData->engine->getType() != kEngineTypePlugin;

for (; Time::currentTimeMillis() < fLastPongTime + timeoutEnd && fBridgeThread.isThreadRunning();)
{
pData->engine->callback(ENGINE_CALLBACK_IDLE, 0, 0, 0, 0.0f, nullptr);

if (needsEngineIdle)
pData->engine->idle();

idle();

if (fInitiated)
break;
if (pData->engine->isAboutToClose())
break;

carla_msleep(20);
}

fLastPongTime = -1;

if (fInitError || ! fInitiated)
{
fBridgeThread.stopThread(6000);

if (! fInitError)
pData->engine->setLastError("Timeout while waiting for a response from plugin-bridge\n"
"(or the plugin crashed on initialization?)");

return false;
}

if (const size_t dataSize = fInfo.chunk.size())
{
#ifdef CARLA_PROPER_CPP11_SUPPORT
void* data = fInfo.chunk.data();
#else
void* data = &fInfo.chunk.front();
#endif
CarlaString dataBase64(CarlaString::asBase64(data, dataSize));
CARLA_SAFE_ASSERT_RETURN(dataBase64.length() > 0, true);

String filePath(File::getSpecialLocation(File::tempDirectory).getFullPathName());

filePath += CARLA_OS_SEP_STR ".CarlaChunk_";
filePath += fShmAudioPool.getFilenameSuffix();

if (File(filePath).replaceWithText(dataBase64.buffer()))
{
const uint32_t ulength(static_cast<uint32_t>(filePath.length()));

const CarlaMutexLocker _cml(fShmNonRtClientControl.mutex);

fShmNonRtClientControl.writeOpcode(kPluginBridgeNonRtClientSetChunkDataFile);
fShmNonRtClientControl.writeUInt(ulength);
fShmNonRtClientControl.writeCustomData(filePath.toRawUTF8(), ulength);
fShmNonRtClientControl.commitWrite();
}
}

return true;
}

CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginBridge)
};



+ 15
- 16
source/backend/plugin/CarlaPluginDSSI.cpp View File

@@ -21,7 +21,7 @@
#include "CarlaDssiUtils.hpp"
#include "CarlaMathUtils.hpp"

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
# include "CarlaOscUtils.hpp"
# include "CarlaPipeUtils.hpp"
# include "CarlaThread.hpp"
@@ -63,7 +63,7 @@ CARLA_BACKEND_START_NAMESPACE

static const CustomData kCustomDataFallback = { nullptr, nullptr, nullptr };

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
// -------------------------------------------------------------------

class CarlaThreadDSSIUI : public CarlaThread
@@ -283,7 +283,7 @@ public:
fForcedStereoOut(false),
fNeedsFixedBuffers(false),
fUsesCustomData(false)
#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
, fOscData(),
fThreadUI(engine, this, fOscData),
fUiFilename(nullptr)
@@ -298,7 +298,7 @@ public:
{
carla_debug("CarlaPluginDSSI::~CarlaPluginDSSI()");

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
// close UI
if (fUiFilename != nullptr)
{
@@ -594,7 +594,7 @@ public:
}
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
if (sendGui && fOscData.target != nullptr)
osc_send_configure(fOscData, key, value);
#endif
@@ -632,7 +632,7 @@ public:
}
}

#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
const bool sendOsc(pData->engine->isOscControlRegistered());
#else
const bool sendOsc(false);
@@ -684,7 +684,7 @@ public:
}
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
// -------------------------------------------------------------------
// Set ui stuff

@@ -1083,7 +1083,7 @@ public:
if (LADSPA_IS_HARD_RT_CAPABLE(fDescriptor->Properties))
pData->hints |= PLUGIN_IS_RTSAFE;

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
if (fUiFilename != nullptr)
pData->hints |= PLUGIN_HAS_CUSTOM_UI;
#endif
@@ -1100,8 +1100,7 @@ public:
#endif

// extra plugin hints
pData->extraHints = 0x0;
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
pData->extraHints = 0x0;

if (mIns > 0)
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
@@ -1219,7 +1218,7 @@ public:
}
}

#if defined(HAVE_LIBLO) && ! defined(BUILD_BRIDGE)
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE)
// Update OSC Names
if (pData->engine->isOscControlRegistered() && pData->id < pData->engine->getCurrentPluginCount())
{
@@ -2185,7 +2184,7 @@ public:
carla_debug("CarlaPluginDSSI::clearBuffers() - end");
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
// -------------------------------------------------------------------
// OSC stuff

@@ -2444,7 +2443,7 @@ public:
osc_send_midi(fOscData, midiData);
#endif
}
#endif // HAVE_LIBLO
#endif // HAVE_LIBLO && !BUILD_BRIDGE_ALTERNATIVE_ARCH

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

@@ -2453,7 +2452,7 @@ public:
return fDssiDescriptor;
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
uintptr_t getUiBridgeProcessId() const noexcept override
{
return fThreadUI.getProcessId();
@@ -2653,7 +2652,7 @@ public:
}
}

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
// ---------------------------------------------------------------
// check for gui

@@ -2719,7 +2718,7 @@ private:
bool fNeedsFixedBuffers;
bool fUsesCustomData;

#ifdef HAVE_LIBLO
#if defined(HAVE_LIBLO) && !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH)
CarlaOscData fOscData;
CarlaThreadDSSIUI fThreadUI;
const char* fUiFilename;


+ 0
- 3
source/backend/plugin/CarlaPluginFluidSynth.cpp View File

@@ -919,9 +919,6 @@ public:
pData->extraHints = 0x0;
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;

if (! kUse16Outs)
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);



+ 2
- 3
source/backend/plugin/CarlaPluginInternal.hpp View File

@@ -47,9 +47,8 @@ const ushort kPluginMaxMidiEvents = 512;
// -----------------------------------------------------------------------
// Extra plugin hints, hidden from backend

const uint PLUGIN_EXTRA_HINT_HAS_MIDI_IN = 0x01;
const uint PLUGIN_EXTRA_HINT_HAS_MIDI_OUT = 0x02;
const uint PLUGIN_EXTRA_HINT_CAN_RUN_RACK = 0x04;
const uint PLUGIN_EXTRA_HINT_HAS_MIDI_IN = 0x01;
const uint PLUGIN_EXTRA_HINT_HAS_MIDI_OUT = 0x02;

// -----------------------------------------------------------------------
// Special parameters


+ 0
- 3
source/backend/plugin/CarlaPluginJack.cpp View File

@@ -576,9 +576,6 @@ public:
if (fInfo.mOuts > 0)
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;

if (fInfo.aIns <= 2 && fInfo.aOuts <= 2 && (fInfo.aIns == fInfo.aOuts || fInfo.aIns == 0 || fInfo.aOuts == 0))
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);



+ 1
- 2
source/backend/plugin/CarlaPluginLADSPA.cpp View File

@@ -788,8 +788,7 @@ public:
#endif

// extra plugin hints
pData->extraHints = 0x0;
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
pData->extraHints = 0x0;

// check initial latency
findInitialLatencyValue(aIns, aOuts);


+ 14
- 32
source/backend/plugin/CarlaPluginLV2.cpp View File

@@ -30,7 +30,6 @@
#include "CarlaPluginUI.hpp"
#include "Lv2AtomRingBuffer.hpp"

#include "../engine/CarlaEngineOsc.hpp"
#include "../modules/lilv/config/lilv_config.h"

extern "C" {
@@ -519,7 +518,6 @@ public:
fCvInBuffers(nullptr),
fCvOutBuffers(nullptr),
fParamBuffers(nullptr),
fCanInit2(true),
fNeedsFixedBuffers(false),
fNeedsUiClose(false),
fLatencyIndex(-1),
@@ -841,7 +839,7 @@ public:
if (pData->engine->getOptions().forceStereo)
pass();
// if inputs or outputs are just 1, then yes we can force stereo
else if (((pData->audioIn.count == 1 || pData->audioOut.count == 1) && fCanInit2) || fHandle2 != nullptr)
else if ((pData->audioIn.count == 1 || pData->audioOut.count == 1) || fHandle2 != nullptr)
options |= PLUGIN_OPTION_FORCE_STEREO;

if (fExt.programs != nullptr)
@@ -2381,7 +2379,7 @@ public:
if (fEventsOut.ctrl != nullptr && fEventsOut.ctrl->port == nullptr)
fEventsOut.ctrl->port = pData->event.portOut;

if (fCanInit2 && (forcedStereoIn || forcedStereoOut))
if (forcedStereoIn || forcedStereoOut)
pData->options |= PLUGIN_OPTION_FORCE_STEREO;
else
pData->options &= ~PLUGIN_OPTION_FORCE_STEREO;
@@ -2415,21 +2413,6 @@ public:
// extra plugin hints
pData->extraHints = 0x0;

if (! fCanInit2)
{
// can't run in rack
}
else if (fExt.state != nullptr || fExt.worker != nullptr)
{
if ((aIns == 0 || aIns == 2) && (aOuts == 0 || aOuts == 2) && evIns.count() <= 1 && evOuts.count() <= 1)
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
}
else
{
if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && evIns.count() <= 1 && evOuts.count() <= 1)
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;
}

// check initial latency
findInitialLatencyValue(aIns, aOuts);

@@ -2804,7 +2787,7 @@ public:
int32_t rindex;

const double barBeat = static_cast<double>(timeInfo.bbt.beat - 1)
+ (static_cast<double>(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat);
+ (timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat);

// update input ports
for (uint32_t k=0; k < pData->param.count; ++k)
@@ -4500,7 +4483,10 @@ public:
CARLA_SAFE_ASSERT_RETURN(value != nullptr, LV2_STATE_ERR_NO_PROPERTY);
CARLA_SAFE_ASSERT_RETURN(size > 0, LV2_STATE_ERR_NO_PROPERTY);
CARLA_SAFE_ASSERT_RETURN(type != kUridNull, LV2_STATE_ERR_BAD_TYPE);
CARLA_SAFE_ASSERT_RETURN(flags & LV2_STATE_IS_POD, LV2_STATE_ERR_BAD_FLAGS);

// FIXME linuxsampler does not set POD flag
// CARLA_SAFE_ASSERT_RETURN(flags & LV2_STATE_IS_POD, LV2_STATE_ERR_BAD_FLAGS);

carla_debug("CarlaPluginLV2::handleStateStore(%i:\"%s\", %p, " P_SIZE ", %i:\"%s\", %i)",
key, carla_lv2_urid_unmap(this, key), value, size, type, carla_lv2_urid_unmap(this, type), flags);

@@ -4543,6 +4529,9 @@ public:
pData->custom.append(newData);

return LV2_STATE_SUCCESS;

// unused
(void)flags;
}

const void* handleStateRetrieve(const uint32_t key, size_t* const size, uint32_t* const type, uint32_t* const flags)
@@ -5244,9 +5233,6 @@ public:
return false;
}

if (std::strcmp(uri, "http://hyperglitch.com/dev/VocProc") == 0)
fCanInit2 = false;

recheckExtensions();

// ---------------------------------------------------------------
@@ -5259,13 +5245,10 @@ public:
else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;

if (fCanInit2)
{
if (pData->engine->getOptions().forceStereo)
pData->options |= PLUGIN_OPTION_FORCE_STEREO;
else if (options & PLUGIN_OPTION_FORCE_STEREO)
pData->options |= PLUGIN_OPTION_FORCE_STEREO;
}
if (pData->engine->getOptions().forceStereo)
pData->options |= PLUGIN_OPTION_FORCE_STEREO;
else if (options & PLUGIN_OPTION_FORCE_STEREO)
pData->options |= PLUGIN_OPTION_FORCE_STEREO;

if (getMidiInCount() != 0)
{
@@ -5765,7 +5748,6 @@ private:
float** fCvOutBuffers;
float* fParamBuffers;

bool fCanInit2; // some plugins don't like 2 instances
bool fNeedsFixedBuffers;
bool fNeedsUiClose;
int32_t fLatencyIndex; // -1 if invalid


+ 80
- 75
source/backend/plugin/CarlaPluginNative.cpp View File

@@ -253,7 +253,8 @@ public:
fIsUiVisible(false),
fAudioInBuffers(nullptr),
fAudioOutBuffers(nullptr),
fMidiEventCount(0),
fMidiEventInCount(0),
fMidiEventOutCount(0),
fCurBufferSize(engine->getBufferSize()),
fCurSampleRate(engine->getSampleRate()),
fMidiIn(),
@@ -263,7 +264,8 @@ public:
carla_debug("CarlaPluginNative::CarlaPluginNative(%p, %i)", engine, id);

carla_fill(fCurMidiProgs, 0, MAX_MIDI_CHANNELS);
carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents*2);
carla_zeroStructs(fMidiInEvents, kPluginMaxMidiEvents);
carla_zeroStructs(fMidiOutEvents, kPluginMaxMidiEvents);
carla_zeroStruct(fTimeInfo);

fHost.handle = this;
@@ -410,8 +412,8 @@ public:

uint options = 0x0;

// can't disable fixed buffers if using MIDI output
if (fDescriptor->midiOuts == 0 && (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) == 0)
// can't disable fixed buffers if required by the plugin
if ((fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) == 0x0)
options |= PLUGIN_OPTION_FIXED_BUFFERS;

// can't disable forced stereo if enabled in the engine
@@ -1293,9 +1295,6 @@ public:
// extra plugin hints
pData->extraHints = 0x0;

if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0) && mIns <= 1 && mOuts <= 1)
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);

@@ -1495,8 +1494,9 @@ public:
return;
}

fMidiEventCount = 0;
carla_zeroStructs(fMidiEvents, kPluginMaxMidiEvents*2);
fMidiEventInCount = fMidiEventOutCount = 0;
carla_zeroStructs(fMidiInEvents, kPluginMaxMidiEvents);
carla_zeroStructs(fMidiOutEvents, kPluginMaxMidiEvents);

// --------------------------------------------------------------------------------------------------------
// Check if needs reset
@@ -1505,31 +1505,31 @@ public:
{
if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
{
fMidiEventCount = MAX_MIDI_CHANNELS*2;
fMidiEventInCount = MAX_MIDI_CHANNELS*2;

for (uint8_t k=0, i=MAX_MIDI_CHANNELS; k < MAX_MIDI_CHANNELS; ++k)
{
fMidiEvents[k].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT));
fMidiEvents[k].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
fMidiEvents[k].data[2] = 0;
fMidiEvents[k].size = 3;
fMidiEvents[k+i].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT));
fMidiEvents[k+i].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
fMidiEvents[k+i].data[2] = 0;
fMidiEvents[k+i].size = 3;
fMidiInEvents[k].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT));
fMidiInEvents[k].data[1] = MIDI_CONTROL_ALL_NOTES_OFF;
fMidiInEvents[k].data[2] = 0;
fMidiInEvents[k].size = 3;
fMidiInEvents[k+i].data[0] = uint8_t(MIDI_STATUS_CONTROL_CHANGE | (k & MIDI_CHANNEL_BIT));
fMidiInEvents[k+i].data[1] = MIDI_CONTROL_ALL_SOUND_OFF;
fMidiInEvents[k+i].data[2] = 0;
fMidiInEvents[k+i].size = 3;
}
}
else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
{
fMidiEventCount = MAX_MIDI_NOTE;
fMidiEventInCount = MAX_MIDI_NOTE;

for (uint8_t k=0; k < MAX_MIDI_NOTE; ++k)
{
fMidiEvents[k].data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT));
fMidiEvents[k].data[1] = k;
fMidiEvents[k].data[2] = 0;
fMidiEvents[k].size = 3;
fMidiInEvents[k].data[0] = uint8_t(MIDI_STATUS_NOTE_OFF | (pData->ctrlChannel & MIDI_CHANNEL_BIT));
fMidiInEvents[k].data[1] = k;
fMidiInEvents[k].data[2] = 0;
fMidiInEvents[k].size = 3;
}
}

@@ -1577,13 +1577,13 @@ public:
{
ExternalMidiNote note = { 0, 0, 0 };

for (; fMidiEventCount < kPluginMaxMidiEvents*2 && ! pData->extNotes.data.isEmpty();)
for (; fMidiEventInCount < kPluginMaxMidiEvents && ! pData->extNotes.data.isEmpty();)
{
note = pData->extNotes.data.getFirst(note, true);

CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);

nativeEvent.data[0] = uint8_t((note.velo > 0 ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF) | (note.channel & MIDI_CHANNEL_BIT));
nativeEvent.data[1] = note.note;
@@ -1641,10 +1641,16 @@ public:
else
nextBankId = 0;

if (fMidiEventCount > 0)
if (fMidiEventInCount > 0)
{
carla_zeroStructs(fMidiInEvents, fMidiEventInCount);
fMidiEventInCount = 0;
}

if (fMidiEventOutCount > 0)
{
carla_zeroStructs(fMidiEvents, fMidiEventCount);
fMidiEventCount = 0;
carla_zeroStructs(fMidiOutEvents, fMidiEventOutCount);
fMidiEventOutCount = 0;
}
}
else
@@ -1744,10 +1750,10 @@ public:

if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_CONTROL)
{
if (fMidiEventCount >= kPluginMaxMidiEvents*2)
if (fMidiEventInCount >= kPluginMaxMidiEvents)
continue;

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.time = sampleAccurate ? startTime : eventTime;
@@ -1768,10 +1774,10 @@ public:
}
else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
{
if (fMidiEventCount >= kPluginMaxMidiEvents*2)
if (fMidiEventInCount >= kPluginMaxMidiEvents)
continue;

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.time = sampleAccurate ? startTime : eventTime;
@@ -1810,10 +1816,10 @@ public:
}
else if (pData->options & PLUGIN_OPTION_SEND_PROGRAM_CHANGES)
{
if (fMidiEventCount >= kPluginMaxMidiEvents*2)
if (fMidiEventInCount >= kPluginMaxMidiEvents)
continue;

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.time = sampleAccurate ? startTime : eventTime;
@@ -1826,10 +1832,10 @@ public:
case kEngineControlEventTypeAllSoundOff:
if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
{
if (fMidiEventCount >= kPluginMaxMidiEvents*2)
if (fMidiEventInCount >= kPluginMaxMidiEvents)
continue;

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.time = sampleAccurate ? startTime : eventTime;
@@ -1851,10 +1857,10 @@ public:
}
#endif

if (fMidiEventCount >= kPluginMaxMidiEvents*2)
if (fMidiEventInCount >= kPluginMaxMidiEvents)
continue;

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.time = sampleAccurate ? startTime : eventTime;
@@ -1869,7 +1875,7 @@ public:
}

case kEngineEventTypeMidi: {
if (fMidiEventCount >= kPluginMaxMidiEvents*2)
if (fMidiEventInCount >= kPluginMaxMidiEvents)
continue;

const EngineMidiEvent& midiEvent(event.midi);
@@ -1895,7 +1901,7 @@ public:
if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
status = MIDI_STATUS_NOTE_OFF;

NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]);
NativeMidiEvent& nativeEvent(fMidiInEvents[fMidiEventInCount++]);
carla_zeroStruct(nativeEvent);

nativeEvent.port = midiEvent.port;
@@ -1931,12 +1937,12 @@ public:

} // End of Plugin processing (no events)

#ifndef BUILD_BRIDGE
// --------------------------------------------------------------------------------------------------------
// Control and MIDI Output
// Control Output

if (pData->event.portOut != nullptr)
{
#ifndef BUILD_BRIDGE
float value, curValue;

for (uint32_t k=0; k < pData->param.count; ++k)
@@ -1953,24 +1959,8 @@ public:
pData->event.portOut->writeControlEvent(0, pData->param.data[k].midiChannel, kEngineControlEventTypeParameter, static_cast<uint16_t>(pData->param.data[k].midiCC), value);
}
}
} // End of Control Output
#endif

// reverse lookup MIDI events
for (uint32_t k = (kPluginMaxMidiEvents*2)-1; k >= fMidiEventCount; --k)
{
if (fMidiEvents[k].data[0] == 0)
break;

const uint8_t channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(fMidiEvents[k].data));
const uint8_t port = fMidiEvents[k].port;

if (fMidiOut.count > 1 && port < fMidiOut.count)
fMidiOut.ports[port]->writeMidiEvent(fMidiEvents[k].time, channel, fMidiEvents[k].size, fMidiEvents[k].data);
else
pData->event.portOut->writeMidiEvent(fMidiEvents[k].time, channel, fMidiEvents[k].size, fMidiEvents[k].data);
}

} // End of Control and MIDI Output
}

bool processSingle(const float** const audioIn, float** const audioOut, const float** const cvIn, float** const cvOut, const uint32_t frames, const uint32_t timeOffset)
@@ -2044,19 +2034,19 @@ public:

if (fHandle2 == nullptr)
{
fDescriptor->process(fHandle, fAudioInBuffers, fAudioOutBuffers, frames, fMidiEvents, fMidiEventCount);
fDescriptor->process(fHandle, fAudioInBuffers, fAudioOutBuffers, frames, fMidiInEvents, fMidiEventInCount);
}
else
{
fDescriptor->process(fHandle,
(pData->audioIn.count > 0) ? &fAudioInBuffers[0] : nullptr,
(pData->audioOut.count > 0) ? &fAudioOutBuffers[0] : nullptr,
frames, fMidiEvents, fMidiEventCount);
frames, fMidiInEvents, fMidiEventInCount);

fDescriptor->process(fHandle2,
(pData->audioIn.count > 0) ? &fAudioInBuffers[1] : nullptr,
(pData->audioOut.count > 0) ? &fAudioOutBuffers[1] : nullptr,
frames, fMidiEvents, fMidiEventCount);
frames, fMidiInEvents, fMidiEventInCount);
}

fIsProcessing = false;
@@ -2140,6 +2130,23 @@ public:
}
#endif

// --------------------------------------------------------------------------------------------------------
// MIDI Output

if (pData->event.portOut != nullptr)
{
for (uint32_t k = 0; k < fMidiEventOutCount; --k)
{
const uint8_t channel = uint8_t(MIDI_GET_CHANNEL_FROM_DATA(fMidiOutEvents[k].data));
const uint8_t port = fMidiOutEvents[k].port;

if (fMidiOut.count > 1 && port < fMidiOut.count)
fMidiOut.ports[port]->writeMidiEvent(fMidiOutEvents[k].time+timeOffset, channel, fMidiOutEvents[k].size, fMidiOutEvents[k].data);
else
pData->event.portOut->writeMidiEvent(fMidiOutEvents[k].time+timeOffset, channel, fMidiOutEvents[k].size, fMidiOutEvents[k].data);
}
}

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

pData->singleMutex.unlock();
@@ -2351,18 +2358,14 @@ protected:
CARLA_SAFE_ASSERT_RETURN(event != nullptr, false);
CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false);

// reverse-find first free event, and put it there
for (uint32_t i=(kPluginMaxMidiEvents*2)-1; i >= fMidiEventCount; --i)
if (fMidiEventOutCount == kPluginMaxMidiEvents)
{
if (fMidiEvents[i].data[0] != 0)
continue;

std::memcpy(&fMidiEvents[i], event, sizeof(NativeMidiEvent));
return true;
carla_stdout("CarlaPluginNative::handleWriteMidiEvent(%p) - buffer full", event);
return false;
}

carla_stdout("CarlaPluginNative::handleWriteMidiEvent(%p) - buffer full", event);
return false;
std::memcpy(&fMidiOutEvents[fMidiEventOutCount++], event, sizeof(NativeMidiEvent));
return true;
}

void handleUiParameterChanged(const uint32_t index, const float value)
@@ -2564,7 +2567,7 @@ public:

pData->options = 0x0;

if (fDescriptor->midiOuts != 0 || (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS) != 0)
if (fDescriptor->hints & NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS)
pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
else if (options & PLUGIN_OPTION_FIXED_BUFFERS)
pData->options |= PLUGIN_OPTION_FIXED_BUFFERS;
@@ -2614,8 +2617,10 @@ private:

float** fAudioInBuffers;
float** fAudioOutBuffers;
uint32_t fMidiEventCount;
NativeMidiEvent fMidiEvents[kPluginMaxMidiEvents*2];
uint32_t fMidiEventInCount;
uint32_t fMidiEventOutCount;
NativeMidiEvent fMidiInEvents[kPluginMaxMidiEvents];
NativeMidiEvent fMidiOutEvents[kPluginMaxMidiEvents];

int32_t fCurMidiProgs[MAX_MIDI_CHANNELS];
uint32_t fCurBufferSize;


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

@@ -293,7 +293,6 @@ public:
// extra plugin hints
pData->extraHints = 0x0;
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

bufferSizeChanged(pData->engine->getBufferSize());
reloadPrograms(true);


+ 63
- 75
source/backend/plugin/CarlaPluginVST2.cpp View File

@@ -118,7 +118,7 @@ public:

if (fEffect != nullptr)
{
dispatcher(effClose, 0, 0, nullptr, 0.0f);
dispatcher(effClose);
fEffect = nullptr;
}

@@ -161,7 +161,7 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, CarlaPlugin::getCategory());

const intptr_t category(dispatcher(effGetPlugCategory, 0, 0, nullptr, 0.0f));
const intptr_t category = dispatcher(effGetPlugCategory);

switch (category)
{
@@ -209,7 +209,7 @@ public:
*dataPtr = nullptr;

try {
const intptr_t ret = dispatcher(effGetChunk, 0 /* bank */, 0, dataPtr, 0.0f);
const intptr_t ret = dispatcher(effGetChunk, 0 /* bank */, 0, dataPtr);
CARLA_SAFE_ASSERT_RETURN(ret >= 0, 0);
return static_cast<std::size_t>(ret);
} CARLA_SAFE_EXCEPTION_RETURN("CarlaPluginVST2::getChunkData", 0);
@@ -260,7 +260,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,);

strBuf[0] = '\0';
dispatcher(effGetProductString, 0, 0, strBuf, 0.0f);
dispatcher(effGetProductString, 0, 0, strBuf);
}

void getMaker(char* const strBuf) const noexcept override
@@ -268,7 +268,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,);

strBuf[0] = '\0';
dispatcher(effGetVendorString, 0, 0, strBuf, 0.0f);
dispatcher(effGetVendorString, 0, 0, strBuf);
}

void getCopyright(char* const strBuf) const noexcept override
@@ -281,7 +281,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,);

strBuf[0] = '\0';
dispatcher(effGetEffectName, 0, 0, strBuf, 0.0f);
dispatcher(effGetEffectName, 0, 0, strBuf);
}

void getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
@@ -294,7 +294,7 @@ public:
VstParameterProperties prop;
carla_zeroStruct(prop);

if (dispatcher(effGetParameterProperties, static_cast<int32_t>(parameterId), 0, &prop, 0) == 1 && prop.label[0] != '\0')
if (dispatcher(effGetParameterProperties, static_cast<int32_t>(parameterId), 0, &prop) == 1 && prop.label[0] != '\0')
{
std::strncpy(strBuf, prop.label, 64);
strBuf[64] = '\0';
@@ -302,7 +302,7 @@ public:
}

strBuf[0] = '\0';
dispatcher(effGetParamName, static_cast<int32_t>(parameterId), 0, strBuf, 0.0f);
dispatcher(effGetParamName, static_cast<int32_t>(parameterId), 0, strBuf);
}

void getParameterText(const uint32_t parameterId, char* const strBuf) noexcept override
@@ -311,7 +311,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);

strBuf[0] = '\0';
dispatcher(effGetParamDisplay, static_cast<int32_t>(parameterId), 0, strBuf, 0.0f);
dispatcher(effGetParamDisplay, static_cast<int32_t>(parameterId), 0, strBuf);

if (strBuf[0] == '\0')
std::snprintf(strBuf, STR_MAX, "%f", getParameterValue(parameterId));
@@ -323,7 +323,7 @@ public:
CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);

strBuf[0] = '\0';
dispatcher(effGetParamLabel, static_cast<int32_t>(parameterId), 0, strBuf, 0.0f);
dispatcher(effGetParamLabel, static_cast<int32_t>(parameterId), 0, strBuf);
}

// -------------------------------------------------------------------
@@ -391,7 +391,7 @@ public:

{
const ScopedSingleProcessLocker spl(this, true);
dispatcher(effSetChunk, 0 /* bank */, static_cast<intptr_t>(dataSize), fLastChunk, 0.0f);
dispatcher(effSetChunk, 0 /* bank */, static_cast<intptr_t>(dataSize), fLastChunk);
}

// simulate an updateDisplay callback
@@ -414,19 +414,19 @@ public:
if (index >= 0)
{
try {
dispatcher(effBeginSetProgram, 0, 0, nullptr, 0.0f);
dispatcher(effBeginSetProgram);
} CARLA_SAFE_EXCEPTION_RETURN("effBeginSetProgram",);

{
const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));

try {
dispatcher(effSetProgram, 0, index, nullptr, 0.0f);
dispatcher(effSetProgram, 0, index);
} CARLA_SAFE_EXCEPTION("effSetProgram");
}

try {
dispatcher(effEndSetProgram, 0, 0, nullptr, 0.0f);
dispatcher(effEndSetProgram);
} CARLA_SAFE_EXCEPTION("effEndSetProgram");
}

@@ -439,15 +439,15 @@ public:
CARLA_SAFE_ASSERT_RETURN(uindex < pData->prog.count,);

try {
dispatcher(effBeginSetProgram, 0, 0, nullptr, 0.0f);
dispatcher(effBeginSetProgram);
} CARLA_SAFE_EXCEPTION_RETURN("effBeginSetProgram",);

try {
dispatcher(effSetProgram, 0, static_cast<intptr_t>(uindex), nullptr, 0.0f);
dispatcher(effSetProgram, 0, static_cast<intptr_t>(uindex));
} CARLA_SAFE_EXCEPTION("effSetProgram");

try {
dispatcher(effEndSetProgram, 0, 0, nullptr, 0.0f);
dispatcher(effEndSetProgram);
} CARLA_SAFE_EXCEPTION("effEndSetProgram");

CarlaPlugin::setProgramRT(uindex);
@@ -466,9 +466,8 @@ public:
CarlaString uiTitle(pData->name);
uiTitle += " (GUI)";

intptr_t value = 0;
void* vstPtr = nullptr;
ERect* vstRect = nullptr;
intptr_t value = 0;
ERect* vstRect = nullptr;

if (fUI.window == nullptr)
{
@@ -491,18 +490,13 @@ public:
fUI.window->setTitle(uiTitle.buffer());
}

vstPtr = fUI.window->getPtr();

dispatcher(effEditGetRect, 0, 0, &vstRect, 0.0f);

#ifdef HAVE_X11
value = (intptr_t)fUI.window->getDisplay();
#endif

if (dispatcher(effEditOpen, 0, value, vstPtr, 0.0f) != 0)
if (dispatcher(effEditOpen, 0, value, fUI.window->getPtr()) != 0)
{
if (vstRect == nullptr || vstRect->right - vstRect->left < 2)
dispatcher(effEditGetRect, 0, 0, &vstRect, 0.0f);
dispatcher(effEditGetRect, 0, 0, &vstRect);

if (vstRect != nullptr)
{
@@ -534,14 +528,14 @@ public:
CARLA_SAFE_ASSERT_RETURN(fUI.window != nullptr,);
fUI.window->hide();

dispatcher(effEditClose, 0, 0, nullptr, 0.0f);
dispatcher(effEditClose);
}
}

void idle() override
{
if (fNeedIdle)
dispatcher(effIdle, 0, 0, nullptr, 0.0f);
dispatcher(effIdle);

CarlaPlugin::idle();
}
@@ -553,7 +547,7 @@ public:
fUI.window->idle();

if (fUI.isVisible)
dispatcher(effEditIdle, 0, 0, nullptr, 0.0f);
dispatcher(effEditIdle);
}

CarlaPlugin::uiIdle();
@@ -690,7 +684,7 @@ public:
double vrange[2] = { 0.0, 1.0 };
bool isInteger = false;

if (static_cast<uintptr_t>(dispatcher(effVendorSpecific, static_cast<int32_t>(0xdeadbef0), ij, vrange, 0.0f)) >= 0xbeef)
if (static_cast<uintptr_t>(dispatcher(effVendorSpecific, static_cast<int32_t>(0xdeadbef0), ij, vrange)) >= 0xbeef)
{
min = static_cast<float>(vrange[0]);
max = static_cast<float>(vrange[1]);
@@ -708,7 +702,7 @@ public:

// only use values as integer if we have a proper range
if (max - min >= 1.0f)
isInteger = dispatcher(effVendorSpecific, kVstParameterUsesIntStep, ij, nullptr, 0.0f) >= 0xbeef;
isInteger = dispatcher(effVendorSpecific, kVstParameterUsesIntStep, ij) >= 0xbeef;
}
else
{
@@ -730,7 +724,7 @@ public:
stepLarge = range/10.0f;
}
}
else if (dispatcher(effGetParameterProperties, ij, 0, &prop, 0) == 1)
else if (dispatcher(effGetParameterProperties, ij, 0, &prop) == 1)
{
#if 0
if (prop.flags & kVstParameterUsesIntegerMinMax)
@@ -799,7 +793,7 @@ public:
pData->param.data[j].hints |= PARAMETER_IS_ENABLED;
pData->param.data[j].hints |= PARAMETER_USES_CUSTOM_TEXT;

if ((pData->hints & PLUGIN_USES_OLD_VSTSDK) != 0 || dispatcher(effCanBeAutomated, ij, 0, nullptr, 0.0f) == 1)
if ((pData->hints & PLUGIN_USES_OLD_VSTSDK) != 0 || dispatcher(effCanBeAutomated, ij) == 1)
pData->param.data[j].hints |= PARAMETER_IS_AUTOMABLE;

// no such thing as VST default parameters
@@ -851,7 +845,7 @@ public:
}

// plugin hints
const intptr_t vstCategory = dispatcher(effGetPlugCategory, 0, 0, nullptr, 0.0f);
const intptr_t vstCategory = dispatcher(effGetPlugCategory);

pData->hints = 0x0;

@@ -864,7 +858,7 @@ public:
pData->hints |= PLUGIN_NEEDS_UI_MAIN_THREAD;
}

if (dispatcher(effGetVstVersion, 0, 0, nullptr, 0.0f) < kVstVersion)
if (dispatcher(effGetVstVersion) < kVstVersion)
pData->hints |= PLUGIN_USES_OLD_VSTSDK;

if ((fEffect->flags & effFlagsCanReplacing) != 0 && fEffect->processReplacing != fEffect->process)
@@ -891,9 +885,6 @@ public:
if (mOuts > 0)
pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_OUT;

if (aIns <= 2 && aOuts <= 2 && (aIns == aOuts || aIns == 0 || aOuts == 0))
pData->extraHints |= PLUGIN_EXTRA_HINT_CAN_RUN_RACK;

// dummy pre-start to get latency and wantEvents() on old plugins
{
activate();
@@ -966,7 +957,7 @@ public:
if (newCount > 0)
setProgram(0, false, false, false, true);
else
dispatcher(effSetProgram, 0, 0, nullptr, 0.0f);
dispatcher(effSetProgram);
}
else
{
@@ -1025,21 +1016,20 @@ public:
{
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,);

dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);

dispatcher(effSetBlockSizeAndSampleRate, 0,
static_cast<int32_t>(pData->engine->getBufferSize()), nullptr,
static_cast<float>(pData->engine->getSampleRate()));
const int32_t iBufferSize = static_cast<int32_t>(pData->engine->getBufferSize());
const float fSampleRate = static_cast<float>(pData->engine->getSampleRate());

dispatcher(effSetSampleRate, 0, 0, nullptr, static_cast<float>(pData->engine->getSampleRate()));
dispatcher(effSetBlockSize, 0, static_cast<int32_t>(pData->engine->getBufferSize()), nullptr, 0.0f);
dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32);
dispatcher(effSetBlockSizeAndSampleRate, 0, iBufferSize, nullptr, fSampleRate);
dispatcher(effSetSampleRate, 0, 0, nullptr, fSampleRate);
dispatcher(effSetBlockSize, 0, iBufferSize);

try {
dispatcher(effMainsChanged, 0, 1, nullptr, 0.0f);
dispatcher(effMainsChanged, 0, 1);
} catch(...) {}

try {
dispatcher(effStartProcess, 0, 0, nullptr, 0.0f);
dispatcher(effStartProcess, 0, 0);
} catch(...) {}
}

@@ -1048,11 +1038,11 @@ public:
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr,);

try {
dispatcher(effStopProcess, 0, 0, nullptr, 0.0f);
dispatcher(effStopProcess);
} catch(...) {}

try {
dispatcher(effMainsChanged, 0, 0, nullptr, 0.0f);
dispatcher(effMainsChanged);
} catch(...) {}
}

@@ -1138,7 +1128,7 @@ public:

const double ppqBar = double(timeInfo.bbt.bar - 1) * timeInfo.bbt.beatsPerBar;
const double ppqBeat = double(timeInfo.bbt.beat - 1);
const double ppqTick = double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat;
const double ppqTick = timeInfo.bbt.tick / timeInfo.bbt.ticksPerBeat;

// PPQ Pos
fTimeInfo.ppqPos = ppqBar + ppqBeat + ppqTick;
@@ -1750,7 +1740,7 @@ protected:

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

intptr_t dispatcher(int32_t opcode, int32_t index, intptr_t value, void* ptr, float opt) const noexcept
intptr_t dispatcher(int32_t opcode, int32_t index = 0, intptr_t value = 0, void* ptr = nullptr, float opt = 0.0f) const noexcept
{
CARLA_SAFE_ASSERT_RETURN(fEffect != nullptr, 0);
#ifdef DEBUG
@@ -1920,8 +1910,8 @@ protected:

if (m_active)
{
effect->dispatcher(effect, effStopProcess, 0, 0, nullptr, 0.0f);
effect->dispatcher(effect, effMainsChanged, 0, 0, nullptr, 0.0f);
effect->dispatcher(effect, effStopProcess);
effect->dispatcher(effect, effMainsChanged, 0, 0);
}

reload();
@@ -1929,7 +1919,7 @@ protected:
if (m_active)
{
effect->dispatcher(effect, effMainsChanged, 0, 1, nullptr, 0.0f);
effect->dispatcher(effect, effStartProcess, 0, 0, nullptr, 0.0f);
effect->dispatcher(effect, effStartProcess);
}

x_engine->callback(CALLBACK_RELOAD_ALL, m_id, 0, 0, 0.0, nullptr);
@@ -2051,17 +2041,17 @@ protected:
case audioMasterUpdateDisplay:
// Idle UI if visible
if (fUI.isVisible)
dispatcher(effEditIdle, 0, 0, nullptr, 0.0f);
dispatcher(effEditIdle);

// Update current program
if (pData->prog.count > 0)
{
const int32_t current = static_cast<int32_t>(dispatcher(effGetProgram, 0, 0, nullptr, 0.0f));
const int32_t current = static_cast<int32_t>(dispatcher(effGetProgram));

if (current >= 0 && current < static_cast<int32_t>(pData->prog.count))
{
char strBuf[STR_MAX+1] = { '\0' };
dispatcher(effGetProgramName, 0, 0, strBuf, 0.0f);
dispatcher(effGetProgramName, 0, 0, strBuf);

if (pData->prog.names[current] != nullptr)
delete[] pData->prog.names[current];
@@ -2121,7 +2111,7 @@ protected:
bool canDo(const char* const feature) const noexcept
{
try {
return (fEffect->dispatcher(fEffect, effCanDo, 0, 0, const_cast<char*>(feature), 0.0f) == 1);
return (dispatcher(effCanDo, 0, 0, const_cast<char*>(feature)) == 1);
} CARLA_SAFE_EXCEPTION_RETURN("vstPluginCanDo", false);
}

@@ -2260,18 +2250,16 @@ public:

fEffect->ptr1 = this;

dispatcher(effIdentify, 0, 0, 0, 0);

dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32, nullptr, 0.0f);

dispatcher(effSetBlockSizeAndSampleRate, 0,
static_cast<int32_t>(pData->engine->getBufferSize()), nullptr,
static_cast<float>(pData->engine->getSampleRate()));
const int32_t iBufferSize = static_cast<int32_t>(pData->engine->getBufferSize());
const float fSampleRate = static_cast<float>(pData->engine->getSampleRate());

dispatcher(effSetSampleRate, 0, 0, nullptr, static_cast<float>(pData->engine->getSampleRate()));
dispatcher(effSetBlockSize, 0, static_cast<int32_t>(pData->engine->getBufferSize()), nullptr, 0.0f);
dispatcher(effIdentify);
dispatcher(effSetProcessPrecision, 0, kVstProcessPrecision32);
dispatcher(effSetBlockSizeAndSampleRate, 0, iBufferSize, nullptr, fSampleRate);
dispatcher(effSetSampleRate, 0, 0, nullptr, fSampleRate);
dispatcher(effSetBlockSize, 0, iBufferSize);

dispatcher(effOpen, 0, 0, nullptr, 0.0f);
dispatcher(effOpen);

// ---------------------------------------------------------------
// get info
@@ -2284,7 +2272,7 @@ public:
{
char strBuf[STR_MAX+1];
carla_zeroChars(strBuf, STR_MAX+1);
dispatcher(effGetEffectName, 0, 0, strBuf, 0.0f);
dispatcher(effGetEffectName, 0, 0, strBuf);

if (strBuf[0] != '\0')
pData->name = pData->engine->getUniquePluginName(strBuf);
@@ -2310,15 +2298,15 @@ public:
// ---------------------------------------------------------------
// initialize plugin (part 2)

for (int i = fEffect->numInputs; --i >= 0;) dispatcher(effConnectInput, i, 1, 0, 0);
for (int i = fEffect->numOutputs; --i >= 0;) dispatcher(effConnectOutput, i, 1, 0, 0);
for (int i = fEffect->numInputs; --i >= 0;) dispatcher(effConnectInput, i, 1);
for (int i = fEffect->numOutputs; --i >= 0;) dispatcher(effConnectOutput, i, 1);

if (dispatcher(effGetVstVersion, 0, 0, nullptr, 0.0f) < kVstVersion)
if (dispatcher(effGetVstVersion) < kVstVersion)
pData->hints |= PLUGIN_USES_OLD_VSTSDK;

static const char kHasCockosExtensions[] = "hasCockosExtensions";

if (static_cast<uintptr_t>(dispatcher(effCanDo, 0, 0, const_cast<char*>(kHasCockosExtensions), 0.0f)) == 0xbeef0000)
if (static_cast<uintptr_t>(dispatcher(effCanDo, 0, 0, const_cast<char*>(kHasCockosExtensions))) == 0xbeef0000)
pData->hints |= PLUGIN_HAS_COCKOS_EXTENSIONS;

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


+ 2
- 7
source/bridges-plugin/Makefile View File

@@ -24,7 +24,6 @@ endif

BUILD_CXX_FLAGS += -DBUILD_BRIDGE -I. -I$(CWD) -I$(CWD)/backend -I$(CWD)/includes -I$(CWD)/modules -I$(CWD)/utils
BUILD_CXX_FLAGS += -I$(CWD)/backend/engine -I$(CWD)/backend/plugin
BUILD_CXX_FLAGS += $(LIBLO_FLAGS)

32BIT_FLAGS += -DBUILD_BRIDGE_ALTERNATIVE_ARCH
64BIT_FLAGS += -DBUILD_BRIDGE_ALTERNATIVE_ARCH
@@ -64,13 +63,12 @@ LIBS_win32 += $(MODULEDIR)/water.win32.a
LIBS_win64 += $(MODULEDIR)/water.win64.a
LINK_FLAGS += $(WATER_LIBS)

LINK_FLAGS += $(LIBLO_LIBS)
LINK_FLAGS += $(X11_LIBS)

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

NATIVE_BUILD_FLAGS = $(NATIVE_PLUGINS_FLAGS)
NATIVE_LINK_FLAGS =
NATIVE_BUILD_FLAGS = $(NATIVE_PLUGINS_FLAGS) $(LIBLO_FLAGS)
NATIVE_LINK_FLAGS = $(LIBLO_LIBS)

NATIVE_BUILD_FLAGS += $(FLUIDSYNTH_FLAGS)
NATIVE_LINK_FLAGS += $(FLUIDSYNTH_LIBS)
@@ -126,8 +124,6 @@ OBJS_arch = \
$(OBJDIR)/CarlaEngineClient.cpp.arch.o \
$(OBJDIR)/CarlaEngineData.cpp.arch.o \
$(OBJDIR)/CarlaEngineInternal.cpp.arch.o \
$(OBJDIR)/CarlaEngineOsc.cpp.arch.o \
$(OBJDIR)/CarlaEngineOscSend.cpp.arch.o \
$(OBJDIR)/CarlaEnginePorts.cpp.arch.o \
$(OBJDIR)/CarlaEngineThread.cpp.arch.o \
$(OBJDIR)/CarlaEngineJack.cpp.arch.o \
@@ -135,7 +131,6 @@ OBJS_arch = \
$(OBJDIR)/CarlaPlugin.cpp.arch.o \
$(OBJDIR)/CarlaPluginBridge.cpp.arch.o \
$(OBJDIR)/CarlaPluginInternal.cpp.arch.o \
$(OBJDIR)/CarlaPluginJack.cpp.arch.o \
$(OBJDIR)/CarlaPluginLADSPA.cpp.arch.o \
$(OBJDIR)/CarlaPluginDSSI.cpp.arch.o \
$(OBJDIR)/CarlaPluginLV2.cpp.arch.o \


+ 0
- 1
source/carla_backend.pro View File

@@ -24,7 +24,6 @@ DEFINES += HAVE_ZYN_UI_DEPS
PKGCONFIG += liblo
PKGCONFIG += fftw3
PKGCONFIG += fluidsynth
PKGCONFIG += linuxsampler
PKGCONFIG += mxml
PKGCONFIG += zlib



+ 6
- 9
source/carla_database.py View File

@@ -191,8 +191,13 @@ def runCarlaDiscovery(itype, stype, filename, tool, wineSettings=None):
else:
winePrefix = os.path.expanduser("~/.wine")

wineCMD = wineSettings['executable'] if wineSettings['executable'] else "wine"

if tool.endswith("64.exe"):
wineCMD += "64"

command.append("WINEPREFIX=" + winePrefix)
command.append(wineSettings['executable'] if wineSettings['executable'] else "wine")
command.append(wineCMD)

command.append(tool)
command.append(stype)
@@ -465,14 +470,6 @@ class SearchPluginsThread(QThread):
else:
self.fCheckLV2 = False

# Special case for AU, only search native and posix32
if self.fCheckAU:
if self.fCheckNative or self.fCheckPosix32:
if self.fCheckNative: self.fCurCount += 1
if self.fCheckPosix32: self.fCurCount += 1
else:
self.fCheckAU = False

# Special case for Sound Kits, only search native
if self.fCheckNative and self.fToolNative:
if self.fCheckSF2: self.fCurCount += 1


+ 2
- 2
source/includes/CarlaNative.h View File

@@ -157,8 +157,8 @@ typedef struct {

int32_t bar; /** current bar */
int32_t beat; /** current beat-within-bar */
int32_t tick; /** current tick-within-beat */
double barStartTick;
double tick; /** current tick-within-beat */
double barStartTick;

float beatsPerBar; /** time signature "numerator" */
float beatType; /** time signature "denominator" */


+ 6
- 6
source/jackbridge/Makefile View File

@@ -10,14 +10,14 @@ include ../modules/Makefile.mk

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

WINECXX ?= wineg++
WINECC ?= winegcc

BUILD_CXX_FLAGS += $(JACKBRIDGE_FLAGS)
LINK_FLAGS += $(JACKBRIDGE_LIBS)

WINE_32BIT_FLAGS = $(32BIT_FLAGS)
WINE_64BIT_FLAGS = $(64BIT_FLAGS)
WINE_LINK_FLAGS = $(LINK_FLAGS) $(LIBDL_LIBS) -lpthread
WINE_LINK_FLAGS = $(LINK_FLAGS) $(LIBDL_LIBS) -lpthread -lstdc++

ifneq ($(MACOS),true)
WINE_32BIT_FLAGS += -I/usr/include/wine/wine/windows
@@ -151,12 +151,12 @@ $(MODULEDIR)/$(MODULENAME).win64e.a: $(OBJS_win64e)
$(MODULEDIR)/$(MODULENAME)-wine32.dll$(LIB_EXT): $(OBJS_wine32) JackBridgeExport.def
-@mkdir -p $(MODULEDIR)
@echo "Linking $(MODULENAME)-wine32.dll$(LIB_EXT)"
@$(WINECXX) $^ $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) $(SHARED) -o $@
@$(WINECC) $^ $(WINE_32BIT_FLAGS) $(WINE_LINK_FLAGS) $(SHARED) -o $@

$(MODULEDIR)/$(MODULENAME)-wine64.dll$(LIB_EXT): $(OBJS_wine64) JackBridgeExport.def
-@mkdir -p $(MODULEDIR)
@echo "Linking $(MODULENAME)-wine64.dll$(LIB_EXT)"
@$(WINECXX) $^ $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) $(SHARED) -o $@
@$(WINECC) $^ $(WINE_64BIT_FLAGS) $(WINE_LINK_FLAGS) $(SHARED) -o $@

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

@@ -207,12 +207,12 @@ $(OBJDIR)/%.cpp.win64.o: %.cpp
$(OBJDIR)/%.cpp.wine32.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (wine32)"
@$(WINECXX) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -c -o $@
@$(WINECC) $< $(BUILD_CXX_FLAGS) $(32BIT_FLAGS) -c -o $@

$(OBJDIR)/%.cpp.wine64.o: %.cpp
-@mkdir -p $(OBJDIR)
@echo "Compiling $< (wine64)"
@$(WINECXX) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@
@$(WINECC) $< $(BUILD_CXX_FLAGS) $(64BIT_FLAGS) -c -o $@

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



+ 1
- 1
source/libjack/libjack.cpp View File

@@ -602,7 +602,7 @@ bool CarlaJackAppClient::handleRtData()

fServer.position.bar = bridgeTimeInfo.bar;
fServer.position.beat = bridgeTimeInfo.beat;
fServer.position.tick = bridgeTimeInfo.tick;
fServer.position.tick = static_cast<int32_t>(bridgeTimeInfo.tick + 0.5);

fServer.position.beats_per_bar = bridgeTimeInfo.beatsPerBar;
fServer.position.beat_type = bridgeTimeInfo.beatType;


+ 61
- 168
source/modules/rtaudio/RtAudio.cpp View File

@@ -222,11 +222,12 @@ void RtAudio :: openStream( RtAudio::StreamParameters *outputParameters,
unsigned int *bufferFrames,
RtAudioCallback callback, void *userData,
RtAudio::StreamOptions *options,
RtAudioBufferSizeCallback bufSizeCallback,
RtAudioErrorCallback errorCallback )
{
return rtapi_->openStream( outputParameters, inputParameters, format,
sampleRate, bufferFrames, callback,
userData, options, errorCallback );
userData, options, bufSizeCallback, errorCallback );
}

// *************************************************** //
@@ -259,6 +260,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,
unsigned int *bufferFrames,
RtAudioCallback callback, void *userData,
RtAudio::StreamOptions *options,
RtAudioBufferSizeCallback bufSizeCallback,
RtAudioErrorCallback errorCallback )
{
if ( stream_.state != STREAM_CLOSED ) {
@@ -340,6 +342,7 @@ void RtApi :: openStream( RtAudio::StreamParameters *oParams,

stream_.callbackInfo.callback = (void *) callback;
stream_.callbackInfo.userData = userData;
stream_.callbackInfo.bufSizeCallback = (void *) bufSizeCallback;
stream_.callbackInfo.errorCallback = (void *) errorCallback;

if ( options ) options->numberOfBuffers = stream_.nBuffers;
@@ -1936,7 +1939,6 @@ const char* RtApiCore :: getErrorCode( OSStatus code )
struct JackHandle {
jack_client_t *client;
jack_port_t **ports[2];
std::string deviceName[2];
bool xrun[2];
pthread_cond_t condition;
int drainCounter; // Tracks callback counts when draining
@@ -1958,128 +1960,40 @@ RtApiJack :: ~RtApiJack()

unsigned int RtApiJack :: getDeviceCount( void )
{
// See if we can become a jack client.
jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption;
jack_status_t *status = NULL;
jack_client_t *client = jackbridge_client_open( "CarlaJackCount", options, status );
if ( client == 0 ) return 0;

const char **ports;
std::string port, previousPort;
unsigned int nChannels = 0, nDevices = 0;
ports = jackbridge_get_ports( client, NULL, NULL, 0 );
if ( ports ) {
// Parse the port names up to the first colon (:).
size_t iColon = 0;
do {
port = (char *) ports[ nChannels ];
iColon = port.find(":");
if ( iColon != std::string::npos ) {
port = port.substr( 0, iColon + 1 );
if ( port != previousPort ) {
nDevices++;
previousPort = port;
}
}
} while ( ports[++nChannels] );
jackbridge_free( ports );
}

jackbridge_client_close( client );
return nDevices;
return 2;
}

RtAudio::DeviceInfo RtApiJack :: getDeviceInfo( unsigned int device )
{
RtAudio::DeviceInfo info;
info.probed = false;
static RtAudio::DeviceInfo devInfo[3];

jack_options_t options = (jack_options_t) ( JackNoStartServer ); //JackNullOption
jack_status_t *status = NULL;
jack_client_t *client = jackbridge_client_open( "CarlaJackInfo", options, status );
if ( client == 0 ) {
errorText_ = "RtApiJack::getDeviceInfo: Jack server not found or connection error!";
error( RtAudioError::WARNING );
return info;
}

const char **ports;
std::string port, previousPort;
unsigned int nPorts = 0, nDevices = 0;
ports = jackbridge_get_ports( client, NULL, NULL, 0 );
if ( ports ) {
// Parse the port names up to the first colon (:).
size_t iColon = 0;
do {
port = (char *) ports[ nPorts ];
iColon = port.find(":");
if ( iColon != std::string::npos ) {
port = port.substr( 0, iColon );
if ( port != previousPort ) {
if ( nDevices == device ) info.name = port;
nDevices++;
previousPort = port;
}
}
} while ( ports[++nPorts] );
jackbridge_free( ports );
}

if ( device >= nDevices ) {
jackbridge_client_close( client );
errorText_ = "RtApiJack::getDeviceInfo: device ID is invalid!";
error( RtAudioError::INVALID_USE );
return info;
}

// Get the current jack server sample rate.
info.sampleRates.clear();

info.preferredSampleRate = jackbridge_get_sample_rate( client );
info.sampleRates.push_back( info.preferredSampleRate );

// Count the available ports containing the client name as device
// channels. Jack "input ports" equal RtAudio output channels.
unsigned int nChannels = 0;
ports = jackbridge_get_ports( client, info.name.c_str(), NULL, JackPortIsInput );
if ( ports ) {
while ( ports[ nChannels ] ) nChannels++;
jackbridge_free( ports );
info.outputChannels = nChannels;
}

// Jack "output ports" equal RtAudio input channels.
nChannels = 0;
ports = jackbridge_get_ports( client, info.name.c_str(), NULL, JackPortIsOutput );
if ( ports ) {
while ( ports[ nChannels ] ) nChannels++;
jackbridge_free( ports );
info.inputChannels = nChannels;
if (! devInfo[0].probed)
{
devInfo[0].probed = devInfo[1].probed = true;
devInfo[0].outputChannels = devInfo[1].outputChannels = 2;
devInfo[0].inputChannels = devInfo[1].inputChannels = 2;
devInfo[0].duplexChannels = devInfo[1].duplexChannels = 2;
devInfo[0].isDefaultOutput = devInfo[1].isDefaultOutput = true;
devInfo[0].isDefaultInput = devInfo[1].isDefaultInput = true;
devInfo[0].nativeFormats = devInfo[1].nativeFormats = RTAUDIO_FLOAT32;
devInfo[0].name = "Auto-connect ON";
devInfo[1].name = "Auto-connect OFF";
}

if ( info.outputChannels == 0 && info.inputChannels == 0 ) {
jackbridge_client_close(client);
errorText_ = "RtApiJack::getDeviceInfo: error determining Jack input/output channels!";
error( RtAudioError::WARNING );
return info;
}
if (device > 2)
device = 2;

// If device opens for both playback and capture, we determine the channels.
if ( info.outputChannels > 0 && info.inputChannels > 0 )
info.duplexChannels = (info.outputChannels > info.inputChannels) ? info.inputChannels : info.outputChannels;
return devInfo[device];
}

// Jack always uses 32-bit floats.
info.nativeFormats = RTAUDIO_FLOAT32;
static int jackBufferSizeHandler( jack_nframes_t nframes, void *infoPointer )
{
CallbackInfo *info = (CallbackInfo *) infoPointer;

// Jack doesn't provide default devices so we'll use the first available one.
if ( device == 0 && info.outputChannels > 0 )
info.isDefaultOutput = true;
if ( device == 0 && info.inputChannels > 0 )
info.isDefaultInput = true;
RtApiJack *object = (RtApiJack *) info->object;
if ( object->bufferSizeEvent( (unsigned long) nframes ) == false ) return 1;

jackbridge_client_close(client);
info.probed = true;
return info;
return 0;
}

static int jackCallbackHandler( jack_nframes_t nframes, void *infoPointer )
@@ -2149,7 +2063,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
if ( options && !options->streamName.empty() )
client = jackbridge_client_open( options->streamName.c_str(), jackoptions, status );
else
client = jackbridge_client_open( "CarlaJack", jackoptions, status );
client = jackbridge_client_open( "Carla", jackoptions, status );
if ( client == 0 ) {
errorText_ = "RtApiJack::probeDeviceOpen: Jack server not found or connection error!";
error( RtAudioError::WARNING );
@@ -2161,51 +2075,6 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
client = handle->client;
}

const char **ports;
std::string port, previousPort, deviceName;
unsigned int nPorts = 0, nDevices = 0;
ports = jackbridge_get_ports( client, NULL, NULL, 0 );
if ( ports ) {
// Parse the port names up to the first colon (:).
size_t iColon = 0;
do {
port = (char *) ports[ nPorts ];
iColon = port.find(":");
if ( iColon != std::string::npos ) {
port = port.substr( 0, iColon );
if ( port != previousPort ) {
if ( nDevices == device ) deviceName = port;
nDevices++;
previousPort = port;
}
}
} while ( ports[++nPorts] );
jackbridge_free( ports );
}

if ( device >= nDevices ) {
errorText_ = "RtApiJack::probeDeviceOpen: device ID is invalid!";
return FAILURE;
}

// Count the available ports containing the client name as device
// channels. Jack "input ports" equal RtAudio output channels.
unsigned int nChannels = 0;
unsigned long flag = JackPortIsInput;
if ( mode == INPUT ) flag = JackPortIsOutput;
ports = jackbridge_get_ports( client, deviceName.c_str(), NULL, flag );
if ( ports ) {
while ( ports[ nChannels ] ) nChannels++;
jackbridge_free( ports );
}

// Compare the jack ports for specified client to the requested number of channels.
if ( nChannels < (channels + firstChannel) ) {
errorStream_ << "RtApiJack::probeDeviceOpen: requested number of channels (" << channels << ") + offset (" << firstChannel << ") not found for specified device (" << device << ":" << deviceName << ").";
errorText_ = errorStream_.str();
return FAILURE;
}

// Check the jack server sample rate.
unsigned int jackRate = jackbridge_get_sample_rate( client );
if ( sampleRate != jackRate ) {
@@ -2214,7 +2083,8 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
stream_.sampleRate = jackRate;

// Get the latency of the JACK port.
ports = jackbridge_get_ports( client, deviceName.c_str(), NULL, flag );
const char **ports;
ports = jackbridge_get_ports( client, "system:", NULL, JackPortIsInput );
if ( ports[ firstChannel ] ) {
// Added by Ge Wang
jack_latency_callback_mode_t cbmode = (mode == INPUT ? JackCaptureLatency : JackPlaybackLatency);
@@ -2274,11 +2144,10 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
stream_.apiHandle = (void *) handle;
handle->client = client;
}
handle->deviceName[mode] = deviceName;

// Allocate necessary internal buffers.
unsigned long bufferBytes;
bufferBytes = stream_.nUserChannels[mode] * *bufferSize * formatBytes( stream_.userFormat );
bufferBytes = stream_.nUserChannels[mode] * 8192 * formatBytes( stream_.userFormat );
stream_.userBuffer[mode] = (char *) calloc( bufferBytes, 1 );
if ( stream_.userBuffer[mode] == NULL ) {
errorText_ = "RtApiJack::probeDeviceOpen: error allocating user buffer memory.";
@@ -2299,7 +2168,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
}

if ( makeBuffer ) {
bufferBytes *= *bufferSize;
bufferBytes *= 8192;
if ( stream_.deviceBuffer ) free( stream_.deviceBuffer );
stream_.deviceBuffer = (char *) calloc( bufferBytes, 1 );
if ( stream_.deviceBuffer == NULL ) {
@@ -2326,6 +2195,7 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
stream_.mode = DUPLEX;
else {
stream_.mode = mode;
jackbridge_set_buffer_size_callback( handle->client, jackBufferSizeHandler, (void *) &stream_.callbackInfo );
jackbridge_set_process_callback( handle->client, jackCallbackHandler, (void *) &stream_.callbackInfo );
jackbridge_set_xrun_callback( handle->client, jackXrun, (void *) &stream_.apiHandle );
jackbridge_on_shutdown( handle->client, jackShutdown, (void *) &stream_.callbackInfo );
@@ -2348,6 +2218,9 @@ bool RtApiJack :: probeDeviceOpen( unsigned int device, StreamMode mode, unsigne
}
}

// auto-connect "device" is #1
shouldAutoconnect_ = device == 0;

// Setup the buffer conversion information structure. We don't use
// buffers to do channel offsets, so we override that parameter
// here.
@@ -2446,7 +2319,7 @@ void RtApiJack :: startStream( void )
// Get the list of available ports.
if ( shouldAutoconnect_ && (stream_.mode == OUTPUT || stream_.mode == DUPLEX) ) {
result = false;
ports = jackbridge_get_ports( handle->client, handle->deviceName[0].c_str(), NULL, JackPortIsInput);
ports = jackbridge_get_ports( handle->client, "system:", NULL, JackPortIsInput);
if ( ports == NULL) {
errorText_ = "RtApiJack::startStream(): error determining available JACK input ports!";
goto unlock;
@@ -2470,7 +2343,7 @@ void RtApiJack :: startStream( void )

if ( shouldAutoconnect_ && (stream_.mode == INPUT || stream_.mode == DUPLEX) ) {
result = false;
ports = jackbridge_get_ports( handle->client, handle->deviceName[1].c_str(), NULL, JackPortIsOutput );
ports = jackbridge_get_ports( handle->client, "system:", NULL, JackPortIsOutput );
if ( ports == NULL) {
errorText_ = "RtApiJack::startStream(): error determining available JACK output ports!";
goto unlock;
@@ -2560,8 +2433,8 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
error( RtAudioError::WARNING );
return FAILURE;
}
if ( stream_.bufferSize != nframes ) {
errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size has changed ... cannot process!";
if ( nframes > 8192 ) {
errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size is too big ... cannot process!";
error( RtAudioError::WARNING );
return FAILURE;
}
@@ -2595,7 +2468,7 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
handle->xrun[1] = false;
}
int cbReturnValue = callback( stream_.userBuffer[0], stream_.userBuffer[1],
stream_.bufferSize, streamTime, status, info->userData );
nframes, streamTime, status, info->userData );
if ( cbReturnValue == 2 ) {
stream_.state = STREAM_STOPPING;
handle->drainCounter = 2;
@@ -2665,6 +2538,26 @@ bool RtApiJack :: callbackEvent( unsigned long nframes )
RtApi::tickStreamTime();
return SUCCESS;
}

bool RtApiJack :: bufferSizeEvent( unsigned long nframes )
{
if ( stream_.state == STREAM_STOPPED || stream_.state == STREAM_STOPPING ) return SUCCESS;
if ( stream_.state == STREAM_CLOSED ) {
errorText_ = "RtApiCore::callbackEvent(): the stream is closed ... this shouldn't happen!";
error( RtAudioError::WARNING );
return FAILURE;
}
if ( nframes > 8192 ) {
errorText_ = "RtApiCore::callbackEvent(): the JACK buffer size is too big ... cannot process!";
error( RtAudioError::WARNING );
return FAILURE;
}

CallbackInfo *info = (CallbackInfo *) &stream_.callbackInfo;

RtAudioBufferSizeCallback callback = (RtAudioBufferSizeCallback) info->bufSizeCallback;
return callback( nframes, info->userData );
}
//******************** End of __UNIX_JACK__ *********************//
#endif



+ 12
- 2
source/modules/rtaudio/RtAudio.h View File

@@ -246,6 +246,9 @@ class RTAUDIO_DLL_PUBLIC RtAudioError : public std::runtime_error
*/
typedef void (*RtAudioErrorCallback)( RtAudioError::Type type, const std::string &errorText );

//! RtAudio buffer size change callback.
typedef bool (*RtAudioBufferSizeCallback)( unsigned int bufferSize, void* userData );

// **************************************************************** //
//
// RtAudio class declaration.
@@ -494,7 +497,9 @@ class RTAUDIO_DLL_PUBLIC RtAudio
RtAudio::StreamParameters *inputParameters,
RtAudioFormat format, unsigned int sampleRate,
unsigned int *bufferFrames, RtAudioCallback callback,
void *userData = NULL, RtAudio::StreamOptions *options = NULL, RtAudioErrorCallback errorCallback = NULL );
void *userData = NULL, RtAudio::StreamOptions *options = NULL,
RtAudioBufferSizeCallback bufSizeCallback = NULL,
RtAudioErrorCallback errorCallback = NULL );

//! A function that closes a stream and frees any associated stream memory.
/*!
@@ -611,6 +616,7 @@ struct CallbackInfo {
ThreadHandle thread;
void *callback;
void *userData;
void *bufSizeCallback;
void *errorCallback;
void *apiInfo; // void pointer for API specific callback information
bool isRunning;
@@ -619,7 +625,7 @@ struct CallbackInfo {

// Default constructor.
CallbackInfo()
:object(0), callback(0), userData(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
:object(0), callback(0), userData(0), bufSizeCallback(0), errorCallback(0), apiInfo(0), isRunning(false), doRealtime(false), priority(0) {}
};

// **************************************************************** //
@@ -688,6 +694,7 @@ public:
RtAudioFormat format, unsigned int sampleRate,
unsigned int *bufferFrames, RtAudioCallback callback,
void *userData, RtAudio::StreamOptions *options,
RtAudioBufferSizeCallback bufSizeCallback,
RtAudioErrorCallback errorCallback );
virtual void closeStream( void );
virtual void startStream( void ) = 0;
@@ -909,6 +916,9 @@ public:
// will most likely produce highly undesireable results!
bool callbackEvent( unsigned long nframes );

// Buffer size change callback
bool bufferSizeEvent( unsigned long nframes );

private:

bool probeDeviceOpen( unsigned int device, StreamMode mode, unsigned int channels,


+ 23
- 0
source/native-plugins/_data.base.cpp View File

@@ -164,6 +164,29 @@ static const NativePluginDescriptor sNativePluginDescriptors[] = {
DESCFUNCS
},

// --------------------------------------------------------------------------------------------------------------------
// Audio file

{
/* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
/* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE
|NATIVE_PLUGIN_HAS_UI
|NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE
|NATIVE_PLUGIN_USES_TIME),
/* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING,
/* audioIns */ 0,
/* audioOuts */ 2,
/* midiIns */ 0,
/* midiOuts */ 0,
/* paramIns */ 1,
/* paramOuts */ 0,
/* name */ "Audio File",
/* label */ "audiofile",
/* maker */ "falkTX",
/* copyright */ "GNU GPL v2+",
DESCFUNCS
},

// --------------------------------------------------------------------------------------------------------------------
// MIDI sequencer



+ 120
- 84
source/native-plugins/audio-base.hpp View File

@@ -1,6 +1,6 @@
/*
* Carla Native Plugins
* Copyright (C) 2013-2017 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -29,17 +29,20 @@ typedef struct adinfo ADInfo;

struct AudioFilePool {
float* buffer[2];
uint32_t sampleRate;
uint32_t startFrame;
uint32_t size;

#ifdef CARLA_PROPER_CPP11_SUPPORT
AudioFilePool()
: buffer{nullptr},
sampleRate(0),
startFrame(0),
size(0) {}
#else
AudioFilePool()
: startFrame(0),
sampleRate(0),
size(0)
{
buffer[0] = buffer[1] = nullptr;
@@ -54,14 +57,15 @@ struct AudioFilePool {
CARLA_ASSERT(size == 0);
}

void create(const uint32_t sampleRate)
void create(const uint32_t srate)
{
CARLA_ASSERT(buffer[0] == nullptr);
CARLA_ASSERT(buffer[1] == nullptr);
CARLA_ASSERT(startFrame == 0);
CARLA_ASSERT(size == 0);

size = sampleRate * 2;
size = srate * 8;
sampleRate = srate;

buffer[0] = new float[size];
buffer[1] = new float[size];
@@ -114,9 +118,13 @@ public:
AudioFileThread(AbstractAudioPlayer* const player, const double sampleRate)
: CarlaThread("AudioFileThread"),
kPlayer(player),
fLoopingMode(true),
fNeedsRead(false),
fQuitNow(true),
fFilePtr(nullptr)
fFilePtr(nullptr),
fMaxPlayerFrame(0),
fPollTempData(nullptr),
fPollTempSize(0)
{
CARLA_ASSERT(kPlayer != nullptr);

@@ -139,7 +147,17 @@ public:
CARLA_ASSERT(! isThreadRunning());

if (fFilePtr != nullptr)
{
ad_close(fFilePtr);
fFilePtr = nullptr;
}

if (fPollTempData != nullptr)
{
delete[] fPollTempData;
fPollTempData = nullptr;
fPollTempSize = 0;
}

fPool.destroy();
}
@@ -162,20 +180,25 @@ public:
fPool.reset();
}

uint32_t getMaxFrame() const
uint32_t getMaxFrame() const noexcept
{
return fMaxPlayerFrame;
}

void setLoopingMode(const bool on) noexcept
{
return fFileNfo.frames > 0 ? fFileNfo.frames : 0;
fLoopingMode = on;
}

void setNeedsRead()
void setNeedsRead() noexcept
{
fNeedsRead = true;
}

bool loadFilename(const char* const filename)
{
CARLA_ASSERT(! isThreadRunning());
CARLA_ASSERT(filename != nullptr);
CARLA_SAFE_ASSERT_RETURN(! isThreadRunning(), false);
CARLA_SAFE_ASSERT_RETURN(filename != nullptr && *filename != '\0', false);

fPool.startFrame = 0;

@@ -185,6 +208,13 @@ public:
ad_close(fFilePtr);
fFilePtr = nullptr;
}
if (fPollTempData != nullptr)
{
delete[] fPollTempData;
fPollTempData = nullptr;
fPollTempSize = 0;
fMaxPlayerFrame = 0;
}

ad_clear_nfo(&fFileNfo);

@@ -196,16 +226,30 @@ public:

ad_dump_nfo(99, &fFileNfo);

if (fFileNfo.frames == 0)
carla_stderr("L: filename \"%s\" has 0 frames", filename);

// Fix for misinformation using libsndfile
if (fFileNfo.frames % fFileNfo.channels)
--fFileNfo.frames;

if (fFileNfo.frames <= 0)
carla_stderr("L: filename \"%s\" has 0 frames", filename);

if ((fFileNfo.channels == 1 || fFileNfo.channels == 2) && fFileNfo.frames > 0)
{
// valid
const size_t pollTempSize = std::min(static_cast<uint>(fFileNfo.frames),
fPool.size * fFileNfo.channels);

try {
fPollTempData = new float[pollTempSize];
} catch (...) {
ad_close(fFilePtr);
fFilePtr = nullptr;
return false;
}

fMaxPlayerFrame = fFileNfo.frames/fFileNfo.channels;
fPollTempSize = pollTempSize;

readPoll();
return true;
}
@@ -221,10 +265,8 @@ public:

void tryPutData(AudioFilePool& pool)
{
CARLA_ASSERT(pool.size == fPool.size);
CARLA_SAFE_ASSERT_RETURN(pool.size == fPool.size,);

if (pool.size != fPool.size)
return;
if (! fMutex.tryLock())
return;

@@ -253,24 +295,12 @@ public:

if (lastFrame >= maxFrame)
{
#if 0
if (false)
//if (handlePtr->loopMode)
if (fLoopingMode)
{
carla_stderr("R: DEBUG read loop, lastFrame:%i, maxFrame:%i", lastFrame, maxFrame);

if (maxFrame >= static_cast<int64_t>(fPool.size))
{
readFrame %= maxFrame;
}
else
{
readFrame = 0;
lastFrame -= lastFrame % maxFrame;
}
carla_debug("R: transport out of bounds for loop");
readFrame %= fMaxPlayerFrame;
}
else
#endif
{
carla_stderr("R: transport out of bounds");
fNeedsRead = false;
@@ -279,82 +309,81 @@ public:
}

// temp data buffer
const size_t tmpSize = fPool.size * fFileNfo.channels;

float tmpData[tmpSize];
carla_zeroFloats(tmpData, tmpSize);
carla_zeroFloats(fPollTempData, fPollTempSize);

{
carla_stderr("R: poll data - reading at %li:%02li", readFrame/44100/60, (readFrame/44100) % 60);
carla_debug("R: poll data - reading at %li:%02li", readFrame/fPool.sampleRate/60, (readFrame/fPool.sampleRate) % 60);

ad_seek(fFilePtr, readFrame);
size_t i = 0;
ssize_t j = 0;
ssize_t rv = ad_read(fFilePtr, tmpData, tmpSize);
ssize_t rv = ad_read(fFilePtr, fPollTempData, fPollTempSize);

if (rv < 0)
{
carla_stderr("R: ad_read failed");
fNeedsRead = false;
return;
}

// see if we can read more
if (readFrame + rv >= static_cast<ssize_t>(fFileNfo.frames) && static_cast<size_t>(rv) < fPollTempSize)
{
carla_debug("R: from start");
ad_seek(fFilePtr, 0);
rv += ad_read(fFilePtr, fPollTempData+rv, fPollTempSize-rv);
}

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

for (; i < fPool.size && j < rv; ++j)
{
if (fFileNfo.channels == 1)
do {
for (; i < fPool.size && j < rv; ++j)
{
fPool.buffer[0][i] = tmpData[j];
fPool.buffer[1][i] = tmpData[j];
i++;
}
else
{
if (j % 2 == 0)
{
fPool.buffer[0][i] = tmpData[j];
}
else
if (fFileNfo.channels == 1)
{
fPool.buffer[1][i] = tmpData[j];
fPool.buffer[0][i] = fPollTempData[j];
fPool.buffer[1][i] = fPollTempData[j];
i++;
}
}
}

#if 0
if (false)
//if (handlePtr->loopMode && i < fPool.size)
{
while (i < fPool.size)
{
for (j=0; i < fPool.size && j < rv; ++j)
else
{
if (fFileNfo.channels == 1)
if (j % 2 == 0)
{
fPool.buffer[0][i] = tmpData[j];
fPool.buffer[1][i] = tmpData[j];
i++;
fPool.buffer[0][i] = fPollTempData[j];
}
else
{
if (j % 2 == 0)
{
fPool.buffer[0][i] = tmpData[j];
}
else
{
fPool.buffer[1][i] = tmpData[j];
i++;
}
fPool.buffer[1][i] = fPollTempData[j];
i++;
}
}
}
}
else
#endif
{
for (; i < fPool.size; ++i)

if (i >= fPool.size)
break;

if (rv == fFileNfo.frames)
{
fPool.buffer[0][i] = 0.0f;
fPool.buffer[1][i] = 0.0f;
// full file read
j = 0;
carla_debug("R: full file was read, filling buffers again");
}
}
else
{
carla_debug("read break, not enough space");

// FIXME use carla_zeroFloats
for (; i < fPool.size; ++i)
{
fPool.buffer[0][i] = 0.0f;
fPool.buffer[1][i] = 0.0f;
}

break;
}

} while (i < fPool.size);

fPool.startFrame = lastFrame;
}
@@ -367,9 +396,10 @@ protected:
{
while (! fQuitNow)
{
const uint32_t lastFrame(kPlayer->getLastFrame());
const uint32_t lastFrame = kPlayer->getLastFrame();
const uint32_t loopedFrame = fLoopingMode ? lastFrame % fMaxPlayerFrame : lastFrame;

if (fNeedsRead || lastFrame < fPool.startFrame || (lastFrame - fPool.startFrame >= fPool.size*3/4 && lastFrame < fFileNfo.frames))
if (fNeedsRead || lastFrame < fPool.startFrame || (lastFrame - fPool.startFrame >= fPool.size*3/4 && loopedFrame < fMaxPlayerFrame))
readPoll();
else
carla_msleep(50);
@@ -379,12 +409,18 @@ protected:
private:
AbstractAudioPlayer* const kPlayer;

bool fLoopingMode;
bool fNeedsRead;
bool fQuitNow;

void* fFilePtr;
ADInfo fFileNfo;

uint32_t fMaxPlayerFrame;

float* fPollTempData;
size_t fPollTempSize;

AudioFilePool fPool;
CarlaMutex fMutex;
};


+ 11
- 7
source/native-plugins/audio-file.cpp View File

@@ -1,6 +1,6 @@
/*
* Carla Native Plugins
* Copyright (C) 2013 Filipe Coelho <falktx@falktx.com>
* Copyright (C) 2013-2018 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -29,7 +29,7 @@ public:
AudioFilePlugin(const NativeHostDescriptor* const host)
: NativePluginClass(host),
AbstractAudioPlayer(),
fLoopMode(false),
fLoopMode(true),
fDoProcess(false),
fLastFrame(0),
fMaxFrame(0),
@@ -55,7 +55,7 @@ protected:

uint32_t getParameterCount() const override
{
return 0; // TODO - loopMode
return 1;
}

const NativeParameter* getParameterInfo(const uint32_t index) const override
@@ -67,7 +67,7 @@ protected:

param.name = "Loop Mode";
param.unit = nullptr;
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_BOOLEAN);
param.hints = static_cast<NativeParameterHints>(NATIVE_PARAMETER_IS_AUTOMABLE|NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_BOOLEAN);
param.ranges.def = 1.0f;
param.ranges.min = 0.0f;
param.ranges.max = 1.0f;
@@ -102,6 +102,7 @@ protected:
return;

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

@@ -149,9 +150,12 @@ protected:
fThread.tryPutData(fPool);

// out of reach
if (timePos->frame + frames < fPool.startFrame || timePos->frame >= fMaxFrame) /*&& ! loopMode)*/
if (timePos->frame + frames < fPool.startFrame || (timePos->frame >= fMaxFrame && !fLoopMode))
{
//carla_stderr("P: out of reach");
if (fLoopMode) {
carla_stderr("P: out of reach");
}

fLastFrame = timePos->frame;

if (timePos->frame + frames < fPool.startFrame)
@@ -254,7 +258,7 @@ static const NativePluginDescriptor audiofileDesc = {
/* audioOuts */ 2,
/* midiIns */ 0,
/* midiOuts */ 0,
/* paramIns */ 0, // TODO - loopMode
/* paramIns */ 1,
/* paramOuts */ 0,
/* name */ "Audio File",
/* label */ "audiofile",


+ 1
- 1
source/tests/Makefile View File

@@ -215,7 +215,7 @@ Engine: Engine.cpp
../backend/carla_engine.a ../backend/carla_plugin.a $(MODULEDIR)/native-plugins.a \
$(MODULEDIR)/dgl.a $(MODULEDIR)/jackbridge.a $(MODULEDIR)/lilv.a $(MODULEDIR)/rtmempool.a \
-Wl,--end-group \
$(PEDANTIC_CXX_FLAGS) $(shell pkg-config --libs alsa libpulse-simple liblo QtCore QtXml fluidsynth linuxsampler x11 gl smf fftw3 mxml zlib ntk_images ntk) -o $@
$(PEDANTIC_CXX_FLAGS) $(shell pkg-config --libs alsa libpulse-simple liblo QtCore QtXml fluidsynth x11 gl smf fftw3 mxml zlib ntk_images ntk) -o $@
env LD_LIBRARY_PATH=../backend valgrind --leak-check=full ./$@
# $(MODULEDIR)/juce_audio_basics.a $(MODULEDIR)/juce_core.a \



+ 3
- 3
source/utils/CarlaBridgeDefines.hpp View File

@@ -20,7 +20,7 @@

#include "CarlaRingBuffer.hpp"

#define CARLA_PLUGIN_BRIDGE_API_VERSION 3
#define CARLA_PLUGIN_BRIDGE_API_VERSION 4

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

@@ -141,9 +141,9 @@ struct BridgeTimeInfo {
uint64_t usecs;
uint32_t validFlags;
// bbt
int32_t bar, beat, tick;
int32_t bar, beat;
float beatsPerBar, beatType;
double barStartTick, ticksPerBeat, beatsPerMinute;
double tick, barStartTick, ticksPerBeat, beatsPerMinute;
};

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


Loading…
Cancel
Save