diff --git a/src/carla.py b/src/carla.py index b8232f9..fbc6b92 100755 --- a/src/carla.py +++ b/src/carla.py @@ -18,12 +18,12 @@ # Imports (Global) import json, os, sys -#from PyQt4.QtCore import Qt, QSettings, QThread, QTimer, QVariant, SIGNAL, SLOT -#from PyQt4.QtGui import QApplication, QColor, QCursor, QFileDialog, QFontMetrics, QInputDialog, QMenu, QPainter, QPixmap, QVBoxLayout +#from PyQt4.QtCore import QTimer +#from PyQt4.QtGui import QCursor, QFontMetrics, QInputDialog, QMenu, QPixmap, QVBoxLayout from time import sleep #from sip import unwrapinstance from PyQt4.QtCore import pyqtSlot, Qt, QSettings, QThread -from PyQt4.QtGui import QApplication, QDialog, QFrame, QMainWindow, QTableWidgetItem, QWidget +from PyQt4.QtGui import QApplication, QColor, QDialog, QFrame, QMainWindow, QPainter, QTableWidgetItem, QWidget from PyQt4.QtXml import QDomDocument # Imports (Custom Stuff) @@ -1048,11 +1048,11 @@ class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW): elif (hide_non_stereo and not is_stereo): self.tableWidget.hideRow(i) elif (text and not ( - text in self.tableWidget.item(i, 0).text().toLower() or - text in self.tableWidget.item(i, 1).text().toLower() or - text in self.tableWidget.item(i, 2).text().toLower() or - text in self.tableWidget.item(i, 3).text().toLower() or - text in self.tableWidget.item(i, 14).text().toLower()) + text in self.tableWidget.item(i, 0).text().lower() or + text in self.tableWidget.item(i, 1).text().lower() or + text in self.tableWidget.item(i, 2).text().lower() or + text in self.tableWidget.item(i, 3).text().lower() or + text in self.tableWidget.item(i, 13).text().lower()) ): self.tableWidget.hideRow(i) @@ -1904,7 +1904,7 @@ class PluginEdit(QDialog, ui_carla_edit.Ui_PluginEdit): # (New) Plugin Widget class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): def __init__(self, parent, plugin_id): - super(PluginWidget, self).__init__(parent) + QFrame.__init__(self, parent) self.setupUi(self) self.plugin_id = plugin_id @@ -1949,7 +1949,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): self.peak_out.setColor(self.peak_in.BLUE) self.peak_out.setOrientation(self.peak_out.HORIZONTAL) - audio_count = NativeHost.get_audio_port_count_info(self.plugin_id) + audio_count = CarlaHost.get_audio_port_count_info(self.plugin_id) if (not audio_count['valid']): audio_count['ins'] = 0 audio_count['outs'] = 0 @@ -1967,7 +1967,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): self.peak_in.setChannels(self.peaks_in) self.peak_out.setChannels(self.peaks_out) - self.pinfo = NativeHost.get_plugin_info(self.plugin_id) + self.pinfo = CarlaHost.get_plugin_info(self.plugin_id) if (not self.pinfo['valid']): self.pinfo["type"] = PLUGIN_NONE self.pinfo["category"] = PLUGIN_CATEGORY_NONE @@ -1989,7 +1989,7 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): if (self.pinfo['type'] == PLUGIN_NONE or audio_count['total'] == 0): self.stackedWidget.setCurrentIndex(1) - self.label_name.setText(self.pinfo['name']) + self.label_name.setText(self.pinfo['name'].decode("utf-8")) self.dial_drywet.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_DRYWET) self.dial_vol.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_VOL) @@ -1999,177 +1999,76 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): # Colorify if (self.pinfo['category'] == PLUGIN_CATEGORY_SYNTH): - self.set_plugin_widget_color(PALETTE_COLOR_WHITE) + self.setWidgetColor(PALETTE_COLOR_WHITE) elif (self.pinfo['category'] == PLUGIN_CATEGORY_DELAY): - self.set_plugin_widget_color(PALETTE_COLOR_ORANGE) + self.setWidgetColor(PALETTE_COLOR_ORANGE) elif (self.pinfo['category'] == PLUGIN_CATEGORY_EQ): - self.set_plugin_widget_color(PALETTE_COLOR_GREEN) + self.setWidgetColor(PALETTE_COLOR_GREEN) elif (self.pinfo['category'] == PLUGIN_CATEGORY_FILTER): - self.set_plugin_widget_color(PALETTE_COLOR_BLUE) + self.setWidgetColor(PALETTE_COLOR_BLUE) elif (self.pinfo['category'] == PLUGIN_CATEGORY_DYNAMICS): - self.set_plugin_widget_color(PALETTE_COLOR_PINK) + self.setWidgetColor(PALETTE_COLOR_PINK) elif (self.pinfo['category'] == PLUGIN_CATEGORY_MODULATOR): - self.set_plugin_widget_color(PALETTE_COLOR_RED) + self.setWidgetColor(PALETTE_COLOR_RED) elif (self.pinfo['category'] == PLUGIN_CATEGORY_UTILITY): - self.set_plugin_widget_color(PALETTE_COLOR_YELLOW) + self.setWidgetColor(PALETTE_COLOR_YELLOW) elif (self.pinfo['category'] == PLUGIN_CATEGORY_OUTRO): - self.set_plugin_widget_color(PALETTE_COLOR_BROWN) + self.setWidgetColor(PALETTE_COLOR_BROWN) else: - self.set_plugin_widget_color(PALETTE_COLOR_NONE) + self.setWidgetColor(PALETTE_COLOR_NONE) if (self.pinfo['hints'] & PLUGIN_IS_SYNTH): self.led_audio_in.setVisible(False) else: self.led_midi.setVisible(False) - self.edit_dialog = PluginEdit(self, self.plugin_id) - self.edit_dialog.hide() - self.edit_dialog_geometry = QVariant(self.edit_dialog.saveGeometry()) + #self.edit_dialog = PluginEdit(self, self.plugin_id) + #self.edit_dialog.hide() + #self.edit_dialog_geometry = QVariant(self.edit_dialog.saveGeometry()) - if (self.pinfo['hints'] & PLUGIN_HAS_GUI): - gui_data = NativeHost.get_gui_data(self.plugin_id) - self.gui_dialog_type = gui_data['type'] + #if (self.pinfo['hints'] & PLUGIN_HAS_GUI): + #gui_data = NativeHost.get_gui_data(self.plugin_id) + #self.gui_dialog_type = gui_data['type'] - if (self.gui_dialog_type in (GUI_INTERNAL_QT4, GUI_INTERNAL_X11)): - self.gui_dialog = PluginGUI(self, self.pinfo['name'], gui_data) - self.gui_dialog.hide() - self.gui_dialog_geometry = QVariant(self.gui_dialog.saveGeometry()) - self.connect(self.gui_dialog, SIGNAL("finished(int)"), self.gui_dialog_closed) + #if (self.gui_dialog_type in (GUI_INTERNAL_QT4, GUI_INTERNAL_X11)): + #self.gui_dialog = PluginGUI(self, self.pinfo['name'], gui_data) + #self.gui_dialog.hide() + #self.gui_dialog_geometry = QVariant(self.gui_dialog.saveGeometry()) + #self.connect(self.gui_dialog, SIGNAL("finished(int)"), self.gui_dialog_closed) - NativeHost.set_gui_data(self.plugin_id, Display, unwrapinstance(self.gui_dialog)) + #NativeHost.set_gui_data(self.plugin_id, Display, unwrapinstance(self.gui_dialog)) - elif (self.gui_dialog_type in (GUI_EXTERNAL_OSC, GUI_EXTERNAL_LV2)): - self.gui_dialog = None + #elif (self.gui_dialog_type in (GUI_EXTERNAL_OSC, GUI_EXTERNAL_LV2)): + #self.gui_dialog = None - else: - self.gui_dialog = None - self.b_gui.setEnabled(False) + #else: + #self.gui_dialog = None + #self.b_gui.setEnabled(False) - else: - self.gui_dialog = None - self.gui_dialog_type = GUI_NONE + #else: + self.gui_dialog = None + self.gui_dialog_type = GUI_NONE - self.connect(self.led_enable, SIGNAL("clicked(bool)"), self.set_active) - self.connect(self.dial_drywet, SIGNAL("sliderMoved(int)"), self.set_drywet) - self.connect(self.dial_vol, SIGNAL("sliderMoved(int)"), self.set_vol) - self.connect(self.dial_b_left, SIGNAL("sliderMoved(int)"), self.set_balance_left) - self.connect(self.dial_b_right, SIGNAL("sliderMoved(int)"), self.set_balance_right) - self.connect(self.b_gui, SIGNAL("clicked(bool)"), self.handleShowGUI) - self.connect(self.b_edit, SIGNAL("clicked(bool)"), self.handleEdit) - self.connect(self.b_remove, SIGNAL("clicked()"), self.handleRemove) + #self.connect(self.led_enable, SIGNAL("clicked(bool)"), self.set_active) + #self.connect(self.dial_drywet, SIGNAL("sliderMoved(int)"), self.set_drywet) + #self.connect(self.dial_vol, SIGNAL("sliderMoved(int)"), self.set_vol) + #self.connect(self.dial_b_left, SIGNAL("sliderMoved(int)"), self.set_balance_left) + #self.connect(self.dial_b_right, SIGNAL("sliderMoved(int)"), self.set_balance_right) + #self.connect(self.b_gui, SIGNAL("clicked(bool)"), self.handleShowGUI) + #self.connect(self.b_edit, SIGNAL("clicked(bool)"), self.handleEdit) + #self.connect(self.b_remove, SIGNAL("clicked()"), self.handleRemove) - self.connect(self.dial_drywet, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) - self.connect(self.dial_vol, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) - self.connect(self.dial_b_left, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) - self.connect(self.dial_b_right, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) + #self.connect(self.dial_drywet, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) + #self.connect(self.dial_vol, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) + #self.connect(self.dial_b_left, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) + #self.connect(self.dial_b_right, SIGNAL("customContextMenuRequested(QPoint)"), self.showCustomDialMenu) - self.connect(self.edit_dialog, SIGNAL("finished(int)"), self.edit_dialog_closed) + #self.connect(self.edit_dialog, SIGNAL("finished(int)"), self.edit_dialog_closed) #self.check_gui_stuff() - self.TIMER_GUI_STUFF = self.startTimer(50) - - def recheck_hints(self, hints): - self.pinfo['hints'] = hints - self.dial_drywet.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_DRYWET) - self.dial_vol.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_VOL) - self.dial_b_left.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_BALANCE) - self.dial_b_right.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_BALANCE) - self.b_gui.setEnabled(self.pinfo['hints'] & PLUGIN_HAS_GUI) + #self.TIMER_GUI_STUFF = self.startTimer(50) - def set_active(self, active, gui_send=False, callback_send=True): - if (gui_send): self.led_enable.setChecked(active) - if (callback_send): NativeHost.set_active(self.plugin_id, active) - - def set_drywet(self, value, gui_send=False, callback_send=True): - if (gui_send): self.dial_drywet.setValue(value) - if (callback_send): NativeHost.set_drywet(self.plugin_id, float(value)/1000) - - message = self.tr("Output dry/wet (%1%)").arg(value/10) - self.dial_drywet.setStatusTip(message) - gui.statusBar().showMessage(message) - - def set_vol(self, value, gui_send=False, callback_send=True): - if (gui_send): self.dial_vol.setValue(value) - if (callback_send): NativeHost.set_vol(self.plugin_id, float(value)/1000) - - message = self.tr("Output volume (%1%)").arg(value/10) - self.dial_vol.setStatusTip(message) - gui.statusBar().showMessage(message) - - def set_balance_left(self, value, gui_send=False, callback_send=True): - if (gui_send): self.dial_b_left.setValue(value) - if (callback_send): NativeHost.set_balance_left(self.plugin_id, float(value)/1000) - - if (value == 0): - message = self.tr("Left Panning (Center)") - elif (value < 0): - message = self.tr("Left Panning (%1% Left)").arg(-value/10) - else: - message = self.tr("Left Panning (%1% Right)").arg(value/10) - - self.dial_b_left.setStatusTip(message) - gui.statusBar().showMessage(message) - - def set_balance_right(self, value, gui_send=False, callback_send=True): - if (gui_send): self.dial_b_right.setValue(value) - if (callback_send): NativeHost.set_balance_right(self.plugin_id, float(value)/1000) - - if (value == 0): - message = self.tr("Right Panning (Center)") - elif (value < 0): - message = self.tr("Right Panning (%1%) Left").arg(-value/10) - else: - message = self.tr("Right Panning (%1% Right)").arg(value/10) - - self.dial_b_right.setStatusTip(message) - gui.statusBar().showMessage(message) - - def gui_dialog_closed(self): - self.b_gui.setChecked(False) - - def edit_dialog_closed(self): - self.b_edit.setChecked(False) - - def check_gui_stuff(self): - # Input peaks - if (self.peaks_in > 0): - if (self.peaks_in > 1): - peak1 = NativeHost.get_input_peak_value(self.plugin_id, 1) - peak2 = NativeHost.get_input_peak_value(self.plugin_id, 2) - self.peak_in.displayMeter(1, peak1) - self.peak_in.displayMeter(2, peak2) - self.led_audio_in.setChecked((peak1 != 0.0 or peak2 != 0.0)) - - else: - peak = NativeHost.get_input_peak_value(self.plugin_id, 1) - self.peak_in.displayMeter(1, peak) - self.led_audio_in.setChecked((peak != 0.0)) - - # Output peaks - if (self.peaks_out > 0): - if (self.peaks_out > 1): - peak1 = NativeHost.get_output_peak_value(self.plugin_id, 1) - peak2 = NativeHost.get_output_peak_value(self.plugin_id, 2) - self.peak_out.displayMeter(1, peak1) - self.peak_out.displayMeter(2, peak2) - self.led_audio_out.setChecked((peak1 != 0.0 or peak2 != 0.0)) - - else: - peak = NativeHost.get_output_peak_value(self.plugin_id, 1) - self.peak_out.displayMeter(1, peak) - self.led_audio_out.setChecked((peak != 0.0)) - - # Parameter Activity LED - if (self.parameter_activity_timer == ICON_STATE_ON): - self.led_control.setChecked(True) - self.parameter_activity_timer = ICON_STATE_WAIT - elif (self.parameter_activity_timer == ICON_STATE_WAIT): - self.parameter_activity_timer = ICON_STATE_OFF - elif (self.parameter_activity_timer == ICON_STATE_OFF): - self.led_control.setChecked(False) - self.parameter_activity_timer = None - - def set_plugin_widget_color(self, color): + def setWidgetColor(self, color): if (color == PALETTE_COLOR_WHITE): r = 110 g = 110 @@ -2245,399 +2144,495 @@ class PluginWidget(QFrame, ui_carla_plugin.Ui_PluginWidget): } """ % (texture, r, g, b, r, g, b)) - def handleShowGUI(self, show): - if (self.gui_dialog_type in (GUI_INTERNAL_QT4, GUI_INTERNAL_X11)): - if (show): - self.gui_dialog.restoreGeometry(self.gui_dialog_geometry.toByteArray()) - else: - self.gui_dialog_geometry = QVariant(self.gui_dialog.saveGeometry()) - self.gui_dialog.setVisible(show) - NativeHost.show_gui(self.plugin_id, show) + #def recheck_hints(self, hints): + #self.pinfo['hints'] = hints + #self.dial_drywet.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_DRYWET) + #self.dial_vol.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_VOL) + #self.dial_b_left.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_BALANCE) + #self.dial_b_right.setEnabled(self.pinfo['hints'] & PLUGIN_CAN_BALANCE) + #self.b_gui.setEnabled(self.pinfo['hints'] & PLUGIN_HAS_GUI) + + #def set_active(self, active, gui_send=False, callback_send=True): + #if (gui_send): self.led_enable.setChecked(active) + #if (callback_send): NativeHost.set_active(self.plugin_id, active) + + #def set_drywet(self, value, gui_send=False, callback_send=True): + #if (gui_send): self.dial_drywet.setValue(value) + #if (callback_send): NativeHost.set_drywet(self.plugin_id, float(value)/1000) + + #message = self.tr("Output dry/wet (%1%)").arg(value/10) + #self.dial_drywet.setStatusTip(message) + #gui.statusBar().showMessage(message) + + #def set_vol(self, value, gui_send=False, callback_send=True): + #if (gui_send): self.dial_vol.setValue(value) + #if (callback_send): NativeHost.set_vol(self.plugin_id, float(value)/1000) + + #message = self.tr("Output volume (%1%)").arg(value/10) + #self.dial_vol.setStatusTip(message) + #gui.statusBar().showMessage(message) + + #def set_balance_left(self, value, gui_send=False, callback_send=True): + #if (gui_send): self.dial_b_left.setValue(value) + #if (callback_send): NativeHost.set_balance_left(self.plugin_id, float(value)/1000) + + #if (value == 0): + #message = self.tr("Left Panning (Center)") + #elif (value < 0): + #message = self.tr("Left Panning (%1% Left)").arg(-value/10) + #else: + #message = self.tr("Left Panning (%1% Right)").arg(value/10) - def handleEdit(self, show): - if (show): - self.edit_dialog.restoreGeometry(self.edit_dialog_geometry.toByteArray()) - else: - self.edit_dialog_geometry = QVariant(self.edit_dialog.saveGeometry()) - self.edit_dialog.setVisible(show) - - def handleRemove(self): - gui.func_remove_plugin(self.plugin_id, True) - - def showCustomDialMenu(self, pos): - dial_name = QStringStr(self.sender().objectName()) - if (dial_name == "dial_drywet"): - minimum = 0 - maximum = 100 - default = 100 - label = "Dry/Wet" - elif (dial_name == "dial_vol"): - minimum = 0 - maximum = 127 - default = 100 - label = "Volume" - elif (dial_name == "dial_b_left"): - minimum = -100 - maximum = 100 - default = -100 - label = "Balance-Left" - elif (dial_name == "dial_b_right"): - minimum = -100 - maximum = 100 - default = 100 - label = "Balance-Right" - else: - minimum = 0 - maximum = 100 - default = 100 - label = "Unknown" - - current = self.sender().value()/10 - - menu = QMenu(self) - act_x_reset = menu.addAction(self.tr("Reset (%1%)").arg(default)) - menu.addSeparator() - act_x_min = menu.addAction(self.tr("Set to Minimum (%1%)").arg(minimum)) - act_x_cen = menu.addAction(self.tr("Set to Center")) - act_x_max = menu.addAction(self.tr("Set to Maximum (%1%)").arg(maximum)) - menu.addSeparator() - act_x_set = menu.addAction(self.tr("Set value...")) - - if (label not in ("Balance-Left", "Balance-Right")): - menu.removeAction(act_x_cen) - - act_x_sel = menu.exec_(QCursor.pos()) - - if (act_x_sel == act_x_set): - value_try = QInputDialog.getInteger(self, self.tr("Set value"), label, current, minimum, maximum, 1) - if (value_try[1]): - value = value_try[0]*10 - else: - value = None - - elif (act_x_sel == act_x_min): - value = minimum*10 - elif (act_x_sel == act_x_max): - value = maximum*10 - elif (act_x_sel == act_x_reset): - value = default*10 - elif (act_x_sel == act_x_cen): - value = 0 - else: - value = None - - if (value != None): - if (label == "Dry/Wet"): - self.set_drywet(value, True, True) - elif (label == "Volume"): - self.set_vol(value, True, True) - elif (label == "Balance-Left"): - self.set_balance_left(value, True, True) - elif (label == "Balance-Right"): - self.set_balance_right(value, True, True) - - def getSaveXMLContent(self): - NativeHost.prepare_for_save(self.plugin_id) - - if (self.pinfo['type'] == PLUGIN_LADSPA): - type_str = "LADSPA" - elif (self.pinfo['type'] == PLUGIN_DSSI): - type_str = "DSSI" - elif (self.pinfo['type'] == PLUGIN_LV2): - type_str = "LV2" - elif (self.pinfo['type'] == PLUGIN_VST): - type_str = "VST" - elif (self.pinfo['type'] == PLUGIN_WINVST): - type_str = "Windows VST" - elif (self.pinfo['type'] == PLUGIN_SF2): - type_str = "SoundFont" - else: - type_str = "Unknown" + #self.dial_b_left.setStatusTip(message) + #gui.statusBar().showMessage(message) - real_plugin_name = NativeHost.get_real_plugin_name(self.plugin_id) - if not real_plugin_name: real_plugin_name = "" + #def set_balance_right(self, value, gui_send=False, callback_send=True): + #if (gui_send): self.dial_b_right.setValue(value) + #if (callback_send): NativeHost.set_balance_right(self.plugin_id, float(value)/1000) - x_save_state_dict = deepcopy(save_state_dict) + #if (value == 0): + #message = self.tr("Right Panning (Center)") + #elif (value < 0): + #message = self.tr("Right Panning (%1%) Left").arg(-value/10) + #else: + #message = self.tr("Right Panning (%1% Right)").arg(value/10) - # ---------------------------- - # Basic info + #self.dial_b_right.setStatusTip(message) + #gui.statusBar().showMessage(message) - x_save_state_dict['Type'] = type_str - x_save_state_dict['Name'] = real_plugin_name - x_save_state_dict['Label'] = self.pinfo['label'] - x_save_state_dict['Binary'] = self.pinfo['binary'] - x_save_state_dict['UniqueID'] = self.pinfo['unique_id'] + #def gui_dialog_closed(self): + #self.b_gui.setChecked(False) - # ---------------------------- - # Internals + #def edit_dialog_closed(self): + #self.b_edit.setChecked(False) - x_save_state_dict['Active'] = self.led_enable.isChecked() - x_save_state_dict['DryWet'] = float(self.dial_drywet.value())/1000 - x_save_state_dict['Vol'] = float(self.dial_vol.value())/1000 - x_save_state_dict['Balance-Left'] = float(self.dial_b_left.value())/1000 - x_save_state_dict['Balance-Right'] = float(self.dial_b_right.value())/1000 + #def check_gui_stuff(self): + ## Input peaks + #if (self.peaks_in > 0): + #if (self.peaks_in > 1): + #peak1 = NativeHost.get_input_peak_value(self.plugin_id, 1) + #peak2 = NativeHost.get_input_peak_value(self.plugin_id, 2) + #self.peak_in.displayMeter(1, peak1) + #self.peak_in.displayMeter(2, peak2) + #self.led_audio_in.setChecked((peak1 != 0.0 or peak2 != 0.0)) - # ---------------------------- - # Programs + #else: + #peak = NativeHost.get_input_peak_value(self.plugin_id, 1) + #self.peak_in.displayMeter(1, peak) + #self.led_audio_in.setChecked((peak != 0.0)) + + ## Output peaks + #if (self.peaks_out > 0): + #if (self.peaks_out > 1): + #peak1 = NativeHost.get_output_peak_value(self.plugin_id, 1) + #peak2 = NativeHost.get_output_peak_value(self.plugin_id, 2) + #self.peak_out.displayMeter(1, peak1) + #self.peak_out.displayMeter(2, peak2) + #self.led_audio_out.setChecked((peak1 != 0.0 or peak2 != 0.0)) + + #else: + #peak = NativeHost.get_output_peak_value(self.plugin_id, 1) + #self.peak_out.displayMeter(1, peak) + #self.led_audio_out.setChecked((peak != 0.0)) + + ## Parameter Activity LED + #if (self.parameter_activity_timer == ICON_STATE_ON): + #self.led_control.setChecked(True) + #self.parameter_activity_timer = ICON_STATE_WAIT + #elif (self.parameter_activity_timer == ICON_STATE_WAIT): + #self.parameter_activity_timer = ICON_STATE_OFF + #elif (self.parameter_activity_timer == ICON_STATE_OFF): + #self.led_control.setChecked(False) + #self.parameter_activity_timer = None + + #def handleShowGUI(self, show): + #if (self.gui_dialog_type in (GUI_INTERNAL_QT4, GUI_INTERNAL_X11)): + #if (show): + #self.gui_dialog.restoreGeometry(self.gui_dialog_geometry.toByteArray()) + #else: + #self.gui_dialog_geometry = QVariant(self.gui_dialog.saveGeometry()) + #self.gui_dialog.setVisible(show) + #NativeHost.show_gui(self.plugin_id, show) - if (self.edit_dialog.cb_programs.currentIndex() >= 0): - x_save_state_dict['ProgramIndex'] = self.edit_dialog.cb_programs.currentIndex() - x_save_state_dict['ProgramName'] = QStringStr(self.edit_dialog.cb_programs.currentText()) + #def handleEdit(self, show): + #if (show): + #self.edit_dialog.restoreGeometry(self.edit_dialog_geometry.toByteArray()) + #else: + #self.edit_dialog_geometry = QVariant(self.edit_dialog.saveGeometry()) + #self.edit_dialog.setVisible(show) + + #def handleRemove(self): + #gui.func_remove_plugin(self.plugin_id, True) + + #def showCustomDialMenu(self, pos): + #dial_name = QStringStr(self.sender().objectName()) + #if (dial_name == "dial_drywet"): + #minimum = 0 + #maximum = 100 + #default = 100 + #label = "Dry/Wet" + #elif (dial_name == "dial_vol"): + #minimum = 0 + #maximum = 127 + #default = 100 + #label = "Volume" + #elif (dial_name == "dial_b_left"): + #minimum = -100 + #maximum = 100 + #default = -100 + #label = "Balance-Left" + #elif (dial_name == "dial_b_right"): + #minimum = -100 + #maximum = 100 + #default = 100 + #label = "Balance-Right" + #else: + #minimum = 0 + #maximum = 100 + #default = 100 + #label = "Unknown" + + #current = self.sender().value()/10 + + #menu = QMenu(self) + #act_x_reset = menu.addAction(self.tr("Reset (%1%)").arg(default)) + #menu.addSeparator() + #act_x_min = menu.addAction(self.tr("Set to Minimum (%1%)").arg(minimum)) + #act_x_cen = menu.addAction(self.tr("Set to Center")) + #act_x_max = menu.addAction(self.tr("Set to Maximum (%1%)").arg(maximum)) + #menu.addSeparator() + #act_x_set = menu.addAction(self.tr("Set value...")) + + #if (label not in ("Balance-Left", "Balance-Right")): + #menu.removeAction(act_x_cen) + + #act_x_sel = menu.exec_(QCursor.pos()) + + #if (act_x_sel == act_x_set): + #value_try = QInputDialog.getInteger(self, self.tr("Set value"), label, current, minimum, maximum, 1) + #if (value_try[1]): + #value = value_try[0]*10 + #else: + #value = None + + #elif (act_x_sel == act_x_min): + #value = minimum*10 + #elif (act_x_sel == act_x_max): + #value = maximum*10 + #elif (act_x_sel == act_x_reset): + #value = default*10 + #elif (act_x_sel == act_x_cen): + #value = 0 + #else: + #value = None + + #if (value != None): + #if (label == "Dry/Wet"): + #self.set_drywet(value, True, True) + #elif (label == "Volume"): + #self.set_vol(value, True, True) + #elif (label == "Balance-Left"): + #self.set_balance_left(value, True, True) + #elif (label == "Balance-Right"): + #self.set_balance_right(value, True, True) + + #def getSaveXMLContent(self): + #NativeHost.prepare_for_save(self.plugin_id) + + #if (self.pinfo['type'] == PLUGIN_LADSPA): + #type_str = "LADSPA" + #elif (self.pinfo['type'] == PLUGIN_DSSI): + #type_str = "DSSI" + #elif (self.pinfo['type'] == PLUGIN_LV2): + #type_str = "LV2" + #elif (self.pinfo['type'] == PLUGIN_VST): + #type_str = "VST" + #elif (self.pinfo['type'] == PLUGIN_WINVST): + #type_str = "Windows VST" + #elif (self.pinfo['type'] == PLUGIN_SF2): + #type_str = "SoundFont" + #else: + #type_str = "Unknown" - # ---------------------------- - # MIDI Programs + #real_plugin_name = NativeHost.get_real_plugin_name(self.plugin_id) + #if not real_plugin_name: real_plugin_name = "" - if (self.edit_dialog.cb_midi_programs.currentIndex() >= 0): - midi_program_info = NativeHost.get_midi_program_info(self.plugin_id, self.edit_dialog.cb_midi_programs.currentIndex()) - x_save_state_dict['MidiBank'] = midi_program_info['bank'] - x_save_state_dict['MidiProgram'] = midi_program_info['program'] + #x_save_state_dict = deepcopy(save_state_dict) - # ---------------------------- - # Parameters + ## ---------------------------- + ## Basic info - parameter_count = NativeHost.get_parameter_count(self.plugin_id) + #x_save_state_dict['Type'] = type_str + #x_save_state_dict['Name'] = real_plugin_name + #x_save_state_dict['Label'] = self.pinfo['label'] + #x_save_state_dict['Binary'] = self.pinfo['binary'] + #x_save_state_dict['UniqueID'] = self.pinfo['unique_id'] - for i in range(parameter_count): - parameter_info = NativeHost.get_parameter_info(self.plugin_id, i) - parameter_data = NativeHost.get_parameter_data(self.plugin_id, i) + ## ---------------------------- + ## Internals - if (not parameter_info['valid'] or parameter_data['type'] != PARAMETER_INPUT): - continue - - # Save from null values - if not parameter_info['name']: parameter_info['name'] = "" - if not parameter_info['symbol']: parameter_info['symbol'] = "" - if not parameter_info['label']: parameter_info['label'] = "" - - x_save_state_parameter = deepcopy(save_state_parameter) - - x_save_state_parameter['index'] = parameter_data['index'] - x_save_state_parameter['rindex'] = parameter_data['rindex'] - x_save_state_parameter['name'] = parameter_info['name'] - x_save_state_parameter['symbol'] = parameter_info['symbol'] - x_save_state_parameter['value'] = NativeHost.get_current_parameter_value(self.plugin_id, parameter_data['index']) - x_save_state_parameter['midi_channel'] = parameter_data['midi_channel']+1 - x_save_state_parameter['midi_cc'] = parameter_data['midi_cc'] - - if (parameter_data['hints'] & PARAMETER_USES_SAMPLERATE): - x_save_state_parameter['value'] /= NativeHost.get_sample_rate() - - x_save_state_dict['Parameters'].append(x_save_state_parameter) - - # ---------------------------- - # Custom Data - - custom_data_count = NativeHost.get_custom_data_count(self.plugin_id) - - for i in range(custom_data_count): - custom_data = NativeHost.get_custom_data(self.plugin_id, i) - - if (custom_data['type'] == CUSTOM_DATA_INVALID): - continue - - # Save from null values - if not custom_data['key']: custom_data['key'] = "" - if not custom_data['value']: custom_data['value'] = "" - - x_save_state_custom_data = deepcopy(save_state_custom_data) - - x_save_state_custom_data['type'] = custom_data['type'] - x_save_state_custom_data['key'] = custom_data['key'] - x_save_state_custom_data['value'] = custom_data['value'] - - x_save_state_dict['CustomData'].append(x_save_state_custom_data) - - # ---------------------------- - # Chunk - - if (self.pinfo['hints'] & PLUGIN_USES_CHUNKS): - chunk_data = NativeHost.get_chunk_data(self.plugin_id) - if chunk_data: - x_save_state_dict['Chunk'] = chunk_data - - # ---------------------------- - # Generate XML for this plugin - - content = "" - - content += " \n" - content += " %s\n" % (x_save_state_dict['Type']) - content += " %s\n" % (x_save_state_dict['Name']) - content += " \n" % (x_save_state_dict['Label']) - content += " %s\n" % (x_save_state_dict['Binary']) - content += " %li\n" % (x_save_state_dict['UniqueID']) - content += " \n" - - content += "\n" - content += " \n" - content += " %s\n" % ("Yes" if x_save_state_dict['Active'] else "No") - content += " %f\n" % (x_save_state_dict['DryWet']) - content += " %f\n" % (x_save_state_dict['Vol']) - content += " %f\n" % (x_save_state_dict['Balance-Left']) - content += " %f\n" % (x_save_state_dict['Balance-Right']) - - for parameter in x_save_state_dict['Parameters']: - content += "\n" - content += " \n" - content += " %i\n" % (parameter['index']) - content += " %i\n" % (parameter['rindex']) - content += " %s\n" % (parameter['name']) - content += " %s\n" % (parameter['symbol']) - content += " %f\n" % (parameter['value']) - content += " %i\n" % (parameter['midi_channel']) - content += " %i\n" % (parameter['midi_cc']) - content += " \n" - - if (x_save_state_dict['ProgramIndex'] >= 0): - content += "\n" - content += " %i\n" % (x_save_state_dict['ProgramIndex']) - content += " %s\n" % (x_save_state_dict['ProgramName']) - - if (x_save_state_dict['MidiBank'] >= 0 and x_save_state_dict['MidiProgram'] >= 0): - content += "\n" - content += " %i\n" % (x_save_state_dict['MidiBank']) - content += " %i\n" % (x_save_state_dict['MidiProgram']) - - for custom_data in x_save_state_dict['CustomData']: - if (not custom_data['value'].endswith("\n")): - custom_data['value'] += "\n" - content += "\n" - content += " \n" - content += " %i\n" % (custom_data['type']) - content += " %s\n" % (custom_data['key']) - content += " \n" - content += "%s" % (Qt.escape(custom_data['value'])) - content += " \n" - content += " \n" - - if (x_save_state_dict['Chunk']): - if (not x_save_state_dict['Chunk'].endswith("\n")): - x_save_state_dict['Chunk'] += "\n" - content += "\n" - content += " \n" - content += "%s" % (x_save_state_dict['Chunk']) - content += " \n" - - content += " \n" - - return content - - def load_save_state_dict(self, content): - - # Part 1 - set custom data - for custom_data in content['CustomData']: - NativeHost.set_custom_data(self.plugin_id, custom_data['type'], custom_data['key'], custom_data['value']) - - # Part 2 - set program (carefully) - program_id = -1 - program_count = NativeHost.get_program_count(self.plugin_id) + #x_save_state_dict['Active'] = self.led_enable.isChecked() + #x_save_state_dict['DryWet'] = float(self.dial_drywet.value())/1000 + #x_save_state_dict['Vol'] = float(self.dial_vol.value())/1000 + #x_save_state_dict['Balance-Left'] = float(self.dial_b_left.value())/1000 + #x_save_state_dict['Balance-Right'] = float(self.dial_b_right.value())/1000 - if (content['ProgramName']): - test_pname = NativeHost.get_program_name(self.plugin_id, content['ProgramIndex']) + ## ---------------------------- + ## Programs - if (content['ProgramName'] == test_pname): - program_id = content['ProgramIndex'] - else: - for i in range(program_count): - new_test_pname = NativeHost.get_program_name(self.plugin_id, i) - if (content['ProgramName'] == new_test_pname): - program_id = i - break - else: - if (content['ProgramIndex'] < program_count): - program_id = content['ProgramIndex'] - else: - if (content['ProgramIndex'] < program_count): - program_id = content['ProgramIndex'] + #if (self.edit_dialog.cb_programs.currentIndex() >= 0): + #x_save_state_dict['ProgramIndex'] = self.edit_dialog.cb_programs.currentIndex() + #x_save_state_dict['ProgramName'] = QStringStr(self.edit_dialog.cb_programs.currentText()) - if (program_id >= 0): - NativeHost.set_program(self.plugin_id, program_id) - self.edit_dialog.set_program(program_id) + ## ---------------------------- + ## MIDI Programs - # Part 3 - set midi program - if (content['MidiBank'] >= 0 and content['MidiProgram'] >= 0): - midi_program_count = NativeHost.get_midi_program_count(self.plugin_id) + #if (self.edit_dialog.cb_midi_programs.currentIndex() >= 0): + #midi_program_info = NativeHost.get_midi_program_info(self.plugin_id, self.edit_dialog.cb_midi_programs.currentIndex()) + #x_save_state_dict['MidiBank'] = midi_program_info['bank'] + #x_save_state_dict['MidiProgram'] = midi_program_info['program'] - for i in range(midi_program_count): - program_info = NativeHost.get_midi_program_info(self.plugin_id, i) - if (program_info['bank'] == content['MidiBank'] and program_info['program'] == content['MidiProgram']): - NativeHost.set_midi_program(self.plugin_id, i) - self.edit_dialog.set_midi_program(i) - break + ## ---------------------------- + ## Parameters - # Part 4a - store symbol values, for ladspa and lv2 - param_symbols = [] # (index, symbol) + #parameter_count = NativeHost.get_parameter_count(self.plugin_id) - for parameter in content['Parameters']: - if (parameter['symbol']): - param_info = NativeHost.get_parameter_info(self.plugin_id, parameter['index']) + #for i in range(parameter_count): + #parameter_info = NativeHost.get_parameter_info(self.plugin_id, i) + #parameter_data = NativeHost.get_parameter_data(self.plugin_id, i) - if (param_info['valid'] and param_info['symbol']): - param_symbols.append((parameter['index'], param_info['symbol'])) + #if (not parameter_info['valid'] or parameter_data['type'] != PARAMETER_INPUT): + #continue - # Part 4b - set parameter values (carefully) - for parameter in content['Parameters']: - index = -1 + ## Save from null values + #if not parameter_info['name']: parameter_info['name'] = "" + #if not parameter_info['symbol']: parameter_info['symbol'] = "" + #if not parameter_info['label']: parameter_info['label'] = "" - if (content['Type'] == "LADSPA"): - # Try to set by symbol, otherwise use index - if (parameter['symbol'] != None and parameter['symbol'] != ""): - for param_symbol in param_symbols: - if (param_symbol[1] == parameter['symbol']): - index = param_symbol[0] - break - else: - index = parameter['index'] - else: - index = parameter['index'] - - elif (content['Type'] == "LV2"): - # Symbol only - if (parameter['symbol'] != None and parameter['symbol'] != ""): - for param_symbol in param_symbols: - if (param_symbol[1] == parameter['symbol']): - index = param_symbol[0] - break - else: - print("Failed to find LV2 parameter symbol for", parameter['index'], "->", parameter['name']) - else: - print("LV2 Plugin parameter", parameter['index'], "has no symbol ->", parameter['name']) + #x_save_state_parameter = deepcopy(save_state_parameter) - else: - # Index only - index = parameter['index'] + #x_save_state_parameter['index'] = parameter_data['index'] + #x_save_state_parameter['rindex'] = parameter_data['rindex'] + #x_save_state_parameter['name'] = parameter_info['name'] + #x_save_state_parameter['symbol'] = parameter_info['symbol'] + #x_save_state_parameter['value'] = NativeHost.get_current_parameter_value(self.plugin_id, parameter_data['index']) + #x_save_state_parameter['midi_channel'] = parameter_data['midi_channel']+1 + #x_save_state_parameter['midi_cc'] = parameter_data['midi_cc'] - if (index >= 0): - param_data = NativeHost.get_parameter_data(self.plugin_id, parameter['index']) - if (param_data['hints'] & PARAMETER_USES_SAMPLERATE): - parameter['value'] *= NativeHost.get_sample_rate() + #if (parameter_data['hints'] & PARAMETER_USES_SAMPLERATE): + #x_save_state_parameter['value'] /= NativeHost.get_sample_rate() - NativeHost.set_parameter_value(self.plugin_id, index, parameter['value']) - NativeHost.set_parameter_midi_channel(self.plugin_id, index, parameter['midi_channel']-1) - NativeHost.set_parameter_midi_cc(self.plugin_id, index, parameter['midi_cc']) - else: - print("Could not set parameter data for", parameter['index'], "->", parameter['name']) + #x_save_state_dict['Parameters'].append(x_save_state_parameter) - # Part 5 - set chunk data - if (content['Chunk']): - NativeHost.set_chunk_data(self.plugin_id, content['Chunk']) + ## ---------------------------- + ## Custom Data - # Part 6 - set internal stuff - self.set_drywet(content['DryWet']*1000, True, True) - self.set_vol(content['Vol']*1000, True, True) - self.set_balance_left(content['Balance-Left']*1000, True, True) - self.set_balance_right(content['Balance-Right']*1000, True, True) - self.edit_dialog.do_reload_all() + #custom_data_count = NativeHost.get_custom_data_count(self.plugin_id) - self.set_active(content['Active'], True, True) + #for i in range(custom_data_count): + #custom_data = NativeHost.get_custom_data(self.plugin_id, i) - # Done! - gui.statusBar().showMessage("State File Loaded Sucessfully!") + #if (custom_data['type'] == CUSTOM_DATA_INVALID): + #continue - def timerEvent(self, event): - if (event.timerId() == self.TIMER_GUI_STUFF): - self.check_gui_stuff() - return QFrame.timerEvent(self, event) + ## Save from null values + #if not custom_data['key']: custom_data['key'] = "" + #if not custom_data['value']: custom_data['value'] = "" + + #x_save_state_custom_data = deepcopy(save_state_custom_data) + + #x_save_state_custom_data['type'] = custom_data['type'] + #x_save_state_custom_data['key'] = custom_data['key'] + #x_save_state_custom_data['value'] = custom_data['value'] + + #x_save_state_dict['CustomData'].append(x_save_state_custom_data) + + ## ---------------------------- + ## Chunk + + #if (self.pinfo['hints'] & PLUGIN_USES_CHUNKS): + #chunk_data = NativeHost.get_chunk_data(self.plugin_id) + #if chunk_data: + #x_save_state_dict['Chunk'] = chunk_data + + ## ---------------------------- + ## Generate XML for this plugin + + #content = "" + + #content += " \n" + #content += " %s\n" % (x_save_state_dict['Type']) + #content += " %s\n" % (x_save_state_dict['Name']) + #content += " \n" % (x_save_state_dict['Label']) + #content += " %s\n" % (x_save_state_dict['Binary']) + #content += " %li\n" % (x_save_state_dict['UniqueID']) + #content += " \n" + + #content += "\n" + #content += " \n" + #content += " %s\n" % ("Yes" if x_save_state_dict['Active'] else "No") + #content += " %f\n" % (x_save_state_dict['DryWet']) + #content += " %f\n" % (x_save_state_dict['Vol']) + #content += " %f\n" % (x_save_state_dict['Balance-Left']) + #content += " %f\n" % (x_save_state_dict['Balance-Right']) + + #for parameter in x_save_state_dict['Parameters']: + #content += "\n" + #content += " \n" + #content += " %i\n" % (parameter['index']) + #content += " %i\n" % (parameter['rindex']) + #content += " %s\n" % (parameter['name']) + #content += " %s\n" % (parameter['symbol']) + #content += " %f\n" % (parameter['value']) + #content += " %i\n" % (parameter['midi_channel']) + #content += " %i\n" % (parameter['midi_cc']) + #content += " \n" + + #if (x_save_state_dict['ProgramIndex'] >= 0): + #content += "\n" + #content += " %i\n" % (x_save_state_dict['ProgramIndex']) + #content += " %s\n" % (x_save_state_dict['ProgramName']) + + #if (x_save_state_dict['MidiBank'] >= 0 and x_save_state_dict['MidiProgram'] >= 0): + #content += "\n" + #content += " %i\n" % (x_save_state_dict['MidiBank']) + #content += " %i\n" % (x_save_state_dict['MidiProgram']) + + #for custom_data in x_save_state_dict['CustomData']: + #if (not custom_data['value'].endswith("\n")): + #custom_data['value'] += "\n" + #content += "\n" + #content += " \n" + #content += " %i\n" % (custom_data['type']) + #content += " %s\n" % (custom_data['key']) + #content += " \n" + #content += "%s" % (Qt.escape(custom_data['value'])) + #content += " \n" + #content += " \n" + + #if (x_save_state_dict['Chunk']): + #if (not x_save_state_dict['Chunk'].endswith("\n")): + #x_save_state_dict['Chunk'] += "\n" + #content += "\n" + #content += " \n" + #content += "%s" % (x_save_state_dict['Chunk']) + #content += " \n" + + #content += " \n" + + #return content + + #def load_save_state_dict(self, content): + + ## Part 1 - set custom data + #for custom_data in content['CustomData']: + #NativeHost.set_custom_data(self.plugin_id, custom_data['type'], custom_data['key'], custom_data['value']) + + ## Part 2 - set program (carefully) + #program_id = -1 + #program_count = NativeHost.get_program_count(self.plugin_id) + + #if (content['ProgramName']): + #test_pname = NativeHost.get_program_name(self.plugin_id, content['ProgramIndex']) + + #if (content['ProgramName'] == test_pname): + #program_id = content['ProgramIndex'] + #else: + #for i in range(program_count): + #new_test_pname = NativeHost.get_program_name(self.plugin_id, i) + #if (content['ProgramName'] == new_test_pname): + #program_id = i + #break + #else: + #if (content['ProgramIndex'] < program_count): + #program_id = content['ProgramIndex'] + #else: + #if (content['ProgramIndex'] < program_count): + #program_id = content['ProgramIndex'] + + #if (program_id >= 0): + #NativeHost.set_program(self.plugin_id, program_id) + #self.edit_dialog.set_program(program_id) + + ## Part 3 - set midi program + #if (content['MidiBank'] >= 0 and content['MidiProgram'] >= 0): + #midi_program_count = NativeHost.get_midi_program_count(self.plugin_id) + + #for i in range(midi_program_count): + #program_info = NativeHost.get_midi_program_info(self.plugin_id, i) + #if (program_info['bank'] == content['MidiBank'] and program_info['program'] == content['MidiProgram']): + #NativeHost.set_midi_program(self.plugin_id, i) + #self.edit_dialog.set_midi_program(i) + #break + + ## Part 4a - store symbol values, for ladspa and lv2 + #param_symbols = [] # (index, symbol) + + #for parameter in content['Parameters']: + #if (parameter['symbol']): + #param_info = NativeHost.get_parameter_info(self.plugin_id, parameter['index']) + + #if (param_info['valid'] and param_info['symbol']): + #param_symbols.append((parameter['index'], param_info['symbol'])) + + ## Part 4b - set parameter values (carefully) + #for parameter in content['Parameters']: + #index = -1 + + #if (content['Type'] == "LADSPA"): + ## Try to set by symbol, otherwise use index + #if (parameter['symbol'] != None and parameter['symbol'] != ""): + #for param_symbol in param_symbols: + #if (param_symbol[1] == parameter['symbol']): + #index = param_symbol[0] + #break + #else: + #index = parameter['index'] + #else: + #index = parameter['index'] + + #elif (content['Type'] == "LV2"): + ## Symbol only + #if (parameter['symbol'] != None and parameter['symbol'] != ""): + #for param_symbol in param_symbols: + #if (param_symbol[1] == parameter['symbol']): + #index = param_symbol[0] + #break + #else: + #print("Failed to find LV2 parameter symbol for", parameter['index'], "->", parameter['name']) + #else: + #print("LV2 Plugin parameter", parameter['index'], "has no symbol ->", parameter['name']) + + #else: + ## Index only + #index = parameter['index'] + + #if (index >= 0): + #param_data = NativeHost.get_parameter_data(self.plugin_id, parameter['index']) + #if (param_data['hints'] & PARAMETER_USES_SAMPLERATE): + #parameter['value'] *= NativeHost.get_sample_rate() + + #NativeHost.set_parameter_value(self.plugin_id, index, parameter['value']) + #NativeHost.set_parameter_midi_channel(self.plugin_id, index, parameter['midi_channel']-1) + #NativeHost.set_parameter_midi_cc(self.plugin_id, index, parameter['midi_cc']) + #else: + #print("Could not set parameter data for", parameter['index'], "->", parameter['name']) + + ## Part 5 - set chunk data + #if (content['Chunk']): + #NativeHost.set_chunk_data(self.plugin_id, content['Chunk']) + + ## Part 6 - set internal stuff + #self.set_drywet(content['DryWet']*1000, True, True) + #self.set_vol(content['Vol']*1000, True, True) + #self.set_balance_left(content['Balance-Left']*1000, True, True) + #self.set_balance_right(content['Balance-Right']*1000, True, True) + #self.edit_dialog.do_reload_all() + + #self.set_active(content['Active'], True, True) + + ## Done! + #gui.statusBar().showMessage("State File Loaded Sucessfully!") def paintEvent(self, event): painter = QPainter(self) @@ -2690,7 +2685,7 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): self.m_project_filename = None - NativeHost.set_callback_function(self.callback_function) + CarlaHost.set_callback_function(self.callback_function) # ------------------------------------------------------------- # Set-up GUI stuff @@ -2856,16 +2851,16 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): #"You may want to save your session now...", QMessageBox.Ok, QMessageBox.Ok) def add_plugin(self, btype, ptype, filename, label, extra_stuff, activate): - new_plugin_id = NativeHost.add_plugin(btype, ptype, filename, label, extra_stuff) + new_plugin_id = CarlaHost.add_plugin(btype, ptype, filename, label, extra_stuff) if (new_plugin_id < 0): CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to load plugin"), - NativeHost.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) - #else: - #pwidget = PluginWidget(self, new_plugin_id) - #self.w_plugins.layout().addWidget(pwidget) - #self.plugin_list[new_plugin_id] = pwidget - #self.act_plugin_remove_all.setEnabled(True) + CarlaHost.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) + else: + pwidget = PluginWidget(self, new_plugin_id) + self.w_plugins.layout().addWidget(pwidget) + self.m_plugin_list[new_plugin_id] = pwidget + self.act_plugin_remove_all.setEnabled(True) #if (activate): #pwidget.set_active(True, True) @@ -2879,16 +2874,16 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): #if (pwidget.gui_dialog): #pwidget.gui_dialog.close() - #if (NativeHost.remove_plugin(plugin_id)): - #pwidget.close() - #pwidget.deleteLater() - #self.w_plugins.layout().removeWidget(pwidget) - #self.plugin_list[plugin_id] = None + if (CarlaHost.remove_plugin(plugin_id)): + pwidget.close() + pwidget.deleteLater() + self.w_plugins.layout().removeWidget(pwidget) + self.m_plugin_list[plugin_id] = None - #else: - #if (showError): - #CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to remove plugin"), - #NativeHost.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) + else: + if (showError): + CustomMessageBox(self, QMessageBox.Critical, self.tr("Error"), self.tr("Failed to remove plugin"), + CarlaHost.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) for i in range(MAX_PLUGINS): if (self.m_plugin_list[i] != None): @@ -3184,6 +3179,11 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW): def loadSettings(self): self.restoreGeometry(self.settings.value("Geometry", "")) + def timerEvent(self, event): + #if (event.timerId() == self.TIMER_GUI_STUFF): + #self.check_gui_stuff() + QMainWindow.timerEvent(self, event) + def closeEvent(self, event): self.saveSettings() self.slot_remove_all() @@ -3202,29 +3202,14 @@ if __name__ == '__main__': #style = app.style().metaObject().className() #force_parameters_style = (style in ("Bespin::Style",)) - NativeHost = Host() - #NativeHost.set_option(OPTION_GLOBAL_JACK_CLIENT, 0, "") - #NativeHost.set_option(OPTION_BRIDGE_PATH_LV2_GTK2, 0, carla_bridge_lv2_gtk2) - #NativeHost.set_option(OPTION_BRIDGE_PATH_LV2_QT4, 0, carla_bridge_lv2_qt4) - #NativeHost.set_option(OPTION_BRIDGE_PATH_LV2_X11, 0, carla_bridge_lv2_x11) - #NativeHost.set_option(OPTION_BRIDGE_PATH_VST_QT4, 0, carla_bridge_vst_qt4) - #NativeHost.set_option(OPTION_BRIDGE_PATH_WINVST, 0, carla_bridge_winvst) + CarlaHost = Host() + #CarlaHost.set_option(OPTION_GLOBAL_JACK_CLIENT, 1, "") - if (not NativeHost.carla_init("Carla")): + if (not CarlaHost.carla_init("Carla")): CustomMessageBox(None, QMessageBox.Critical, "Error", "Could not connect to JACK", - NativeHost.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) + CarlaHost.get_last_error(), QMessageBox.Ok, QMessageBox.Ok) sys.exit(1) - ## X11 Display - #Display = 0 - #if (LINUX): - #Display_env = os.getenv("DISPLAY") - #if (Display_env != None): - #try: - #Display = int(float(Display_env.replace(":",""))) - #except: - #Display = 0 - # Show GUI gui = CarlaMainW() gui.show() @@ -3244,9 +3229,9 @@ if __name__ == '__main__': ret = app.exec_() # Close Host - if (NativeHost.carla_is_engine_running()): - if (not NativeHost.carla_close()): - print(NativeHost.get_last_error()) + if (CarlaHost.carla_is_engine_running()): + if (not CarlaHost.carla_close()): + print(CarlaHost.get_last_error().decode("utf-8")) # Exit properly sys.exit(ret) diff --git a/src/carla/Makefile b/src/carla/Makefile index c27a142..bf082f3 100644 --- a/src/carla/Makefile +++ b/src/carla/Makefile @@ -7,13 +7,13 @@ CC ?= gcc CXX ?= g++ -CARLA_BUILD_FLAGS = -Wall -std=c++0x -fPIC -I. -Ivestige `pkg-config --cflags jack fluidsynth liblo QtCore QtGui` $(CXXFLAGS) +CARLA_BUILD_FLAGS = -Wall -std=c++0x -fPIC -I. -I../carla-includes `pkg-config --cflags jack fluidsynth liblo QtCore QtGui` $(CXXFLAGS) CARLA_BUILD_FLAGS += -DDEBUG -O0 -g # CARLA_BUILD_FLAGS += -DNDEBUG -DQT_NO_DEBUG -DQT_NO_DEBUG_STREAM -DQT_NO_DEBUG_OUTPUT -O2 -fvisibility=hidden -ffast-math -fomit-frame-pointer -mtune=generic -msse CARLA_LINK_FLAGS = -shared -fPIC -ldl `pkg-config --libs jack fluidsynth liblo QtCore QtGui` $(LDFLAGS) -OBJS = carla_backend.o -# jack.o osc.o misc.o ladspa.o dssi.o lv2.o vst.o winvst.o sf2.o lv2-rtmempool/rtmempool.o +OBJS = carla_backend.o jack.o ladspa.o +# osc.o misc.o dssi.o lv2.o vst.o winvst.o sf2.o lv2-rtmempool/rtmempool.o all: carla_backend.so diff --git a/src/carla/carla_backend.cpp b/src/carla/carla_backend.cpp index 68211d6..d705acd 100644 --- a/src/carla/carla_backend.cpp +++ b/src/carla/carla_backend.cpp @@ -16,32 +16,26 @@ */ #include "carla_backend.h" +#include "carla_plugin.h" + +#include +#include + +#include +#include // Global variables CallbackFunc Callback = nullptr; const char* last_error = nullptr; const char* carla_client_name = nullptr; -#if 0 - -#include "audio_plugin.h" -#include "misc.h" - -#include -#include -#include - -#include -#include - QMutex carla_proc_lock_var; QMutex carla_midi_lock_var; -CarlaCheckThread check_thread; // Global variables (shared) const char* unique_names[MAX_PLUGINS] = { nullptr }; -AudioPlugin* AudioPlugins[MAX_PLUGINS] = { nullptr }; -ExternalMidiNote ExternalMidiNotes[MAX_MIDI_EVENTS]; +CarlaPlugin* CarlaPlugins[MAX_PLUGINS] = { nullptr }; +//ExternalMidiNote ExternalMidiNotes[MAX_MIDI_EVENTS]; volatile double ains_peak[MAX_PLUGINS*2] = { 0.0 }; volatile double aouts_peak[MAX_PLUGINS*2] = { 0.0 }; @@ -49,22 +43,12 @@ volatile double aouts_peak[MAX_PLUGINS*2] = { 0.0 }; // Global JACK client jack_client_t* carla_jack_client = nullptr; jack_nframes_t carla_buffer_size = 512; -jack_nframes_t carla_sample_rate = 48000; - -// Global OSC stuff -lo_server_thread global_osc_server_thread = nullptr; -const char* global_osc_server_path = nullptr; -OscData global_osc_data = { nullptr, nullptr, nullptr }; +jack_nframes_t carla_sample_rate = 44100; // Global options carla_options_t carla_options = { /* _initiated */ false, - /* global_jack_client */ false, - /* bridge_path_lv2_gtk2 */ nullptr, - /* bridge_path_lv2_qt4 */ nullptr, - /* bridge_path_lv2_x11 */ nullptr, - /* bridge_path_vst_qt4 */ nullptr, - /* bridge_path_winvst */ nullptr + /* global_jack_client */ true }; // jack.cpp @@ -75,22 +59,23 @@ void carla_jack_shutdown_callback(void* arg); // plugin specific short add_plugin_ladspa(const char* filename, const char* label, void* extra_stuff); -short add_plugin_dssi(const char* filename, const char* label, void* extra_stuff); -short add_plugin_lv2(const char* filename, const char* label, void* extra_stuff); -short add_plugin_vst(const char* filename, const char* label); -short add_plugin_winvst(const char* filename, const char* label, void* extra_stuff); -short add_plugin_sf2(const char* filename, const char* label); +//short add_plugin_dssi(const char* filename, const char* label, void* extra_stuff); +//short add_plugin_lv2(const char* filename, const char* label, void* extra_stuff); +//short add_plugin_vst(const char* filename, const char* label); +//short add_plugin_sf2(const char* filename, const char* label); // ------------------------------------------------------------------------------------------------------------------- // Exported symbols (API) + bool carla_init(const char* client_name) { qDebug("carla_init(%s)", client_name); - carla_options._initiated = true; + // todo - check this in python + carla_options.initiated = true; bool started = false; - carla_jack_client = jack_client_open(client_name, JackNullOption, 0x0); + carla_jack_client = jack_client_open(client_name, JackNullOption, nullptr); if (carla_jack_client) { @@ -120,25 +105,25 @@ bool carla_init(const char* client_name) if (started) { - client_name = jack_get_client_name(carla_jack_client); + const char* real_client_name = jack_get_client_name(carla_jack_client); // Fix name for OSC usage - char* fixed_name = strdup(client_name); + char* fixed_name = strdup(real_client_name); for (size_t i=0; i < strlen(fixed_name); i++) { - if (!std::isalpha(fixed_name[i]) && !std::isdigit(fixed_name[i])) + if (std::isalpha(fixed_name[i]) == false && std::isdigit(fixed_name[i]) == false) fixed_name[i] = '_'; } carla_client_name = strdup(fixed_name); free((void*)fixed_name); - for (unsigned short i=0; iid >= 0) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() >= 0) remove_plugin(i); } - check_thread.quit(); + //check_thread.quit(); - if (!check_thread.wait(1000000)) // 1 sec - qWarning("Failed to properly stop global check thread"); + //if (!check_thread.wait(1000000)) // 1 sec + // qWarning("Failed to properly stop global check thread"); - osc_send_exit(&global_osc_data); - osc_close(); + //osc_send_exit(&global_osc_data); + //osc_close(); if (carla_client_name) free((void*)carla_client_name); @@ -185,30 +172,12 @@ bool carla_close() if (last_error) free((void*)last_error); - if (carla_options._initiated) - { - if (carla_options.bridge_path_lv2_gtk2) - free((void*)carla_options.bridge_path_lv2_gtk2); - - if (carla_options.bridge_path_lv2_qt4) - free((void*)carla_options.bridge_path_lv2_qt4); - - if (carla_options.bridge_path_lv2_x11) - free((void*)carla_options.bridge_path_lv2_x11); - - if (carla_options.bridge_path_vst_qt4) - free((void*)carla_options.bridge_path_vst_qt4); - - if (carla_options.bridge_path_winvst) - free((void*)carla_options.bridge_path_winvst); - } - // cleanup static data get_plugin_info(0); get_parameter_info(0, 0); get_scalepoint_info(0, 0, 0); - get_chunk_data(0); - get_real_plugin_name(0); + //get_chunk_data(0); + //get_real_plugin_name(0); return closed; } @@ -218,24 +187,26 @@ bool carla_is_engine_running() return bool(carla_jack_client); } -short add_plugin(PluginType ptype, const char* filename, const char* label, void* extra_stuff) +short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff) { - qDebug("add_plugin(%s, %s, %i, %p)", filename, label, ptype, extra_stuff); + qDebug("add_plugin(%i, %i, %s, %s, %p)", btype, ptype, filename, label, extra_stuff); + + // TODO - check for bridge type switch (ptype) { case PLUGIN_LADSPA: return add_plugin_ladspa(filename, label, extra_stuff); +#if 0 case PLUGIN_DSSI: return add_plugin_dssi(filename, label, extra_stuff); case PLUGIN_LV2: return add_plugin_lv2(filename, label, extra_stuff); case PLUGIN_VST: return add_plugin_vst(filename, label); - case PLUGIN_WINVST: - return add_plugin_winvst(filename, label, extra_stuff); case PLUGIN_SF2: return add_plugin_sf2(filename, label); +#endif default: set_last_error("Unknown plugin type"); return -1; @@ -248,18 +219,18 @@ bool remove_plugin(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - osc_send_remove_plugin(&global_osc_data, plugin->id); + //osc_send_remove_plugin(&global_osc_data, plugin->id); carla_proc_lock(); - plugin->id = -1; + plugin->set_id(-1); carla_proc_unlock(); - plugin->delete_me(); + delete plugin; - AudioPlugins[i] = nullptr; + CarlaPlugins[i] = nullptr; unique_names[i] = nullptr; return true; @@ -274,7 +245,7 @@ PluginInfo* get_plugin_info(unsigned short plugin_id) { qDebug("get_plugin_info(%i)", plugin_id); - static PluginInfo info = { false, PLUGIN_NONE, PLUGIN_CATEGORY_NONE, 0, nullptr, nullptr, nullptr, nullptr, nullptr, 0 }; + static PluginInfo info = { false, PLUGIN_NONE, PLUGIN_CATEGORY_NONE, 0x0, nullptr, nullptr, nullptr, nullptr, nullptr, 0 }; if (info.valid) { @@ -287,18 +258,18 @@ PluginInfo* get_plugin_info(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { char buf_str[STR_MAX] = { 0 }; info.valid = true; - info.type = plugin->type; - info.category = plugin->get_category(); - info.hints = plugin->hints; - info.binary = plugin->filename; - info.name = plugin->name; - info.unique_id = plugin->get_unique_id(); + info.type = plugin->type(); + info.category = plugin->category(); + info.hints = plugin->hints(); + info.binary = plugin->filename(); + info.name = plugin->name(); + info.unique_id = plugin->unique_id(); plugin->get_label(buf_str); info.label = strdup(buf_str); @@ -328,13 +299,11 @@ PortCountInfo* get_audio_port_count_info(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { info.valid = true; - info.ins = plugin->ain.count; - info.outs = plugin->aout.count; - info.total = info.ins + info.outs; + plugin->get_audio_port_count_info(&info); return &info; } } @@ -352,13 +321,11 @@ PortCountInfo* get_midi_port_count_info(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { info.valid = true; - info.ins = plugin->min.count; - info.outs = plugin->mout.count; - info.total = info.ins + info.outs; + plugin->get_midi_port_count_info(&info); return &info; } } @@ -376,23 +343,11 @@ PortCountInfo* get_parameter_count_info(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { info.valid = true; - info.ins = 0; - info.outs = 0; - info.total = plugin->param.count; - - for (uint32_t j=0; j < plugin->param.count; j++) - { - ParameterType ParamType = plugin->param.data[j].type; - if (ParamType == PARAMETER_INPUT) - info.ins += 1; - else if (ParamType == PARAMETER_OUTPUT) - info.outs += 1; - } - + plugin->get_parameter_count_info(&info); return &info; } } @@ -418,30 +373,24 @@ ParameterInfo* get_parameter_info(unsigned short plugin_id, uint32_t parameter_i for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) + if (parameter_id < plugin->param_count()) { char buf_str[STR_MAX] = { 0 }; - int32_t rindex = plugin->param.data[parameter_id].rindex; - if (rindex >= 0) - { - info.valid = true; - info.scalepoint_count = plugin->get_scalepoint_count(rindex); + info.valid = true; + info.scalepoint_count = plugin->param_scalepoint_count(parameter_id); - plugin->get_parameter_name(rindex, buf_str); - info.name = strdup(buf_str); + plugin->get_parameter_name(parameter_id, buf_str); + info.name = strdup(buf_str); - plugin->get_parameter_symbol(rindex, buf_str); - info.symbol = strdup(buf_str); + plugin->get_parameter_symbol(parameter_id, buf_str); + info.symbol = strdup(buf_str); - plugin->get_parameter_label(rindex, buf_str); - info.label = strdup(buf_str); - } - else - qCritical("get_parameter_info(%i, %i) - invalid rindex: %i", plugin_id, parameter_id, rindex); + plugin->get_parameter_label(parameter_id, buf_str); + info.label = strdup(buf_str); } else qCritical("get_parameter_info(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); @@ -463,29 +412,25 @@ ScalePointInfo* get_scalepoint_info(unsigned short plugin_id, uint32_t parameter static ScalePointInfo info = { false, 0.0, nullptr }; if (info.valid) - { free((void*)info.label); - } info.valid = false; for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) + if (parameter_id < plugin->param_count()) { - int32_t rindex = plugin->param.data[parameter_id].rindex; - - if (scalepoint_id < plugin->get_scalepoint_count(rindex)) + if (scalepoint_id < plugin->param_scalepoint_count(parameter_id)) { char buf_str[STR_MAX] = { 0 }; info.valid = true; - info.value = plugin->get_scalepoint_value(rindex, scalepoint_id); + info.value = plugin->param_scalepoint_value(parameter_id, scalepoint_id); - plugin->get_scalepoint_label(rindex, scalepoint_id, buf_str); + plugin->get_parameter_scalepoint_label(parameter_id, scalepoint_id, buf_str); info.label = strdup(buf_str); } else @@ -513,18 +458,18 @@ MidiProgramInfo* get_midi_program_info(unsigned short plugin_id, uint32_t midi_p for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (midi_program_id < plugin->midiprog.count) - { - info.valid = true; - info.bank = plugin->midiprog.data[midi_program_id].bank; - info.program = plugin->midiprog.data[midi_program_id].program; - info.label = plugin->midiprog.names[midi_program_id]; - } - else - qCritical("get_midi_program_info(%i, %i) - midi_program_id out of bounds", plugin_id, midi_program_id); +// if (midi_program_id < plugin->midiprog.count) +// { +// info.valid = true; +// info.bank = plugin->midiprog.data[midi_program_id].bank; +// info.program = plugin->midiprog.data[midi_program_id].program; +// info.label = plugin->midiprog.names[midi_program_id]; +// } +// else +// qCritical("get_midi_program_info(%i, %i) - midi_program_id out of bounds", plugin_id, midi_program_id); return &info; } @@ -542,13 +487,13 @@ ParameterData* get_parameter_data(unsigned short plugin_id, uint32_t parameter_i for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) - return &plugin->param.data[parameter_id]; - else - qCritical("get_parameter_data(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); +// if (parameter_id < plugin->param_count()) +// return &plugin->param.data[parameter_id]; +// else +// qCritical("get_parameter_data(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); return &data; } @@ -566,13 +511,13 @@ ParameterRanges* get_parameter_ranges(unsigned short plugin_id, uint32_t paramet for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) - return &plugin->param.ranges[parameter_id]; - else - qCritical("get_parameter_ranges(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); +// if (parameter_id < plugin->param.count) +// return &plugin->param.ranges[parameter_id]; +// else +// qCritical("get_parameter_ranges(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); return &ranges; } @@ -586,17 +531,17 @@ CustomData* get_custom_data(unsigned short plugin_id, uint32_t custom_data_id) { qDebug("get_custom_data(%i, %i)", plugin_id, custom_data_id); - static CustomData data = { CUSTOM_DATA_INVALID, nullptr, nullptr }; + static CustomData data = { "NULL", nullptr, nullptr }; for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (custom_data_id < (uint32_t)plugin->custom.count()) - return &plugin->custom[custom_data_id]; - else - qCritical("get_custom_data(%i, %i) - custom_data_id out of bounds", plugin_id, custom_data_id); +// if (custom_data_id < (uint32_t)plugin->custom.count()) +// return &plugin->custom[custom_data_id]; +// else +// qCritical("get_custom_data(%i, %i) - custom_data_id out of bounds", plugin_id, custom_data_id); return &data; } @@ -619,24 +564,24 @@ const char* get_chunk_data(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (plugin->hints & PLUGIN_USES_CHUNKS) - { - void* data = nullptr; - int32_t data_size = plugin->get_chunk_data(&data); - - if (data && data_size >= 4) - { - QByteArray chunk((const char*)data, data_size); - chunk_data = strdup(chunk.toBase64().data()); - } - else - qCritical("get_chunk_data(%i) - got invalid chunk data", plugin_id); - } - else - qCritical("get_chunk_data(%i) - plugin does not support chunks", plugin_id); +// if (plugin->hints & PLUGIN_USES_CHUNKS) +// { +// void* data = nullptr; +// int32_t data_size = plugin->get_chunk_data(&data); + +// if (data && data_size >= 4) +// { +// QByteArray chunk((const char*)data, data_size); +// chunk_data = strdup(chunk.toBase64().data()); +// } +// else +// qCritical("get_chunk_data(%i) - got invalid chunk data", plugin_id); +// } +// else +// qCritical("get_chunk_data(%i) - plugin does not support chunks", plugin_id); return chunk_data; } @@ -656,9 +601,9 @@ GuiData* get_gui_data(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return &plugin->gui; +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return &plugin->gui; } qCritical("get_gui_data(%i) - could not find plugin", plugin_id); @@ -671,9 +616,9 @@ uint32_t get_parameter_count(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return plugin->param.count; +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->param_count; } qCritical("get_parameter_count(%i) - could not find plugin", plugin_id); @@ -686,9 +631,9 @@ uint32_t get_program_count(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return plugin->prog.count; +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->prog.count; } qCritical("get_program_count(%i) - could not find plugin", plugin_id); @@ -701,9 +646,9 @@ uint32_t get_midi_program_count(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return plugin->midiprog.count; +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->midiprog.count; } qCritical("get_midi_program_count(%i) - could not find plugin", plugin_id); @@ -716,9 +661,9 @@ uint32_t get_custom_data_count(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return plugin->custom.count(); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->custom.count(); } qCritical("get_custom_data_count(%i) - could not find plugin", plugin_id); @@ -731,13 +676,13 @@ const char* get_program_name(unsigned short plugin_id, uint32_t program_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (program_id < plugin->prog.count) - return plugin->prog.names[program_id]; - else - qCritical("get_program_name(%i, %i) - program_id out of bounds", plugin_id, program_id); +// if (program_id < plugin->prog.count) +// return plugin->prog.names[program_id]; +// else +// qCritical("get_program_name(%i, %i) - program_id out of bounds", plugin_id, program_id); return nullptr; } @@ -753,13 +698,13 @@ const char* get_midi_program_name(unsigned short plugin_id, uint32_t midi_progra for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (midi_program_id < plugin->midiprog.count) - return plugin->midiprog.names[midi_program_id]; - else - qCritical("get_midi_program_name(%i, %i) - program_id out of bounds", plugin_id, midi_program_id); +// if (midi_program_id < plugin->midiprog.count) +// return plugin->midiprog.names[midi_program_id]; +// else +// qCritical("get_midi_program_name(%i, %i) - program_id out of bounds", plugin_id, midi_program_id); return nullptr; } @@ -782,15 +727,15 @@ const char* get_real_plugin_name(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - char buf_str[STR_MAX] = { 0 }; +// char buf_str[STR_MAX] = { 0 }; - plugin->get_real_name(buf_str); - real_plugin_name = strdup(buf_str); +// plugin->get_real_name(buf_str); +// real_plugin_name = strdup(buf_str); - return real_plugin_name; +// return real_plugin_name; } } @@ -806,9 +751,9 @@ int32_t get_current_program_index(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return plugin->prog.current; +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->prog.current; } qCritical("get_current_program_index(%i) - could not find plugin", plugin_id); @@ -821,9 +766,9 @@ int32_t get_current_midi_program_index(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) - return plugin->midiprog.current; +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->midiprog.current; } qCritical("get_current_midi_program_index(%i) - could not find plugin", plugin_id); @@ -836,13 +781,13 @@ double get_default_parameter_value(unsigned short plugin_id, uint32_t parameter_ for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) - return plugin->param.ranges[parameter_id].def; - else - qCritical("get_default_parameter_value(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); +// if (parameter_id < plugin->param.count) +// return plugin->param.ranges[parameter_id].def; +// else +// qCritical("get_default_parameter_value(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); return 0.0; } @@ -858,20 +803,20 @@ double get_current_parameter_value(unsigned short plugin_id, uint32_t parameter_ for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) - { - double value = plugin->param.buffers[parameter_id]; +// if (parameter_id < plugin->param.count) +// { +// double value = plugin->param.buffers[parameter_id]; - if (plugin->param.data[parameter_id].hints & PARAMETER_HAS_STRICT_BOUNDS) - plugin->fix_parameter_value(value, plugin->param.ranges[parameter_id]); +// if (plugin->param.data[parameter_id].hints & PARAMETER_HAS_STRICT_BOUNDS) +// plugin->fix_parameter_value(value, plugin->param.ranges[parameter_id]); - return value; - } - else - qCritical("get_current_parameter_value(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); +// return value; +// } +// else +// qCritical("get_current_parameter_value(%i, %i) - parameter_id out of bounds", plugin_id, parameter_id); return 0.0; } @@ -899,16 +844,16 @@ double get_output_peak_value(unsigned short plugin_id, unsigned short port_id) void set_active(unsigned short plugin_id, bool onoff) { - qDebug("set_active(%i, %s)", plugin_id, bool2str(onoff)); +// qDebug("set_active(%i, %s)", plugin_id, bool2str(onoff)); for (unsigned short i=0; iid == plugin_id) - return plugin->set_active(onoff, true, false); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->set_active(onoff, true, false); } - qCritical("set_active(%i, %s) - could not find plugin", plugin_id, bool2str(onoff)); +// qCritical("set_active(%i, %s) - could not find plugin", plugin_id, bool2str(onoff)); } void set_drywet(unsigned short plugin_id, double value) @@ -917,23 +862,23 @@ void set_drywet(unsigned short plugin_id, double value) for (unsigned short i=0; iid == plugin_id) - return plugin->set_drywet(value, true, false); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->set_drywet(value, true, false); } qCritical("set_drywet(%i, %f) - could not find plugin", plugin_id, value); } -void set_vol(unsigned short plugin_id, double value) +void set_volume(unsigned short plugin_id, double value) { qDebug("set_vol(%i, %f)", plugin_id, value); for (unsigned short i=0; iid == plugin_id) - return plugin->set_vol(value, true, false); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->set_vol(value, true, false); } qCritical("set_vol(%i, %f) - could not find plugin", plugin_id, value); @@ -945,9 +890,9 @@ void set_balance_left(unsigned short plugin_id, double value) for (unsigned short i=0; iid == plugin_id) - return plugin->set_balance_left(value, true, false); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->set_balance_left(value, true, false); } qCritical("set_balance_left(%i, %f) - could not find plugin", plugin_id, value); @@ -959,9 +904,9 @@ void set_balance_right(unsigned short plugin_id, double value) for (unsigned short i=0; iid == plugin_id) - return plugin->set_balance_right(value, true, false); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->set_balance_right(value, true, false); } qCritical("set_balance_right(%i, %f) - could not find plugin", plugin_id, value); @@ -973,16 +918,16 @@ void set_parameter_value(unsigned short plugin_id, uint32_t parameter_id, double for (unsigned short i=0; iid == plugin_id) - { - if (parameter_id < plugin->param.count) - plugin->set_parameter_value(parameter_id, value, true, true, false); - else - qCritical("set_parameter_value(%i, %i, %f) - parameter_id out of bounds", plugin_id, parameter_id, value); - - return; - } +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// { +// if (parameter_id < plugin->param.count) +// plugin->set_parameter_value(parameter_id, value, true, true, false); +// else +// qCritical("set_parameter_value(%i, %i, %f) - parameter_id out of bounds", plugin_id, parameter_id, value); + +// return; +// } } qCritical("set_parameter_value(%i, %i, %f) - could not find plugin", plugin_id, parameter_id, value); @@ -1000,18 +945,18 @@ void set_parameter_midi_channel(unsigned short plugin_id, uint32_t parameter_id, for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) - { - plugin->param.data[parameter_id].midi_channel = channel; +// if (parameter_id < plugin->param.count) +// { +// plugin->param.data[parameter_id].midi_channel = channel; - if (plugin->hints & PLUGIN_IS_BRIDGE) - osc_send_set_parameter_midi_channel(&plugin->osc.data, plugin->id, parameter_id, channel); - } - else - qCritical("set_parameter_midi_channel(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, channel); +// if (plugin->hints & PLUGIN_IS_BRIDGE) +// osc_send_set_parameter_midi_channel(&plugin->osc.data, plugin->id, parameter_id, channel); +// } +// else +// qCritical("set_parameter_midi_channel(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, channel); return; } @@ -1036,18 +981,18 @@ void set_parameter_midi_cc(unsigned short plugin_id, uint32_t parameter_id, int1 for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (parameter_id < plugin->param.count) - { - plugin->param.data[parameter_id].midi_cc = midi_cc; +// if (parameter_id < plugin->param.count) +// { +// plugin->param.data[parameter_id].midi_cc = midi_cc; - if (plugin->hints & PLUGIN_IS_BRIDGE) - osc_send_set_parameter_midi_cc(&plugin->osc.data, plugin->id, parameter_id, midi_cc); - } - else - qCritical("set_parameter_midi_cc(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, midi_cc); +// if (plugin->hints & PLUGIN_IS_BRIDGE) +// osc_send_set_parameter_midi_cc(&plugin->osc.data, plugin->id, parameter_id, midi_cc); +// } +// else +// qCritical("set_parameter_midi_cc(%i, %i, %i) - parameter_id out of bounds", plugin_id, parameter_id, midi_cc); return; } @@ -1062,16 +1007,16 @@ void set_program(unsigned short plugin_id, uint32_t program_id) for (unsigned short i=0; iid == plugin_id) - { - if (program_id < plugin->prog.count) - plugin->set_program(program_id, true, true, false, true); - else - qCritical("set_program(%i, %i) - program_id out of bounds", plugin_id, program_id); - - return; - } +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// { +// if (program_id < plugin->prog.count) +// plugin->set_program(program_id, true, true, false, true); +// else +// qCritical("set_program(%i, %i) - program_id out of bounds", plugin_id, program_id); + +// return; +// } } qCritical("set_program(%i, %i) - could not find plugin", plugin_id, program_id); @@ -1083,33 +1028,33 @@ void set_midi_program(unsigned short plugin_id, uint32_t midi_program_id) for (unsigned short i=0; iid == plugin_id) - { - if (midi_program_id < plugin->midiprog.count) - plugin->set_midi_program(midi_program_id, true, true, false, true); - else - qCritical("set_midi_program(%i, %i) - program_id out of bounds", plugin_id, midi_program_id); - - return; - } +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// { +// if (midi_program_id < plugin->midiprog.count) +// plugin->set_midi_program(midi_program_id, true, true, false, true); +// else +// qCritical("set_midi_program(%i, %i) - program_id out of bounds", plugin_id, midi_program_id); + +// return; +// } } qCritical("set_midi_program(%i, %i) - could not find plugin", plugin_id, midi_program_id); } -void set_custom_data(unsigned short plugin_id, CustomDataType type, const char* key, const char* value) +void set_custom_data(unsigned short plugin_id, const char* type, const char* key, const char* value) { - qDebug("set_custom_data(%i, %i, %s, %s)", plugin_id, type, key, value); + qDebug("set_custom_data(%i, %s, %s, %s)", plugin_id, type, key, value); for (unsigned short i=0; iid == plugin_id) - return plugin->set_custom_data(type, key, value, true); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return plugin->set_custom_data(type, key, value, true); } - qCritical("set_custom_data(%i, %i, %s, %s) - could not find plugin", plugin_id, type, key, value); + qCritical("set_custom_data(%i, %s, %s, %s) - could not find plugin", plugin_id, type, key, value); } void set_chunk_data(unsigned short plugin_id, const char* chunk_data) @@ -1118,13 +1063,13 @@ void set_chunk_data(unsigned short plugin_id, const char* chunk_data) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - if (plugin->hints & PLUGIN_USES_CHUNKS) - plugin->set_chunk_data(chunk_data); - else - qCritical("set_chunk_data(%i, %s) - plugin does not support chunks", plugin_id, chunk_data); +// if (plugin->hints & PLUGIN_USES_CHUNKS) +// plugin->set_chunk_data(chunk_data); +// else +// qCritical("set_chunk_data(%i, %s) - plugin does not support chunks", plugin_id, chunk_data); return; } @@ -1139,16 +1084,16 @@ void set_gui_data(unsigned short plugin_id, int data, intptr_t gui_addr) for (unsigned short i=0; iid == plugin_id) - { - if (plugin->gui.type != GUI_NONE) - plugin->set_gui_data(data, get_pointer(gui_addr)); - else - qCritical("set_gui_data(%i, %i, " P_INTPTR ") - plugin has no UI", plugin_id, data, gui_addr); - - return; - } +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// { +// if (plugin->gui.type != GUI_NONE) +// plugin->set_gui_data(data, get_pointer(gui_addr)); +// else +// qCritical("set_gui_data(%i, %i, " P_INTPTR ") - plugin has no UI", plugin_id, data, gui_addr); + +// return; +// } } qCritical("set_gui_data(%i, %i, " P_INTPTR ") - could not find plugin", plugin_id, data, gui_addr); @@ -1156,19 +1101,19 @@ void set_gui_data(unsigned short plugin_id, int data, intptr_t gui_addr) void show_gui(unsigned short plugin_id, bool yesno) { - qDebug("show_gui(%i, %s)", plugin_id, bool2str(yesno)); +// qDebug("show_gui(%i, %s)", plugin_id, bool2str(yesno)); for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - plugin->show_gui(yesno); +// plugin->show_gui(yesno); return; } } - qCritical("show_gui(%i, %s) - could not find plugin", plugin_id, bool2str(yesno)); +// qCritical("show_gui(%i, %s) - could not find plugin", plugin_id, bool2str(yesno)); } void idle_gui(unsigned short plugin_id) @@ -1177,10 +1122,10 @@ void idle_gui(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) { - plugin->idle_gui(); +// plugin->idle_gui(); return; } } @@ -1190,16 +1135,16 @@ void idle_gui(unsigned short plugin_id) void send_midi_note(unsigned short plugin_id, bool onoff, uint8_t note, uint8_t velocity) { - qDebug("send_midi_note(%i, %s, %i, %i)", plugin_id, bool2str(onoff), note, velocity); +// qDebug("send_midi_note(%i, %s, %i, %i)", plugin_id, bool2str(onoff), note, velocity); for (unsigned short i=0; iid == plugin_id) - return send_plugin_midi_note(plugin_id, onoff, note, velocity, true, true, false); +// CarlaPlugin* plugin = CarlaPlugins[i]; +// if (plugin && plugin->id() == plugin_id) +// return send_plugin_midi_note(plugin_id, onoff, note, velocity, true, true, false); } - qCritical("send_midi_note(%i, %s, %i, %i) - could not find plugin", plugin_id, bool2str(onoff), note, velocity); +// qCritical("send_midi_note(%i, %s, %i, %i) - could not find plugin", plugin_id, bool2str(onoff), note, velocity); } void prepare_for_save(unsigned short plugin_id) @@ -1208,8 +1153,8 @@ void prepare_for_save(unsigned short plugin_id) for (unsigned short i=0; iid == plugin_id) + CarlaPlugin* plugin = CarlaPlugins[i]; + if (plugin && plugin->id() == plugin_id) return plugin->prepare_for_save(); } @@ -1226,7 +1171,7 @@ void set_option(OptionsType option, int value, const char* value_str) { qDebug("set_option(%i, %i, %s)", option, value, value_str); - if (carla_options._initiated) + if (carla_options.initiated) return; switch(option) @@ -1234,21 +1179,6 @@ void set_option(OptionsType option, int value, const char* value_str) case OPTION_GLOBAL_JACK_CLIENT: carla_options.global_jack_client = value; break; - case OPTION_BRIDGE_PATH_LV2_GTK2: - if (value_str) carla_options.bridge_path_lv2_gtk2 = strdup(value_str); - break; - case OPTION_BRIDGE_PATH_LV2_QT4: - if (value_str) carla_options.bridge_path_lv2_qt4 = strdup(value_str); - break; - case OPTION_BRIDGE_PATH_LV2_X11: - if (value_str) carla_options.bridge_path_lv2_x11 = strdup(value_str); - break; - case OPTION_BRIDGE_PATH_VST_QT4: - if (value_str) carla_options.bridge_path_vst_qt4 = strdup(value_str); - break; - case OPTION_BRIDGE_PATH_WINVST: - if (value_str) carla_options.bridge_path_winvst = strdup(value_str); - break; default: break; } @@ -1269,7 +1199,7 @@ const char* get_host_client_name() const char* get_host_osc_url() { qDebug("get_host_osc_url()"); - return global_osc_server_path; + return 0; //global_osc_server_path; } uint32_t get_buffer_size() @@ -1289,6 +1219,7 @@ double get_latency() qDebug("get_latency()"); return double(carla_buffer_size)/carla_sample_rate*1000; } + // End of exported symbols (API) // ------------------------------------------------------------------------------------------------------------------- @@ -1299,7 +1230,7 @@ short get_new_plugin_id() { for (unsigned short i=0; iosc.data, plugin_id, note, velo); - else - osc_send_note_off(&AudioPlugins[plugin_id]->osc.data, plugin_id, note, velo); - } + if (Callback) + Callback(action, plugin_id, value1, value2, value3); +} - if (callback_send) - callback_action(onoff ? CALLBACK_NOTE_ON : CALLBACK_NOTE_OFF, plugin_id, note, velo, 0.0); +void send_plugin_midi_note(unsigned short /*plugin_id*/, bool /*onoff*/, uint8_t /*note*/, uint8_t /*velo*/, bool /*gui_send*/, bool /*osc_send*/, bool /*callback_send*/) +{ +// carla_midi_lock(); +// for (unsigned int i=0; iosc.data, plugin_id, note, velo); +// else +// osc_send_note_off(&AudioPlugins[plugin_id]->osc.data, plugin_id, note, velo); +// } + +// if (callback_send) +// callback_action(onoff ? CALLBACK_NOTE_ON : CALLBACK_NOTE_OFF, plugin_id, note, velo, 0.0); } + // End of helper functions // ------------------------------------------------------------------------------------------------------------------- +#if 0 + +#include "misc.h" + +#include +#include +#include + +#include + +QMutex carla_midi_lock_var; +CarlaCheckThread check_thread; + +// Global OSC stuff +lo_server_thread global_osc_server_thread = nullptr; +const char* global_osc_server_path = nullptr; +OscData global_osc_data = { nullptr, nullptr, nullptr }; + #endif diff --git a/src/carla/carla_backend.h b/src/carla/carla_backend.h index 918cffc..3bb770e 100644 --- a/src/carla/carla_backend.h +++ b/src/carla/carla_backend.h @@ -210,6 +210,8 @@ typedef void (*CallbackFunc)(CallbackType action, unsigned short plugin_id, int // ----------------------------------------------------- // Exported symbols (API) +class CarlaPlugin; + CARLA_EXPORT bool carla_init(const char* client_name); CARLA_EXPORT bool carla_close(); CARLA_EXPORT bool carla_is_engine_running(); @@ -285,19 +287,26 @@ CARLA_EXPORT double get_latency(); // End of exported symbols // ----------------------------------------------------- -#if 0 // Helper functions short get_new_plugin_id(); const char* get_unique_name(const char* name); void* get_pointer(intptr_t ptr_addr); void set_last_error(const char* error); -void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3); void carla_proc_lock(); -bool carla_proc_trylock(); void carla_proc_unlock(); void carla_midi_lock(); void carla_midi_unlock(); +void callback_action(CallbackType action, unsigned short plugin_id, int value1, int value2, double value3); void send_plugin_midi_note(unsigned short plugin_id, bool onoff, uint8_t note, uint8_t velo, bool gui_send, bool osc_send, bool callback_send); -#endif + +// Global variables (shared) +extern const char* unique_names[MAX_PLUGINS]; +extern CarlaPlugin* CarlaPlugins[MAX_PLUGINS]; + +extern volatile double ains_peak[MAX_PLUGINS*2]; +extern volatile double aouts_peak[MAX_PLUGINS*2]; + +// Global options +extern carla_options_t carla_options; #endif // CARLA_BACKEND_H diff --git a/src/carla/carla_plugin.h b/src/carla/carla_plugin.h new file mode 100644 index 0000000..a7adb27 --- /dev/null +++ b/src/carla/carla_plugin.h @@ -0,0 +1,366 @@ +/* + * JACK Backend code for Carla + * Copyright (C) 2011-2012 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef CARLA_PLUGIN_H +#define CARLA_PLUGIN_H + +#include "carla_backend.h" + +#include +#include + +#include +#include + +#define CARLA_PROCESS_CONTINUE_CHECK if (m_id != plugin_id) { return callback_action(CALLBACK_DEBUG, plugin_id, m_id, 0, 0.0f); } + +// Global JACK client +extern jack_client_t* carla_jack_client; + +struct PluginAudioData { + uint32_t count; + uint32_t* rindexes; + jack_port_t** ports; +}; + +struct PluginParameterData { + uint32_t count; + ParameterData* data; + ParameterRanges* ranges; + jack_port_t* port_cin; + jack_port_t* port_cout; +}; + +class CarlaPlugin +{ +public: + CarlaPlugin() + { + qDebug("CarlaPlugin::CarlaPlugin()"); + + m_type = PLUGIN_NONE; + m_id = -1; + m_hints = 0; + + m_active = false; + m_active_before = false; + + m_lib = nullptr; + m_name = nullptr; + m_filename = nullptr; + + x_drywet = 1.0; + x_vol = 1.0; + x_bal_left = -1.0; + x_bal_right = 1.0; + + jack_client = nullptr; + + ain.count = 0; + ain.ports = nullptr; + ain.rindexes = nullptr; + + aout.count = 0; + aout.ports = nullptr; + aout.rindexes = nullptr; + + param.count = 0; + param.data = nullptr; + param.ranges = nullptr; + param.port_cin = nullptr; + param.port_cout = nullptr; + } + + virtual ~CarlaPlugin() + { + qDebug("CarlaPlugin::~CarlaPlugin()"); + + lib_close(); + + if (m_name) + free((void*)m_name); + + if (m_filename) + free((void*)m_filename); + + if (jack_client && carla_options.global_jack_client == false) + jack_client_close(jack_client); + } + + PluginType type() + { + return m_type; + } + + short id() + { + return m_id; + } + + unsigned int hints() + { + return m_hints; + } + + const char* name() + { + return m_name; + } + + const char* filename() + { + return m_filename; + } + + uint32_t param_count() + { + return param.count; + } + + void set_id(short id) + { + m_id = id; + } + + void get_audio_port_count_info(PortCountInfo* info) + { + info->ins = ain.count; + info->outs = aout.count; + info->total = ain.count + aout.count; + } + + void get_midi_port_count_info(PortCountInfo* info) + { + info->ins = 0; //min.count; + info->outs = 0; //mout.count; + info->total = 0; //min.count + mout.count; + } + + void get_parameter_count_info(PortCountInfo* info) + { + info->ins = 0; + info->outs = 0; + info->total = param.count; + + for (uint32_t i=0; i < param.count; i++) + { + if (param.data[i].type == PARAMETER_INPUT) + info->ins += 1; + else if (param.data[i].type == PARAMETER_OUTPUT) + info->outs += 1; + } + } + + virtual PluginCategory category() = 0; + virtual long unique_id() = 0; + + virtual uint32_t param_scalepoint_count(uint32_t index) = 0; + virtual double param_scalepoint_value(uint32_t pindex, uint32_t index) = 0; + + virtual void get_label(char* buf_str) = 0; + virtual void get_maker(char* buf_str) = 0; + virtual void get_copyright(char* buf_str) = 0; + virtual void get_real_name(char* buf_str) = 0; + + virtual void get_parameter_name(uint32_t index, char* buf_str) = 0; + virtual void get_parameter_symbol(uint32_t index, char* buf_str) = 0; + virtual void get_parameter_label(uint32_t index, char* buf_str) = 0; + + virtual void get_parameter_scalepoint_label(uint32_t pindex, uint32_t index, char* buf_str) = 0; + +// virtual int set_osc_bridge_info(PluginOscBridgeInfoType, lo_arg**) = 0; + +// virtual int32_t get_chunk_data(void** data_ptr) = 0; + +// virtual void x_set_parameter_value(uint32_t parameter_id, double value, bool gui_send) = 0; +// virtual void x_set_program(uint32_t program_id, bool gui_send, bool block) = 0; +// virtual void x_set_midi_program(uint32_t midi_program_id, bool gui_send, bool block) = 0; +// virtual void x_set_custom_data(CustomDataType dtype, const char* key, const char* value, bool gui_send) = 0; + +// virtual void set_chunk_data(const char* string_data) = 0; +// virtual void set_gui_data(int data, void* ptr) = 0; + +// virtual void show_gui(bool yesno) = 0; +// virtual void idle_gui() = 0; + + virtual void reload() = 0; + virtual void reload_programs(bool init) = 0; + virtual void prepare_for_save() = 0; + + virtual void process(jack_nframes_t nframes) = 0; + virtual void buffer_size_changed(jack_nframes_t new_buffer_size) = 0; + + void remove_from_jack() + { + qDebug("CarlaPlugin::remove_from_jack()"); + + if (jack_client == nullptr) + return; + + uint32_t i; + + for (i=0; i < ain.count; i++) + jack_port_unregister(jack_client, ain.ports[i]); + + for (i=0; i < aout.count; i++) + jack_port_unregister(jack_client, aout.ports[i]); + + //for (i=0; i < min.count; i++) + // jack_port_unregister(jack_client, min.ports[i]); + + //for (i=0; i < mout.count; i++) + // jack_port_unregister(jack_client, mout.ports[i]); + + if (param.port_cin) + jack_port_unregister(jack_client, param.port_cin); + + if (param.port_cout) + jack_port_unregister(jack_client, param.port_cout); + + qDebug("CarlaPlugin::remove_from_jack() - end"); + } + + void delete_buffers() + { + qDebug("CarlaPlugin::delete_buffers()"); + + if (ain.count > 0) + { + delete[] ain.ports; + delete[] ain.rindexes; + } + + if (aout.count > 0) + { + delete[] aout.ports; + delete[] aout.rindexes; + } + + //if (min.count > 0) + //{ + // delete[] min.ports; + //} + + //if (mout.count > 0) + //{ + // delete[] mout.ports; + //} + + if (param.count > 0) + { + delete[] param.data; + delete[] param.ranges; + } + + ain.count = 0; + ain.ports = nullptr; + ain.rindexes = nullptr; + + aout.count = 0; + aout.ports = nullptr; + aout.rindexes = nullptr; + + //min.count = 0; + //min.ports = nullptr; + + //mout.count = 0; + //mout.ports = nullptr; + + param.count = 0; + param.data = nullptr; + param.ranges = nullptr; + param.port_cin = nullptr; + param.port_cout = nullptr; + + qDebug("CarlaPlugin::delete_buffers() - end"); + } + + bool lib_open(const char* filename) + { +#ifdef Q_OS_WIN + m_lib = LoadLibraryA(filename); +#else + m_lib = dlopen(filename, RTLD_NOW); +#endif + return bool(m_lib); + } + + bool lib_close() + { + if (m_lib) +#ifdef Q_OS_WIN + return FreeLibrary((HMODULE)m_lib) != 0; +#else + return dlclose(m_lib) != 0; +#endif + else + return false; + } + + void* lib_symbol(const char* symbol) + { + if (m_lib) +#ifdef Q_OS_WIN + return (void*)GetProcAddress((HMODULE)m_lib, symbol); +#else + return dlsym(m_lib, symbol); +#endif + else + return nullptr; + } + + const char* lib_error() + { +#ifdef Q_OS_WIN + static char libError[2048]; + memset(libError, 0, sizeof(char)*2048); + + LPVOID winErrorString; + DWORD winErrorCode = GetLastError(); + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, winErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&winErrorString, 0, nullptr); + + snprintf(libError, 2048, "%s: error code %li: %s", m_filename, winErrorCode, (const char*)winErrorString); + LocalFree(winErrorString); + + return libError; +#else + return dlerror(); +#endif + } + +protected: + PluginType m_type; + short m_id; + unsigned int m_hints; + + bool m_active; + bool m_active_before; + + void* m_lib; + const char* m_name; + const char* m_filename; + + double x_drywet, x_vol, x_bal_left, x_bal_right; + jack_client_t* jack_client; + + // Storage Data + PluginAudioData ain; + PluginAudioData aout; + PluginParameterData param; +}; + +#endif // CARLA_PLUGIN_H diff --git a/src/carla/jack.cpp b/src/carla/jack.cpp new file mode 100644 index 0000000..0049bd4 --- /dev/null +++ b/src/carla/jack.cpp @@ -0,0 +1,92 @@ +/* + * JACK Backend code for Carla + * Copyright (C) 2011-2012 Filipe Coelho + * + * 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 COPYING file + */ + +#include "carla_plugin.h" + +// Global JACK client +extern jack_client_t* carla_jack_client; +extern jack_nframes_t carla_buffer_size; +extern jack_nframes_t carla_sample_rate; + +int carla_jack_process_callback(jack_nframes_t nframes, void* arg) +{ + if (carla_options.global_jack_client) + { + for (unsigned short i=0; iid() >= 0) + { + carla_proc_lock(); + plugin->process(nframes); + carla_proc_unlock(); + } + } + } + else if (arg) + { + CarlaPlugin* plugin = (CarlaPlugin*)arg; + if (plugin->id() >= 0) + { + carla_proc_lock(); + plugin->process(nframes); + carla_proc_unlock(); + } + } + + return 0; +} + +int carla_jack_bufsize_callback(jack_nframes_t new_buffer_size, void*) +{ + carla_buffer_size = new_buffer_size; + + for (unsigned short i=0; iid() >= 0) + plugin->buffer_size_changed(new_buffer_size); + } + + return 0; +} + +int carla_jack_srate_callback(jack_nframes_t new_sample_rate, void*) +{ + carla_sample_rate = new_sample_rate; + return 0; +} + +void carla_jack_shutdown_callback(void*) +{ + for (unsigned short i=0; iid() == plugin_id) + // plugin->jack_client = nullptr; + } + carla_jack_client = nullptr; + callback_action(CALLBACK_QUIT, 0, 0, 0, 0.0f); +} + +//void carla_jack_register_plugin(CarlaPlugin* plugin) +//{ + //plugin->jack_client = jack_client_open(plugin->name, JackNullOption, 0); + + //if (plugin->jack_client) + // jack_set_process_callback(plugin->jack_client, carla_jack_process_callback, plugin); +//} diff --git a/src/carla/ladspa.cpp b/src/carla/ladspa.cpp new file mode 100644 index 0000000..033c54a --- /dev/null +++ b/src/carla/ladspa.cpp @@ -0,0 +1,968 @@ +/* + * JACK Backend code for Carla + * Copyright (C) 2011-2012 Filipe Coelho + * + * 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 COPYING file + */ + +#include "carla_plugin.h" + +#include "ladspa/ladspa.h" +#include "ladspa_rdf.h" + +bool is_port_good(int Type1, int Type2) +{ + if (LADSPA_IS_PORT_INPUT(Type1) && ! LADSPA_IS_PORT_INPUT(Type2)) + return false; + else if (LADSPA_IS_PORT_OUTPUT(Type1) && ! LADSPA_IS_PORT_OUTPUT(Type2)) + return false; + else if (LADSPA_IS_PORT_CONTROL(Type1) && ! LADSPA_IS_PORT_CONTROL(Type2)) + return false; + else if (LADSPA_IS_PORT_AUDIO(Type1) && ! LADSPA_IS_PORT_AUDIO(Type2)) + return false; + else + return true; +} + +bool is_ladspa_rdf_descriptor_valid(const LADSPA_RDF_Descriptor* rdf_descriptor, const LADSPA_Descriptor* descriptor) +{ + if (rdf_descriptor) + { + if (rdf_descriptor->PortCount <= descriptor->PortCount) + { + for (unsigned long i=0; i < rdf_descriptor->PortCount; i++) + { + if (is_port_good(rdf_descriptor->Ports[i].Type, descriptor->PortDescriptors[i]) == false) + { + qWarning("WARNING - Plugin has RDF data, but invalid PortTypes - %i != %i", rdf_descriptor->Ports[i].Type, descriptor->PortDescriptors[i]); + return false; + } + } + return true; + } + else + { + qWarning("WARNING - Plugin has RDF data, but invalid PortCount -> %li > %li", rdf_descriptor->PortCount, descriptor->PortCount); + return false; + } + } + else + // No RDF Descriptor + return false; +} + +class LadspaPlugin : public CarlaPlugin +{ +public: + LadspaPlugin() : + CarlaPlugin() + { + qDebug("LadspaPlugin::LadspaPlugin()"); + m_type = PLUGIN_LADSPA; + + handle = nullptr; + descriptor = nullptr; + rdf_descriptor = nullptr; + } + + virtual ~LadspaPlugin() + { + qDebug("LadspaPlugin::~LadspaPlugin()"); + + if (handle && descriptor->deactivate && m_active_before) + descriptor->deactivate(handle); + + if (handle && descriptor->cleanup) + descriptor->cleanup(handle); + + if (rdf_descriptor) + ladspa_rdf_free(rdf_descriptor); + + handle = nullptr; + descriptor = nullptr; + rdf_descriptor = nullptr; + } + + virtual PluginCategory category() + { + if (rdf_descriptor) + { + LADSPA_Properties Category = rdf_descriptor->Type; + + // Specific Types + if (Category & (LADSPA_CLASS_DELAY|LADSPA_CLASS_REVERB)) + return PLUGIN_CATEGORY_DELAY; + else if (Category & (LADSPA_CLASS_PHASER|LADSPA_CLASS_FLANGER|LADSPA_CLASS_CHORUS)) + return PLUGIN_CATEGORY_MODULATOR; + else if (Category & (LADSPA_CLASS_AMPLIFIER)) + return PLUGIN_CATEGORY_DYNAMICS; + else if (Category & (LADSPA_CLASS_UTILITY|LADSPA_CLASS_SPECTRAL|LADSPA_CLASS_FREQUENCY_METER)) + return PLUGIN_CATEGORY_UTILITY; + + // Pre-set LADSPA Types + else if (LADSPA_IS_PLUGIN_DYNAMICS(Category)) + return PLUGIN_CATEGORY_DYNAMICS; + else if (LADSPA_IS_PLUGIN_AMPLITUDE(Category)) + return PLUGIN_CATEGORY_MODULATOR; + else if (LADSPA_IS_PLUGIN_EQ(Category)) + return PLUGIN_CATEGORY_EQ; + else if (LADSPA_IS_PLUGIN_FILTER(Category)) + return PLUGIN_CATEGORY_FILTER; + else if (LADSPA_IS_PLUGIN_FREQUENCY(Category)) + return PLUGIN_CATEGORY_UTILITY; + else if (LADSPA_IS_PLUGIN_SIMULATOR(Category)) + return PLUGIN_CATEGORY_OUTRO; + else if (LADSPA_IS_PLUGIN_TIME(Category)) + return PLUGIN_CATEGORY_DELAY; + else if (LADSPA_IS_PLUGIN_GENERATOR(Category)) + return PLUGIN_CATEGORY_SYNTH; + } + + return PLUGIN_CATEGORY_NONE; + } + + virtual long unique_id() + { + return descriptor->UniqueID; + } + + virtual uint32_t param_scalepoint_count(uint32_t index) + { + int32_t rindex = param.data[index].rindex; + + bool HasPortRDF = (rdf_descriptor && rindex < (int32_t)rdf_descriptor->PortCount); + if (HasPortRDF) + return rdf_descriptor->Ports[rindex].ScalePointCount; + else + return 0; + } + + virtual double param_scalepoint_value(uint32_t pindex, uint32_t index) + { + int32_t prindex = param.data[pindex].rindex; + + bool HasPortRDF = (rdf_descriptor && prindex < (int32_t)rdf_descriptor->PortCount); + if (HasPortRDF) + return rdf_descriptor->Ports[prindex].ScalePoints[index].Value; + else + return 0.0; + } + + virtual void get_label(char* buf_str) + { + strncpy(buf_str, descriptor->Label, STR_MAX); + } + + virtual void get_maker(char* buf_str) + { + strncpy(buf_str, descriptor->Maker, STR_MAX); + } + + virtual void get_copyright(char* buf_str) + { + strncpy(buf_str, descriptor->Copyright, STR_MAX); + } + + virtual void get_real_name(char* buf_str) + { + if (rdf_descriptor && rdf_descriptor->Title) + strncpy(buf_str, rdf_descriptor->Title, STR_MAX); + else + strncpy(buf_str, descriptor->Name, STR_MAX); + } + + virtual void get_parameter_name(uint32_t index, char* buf_str) + { + int32_t rindex = param.data[index].rindex; + strncpy(buf_str, descriptor->PortNames[rindex], STR_MAX); + } + + virtual void get_parameter_symbol(uint32_t index, char* buf_str) + { + int32_t rindex = param.data[index].rindex; + + bool HasPortRDF = (rdf_descriptor && rindex < (int32_t)rdf_descriptor->PortCount); + if (HasPortRDF) + { + LADSPA_RDF_Port Port = rdf_descriptor->Ports[rindex]; + if (LADSPA_PORT_HAS_LABEL(Port.Hints)) + { + strncpy(buf_str, Port.Label, STR_MAX); + return; + } + } + *buf_str = 0; + } + + virtual void get_parameter_label(uint32_t index, char* buf_str) + { + int32_t rindex = param.data[index].rindex; + + bool HasPortRDF = (rdf_descriptor && rindex < (int32_t)rdf_descriptor->PortCount); + if (HasPortRDF) + { + LADSPA_RDF_Port Port = rdf_descriptor->Ports[rindex]; + if (LADSPA_PORT_HAS_UNIT(Port.Hints)) + { + switch (Port.Unit) + { + case LADSPA_UNIT_DB: + strncpy(buf_str, "dB", STR_MAX); + return; + case LADSPA_UNIT_COEF: + strncpy(buf_str, "(coef)", STR_MAX); + return; + case LADSPA_UNIT_HZ: + strncpy(buf_str, "Hz", STR_MAX); + return; + case LADSPA_UNIT_S: + strncpy(buf_str, "s", STR_MAX); + return; + case LADSPA_UNIT_MS: + strncpy(buf_str, "ms", STR_MAX); + return; + case LADSPA_UNIT_MIN: + strncpy(buf_str, "min", STR_MAX); + return; + } + } + } + *buf_str = 0; + } + + virtual void get_parameter_scalepoint_label(uint32_t pindex, uint32_t index, char* buf_str) + { + int32_t prindex = param.data[pindex].rindex; + + bool HasPortRDF = (rdf_descriptor && prindex < (int32_t)rdf_descriptor->PortCount); + if (HasPortRDF) + strncpy(buf_str, rdf_descriptor->Ports[prindex].ScalePoints[index].Label, STR_MAX); + else + *buf_str = 0; + } + + virtual void reload() + { + qDebug("LadspaPlugin::reload()"); + short _id = m_id; + + // Safely disable plugin for reload + carla_proc_lock(); + m_id = -1; + carla_proc_unlock(); + + if (carla_options.global_jack_client == false && _id >= 0) + jack_deactivate(jack_client); + + // Unregister previous jack ports + remove_from_jack(); + + // Delete old data + delete_buffers(); + + uint32_t ains, aouts, params, j; + ains = aouts = params = 0; + + const unsigned long PortCount = descriptor->PortCount; + + for (unsigned long i=0; iPortDescriptors[i]; + if (LADSPA_IS_PORT_AUDIO(PortType)) + { + if (LADSPA_IS_PORT_INPUT(PortType)) + ains += 1; + else if (LADSPA_IS_PORT_OUTPUT(PortType)) + aouts += 1; + } + else if (LADSPA_IS_PORT_CONTROL(PortType)) + params += 1; + } + + if (ains > 0) + { + ain.rindexes = new uint32_t[ains]; + ain.ports = new jack_port_t*[ains]; + } + + if (aouts > 0) + { + aout.rindexes = new uint32_t[aouts]; + aout.ports = new jack_port_t*[aouts]; + } + + if (params > 0) + { + param.data = new ParameterData[params]; + param.ranges = new ParameterRanges[params]; + param_buffers = new float[params]; + } + + const int port_name_size = jack_port_name_size(); + char port_name[port_name_size]; + bool needs_cin = false; + bool needs_cout = false; + + for (unsigned long i=0; iPortDescriptors[i]; + LADSPA_PortRangeHint PortHint = descriptor->PortRangeHints[i]; + bool HasPortRDF = (rdf_descriptor && i < rdf_descriptor->PortCount); + + if (LADSPA_IS_PORT_AUDIO(PortType)) + { + if (carla_options.global_jack_client) + { + strcpy(port_name, m_name); + strcat(port_name, ":"); + strncat(port_name, descriptor->PortNames[i], port_name_size/2); + } + else + strncpy(port_name, descriptor->PortNames[i], port_name_size/2); + + if (LADSPA_IS_PORT_INPUT(PortType)) + { + j = ain.count++; + ain.ports[j] = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + ain.rindexes[j] = i; + } + else if (LADSPA_IS_PORT_OUTPUT(PortType)) + { + j = aout.count++; + aout.ports[j] = jack_port_register(jack_client, port_name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + aout.rindexes[j] = i; + needs_cin = true; + } + else + qWarning("WARNING - Got a broken Port (Audio, but not input or output)"); + } + else if (LADSPA_IS_PORT_CONTROL(PortType)) + { + j = param.count++; + param.data[j].index = j; + param.data[j].rindex = i; + param.data[j].hints = 0; + param.data[j].midi_channel = 0; + param.data[j].midi_cc = -1; + + double min, max, def, step, step_small, step_large; + + // min value + if (LADSPA_IS_HINT_BOUNDED_BELOW(PortHint.HintDescriptor)) + min = PortHint.LowerBound; + else + min = 0.0; + + // max value + if (LADSPA_IS_HINT_BOUNDED_ABOVE(PortHint.HintDescriptor)) + max = PortHint.UpperBound; + else + max = 1.0; + + if (min > max) + max = min; + else if (max < min) + min = max; + + // default value + if (HasPortRDF && LADSPA_PORT_HAS_DEFAULT(rdf_descriptor->Ports[j].Hints)) + def = rdf_descriptor->Ports[j].Default; + + else if (LADSPA_IS_HINT_HAS_DEFAULT(PortHint.HintDescriptor)) + { + switch (PortHint.HintDescriptor & LADSPA_HINT_DEFAULT_MASK) + { + case LADSPA_HINT_DEFAULT_MINIMUM: + def = min; + break; + case LADSPA_HINT_DEFAULT_MAXIMUM: + def = max; + break; + case LADSPA_HINT_DEFAULT_0: + def = 0.0; + break; + case LADSPA_HINT_DEFAULT_1: + def = 1.0; + break; + case LADSPA_HINT_DEFAULT_100: + def = 100.0; + break; + case LADSPA_HINT_DEFAULT_440: + def = 440.0; + break; + case LADSPA_HINT_DEFAULT_LOW: + if (LADSPA_IS_HINT_LOGARITHMIC(PortHint.HintDescriptor)) + def = exp((log(min)*0.75) + (log(max)*0.25)); + else + def = (min*0.75) + (max*0.25); + break; + case LADSPA_HINT_DEFAULT_MIDDLE: + if (LADSPA_IS_HINT_LOGARITHMIC(PortHint.HintDescriptor)) + def = sqrt(min*max); + else + def = (min+max)/2; + break; + case LADSPA_HINT_DEFAULT_HIGH: + if (LADSPA_IS_HINT_LOGARITHMIC(PortHint.HintDescriptor)) + def = exp((log(min)*0.25) + (log(max)*0.75)); + else + def = (min*0.25) + (max*0.75); + break; + default: + if (min < 0.0 && max > 0.0) + def = 0.0; + else + def = min; + break; + } + } + else + { + // no default value + if (min < 0.0 && max > 0.0) + def = 0.0; + else + def = min; + } + + if (def < min) + def = min; + else if (def > max) + def = max; + + if (max - min <= 0.0) + { + qWarning("Broken plugin parameter -> max - min <= 0"); + max = min + 0.1; + } + + if (LADSPA_IS_HINT_SAMPLE_RATE(PortHint.HintDescriptor)) + { + double sample_rate = get_sample_rate(); + min *= sample_rate; + max *= sample_rate; + def *= sample_rate; + param.data[j].hints |= PARAMETER_USES_SAMPLERATE; + } + + if (LADSPA_IS_HINT_INTEGER(PortHint.HintDescriptor)) + { + step = 1.0; + step_small = 1.0; + step_large = 10.0; + } + else if (LADSPA_IS_HINT_TOGGLED(PortHint.HintDescriptor)) + { + step = max - min; + step_small = step; + step_large = step; + } + else + { + double range = max - min; + step = range/100.0; + step_small = range/1000.0; + step_large = range/10.0; + } + + if (LADSPA_IS_PORT_INPUT(PortType)) + { + param.data[j].type = PARAMETER_INPUT; + param.data[j].hints |= PARAMETER_IS_ENABLED; + param.data[j].hints |= PARAMETER_IS_AUTOMABLE; + needs_cin = true; + } + else if (LADSPA_IS_PORT_OUTPUT(PortType)) + { + param.data[j].type = PARAMETER_OUTPUT; + param.data[j].hints |= PARAMETER_IS_ENABLED; + + if (strcmp(descriptor->PortNames[i], "latency") != 0 && strcmp(descriptor->PortNames[i], "_latency") != 0) + { + param.data[j].hints |= PARAMETER_IS_AUTOMABLE; + needs_cout = true; + } + else + { + // latency parameter + min = 0; + max = get_sample_rate(); + def = 0; + step = 1; + step_small = 1; + step_large = 1; + } + } + else + { + param.data[j].type = PARAMETER_UNKNOWN; + qWarning("WARNING - Got a broken Port (Control, but not input or output)"); + } + + // check for scalepoints, require at least 2 to make it useful + if (HasPortRDF && rdf_descriptor->Ports[i].ScalePointCount > 1) + param.data[j].hints |= PARAMETER_USES_SCALEPOINTS; + + param.ranges[j].min = min; + param.ranges[j].max = max; + param.ranges[j].def = def; + param.ranges[j].step = step; + param.ranges[j].step_small = step_small; + param.ranges[j].step_large = step_large; + + // Start parameters in their default values + param_buffers[j] = def; + + descriptor->connect_port(handle, i, ¶m_buffers[j]); + } + else + { + // Not Audio or Control + qCritical("ERROR - Got a broken Port (neither Audio or Control)"); + descriptor->connect_port(handle, i, nullptr); + } + } + + if (needs_cin) + { + if (carla_options.global_jack_client) + { + strcpy(port_name, m_name); + strcat(port_name, ":control-in"); + } + else + strcpy(port_name, "control-in"); + + param.port_cin = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); + } + + if (needs_cout) + { + if (carla_options.global_jack_client) + { + strcpy(port_name, m_name); + strcat(port_name, ":control-out"); + } + else + strcpy(port_name, "control-out"); + + param.port_cout = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0); + } + + ain.count = ains; + aout.count = aouts; + param.count = params; + + // plugin checks + m_hints = 0; + + if (aouts > 0 && (ains == aouts || ains == 1)) + m_hints |= PLUGIN_CAN_DRYWET; + + if (aouts > 0) + m_hints |= PLUGIN_CAN_VOL; + + if (aouts >= 2 && aouts%2 == 0) + m_hints |= PLUGIN_CAN_BALANCE; + + carla_proc_lock(); + m_id = _id; + carla_proc_unlock(); + + if (carla_options.global_jack_client == false) + jack_activate(jack_client); + } + + virtual void reload_programs(bool) + { + } + + virtual void prepare_for_save() + { + } + + virtual void process(jack_nframes_t nframes) + { + uint32_t i, k; + unsigned short plugin_id = m_id; + + double ains_peak_tmp[2] = { 0.0 }; + double aouts_peak_tmp[2] = { 0.0 }; + + jack_default_audio_sample_t* ains_buffer[ain.count]; + jack_default_audio_sample_t* aouts_buffer[aout.count]; + + for (i=0; i < ain.count; i++) + ains_buffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(ain.ports[i], nframes); + + for (i=0; i < aout.count; i++) + aouts_buffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(aout.ports[i], nframes); + + // -------------------------------------------------------------------------------------------------------- + // Input VU + + if (ain.count > 0) + { + short j2 = (ain.count == 1) ? 0 : 1; + + for (k=0; k ains_peak_tmp[0]) + ains_peak_tmp[0] = ains_buffer[0][k]; + if (ains_buffer[j2][k] > ains_peak_tmp[1]) + ains_peak_tmp[1] = ains_buffer[j2][k]; + } + } + + CARLA_PROCESS_CONTINUE_CHECK; + + // -------------------------------------------------------------------------------------------------------- + // Parameters Input [Automation] + + if (param.port_cin) + { + jack_default_audio_sample_t* pin_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cin, nframes); + + jack_midi_event_t pin_event; + uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer); + + for (i=0; i 0) + { + // Dry/Wet (using '0x09', undefined) + //set_drywet(velo_per, false, false); + //postpone_event(PostEventParameter, PARAMETER_DRYWET, velo_per); + } + else if (status == 0x07 && (m_hints & PLUGIN_CAN_VOL) > 0) + { + // Volume + //value = double(velo)/100; + //set_vol(value, false, false); + //postpone_event(PostEventParameter, PARAMETER_VOLUME, value); + } + else if (status == 0x08 && (m_hints & PLUGIN_CAN_BALANCE) > 0) + { + // Balance +// double left, right; +// value = (double(velo)-63.5)/63.5; + +// if (value < 0) +// { +// left = -1.0; +// right = (value*2)+1.0; +// } +// else if (value > 0) +// { +// left = (value*2)-1.0; +// right = 1.0; +// } +// else +// { +// left = -1.0; +// right = 1.0; +// } + + //set_balance_left(left, false, false); + //set_balance_right(right, false, false); + //postpone_event(PostEventParameter, PARAMETER_BALANCE_LEFT, left); + //postpone_event(PostEventParameter, PARAMETER_BALANCE_RIGHT, right); + } + } + + // Control plugin parameters + for (k=0; k < param.count; k++) + { + if (param.data[k].type == PARAMETER_INPUT && (param.data[k].hints & PARAMETER_IS_AUTOMABLE) > 0 && + param.data[k].midi_channel == channel && param.data[k].midi_cc == status) + { + //value = (velo_per * (param.ranges[k].max - param.ranges[k].min)) + param.ranges[k].min; + //set_parameter_value(k, value, false, false, false); + //postpone_event(PostEventParameter, k, value); + } + } + } + } + } // End of Parameters Input + + CARLA_PROCESS_CONTINUE_CHECK; + + // -------------------------------------------------------------------------------------------------------- + // Plugin processing + + if (m_active) + { + if (m_active_before == false) + { + if (descriptor->activate) + descriptor->activate(handle); + } + + for (i=0; i < ain.count; i++) + descriptor->connect_port(handle, ain.rindexes[i], ains_buffer[i]); + + for (i=0; i < aout.count; i++) + descriptor->connect_port(handle, aout.rindexes[i], aouts_buffer[i]); + + if (descriptor->run) + descriptor->run(handle, nframes); + } + else + { + if (m_active_before) + { + if (descriptor->deactivate) + descriptor->deactivate(handle); + } + } + + CARLA_PROCESS_CONTINUE_CHECK; + + // -------------------------------------------------------------------------------------------------------- + // Post-processing (dry/wet, volume and balance) + + if (m_active) + { + double bal_rangeL, bal_rangeR; + jack_default_audio_sample_t old_bal_left[nframes]; + + for (i=0; i < aout.count; i++) + { + // Dry/Wet and Volume + for (k=0; k 0 && x_drywet != 1.0) + { + if (aout.count == 1) + aouts_buffer[i][k] = (aouts_buffer[i][k]*x_drywet)+(ains_buffer[0][k]*(1.0-x_drywet)); + else + aouts_buffer[i][k] = (aouts_buffer[i][k]*x_drywet)+(ains_buffer[i][k]*(1.0-x_drywet)); + } + + if (m_hints & PLUGIN_CAN_VOL) + aouts_buffer[i][k] *= x_vol; + } + + // Balance + if (m_hints & PLUGIN_CAN_BALANCE) + { + if (i%2 == 0) + memcpy(&old_bal_left, aouts_buffer[i], sizeof(jack_default_audio_sample_t)*nframes); + + bal_rangeL = (x_bal_left+1.0)/2; + bal_rangeR = (x_bal_right+1.0)/2; + + for (k=0; k aouts_peak_tmp[i]) + aouts_peak_tmp[i] = aouts_buffer[i][k]; + } + } + } + } + else + { + // disable any output sound if not active + for (i=0; i < aout.count; i++) + memset(aouts_buffer[i], 0.0f, sizeof(jack_default_audio_sample_t)*nframes); + + aouts_peak_tmp[0] = 0.0; + aouts_peak_tmp[1] = 0.0; + + } // End of Post-processing + + CARLA_PROCESS_CONTINUE_CHECK; + + // -------------------------------------------------------------------------------------------------------- + // Control Output + + if (param.port_cout) + { + jack_default_audio_sample_t* cout_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cout, nframes); + jack_midi_clear_buffer(cout_buffer); + + double value_per; + + for (k=0; k < param.count; k++) + { + if (param.data[k].type == PARAMETER_OUTPUT && param.data[k].midi_cc >= 0) + { + value_per = (param_buffers[k] - param.ranges[k].min)/(param.ranges[k].max - param.ranges[k].min); + + jack_midi_data_t* event_buffer = jack_midi_event_reserve(cout_buffer, 0, 3); + event_buffer[0] = 0xB0 + param.data[k].midi_channel; + event_buffer[1] = param.data[k].midi_cc; + event_buffer[2] = 127*value_per; + } + } + } // End of Control Output + + CARLA_PROCESS_CONTINUE_CHECK; + + // -------------------------------------------------------------------------------------------------------- + // Peak Values + + ains_peak[(plugin_id*2)+0] = ains_peak_tmp[0]; + ains_peak[(plugin_id*2)+1] = ains_peak_tmp[1]; + aouts_peak[(plugin_id*2)+0] = aouts_peak_tmp[0]; + aouts_peak[(plugin_id*2)+1] = aouts_peak_tmp[1]; + + m_active_before = m_active; + } + + virtual void buffer_size_changed(jack_nframes_t) + { + } + + bool init(const char* filename, const char* label, void* extra_stuff) + { + if (lib_open(filename)) + { + LADSPA_Descriptor_Function descfn = (LADSPA_Descriptor_Function)lib_symbol("ladspa_descriptor"); + + if (descfn) + { + unsigned long i = 0; + while ((descriptor = descfn(i++))) + { + if (strcmp(descriptor->Label, label) == 0) + break; + } + + if (descriptor) + { + handle = descriptor->instantiate(descriptor, get_sample_rate()); + + if (handle) + { + m_filename = strdup(filename); + + const LADSPA_RDF_Descriptor* rdf_descriptor_ = (LADSPA_RDF_Descriptor*)extra_stuff; + + if (is_ladspa_rdf_descriptor_valid(rdf_descriptor_, descriptor)) + rdf_descriptor = ladspa_rdf_dup(rdf_descriptor_); + + if (rdf_descriptor && rdf_descriptor->Title) + m_name = get_unique_name(rdf_descriptor->Title); + else + m_name = get_unique_name(descriptor->Name); + + //if (carla_options.global_jack_client) + jack_client = carla_jack_client; + //else + // carla_jack_register_plugin(plugin); + + if (jack_client) + { + return true; + } + else + set_last_error("Failed to register plugin in JACK"); + } + else + set_last_error("Plugin failed to initialize"); + } + else + set_last_error("Could not find the requested plugin Label in the plugin library"); + } + else + set_last_error("Could not find the LASDPA Descriptor in the plugin library"); + } + else + set_last_error(lib_error()); + + return false; + } + +private: + LADSPA_Handle handle; + const LADSPA_Descriptor* descriptor; + const LADSPA_RDF_Descriptor* rdf_descriptor; + + float* param_buffers; +}; + +short add_plugin_ladspa(const char* filename, const char* label, void* extra_stuff) +{ + qDebug("add_plugin_ladspa(%s, %s, %p)", filename, label, extra_stuff); + + short id = get_new_plugin_id(); + + if (id >= 0) + { + LadspaPlugin* plugin = new LadspaPlugin; + + if (plugin->init(filename, label, extra_stuff)) + { + plugin->reload(); + plugin->set_id(id); + + unique_names[id] = plugin->name(); + CarlaPlugins[id] = plugin; + + //osc_new_plugin(plugin); + } + else + { + delete plugin; + id = -1; + } + } + else + set_last_error("Maximum number of plugins reached"); + + return id; +} diff --git a/src/carla/ladspa_rdf.h b/src/carla/ladspa_rdf.h new file mode 100644 index 0000000..ed42635 --- /dev/null +++ b/src/carla/ladspa_rdf.h @@ -0,0 +1,224 @@ +/* + * Custom types to store LADSPA RDF information + * Copyright (C) 2011-2012 Filipe Coelho + * + * 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 COPYING file + */ + +#ifndef LADSPA_RDF_INCLUDED +#define LADSPA_RDF_INCLUDED + +// Base Types +typedef float LADSPA_Data; +typedef int LADSPA_Property; +typedef unsigned long long LADSPA_PluginType; + +// Unit Types +#define LADSPA_UNIT_DB 0x01 +#define LADSPA_UNIT_COEF 0x02 +#define LADSPA_UNIT_HZ 0x04 +#define LADSPA_UNIT_S 0x08 +#define LADSPA_UNIT_MS 0x10 +#define LADSPA_UNIT_MIN 0x20 + +#define LADSPA_UNIT_CLASS_AMPLITUDE (LADSPA_UNIT_DB|LADSPA_UNIT_COEF) +#define LADSPA_UNIT_CLASS_FREQUENCY (LADSPA_UNIT_HZ) +#define LADSPA_UNIT_CLASS_TIME (LADSPA_UNIT_S|LADSPA_UNIT_MS|LADSPA_UNIT_MIN) + +#define LADSPA_IS_UNIT_DB(x) ((x) == LADSPA_UNIT_DB) +#define LADSPA_IS_UNIT_COEF(x) ((x) == LADSPA_UNIT_COEF) +#define LADSPA_IS_UNIT_HZ(x) ((x) == LADSPA_UNIT_HZ) +#define LADSPA_IS_UNIT_S(x) ((x) == LADSPA_UNIT_S) +#define LADSPA_IS_UNIT_MS(x) ((x) == LADSPA_UNIT_MS) +#define LADSPA_IS_UNIT_MIN(x) ((x) == LADSPA_UNIT_MIN) + +#define LADSPA_IS_UNIT_CLASS_AMPLITUDE(x) ((x) & LADSPA_UNIT_CLASS_AMPLITUDE) +#define LADSPA_IS_UNIT_CLASS_FREQUENCY(x) ((x) & LADSPA_UNIT_CLASS_FREQUENCY) +#define LADSPA_IS_UNIT_CLASS_TIME(x) ((x) & LADSPA_UNIT_CLASS_TIME) + +// Port Types (Official API) +#define LADSPA_PORT_INPUT 0x1 +#define LADSPA_PORT_OUTPUT 0x2 +#define LADSPA_PORT_CONTROL 0x4 +#define LADSPA_PORT_AUDIO 0x8 + +// Port Hints +#define LADSPA_PORT_UNIT 0x1 +#define LADSPA_PORT_DEFAULT 0x2 +#define LADSPA_PORT_LABEL 0x4 + +#define LADSPA_PORT_HAS_UNIT(x) ((x) & LADSPA_PORT_UNIT) +#define LADSPA_PORT_HAS_DEFAULT(x) ((x) & LADSPA_PORT_DEFAULT) +#define LADSPA_PORT_HAS_LABEL(x) ((x) & LADSPA_PORT_LABEL) + +// Plugin Types +#define LADSPA_CLASS_UTILITY 0x000000001 +#define LADSPA_CLASS_GENERATOR 0x000000002 +#define LADSPA_CLASS_SIMULATOR 0x000000004 +#define LADSPA_CLASS_OSCILLATOR 0x000000008 +#define LADSPA_CLASS_TIME 0x000000010 +#define LADSPA_CLASS_DELAY 0x000000020 +#define LADSPA_CLASS_PHASER 0x000000040 +#define LADSPA_CLASS_FLANGER 0x000000080 +#define LADSPA_CLASS_CHORUS 0x000000100 +#define LADSPA_CLASS_REVERB 0x000000200 +#define LADSPA_CLASS_FREQUENCY 0x000000400 +#define LADSPA_CLASS_FREQUENCY_METER 0x000000800 +#define LADSPA_CLASS_FILTER 0x000001000 +#define LADSPA_CLASS_LOWPASS 0x000002000 +#define LADSPA_CLASS_HIGHPASS 0x000004000 +#define LADSPA_CLASS_BANDPASS 0x000008000 +#define LADSPA_CLASS_COMB 0x000010000 +#define LADSPA_CLASS_ALLPASS 0x000020000 +#define LADSPA_CLASS_EQ 0x000040000 +#define LADSPA_CLASS_PARAEQ 0x000080000 +#define LADSPA_CLASS_MULTIEQ 0x000100000 +#define LADSPA_CLASS_AMPLITUDE 0x000200000 +#define LADSPA_CLASS_PITCH 0x000400000 +#define LADSPA_CLASS_AMPLIFIER 0x000800000 +#define LADSPA_CLASS_WAVESHAPER 0x001000000 +#define LADSPA_CLASS_MODULATOR 0x002000000 +#define LADSPA_CLASS_DISTORTION 0x004000000 +#define LADSPA_CLASS_DYNAMICS 0x008000000 +#define LADSPA_CLASS_COMPRESSOR 0x010000000 +#define LADSPA_CLASS_EXPANDER 0x020000000 +#define LADSPA_CLASS_LIMITER 0x040000000 +#define LADSPA_CLASS_GATE 0x080000000 +#define LADSPA_CLASS_SPECTRAL 0x100000000LL +#define LADSPA_CLASS_NOTCH 0x200000000LL + +#define LADSPA_GROUP_DYNAMICS (LADSPA_CLASS_DYNAMICS|LADSPA_CLASS_COMPRESSOR|LADSPA_CLASS_EXPANDER|LADSPA_CLASS_LIMITER|LADSPA_CLASS_GATE) +#define LADSPA_GROUP_AMPLITUDE (LADSPA_CLASS_AMPLITUDE|LADSPA_CLASS_AMPLIFIER|LADSPA_CLASS_WAVESHAPER|LADSPA_CLASS_MODULATOR|LADSPA_CLASS_DISTORTION|LADSPA_GROUP_DYNAMICS) +#define LADSPA_GROUP_EQ (LADSPA_CLASS_EQ|LADSPA_CLASS_PARAEQ|LADSPA_CLASS_MULTIEQ) +#define LADSPA_GROUP_FILTER (LADSPA_CLASS_FILTER|LADSPA_CLASS_LOWPASS|LADSPA_CLASS_HIGHPASS|LADSPA_CLASS_BANDPASS|LADSPA_CLASS_COMB|LADSPA_CLASS_ALLPASS|LADSPA_CLASS_NOTCH) +#define LADSPA_GROUP_FREQUENCY (LADSPA_CLASS_FREQUENCY|LADSPA_CLASS_FREQUENCY_METER|LADSPA_GROUP_FILTER|LADSPA_GROUP_EQ|LADSPA_CLASS_PITCH) +#define LADSPA_GROUP_SIMULATOR (LADSPA_CLASS_SIMULATOR|LADSPA_CLASS_REVERB) +#define LADSPA_GROUP_TIME (LADSPA_CLASS_TIME|LADSPA_CLASS_DELAY|LADSPA_CLASS_PHASER|LADSPA_CLASS_FLANGER|LADSPA_CLASS_CHORUS|LADSPA_CLASS_REVERB) +#define LADSPA_GROUP_GENERATOR (LADSPA_CLASS_GENERATOR|LADSPA_CLASS_OSCILLATOR) + +#define LADSPA_IS_PLUGIN_DYNAMICS(x) ((x) & LADSPA_GROUP_DYNAMICS) +#define LADSPA_IS_PLUGIN_AMPLITUDE(x) ((x) & LADSPA_GROUP_AMPLITUDE) +#define LADSPA_IS_PLUGIN_EQ(x) ((x) & LADSPA_GROUP_EQ) +#define LADSPA_IS_PLUGIN_FILTER(x) ((x) & LADSPA_GROUP_FILTER) +#define LADSPA_IS_PLUGIN_FREQUENCY(x) ((x) & LADSPA_GROUP_FREQUENCY) +#define LADSPA_IS_PLUGIN_SIMULATOR(x) ((x) & LADSPA_GROUP_SIMULATOR) +#define LADSPA_IS_PLUGIN_TIME(x) ((x) & LADSPA_GROUP_TIME) +#define LADSPA_IS_PLUGIN_GENERATOR(x) ((x) & LADSPA_GROUP_GENERATOR) + +// A Scale Point +struct LADSPA_RDF_ScalePoint { + LADSPA_Data Value; + const char* Label; +}; + +// A Port +struct LADSPA_RDF_Port { + LADSPA_Property Type; + LADSPA_Property Hints; + const char* Label; + LADSPA_Data Default; + LADSPA_Property Unit; + + unsigned long ScalePointCount; + LADSPA_RDF_ScalePoint* ScalePoints; +}; + +// The actual plugin descriptor +struct LADSPA_RDF_Descriptor { + LADSPA_PluginType Type; + unsigned long UniqueID; + const char* Title; + const char* Creator; + + unsigned long PortCount; + LADSPA_RDF_Port* Ports; +}; + + +// Copy RDF object +inline const LADSPA_RDF_Descriptor* ladspa_rdf_dup(const LADSPA_RDF_Descriptor* rdf_descriptor) +{ + unsigned long i, j; + LADSPA_RDF_Descriptor* new_descriptor = new LADSPA_RDF_Descriptor; + + new_descriptor->Type = rdf_descriptor->Type; + new_descriptor->UniqueID = rdf_descriptor->UniqueID; + new_descriptor->PortCount = rdf_descriptor->PortCount; + + new_descriptor->Title = strdup(rdf_descriptor->Title); + new_descriptor->Creator = strdup(rdf_descriptor->Creator); + + if (new_descriptor->PortCount > 0) + { + new_descriptor->Ports = new LADSPA_RDF_Port[new_descriptor->PortCount]; + + for (i=0; i < new_descriptor->PortCount; i++) + { + LADSPA_RDF_Port* Port = &new_descriptor->Ports[i]; + Port->Type = rdf_descriptor->Ports[i].Type; + Port->Hints = rdf_descriptor->Ports[i].Hints; + Port->Default = rdf_descriptor->Ports[i].Default; + Port->Unit = rdf_descriptor->Ports[i].Unit; + Port->ScalePointCount = rdf_descriptor->Ports[i].ScalePointCount; + + Port->Label = strdup(rdf_descriptor->Ports[i].Label); + + if (Port->ScalePointCount > 0) + { + Port->ScalePoints = new LADSPA_RDF_ScalePoint[Port->ScalePointCount]; + + for (j=0; j < Port->ScalePointCount; j++) + { + Port->ScalePoints[j].Value = rdf_descriptor->Ports[i].ScalePoints[j].Value; + Port->ScalePoints[j].Label = strdup(rdf_descriptor->Ports[i].ScalePoints[j].Label); + } + } + else + Port->ScalePoints = nullptr; + } + } + else + new_descriptor->Ports = nullptr; + + return new_descriptor; +} + +// Delete copied object +inline void ladspa_rdf_free(const LADSPA_RDF_Descriptor* rdf_descriptor) +{ + unsigned long i, j; + + free((void*)rdf_descriptor->Title); + free((void*)rdf_descriptor->Creator); + + if (rdf_descriptor->PortCount > 0) + { + for (i=0; i < rdf_descriptor->PortCount; i++) + { + LADSPA_RDF_Port* Port = &rdf_descriptor->Ports[i]; + free((void*)Port->Label); + + if (Port->ScalePointCount > 0) + { + for (j=0; j < Port->ScalePointCount; j++) + free((void*)Port->ScalePoints[j].Label); + + delete[] Port->ScalePoints; + } + } + delete[] rdf_descriptor->Ports; + } + delete rdf_descriptor; +} + +#endif // LADSPA_RDF_INCLUDED diff --git a/src/carla_backend.py b/src/carla_backend.py index 61302d2..34fe60b 100644 --- a/src/carla_backend.py +++ b/src/carla_backend.py @@ -342,31 +342,31 @@ def findSoundFonts(PATH): #return bundles -#def findDSSIGUI(filename, name, label): - #gui_filename = "" - #plugin_dir = filename.rsplit(".", 1)[0] - #short_name = getShortFileName(filename).rsplit(".", 1)[0] - - #check_name = name.replace(" ","_") - #check_label = label - #check_sname = short_name - - #if (check_name[-1] != "_"): check_name += "_" - #if (check_label[-1] != "_"): check_label += "_" - #if (check_sname[-1] != "_"): check_sname += "_" - - #for root, dirs, files in os.walk(plugin_dir): - #plugin_files = files - #break - #else: - #plugin_files = [] +def findDSSIGUI(filename, name, label): + plugin_dir = filename.rsplit(".", 1)[0] + short_name = getShortFileName(plugin_dir) + gui_filename = "" + + check_name = name.replace(" ","_") + check_label = label + check_sname = short_name + + if (check_name[-1] != "_"): check_name += "_" + if (check_label[-1] != "_"): check_label += "_" + if (check_sname[-1] != "_"): check_sname += "_" + + for root, dirs, files in os.walk(plugin_dir): + gui_files = files + break + else: + gui_files = [] - #for i in range(len(plugin_files)): - #if (check_name in files[i] or check_label in files[i] or check_sname in files[i]): - #gui_filename = os.path.join(plugin_dir, files[i]) - #break + for gui in gui_files: + if (gui.startswith(check_name) or gui.startswith(check_label) or gui.startswith(check_sname)): + gui_filename = os.path.join(plugin_dir, gui) + break - #return gui_filename + return gui_filename # ------------------------------------------------------------------------------------------------ # Plugin Query @@ -477,10 +477,10 @@ def runCarlaDiscovery(itype, stype, filename, tool, isWine=False): if value.isdigit(): pinfo['build'] = int(value) # Additional checks - #for pinfo in plugins: - #if (itype == PLUGIN_DSSI): - #if (findDSSIGUI(pinfo['binary'], pinfo['name'], pinfo['label'])): - #pinfo['hints'] |= PLUGIN_HAS_GUI + for pinfo in plugins: + if (itype == PLUGIN_DSSI): + if (findDSSIGUI(pinfo['binary'], pinfo['name'], pinfo['label'])): + pinfo['hints'] |= PLUGIN_HAS_GUI return plugins @@ -767,190 +767,182 @@ class Host(object): self.lib = cdll.LoadLibrary(os.path.join("carla", libname)) - #self.lib.carla_init.argtypes = [c_char_p] - #self.lib.carla_init.restype = c_bool + self.lib.carla_init.argtypes = [c_char_p] + self.lib.carla_init.restype = c_bool - #self.lib.carla_close.argtypes = None - #self.lib.carla_close.restype = c_bool + self.lib.carla_close.argtypes = None + self.lib.carla_close.restype = c_bool - #self.lib.carla_is_engine_running.argtypes = None - #self.lib.carla_is_engine_running.restype = c_bool + self.lib.carla_is_engine_running.argtypes = None + self.lib.carla_is_engine_running.restype = c_bool - #self.lib.add_plugin.argtypes = [c_enum, c_enum, c_char_p, c_char_p, c_void_p] - #self.lib.add_plugin.restype = c_short + self.lib.add_plugin.argtypes = [c_enum, c_enum, c_char_p, c_char_p, c_void_p] + self.lib.add_plugin.restype = c_short - #self.lib.remove_plugin.argtypes = [c_ushort] - #self.lib.remove_plugin.restype = c_bool + self.lib.remove_plugin.argtypes = [c_ushort] + self.lib.remove_plugin.restype = c_bool - #self.lib.get_plugin_info.argtypes = [c_ushort] - #self.lib.get_plugin_info.restype = POINTER(PluginInfo) + self.lib.get_plugin_info.argtypes = [c_ushort] + self.lib.get_plugin_info.restype = POINTER(PluginInfo) - #self.lib.get_audio_port_count_info.argtypes = [c_ushort] - #self.lib.get_audio_port_count_info.restype = POINTER(PortCountInfo) + self.lib.get_audio_port_count_info.argtypes = [c_ushort] + self.lib.get_audio_port_count_info.restype = POINTER(PortCountInfo) - #self.lib.get_midi_port_count_info.argtypes = [c_ushort] - #self.lib.get_midi_port_count_info.restype = POINTER(PortCountInfo) + self.lib.get_midi_port_count_info.argtypes = [c_ushort] + self.lib.get_midi_port_count_info.restype = POINTER(PortCountInfo) - #self.lib.get_parameter_count_info.argtypes = [c_ushort] - #self.lib.get_parameter_count_info.restype = POINTER(PortCountInfo) + self.lib.get_parameter_count_info.argtypes = [c_ushort] + self.lib.get_parameter_count_info.restype = POINTER(PortCountInfo) - #self.lib.get_parameter_info.argtypes = [c_ushort, c_uint32] - #self.lib.get_parameter_info.restype = POINTER(ParameterInfo) + self.lib.get_parameter_info.argtypes = [c_ushort, c_uint32] + self.lib.get_parameter_info.restype = POINTER(ParameterInfo) - #self.lib.get_scalepoint_info.argtypes = [c_ushort, c_uint32, c_uint32] - #self.lib.get_scalepoint_info.restype = POINTER(ScalePointInfo) + self.lib.get_scalepoint_info.argtypes = [c_ushort, c_uint32, c_uint32] + self.lib.get_scalepoint_info.restype = POINTER(ScalePointInfo) - #self.lib.get_midi_program_info.argtypes = [c_ushort, c_uint32] - #self.lib.get_midi_program_info.restype = POINTER(MidiProgramInfo) + self.lib.get_midi_program_info.argtypes = [c_ushort, c_uint32] + self.lib.get_midi_program_info.restype = POINTER(MidiProgramInfo) - #self.lib.get_parameter_data.argtypes = [c_ushort, c_uint32] - #self.lib.get_parameter_data.restype = POINTER(ParameterData) + self.lib.get_parameter_data.argtypes = [c_ushort, c_uint32] + self.lib.get_parameter_data.restype = POINTER(ParameterData) - #self.lib.get_parameter_ranges.argtypes = [c_ushort, c_uint32] - #self.lib.get_parameter_ranges.restype = POINTER(ParameterRanges) + self.lib.get_parameter_ranges.argtypes = [c_ushort, c_uint32] + self.lib.get_parameter_ranges.restype = POINTER(ParameterRanges) - #self.lib.get_custom_data.argtypes = [c_ushort, c_uint32] - #self.lib.get_custom_data.restype = POINTER(CustomData) + self.lib.get_custom_data.argtypes = [c_ushort, c_uint32] + self.lib.get_custom_data.restype = POINTER(CustomData) - #self.lib.get_chunk_data.argtypes = [c_ushort] - #self.lib.get_chunk_data.restype = c_char_p + self.lib.get_chunk_data.argtypes = [c_ushort] + self.lib.get_chunk_data.restype = c_char_p - #self.lib.get_gui_data.argtypes = [c_ushort] - #self.lib.get_gui_data.restype = POINTER(GuiData) + self.lib.get_gui_data.argtypes = [c_ushort] + self.lib.get_gui_data.restype = POINTER(GuiData) - #self.lib.get_parameter_count.argtypes = [c_ushort] - #self.lib.get_parameter_count.restype = c_uint32 + self.lib.get_parameter_count.argtypes = [c_ushort] + self.lib.get_parameter_count.restype = c_uint32 - #self.lib.get_program_count.argtypes = [c_ushort] - #self.lib.get_program_count.restype = c_uint32 + self.lib.get_program_count.argtypes = [c_ushort] + self.lib.get_program_count.restype = c_uint32 - #self.lib.get_midi_program_count.argtypes = [c_ushort] - #self.lib.get_midi_program_count.restype = c_uint32 + self.lib.get_midi_program_count.argtypes = [c_ushort] + self.lib.get_midi_program_count.restype = c_uint32 - #self.lib.get_custom_data_count.argtypes = [c_ushort] - #self.lib.get_custom_data_count.restype = c_uint32 + self.lib.get_custom_data_count.argtypes = [c_ushort] + self.lib.get_custom_data_count.restype = c_uint32 - #self.lib.get_program_name.argtypes = [c_ushort, c_uint32] - #self.lib.get_program_name.restype = c_char_p + self.lib.get_program_name.argtypes = [c_ushort, c_uint32] + self.lib.get_program_name.restype = c_char_p - #self.lib.get_midi_program_name.argtypes = [c_ushort, c_uint32] - #self.lib.get_midi_program_name.restype = c_char_p + self.lib.get_midi_program_name.argtypes = [c_ushort, c_uint32] + self.lib.get_midi_program_name.restype = c_char_p - #self.lib.get_real_plugin_name.argtypes = [c_ushort] - #self.lib.get_real_plugin_name.restype = c_char_p + self.lib.get_real_plugin_name.argtypes = [c_ushort] + self.lib.get_real_plugin_name.restype = c_char_p - #self.lib.get_current_program_index.argtypes = [c_ushort] - #self.lib.get_current_program_index.restype = c_int32 + self.lib.get_current_program_index.argtypes = [c_ushort] + self.lib.get_current_program_index.restype = c_int32 - #self.lib.get_current_midi_program_index.argtypes = [c_ushort] - #self.lib.get_current_midi_program_index.restype = c_int32 + self.lib.get_current_midi_program_index.argtypes = [c_ushort] + self.lib.get_current_midi_program_index.restype = c_int32 - #self.lib.get_default_parameter_value.argtypes = [c_ushort, c_uint32] - #self.lib.get_default_parameter_value.restype = c_double + self.lib.get_default_parameter_value.argtypes = [c_ushort, c_uint32] + self.lib.get_default_parameter_value.restype = c_double - #self.lib.get_current_parameter_value.argtypes = [c_ushort, c_uint32] - #self.lib.get_current_parameter_value.restype = c_double + self.lib.get_current_parameter_value.argtypes = [c_ushort, c_uint32] + self.lib.get_current_parameter_value.restype = c_double - #self.lib.get_input_peak_value.argtypes = [c_ushort, c_ushort] - #self.lib.get_input_peak_value.restype = c_double + self.lib.get_input_peak_value.argtypes = [c_ushort, c_ushort] + self.lib.get_input_peak_value.restype = c_double - #self.lib.get_output_peak_value.argtypes = [c_ushort, c_ushort] - #self.lib.get_output_peak_value.restype = c_double + self.lib.get_output_peak_value.argtypes = [c_ushort, c_ushort] + self.lib.get_output_peak_value.restype = c_double - #self.lib.set_active.argtypes = [c_ushort, c_bool] - #self.lib.set_active.restype = None + self.lib.set_active.argtypes = [c_ushort, c_bool] + self.lib.set_active.restype = None - #self.lib.set_drywet.argtypes = [c_ushort, c_double] - #self.lib.set_drywet.restype = None + self.lib.set_drywet.argtypes = [c_ushort, c_double] + self.lib.set_drywet.restype = None - #self.lib.set_volume.argtypes = [c_ushort, c_double] - #self.lib.set_volume.restype = None + self.lib.set_volume.argtypes = [c_ushort, c_double] + self.lib.set_volume.restype = None - #self.lib.set_balance_left.argtypes = [c_ushort, c_double] - #self.lib.set_balance_left.restype = None + self.lib.set_balance_left.argtypes = [c_ushort, c_double] + self.lib.set_balance_left.restype = None - #self.lib.set_balance_right.argtypes = [c_ushort, c_double] - #self.lib.set_balance_right.restype = None + self.lib.set_balance_right.argtypes = [c_ushort, c_double] + self.lib.set_balance_right.restype = None - #self.lib.set_parameter_value.argtypes = [c_ushort, c_uint32, c_double] - #self.lib.set_parameter_value.restype = None + self.lib.set_parameter_value.argtypes = [c_ushort, c_uint32, c_double] + self.lib.set_parameter_value.restype = None - #self.lib.set_parameter_midi_channel.argtypes = [c_ushort, c_uint32, c_uint8] - #self.lib.set_parameter_midi_channel.restype = None + self.lib.set_parameter_midi_channel.argtypes = [c_ushort, c_uint32, c_uint8] + self.lib.set_parameter_midi_channel.restype = None - #self.lib.set_parameter_midi_cc.argtypes = [c_ushort, c_uint32, c_int16] - #self.lib.set_parameter_midi_cc.restype = None + self.lib.set_parameter_midi_cc.argtypes = [c_ushort, c_uint32, c_int16] + self.lib.set_parameter_midi_cc.restype = None - #self.lib.set_program.argtypes = [c_ushort, c_uint32] - #self.lib.set_program.restype = None + self.lib.set_program.argtypes = [c_ushort, c_uint32] + self.lib.set_program.restype = None - #self.lib.set_midi_program.argtypes = [c_ushort, c_uint32] - #self.lib.set_midi_program.restype = None + self.lib.set_midi_program.argtypes = [c_ushort, c_uint32] + self.lib.set_midi_program.restype = None - #self.lib.set_custom_data.argtypes = [c_ushort, c_char_p, c_char_p, c_char_p] - #self.lib.set_custom_data.restype = None + self.lib.set_custom_data.argtypes = [c_ushort, c_char_p, c_char_p, c_char_p] + self.lib.set_custom_data.restype = None - #self.lib.set_chunk_data.argtypes = [c_ushort, c_char_p] - #self.lib.set_chunk_data.restype = None + self.lib.set_chunk_data.argtypes = [c_ushort, c_char_p] + self.lib.set_chunk_data.restype = None - #self.lib.set_gui_data.argtypes = [c_ushort, c_int, c_intptr] - #self.lib.set_gui_data.restype = None + self.lib.set_gui_data.argtypes = [c_ushort, c_int, c_intptr] + self.lib.set_gui_data.restype = None - #self.lib.show_gui.argtypes = [c_ushort, c_bool] - #self.lib.show_gui.restype = None + self.lib.show_gui.argtypes = [c_ushort, c_bool] + self.lib.show_gui.restype = None - #self.lib.idle_gui.argtypes = [c_ushort] - #self.lib.idle_gui.restype = None + self.lib.idle_gui.argtypes = [c_ushort] + self.lib.idle_gui.restype = None - #self.lib.send_midi_note.argtypes = [c_ushort, c_bool, c_uint8, c_uint8] - #self.lib.send_midi_note.restype = None + self.lib.send_midi_note.argtypes = [c_ushort, c_bool, c_uint8, c_uint8] + self.lib.send_midi_note.restype = None - #self.lib.prepare_for_save.argtypes = [c_ushort] - #self.lib.prepare_for_save.restype = None + self.lib.prepare_for_save.argtypes = [c_ushort] + self.lib.prepare_for_save.restype = None - #self.lib.set_callback_function.argtypes = [CallbackFunc] - #self.lib.set_callback_function.restype = None + self.lib.set_callback_function.argtypes = [CallbackFunc] + self.lib.set_callback_function.restype = None - #self.lib.set_option.argtypes = [c_enum, c_int, c_char_p] - #self.lib.set_option.restype = None + self.lib.set_option.argtypes = [c_enum, c_int, c_char_p] + self.lib.set_option.restype = None - #self.lib.get_last_error.argtypes = None - #self.lib.get_last_error.restype = c_char_p + self.lib.get_last_error.argtypes = None + self.lib.get_last_error.restype = c_char_p - #self.lib.get_host_client_name.argtypes = None - #self.lib.get_host_client_name.restype = c_char_p + self.lib.get_host_client_name.argtypes = None + self.lib.get_host_client_name.restype = c_char_p - #self.lib.get_host_osc_url.argtypes = None - #self.lib.get_host_osc_url.restype = c_char_p + self.lib.get_host_osc_url.argtypes = None + self.lib.get_host_osc_url.restype = c_char_p - #self.lib.get_buffer_size.argtypes = None - #self.lib.get_buffer_size.restype = c_uint32 + self.lib.get_buffer_size.argtypes = None + self.lib.get_buffer_size.restype = c_uint32 - #self.lib.get_sample_rate.argtypes = None - #self.lib.get_sample_rate.restype = c_double + self.lib.get_sample_rate.argtypes = None + self.lib.get_sample_rate.restype = c_double - #self.lib.get_latency.argtypes = None - #self.lib.get_latency.restype = c_double + self.lib.get_latency.argtypes = None + self.lib.get_latency.restype = c_double - # bool carla_init(const char* client_name); - FIXME def carla_init(self, client_name): - return True - return self.lib.carla_init(client_name) + return self.lib.carla_init(client_name.encode("utf-8")) - # bool carla_close(); - FIXME def carla_close(self): - return True return self.lib.carla_close() - # bool carla_is_engine_running(); - FIXME def carla_is_engine_running(self): - return False return self.lib.carla_is_engine_running() - # short add_plugin(BinaryType btype, PluginType ptype, const char* filename, const char* label, void* extra_stuff); - FIXME def add_plugin(self, btype, ptype, filename, label, extra_stuff): - return -1 - return self.lib.add_plugin(btype, ptype, filename, label, cast(extra_stuff, c_void_p)) + return self.lib.add_plugin(btype, ptype, filename.encode("utf-8"), label.encode("utf-8"), cast(extra_stuff, c_void_p)) def remove_plugin(self, plugin_id): return self.lib.remove_plugin(plugin_id) @@ -1081,9 +1073,7 @@ class Host(object): def prepare_for_save(self, plugin_id): self.lib.prepare_for_save(plugin_id) - # void set_callback_function(CallbackFunc func); - FIXME def set_callback_function(self, func): - return global Callback Callback = CallbackFunc(func) self.lib.set_callback_function(Callback) @@ -1091,19 +1081,13 @@ class Host(object): def set_option(self, option, value, value_str): self.lib.set_option(option, value, value_str) - # const char* get_last_error(); - FIXME def get_last_error(self): - return "" return self.lib.get_last_error() - # const char* get_host_client_name(); - FIXME def get_host_client_name(self): - return "" return self.lib.get_host_client_name() - # const char* get_host_osc_url(); - FIXME def get_host_osc_url(self): - return "" return self.lib.get_host_osc_url() def get_buffer_size(self): diff --git a/src/icons/bitmaps/credits.txt b/src/icons/bitmaps/credits.txt new file mode 100644 index 0000000..920a3ae --- /dev/null +++ b/src/icons/bitmaps/credits.txt @@ -0,0 +1,5 @@ +The pixmaps in this folder were taken from the following projects: + +dial_* - TAL Plugins +kbd_* - FL Studio + diff --git a/src/icons/bitmaps/glass.png b/src/icons/bitmaps/glass.png new file mode 100644 index 0000000..fecd69d Binary files /dev/null and b/src/icons/bitmaps/glass.png differ diff --git a/src/icons/bitmaps/glass2.png b/src/icons/bitmaps/glass2.png new file mode 100644 index 0000000..b28d093 Binary files /dev/null and b/src/icons/bitmaps/glass2.png differ diff --git a/src/icons/bitmaps/textures/metal_1-512px.jpg b/src/icons/bitmaps/textures/metal_1-512px.jpg new file mode 100644 index 0000000..bb02640 Binary files /dev/null and b/src/icons/bitmaps/textures/metal_1-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_2-512px.jpg b/src/icons/bitmaps/textures/metal_2-512px.jpg new file mode 100644 index 0000000..c168515 Binary files /dev/null and b/src/icons/bitmaps/textures/metal_2-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_3-512px.jpg b/src/icons/bitmaps/textures/metal_3-512px.jpg new file mode 100644 index 0000000..6245f30 Binary files /dev/null and b/src/icons/bitmaps/textures/metal_3-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_4-512px.jpg b/src/icons/bitmaps/textures/metal_4-512px.jpg new file mode 100644 index 0000000..7531e62 Binary files /dev/null and b/src/icons/bitmaps/textures/metal_4-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_5-512px.jpg b/src/icons/bitmaps/textures/metal_5-512px.jpg new file mode 100644 index 0000000..74a040c Binary files /dev/null and b/src/icons/bitmaps/textures/metal_5-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_6-512px.jpg b/src/icons/bitmaps/textures/metal_6-512px.jpg new file mode 100644 index 0000000..5498a9a Binary files /dev/null and b/src/icons/bitmaps/textures/metal_6-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_7-512px.jpg b/src/icons/bitmaps/textures/metal_7-512px.jpg new file mode 100644 index 0000000..3cc9b3a Binary files /dev/null and b/src/icons/bitmaps/textures/metal_7-512px.jpg differ diff --git a/src/icons/bitmaps/textures/metal_8-512px.jpg b/src/icons/bitmaps/textures/metal_8-512px.jpg new file mode 100644 index 0000000..1f42673 Binary files /dev/null and b/src/icons/bitmaps/textures/metal_8-512px.jpg differ diff --git a/src/icons/icons.qrc b/src/icons/icons.qrc index b1e41cd..c610eae 100644 --- a/src/icons/icons.qrc +++ b/src/icons/icons.qrc @@ -71,5 +71,15 @@ bitmaps/led-big_on.png bitmaps/led-big_off.png bitmaps/carla_about.png + bitmaps/glass.png + bitmaps/glass2.png + bitmaps/textures/metal_1-512px.jpg + bitmaps/textures/metal_2-512px.jpg + bitmaps/textures/metal_3-512px.jpg + bitmaps/textures/metal_4-512px.jpg + bitmaps/textures/metal_5-512px.jpg + bitmaps/textures/metal_6-512px.jpg + bitmaps/textures/metal_7-512px.jpg + bitmaps/textures/metal_8-512px.jpg diff --git a/src/ladspa_rdf.py b/src/ladspa_rdf.py index c3eca7b..b95b5da 100644 --- a/src/ladspa_rdf.py +++ b/src/ladspa_rdf.py @@ -709,7 +709,7 @@ def recheck_all_plugins(qobject, start_value, percent_value, m_value): # Convert PyLADSPA_Plugins into ctype structs def get_c_ladspa_rdfs(PyPluginList): C_LADSPA_Plugins = [] - c_unicode_error_str = "(unicode error)".encode("ascii") + c_unicode_error_str = "(unicode error)".encode("utf-8") for plugin in PyPluginList: # Sort the ports by index @@ -721,12 +721,18 @@ def get_c_ladspa_rdfs(PyPluginList): desc.UniqueID = plugin['UniqueID'] try: - desc.Title = plugin['Title'].encode("ascii") + if (plugin['Title']) + desc.Title = plugin['Title'].encode("utf-8") + else: + desc.Title = None except: desc.Title = c_unicode_error_str try: - desc.Creator = plugin['Creator'].encode("ascii") + if (plugin['Creator']) + desc.Creator = plugin['Creator'].encode("utf-8") + else: + desc.Creator = None except: desc.Creator = c_unicode_error_str @@ -744,7 +750,7 @@ def get_c_ladspa_rdfs(PyPluginList): port.Hints = py_port['Hints'] try: - port.Label = py_port['Label'].encode("ascii") + port.Label = py_port['Label'].encode("utf-8") except: port.Label = c_unicode_error_str @@ -762,7 +768,7 @@ def get_c_ladspa_rdfs(PyPluginList): py_scalepoint = py_port['ScalePoints'][j] try: - scalepoint.Label = py_scalepoint['Label'].encode("ascii") + scalepoint.Label = py_scalepoint['Label'].encode("utf-8") except: scalepoint.Label = c_unicode_error_str