Signed-off-by: falkTX <falktx@falktx.com>tags/v2.1-rc1
| @@ -88,7 +88,12 @@ | |||||
| </row> | </row> | ||||
| <row> | <row> | ||||
| <property name="text"> | <property name="text"> | ||||
| <string>paths</string> | |||||
| <string>file-paths</string> | |||||
| </property> | |||||
| </row> | |||||
| <row> | |||||
| <property name="text"> | |||||
| <string>plugin-paths</string> | |||||
| </property> | </property> | ||||
| </row> | </row> | ||||
| <row> | <row> | ||||
| @@ -186,7 +191,7 @@ | |||||
| </item> | </item> | ||||
| <item row="4" column="0"> | <item row="4" column="0"> | ||||
| <property name="text"> | <property name="text"> | ||||
| <string>Paths</string> | |||||
| <string>File Paths</string> | |||||
| </property> | </property> | ||||
| <property name="font"> | <property name="font"> | ||||
| <font> | <font> | ||||
| @@ -203,6 +208,24 @@ | |||||
| </property> | </property> | ||||
| </item> | </item> | ||||
| <item row="5" column="0"> | <item row="5" column="0"> | ||||
| <property name="text"> | |||||
| <string>Plugin Paths</string> | |||||
| </property> | |||||
| <property name="font"> | |||||
| <font> | |||||
| <weight>75</weight> | |||||
| <bold>true</bold> | |||||
| </font> | |||||
| </property> | |||||
| <property name="icon"> | |||||
| <iconset resource="../resources.qrc"> | |||||
| <normaloff>:/scalable/folder.svgz</normaloff>:/scalable/folder.svgz</iconset> | |||||
| </property> | |||||
| <property name="flags"> | |||||
| <set>ItemIsSelectable|ItemIsEnabled</set> | |||||
| </property> | |||||
| </item> | |||||
| <item row="6" column="0"> | |||||
| <property name="text"> | <property name="text"> | ||||
| <string>Wine</string> | <string>Wine</string> | ||||
| </property> | </property> | ||||
| @@ -220,7 +243,7 @@ | |||||
| <set>ItemIsSelectable|ItemIsEnabled</set> | <set>ItemIsSelectable|ItemIsEnabled</set> | ||||
| </property> | </property> | ||||
| </item> | </item> | ||||
| <item row="6" column="0"> | |||||
| <item row="7" column="0"> | |||||
| <property name="text"> | <property name="text"> | ||||
| <string>Experimental</string> | <string>Experimental</string> | ||||
| </property> | </property> | ||||
| @@ -1647,7 +1670,253 @@ | |||||
| <zorder>group_osc_udp_port</zorder> | <zorder>group_osc_udp_port</zorder> | ||||
| <zorder>group_osc_core</zorder> | <zorder>group_osc_core</zorder> | ||||
| </widget> | </widget> | ||||
| <widget class="QWidget" name="page_paths"> | |||||
| <widget class="QWidget" name="page_filepaths"> | |||||
| <layout class="QVBoxLayout" name="verticalLayout_30"> | |||||
| <property name="margin"> | |||||
| <number>2</number> | |||||
| </property> | |||||
| <item> | |||||
| <layout class="QHBoxLayout" name="horizontalLayout_8"> | |||||
| <item> | |||||
| <widget class="QLabel" name="label_24"> | |||||
| <property name="text"> | |||||
| <string><b>File Paths</b></string> | |||||
| </property> | |||||
| <property name="alignment"> | |||||
| <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <spacer name="horizontalSpacer_10"> | |||||
| <property name="orientation"> | |||||
| <enum>Qt::Horizontal</enum> | |||||
| </property> | |||||
| <property name="sizeHint" stdset="0"> | |||||
| <size> | |||||
| <width>40</width> | |||||
| <height>20</height> | |||||
| </size> | |||||
| </property> | |||||
| </spacer> | |||||
| </item> | |||||
| <item> | |||||
| <widget class="QLabel" name="label_31"> | |||||
| <property name="maximumSize"> | |||||
| <size> | |||||
| <width>48</width> | |||||
| <height>48</height> | |||||
| </size> | |||||
| </property> | |||||
| <property name="text"> | |||||
| <string notr="true"/> | |||||
| </property> | |||||
| <property name="pixmap"> | |||||
| <pixmap resource="../resources.qrc">:/scalable/folder.svgz</pixmap> | |||||
| </property> | |||||
| <property name="scaledContents"> | |||||
| <bool>true</bool> | |||||
| </property> | |||||
| <property name="alignment"> | |||||
| <set>Qt::AlignHCenter|Qt::AlignTop</set> | |||||
| </property> | |||||
| <property name="wordWrap"> | |||||
| <bool>true</bool> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| </layout> | |||||
| </item> | |||||
| <item> | |||||
| <layout class="QHBoxLayout" name="horizontalLayout_19"> | |||||
| <item> | |||||
| <widget class="QComboBox" name="cb_filepaths"> | |||||
| <property name="minimumSize"> | |||||
| <size> | |||||
| <width>120</width> | |||||
| <height>0</height> | |||||
| </size> | |||||
| </property> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>Audio</string> | |||||
| </property> | |||||
| </item> | |||||
| <item> | |||||
| <property name="text"> | |||||
| <string>MIDI</string> | |||||
| </property> | |||||
| </item> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <widget class="QStackedWidget" name="tw_filepaths_info"> | |||||
| <property name="sizePolicy"> | |||||
| <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | |||||
| <horstretch>0</horstretch> | |||||
| <verstretch>0</verstretch> | |||||
| </sizepolicy> | |||||
| </property> | |||||
| <property name="currentIndex"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <widget class="QWidget" name="tw_filepaths_info_audio"> | |||||
| <layout class="QHBoxLayout" name="horizontalLayout_20"> | |||||
| <property name="spacing"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <property name="margin"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <item> | |||||
| <widget class="QLabel" name="label_12"> | |||||
| <property name="text"> | |||||
| <string>Used for the "audiofile" plugin</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| <widget class="QWidget" name="tw_filepaths_info_midi"> | |||||
| <layout class="QHBoxLayout" name="horizontalLayout_26"> | |||||
| <property name="spacing"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <property name="margin"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <item> | |||||
| <widget class="QLabel" name="label_13"> | |||||
| <property name="text"> | |||||
| <string>Used for the "midifile" plugin</string> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <spacer name="horizontalSpacer_23"> | |||||
| <property name="orientation"> | |||||
| <enum>Qt::Horizontal</enum> | |||||
| </property> | |||||
| <property name="sizeHint" stdset="0"> | |||||
| <size> | |||||
| <width>20</width> | |||||
| <height>20</height> | |||||
| </size> | |||||
| </property> | |||||
| </spacer> | |||||
| </item> | |||||
| </layout> | |||||
| </item> | |||||
| <item> | |||||
| <layout class="QHBoxLayout" name="horizontalLayout_16"> | |||||
| <item> | |||||
| <widget class="QStackedWidget" name="tw_filepaths"> | |||||
| <property name="currentIndex"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <widget class="QWidget" name="tw_filepaths_audio"> | |||||
| <layout class="QVBoxLayout" name="verticalLayout_18"> | |||||
| <property name="spacing"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <property name="margin"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <item> | |||||
| <widget class="QListWidget" name="lw_files_audio"/> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| <widget class="QWidget" name="tw_filepaths_midi"> | |||||
| <layout class="QVBoxLayout" name="verticalLayout_23"> | |||||
| <property name="spacing"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <property name="margin"> | |||||
| <number>0</number> | |||||
| </property> | |||||
| <item> | |||||
| <widget class="QListWidget" name="lw_files_midi"/> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <layout class="QVBoxLayout" name="verticalLayout_29"> | |||||
| <item> | |||||
| <widget class="QPushButton" name="b_filepaths_add"> | |||||
| <property name="text"> | |||||
| <string>Add...</string> | |||||
| </property> | |||||
| <property name="icon"> | |||||
| <iconset resource="../resources.qrc"> | |||||
| <normaloff>:/16x16/list-add.svgz</normaloff>:/16x16/list-add.svgz</iconset> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <widget class="QPushButton" name="b_filepaths_remove"> | |||||
| <property name="text"> | |||||
| <string>Remove</string> | |||||
| </property> | |||||
| <property name="icon"> | |||||
| <iconset resource="../resources.qrc"> | |||||
| <normaloff>:/16x16/list-remove.svgz</normaloff>:/16x16/list-remove.svgz</iconset> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <spacer name="verticalSpacer_6"> | |||||
| <property name="orientation"> | |||||
| <enum>Qt::Vertical</enum> | |||||
| </property> | |||||
| <property name="sizeType"> | |||||
| <enum>QSizePolicy::Fixed</enum> | |||||
| </property> | |||||
| <property name="sizeHint" stdset="0"> | |||||
| <size> | |||||
| <width>20</width> | |||||
| <height>20</height> | |||||
| </size> | |||||
| </property> | |||||
| </spacer> | |||||
| </item> | |||||
| <item> | |||||
| <widget class="QPushButton" name="b_filepaths_change"> | |||||
| <property name="text"> | |||||
| <string>Change...</string> | |||||
| </property> | |||||
| <property name="icon"> | |||||
| <iconset resource="../resources.qrc"> | |||||
| <normaloff>:/16x16/edit-rename.svgz</normaloff>:/16x16/edit-rename.svgz</iconset> | |||||
| </property> | |||||
| </widget> | |||||
| </item> | |||||
| <item> | |||||
| <spacer name="verticalSpacer_8"> | |||||
| <property name="orientation"> | |||||
| <enum>Qt::Vertical</enum> | |||||
| </property> | |||||
| <property name="sizeHint" stdset="0"> | |||||
| <size> | |||||
| <width>20</width> | |||||
| <height>40</height> | |||||
| </size> | |||||
| </property> | |||||
| </spacer> | |||||
| </item> | |||||
| </layout> | |||||
| </item> | |||||
| </layout> | |||||
| </item> | |||||
| </layout> | |||||
| </widget> | |||||
| <widget class="QWidget" name="page_pluginpaths"> | |||||
| <layout class="QVBoxLayout" name="verticalLayout_19"> | <layout class="QVBoxLayout" name="verticalLayout_19"> | ||||
| <property name="margin"> | <property name="margin"> | ||||
| <number>2</number> | <number>2</number> | ||||
| @@ -1657,7 +1926,7 @@ | |||||
| <item> | <item> | ||||
| <widget class="QLabel" name="label_18"> | <widget class="QLabel" name="label_18"> | ||||
| <property name="text"> | <property name="text"> | ||||
| <string><b>Paths</b></string> | |||||
| <string><b>Plugin Paths</b></string> | |||||
| </property> | </property> | ||||
| <property name="alignment"> | <property name="alignment"> | ||||
| <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set> | ||||
| @@ -2749,5 +3018,37 @@ This mode is not available for VST plugins.</string> | |||||
| </hint> | </hint> | ||||
| </hints> | </hints> | ||||
| </connection> | </connection> | ||||
| <connection> | |||||
| <sender>cb_filepaths</sender> | |||||
| <signal>currentIndexChanged(int)</signal> | |||||
| <receiver>tw_filepaths</receiver> | |||||
| <slot>setCurrentIndex(int)</slot> | |||||
| <hints> | |||||
| <hint type="sourcelabel"> | |||||
| <x>258</x> | |||||
| <y>79</y> | |||||
| </hint> | |||||
| <hint type="destinationlabel"> | |||||
| <x>350</x> | |||||
| <y>312</y> | |||||
| </hint> | |||||
| </hints> | |||||
| </connection> | |||||
| <connection> | |||||
| <sender>cb_filepaths</sender> | |||||
| <signal>currentIndexChanged(int)</signal> | |||||
| <receiver>tw_filepaths_info</receiver> | |||||
| <slot>setCurrentIndex(int)</slot> | |||||
| <hints> | |||||
| <hint type="sourcelabel"> | |||||
| <x>258</x> | |||||
| <y>79</y> | |||||
| </hint> | |||||
| <hint type="destinationlabel"> | |||||
| <x>409</x> | |||||
| <y>79</y> | |||||
| </hint> | |||||
| </hints> | |||||
| </connection> | |||||
| </connections> | </connections> | ||||
| </ui> | </ui> | ||||
| @@ -488,6 +488,30 @@ typedef enum { | |||||
| } BinaryType; | } BinaryType; | ||||
| /* ------------------------------------------------------------------------------------------------------------ | |||||
| * File Type */ | |||||
| /*! | |||||
| * File type. | |||||
| */ | |||||
| typedef enum { | |||||
| /*! | |||||
| * Null file type. | |||||
| */ | |||||
| FILE_NONE = 0, | |||||
| /*! | |||||
| * Audio file. | |||||
| */ | |||||
| FILE_AUDIO = 1, | |||||
| /*! | |||||
| * MIDI file. | |||||
| */ | |||||
| FILE_MIDI = 2 | |||||
| } FileType; | |||||
| /* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||
| * Plugin Type */ | * Plugin Type */ | ||||
| @@ -1233,79 +1257,85 @@ typedef enum { | |||||
| */ | */ | ||||
| ENGINE_OPTION_OSC_PORT_UDP = 16, | ENGINE_OPTION_OSC_PORT_UDP = 16, | ||||
| /*! | |||||
| * Set path used for a specific file type. | |||||
| * Uses value as the file format, valueStr as actual path. | |||||
| */ | |||||
| ENGINE_OPTION_FILE_PATH = 17, | |||||
| /*! | /*! | ||||
| * Set path used for a specific plugin type. | * Set path used for a specific plugin type. | ||||
| * Uses value as the plugin format, valueStr as actual path. | * Uses value as the plugin format, valueStr as actual path. | ||||
| * @see PluginType | * @see PluginType | ||||
| */ | */ | ||||
| ENGINE_OPTION_PLUGIN_PATH = 17, | |||||
| ENGINE_OPTION_PLUGIN_PATH = 18, | |||||
| /*! | /*! | ||||
| * Set path to the binary files. | * Set path to the binary files. | ||||
| * Default unset. | * Default unset. | ||||
| * @note Must be set for plugin and UI bridges to work | * @note Must be set for plugin and UI bridges to work | ||||
| */ | */ | ||||
| ENGINE_OPTION_PATH_BINARIES = 18, | |||||
| ENGINE_OPTION_PATH_BINARIES = 19, | |||||
| /*! | /*! | ||||
| * Set path to the resource files. | * Set path to the resource files. | ||||
| * Default unset. | * Default unset. | ||||
| * @note Must be set for some internal plugins to work | * @note Must be set for some internal plugins to work | ||||
| */ | */ | ||||
| ENGINE_OPTION_PATH_RESOURCES = 19, | |||||
| ENGINE_OPTION_PATH_RESOURCES = 20, | |||||
| /*! | /*! | ||||
| * Prevent bad plugin and UI behaviour. | * Prevent bad plugin and UI behaviour. | ||||
| * @note: Linux only | * @note: Linux only | ||||
| */ | */ | ||||
| ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 20, | |||||
| ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 21, | |||||
| /*! | /*! | ||||
| * Set UI scaling used in frontend, so backend can do the same for plugin UIs. | * Set UI scaling used in frontend, so backend can do the same for plugin UIs. | ||||
| */ | */ | ||||
| ENGINE_OPTION_FRONTEND_UI_SCALE = 21, | |||||
| ENGINE_OPTION_FRONTEND_UI_SCALE = 22, | |||||
| /*! | /*! | ||||
| * Set frontend winId, used to define as parent window for plugin UIs. | * Set frontend winId, used to define as parent window for plugin UIs. | ||||
| */ | */ | ||||
| ENGINE_OPTION_FRONTEND_WIN_ID = 22, | |||||
| ENGINE_OPTION_FRONTEND_WIN_ID = 23, | |||||
| #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN) | #if !defined(BUILD_BRIDGE_ALTERNATIVE_ARCH) && !defined(CARLA_OS_WIN) | ||||
| /*! | /*! | ||||
| * Set path to wine executable. | * Set path to wine executable. | ||||
| */ | */ | ||||
| ENGINE_OPTION_WINE_EXECUTABLE = 23, | |||||
| ENGINE_OPTION_WINE_EXECUTABLE = 24, | |||||
| /*! | /*! | ||||
| * Enable automatic wineprefix detection. | * Enable automatic wineprefix detection. | ||||
| */ | */ | ||||
| ENGINE_OPTION_WINE_AUTO_PREFIX = 24, | |||||
| ENGINE_OPTION_WINE_AUTO_PREFIX = 25, | |||||
| /*! | /*! | ||||
| * Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. | * Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. | ||||
| */ | */ | ||||
| ENGINE_OPTION_WINE_FALLBACK_PREFIX = 25, | |||||
| ENGINE_OPTION_WINE_FALLBACK_PREFIX = 26, | |||||
| /*! | /*! | ||||
| * Enable realtime priority for Wine application and server threads. | * Enable realtime priority for Wine application and server threads. | ||||
| */ | */ | ||||
| ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 26, | |||||
| ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 27, | |||||
| /*! | /*! | ||||
| * Base realtime priority for Wine threads. | * Base realtime priority for Wine threads. | ||||
| */ | */ | ||||
| ENGINE_OPTION_WINE_BASE_RT_PRIO = 27, | |||||
| ENGINE_OPTION_WINE_BASE_RT_PRIO = 28, | |||||
| /*! | /*! | ||||
| * Wine server realtime priority. | * Wine server realtime priority. | ||||
| */ | */ | ||||
| ENGINE_OPTION_WINE_SERVER_RT_PRIO = 28, | |||||
| ENGINE_OPTION_WINE_SERVER_RT_PRIO = 29, | |||||
| #endif | #endif | ||||
| /*! | /*! | ||||
| * Capture console output into debug callbacks. | * Capture console output into debug callbacks. | ||||
| */ | */ | ||||
| ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 29 | |||||
| ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 30 | |||||
| } EngineOption; | } EngineOption; | ||||
| @@ -249,6 +249,9 @@ struct CARLA_API EngineOptions { | |||||
| int oscPortUDP; | int oscPortUDP; | ||||
| #endif | #endif | ||||
| const char* pathAudio; | |||||
| const char* pathMIDI; | |||||
| const char* pathLADSPA; | const char* pathLADSPA; | ||||
| const char* pathDSSI; | const char* pathDSSI; | ||||
| const char* pathLV2; | const char* pathLV2; | ||||
| @@ -208,6 +208,12 @@ static void carla_engine_init_common(CarlaEngine* const engine) | |||||
| if (const char* const uiBridgesTimeout = std::getenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT")) | if (const char* const uiBridgesTimeout = std::getenv("ENGINE_OPTION_UI_BRIDGES_TIMEOUT")) | ||||
| engine->setOption(CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT, std::atoi(uiBridgesTimeout), nullptr); | engine->setOption(CB::ENGINE_OPTION_UI_BRIDGES_TIMEOUT, std::atoi(uiBridgesTimeout), nullptr); | ||||
| if (const char* const pathAudio = std::getenv("ENGINE_OPTION_FILE_PATH_AUDIO")) | |||||
| engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_AUDIO, pathAudio); | |||||
| if (const char* const pathMIDI = std::getenv("ENGINE_OPTION_FILE_PATH_MIDI")) | |||||
| engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_MIDI, pathMIDI); | |||||
| if (const char* const pathLADSPA = std::getenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA")) | if (const char* const pathLADSPA = std::getenv("ENGINE_OPTION_PLUGIN_PATH_LADSPA")) | ||||
| engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, pathLADSPA); | engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, pathLADSPA); | ||||
| @@ -265,6 +271,12 @@ static void carla_engine_init_common(CarlaEngine* const engine) | |||||
| engine->setOption(CB::ENGINE_OPTION_OSC_PORT_TCP, gStandalone.engineOptions.oscPortTCP, nullptr); | engine->setOption(CB::ENGINE_OPTION_OSC_PORT_TCP, gStandalone.engineOptions.oscPortTCP, nullptr); | ||||
| engine->setOption(CB::ENGINE_OPTION_OSC_PORT_UDP, gStandalone.engineOptions.oscPortUDP, nullptr); | engine->setOption(CB::ENGINE_OPTION_OSC_PORT_UDP, gStandalone.engineOptions.oscPortUDP, nullptr); | ||||
| if (gStandalone.engineOptions.pathAudio != nullptr) | |||||
| engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_AUDIO, gStandalone.engineOptions.pathAudio); | |||||
| if (gStandalone.engineOptions.pathMIDI != nullptr) | |||||
| engine->setOption(CB::ENGINE_OPTION_FILE_PATH, CB::FILE_MIDI, gStandalone.engineOptions.pathMIDI); | |||||
| if (gStandalone.engineOptions.pathLADSPA != nullptr) | if (gStandalone.engineOptions.pathLADSPA != nullptr) | ||||
| engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, gStandalone.engineOptions.pathLADSPA); | engine->setOption(CB::ENGINE_OPTION_PLUGIN_PATH, CB::PLUGIN_LADSPA, gStandalone.engineOptions.pathLADSPA); | ||||
| @@ -733,6 +745,26 @@ void carla_set_engine_option(EngineOption option, int value, const char* valueSt | |||||
| gStandalone.engineOptions.oscPortUDP = value; | gStandalone.engineOptions.oscPortUDP = value; | ||||
| break; | break; | ||||
| case CB::ENGINE_OPTION_FILE_PATH: | |||||
| CARLA_SAFE_ASSERT_RETURN(value > CB::FILE_NONE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(value <= CB::FILE_MIDI,); | |||||
| CARLA_SAFE_ASSERT_RETURN(valueStr != nullptr,); | |||||
| switch (value) | |||||
| { | |||||
| case CB::FILE_AUDIO: | |||||
| if (gStandalone.engineOptions.pathAudio != nullptr) | |||||
| delete[] gStandalone.engineOptions.pathAudio; | |||||
| gStandalone.engineOptions.pathAudio = carla_strdup_safe(valueStr); | |||||
| break; | |||||
| case CB::FILE_MIDI: | |||||
| if (gStandalone.engineOptions.pathMIDI != nullptr) | |||||
| delete[] gStandalone.engineOptions.pathMIDI; | |||||
| gStandalone.engineOptions.pathMIDI = carla_strdup_safe(valueStr); | |||||
| break; | |||||
| } | |||||
| break; | |||||
| case CB::ENGINE_OPTION_PLUGIN_PATH: | case CB::ENGINE_OPTION_PLUGIN_PATH: | ||||
| CARLA_SAFE_ASSERT_RETURN(value > CB::PLUGIN_NONE,); | CARLA_SAFE_ASSERT_RETURN(value > CB::PLUGIN_NONE,); | ||||
| CARLA_SAFE_ASSERT_RETURN(value <= CB::PLUGIN_SFZ,); | CARLA_SAFE_ASSERT_RETURN(value <= CB::PLUGIN_SFZ,); | ||||
| @@ -1740,6 +1740,34 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch | |||||
| #endif | #endif | ||||
| break; | break; | ||||
| case ENGINE_OPTION_FILE_PATH: | |||||
| CARLA_SAFE_ASSERT_RETURN(value > FILE_NONE,); | |||||
| CARLA_SAFE_ASSERT_RETURN(value <= FILE_MIDI,); | |||||
| switch (value) | |||||
| { | |||||
| case FILE_AUDIO: | |||||
| if (pData->options.pathAudio != nullptr) | |||||
| delete[] pData->options.pathAudio; | |||||
| if (valueStr != nullptr) | |||||
| pData->options.pathAudio = carla_strdup_safe(valueStr); | |||||
| else | |||||
| pData->options.pathAudio = nullptr; | |||||
| break; | |||||
| case FILE_MIDI: | |||||
| if (pData->options.pathMIDI != nullptr) | |||||
| delete[] pData->options.pathMIDI; | |||||
| if (valueStr != nullptr) | |||||
| pData->options.pathMIDI = carla_strdup_safe(valueStr); | |||||
| else | |||||
| pData->options.pathMIDI = nullptr; | |||||
| break; | |||||
| default: | |||||
| return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid file type", | |||||
| option, EngineOption2Str(option), value, valueStr); | |||||
| break; | |||||
| } | |||||
| break; | |||||
| case ENGINE_OPTION_PLUGIN_PATH: | case ENGINE_OPTION_PLUGIN_PATH: | ||||
| CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,); | CARLA_SAFE_ASSERT_RETURN(value > PLUGIN_NONE,); | ||||
| CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_SFZ,); | CARLA_SAFE_ASSERT_RETURN(value <= PLUGIN_SFZ,); | ||||
| @@ -1803,7 +1831,8 @@ void CarlaEngine::setOption(const EngineOption option, const int value, const ch | |||||
| pData->options.pathSFZ = nullptr; | pData->options.pathSFZ = nullptr; | ||||
| break; | break; | ||||
| default: | default: | ||||
| return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid plugin type", option, EngineOption2Str(option), value, valueStr); | |||||
| return carla_stderr("CarlaEngine::setOption(%i:%s, %i, \"%s\") - Invalid plugin type", | |||||
| option, EngineOption2Str(option), value, valueStr); | |||||
| break; | break; | ||||
| } | } | ||||
| break; | break; | ||||
| @@ -208,6 +208,8 @@ EngineOptions::EngineOptions() noexcept | |||||
| oscPortTCP(22752), | oscPortTCP(22752), | ||||
| oscPortUDP(22752), | oscPortUDP(22752), | ||||
| #endif | #endif | ||||
| pathAudio(nullptr), | |||||
| pathMIDI(nullptr), | |||||
| pathLADSPA(nullptr), | pathLADSPA(nullptr), | ||||
| pathDSSI(nullptr), | pathDSSI(nullptr), | ||||
| pathLV2(nullptr), | pathLV2(nullptr), | ||||
| @@ -232,61 +234,61 @@ EngineOptions::~EngineOptions() noexcept | |||||
| delete[] audioDriver; | delete[] audioDriver; | ||||
| audioDriver = nullptr; | audioDriver = nullptr; | ||||
| } | } | ||||
| if (audioDevice != nullptr) | if (audioDevice != nullptr) | ||||
| { | { | ||||
| delete[] audioDevice; | delete[] audioDevice; | ||||
| audioDevice = nullptr; | audioDevice = nullptr; | ||||
| } | } | ||||
| if (pathAudio != nullptr) | |||||
| { | |||||
| delete[] pathAudio; | |||||
| pathAudio = nullptr; | |||||
| } | |||||
| if (pathMIDI != nullptr) | |||||
| { | |||||
| delete[] pathMIDI; | |||||
| pathMIDI = nullptr; | |||||
| } | |||||
| if (pathLADSPA != nullptr) | if (pathLADSPA != nullptr) | ||||
| { | { | ||||
| delete[] pathLADSPA; | delete[] pathLADSPA; | ||||
| pathLADSPA = nullptr; | pathLADSPA = nullptr; | ||||
| } | } | ||||
| if (pathDSSI != nullptr) | if (pathDSSI != nullptr) | ||||
| { | { | ||||
| delete[] pathDSSI; | delete[] pathDSSI; | ||||
| pathDSSI = nullptr; | pathDSSI = nullptr; | ||||
| } | } | ||||
| if (pathLV2 != nullptr) | if (pathLV2 != nullptr) | ||||
| { | { | ||||
| delete[] pathLV2; | delete[] pathLV2; | ||||
| pathLV2 = nullptr; | pathLV2 = nullptr; | ||||
| } | } | ||||
| if (pathVST2 != nullptr) | if (pathVST2 != nullptr) | ||||
| { | { | ||||
| delete[] pathVST2; | delete[] pathVST2; | ||||
| pathVST2 = nullptr; | pathVST2 = nullptr; | ||||
| } | } | ||||
| if (pathVST3 != nullptr) | if (pathVST3 != nullptr) | ||||
| { | { | ||||
| delete[] pathVST3; | delete[] pathVST3; | ||||
| pathVST3 = nullptr; | pathVST3 = nullptr; | ||||
| } | } | ||||
| if (pathSF2 != nullptr) | if (pathSF2 != nullptr) | ||||
| { | { | ||||
| delete[] pathSF2; | delete[] pathSF2; | ||||
| pathSF2 = nullptr; | pathSF2 = nullptr; | ||||
| } | } | ||||
| if (pathSFZ != nullptr) | if (pathSFZ != nullptr) | ||||
| { | { | ||||
| delete[] pathSFZ; | delete[] pathSFZ; | ||||
| pathSFZ = nullptr; | pathSFZ = nullptr; | ||||
| } | } | ||||
| if (binaryDir != nullptr) | if (binaryDir != nullptr) | ||||
| { | { | ||||
| delete[] binaryDir; | delete[] binaryDir; | ||||
| binaryDir = nullptr; | binaryDir = nullptr; | ||||
| } | } | ||||
| if (resourceDir != nullptr) | if (resourceDir != nullptr) | ||||
| { | { | ||||
| delete[] resourceDir; | delete[] resourceDir; | ||||
| @@ -1636,6 +1636,9 @@ public: | |||||
| CarlaEngineNative* const engine = handlePtr; | CarlaEngineNative* const engine = handlePtr; | ||||
| return (intptr_t)(CarlaEngine*)engine; | return (intptr_t)(CarlaEngine*)engine; | ||||
| } | } | ||||
| case NATIVE_PLUGIN_OPCODE_IDLE: | |||||
| //handlePtr->idle(); | |||||
| return 0; | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -252,6 +252,7 @@ public: | |||||
| fIsOffline(false), | fIsOffline(false), | ||||
| fIsUiAvailable(false), | fIsUiAvailable(false), | ||||
| fIsUiVisible(false), | fIsUiVisible(false), | ||||
| fNeedsIdle(false), | |||||
| fInlineDisplayNeedsRedraw(false), | fInlineDisplayNeedsRedraw(false), | ||||
| fInlineDisplayLastRedrawTime(0), | fInlineDisplayLastRedrawTime(0), | ||||
| fAudioAndCvInBuffers(nullptr), | fAudioAndCvInBuffers(nullptr), | ||||
| @@ -921,6 +922,12 @@ public: | |||||
| void idle() override | void idle() override | ||||
| { | { | ||||
| if (fNeedsIdle) | |||||
| { | |||||
| fNeedsIdle = false; | |||||
| fDescriptor->dispatcher(fHandle, NATIVE_PLUGIN_OPCODE_IDLE, 0, 0, nullptr, 0.0f); | |||||
| } | |||||
| if (fInlineDisplayNeedsRedraw) | if (fInlineDisplayNeedsRedraw) | ||||
| { | { | ||||
| // TESTING | // TESTING | ||||
| @@ -2555,7 +2562,8 @@ protected: | |||||
| return pData->engine->runFileCallback(FILE_CALLBACK_SAVE, isDir, title, filter); | return pData->engine->runFileCallback(FILE_CALLBACK_SAVE, isDir, title, filter); | ||||
| } | } | ||||
| intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) | |||||
| intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, | |||||
| const int32_t index, const intptr_t value, void* const ptr, const float opt) | |||||
| { | { | ||||
| carla_debug("CarlaPluginNative::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", | carla_debug("CarlaPluginNative::handleDispatcher(%i, %i, " P_INTPTR ", %p, %f)", | ||||
| opcode, index, value, ptr, static_cast<double>(opt)); | opcode, index, value, ptr, static_cast<double>(opt)); | ||||
| @@ -2603,12 +2611,26 @@ protected: | |||||
| CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); | CARLA_SAFE_ASSERT_RETURN(index >= 0, 0); | ||||
| pData->engine->touchPluginParameter(pData->id, static_cast<uint32_t>(index), value != 0); | pData->engine->touchPluginParameter(pData->id, static_cast<uint32_t>(index), value != 0); | ||||
| break; | break; | ||||
| case NATIVE_HOST_OPCODE_REQUEST_IDLE: | |||||
| fNeedsIdle = true; | |||||
| break; | |||||
| case NATIVE_HOST_OPCODE_GET_FILE_PATH: | |||||
| CARLA_SAFE_ASSERT_RETURN(ptr != nullptr, 0); | |||||
| { | |||||
| const EngineOptions& opts(pData->engine->getOptions()); | |||||
| const char* const filetype = (const char*)ptr; | |||||
| if (std::strcmp(filetype, "audio") == 0) | |||||
| return static_cast<intptr_t>((uintptr_t)opts.pathAudio); | |||||
| if (std::strcmp(filetype, "midi") == 0) | |||||
| return static_cast<intptr_t>((uintptr_t)opts.pathMIDI); | |||||
| } | |||||
| break; | |||||
| } | } | ||||
| return ret; | return ret; | ||||
| // unused for now | // unused for now | ||||
| (void)ptr; | |||||
| (void)opt; | (void)opt; | ||||
| } | } | ||||
| @@ -2792,6 +2814,8 @@ private: | |||||
| bool fIsOffline; | bool fIsOffline; | ||||
| bool fIsUiAvailable; | bool fIsUiAvailable; | ||||
| bool fIsUiVisible; | bool fIsUiVisible; | ||||
| volatile bool fNeedsIdle; | |||||
| bool fInlineDisplayNeedsRedraw; | bool fInlineDisplayNeedsRedraw; | ||||
| int64_t fInlineDisplayLastRedrawTime; | int64_t fInlineDisplayLastRedrawTime; | ||||
| @@ -387,6 +387,19 @@ BINARY_WIN64 = 4 | |||||
| # Other binary type. | # Other binary type. | ||||
| BINARY_OTHER = 5 | BINARY_OTHER = 5 | ||||
| # ------------------------------------------------------------------------------------------------------------ | |||||
| # File Type | |||||
| # File type. | |||||
| # Null file type. | |||||
| FILE_NONE = 0 | |||||
| # Audio file. | |||||
| FILE_AUDIO = 1 | |||||
| # MIDI file. | |||||
| FILE_MIDI = 2 | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Plugin Type | # Plugin Type | ||||
| # Plugin type. | # Plugin type. | ||||
| @@ -885,51 +898,55 @@ ENGINE_OPTION_OSC_PORT_TCP = 15 | |||||
| # @note Valid ports begin at 1024 and end at 32767 (inclusive) | # @note Valid ports begin at 1024 and end at 32767 (inclusive) | ||||
| ENGINE_OPTION_OSC_PORT_UDP = 16 | ENGINE_OPTION_OSC_PORT_UDP = 16 | ||||
| # Set path used for a specific file type. | |||||
| # Uses value as the file format, valueStr as actual path. | |||||
| ENGINE_OPTION_FILE_PATH = 17 | |||||
| # Set path used for a specific plugin type. | # Set path used for a specific plugin type. | ||||
| # Uses value as the plugin format, valueStr as actual path. | # Uses value as the plugin format, valueStr as actual path. | ||||
| # @see PluginType | # @see PluginType | ||||
| ENGINE_OPTION_PLUGIN_PATH = 17 | |||||
| ENGINE_OPTION_PLUGIN_PATH = 18 | |||||
| # Set path to the binary files. | # Set path to the binary files. | ||||
| # Default unset. | # Default unset. | ||||
| # @note Must be set for plugin and UI bridges to work | # @note Must be set for plugin and UI bridges to work | ||||
| ENGINE_OPTION_PATH_BINARIES = 18 | |||||
| ENGINE_OPTION_PATH_BINARIES = 19 | |||||
| # Set path to the resource files. | # Set path to the resource files. | ||||
| # Default unset. | # Default unset. | ||||
| # @note Must be set for some internal plugins to work | # @note Must be set for some internal plugins to work | ||||
| ENGINE_OPTION_PATH_RESOURCES = 19 | |||||
| ENGINE_OPTION_PATH_RESOURCES = 20 | |||||
| # Prevent bad plugin and UI behaviour. | # Prevent bad plugin and UI behaviour. | ||||
| # @note: Linux only | # @note: Linux only | ||||
| ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 20 | |||||
| ENGINE_OPTION_PREVENT_BAD_BEHAVIOUR = 21 | |||||
| # Set UI scaling used in frontend, so backend can do the same for plugin UIs. | # Set UI scaling used in frontend, so backend can do the same for plugin UIs. | ||||
| ENGINE_OPTION_FRONTEND_UI_SCALE = 21 | |||||
| ENGINE_OPTION_FRONTEND_UI_SCALE = 22 | |||||
| # Set frontend winId, used to define as parent window for plugin UIs. | # Set frontend winId, used to define as parent window for plugin UIs. | ||||
| ENGINE_OPTION_FRONTEND_WIN_ID = 22 | |||||
| ENGINE_OPTION_FRONTEND_WIN_ID = 23 | |||||
| # Set path to wine executable. | # Set path to wine executable. | ||||
| ENGINE_OPTION_WINE_EXECUTABLE = 23 | |||||
| ENGINE_OPTION_WINE_EXECUTABLE = 24 | |||||
| # Enable automatic wineprefix detection. | # Enable automatic wineprefix detection. | ||||
| ENGINE_OPTION_WINE_AUTO_PREFIX = 24 | |||||
| ENGINE_OPTION_WINE_AUTO_PREFIX = 25 | |||||
| # Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. | # Fallback wineprefix to use if automatic detection fails or is disabled, and WINEPREFIX is not set. | ||||
| ENGINE_OPTION_WINE_FALLBACK_PREFIX = 25 | |||||
| ENGINE_OPTION_WINE_FALLBACK_PREFIX = 26 | |||||
| # Enable realtime priority for Wine application and server threads. | # Enable realtime priority for Wine application and server threads. | ||||
| ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 26 | |||||
| ENGINE_OPTION_WINE_RT_PRIO_ENABLED = 27 | |||||
| # Base realtime priority for Wine threads. | # Base realtime priority for Wine threads. | ||||
| ENGINE_OPTION_WINE_BASE_RT_PRIO = 27 | |||||
| ENGINE_OPTION_WINE_BASE_RT_PRIO = 28 | |||||
| # Wine server realtime priority. | # Wine server realtime priority. | ||||
| ENGINE_OPTION_WINE_SERVER_RT_PRIO = 28 | |||||
| ENGINE_OPTION_WINE_SERVER_RT_PRIO = 29 | |||||
| # Capture console output into debug callbacks | # Capture console output into debug callbacks | ||||
| ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 29 | |||||
| ENGINE_OPTION_DEBUG_CONSOLE_OUTPUT = 30 | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Engine Process Mode | # Engine Process Mode | ||||
| @@ -3101,6 +3101,15 @@ def setEngineSettings(host): | |||||
| setHostSettings(host) | setHostSettings(host) | ||||
| # -------------------------------------------------------------------------------------------------------- | |||||
| # file paths | |||||
| FILE_PATH_AUDIO = toList(settings.value(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO)) | |||||
| FILE_PATH_MIDI = toList(settings.value(CARLA_KEY_PATHS_MIDI, CARLA_DEFAULT_FILE_PATH_MIDI)) | |||||
| host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_AUDIO, splitter.join(FILE_PATH_AUDIO)) | |||||
| host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_MIDI, splitter.join(FILE_PATH_MIDI)) | |||||
| # -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
| # plugin paths | # plugin paths | ||||
| @@ -324,19 +324,24 @@ class CarlaSettingsW(QDialog): | |||||
| TAB_INDEX_CANVAS = 1 | TAB_INDEX_CANVAS = 1 | ||||
| TAB_INDEX_ENGINE = 2 | TAB_INDEX_ENGINE = 2 | ||||
| TAB_INDEX_OSC = 3 | TAB_INDEX_OSC = 3 | ||||
| TAB_INDEX_PATHS = 4 | |||||
| TAB_INDEX_WINE = 5 | |||||
| TAB_INDEX_EXPERIMENTAL = 6 | |||||
| TAB_INDEX_NONE = 7 | |||||
| # Path indexes | |||||
| PATH_INDEX_LADSPA = 0 | |||||
| PATH_INDEX_DSSI = 1 | |||||
| PATH_INDEX_LV2 = 2 | |||||
| PATH_INDEX_VST2 = 3 | |||||
| PATH_INDEX_VST3 = 4 | |||||
| PATH_INDEX_SF2 = 5 | |||||
| PATH_INDEX_SFZ = 6 | |||||
| TAB_INDEX_FILEPATHS = 4 | |||||
| TAB_INDEX_PLUGINPATHS = 5 | |||||
| TAB_INDEX_WINE = 6 | |||||
| TAB_INDEX_EXPERIMENTAL = 7 | |||||
| TAB_INDEX_NONE = 8 | |||||
| # File Path indexes | |||||
| FILEPATH_INDEX_AUDIO = 0 | |||||
| FILEPATH_INDEX_MIDI = 1 | |||||
| # Plugin Path indexes | |||||
| PLUGINPATH_INDEX_LADSPA = 0 | |||||
| PLUGINPATH_INDEX_DSSI = 1 | |||||
| PLUGINPATH_INDEX_LV2 = 2 | |||||
| PLUGINPATH_INDEX_VST2 = 3 | |||||
| PLUGINPATH_INDEX_VST3 = 4 | |||||
| PLUGINPATH_INDEX_SF2 = 5 | |||||
| PLUGINPATH_INDEX_SFZ = 6 | |||||
| # Single and Multiple client mode is only for JACK, | # Single and Multiple client mode is only for JACK, | ||||
| # but we still want to match QComboBox index to backend defines, | # but we still want to match QComboBox index to backend defines, | ||||
| @@ -377,7 +382,8 @@ class CarlaSettingsW(QDialog): | |||||
| if host.isControl: | if host.isControl: | ||||
| self.ui.lw_page.hideRow(self.TAB_INDEX_ENGINE) | self.ui.lw_page.hideRow(self.TAB_INDEX_ENGINE) | ||||
| self.ui.lw_page.hideRow(self.TAB_INDEX_PATHS) | |||||
| self.ui.lw_page.hideRow(self.TAB_INDEX_FILEPATHS) | |||||
| self.ui.lw_page.hideRow(self.TAB_INDEX_PLUGINPATHS) | |||||
| self.ui.ch_exp_export_lv2.hide() | self.ui.ch_exp_export_lv2.hide() | ||||
| self.ui.group_experimental_engine.hide() | self.ui.group_experimental_engine.hide() | ||||
| @@ -450,6 +456,13 @@ class CarlaSettingsW(QDialog): | |||||
| self.ui.lw_sf2.currentRowChanged.connect(self.slot_pluginPathRowChanged) | self.ui.lw_sf2.currentRowChanged.connect(self.slot_pluginPathRowChanged) | ||||
| self.ui.lw_sfz.currentRowChanged.connect(self.slot_pluginPathRowChanged) | self.ui.lw_sfz.currentRowChanged.connect(self.slot_pluginPathRowChanged) | ||||
| self.ui.b_filepaths_add.clicked.connect(self.slot_addFilePath) | |||||
| self.ui.b_filepaths_remove.clicked.connect(self.slot_removeFilePath) | |||||
| self.ui.b_filepaths_change.clicked.connect(self.slot_changeFilePath) | |||||
| self.ui.cb_filepaths.currentIndexChanged.connect(self.slot_filePathTabChanged) | |||||
| self.ui.lw_files_audio.currentRowChanged.connect(self.slot_filePathRowChanged) | |||||
| self.ui.lw_files_midi.currentRowChanged.connect(self.slot_filePathRowChanged) | |||||
| self.ui.ch_main_experimental.toggled.connect(self.slot_enableExperimental) | self.ui.ch_main_experimental.toggled.connect(self.slot_enableExperimental) | ||||
| self.ui.ch_exp_wine_bridges.toggled.connect(self.slot_enableWineBridges) | self.ui.ch_exp_wine_bridges.toggled.connect(self.slot_enableWineBridges) | ||||
| self.ui.cb_exp_plugin_bridges.toggled.connect(self.slot_pluginBridgesToggled) | self.ui.cb_exp_plugin_bridges.toggled.connect(self.slot_pluginBridgesToggled) | ||||
| @@ -468,8 +481,14 @@ class CarlaSettingsW(QDialog): | |||||
| self.ui.lw_sf2.setCurrentRow(0) | self.ui.lw_sf2.setCurrentRow(0) | ||||
| self.ui.lw_sfz.setCurrentRow(0) | self.ui.lw_sfz.setCurrentRow(0) | ||||
| self.ui.lw_files_audio.setCurrentRow(0) | |||||
| self.ui.lw_files_midi.setCurrentRow(0) | |||||
| self.ui.lw_page.setCurrentCell(0, 0) | self.ui.lw_page.setCurrentCell(0, 0) | ||||
| self.slot_filePathTabChanged(0) | |||||
| self.slot_pluginPathTabChanged(0) | |||||
| self.adjustSize() | self.adjustSize() | ||||
| # -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
| @@ -602,7 +621,24 @@ class CarlaSettingsW(QDialog): | |||||
| self.ui.rb_osc_udp_port_specific.setChecked(True) | self.ui.rb_osc_udp_port_specific.setChecked(True) | ||||
| # ---------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------- | ||||
| # Paths | |||||
| # File Paths | |||||
| audioPaths = toList(settings.value(CARLA_KEY_PATHS_AUDIO, CARLA_DEFAULT_FILE_PATH_AUDIO)) | |||||
| midiPaths = toList(settings.value(CARLA_KEY_PATHS_MIDI, CARLA_DEFAULT_FILE_PATH_MIDI)) | |||||
| audioPaths.sort() | |||||
| midiPaths.sort() | |||||
| for audioPath in audioPaths: | |||||
| if not audioPath: continue | |||||
| self.ui.lw_files_audio.addItem(audioPath) | |||||
| for midiPath in midiPaths: | |||||
| if not midiPath: continue | |||||
| self.ui.lw_files_midi.addItem(midiPath) | |||||
| # ---------------------------------------------------------------------------------------------------- | |||||
| # Plugin Paths | |||||
| ladspas = toList(settings.value(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH)) | ladspas = toList(settings.value(CARLA_KEY_PATHS_LADSPA, CARLA_DEFAULT_LADSPA_PATH)) | ||||
| dssis = toList(settings.value(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH)) | dssis = toList(settings.value(CARLA_KEY_PATHS_DSSI, CARLA_DEFAULT_DSSI_PATH)) | ||||
| @@ -794,7 +830,25 @@ class CarlaSettingsW(QDialog): | |||||
| settings.setValue(CARLA_KEY_OSC_UDP_PORT_NUMBER, self.ui.sb_osc_udp_port_number.value()) | settings.setValue(CARLA_KEY_OSC_UDP_PORT_NUMBER, self.ui.sb_osc_udp_port_number.value()) | ||||
| # ---------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------- | ||||
| # Paths | |||||
| # File Paths | |||||
| audioPaths = [] | |||||
| midiPaths = [] | |||||
| for i in range(self.ui.lw_files_audio.count()): | |||||
| audioPaths.append(self.ui.lw_files_audio.item(i).text()) | |||||
| for i in range(self.ui.lw_files_midi.count()): | |||||
| midiPaths.append(self.ui.lw_files_midi.item(i).text()) | |||||
| self.host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_AUDIO, splitter.join(audioPaths)) | |||||
| self.host.set_engine_option(ENGINE_OPTION_FILE_PATH, FILE_MIDI, splitter.join(midiPaths)) | |||||
| settings.setValue(CARLA_KEY_PATHS_AUDIO, audioPaths) | |||||
| settings.setValue(CARLA_KEY_PATHS_MIDI, midiPaths) | |||||
| # ---------------------------------------------------------------------------------------------------- | |||||
| # Plugin Paths | |||||
| ladspas = [] | ladspas = [] | ||||
| dssis = [] | dssis = [] | ||||
| @@ -934,12 +988,24 @@ class CarlaSettingsW(QDialog): | |||||
| self.ui.rb_osc_udp_port_specific.setChecked(True) | self.ui.rb_osc_udp_port_specific.setChecked(True) | ||||
| # ---------------------------------------------------------------------------------------------------- | # ---------------------------------------------------------------------------------------------------- | ||||
| # Paths | |||||
| # Plugin Paths | |||||
| elif currentRow == self.TAB_INDEX_FILEPATHS: | |||||
| curIndex = self.ui.tw_filepaths.currentIndex() | |||||
| if curIndex == self.FILEPATH_INDEX_AUDIO: | |||||
| self.ui.lw_files_audio.clear() | |||||
| elif curIndex == self.FILEPATH_INDEX_MIDI: | |||||
| self.ui.lw_files_midi.clear() | |||||
| # ---------------------------------------------------------------------------------------------------- | |||||
| # Plugin Paths | |||||
| elif currentRow == self.TAB_INDEX_PATHS: | |||||
| elif currentRow == self.TAB_INDEX_PLUGINPATHS: | |||||
| curIndex = self.ui.tw_paths.currentIndex() | curIndex = self.ui.tw_paths.currentIndex() | ||||
| if curIndex == self.PATH_INDEX_LADSPA: | |||||
| if curIndex == self.PLUGINPATH_INDEX_LADSPA: | |||||
| paths = CARLA_DEFAULT_LADSPA_PATH | paths = CARLA_DEFAULT_LADSPA_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_ladspa.clear() | self.ui.lw_ladspa.clear() | ||||
| @@ -948,7 +1014,7 @@ class CarlaSettingsW(QDialog): | |||||
| if not path: continue | if not path: continue | ||||
| self.ui.lw_ladspa.addItem(path) | self.ui.lw_ladspa.addItem(path) | ||||
| elif curIndex == self.PATH_INDEX_DSSI: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_DSSI: | |||||
| paths = CARLA_DEFAULT_DSSI_PATH | paths = CARLA_DEFAULT_DSSI_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_dssi.clear() | self.ui.lw_dssi.clear() | ||||
| @@ -957,7 +1023,7 @@ class CarlaSettingsW(QDialog): | |||||
| if not path: continue | if not path: continue | ||||
| self.ui.lw_dssi.addItem(path) | self.ui.lw_dssi.addItem(path) | ||||
| elif curIndex == self.PATH_INDEX_LV2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_LV2: | |||||
| paths = CARLA_DEFAULT_LV2_PATH | paths = CARLA_DEFAULT_LV2_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_lv2.clear() | self.ui.lw_lv2.clear() | ||||
| @@ -966,7 +1032,7 @@ class CarlaSettingsW(QDialog): | |||||
| if not path: continue | if not path: continue | ||||
| self.ui.lw_lv2.addItem(path) | self.ui.lw_lv2.addItem(path) | ||||
| elif curIndex == self.PATH_INDEX_VST2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST2: | |||||
| paths = CARLA_DEFAULT_VST2_PATH | paths = CARLA_DEFAULT_VST2_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_vst.clear() | self.ui.lw_vst.clear() | ||||
| @@ -975,7 +1041,7 @@ class CarlaSettingsW(QDialog): | |||||
| if not path: continue | if not path: continue | ||||
| self.ui.lw_vst.addItem(path) | self.ui.lw_vst.addItem(path) | ||||
| elif curIndex == self.PATH_INDEX_VST3: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST3: | |||||
| paths = CARLA_DEFAULT_VST3_PATH | paths = CARLA_DEFAULT_VST3_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_vst3.clear() | self.ui.lw_vst3.clear() | ||||
| @@ -984,7 +1050,7 @@ class CarlaSettingsW(QDialog): | |||||
| if not path: continue | if not path: continue | ||||
| self.ui.lw_vst3.addItem(path) | self.ui.lw_vst3.addItem(path) | ||||
| elif curIndex == self.PATH_INDEX_SF2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SF2: | |||||
| paths = CARLA_DEFAULT_SF2_PATH | paths = CARLA_DEFAULT_SF2_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_sf2.clear() | self.ui.lw_sf2.clear() | ||||
| @@ -993,7 +1059,7 @@ class CarlaSettingsW(QDialog): | |||||
| if not path: continue | if not path: continue | ||||
| self.ui.lw_sf2.addItem(path) | self.ui.lw_sf2.addItem(path) | ||||
| elif curIndex == self.PATH_INDEX_SFZ: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SFZ: | |||||
| paths = CARLA_DEFAULT_SFZ_PATH | paths = CARLA_DEFAULT_SFZ_PATH | ||||
| paths.sort() | paths.sort() | ||||
| self.ui.lw_sfz.clear() | self.ui.lw_sfz.clear() | ||||
| @@ -1113,57 +1179,57 @@ class CarlaSettingsW(QDialog): | |||||
| curIndex = self.ui.tw_paths.currentIndex() | curIndex = self.ui.tw_paths.currentIndex() | ||||
| if curIndex == self.PATH_INDEX_LADSPA: | |||||
| if curIndex == self.PLUGINPATH_INDEX_LADSPA: | |||||
| self.ui.lw_ladspa.addItem(newPath) | self.ui.lw_ladspa.addItem(newPath) | ||||
| elif curIndex == self.PATH_INDEX_DSSI: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_DSSI: | |||||
| self.ui.lw_dssi.addItem(newPath) | self.ui.lw_dssi.addItem(newPath) | ||||
| elif curIndex == self.PATH_INDEX_LV2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_LV2: | |||||
| self.ui.lw_lv2.addItem(newPath) | self.ui.lw_lv2.addItem(newPath) | ||||
| elif curIndex == self.PATH_INDEX_VST2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST2: | |||||
| self.ui.lw_vst.addItem(newPath) | self.ui.lw_vst.addItem(newPath) | ||||
| elif curIndex == self.PATH_INDEX_VST3: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST3: | |||||
| self.ui.lw_vst3.addItem(newPath) | self.ui.lw_vst3.addItem(newPath) | ||||
| elif curIndex == self.PATH_INDEX_SF2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SF2: | |||||
| self.ui.lw_sf2.addItem(newPath) | self.ui.lw_sf2.addItem(newPath) | ||||
| elif curIndex == self.PATH_INDEX_SFZ: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SFZ: | |||||
| self.ui.lw_sfz.addItem(newPath) | self.ui.lw_sfz.addItem(newPath) | ||||
| @pyqtSlot() | @pyqtSlot() | ||||
| def slot_removePluginPath(self): | def slot_removePluginPath(self): | ||||
| curIndex = self.ui.tw_paths.currentIndex() | curIndex = self.ui.tw_paths.currentIndex() | ||||
| if curIndex == self.PATH_INDEX_LADSPA: | |||||
| if curIndex == self.PLUGINPATH_INDEX_LADSPA: | |||||
| self.ui.lw_ladspa.takeItem(self.ui.lw_ladspa.currentRow()) | self.ui.lw_ladspa.takeItem(self.ui.lw_ladspa.currentRow()) | ||||
| elif curIndex == self.PATH_INDEX_DSSI: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_DSSI: | |||||
| self.ui.lw_dssi.takeItem(self.ui.lw_dssi.currentRow()) | self.ui.lw_dssi.takeItem(self.ui.lw_dssi.currentRow()) | ||||
| elif curIndex == self.PATH_INDEX_LV2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_LV2: | |||||
| self.ui.lw_lv2.takeItem(self.ui.lw_lv2.currentRow()) | self.ui.lw_lv2.takeItem(self.ui.lw_lv2.currentRow()) | ||||
| elif curIndex == self.PATH_INDEX_VST2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST2: | |||||
| self.ui.lw_vst.takeItem(self.ui.lw_vst.currentRow()) | self.ui.lw_vst.takeItem(self.ui.lw_vst.currentRow()) | ||||
| elif curIndex == self.PATH_INDEX_VST3: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST3: | |||||
| self.ui.lw_vst3.takeItem(self.ui.lw_vst3.currentRow()) | self.ui.lw_vst3.takeItem(self.ui.lw_vst3.currentRow()) | ||||
| elif curIndex == self.PATH_INDEX_SF2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SF2: | |||||
| self.ui.lw_sf2.takeItem(self.ui.lw_sf2.currentRow()) | self.ui.lw_sf2.takeItem(self.ui.lw_sf2.currentRow()) | ||||
| elif curIndex == self.PATH_INDEX_SFZ: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SFZ: | |||||
| self.ui.lw_sfz.takeItem(self.ui.lw_sfz.currentRow()) | self.ui.lw_sfz.takeItem(self.ui.lw_sfz.currentRow()) | ||||
| @pyqtSlot() | @pyqtSlot() | ||||
| def slot_changePluginPath(self): | def slot_changePluginPath(self): | ||||
| curIndex = self.ui.tw_paths.currentIndex() | curIndex = self.ui.tw_paths.currentIndex() | ||||
| if curIndex == self.PATH_INDEX_LADSPA: | |||||
| if curIndex == self.PLUGINPATH_INDEX_LADSPA: | |||||
| currentPath = self.ui.lw_ladspa.currentItem().text() | currentPath = self.ui.lw_ladspa.currentItem().text() | ||||
| elif curIndex == self.PATH_INDEX_DSSI: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_DSSI: | |||||
| currentPath = self.ui.lw_dssi.currentItem().text() | currentPath = self.ui.lw_dssi.currentItem().text() | ||||
| elif curIndex == self.PATH_INDEX_LV2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_LV2: | |||||
| currentPath = self.ui.lw_lv2.currentItem().text() | currentPath = self.ui.lw_lv2.currentItem().text() | ||||
| elif curIndex == self.PATH_INDEX_VST2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST2: | |||||
| currentPath = self.ui.lw_vst.currentItem().text() | currentPath = self.ui.lw_vst.currentItem().text() | ||||
| elif curIndex == self.PATH_INDEX_VST3: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST3: | |||||
| currentPath = self.ui.lw_vst3.currentItem().text() | currentPath = self.ui.lw_vst3.currentItem().text() | ||||
| elif curIndex == self.PATH_INDEX_SF2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SF2: | |||||
| currentPath = self.ui.lw_sf2.currentItem().text() | currentPath = self.ui.lw_sf2.currentItem().text() | ||||
| elif curIndex == self.PATH_INDEX_SFZ: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SFZ: | |||||
| currentPath = self.ui.lw_sfz.currentItem().text() | currentPath = self.ui.lw_sfz.currentItem().text() | ||||
| else: | else: | ||||
| currentPath = "" | currentPath = "" | ||||
| @@ -1173,38 +1239,38 @@ class CarlaSettingsW(QDialog): | |||||
| if not newPath: | if not newPath: | ||||
| return | return | ||||
| if curIndex == self.PATH_INDEX_LADSPA: | |||||
| if curIndex == self.PLUGINPATH_INDEX_LADSPA: | |||||
| self.ui.lw_ladspa.currentItem().setText(newPath) | self.ui.lw_ladspa.currentItem().setText(newPath) | ||||
| elif curIndex == self.PATH_INDEX_DSSI: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_DSSI: | |||||
| self.ui.lw_dssi.currentItem().setText(newPath) | self.ui.lw_dssi.currentItem().setText(newPath) | ||||
| elif curIndex == self.PATH_INDEX_LV2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_LV2: | |||||
| self.ui.lw_lv2.currentItem().setText(newPath) | self.ui.lw_lv2.currentItem().setText(newPath) | ||||
| elif curIndex == self.PATH_INDEX_VST2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST2: | |||||
| self.ui.lw_vst.currentItem().setText(newPath) | self.ui.lw_vst.currentItem().setText(newPath) | ||||
| elif curIndex == self.PATH_INDEX_VST3: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_VST3: | |||||
| self.ui.lw_vst3.currentItem().setText(newPath) | self.ui.lw_vst3.currentItem().setText(newPath) | ||||
| elif curIndex == self.PATH_INDEX_SF2: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SF2: | |||||
| self.ui.lw_sf2.currentItem().setText(newPath) | self.ui.lw_sf2.currentItem().setText(newPath) | ||||
| elif curIndex == self.PATH_INDEX_SFZ: | |||||
| elif curIndex == self.PLUGINPATH_INDEX_SFZ: | |||||
| self.ui.lw_sfz.currentItem().setText(newPath) | self.ui.lw_sfz.currentItem().setText(newPath) | ||||
| # -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
| @pyqtSlot(int) | @pyqtSlot(int) | ||||
| def slot_pluginPathTabChanged(self, index): | def slot_pluginPathTabChanged(self, index): | ||||
| if index == self.PATH_INDEX_LADSPA: | |||||
| if index == self.PLUGINPATH_INDEX_LADSPA: | |||||
| row = self.ui.lw_ladspa.currentRow() | row = self.ui.lw_ladspa.currentRow() | ||||
| elif index == self.PATH_INDEX_DSSI: | |||||
| elif index == self.PLUGINPATH_INDEX_DSSI: | |||||
| row = self.ui.lw_dssi.currentRow() | row = self.ui.lw_dssi.currentRow() | ||||
| elif index == self.PATH_INDEX_LV2: | |||||
| elif index == self.PLUGINPATH_INDEX_LV2: | |||||
| row = self.ui.lw_lv2.currentRow() | row = self.ui.lw_lv2.currentRow() | ||||
| elif index == self.PATH_INDEX_VST2: | |||||
| elif index == self.PLUGINPATH_INDEX_VST2: | |||||
| row = self.ui.lw_vst.currentRow() | row = self.ui.lw_vst.currentRow() | ||||
| elif index == self.PATH_INDEX_VST3: | |||||
| elif index == self.PLUGINPATH_INDEX_VST3: | |||||
| row = self.ui.lw_vst3.currentRow() | row = self.ui.lw_vst3.currentRow() | ||||
| elif index == self.PATH_INDEX_SF2: | |||||
| elif index == self.PLUGINPATH_INDEX_SF2: | |||||
| row = self.ui.lw_sf2.currentRow() | row = self.ui.lw_sf2.currentRow() | ||||
| elif index == self.PATH_INDEX_SFZ: | |||||
| elif index == self.PLUGINPATH_INDEX_SFZ: | |||||
| row = self.ui.lw_sfz.currentRow() | row = self.ui.lw_sfz.currentRow() | ||||
| else: | else: | ||||
| row = -1 | row = -1 | ||||
| @@ -1221,6 +1287,73 @@ class CarlaSettingsW(QDialog): | |||||
| # -------------------------------------------------------------------------------------------------------- | # -------------------------------------------------------------------------------------------------------- | ||||
| @pyqtSlot() | |||||
| def slot_addFilePath(self): | |||||
| newPath = QFileDialog.getExistingDirectory(self, self.tr("Add Path"), "", QFileDialog.ShowDirsOnly) | |||||
| if not newPath: | |||||
| return | |||||
| curIndex = self.ui.tw_filepaths.currentIndex() | |||||
| if curIndex == self.FILEPATH_INDEX_AUDIO: | |||||
| self.ui.lw_files_audio.addItem(newPath) | |||||
| elif curIndex == self.FILEPATH_INDEX_MIDI: | |||||
| self.ui.lw_files_midi.addItem(newPath) | |||||
| @pyqtSlot() | |||||
| def slot_removeFilePath(self): | |||||
| curIndex = self.ui.tw_filepaths.currentIndex() | |||||
| if curIndex == self.FILEPATH_INDEX_AUDIO: | |||||
| self.ui.lw_files_audio.takeItem(self.ui.lw_files_audio.currentRow()) | |||||
| elif curIndex == self.FILEPATH_INDEX_MIDI: | |||||
| self.ui.lw_files_midi.takeItem(self.ui.lw_files_midi.currentRow()) | |||||
| @pyqtSlot() | |||||
| def slot_changeFilePath(self): | |||||
| curIndex = self.ui.tw_filepaths.currentIndex() | |||||
| if curIndex == self.FILEPATH_INDEX_AUDIO: | |||||
| currentPath = self.ui.lw_files_audio.currentItem().text() | |||||
| elif curIndex == self.FILEPATH_INDEX_MIDI: | |||||
| currentPath = self.ui.lw_files_midi.currentItem().text() | |||||
| else: | |||||
| currentPath = "" | |||||
| newPath = QFileDialog.getExistingDirectory(self, self.tr("Add Path"), currentPath, QFileDialog.ShowDirsOnly) | |||||
| if not newPath: | |||||
| return | |||||
| if curIndex == self.FILEPATH_INDEX_AUDIO: | |||||
| self.ui.lw_files_audio.currentItem().setText(newPath) | |||||
| elif curIndex == self.FILEPATH_INDEX_MIDI: | |||||
| self.ui.lw_files_midi.currentItem().setText(newPath) | |||||
| # -------------------------------------------------------------------------------------------------------- | |||||
| @pyqtSlot(int) | |||||
| def slot_filePathTabChanged(self, index): | |||||
| if index == self.FILEPATH_INDEX_AUDIO: | |||||
| row = self.ui.lw_files_audio.currentRow() | |||||
| elif index == self.FILEPATH_INDEX_MIDI: | |||||
| row = self.ui.lw_files_midi.currentRow() | |||||
| else: | |||||
| row = -1 | |||||
| check = bool(row >= 0) | |||||
| self.ui.b_filepaths_remove.setEnabled(check) | |||||
| self.ui.b_filepaths_change.setEnabled(check) | |||||
| @pyqtSlot(int) | |||||
| def slot_filePathRowChanged(self, row): | |||||
| check = bool(row >= 0) | |||||
| self.ui.b_filepaths_remove.setEnabled(check) | |||||
| self.ui.b_filepaths_change.setEnabled(check) | |||||
| # -------------------------------------------------------------------------------------------------------- | |||||
| def done(self, r): | def done(self, r): | ||||
| QDialog.done(self, r) | QDialog.done(self, r) | ||||
| self.close() | self.close() | ||||
| @@ -222,6 +222,9 @@ CARLA_KEY_OSC_UDP_PORT_ENABLED = "OSC/UDPEnabled" | |||||
| CARLA_KEY_OSC_UDP_PORT_NUMBER = "OSC/UDPNumber" | CARLA_KEY_OSC_UDP_PORT_NUMBER = "OSC/UDPNumber" | ||||
| CARLA_KEY_OSC_UDP_PORT_RANDOM = "OSC/UDPRandom" | CARLA_KEY_OSC_UDP_PORT_RANDOM = "OSC/UDPRandom" | ||||
| CARLA_KEY_PATHS_AUDIO = "Paths/Audio" | |||||
| CARLA_KEY_PATHS_MIDI = "Paths/MIDI" | |||||
| CARLA_KEY_PATHS_LADSPA = "Paths/LADSPA" | CARLA_KEY_PATHS_LADSPA = "Paths/LADSPA" | ||||
| CARLA_KEY_PATHS_DSSI = "Paths/DSSI" | CARLA_KEY_PATHS_DSSI = "Paths/DSSI" | ||||
| CARLA_KEY_PATHS_LV2 = "Paths/LV2" | CARLA_KEY_PATHS_LV2 = "Paths/LV2" | ||||
| @@ -303,7 +306,7 @@ if CARLA_DEFAULT_AUDIO_DRIVER == "JACK": | |||||
| else: | else: | ||||
| CARLA_DEFAULT_PROCESS_MODE = ENGINE_PROCESS_MODE_PATCHBAY | CARLA_DEFAULT_PROCESS_MODE = ENGINE_PROCESS_MODE_PATCHBAY | ||||
| CARLA_DEFAULT_TRANSPORT_MODE = ENGINE_TRANSPORT_MODE_INTERNAL | CARLA_DEFAULT_TRANSPORT_MODE = ENGINE_TRANSPORT_MODE_INTERNAL | ||||
| # OSC | # OSC | ||||
| CARLA_DEFAULT_OSC_ENABLED = not WINDOWS | CARLA_DEFAULT_OSC_ENABLED = not WINDOWS | ||||
| CARLA_DEFAULT_OSC_TCP_PORT_ENABLED = True | CARLA_DEFAULT_OSC_TCP_PORT_ENABLED = True | ||||
| @@ -329,6 +332,12 @@ CARLA_DEFAULT_EXPERIMENTAL_LV2_EXPORT = False | |||||
| CARLA_DEFAULT_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR = False | CARLA_DEFAULT_EXPERIMENTAL_PREVENT_BAD_BEHAVIOUR = False | ||||
| CARLA_DEFAULT_EXPERIMENTAL_LOAD_LIB_GLOBAL = False | CARLA_DEFAULT_EXPERIMENTAL_LOAD_LIB_GLOBAL = False | ||||
| # ------------------------------------------------------------------------------------------------------------ | |||||
| # Default File Folders | |||||
| CARLA_DEFAULT_FILE_PATH_AUDIO = [] | |||||
| CARLA_DEFAULT_FILE_PATH_MIDI = [] | |||||
| # ------------------------------------------------------------------------------------------------------------ | # ------------------------------------------------------------------------------------------------------------ | ||||
| # Default Plugin Folders (get) | # Default Plugin Folders (get) | ||||
| @@ -65,7 +65,8 @@ typedef enum { | |||||
| NATIVE_PLUGIN_USES_TIME = 1 << 10, | NATIVE_PLUGIN_USES_TIME = 1 << 10, | ||||
| NATIVE_PLUGIN_USES_PARENT_ID = 1 << 11, /** can set transient hint to parent */ | NATIVE_PLUGIN_USES_PARENT_ID = 1 << 11, /** can set transient hint to parent */ | ||||
| NATIVE_PLUGIN_HAS_INLINE_DISPLAY = 1 << 12, | NATIVE_PLUGIN_HAS_INLINE_DISPLAY = 1 << 12, | ||||
| NATIVE_PLUGIN_USES_CONTROL_VOLTAGE = 1 << 13 | |||||
| NATIVE_PLUGIN_USES_CONTROL_VOLTAGE = 1 << 13, | |||||
| NATIVE_PLUGIN_REQUESTS_IDLE = 1 << 15, | |||||
| } NativePluginHints; | } NativePluginHints; | ||||
| typedef enum { | typedef enum { | ||||
| @@ -96,21 +97,24 @@ typedef enum { | |||||
| NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED = 2, /** uses opt */ | NATIVE_PLUGIN_OPCODE_SAMPLE_RATE_CHANGED = 2, /** uses opt */ | ||||
| NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED = 3, /** uses value (0=off, 1=on) */ | NATIVE_PLUGIN_OPCODE_OFFLINE_CHANGED = 3, /** uses value (0=off, 1=on) */ | ||||
| NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED = 4, /** uses ptr */ | NATIVE_PLUGIN_OPCODE_UI_NAME_CHANGED = 4, /** uses ptr */ | ||||
| NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE = 5 /** nothing */ | |||||
| NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE = 5, /** nothing */ | |||||
| NATIVE_PLUGIN_OPCODE_IDLE = 6 /** nothing */ | |||||
| } NativePluginDispatcherOpcode; | } NativePluginDispatcherOpcode; | ||||
| typedef enum { | typedef enum { | ||||
| NATIVE_HOST_OPCODE_NULL = 0, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_UPDATE_PARAMETER = 1, /** uses index, -1 for all */ | |||||
| NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM = 2, /** uses index, -1 for all; may use value for channel */ | |||||
| NATIVE_HOST_OPCODE_RELOAD_PARAMETERS = 3, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS = 4, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_RELOAD_ALL = 5, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_UI_UNAVAILABLE = 6, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_HOST_IDLE = 7, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_INTERNAL_PLUGIN = 8, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY = 9, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER = 10 /** uses index, value as bool */ | |||||
| NATIVE_HOST_OPCODE_NULL = 0, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_UPDATE_PARAMETER = 1, /** uses index, -1 for all */ | |||||
| NATIVE_HOST_OPCODE_UPDATE_MIDI_PROGRAM = 2, /** uses index, -1 for all; may use value for channel */ | |||||
| NATIVE_HOST_OPCODE_RELOAD_PARAMETERS = 3, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_RELOAD_MIDI_PROGRAMS = 4, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_RELOAD_ALL = 5, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_UI_UNAVAILABLE = 6, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_HOST_IDLE = 7, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_INTERNAL_PLUGIN = 8, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY = 9, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_UI_TOUCH_PARAMETER = 10, /** uses index, value as bool */ | |||||
| NATIVE_HOST_OPCODE_REQUEST_IDLE = 11, /** nothing */ | |||||
| NATIVE_HOST_OPCODE_GET_FILE_PATH = 12 /** uses ptr as string for file type */ | |||||
| } NativeHostDispatcherOpcode; | } NativeHostDispatcherOpcode; | ||||
| /* ------------------------------------------------------------------------------------------------------------ | /* ------------------------------------------------------------------------------------------------------------ | ||||
| @@ -27,7 +27,7 @@ | |||||
| * @{ | * @{ | ||||
| */ | */ | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| // Native Plugin Class | // Native Plugin Class | ||||
| class NativePluginClass | class NativePluginClass | ||||
| @@ -225,6 +225,13 @@ protected: | |||||
| pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f); | pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_HOST_IDLE, 0, 0, nullptr, 0.0f); | ||||
| } | } | ||||
| void hostRequestIdle() const | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,); | |||||
| pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_REQUEST_IDLE, 0, 0, nullptr, 0.0f); | |||||
| } | |||||
| void hostQueueDrawInlineDisplay() | void hostQueueDrawInlineDisplay() | ||||
| { | { | ||||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,); | CARLA_SAFE_ASSERT_RETURN(pHost != nullptr,); | ||||
| @@ -232,6 +239,17 @@ protected: | |||||
| pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY, 0, 0, nullptr, 0.0f); | pHost->dispatcher(pHost->handle, NATIVE_HOST_OPCODE_QUEUE_INLINE_DISPLAY, 0, 0, nullptr, 0.0f); | ||||
| } | } | ||||
| const char* hostGetFilePath(const char* const filetype) const | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(pHost != nullptr, nullptr); | |||||
| return (const char*)(uintptr_t)pHost->dispatcher(pHost->handle, | |||||
| NATIVE_HOST_OPCODE_GET_FILE_PATH, | |||||
| 0, 0, | |||||
| (void*)const_cast<char*>(filetype), | |||||
| 0.0f); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Plugin parameter calls | // Plugin parameter calls | ||||
| @@ -394,6 +412,8 @@ protected: | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| virtual void idle() {} | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| private: | private: | ||||
| @@ -521,6 +541,9 @@ public: | |||||
| return 0; | return 0; | ||||
| case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE: | case NATIVE_PLUGIN_OPCODE_GET_INTERNAL_HANDLE: | ||||
| return 0; | return 0; | ||||
| case NATIVE_PLUGIN_OPCODE_IDLE: | |||||
| handlePtr->idle(); | |||||
| return 0; | |||||
| } | } | ||||
| return 0; | return 0; | ||||
| @@ -542,7 +565,7 @@ public: | |||||
| /**@}*/ | /**@}*/ | ||||
| // --------------------------------------------------------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| // -Weffc++ compat ext widget | // -Weffc++ compat ext widget | ||||
| extern "C" { | extern "C" { | ||||
| @@ -559,7 +582,7 @@ typedef struct _NativeInlineDisplayImageSurfaceCompat { | |||||
| } | } | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| #define PluginClassEND(ClassName) \ | #define PluginClassEND(ClassName) \ | ||||
| public: \ | public: \ | ||||
| @@ -597,6 +620,6 @@ public: \ | |||||
| ClassName::_render_inline_display, \ | ClassName::_render_inline_display, \ | ||||
| 0, 0 | 0, 0 | ||||
| // ----------------------------------------------------------------------- | |||||
| // -------------------------------------------------------------------------------------------------------------------- | |||||
| #endif // CARLA_NATIVE_HPP_INCLUDED | #endif // CARLA_NATIVE_HPP_INCLUDED | ||||
| @@ -0,0 +1,206 @@ | |||||
| /* | |||||
| * Carla Native Plugin API (C++) | |||||
| * Copyright (C) 2012-2019 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 | |||||
| * published by the Free Software Foundation; either version 2 of | |||||
| * the License, or any later version. | |||||
| * | |||||
| * This program is distributed in the hope that it will be useful, | |||||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
| * GNU General Public License for more details. | |||||
| * | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||||
| */ | |||||
| #ifndef CARLA_NATIVE_PROGRAMS_HPP_INCLUDED | |||||
| #define CARLA_NATIVE_PROGRAMS_HPP_INCLUDED | |||||
| #include "CarlaNative.hpp" | |||||
| #include "CarlaMathUtils.hpp" | |||||
| #include "CarlaMutex.hpp" | |||||
| #include "water/files/File.h" | |||||
| #include "water/memory/SharedResourcePointer.h" | |||||
| #include "water/text/StringArray.h" | |||||
| using water::Array; | |||||
| using water::File; | |||||
| using water::SharedResourcePointer; | |||||
| using water::String; | |||||
| using water::StringArray; | |||||
| /*! | |||||
| * @defgroup CarlaNativeAPI Carla Native API | |||||
| * @{ | |||||
| */ | |||||
| // ----------------------------------------------------------------------- | |||||
| // ... | |||||
| enum FileType { | |||||
| FileNone, | |||||
| FileAudio, | |||||
| FileMIDI, | |||||
| }; | |||||
| template <FileType FileType> | |||||
| struct NativePluginPresetManager { | |||||
| StringArray filenames; | |||||
| NativePluginPresetManager(const char* const paths, const char* const wildcard) | |||||
| : filenames() | |||||
| { | |||||
| CARLA_SAFE_ASSERT_RETURN(paths != nullptr,); | |||||
| CARLA_SAFE_ASSERT_RETURN(wildcard != nullptr,); | |||||
| if (paths[0] == '\0' || wildcard[0] == '\0') | |||||
| return; | |||||
| const StringArray splitPaths(StringArray::fromTokens(paths, CARLA_OS_SPLIT_STR, "")); | |||||
| for (String *it = splitPaths.begin(), *end = splitPaths.end(); it != end; ++it) | |||||
| { | |||||
| Array<File> results; | |||||
| if (File(*it).findChildFiles(results, File::findFiles|File::ignoreHiddenFiles, true, wildcard) > 0) | |||||
| { | |||||
| for (File *it2 = results.begin(), *end2 = results.end(); it2 != end2; ++it2) | |||||
| filenames.add(it2->getFullPathName()); | |||||
| } | |||||
| } | |||||
| filenames.sort(true); | |||||
| } | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| // Native Plugin with MIDI programs class | |||||
| template <FileType FileType> | |||||
| class NativePluginWithMidiPrograms : public NativePluginClass | |||||
| { | |||||
| public: | |||||
| typedef SharedResourcePointer<NativePluginPresetManager<FileType>> NativeMidiPrograms; | |||||
| NativePluginWithMidiPrograms(const NativeHostDescriptor* const host, | |||||
| const NativeMidiPrograms& programs, | |||||
| const uint32_t numOutputs) | |||||
| : NativePluginClass(host), | |||||
| fRetMidiProgram(), | |||||
| fRetMidiProgramName(), | |||||
| fNextFilename(nullptr), | |||||
| fProgramChangeMutex(), | |||||
| kPrograms(programs), | |||||
| kNumOutputs(numOutputs) {} | |||||
| protected: | |||||
| // ------------------------------------------------------------------- | |||||
| // New Plugin program calls | |||||
| virtual void setStateFromFile(const char* filename) = 0; | |||||
| virtual void process2(const float** inBuffer, float** outBuffer, uint32_t frames, | |||||
| const NativeMidiEvent* midiEvents, uint32_t midiEventCount) = 0; | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin midi-program calls | |||||
| uint32_t getMidiProgramCount() const override | |||||
| { | |||||
| const NativePluginPresetManager<FileType>& pm(kPrograms.get()); | |||||
| return static_cast<uint32_t>(pm.filenames.size()); | |||||
| } | |||||
| const NativeMidiProgram* getMidiProgramInfo(const uint32_t uindex) const override | |||||
| { | |||||
| const int index = static_cast<int>(uindex); | |||||
| const NativePluginPresetManager<FileType>& pm(kPrograms.get()); | |||||
| CARLA_SAFE_ASSERT_RETURN(index < pm.filenames.size(), nullptr); | |||||
| fRetMidiProgramName = File(pm.filenames.strings.getUnchecked(index)).getFileNameWithoutExtension(); | |||||
| fRetMidiProgram.bank = 0; | |||||
| fRetMidiProgram.program = uindex; | |||||
| fRetMidiProgram.name = fRetMidiProgramName.toRawUTF8(); | |||||
| return &fRetMidiProgram; | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin state calls | |||||
| void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program) override | |||||
| { | |||||
| const int iprogram = static_cast<int>(program); | |||||
| const NativePluginPresetManager<FileType>& pm(kPrograms.get()); | |||||
| CARLA_SAFE_ASSERT_RETURN(iprogram < pm.filenames.size(),); | |||||
| const char* const filename(pm.filenames.strings.getUnchecked(iprogram).toRawUTF8()); | |||||
| const CarlaMutexLocker cml(fProgramChangeMutex); | |||||
| if (isOffline()) | |||||
| { | |||||
| setStateFromFile(filename); | |||||
| } | |||||
| else | |||||
| { | |||||
| fNextFilename = filename; | |||||
| hostRequestIdle(); | |||||
| } | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin process calls | |||||
| void process(const float** const inBuffer, float** const outBuffer, uint32_t frames, | |||||
| const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override | |||||
| { | |||||
| const CarlaMutexTryLocker cmtl(fProgramChangeMutex, isOffline()); | |||||
| if (cmtl.wasLocked()) | |||||
| { | |||||
| process2(inBuffer, outBuffer, frames, midiEvents, midiEventCount); | |||||
| } | |||||
| else | |||||
| { | |||||
| for (uint32_t i=0; i<kNumOutputs; ++i) | |||||
| carla_zeroFloats(outBuffer[i], frames); | |||||
| } | |||||
| } | |||||
| // ------------------------------------------------------------------- | |||||
| // Plugin dispatcher calls | |||||
| void idle() override | |||||
| { | |||||
| if (const char* const filename = fNextFilename) | |||||
| { | |||||
| const CarlaMutexLocker cml(fProgramChangeMutex); | |||||
| fNextFilename = nullptr; | |||||
| setStateFromFile(filename); | |||||
| } | |||||
| } | |||||
| private: | |||||
| mutable NativeMidiProgram fRetMidiProgram; | |||||
| mutable String fRetMidiProgramName; | |||||
| const char* fNextFilename; | |||||
| CarlaMutex fProgramChangeMutex; | |||||
| const NativeMidiPrograms& kPrograms; | |||||
| const uint32_t kNumOutputs; | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(NativePluginWithMidiPrograms) | |||||
| }; | |||||
| /**@}*/ | |||||
| // ----------------------------------------------------------------------- | |||||
| #endif // CARLA_NATIVE_PROGRAMS_HPP_INCLUDED | |||||
| @@ -373,7 +373,7 @@ public: | |||||
| */ | */ | ||||
| bool add (const ElementType& newElement) noexcept | bool add (const ElementType& newElement) noexcept | ||||
| { | { | ||||
| if (! data.ensureAllocatedSize (numUsed + 1)) | |||||
| if (! data.ensureAllocatedSize (static_cast<size_t>(numUsed + 1))) | |||||
| return false; | return false; | ||||
| new (data.elements + numUsed++) ElementType (newElement); | new (data.elements + numUsed++) ElementType (newElement); | ||||
| @@ -3,7 +3,7 @@ | |||||
| This file is part of the Water library. | This file is part of the Water library. | ||||
| Copyright (c) 2016 ROLI Ltd. | Copyright (c) 2016 ROLI Ltd. | ||||
| Copyright (C) 2017 Filipe Coelho <falktx@falktx.com> | |||||
| Copyright (C) 2017-2019 Filipe Coelho <falktx@falktx.com> | |||||
| Permission is granted to use this software under the terms of the ISC license | Permission is granted to use this software under the terms of the ISC license | ||||
| http://www.isc.org/downloads/software-support-policy/isc-license/ | http://www.isc.org/downloads/software-support-policy/isc-license/ | ||||
| @@ -94,11 +94,19 @@ public: | |||||
| then a shared object will be created automatically. | then a shared object will be created automatically. | ||||
| */ | */ | ||||
| SharedResourcePointer() | SharedResourcePointer() | ||||
| : sharedObject(nullptr) | |||||
| { | { | ||||
| initialise(); | initialise(); | ||||
| } | } | ||||
| SharedResourcePointer(const char* const v1, const char* const v2) | |||||
| : sharedObject(nullptr) | |||||
| { | |||||
| initialise_v2(v1, v2); | |||||
| } | |||||
| SharedResourcePointer (const SharedResourcePointer&) | SharedResourcePointer (const SharedResourcePointer&) | ||||
| : sharedObject(nullptr) | |||||
| { | { | ||||
| initialise(); | initialise(); | ||||
| } | } | ||||
| @@ -140,7 +148,7 @@ private: | |||||
| static SharedObjectHolder& getSharedObjectHolder() noexcept | static SharedObjectHolder& getSharedObjectHolder() noexcept | ||||
| { | { | ||||
| static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { 0 }; | |||||
| static void* holder [(sizeof (SharedObjectHolder) + sizeof(void*) - 1) / sizeof(void*)] = { nullptr }; | |||||
| return *reinterpret_cast<SharedObjectHolder*> (holder); | return *reinterpret_cast<SharedObjectHolder*> (holder); | ||||
| } | } | ||||
| @@ -157,6 +165,17 @@ private: | |||||
| sharedObject = holder.sharedInstance; | sharedObject = holder.sharedInstance; | ||||
| } | } | ||||
| void initialise_v2(const char* const v1, const char* const v2) | |||||
| { | |||||
| SharedObjectHolder& holder = getSharedObjectHolder(); | |||||
| const SpinLock::ScopedLockType sl (holder.lock); | |||||
| if (++(holder.refCount) == 1) | |||||
| holder.sharedInstance = new SharedObjectType(v1, v2); | |||||
| sharedObject = holder.sharedInstance; | |||||
| } | |||||
| // There's no need to assign to a SharedResourcePointer because every | // There's no need to assign to a SharedResourcePointer because every | ||||
| // instance of the class is exactly the same! | // instance of the class is exactly the same! | ||||
| SharedResourcePointer& operator= (const SharedResourcePointer&) WATER_DELETED_FUNCTION; | SharedResourcePointer& operator= (const SharedResourcePointer&) WATER_DELETED_FUNCTION; | ||||
| @@ -47,7 +47,7 @@ namespace water { | |||||
| class SpinLock | class SpinLock | ||||
| { | { | ||||
| public: | public: | ||||
| inline SpinLock() noexcept {} | |||||
| inline SpinLock() noexcept : lock() {} | |||||
| inline ~SpinLock() noexcept {} | inline ~SpinLock() noexcept {} | ||||
| /** Acquires the lock. | /** Acquires the lock. | ||||
| @@ -237,6 +237,7 @@ static const NativePluginDescriptor sNativePluginDescriptors[] = { | |||||
| |NATIVE_PLUGIN_HAS_INLINE_DISPLAY | |NATIVE_PLUGIN_HAS_INLINE_DISPLAY | ||||
| |NATIVE_PLUGIN_HAS_UI | |NATIVE_PLUGIN_HAS_UI | ||||
| |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | ||||
| |NATIVE_PLUGIN_REQUESTS_IDLE | |||||
| |NATIVE_PLUGIN_USES_TIME), | |NATIVE_PLUGIN_USES_TIME), | ||||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | ||||
| /* audioIns */ 0, | /* audioIns */ 0, | ||||
| @@ -260,6 +261,7 @@ static const NativePluginDescriptor sNativePluginDescriptors[] = { | |||||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | ||||
| |NATIVE_PLUGIN_HAS_UI | |NATIVE_PLUGIN_HAS_UI | ||||
| |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | ||||
| |NATIVE_PLUGIN_REQUESTS_IDLE | |||||
| |NATIVE_PLUGIN_USES_STATE | |NATIVE_PLUGIN_USES_STATE | ||||
| |NATIVE_PLUGIN_USES_TIME), | |NATIVE_PLUGIN_USES_TIME), | ||||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | ||||
| @@ -12,22 +12,35 @@ | |||||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||||
| * GNU General Public License for more details. | * GNU General Public License for more details. | ||||
| * | * | ||||
| * For a full copy of the GNU General Public License see the GPL.txt file | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||||
| */ | */ | ||||
| #include "CarlaNative.hpp" | |||||
| #include "CarlaNativePrograms.hpp" | |||||
| #include "CarlaString.hpp" | #include "CarlaString.hpp" | ||||
| #include "audio-base.hpp" | #include "audio-base.hpp" | ||||
| #define PROGRAM_COUNT 16 | |||||
| static const char* const audiofilesWildcard = | |||||
| #ifdef HAVE_SNDFILE | |||||
| "*.aif;*.aifc;*.aiff;*.au;*.bwf;*.flac;*.htk;*.iff;*.mat4;*.mat5;*.oga;*.ogg;" | |||||
| "*.paf;*.pvf;*.pvf5;*.sd2;*.sf;*.snd;*.svx;*.vcc;*.w64;*.wav;*.xi;" | |||||
| #endif | |||||
| #ifdef HAVE_FFMPEG | |||||
| "*.3g2;*.3gp;*.aac;*.ac3;*.amr;*.ape;*.mp2;*.mp3;*.mpc;*.wma;" | |||||
| # ifndef HAVE_SNDFILE | |||||
| "*.flac;*.oga;*.ogg;*.w64;*.wav;" | |||||
| # endif | |||||
| #endif | |||||
| ; | |||||
| // ----------------------------------------------------------------------- | |||||
| class AudioFilePlugin : public NativePluginClass, | |||||
| class AudioFilePlugin : public NativePluginWithMidiPrograms<FileAudio>, | |||||
| public AbstractAudioPlayer | public AbstractAudioPlayer | ||||
| { | { | ||||
| public: | public: | ||||
| AudioFilePlugin(const NativeHostDescriptor* const host) | AudioFilePlugin(const NativeHostDescriptor* const host) | ||||
| : NativePluginClass(host), | |||||
| : NativePluginWithMidiPrograms(host, fPrograms, 2), | |||||
| AbstractAudioPlayer(), | AbstractAudioPlayer(), | ||||
| fLoopMode(true), | fLoopMode(true), | ||||
| fDoProcess(false), | fDoProcess(false), | ||||
| @@ -35,6 +48,7 @@ public: | |||||
| fMaxFrame(0), | fMaxFrame(0), | ||||
| fPool(), | fPool(), | ||||
| fThread(this), | fThread(this), | ||||
| fPrograms(hostGetFilePath("audio"), audiofilesWildcard), | |||||
| fInlineDisplay() {} | fInlineDisplay() {} | ||||
| ~AudioFilePlugin() override | ~AudioFilePlugin() override | ||||
| @@ -116,8 +130,8 @@ protected: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Plugin process calls | // Plugin process calls | ||||
| void process(const float**, float** const outBuffer, const uint32_t frames, | |||||
| const NativeMidiEvent*, uint32_t) override | |||||
| void process2(const float**, float** const outBuffer, const uint32_t frames, | |||||
| const NativeMidiEvent*, uint32_t) override | |||||
| { | { | ||||
| const NativeTimeInfo* const timePos(getTimeInfo()); | const NativeTimeInfo* const timePos(getTimeInfo()); | ||||
| @@ -254,6 +268,14 @@ protected: | |||||
| uiClosed(); | uiClosed(); | ||||
| } | } | ||||
| // ------------------------------------------------------------------- | |||||
| // Plugin state calls | |||||
| void setStateFromFile(const char* const filename) override | |||||
| { | |||||
| loadFilename(filename); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Plugin dispatcher calls | // Plugin dispatcher calls | ||||
| @@ -374,6 +396,8 @@ private: | |||||
| AudioFilePool fPool; | AudioFilePool fPool; | ||||
| AudioFileThread fThread; | AudioFileThread fThread; | ||||
| NativeMidiPrograms fPrograms; | |||||
| struct InlineDisplay : NativeInlineDisplayImageSurfaceCompat { | struct InlineDisplay : NativeInlineDisplayImageSurfaceCompat { | ||||
| float lastValuesL[32]; | float lastValuesL[32]; | ||||
| float lastValuesR[32]; | float lastValuesR[32]; | ||||
| @@ -454,6 +478,7 @@ static const NativePluginDescriptor audiofileDesc = { | |||||
| |NATIVE_PLUGIN_HAS_INLINE_DISPLAY | |NATIVE_PLUGIN_HAS_INLINE_DISPLAY | ||||
| |NATIVE_PLUGIN_HAS_UI | |NATIVE_PLUGIN_HAS_UI | ||||
| |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | ||||
| |NATIVE_PLUGIN_REQUESTS_IDLE | |||||
| |NATIVE_PLUGIN_USES_TIME), | |NATIVE_PLUGIN_USES_TIME), | ||||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | ||||
| /* audioIns */ 0, | /* audioIns */ 0, | ||||
| @@ -15,7 +15,7 @@ | |||||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | * For a full copy of the GNU General Public License see the doc/GPL.txt file. | ||||
| */ | */ | ||||
| #include "CarlaNative.hpp" | |||||
| #include "CarlaNativePrograms.hpp" | |||||
| #include "midi-base.hpp" | #include "midi-base.hpp" | ||||
| #include "water/files/FileInputStream.h" | #include "water/files/FileInputStream.h" | ||||
| @@ -23,15 +23,16 @@ | |||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| class MidiFilePlugin : public NativePluginClass, | |||||
| class MidiFilePlugin : public NativePluginWithMidiPrograms<FileMIDI>, | |||||
| public AbstractMidiPlayer | public AbstractMidiPlayer | ||||
| { | { | ||||
| public: | public: | ||||
| MidiFilePlugin(const NativeHostDescriptor* const host) | MidiFilePlugin(const NativeHostDescriptor* const host) | ||||
| : NativePluginClass(host), | |||||
| : NativePluginWithMidiPrograms(host, fPrograms, 0), | |||||
| fMidiOut(this), | fMidiOut(this), | ||||
| fNeedsAllNotesOff(false), | fNeedsAllNotesOff(false), | ||||
| fWasPlayingBefore(false) {} | |||||
| fWasPlayingBefore(false), | |||||
| fPrograms(hostGetFilePath("midi"), "*.mid;*.midi") {} | |||||
| protected: | protected: | ||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| @@ -51,7 +52,7 @@ protected: | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // Plugin process calls | // Plugin process calls | ||||
| void process(const float**, float**, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override | |||||
| void process2(const float**, float**, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override | |||||
| { | { | ||||
| const NativeTimeInfo* const timePos(getTimeInfo()); | const NativeTimeInfo* const timePos(getTimeInfo()); | ||||
| @@ -116,6 +117,11 @@ protected: | |||||
| fMidiOut.setState(data); | fMidiOut.setState(data); | ||||
| } | } | ||||
| void setStateFromFile(const char* const filename) override | |||||
| { | |||||
| _loadMidiFile(filename); | |||||
| } | |||||
| // ------------------------------------------------------------------- | // ------------------------------------------------------------------- | ||||
| // AbstractMidiPlayer calls | // AbstractMidiPlayer calls | ||||
| @@ -140,6 +146,7 @@ private: | |||||
| MidiPattern fMidiOut; | MidiPattern fMidiOut; | ||||
| bool fNeedsAllNotesOff; | bool fNeedsAllNotesOff; | ||||
| bool fWasPlayingBefore; | bool fWasPlayingBefore; | ||||
| NativeMidiPrograms fPrograms; | |||||
| void _loadMidiFile(const char* const filename) | void _loadMidiFile(const char* const filename) | ||||
| { | { | ||||
| @@ -223,6 +230,7 @@ static const NativePluginDescriptor midifileDesc = { | |||||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | ||||
| |NATIVE_PLUGIN_HAS_UI | |NATIVE_PLUGIN_HAS_UI | ||||
| |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | |NATIVE_PLUGIN_NEEDS_UI_OPEN_SAVE | ||||
| |NATIVE_PLUGIN_REQUESTS_IDLE | |||||
| |NATIVE_PLUGIN_USES_STATE | |NATIVE_PLUGIN_USES_STATE | ||||
| |NATIVE_PLUGIN_USES_TIME), | |NATIVE_PLUGIN_USES_TIME), | ||||
| /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | /* supports */ NATIVE_PLUGIN_SUPPORTS_NOTHING, | ||||
| @@ -79,6 +79,23 @@ const char* BinaryType2Str(const BinaryType type) noexcept | |||||
| return nullptr; | return nullptr; | ||||
| } | } | ||||
| static inline | |||||
| const char* FileType2Str(const FileType type) noexcept | |||||
| { | |||||
| switch (type) | |||||
| { | |||||
| case FILE_NONE: | |||||
| return "FILE_NONE"; | |||||
| case FILE_AUDIO: | |||||
| return "FILE_AUDIO"; | |||||
| case FILE_MIDI: | |||||
| return "FILE_MIDI"; | |||||
| } | |||||
| carla_stderr("CarlaBackend::FileType2Str(%i) - invalid type", type); | |||||
| return nullptr; | |||||
| } | |||||
| static inline | static inline | ||||
| const char* PluginType2Str(const PluginType type) noexcept | const char* PluginType2Str(const PluginType type) noexcept | ||||
| { | { | ||||
| @@ -337,6 +354,8 @@ const char* EngineOption2Str(const EngineOption option) noexcept | |||||
| return "ENGINE_OPTION_OSC_PORT_UDP"; | return "ENGINE_OPTION_OSC_PORT_UDP"; | ||||
| case ENGINE_OPTION_OSC_PORT_TCP: | case ENGINE_OPTION_OSC_PORT_TCP: | ||||
| return "ENGINE_OPTION_OSC_PORT_TCP"; | return "ENGINE_OPTION_OSC_PORT_TCP"; | ||||
| case ENGINE_OPTION_FILE_PATH: | |||||
| return "ENGINE_OPTION_FILE_PATH"; | |||||
| case ENGINE_OPTION_PLUGIN_PATH: | case ENGINE_OPTION_PLUGIN_PATH: | ||||
| return "ENGINE_OPTION_PLUGIN_PATH"; | return "ENGINE_OPTION_PLUGIN_PATH"; | ||||
| case ENGINE_OPTION_PATH_BINARIES: | case ENGINE_OPTION_PATH_BINARIES: | ||||