@@ -581,32 +581,42 @@ enum CallbackType { | |||
/*! | |||
* Non-Session-Manager Announce message. | |||
*/ | |||
CALLBACK_NSM_ANNOUNCE = 26, | |||
CALLBACK_BUFFER_SIZE_CHANGED = 26, | |||
/*! | |||
* Non-Session-Manager Announce message. | |||
*/ | |||
CALLBACK_SAMPLE_RATE_CHANGED = 27, | |||
/*! | |||
* Non-Session-Manager Announce message. | |||
*/ | |||
CALLBACK_NSM_ANNOUNCE = 28, | |||
/*! | |||
* Non-Session-Manager Open message #1. | |||
*/ | |||
CALLBACK_NSM_OPEN1 = 27, | |||
CALLBACK_NSM_OPEN1 = 29, | |||
/*! | |||
* Non-Session-Manager Open message #2. | |||
*/ | |||
CALLBACK_NSM_OPEN2 = 28, | |||
CALLBACK_NSM_OPEN2 = 30, | |||
/*! | |||
* Non-Session-Manager Save message. | |||
*/ | |||
CALLBACK_NSM_SAVE = 29, | |||
CALLBACK_NSM_SAVE = 31, | |||
/*! | |||
* An error occurred, show \a valueStr as an error to user. | |||
*/ | |||
CALLBACK_ERROR = 30, | |||
CALLBACK_ERROR = 32, | |||
/*! | |||
* The engine has crashed or malfunctioned and will no longer work. | |||
*/ | |||
CALLBACK_QUIT = 31 | |||
CALLBACK_QUIT = 33 | |||
}; | |||
/*! | |||
@@ -71,6 +71,9 @@ struct CarlaPluginInfo { | |||
if (copyright != nullptr) | |||
delete[] copyright; | |||
} | |||
CarlaPluginInfo(CarlaPluginInfo&) = delete; | |||
CarlaPluginInfo(const CarlaPluginInfo&) = delete; | |||
}; | |||
struct CarlaNativePluginInfo { | |||
@@ -100,6 +103,9 @@ struct CarlaNativePluginInfo { | |||
label(nullptr), | |||
maker(nullptr), | |||
copyright(nullptr) {} | |||
CarlaNativePluginInfo(CarlaNativePluginInfo&) = delete; | |||
CarlaNativePluginInfo(const CarlaNativePluginInfo&) = delete; | |||
}; | |||
struct CarlaPortCountInfo { | |||
@@ -111,6 +117,9 @@ struct CarlaPortCountInfo { | |||
: ins(0), | |||
outs(0), | |||
total(0) {} | |||
CarlaPortCountInfo(CarlaPortCountInfo&) = delete; | |||
CarlaPortCountInfo(const CarlaPortCountInfo&) = delete; | |||
}; | |||
struct CarlaParameterInfo { | |||
@@ -134,6 +143,9 @@ struct CarlaParameterInfo { | |||
if (unit != nullptr) | |||
delete[] unit; | |||
} | |||
CarlaParameterInfo(CarlaParameterInfo&) = delete; | |||
CarlaParameterInfo(const CarlaParameterInfo&) = delete; | |||
}; | |||
struct CarlaScalePointInfo { | |||
@@ -149,8 +161,31 @@ struct CarlaScalePointInfo { | |||
if (label != nullptr) | |||
delete[] label; | |||
} | |||
CarlaScalePointInfo(CarlaScalePointInfo&) = delete; | |||
CarlaScalePointInfo(const CarlaScalePointInfo&) = delete; | |||
}; | |||
struct CarlaTransportInfo { | |||
bool playing; | |||
uint32_t frame; | |||
int32_t bar; | |||
int32_t beat; | |||
int32_t tick; | |||
double bpm; | |||
CarlaTransportInfo() | |||
: playing(false), | |||
frame(0), | |||
bar(0), | |||
beat(0), | |||
bpm(0.0) {} | |||
CarlaTransportInfo(CarlaTransportInfo&) = delete; | |||
CarlaTransportInfo(const CarlaTransportInfo&) = delete; | |||
}; | |||
CARLA_EXPORT const char* carla_get_extended_license_text(); | |||
CARLA_EXPORT const char* carla_get_supported_file_types(); | |||
@@ -178,7 +213,8 @@ CARLA_EXPORT void carla_patchbay_refresh(); | |||
CARLA_EXPORT void carla_transport_play(); | |||
CARLA_EXPORT void carla_transport_pause(); | |||
CARLA_EXPORT void carla_transport_relocate(uint32_t frames); | |||
CARLA_EXPORT uint64_t carla_get_current_transport_frame(); | |||
CARLA_EXPORT uint32_t carla_get_current_transport_frame(); | |||
CARLA_EXPORT const CarlaTransportInfo* carla_get_transport_info(); | |||
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); | |||
@@ -1385,6 +1385,8 @@ void CarlaEngine::bufferSizeChanged(const uint32_t newBufferSize) | |||
if (plugin != nullptr && plugin->enabled()) | |||
plugin->bufferSizeChanged(newBufferSize); | |||
} | |||
callback(CALLBACK_BUFFER_SIZE_CHANGED, 0, newBufferSize, 0, 0.0f, nullptr); | |||
} | |||
void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||
@@ -1398,6 +1400,8 @@ void CarlaEngine::sampleRateChanged(const double newSampleRate) | |||
if (plugin != nullptr && plugin->enabled()) | |||
plugin->sampleRateChanged(newSampleRate); | |||
} | |||
callback(CALLBACK_SAMPLE_RATE_CHANGED, 0, 0, 0, newSampleRate, nullptr); | |||
} | |||
void CarlaEngine::proccessPendingEvents() | |||
@@ -889,6 +889,8 @@ protected: | |||
void handleJackProcessCallback(const uint32_t nframes) | |||
{ | |||
saveTransportInfo(); | |||
#ifndef BUILD_BRIDGE | |||
if (kData->curPluginCount == 0) | |||
{ | |||
@@ -899,7 +901,7 @@ protected: | |||
float* const audioIn2 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioIn2], nframes); | |||
float* const audioOut1 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioOut1], nframes); | |||
float* const audioOut2 = (float*)jackbridge_port_get_buffer(fRackPorts[rackPortAudioOut2], nframes); | |||
void* const eventOut = jackbridge_port_get_buffer(fRackPorts[rackPortEventOut], nframes); | |||
void* const eventOut = jackbridge_port_get_buffer(fRackPorts[rackPortEventOut], nframes); | |||
CARLA_ASSERT(audioIn1 != nullptr); | |||
CARLA_ASSERT(audioIn2 != nullptr); | |||
@@ -916,8 +918,6 @@ protected: | |||
} | |||
#endif | |||
saveTransportInfo(); | |||
#ifdef BUILD_BRIDGE | |||
CarlaPlugin* const plugin = getPluginUnchecked(0); | |||
@@ -593,7 +593,7 @@ void carla_transport_relocate(uint32_t frames) | |||
standalone.engine->transportRelocate(frames); | |||
} | |||
uint64_t carla_get_current_transport_frame() | |||
uint32_t carla_get_current_transport_frame() | |||
{ | |||
CARLA_ASSERT(standalone.engine != nullptr); | |||
@@ -606,6 +606,47 @@ uint64_t carla_get_current_transport_frame() | |||
return 0; | |||
} | |||
const CarlaTransportInfo* carla_get_transport_info() | |||
{ | |||
CARLA_ASSERT(standalone.engine != nullptr); | |||
static CarlaTransportInfo info; | |||
if (standalone.engine != nullptr) | |||
{ | |||
const CarlaBackend::EngineTimeInfo& timeInfo(standalone.engine->getTimeInfo()); | |||
info.playing = timeInfo.playing; | |||
info.frame = timeInfo.frame; | |||
if (timeInfo.valid & timeInfo.ValidBBT) | |||
{ | |||
info.bar = timeInfo.bbt.bar; | |||
info.beat = timeInfo.bbt.beat; | |||
info.tick = timeInfo.bbt.tick; | |||
info.bpm = timeInfo.bbt.beatsPerMinute; | |||
} | |||
else | |||
{ | |||
info.bar = 0; | |||
info.beat = 0; | |||
info.tick = 0; | |||
info.bpm = 0.0; | |||
} | |||
} | |||
else | |||
{ | |||
info.playing = false; | |||
info.frame = 0; | |||
info.bar = 0; | |||
info.beat = 0; | |||
info.tick = 0; | |||
info.bpm = 0.0; | |||
} | |||
return &info; | |||
} | |||
// ------------------------------------------------------------------------------------------------------------------- | |||
bool carla_add_plugin(CarlaBackend::BinaryType btype, CarlaBackend::PluginType ptype, const char* filename, const char* const name, const char* label, const void* extraStuff) | |||
@@ -541,6 +541,9 @@ class CarlaMainW(QMainWindow): | |||
# ------------------------------------------------------------- | |||
# Internal stuff | |||
self.fBufferSize = 0 | |||
self.fSampleRate = 0.0 | |||
self.fEngineStarted = False | |||
self.fFirstEngineInit = False | |||
@@ -705,6 +708,8 @@ class CarlaMainW(QMainWindow): | |||
self.connect(self, SIGNAL("PatchbayPortRenamedCallback(int, QString)"), SLOT("slot_handlePatchbayPortRenamedCallback(int, QString)")) | |||
self.connect(self, SIGNAL("PatchbayConnectionAddedCallback(int, int, int)"), SLOT("slot_handlePatchbayConnectionAddedCallback(int, int, int)")) | |||
self.connect(self, SIGNAL("PatchbayConnectionRemovedCallback(int)"), SLOT("slot_handlePatchbayConnectionRemovedCallback(int)")) | |||
self.connect(self, SIGNAL("BufferSizeChangedCallback(int)"), SLOT("slot_handleBufferSizeChangedCallback(int)")) | |||
self.connect(self, SIGNAL("SampleRateChangedCallback(double)"), SLOT("slot_handleSampleRateChangedCallback(double)")) | |||
#self.connect(self, SIGNAL("NSM_AnnounceCallback()"), SLOT("slot_handleNSM_AnnounceCallback()")) | |||
#self.connect(self, SIGNAL("NSM_Open1Callback()"), SLOT("slot_handleNSM_Open1Callback()")) | |||
#self.connect(self, SIGNAL("NSM_Open2Callback()"), SLOT("slot_handleNSM_Open2Callback()")) | |||
@@ -958,6 +963,9 @@ class CarlaMainW(QMainWindow): | |||
QMessageBox.critical(self, self.tr("Error"), self.tr("Could not connect to Audio backend '%s'" % audioDriver)) | |||
return | |||
self.fBufferSize = Carla.host.get_buffer_size() | |||
self.fSampleRate = Carla.host.get_sample_rate() | |||
self.fEngineStarted = True | |||
self.fFirstEngineInit = False | |||
@@ -996,6 +1004,10 @@ class CarlaMainW(QMainWindow): | |||
if Carla.host.is_engine_running() and not Carla.host.engine_close(): | |||
print(cString(Carla.host.get_last_error())) | |||
return | |||
self.fBufferSize = 0 | |||
self.fSampleRate = 0.0 | |||
self.fEngineStarted = False | |||
self.fPluginCount = 0 | |||
@@ -1109,10 +1121,8 @@ class CarlaMainW(QMainWindow): | |||
self.ui.act_engine_configure.setEnabled(not check) | |||
if check: | |||
bufferSize = Carla.host.get_buffer_size() | |||
sampleRate = Carla.host.get_sample_rate() | |||
self.fInfoText = "Engine running | SampleRate: %g | BufferSize: %i" % (sampleRate, bufferSize) | |||
self.fInfoLabel.setText(self.fInfoText) | |||
self.fInfoText = "Engine running | SampleRate: %g | BufferSize: %i" % (self.fSampleRate, self.fBufferSize) | |||
self.refreshTransport() | |||
self.menuTransport(check) | |||
@@ -1155,13 +1165,17 @@ class CarlaMainW(QMainWindow): | |||
def refreshTransport(self): | |||
if not self.fEngineStarted: | |||
return | |||
if self.fSampleRate == 0.0: | |||
return | |||
time = Carla.host.get_current_transport_frame() / int(Carla.host.get_sample_rate()) | |||
timeInfo = Carla.host.get_transport_info() | |||
time = timeInfo['frame'] / self.fSampleRate | |||
secs = time % 60 | |||
mins = (time / 60) % 60 | |||
hrs = (time / 3600) % 60 | |||
textTransport = "Transport %s, at %02i:%02i:%02i" % ("<TODO>", hrs, mins, secs) | |||
textTransport = "Transport %s, at %02i:%02i:%02i" % ("playing" if timeInfo['playing'] else "stopped", hrs, mins, secs) | |||
self.fInfoLabel.setText("%s | %s" % (self.fInfoText, textTransport)) | |||
@pyqtSlot(bool) | |||
@@ -1522,6 +1536,16 @@ class CarlaMainW(QMainWindow): | |||
def slot_handlePatchbayConnectionRemovedCallback(self, connectionId): | |||
patchcanvas.disconnectPorts(connectionId) | |||
@pyqtSlot(int) | |||
def slot_handleBufferSizeChangedCallback(self, newBufferSize): | |||
self.fBufferSize = newBufferSize | |||
self.fInfoText = "Engine running | SampleRate: %g | BufferSize: %i" % (self.fSampleRate, self.fBufferSize) | |||
@pyqtSlot(float) | |||
def slot_handleSampleRateChangedCallback(self, newSampleRate): | |||
self.fSampleRate = newSampleRate | |||
self.fInfoText = "Engine running | SampleRate: %g | BufferSize: %i" % (self.fSampleRate, self.fBufferSize) | |||
@pyqtSlot(str) | |||
def slot_handleErrorCallback(self, error): | |||
QMessageBox.critical(self, self.tr("Error"), error) | |||
@@ -1780,6 +1804,10 @@ def engineCallback(ptr, action, pluginId, value1, value2, value3, valueStr): | |||
Carla.gui.emit(SIGNAL("PatchbayConnectionAddedCallback(int, int, int)"), value1, value2, value3) | |||
elif action == CALLBACK_PATCHBAY_CONNECTION_REMOVED: | |||
Carla.gui.emit(SIGNAL("PatchbayConnectionRemovedCallback(int)"), value1) | |||
elif action == CALLBACK_BUFFER_SIZE_CHANGED: | |||
Carla.gui.emit(SIGNAL("BufferSizeChangedCallback(int)"), value1) | |||
elif action == CALLBACK_SAMPLE_RATE_CHANGED: | |||
Carla.gui.emit(SIGNAL("SampleRateChangedCallback(double)"), value3) | |||
#elif action == CALLBACK_NSM_ANNOUNCE: | |||
#Carla.gui._nsmAnnounce2str = cString(Carla.host.get_last_error()) | |||
#Carla.gui.emit(SIGNAL("NSM_AnnounceCallback()")) | |||
@@ -131,6 +131,16 @@ class CarlaScalePointInfo(Structure): | |||
("label", c_char_p) | |||
] | |||
class CarlaTransportInfo(Structure): | |||
_fields_ = [ | |||
("playing", c_bool), | |||
("frame", c_uint32), | |||
("bar", c_int32), | |||
("beat", c_int32), | |||
("tick", c_int32), | |||
("bpm", c_double) | |||
] | |||
# ------------------------------------------------------------------------------------------------------------ | |||
# Standalone Python object | |||
@@ -213,7 +223,10 @@ class Host(object): | |||
self.lib.carla_transport_relocate.restype = None | |||
self.lib.carla_get_current_transport_frame.argtypes = None | |||
self.lib.carla_get_current_transport_frame.restype = c_uint64 | |||
self.lib.carla_get_current_transport_frame.restype = c_uint32 | |||
self.lib.carla_get_transport_info.argtypes = None | |||
self.lib.carla_get_transport_info.restype = POINTER(CarlaTransportInfo) | |||
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 | |||
@@ -449,6 +462,9 @@ class Host(object): | |||
def get_current_transport_frame(self): | |||
return self.lib.carla_get_current_transport_frame() | |||
def get_transport_info(self): | |||
return structToDict(self.lib.carla_get_transport_info().contents) | |||
def add_plugin(self, btype, ptype, filename, name, label, extraStuff): | |||
cfilename = filename.encode("utf-8") if filename else c_nullptr | |||
cname = name.encode("utf-8") if name else c_nullptr | |||
@@ -305,12 +305,14 @@ CALLBACK_PATCHBAY_PORT_REMOVED = 22 | |||
CALLBACK_PATCHBAY_PORT_RENAMED = 23 | |||
CALLBACK_PATCHBAY_CONNECTION_ADDED = 24 | |||
CALLBACK_PATCHBAY_CONNECTION_REMOVED = 25 | |||
CALLBACK_NSM_ANNOUNCE = 26 | |||
CALLBACK_NSM_OPEN1 = 27 | |||
CALLBACK_NSM_OPEN2 = 28 | |||
CALLBACK_NSM_SAVE = 29 | |||
CALLBACK_ERROR = 30 | |||
CALLBACK_QUIT = 31 | |||
CALLBACK_BUFFER_SIZE_CHANGED = 26 | |||
CALLBACK_SAMPLE_RATE_CHANGED = 27 | |||
CALLBACK_NSM_ANNOUNCE = 28 | |||
CALLBACK_NSM_OPEN1 = 29 | |||
CALLBACK_NSM_OPEN2 = 30 | |||
CALLBACK_NSM_SAVE = 31 | |||
CALLBACK_ERROR = 32 | |||
CALLBACK_QUIT = 33 | |||
# Process Mode | |||
PROCESS_MODE_SINGLE_CLIENT = 0 | |||
@@ -323,6 +323,10 @@ const char* CallbackType2Str(const CallbackType& type) | |||
return "CALLBACK_RELOAD_PROGRAMS"; | |||
case CALLBACK_RELOAD_ALL: | |||
return "CALLBACK_RELOAD_ALL"; | |||
case CALLBACK_BUFFER_SIZE_CHANGED: | |||
return "CALLBACK_BUFFER_SIZE_CHANGED"; | |||
case CALLBACK_SAMPLE_RATE_CHANGED: | |||
return "CALLBACK_SAMPLE_RATE_CHANGED"; | |||
case CALLBACK_NSM_ANNOUNCE: | |||
return "CALLBACK_NSM_ANNOUNCE"; | |||
case CALLBACK_NSM_OPEN1: | |||