@@ -7,7 +7,7 @@ | |||
<x>0</x> | |||
<y>0</y> | |||
<width>756</width> | |||
<height>218</height> | |||
<height>283</height> | |||
</rect> | |||
</property> | |||
<property name="windowTitle"> | |||
@@ -15,6 +15,140 @@ | |||
</property> | |||
<widget class="QWidget" name="centralwidget"> | |||
<layout class="QVBoxLayout" name="verticalLayout"> | |||
<property name="leftMargin"> | |||
<number>0</number> | |||
</property> | |||
<property name="topMargin"> | |||
<number>0</number> | |||
</property> | |||
<property name="rightMargin"> | |||
<number>0</number> | |||
</property> | |||
<property name="bottomMargin"> | |||
<number>2</number> | |||
</property> | |||
<item> | |||
<widget class="QFrame" name="frame_transport"> | |||
<property name="frameShape"> | |||
<enum>QFrame::StyledPanel</enum> | |||
</property> | |||
<property name="frameShadow"> | |||
<enum>QFrame::Raised</enum> | |||
</property> | |||
<layout class="QHBoxLayout" name="horizontalLayout"> | |||
<item> | |||
<widget class="QLabel" name="label"> | |||
<property name="text"> | |||
<string>Transport Mode:</string> | |||
</property> | |||
<property name="alignment"> | |||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QComboBox" name="ch_transport"/> | |||
</item> | |||
<item> | |||
<widget class="Line" name="line"> | |||
<property name="orientation"> | |||
<enum>Qt::Vertical</enum> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QPushButton" name="b_transport_play"> | |||
<property name="maximumSize"> | |||
<size> | |||
<width>22</width> | |||
<height>22</height> | |||
</size> | |||
</property> | |||
<property name="text"> | |||
<string/> | |||
</property> | |||
<property name="icon"> | |||
<iconset resource="../resources.qrc"> | |||
<normaloff>:/16x16/media-playback-start.png</normaloff>:/16x16/media-playback-start.png</iconset> | |||
</property> | |||
<property name="checkable"> | |||
<bool>true</bool> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QPushButton" name="b_transport_stop"> | |||
<property name="maximumSize"> | |||
<size> | |||
<width>22</width> | |||
<height>22</height> | |||
</size> | |||
</property> | |||
<property name="text"> | |||
<string/> | |||
</property> | |||
<property name="icon"> | |||
<iconset resource="../resources.qrc"> | |||
<normaloff>:/16x16/media-playback-stop.png</normaloff>:/16x16/media-playback-stop.png</iconset> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QPushButton" name="b_transport_back"> | |||
<property name="maximumSize"> | |||
<size> | |||
<width>22</width> | |||
<height>22</height> | |||
</size> | |||
</property> | |||
<property name="text"> | |||
<string/> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QPushButton" name="b_transport_forward"> | |||
<property name="maximumSize"> | |||
<size> | |||
<width>22</width> | |||
<height>22</height> | |||
</size> | |||
</property> | |||
<property name="text"> | |||
<string/> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="Line" name="line_2"> | |||
<property name="orientation"> | |||
<enum>Qt::Vertical</enum> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QLabel" name="label_time"> | |||
<property name="text"> | |||
<string>TIME (TODO)</string> | |||
</property> | |||
</widget> | |||
</item> | |||
<item> | |||
<spacer name="horizontalSpacer"> | |||
<property name="orientation"> | |||
<enum>Qt::Horizontal</enum> | |||
</property> | |||
<property name="sizeHint" stdset="0"> | |||
<size> | |||
<width>40</width> | |||
<height>20</height> | |||
</size> | |||
</property> | |||
</spacer> | |||
</item> | |||
</layout> | |||
</widget> | |||
</item> | |||
<item> | |||
<widget class="QWidget" name="w_plugins" native="true"> | |||
<layout class="QVBoxLayout" name="layout"> | |||
@@ -226,85 +226,92 @@ enum OptionsType { | |||
*/ | |||
OPTION_PROCESS_MODE = 1, | |||
/*! | |||
* Set the engine transport mode.\n | |||
* Default is TRANSPORT_MODE_INTERNAL. | |||
* \see TransportMode | |||
*/ | |||
OPTION_TRANSPORT_MODE = 2, | |||
/*! | |||
* Force mono plugins as stereo, by running 2 instances at the same time. | |||
* \note Not supported by all plugins. | |||
*/ | |||
OPTION_FORCE_STEREO = 2, | |||
OPTION_FORCE_STEREO = 3, | |||
/*! | |||
* Use plugin bridges whenever possible.\n | |||
* Default is no, and not recommended at this point!. | |||
* EXPERIMENTAL AND INCOMPLETE! | |||
*/ | |||
OPTION_PREFER_PLUGIN_BRIDGES = 3, | |||
OPTION_PREFER_PLUGIN_BRIDGES = 4, | |||
/*! | |||
* Use OSC-UI bridges whenever possible, otherwise UIs will be handled in the main thread.\n | |||
* Default is yes. | |||
*/ | |||
OPTION_PREFER_UI_BRIDGES = 4, | |||
OPTION_PREFER_UI_BRIDGES = 5, | |||
#ifdef WANT_DSSI | |||
/*! | |||
* Use (unofficial) dssi-vst chunks feature.\n | |||
* Default is no. | |||
*/ | |||
OPTION_USE_DSSI_VST_CHUNKS = 5, | |||
OPTION_USE_DSSI_VST_CHUNKS = 6, | |||
#endif | |||
/*! | |||
* Maximum number of parameters allowed.\n | |||
* Default is MAX_DEFAULT_PARAMETERS. | |||
*/ | |||
OPTION_MAX_PARAMETERS = 6, | |||
OPTION_MAX_PARAMETERS = 7, | |||
/*! | |||
* Timeout value in ms for how much to wait for OSC-Bridges to respond.\n | |||
* Default is 4000 (4 secs). | |||
*/ | |||
OPTION_OSC_UI_TIMEOUT = 7, | |||
OPTION_OSC_UI_TIMEOUT = 8, | |||
/*! | |||
* Prefered buffer size. | |||
*/ | |||
OPTION_PREFERRED_BUFFER_SIZE = 8, | |||
OPTION_PREFERRED_BUFFER_SIZE = 9, | |||
/*! | |||
* Prefered sample rate. | |||
*/ | |||
OPTION_PREFERRED_SAMPLE_RATE = 9, | |||
OPTION_PREFERRED_SAMPLE_RATE = 10, | |||
#ifndef BUILD_BRIDGE | |||
/*! | |||
* Set path to the native plugin bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_NATIVE = 10, | |||
OPTION_PATH_BRIDGE_NATIVE = 11, | |||
/*! | |||
* Set path to the POSIX 32bit plugin bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_POSIX32 = 11, | |||
OPTION_PATH_BRIDGE_POSIX32 = 12, | |||
/*! | |||
* Set path to the POSIX 64bit plugin bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_POSIX64 = 12, | |||
OPTION_PATH_BRIDGE_POSIX64 = 13, | |||
/*! | |||
* Set path to the Windows 32bit plugin bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_WIN32 = 13, | |||
OPTION_PATH_BRIDGE_WIN32 = 14, | |||
/*! | |||
* Set path to the Windows 64bit plugin bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_WIN64 = 14, | |||
OPTION_PATH_BRIDGE_WIN64 = 15, | |||
#endif | |||
#ifdef WANT_LV2 | |||
@@ -312,43 +319,43 @@ enum OptionsType { | |||
* Set path to the LV2 Gtk2 UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_GTK2 = 15, | |||
OPTION_PATH_BRIDGE_LV2_GTK2 = 16, | |||
/*! | |||
* Set path to the LV2 Gtk3 UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_GTK3 = 16, | |||
OPTION_PATH_BRIDGE_LV2_GTK3 = 17, | |||
/*! | |||
* Set path to the LV2 Qt4 UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_QT4 = 17, | |||
OPTION_PATH_BRIDGE_LV2_QT4 = 18, | |||
/*! | |||
* Set path to the LV2 Qt5 UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_QT5 = 18, | |||
OPTION_PATH_BRIDGE_LV2_QT5 = 19, | |||
/*! | |||
* Set path to the LV2 Cocoa UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_COCOA = 19, | |||
OPTION_PATH_BRIDGE_LV2_COCOA = 20, | |||
/*! | |||
* Set path to the LV2 Windows UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_WINDOWS = 20, | |||
OPTION_PATH_BRIDGE_LV2_WINDOWS = 21, | |||
/*! | |||
* Set path to the LV2 X11 UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_LV2_X11 = 21, | |||
OPTION_PATH_BRIDGE_LV2_X11 = 22, | |||
#endif | |||
#ifdef WANT_VST | |||
@@ -356,19 +363,19 @@ enum OptionsType { | |||
* Set path to the VST Cocoa UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_VST_COCOA = 22, | |||
OPTION_PATH_BRIDGE_VST_COCOA = 23, | |||
/*! | |||
* Set path to the VST HWND UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_VST_HWND = 23, | |||
OPTION_PATH_BRIDGE_VST_HWND = 24, | |||
/*! | |||
* Set path to the VST X11 UI bridge executable.\n | |||
* Default unset. | |||
*/ | |||
OPTION_PATH_BRIDGE_VST_X11 = 24 | |||
OPTION_PATH_BRIDGE_VST_X11 = 25 | |||
#endif | |||
}; | |||
@@ -538,6 +545,14 @@ enum ProcessMode { | |||
PROCESS_MODE_BRIDGE = 4 //!< Special mode, used in plugin-bridges only. RT buffers come from shared memory in a separate host app. | |||
}; | |||
/*! | |||
* All the available transport modes | |||
*/ | |||
enum TransportMode { | |||
TRANSPORT_MODE_INTERNAL = 0, //!< Internal transport mode. | |||
TRANSPORT_MODE_JACK = 1, //!< JACK transport, only available if driver name is "JACK" | |||
}; | |||
/*! | |||
* Callback function the engine will call when something interesting happens. | |||
* | |||
@@ -257,7 +257,8 @@ struct EngineDevices { | |||
* Engine options. | |||
*/ | |||
struct EngineOptions { | |||
ProcessMode processMode; | |||
ProcessMode processMode; | |||
TransportMode transportMode; | |||
bool forceStereo; | |||
bool preferPluginBridges; | |||
@@ -295,6 +296,7 @@ struct EngineOptions { | |||
EngineOptions() | |||
: processMode(PROCESS_MODE_CONTINUOUS_RACK), | |||
transportMode(TRANSPORT_MODE_INTERNAL), | |||
forceStereo(false), | |||
preferPluginBridges(false), | |||
preferUiBridges(true), | |||
@@ -852,6 +854,24 @@ public: | |||
*/ | |||
void setCallback(const CallbackFunc func, void* const ptr); | |||
// ------------------------------------------------------------------- | |||
// Transport | |||
/*! | |||
* TODO. | |||
*/ | |||
virtual void transportPlay(); | |||
/*! | |||
* TODO. | |||
*/ | |||
virtual void transportPause(); | |||
/*! | |||
* TODO. | |||
*/ | |||
virtual void transportRelocate(const uint32_t frame); | |||
// ------------------------------------------------------------------- | |||
// Error handling | |||
@@ -661,7 +661,7 @@ public: | |||
/*! | |||
* Plugin process callback. | |||
*/ | |||
virtual void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset = 0); | |||
virtual void process(float** const inBuffer, float** const outBuffer, const uint32_t frames); | |||
/*! | |||
* Tell the plugin the current buffer size has changed. | |||
@@ -170,6 +170,10 @@ CARLA_EXPORT void carla_set_engine_option(CarlaOptionsType option, int value, co | |||
CARLA_EXPORT bool carla_load_project(const char* filename); | |||
CARLA_EXPORT bool carla_save_project(const char* filename); | |||
CARLA_EXPORT void carla_transport_play(); | |||
CARLA_EXPORT void carla_transport_pause(); | |||
CARLA_EXPORT void carla_transport_relocate(uint32_t frames); | |||
CARLA_EXPORT bool carla_add_plugin(CarlaBinaryType btype, CarlaPluginType ptype, const char* filename, const char* name, const char* label, const void* extraPtr); | |||
CARLA_EXPORT bool carla_remove_plugin(unsigned int pluginId); | |||
CARLA_EXPORT void carla_remove_all_plugins(); | |||
@@ -1064,6 +1064,24 @@ void CarlaEngine::setCallback(const CallbackFunc func, void* const ptr) | |||
kData->callbackPtr = ptr; | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Transport | |||
void CarlaEngine::transportPlay() | |||
{ | |||
kData->time.playing = true; | |||
} | |||
void CarlaEngine::transportPause() | |||
{ | |||
kData->time.playing = false; | |||
} | |||
void CarlaEngine::transportRelocate(const uint32_t frame) | |||
{ | |||
kData->time.frame = frame; | |||
} | |||
// ----------------------------------------------------------------------- | |||
// Error handling | |||
@@ -1141,6 +1159,13 @@ void CarlaEngine::setOption(const OptionsType option, const int value, const cha | |||
fOptions.processMode = static_cast<ProcessMode>(value); | |||
break; | |||
case OPTION_TRANSPORT_MODE: | |||
if (value < CarlaBackend::TRANSPORT_MODE_INTERNAL || value > CarlaBackend::TRANSPORT_MODE_JACK) | |||
return carla_stderr2("carla_set_engine_option(OPTION_TRANSPORT_MODE, %i, \"%s\") - invalid value", value, valueStr); | |||
fOptions.transportMode = static_cast<CarlaBackend::TransportMode>(value); | |||
break; | |||
case OPTION_MAX_PARAMETERS: | |||
CARLA_ENGINE_SET_OPTION_RUNNING_CHECK | |||
@@ -1324,6 +1349,15 @@ void CarlaEngine::proccessPendingEvents() | |||
break; | |||
} | |||
if (kData->time.playing) | |||
kData->time.frame += fBufferSize; | |||
if (fOptions.transportMode == CarlaBackend::TRANSPORT_MODE_INTERNAL) | |||
{ | |||
fTimeInfo.playing = kData->time.playing; | |||
fTimeInfo.frame = kData->time.frame; | |||
} | |||
for (unsigned int i=0; i < kData->curPluginCount; i++) | |||
{ | |||
// TODO - peak values? | |||
@@ -176,6 +176,15 @@ struct CarlaEngineProtectedData { | |||
out(nullptr) {} | |||
} rack; | |||
struct Time { | |||
bool playing; | |||
uint32_t frame; | |||
Time() | |||
: playing(false), | |||
frame(0) {} | |||
} time; | |||
EnginePluginData* plugins; | |||
CarlaEngineProtectedData(CarlaEngine* const engine) | |||
@@ -15,7 +15,7 @@ | |||
* For a full copy of the GNU General Public License see the GPL.txt file | |||
*/ | |||
#ifdef WANT_JACK | |||
#if 1//def WANT_JACK | |||
#include "CarlaEngineInternal.hpp" | |||
#include "CarlaBackendUtils.hpp" | |||
@@ -694,6 +694,33 @@ public: | |||
return new CarlaEngineJackClient(kEngineTypeJack, fOptions.processMode, client); | |||
} | |||
// ------------------------------------------------------------------- | |||
// Transport | |||
void transportPlay() | |||
{ | |||
if (fOptions.transportMode == TRANSPORT_MODE_INTERNAL) | |||
CarlaEngine::transportPlay(); | |||
else if (fClient != nullptr) | |||
jackbridge_transport_start(fClient); | |||
} | |||
void transportPause() | |||
{ | |||
if (fOptions.transportMode == TRANSPORT_MODE_INTERNAL) | |||
CarlaEngine::transportPause(); | |||
else if (fClient != nullptr) | |||
jackbridge_transport_stop(fClient); | |||
} | |||
void transportRelocate(const uint32_t frame) | |||
{ | |||
if (fOptions.transportMode == TRANSPORT_MODE_INTERNAL) | |||
CarlaEngine::transportRelocate(frame); | |||
else if (fClient != nullptr) | |||
jackbridge_transport_locate(fClient, frame); | |||
} | |||
// ------------------------------------- | |||
protected: | |||
@@ -724,6 +751,9 @@ protected: | |||
void saveTransportInfo() | |||
{ | |||
if (fOptions.transportMode != TRANSPORT_MODE_JACK) | |||
return; | |||
fTransportPos.unique_1 = fTransportPos.unique_2 + 1; // invalidate | |||
fTransportState = jackbridge_transport_query(fClient, &fTransportPos); | |||
@@ -427,10 +427,6 @@ protected: | |||
//fMidiOut.sendMessage(); | |||
} | |||
// TESTING | |||
fTimeInfo.playing = true; | |||
fTimeInfo.frame += nframes; | |||
proccessPendingEvents(); | |||
return; | |||
@@ -70,7 +70,7 @@ debug: | |||
# -------------------------------------------------------------- | |||
%.cpp.o: %.cpp ../CarlaEngine.hpp CarlaEngineInternal.hpp CarlaEngineOsc.hpp CarlaEngineThread.hpp | |||
%.cpp.o: %.cpp ../CarlaPlugin.hpp ../CarlaEngine.hpp CarlaEngineInternal.hpp CarlaEngineOsc.hpp CarlaEngineThread.hpp | |||
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
$(SHARED): $(OBJS) $(LIBS) | |||
@@ -908,7 +908,7 @@ void CarlaPlugin::prepareForSave() | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void CarlaPlugin::process(float** const, float** const, const uint32_t, const uint32_t) | |||
void CarlaPlugin::process(float** const, float** const, const uint32_t) | |||
{ | |||
} | |||
@@ -871,7 +871,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
@@ -987,7 +987,7 @@ public: | |||
{ | |||
const EngineEvent& event = kData->event.portIn->getEvent(i); | |||
time = event.time - framesOffset; | |||
time = event.time; | |||
if (time >= frames) | |||
continue; | |||
@@ -1424,7 +1424,7 @@ public: | |||
if (kData->param.data[k].midiCC > 0) | |||
{ | |||
value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); | |||
kData->event.portOut->writeControlEvent(framesOffset, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
} | |||
} | |||
@@ -871,7 +871,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
@@ -948,7 +948,7 @@ public: | |||
{ | |||
const EngineEvent& event = kData->event.portIn->getEvent(i); | |||
time = event.time - framesOffset; | |||
time = event.time; | |||
if (time >= frames) | |||
continue; | |||
@@ -1264,7 +1264,7 @@ public: | |||
if (kData->param.data[k].midiCC > 0) | |||
{ | |||
double value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); | |||
kData->event.portOut->writeControlEvent(framesOffset, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
} | |||
} // End of Control Output | |||
@@ -748,7 +748,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
@@ -813,7 +813,7 @@ public: | |||
{ | |||
const EngineEvent& event = kData->event.portIn->getEvent(i); | |||
time = event.time - framesOffset; | |||
time = event.time; | |||
if (time >= frames) | |||
continue; | |||
@@ -1095,7 +1095,7 @@ public: | |||
if (kData->param.data[k].midiCC > 0) | |||
{ | |||
value = kData->param.ranges[k].normalizeValue(fParamBuffers[k]); | |||
kData->event.portOut->writeControlEvent(framesOffset, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
} | |||
} | |||
@@ -433,7 +433,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
uint32_t midiEventCount = 0; | |||
@@ -463,7 +463,7 @@ public: | |||
if (! cinEvent) | |||
continue; | |||
time = cinEvent->time - framesOffset; | |||
time = cinEvent->time; | |||
if (time >= frames) | |||
continue; | |||
@@ -658,7 +658,7 @@ public: | |||
if (! minEvent) | |||
continue; | |||
time = minEvent->time - framesOffset; | |||
time = minEvent->time; | |||
if (time >= frames) | |||
continue; | |||
@@ -1916,7 +1916,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
uint32_t midiEventCount = 0; | |||
@@ -2024,7 +2024,7 @@ public: | |||
if (! cinEvent) | |||
continue; | |||
time = cinEvent->time - framesOffset; | |||
time = cinEvent->time; | |||
if (time >= frames) | |||
continue; | |||
@@ -2260,7 +2260,7 @@ public: | |||
if (! minEvent) | |||
continue; | |||
time = minEvent->time - framesOffset; | |||
time = minEvent->time; | |||
if (time >= frames) | |||
continue; | |||
@@ -2359,7 +2359,7 @@ public: | |||
} | |||
LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]); | |||
aev->time.frames = framesOffset; | |||
aev->time.frames = 0; | |||
aev->body.type = lv2Pos->type; | |||
aev->body.size = lv2Pos->size; | |||
memcpy(LV2_ATOM_BODY(&aev->body), LV2_ATOM_BODY(lv2Pos), lv2Pos->size); | |||
@@ -2390,7 +2390,7 @@ public: | |||
} | |||
LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]); | |||
aev->time.frames = framesOffset; | |||
aev->time.frames = 0; | |||
aev->body.type = atom->type; | |||
aev->body.size = atom->size; | |||
memcpy(LV2_ATOM_BODY(&aev->body), LV2_ATOM_BODY(atom), atom->size); | |||
@@ -2698,7 +2698,7 @@ public: | |||
if (param.data[k].midiCC > 0) | |||
{ | |||
value = (paramBuffers[k] - param.ranges[k].min) / (param.ranges[k].max - param.ranges[k].min); | |||
param.portCout->writeEvent(CarlaEngineParameterChangeEvent, framesOffset, param.data[k].midiChannel, param.data[k].midiCC, value); | |||
param.portCout->writeEvent(CarlaEngineParameterChangeEvent, 0, param.data[k].midiChannel, param.data[k].midiCC, value); | |||
} | |||
} | |||
} | |||
@@ -55,7 +55,7 @@ debug: | |||
# -------------------------------------------------------------- | |||
%.cpp.o: %.cpp ../CarlaPlugin.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp | |||
%.cpp.o: %.cpp ../CarlaEngine.hpp ../CarlaPlugin.hpp CarlaPluginInternal.hpp CarlaPluginThread.hpp | |||
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
$(SHARED): $(OBJS) $(LIBS) | |||
@@ -954,7 +954,7 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
@@ -1091,7 +1091,7 @@ public: | |||
{ | |||
const EngineEvent& event = kData->event.portIn->getEvent(i); | |||
time = event.time - framesOffset; | |||
time = event.time; | |||
if (time >= frames) | |||
continue; | |||
@@ -1451,7 +1451,7 @@ public: | |||
if (kData->param.data[k].midiCC > 0) | |||
{ | |||
value = kData->param.ranges[k].normalizeValue(curValue); | |||
kData->event.portOut->writeControlEvent(framesOffset, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
kData->event.portOut->writeControlEvent(0, kData->param.data[k].midiChannel, kEngineControlEventTypeParameter, kData->param.data[k].midiCC, value); | |||
} | |||
} | |||
@@ -893,12 +893,12 @@ public: | |||
// ------------------------------------------------------------------- | |||
// Plugin processing | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset) | |||
void process(float** const inBuffer, float** const outBuffer, const uint32_t frames) | |||
{ | |||
uint32_t i, k; | |||
uint32_t midiEventCount = 0; | |||
vstTimeOffset = framesOffset; | |||
vstTimeOffset = 0; | |||
double aInsPeak[2] = { 0.0 }; | |||
double aOutsPeak[2] = { 0.0 }; | |||
@@ -954,7 +954,7 @@ public: | |||
if (! cinEvent) | |||
continue; | |||
time = cinEvent->time - framesOffset; | |||
time = cinEvent->time; | |||
if (time >= frames) | |||
continue; | |||
@@ -1147,7 +1147,7 @@ public: | |||
if (! minEvent) | |||
continue; | |||
time = minEvent->time - framesOffset; | |||
time = minEvent->time; | |||
if (time >= frames) | |||
continue; | |||
@@ -223,12 +223,13 @@ bool carla_engine_init(const char* driverName, const char* clientName) | |||
standalone.engine->setCallback(standalone.callback, nullptr); | |||
#ifndef BUILD_BRIDGE | |||
standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, static_cast<int>(standalone.options.processMode), nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, standalone.options.preferPluginBridges ? 1 : 0, nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, standalone.options.preferUiBridges ? 1 : 0, nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_PROCESS_MODE, static_cast<int>(standalone.options.processMode), nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_TRANSPORT_MODE, static_cast<int>(standalone.options.transportMode), nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_FORCE_STEREO, standalone.options.forceStereo ? 1 : 0, nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_PREFER_PLUGIN_BRIDGES, standalone.options.preferPluginBridges ? 1 : 0, nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_PREFER_UI_BRIDGES, standalone.options.preferUiBridges ? 1 : 0, nullptr); | |||
# ifdef WANT_DSSI | |||
standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_USE_DSSI_VST_CHUNKS, standalone.options.useDssiVstChunks ? 1 : 0, nullptr); | |||
# endif | |||
standalone.engine->setOption(CarlaBackend::OPTION_MAX_PARAMETERS, static_cast<int>(standalone.options.maxParameters), nullptr); | |||
standalone.engine->setOption(CarlaBackend::OPTION_PREFERRED_BUFFER_SIZE, static_cast<int>(standalone.options.preferredBufferSize), nullptr); | |||
@@ -353,6 +354,13 @@ void carla_set_engine_option(CarlaBackend::OptionsType option, int value, const | |||
standalone.options.processMode = static_cast<CarlaBackend::ProcessMode>(value); | |||
break; | |||
case CarlaBackend::OPTION_TRANSPORT_MODE: | |||
if (value < CarlaBackend::TRANSPORT_MODE_INTERNAL || value > CarlaBackend::TRANSPORT_MODE_JACK) | |||
return carla_stderr2("carla_set_engine_option(OPTION_TRANSPORT_MODE, %i, \"%s\") - invalid value", value, valueStr); | |||
standalone.options.transportMode = static_cast<CarlaBackend::TransportMode>(value); | |||
break; | |||
case CarlaBackend::OPTION_FORCE_STEREO: | |||
standalone.options.forceStereo = (value != 0); | |||
break; | |||
@@ -471,6 +479,35 @@ bool carla_save_project(const char* filename) | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
void carla_transport_play() | |||
{ | |||
carla_debug("carla_transport_play()"); | |||
CARLA_ASSERT(standalone.engine != nullptr); | |||
if (standalone.engine != nullptr) | |||
return standalone.engine->transportPlay(); | |||
} | |||
void carla_transport_pause() | |||
{ | |||
carla_debug("carla_transport_pause()"); | |||
CARLA_ASSERT(standalone.engine != nullptr); | |||
if (standalone.engine != nullptr) | |||
return standalone.engine->transportPause(); | |||
} | |||
void carla_transport_relocate(uint32_t frames) | |||
{ | |||
carla_debug("carla_transport_relocate(%i)", frames); | |||
CARLA_ASSERT(standalone.engine != nullptr); | |||
if (standalone.engine != nullptr) | |||
return standalone.engine->transportRelocate(frames); | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
bool carla_add_plugin(CarlaBackend::BinaryType btype, CarlaBackend::PluginType ptype, const char* filename, const char* const name, const char* label, const void* extraStuff) | |||
{ | |||
carla_debug("carla_add_plugin(%s, %s, \"%s\", \"%s\", \"%s\", %p)", CarlaBackend::BinaryType2Str(btype), CarlaBackend::PluginType2Str(ptype), filename, name, label, extraStuff); | |||
@@ -75,7 +75,7 @@ debug: | |||
# -------------------------------------------------------------- | |||
%.cpp.o: %.cpp | |||
%.cpp.o: %.cpp ../CarlaEngine.hpp ../CarlaPlugin.hpp | |||
$(CXX) $< $(BUILD_CXX_FLAGS) -c -o $@ | |||
$(SHARED): $(OBJS) $(LIBS) | |||
@@ -568,6 +568,10 @@ class CarlaMainW(QMainWindow): | |||
self.connect(self.ui.act_help_about, SIGNAL("triggered()"), SLOT("slot_aboutCarla()")) | |||
self.connect(self.ui.act_help_about_qt, SIGNAL("triggered()"), app, SLOT("aboutQt()")) | |||
self.connect(self.ui.ch_transport, SIGNAL("currentIndexChanged(int)"), SLOT("slot_transportModeChanged(int)")) | |||
self.connect(self.ui.b_transport_play, SIGNAL("clicked(bool)"), SLOT("slot_transportPlayPause(bool)")) | |||
self.connect(self.ui.b_transport_stop, SIGNAL("clicked()"), SLOT("slot_transportStop()")) | |||
self.connect(self, SIGNAL("SIGUSR1()"), SLOT("slot_handleSIGUSR1()")) | |||
self.connect(self, SIGNAL("SIGTERM()"), SLOT("slot_handleSIGTERM()")) | |||
@@ -611,6 +615,7 @@ class CarlaMainW(QMainWindow): | |||
Carla.processMode = settings.value("Engine/ProcessMode", PROCESS_MODE_MULTIPLE_CLIENTS, type=int) | |||
Carla.maxParameters = settings.value("Engine/MaxParameters", MAX_DEFAULT_PARAMETERS, type=int) | |||
transportMode = settings.value("Engine/TransportMode", TRANSPORT_MODE_JACK, type=int) | |||
forceStereo = settings.value("Engine/ForceStereo", False, type=bool) | |||
preferPluginBridges = settings.value("Engine/PreferPluginBridges", False, type=bool) | |||
preferUiBridges = settings.value("Engine/PreferUiBridges", True, type=bool) | |||
@@ -667,9 +672,22 @@ class CarlaMainW(QMainWindow): | |||
else: | |||
maxCount = MAX_DEFAULT_PLUGINS | |||
self.ui.ch_transport.blockSignals(True) | |||
self.ui.ch_transport.addItem(self.tr("Internal")) | |||
if audioDriver == "JACK": | |||
self.ui.ch_transport.addItem(self.tr("JACK")) | |||
elif transportMode == TRANSPORT_MODE_JACK: | |||
transportMode = TRANSPORT_MODE_INTERNAL | |||
self.ui.ch_transport.setCurrentIndex(transportMode) | |||
self.ui.ch_transport.blockSignals(False) | |||
for x in range(maxCount): | |||
self.fPluginList.append(None) | |||
Carla.host.set_engine_option(OPTION_TRANSPORT_MODE, transportMode, "") | |||
# Peaks | |||
self.fIdleTimerFast = self.startTimer(self.fSavedSettings["Main/RefreshInterval"]) | |||
# LEDs and edit dialog parameters | |||
@@ -695,6 +713,12 @@ class CarlaMainW(QMainWindow): | |||
self.killTimer(self.fIdleTimerFast) | |||
self.killTimer(self.fIdleTimerSlow) | |||
settings = QSettings() | |||
settings.setValue("Engine/TransportMode", self.ui.ch_transport.currentIndex()) | |||
self.ui.ch_transport.blockSignals(True) | |||
self.ui.ch_transport.clear() | |||
self.ui.ch_transport.blockSignals(False) | |||
def loadProject(self, filename): | |||
self.fProjectFilename = filename | |||
self.setWindowTitle("Carla - %s" % os.path.basename(filename)) | |||
@@ -795,6 +819,8 @@ class CarlaMainW(QMainWindow): | |||
self.ui.act_file_open.setEnabled(check) | |||
self.ui.act_engine_start.setEnabled(not check) | |||
self.ui.act_engine_stop.setEnabled(check) | |||
self.ui.act_engine_configure.setEnabled(not check) | |||
self.ui.frame_transport.setEnabled(check) | |||
@pyqtSlot() | |||
def slot_engineStop(self): | |||
@@ -803,6 +829,7 @@ class CarlaMainW(QMainWindow): | |||
self.ui.act_file_open.setEnabled(check) | |||
self.ui.act_engine_start.setEnabled(not check) | |||
self.ui.act_engine_stop.setEnabled(check) | |||
self.ui.frame_transport.setEnabled(check) | |||
@pyqtSlot() | |||
def slot_pluginAdd(self): | |||
@@ -819,6 +846,26 @@ class CarlaMainW(QMainWindow): | |||
def slot_pluginRemoveAll(self): | |||
self.removeAllPlugins() | |||
self.connect(self.ui.ch_transport, SIGNAL("currentIndexChanged(int)"), SLOT("(int)")) | |||
self.connect(self.ui.b_transport_play, SIGNAL("clicked(bool)"), SLOT("(bool)")) | |||
self.connect(self.ui.b_transport_stop, SIGNAL("clicked()"), SLOT("()")) | |||
@pyqtSlot(int) | |||
def slot_transportModeChanged(self, newMode): | |||
Carla.host.set_engine_option(OPTION_TRANSPORT_MODE, newMode, "") | |||
@pyqtSlot(bool) | |||
def slot_transportPlayPause(self, toggled): | |||
if toggled: | |||
Carla.host.transport_play() | |||
else: | |||
Carla.host.transport_pause() | |||
@pyqtSlot() | |||
def slot_transportStop(self): | |||
Carla.host.transport_pause() | |||
Carla.host.transport_relocate(0) | |||
@pyqtSlot() | |||
def slot_aboutCarla(self): | |||
CarlaAboutW(self).exec_() | |||
@@ -191,6 +191,15 @@ class Host(object): | |||
self.lib.carla_save_project.argtypes = [c_char_p] | |||
self.lib.carla_save_project.restype = c_bool | |||
self.lib.carla_transport_play.argtypes = None | |||
self.lib.carla_transport_play.restype = None | |||
self.lib.carla_transport_pause.argtypes = None | |||
self.lib.carla_transport_pause.restype = None | |||
self.lib.carla_transport_relocate.argtypes = [c_uint32] | |||
self.lib.carla_transport_relocate.restype = None | |||
self.lib.carla_add_plugin.argtypes = [c_enum, c_enum, c_char_p, c_char_p, c_char_p, c_void_p] | |||
self.lib.carla_add_plugin.restype = c_bool | |||
@@ -395,6 +404,15 @@ class Host(object): | |||
def save_project(self, filename): | |||
return self.lib.carla_save_project(filename.encode("utf-8")) | |||
def transport_play(self): | |||
self.lib.carla_transport_play() | |||
def transport_pause(self): | |||
self.lib.carla_transport_pause() | |||
def transport_relocate(self, frames): | |||
self.lib.carla_transport_relocate(frames) | |||
def add_plugin(self, btype, ptype, filename, name, label, extraStuff): | |||
cname = name.encode("utf-8") if name else c_nullptr | |||
return self.lib.carla_add_plugin(btype, ptype, filename.encode("utf-8"), cname, label.encode("utf-8"), cast(extraStuff, c_void_p)) | |||
@@ -249,29 +249,30 @@ PARAMETER_MAX = -9 | |||
# Options Type | |||
OPTION_PROCESS_NAME = 0 | |||
OPTION_PROCESS_MODE = 1 | |||
OPTION_FORCE_STEREO = 2 | |||
OPTION_PREFER_PLUGIN_BRIDGES = 3 | |||
OPTION_PREFER_UI_BRIDGES = 4 | |||
OPTION_USE_DSSI_VST_CHUNKS = 5 | |||
OPTION_MAX_PARAMETERS = 6 | |||
OPTION_OSC_UI_TIMEOUT = 7 | |||
OPTION_PREFERRED_BUFFER_SIZE = 8 | |||
OPTION_PREFERRED_SAMPLE_RATE = 9 | |||
OPTION_PATH_BRIDGE_NATIVE = 10 | |||
OPTION_PATH_BRIDGE_POSIX32 = 11 | |||
OPTION_PATH_BRIDGE_POSIX64 = 12 | |||
OPTION_PATH_BRIDGE_WIN32 = 13 | |||
OPTION_PATH_BRIDGE_WIN64 = 14 | |||
OPTION_PATH_BRIDGE_LV2_GTK2 = 15 | |||
OPTION_PATH_BRIDGE_LV2_GTK3 = 16 | |||
OPTION_PATH_BRIDGE_LV2_QT4 = 17 | |||
OPTION_PATH_BRIDGE_LV2_QT5 = 18 | |||
OPTION_PATH_BRIDGE_LV2_COCOA = 19 | |||
OPTION_PATH_BRIDGE_LV2_WINDOWS = 20 | |||
OPTION_PATH_BRIDGE_LV2_X11 = 21 | |||
OPTION_PATH_BRIDGE_VST_COCOA = 22 | |||
OPTION_PATH_BRIDGE_VST_HWND = 23 | |||
OPTION_PATH_BRIDGE_VST_X11 = 24 | |||
OPTION_TRANSPORT_MODE = 2 | |||
OPTION_FORCE_STEREO = 3 | |||
OPTION_PREFER_PLUGIN_BRIDGES = 4 | |||
OPTION_PREFER_UI_BRIDGES = 5 | |||
OPTION_USE_DSSI_VST_CHUNKS = 6 | |||
OPTION_MAX_PARAMETERS = 7 | |||
OPTION_OSC_UI_TIMEOUT = 8 | |||
OPTION_PREFERRED_BUFFER_SIZE = 9 | |||
OPTION_PREFERRED_SAMPLE_RATE = 10 | |||
OPTION_PATH_BRIDGE_NATIVE = 11 | |||
OPTION_PATH_BRIDGE_POSIX32 = 12 | |||
OPTION_PATH_BRIDGE_POSIX64 = 13 | |||
OPTION_PATH_BRIDGE_WIN32 = 14 | |||
OPTION_PATH_BRIDGE_WIN64 = 15 | |||
OPTION_PATH_BRIDGE_LV2_GTK2 = 16 | |||
OPTION_PATH_BRIDGE_LV2_GTK3 = 17 | |||
OPTION_PATH_BRIDGE_LV2_QT4 = 18 | |||
OPTION_PATH_BRIDGE_LV2_QT5 = 19 | |||
OPTION_PATH_BRIDGE_LV2_COCOA = 20 | |||
OPTION_PATH_BRIDGE_LV2_WINDOWS = 21 | |||
OPTION_PATH_BRIDGE_LV2_X11 = 22 | |||
OPTION_PATH_BRIDGE_VST_COCOA = 23 | |||
OPTION_PATH_BRIDGE_VST_HWND = 24 | |||
OPTION_PATH_BRIDGE_VST_X11 = 25 | |||
# Callback Type | |||
CALLBACK_DEBUG = 0 | |||
@@ -298,12 +299,16 @@ CALLBACK_NSM_SAVE = 20 | |||
CALLBACK_ERROR = 21 | |||
CALLBACK_QUIT = 22 | |||
# Process Mode Type | |||
# Process Mode | |||
PROCESS_MODE_SINGLE_CLIENT = 0 | |||
PROCESS_MODE_MULTIPLE_CLIENTS = 1 | |||
PROCESS_MODE_CONTINUOUS_RACK = 2 | |||
PROCESS_MODE_PATCHBAY = 3 | |||
# Transport Mode | |||
TRANSPORT_MODE_INTERNAL = 0 | |||
TRANSPORT_MODE_JACK = 1 | |||
# Set BINARY_NATIVE | |||
if HAIKU or LINUX or MACOS: | |||
BINARY_NATIVE = BINARY_POSIX64 if kIs64bit else BINARY_POSIX32 | |||
@@ -248,6 +248,15 @@ int jackbridge_midi_event_write(void* port_buffer, jack_nframes_t time, const ja | |||
// ----------------------------------------------------------------------------- | |||
int jackbridge_transport_locate(jack_client_t* client, jack_nframes_t frame) | |||
{ | |||
#ifndef JACKBRIDGE_DUMMY | |||
return jack_transport_locate(client, frame); | |||
#else | |||
return 0; | |||
#endif | |||
} | |||
jack_transport_state_t jackbridge_transport_query(const jack_client_t* client, jack_position_t* pos) | |||
{ | |||
#ifndef JACKBRIDGE_DUMMY | |||
@@ -256,3 +265,17 @@ jack_transport_state_t jackbridge_transport_query(const jack_client_t* client, j | |||
return JackTransportStopped; | |||
#endif | |||
} | |||
void jackbridge_transport_start(jack_client_t* client) | |||
{ | |||
#ifndef JACKBRIDGE_DUMMY | |||
jack_transport_start(client); | |||
#endif | |||
} | |||
void jackbridge_transport_stop(jack_client_t* client) | |||
{ | |||
#ifndef JACKBRIDGE_DUMMY | |||
jack_transport_stop(client); | |||
#endif | |||
} |
@@ -67,7 +67,10 @@ BRIDGE_EXPORT void jackbridge_midi_clear_buffer(void* port_buffer); | |||
BRIDGE_EXPORT jack_midi_data_t* jackbridge_midi_event_reserve(void* port_buffer, jack_nframes_t time, size_t data_size); | |||
BRIDGE_EXPORT int jackbridge_midi_event_write(void* port_buffer, jack_nframes_t time, const jack_midi_data_t* data, size_t data_size); | |||
BRIDGE_EXPORT int jackbridge_transport_locate(jack_client_t* client, jack_nframes_t frame); | |||
BRIDGE_EXPORT jack_transport_state_t jackbridge_transport_query(const jack_client_t* client, jack_position_t* pos); | |||
BRIDGE_EXPORT void jackbridge_transport_start(jack_client_t* client); | |||
BRIDGE_EXPORT void jackbridge_transport_stop(jack_client_t* client); | |||
#ifdef __cplusplus | |||
} | |||
@@ -103,7 +106,10 @@ BRIDGE_EXPORT jack_transport_state_t jackbridge_transport_query(const jack_clien | |||
#define jackbridge_midi_event_reserve jack_midi_event_reserve | |||
#define jackbridge_midi_event_write jack_midi_event_write | |||
#define jackbridge_transport_locate jack_transport_locate | |||
#define jackbridge_transport_query jack_transport_query | |||
#define jackbridge_transport_start jack_transport_start | |||
#define jackbridge_transport_stop jack_transport_stop | |||
#endif // JACKBRIDGE_EXPORT | |||
@@ -204,6 +204,8 @@ const char* OptionsType2Str(const OptionsType& type) | |||
return "OPTION_PROCESS_NAME"; | |||
case OPTION_PROCESS_MODE: | |||
return "OPTION_PROCESS_MODE"; | |||
case OPTION_TRANSPORT_MODE: | |||
return "OPTION_TRANSPORT_MODE"; | |||
case OPTION_FORCE_STEREO: | |||
return "OPTION_FORCE_STEREO"; | |||
case OPTION_PREFER_PLUGIN_BRIDGES: | |||