| @@ -284,7 +284,6 @@ RES = \ | |||
| bin/resources/ui_carla_plugin_calf.py \ | |||
| bin/resources/ui_carla_plugin_default.py \ | |||
| bin/resources/ui_carla_plugin_sf2.py \ | |||
| bin/resources/ui_carla_plugin_zita.py \ | |||
| bin/resources/ui_carla_plugin_zynfx.py \ | |||
| bin/resources/ui_carla_refresh.py \ | |||
| bin/resources/ui_carla_settings.py \ | |||
| @@ -330,7 +329,6 @@ UIs = \ | |||
| source/ui_carla_plugin_calf.py \ | |||
| source/ui_carla_plugin_default.py \ | |||
| source/ui_carla_plugin_sf2.py \ | |||
| source/ui_carla_plugin_zita.py \ | |||
| source/ui_carla_plugin_zynfx.py \ | |||
| source/ui_carla_refresh.py \ | |||
| source/ui_carla_settings.py \ | |||
| @@ -552,7 +550,6 @@ install: | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_plugin_calf.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_plugin_default.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_plugin_sf2.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_plugin_zita.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_plugin_zynfx.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_refresh.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| $(LINK) $(PREFIX)/share/carla/ui_carla_settings.py $(DESTDIR)$(PREFIX)/share/carla/resources/ | |||
| @@ -130,13 +130,6 @@ | |||
| <file>bitmaps/style/arrow.png</file> | |||
| <file>bitmaps/style/groupbox.png</file> | |||
| <file>bitmaps/zita-rev/ambsect.png</file> | |||
| <file>bitmaps/zita-rev/eq1sect.png</file> | |||
| <file>bitmaps/zita-rev/eq2sect.png</file> | |||
| <file>bitmaps/zita-rev/mixsect.png</file> | |||
| <file>bitmaps/zita-rev/redzita.png</file> | |||
| <file>bitmaps/zita-rev/revsect.png</file> | |||
| <file>scalable/pb_generic.svg</file> | |||
| <file>scalable/pb_hardware.svg</file> | |||
| <file>scalable/pb_plugin.svg</file> | |||
| @@ -1,150 +0,0 @@ | |||
| <?xml version="1.0" encoding="UTF-8"?> | |||
| <ui version="4.0"> | |||
| <class>PluginWidget</class> | |||
| <widget class="QFrame" name="PluginWidget"> | |||
| <property name="geometry"> | |||
| <rect> | |||
| <x>0</x> | |||
| <y>0</y> | |||
| <width>640</width> | |||
| <height>75</height> | |||
| </rect> | |||
| </property> | |||
| <property name="contextMenuPolicy"> | |||
| <enum>Qt::CustomContextMenu</enum> | |||
| </property> | |||
| <property name="windowTitle"> | |||
| <string>Frame</string> | |||
| </property> | |||
| <layout class="QHBoxLayout" name="horizontalLayout_6"> | |||
| <property name="spacing"> | |||
| <number>0</number> | |||
| </property> | |||
| <property name="margin"> | |||
| <number>0</number> | |||
| </property> | |||
| <item> | |||
| <widget class="QWidget" name="w_revsect" native="true"> | |||
| <property name="minimumSize"> | |||
| <size> | |||
| <width>315</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <property name="maximumSize"> | |||
| <size> | |||
| <width>315</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <layout class="QHBoxLayout" name="horizontalLayout"> | |||
| <property name="spacing"> | |||
| <number>0</number> | |||
| </property> | |||
| <property name="margin"> | |||
| <number>0</number> | |||
| </property> | |||
| </layout> | |||
| </widget> | |||
| </item> | |||
| <item> | |||
| <widget class="QWidget" name="w_eq1sect" native="true"> | |||
| <property name="minimumSize"> | |||
| <size> | |||
| <width>110</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <property name="maximumSize"> | |||
| <size> | |||
| <width>110</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <layout class="QHBoxLayout" name="horizontalLayout_2"> | |||
| <property name="spacing"> | |||
| <number>0</number> | |||
| </property> | |||
| <property name="margin"> | |||
| <number>0</number> | |||
| </property> | |||
| </layout> | |||
| </widget> | |||
| </item> | |||
| <item> | |||
| <widget class="QWidget" name="w_eq2sect" native="true"> | |||
| <property name="minimumSize"> | |||
| <size> | |||
| <width>110</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <property name="maximumSize"> | |||
| <size> | |||
| <width>110</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <layout class="QHBoxLayout" name="horizontalLayout_3"> | |||
| <property name="spacing"> | |||
| <number>0</number> | |||
| </property> | |||
| <property name="margin"> | |||
| <number>0</number> | |||
| </property> | |||
| </layout> | |||
| </widget> | |||
| </item> | |||
| <item> | |||
| <widget class="QWidget" name="w_ambmixsect" native="true"> | |||
| <property name="minimumSize"> | |||
| <size> | |||
| <width>70</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <property name="maximumSize"> | |||
| <size> | |||
| <width>70</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <layout class="QHBoxLayout" name="horizontalLayout_4"> | |||
| <property name="spacing"> | |||
| <number>0</number> | |||
| </property> | |||
| <property name="margin"> | |||
| <number>0</number> | |||
| </property> | |||
| </layout> | |||
| </widget> | |||
| </item> | |||
| <item> | |||
| <widget class="QWidget" name="w_redzita" native="true"> | |||
| <property name="minimumSize"> | |||
| <size> | |||
| <width>35</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <property name="maximumSize"> | |||
| <size> | |||
| <width>35</width> | |||
| <height>75</height> | |||
| </size> | |||
| </property> | |||
| <layout class="QHBoxLayout" name="horizontalLayout_5"> | |||
| <property name="spacing"> | |||
| <number>0</number> | |||
| </property> | |||
| <property name="margin"> | |||
| <number>0</number> | |||
| </property> | |||
| </layout> | |||
| </widget> | |||
| </item> | |||
| </layout> | |||
| </widget> | |||
| <resources/> | |||
| <connections/> | |||
| </ui> | |||
| @@ -385,7 +385,8 @@ endif | |||
| ifeq ($(EXPERIMENTAL_PLUGINS),true) | |||
| NATIVE_PLUGINS_FLAGS += -DHAVE_EXPERIMENTAL_PLUGINS | |||
| NATIVE_PLUGINS_LIBS += -lzita-convolver $(shell pkg-config --libs cairo fftw3f libpng12 x11 xft) -lclthreads -lclxclient | |||
| NATIVE_PLUGINS_LIBS += -lclthreads -lclxclient -lzita-convolver -lzita-resampler | |||
| NATIVE_PLUGINS_LIBS += $(shell pkg-config --libs cairo fftw3f libpng12 x11 xft) | |||
| endif | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| @@ -39,7 +39,6 @@ import ui_carla_plugin_default | |||
| import ui_carla_plugin_basic_fx | |||
| import ui_carla_plugin_calf | |||
| import ui_carla_plugin_sf2 | |||
| import ui_carla_plugin_zita | |||
| import ui_carla_plugin_zynfx | |||
| from carla_widgets import * | |||
| @@ -1578,150 +1577,6 @@ class PluginSlot_SF2(AbstractPluginSlot): | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| class PluginSlot_ZitaRev(AbstractPluginSlot): | |||
| def __init__(self, parent, host, pluginId): | |||
| AbstractPluginSlot.__init__(self, parent, host, pluginId) | |||
| self.ui = ui_carla_plugin_zita.Ui_PluginWidget() | |||
| self.ui.setupUi(self) | |||
| # ------------------------------------------------------------- | |||
| # Internal stuff | |||
| audioCount = self.host.get_audio_port_count_info(self.fPluginId) | |||
| # ------------------------------------------------------------- | |||
| # Set-up GUI | |||
| self.setMinimumWidth(640) | |||
| self.setStyleSheet(""" | |||
| PluginSlot_ZitaRev#PluginWidget { | |||
| background-color: #404040; | |||
| border: 2px solid transparent; | |||
| } | |||
| QWidget#w_revsect { | |||
| background-image: url(:/bitmaps/zita-rev/revsect.png); | |||
| } | |||
| QWidget#w_eq1sect { | |||
| background-image: url(:/bitmaps/zita-rev/eq1sect.png); | |||
| } | |||
| QWidget#w_eq2sect { | |||
| background-image: url(:/bitmaps/zita-rev/eq2sect.png); | |||
| } | |||
| QWidget#w_ambmixsect { | |||
| background-image: url(:/bitmaps/zita-rev/%s.png); | |||
| } | |||
| QWidget#w_redzita { | |||
| background-image: url(:/bitmaps/zita-rev/redzita.png); | |||
| } | |||
| """ % ("mixsect" if audioCount['outs'] == 2 else "ambsect")) | |||
| # ------------------------------------------------------------- | |||
| # Set-up Knobs | |||
| self.fKnobDelay = PixmapDial(self, 0) | |||
| self.fKnobDelay.setPixmap(6) | |||
| self.fKnobDelay.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobDelay.setMinimum(0.02) | |||
| self.fKnobDelay.setMaximum(0.10) | |||
| self.fKnobXover = PixmapDial(self, 1) | |||
| self.fKnobXover.setPixmap(6) | |||
| self.fKnobXover.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobXover.setMinimum(50.0) | |||
| self.fKnobXover.setMaximum(1000.0) | |||
| self.fKnobRtLow = PixmapDial(self, 2) | |||
| self.fKnobRtLow.setPixmap(6) | |||
| self.fKnobRtLow.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobRtLow.setMinimum(1.0) | |||
| self.fKnobRtLow.setMaximum(8.0) | |||
| self.fKnobRtMid = PixmapDial(self, 3) | |||
| self.fKnobRtMid.setPixmap(6) | |||
| self.fKnobRtMid.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobRtMid.setMinimum(1.0) | |||
| self.fKnobRtMid.setMaximum(8.0) | |||
| self.fKnobDamping = PixmapDial(self, 4) | |||
| self.fKnobDamping.setPixmap(6) | |||
| self.fKnobDamping.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobDamping.setMinimum(1500.0) | |||
| self.fKnobDamping.setMaximum(24000.0) | |||
| self.fKnobEq1Freq = PixmapDial(self, 5) | |||
| self.fKnobEq1Freq.setPixmap(6) | |||
| self.fKnobEq1Freq.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobEq1Freq.setMinimum(40.0) | |||
| self.fKnobEq1Freq.setMaximum(10000.0) | |||
| self.fKnobEq1Gain = PixmapDial(self, 6) | |||
| self.fKnobEq1Gain.setPixmap(6) | |||
| self.fKnobEq1Gain.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobEq1Gain.setMinimum(-20.0) | |||
| self.fKnobEq1Gain.setMaximum(20.0) | |||
| self.fKnobEq2Freq = PixmapDial(self, 7) | |||
| self.fKnobEq2Freq.setPixmap(6) | |||
| self.fKnobEq2Freq.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobEq2Freq.setMinimum(40.0) | |||
| self.fKnobEq2Freq.setMaximum(10000.0) | |||
| self.fKnobEq2Gain = PixmapDial(self, 8) | |||
| self.fKnobEq2Gain.setPixmap(6) | |||
| self.fKnobEq2Gain.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobEq2Gain.setMinimum(-20.0) | |||
| self.fKnobEq2Gain.setMaximum(20.0) | |||
| self.fKnobMix = PixmapDial(self, 9) | |||
| self.fKnobMix.setPixmap(6) | |||
| self.fKnobMix.setCustomPaintMode(PixmapDial.CUSTOM_PAINT_MODE_ZITA) | |||
| self.fKnobMix.setMinimum(0.0) | |||
| self.fKnobMix.setMaximum(1.0) | |||
| self.fParameterList.append([0, self.fKnobDelay]) | |||
| self.fParameterList.append([1, self.fKnobXover]) | |||
| self.fParameterList.append([2, self.fKnobRtLow]) | |||
| self.fParameterList.append([3, self.fKnobRtMid]) | |||
| self.fParameterList.append([4, self.fKnobDamping]) | |||
| self.fParameterList.append([5, self.fKnobEq1Freq]) | |||
| self.fParameterList.append([6, self.fKnobEq1Gain]) | |||
| self.fParameterList.append([7, self.fKnobEq2Freq]) | |||
| self.fParameterList.append([8, self.fKnobEq2Gain]) | |||
| self.fParameterList.append([9, self.fKnobMix]) | |||
| # ------------------------------------------------------------- | |||
| self.ready() | |||
| self.customContextMenuRequested.connect(self.slot_showDefaultCustomMenu) | |||
| #------------------------------------------------------------------ | |||
| def getFixedHeight(self): | |||
| return 79 | |||
| #------------------------------------------------------------------ | |||
| def paintEvent(self, event): | |||
| AbstractPluginSlot.paintEvent(self, event) | |||
| self.drawOutline() | |||
| def resizeEvent(self, event): | |||
| self.fKnobDelay.move(self.ui.w_revsect.x()+31, self.ui.w_revsect.y()+33) | |||
| self.fKnobXover.move(self.ui.w_revsect.x()+93, self.ui.w_revsect.y()+18) | |||
| self.fKnobRtLow.move(self.ui.w_revsect.x()+148, self.ui.w_revsect.y()+18) | |||
| self.fKnobRtMid.move(self.ui.w_revsect.x()+208, self.ui.w_revsect.y()+18) | |||
| self.fKnobDamping.move(self.ui.w_revsect.x()+268, self.ui.w_revsect.y()+18) | |||
| self.fKnobEq1Freq.move(self.ui.w_eq1sect.x()+20, self.ui.w_eq1sect.y()+33) | |||
| self.fKnobEq1Gain.move(self.ui.w_eq1sect.x()+69, self.ui.w_eq1sect.y()+18) | |||
| self.fKnobEq2Freq.move(self.ui.w_eq2sect.x()+20, self.ui.w_eq2sect.y()+33) | |||
| self.fKnobEq2Gain.move(self.ui.w_eq2sect.x()+69, self.ui.w_eq2sect.y()+18) | |||
| self.fKnobMix.move(self.ui.w_ambmixsect.x()+24, self.ui.w_ambmixsect.y()+33) | |||
| AbstractPluginSlot.resizeEvent(self, event) | |||
| # ------------------------------------------------------------------------------------------------------------ | |||
| class PluginSlot_ZynFX(AbstractPluginSlot): | |||
| def __init__(self, parent, host, pluginId): | |||
| AbstractPluginSlot.__init__(self, parent, host, pluginId) | |||
| @@ -1968,8 +1823,6 @@ def createPluginSlot(parent, host, pluginId, useSkins): | |||
| return PluginSlot_ZynFX(parent, host, pluginId) | |||
| elif pluginInfo['type'] == PLUGIN_LADSPA: | |||
| if (pluginLabel == "zita-reverb" and uniqueId == 3701) or (pluginLabel == "zita-reverb-amb" and uniqueId == 3702): | |||
| return PluginSlot_ZitaRev(parent, host, pluginId) | |||
| if pluginLabel.startswith("Zyn") and pluginMaker.startswith("Josep Andreu"): | |||
| return PluginSlot_ZynFX(parent, host, pluginId) | |||
| @@ -39,7 +39,7 @@ public: | |||
| fExtUiPath(extUiPath), | |||
| leakDetector_NativePluginAndUiClass() {} | |||
| ~NativePluginAndUiClass() noexcept override {} | |||
| //~NativePluginAndUiClass() noexcept override {} | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| @@ -31,18 +31,27 @@ extern "C" { | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Macros */ | |||
| #define JACK_DEFAULT_AUDIO_TYPE "audio" | |||
| #define JACK_DEFAULT_MIDI_TYPE "midi" | |||
| #define JACK_DEFAULT_AUDIO_TYPE "32 bit float mono audio" | |||
| #define JACK_DEFAULT_MIDI_TYPE "8 bit raw midi" | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Basic types */ | |||
| typedef float jack_default_audio_sample_t; | |||
| typedef uint8_t jack_midi_data_t; | |||
| typedef uint32_t jack_nframes_t; | |||
| typedef void (*jack_shutdown_callback)(void* ptr); | |||
| typedef int (*jack_process_callback)(jack_nframes_t nframes, void* ptr); | |||
| /* | |||
| * Helper struct for midi events. | |||
| */ | |||
| typedef struct { | |||
| uint32_t count; | |||
| NativeMidiEvent* events; | |||
| } NativeMidiEventsBuffer; | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Enums */ | |||
| @@ -81,15 +90,20 @@ enum JackStatus { | |||
| }; | |||
| typedef enum JackOptions jack_options_t; | |||
| typedef enum JackStatus jack_status_t; | |||
| typedef enum JackStatus jack_status_t; | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Structs */ | |||
| typedef struct { | |||
| bool registered; | |||
| bool isAudio; | |||
| uint flags; | |||
| void* buffer; | |||
| union { | |||
| void* audio; | |||
| NativeMidiEventsBuffer midi; | |||
| } buffer; | |||
| } jack_port_t; | |||
| typedef struct { | |||
| @@ -104,10 +118,18 @@ typedef struct { | |||
| void* processPtr; | |||
| // ports | |||
| jack_port_t portsAudioIn[8]; | |||
| jack_port_t portsAudioOut[8]; | |||
| jack_port_t portsAudioIn [16]; | |||
| jack_port_t portsAudioOut[16]; | |||
| jack_port_t portsMidiIn [16]; | |||
| jack_port_t portsMidiOut [16]; | |||
| } jack_client_t; | |||
| typedef struct { | |||
| uint32_t time; | |||
| uint32_t size; | |||
| uint8_t* buffer; | |||
| } jack_midi_event_t; | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * Client functions */ | |||
| @@ -163,18 +185,31 @@ int jack_set_process_callback(jack_client_t* client, jack_process_callback callb | |||
| static inline | |||
| jack_port_t* jack_port_register(jack_client_t* client, const char* name, const char* type, ulong flags, ulong buffersize) | |||
| { | |||
| jack_port_t* const ports = (flags & JackPortIsInput) ? client->portsAudioIn : client->portsAudioOut; | |||
| const bool isAudio = strcmp(type, JACK_DEFAULT_AUDIO_TYPE) == 0; | |||
| const bool isMIDI = strcmp(type, JACK_DEFAULT_MIDI_TYPE ) == 0; | |||
| for (int i=0; i<8; ++i) | |||
| if (! (isAudio || isMIDI)) | |||
| return NULL; | |||
| jack_port_t* ports; | |||
| if (isAudio) | |||
| ports = (flags & JackPortIsInput) ? client->portsAudioIn : client->portsAudioOut; | |||
| else | |||
| ports = (flags & JackPortIsInput) ? client->portsMidiIn : client->portsMidiOut; | |||
| for (int i=0; i<16; ++i) | |||
| { | |||
| jack_port_t* const port = &ports[i]; | |||
| if (port->registered) | |||
| continue; | |||
| memset(port, 0, sizeof(jack_port_t)); | |||
| port->registered = true; | |||
| port->isAudio = isAudio; | |||
| port->flags = flags; | |||
| port->buffer = NULL; | |||
| return port; | |||
| } | |||
| @@ -196,9 +231,7 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
| { | |||
| if (&ports[i] == port) | |||
| { | |||
| port->registered = false; | |||
| port->flags = 0x0; | |||
| port->buffer = NULL; | |||
| memset(port, 0, sizeof(jack_port_t)); | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -207,14 +240,44 @@ int jack_port_unregister(jack_client_t* client, jack_port_t* port) | |||
| } | |||
| static inline | |||
| void* jack_port_get_buffer(const jack_port_t* port, jack_nframes_t nframes) | |||
| void* jack_port_get_buffer(jack_port_t* port, jack_nframes_t nframes) | |||
| { | |||
| return port->buffer; | |||
| return port->isAudio ? port->buffer.audio : &port->buffer.midi; | |||
| // unused | |||
| (void)nframes; | |||
| } | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * MIDI functions */ | |||
| static inline | |||
| uint32_t jack_midi_get_event_count(void* port_buffer) | |||
| { | |||
| NativeMidiEventsBuffer* const midi_buffer = (NativeMidiEventsBuffer*)port_buffer; | |||
| return midi_buffer->count; | |||
| } | |||
| static inline | |||
| int jack_midi_event_get(jack_midi_event_t* event, void* port_buffer, uint32_t event_index) | |||
| { | |||
| NativeMidiEventsBuffer* const midi_buffer = (NativeMidiEventsBuffer*)port_buffer; | |||
| if (midi_buffer->count == 0) | |||
| return ENODATA; | |||
| if (event_index >= midi_buffer->count) | |||
| return 1; // FIXME | |||
| NativeMidiEvent* const midiEvent = &midi_buffer->events[event_index]; | |||
| event->time = midiEvent->time; | |||
| event->size = midiEvent->size; | |||
| event->buffer = midiEvent->data; | |||
| return 0; | |||
| } | |||
| /* ------------------------------------------------------------------------------------------------------------ | |||
| * [De/]Activate */ | |||
| @@ -147,7 +147,9 @@ endif | |||
| ifeq ($(EXPERIMENTAL_PLUGINS),true) | |||
| OBJS += \ | |||
| $(OBJDIR)/zita-bls1.cpp.o | |||
| $(OBJDIR)/zita-at1.cpp.o \ | |||
| $(OBJDIR)/zita-bls1.cpp.o \ | |||
| $(OBJDIR)/zita-rev1.cpp.o | |||
| endif | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| @@ -250,11 +252,21 @@ $(OBJDIR)/zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FI | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| $(OBJDIR)/zita-at1.cpp.o: zita-at1.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags fftw3f x11 xft) -Wno-unused-parameter -Wno-unused-result -c -o $@ | |||
| $(OBJDIR)/zita-bls1.cpp.o: zita-bls1.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags cairo fftw3f libpng12 x11 xft) -Wno-unused-parameter -Wno-unused-result -c -o $@ | |||
| $(OBJDIR)/zita-rev1.cpp.o: zita-rev1.cpp | |||
| -@mkdir -p $(OBJDIR) | |||
| @echo "Compiling $<" | |||
| @$(CXX) $< $(BUILD_CXX_FLAGS) $(shell pkg-config --cflags fftw3f x11 xft) -Wno-unused-parameter -Wno-unused-result -c -o $@ | |||
| # ---------------------------------------------------------------------------------------------------------------------------- | |||
| $(OBJDIR)/%.cpp.o: %.cpp | |||
| @@ -61,7 +61,9 @@ extern void carla_register_native_plugin_zynaddsubfx_synth(void); | |||
| #ifdef WANT_EXPERIMENTAL_PLUGINS | |||
| // Experimental plugins | |||
| extern void carla_register_native_plugin_zita_at1(void); | |||
| extern void carla_register_native_plugin_zita_bls1(void); | |||
| extern void carla_register_native_plugin_zita_rev1(void); | |||
| #endif | |||
| // ----------------------------------------------------------------------- | |||
| @@ -110,7 +112,9 @@ void carla_register_all_plugins(void) | |||
| #ifdef WANT_EXPERIMENTAL_PLUGINS | |||
| // Experimental plugins | |||
| carla_register_native_plugin_zita_at1(); | |||
| carla_register_native_plugin_zita_bls1(); | |||
| carla_register_native_plugin_zita_rev1(); | |||
| #endif | |||
| } | |||
| @@ -0,0 +1,453 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaNative.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "juce_audio_basics.h" | |||
| #include "zita-common.hpp" | |||
| #include "zita-at1/button.cc" | |||
| #include "zita-at1/guiclass.cc" | |||
| #include "zita-at1/jclient.cc" | |||
| #include "zita-at1/mainwin.cc" | |||
| #include "zita-at1/png2img.cc" | |||
| #include "zita-at1/retuner.cc" | |||
| #include "zita-at1/rotary.cc" | |||
| #include "zita-at1/styles.cc" | |||
| #include "zita-at1/tmeter.cc" | |||
| using juce::FloatVectorOperations; | |||
| using juce::ScopedPointer; | |||
| using namespace AT1; | |||
| // ----------------------------------------------------------------------- | |||
| // AT1 Plugin | |||
| class AT1Plugin : public NativePluginClass, | |||
| private Mainwin::ValueChangedCallback | |||
| { | |||
| public: | |||
| enum Parameters { | |||
| // rotary knobs | |||
| kParameterR_TUNE, | |||
| kParameterR_FILT, | |||
| kParameterR_BIAS, | |||
| kParameterR_CORR, | |||
| kParameterR_OFFS, | |||
| // knob count | |||
| kParameterNROTARY, | |||
| // midi channel | |||
| kParameterM_CHANNEL = kParameterNROTARY, | |||
| // final count | |||
| kNumParameters | |||
| }; | |||
| AT1Plugin(const NativeHostDescriptor* const host) | |||
| : NativePluginClass(host), | |||
| fJackClient(), | |||
| xresman(), | |||
| jclient(nullptr), | |||
| display(nullptr), | |||
| rootwin(nullptr), | |||
| mainwin(nullptr), | |||
| handler(nullptr), | |||
| handlerThread(), | |||
| leakDetector_AT1Plugin() | |||
| { | |||
| CARLA_SAFE_ASSERT(host != nullptr); | |||
| carla_zeroStruct(fJackClient); | |||
| fJackClient.clientName = "at1"; | |||
| fJackClient.bufferSize = getBufferSize(); | |||
| fJackClient.sampleRate = getSampleRate(); | |||
| int argc = 1; | |||
| char* argv[] = { (char*)"at1" }; | |||
| xresman.init(&argc, argv, (char*)"at1", nullptr, 0); | |||
| jclient = new Jclient(xresman.rname(), &fJackClient); | |||
| // set initial values | |||
| fParameters[kParameterR_TUNE] = 440.0f; | |||
| fParameters[kParameterR_FILT] = 0.1f; | |||
| fParameters[kParameterR_BIAS] = 0.5f; | |||
| fParameters[kParameterR_CORR] = 1.0f; | |||
| fParameters[kParameterR_OFFS] = 0.0f; | |||
| fParameters[kParameterM_CHANNEL] = 0.0f; | |||
| Retuner* const retuner(jclient->retuner()); | |||
| jclient->set_midichan(-1); | |||
| retuner->set_refpitch(fParameters[kParameterR_TUNE]); | |||
| retuner->set_corrfilt(fParameters[kParameterR_FILT]); | |||
| retuner->set_notebias(fParameters[kParameterR_BIAS]); | |||
| retuner->set_corrgain(fParameters[kParameterR_CORR]); | |||
| retuner->set_corroffs(fParameters[kParameterR_OFFS]); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin parameter calls | |||
| uint32_t getParameterCount() const override | |||
| { | |||
| return kNumParameters; | |||
| } | |||
| const NativeParameter* getParameterInfo(const uint32_t index) const override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kNumParameters, nullptr); | |||
| static NativeParameter param; | |||
| static NativeParameterScalePoint scalePoints[17]; | |||
| int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMABLE; | |||
| // reset | |||
| param.name = nullptr; | |||
| param.unit = nullptr; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = 0.0f; | |||
| param.ranges.max = 1.0f; | |||
| param.ranges.step = 1.0f; | |||
| param.ranges.stepSmall = 1.0f; | |||
| param.ranges.stepLarge = 1.0f; | |||
| param.scalePointCount = 0; | |||
| param.scalePoints = nullptr; | |||
| switch (index) | |||
| { | |||
| case kParameterR_TUNE: | |||
| param.name = "Tuning"; | |||
| param.ranges.def = 440.0f; | |||
| param.ranges.min = 400.0f; | |||
| param.ranges.max = 480.0f; | |||
| break; | |||
| case kParameterR_FILT: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "Filter"; | |||
| param.ranges.def = 0.1f; | |||
| param.ranges.min = 0.02f; | |||
| param.ranges.max = 0.5f; | |||
| break; | |||
| case kParameterR_BIAS: | |||
| param.name = "Bias"; | |||
| param.ranges.def = 0.5f; | |||
| param.ranges.min = 0.0f; | |||
| param.ranges.max = 1.0f; | |||
| break; | |||
| case kParameterR_CORR: | |||
| param.name = "Correction"; | |||
| param.ranges.def = 1.0f; | |||
| param.ranges.min = 0.0f; | |||
| param.ranges.max = 1.0f; | |||
| break; | |||
| case kParameterR_OFFS: | |||
| param.name = "OfOfset"; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = -2.0f; | |||
| param.ranges.max = 2.0f; | |||
| break; | |||
| case kParameterM_CHANNEL: | |||
| hints |= NATIVE_PARAMETER_USES_SCALEPOINTS; | |||
| param.name = "MIDI Channel"; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = 0.0f; | |||
| param.ranges.max = 16.0f; | |||
| param.scalePointCount = 17; | |||
| param.scalePoints = scalePoints; | |||
| scalePoints[ 0].value = 0.0f; | |||
| scalePoints[ 0].label = "Omni"; | |||
| scalePoints[ 1].value = 1.0f; | |||
| scalePoints[ 1].label = "1"; | |||
| scalePoints[ 2].value = 2.0f; | |||
| scalePoints[ 2].label = "2"; | |||
| scalePoints[ 3].value = 3.0f; | |||
| scalePoints[ 3].label = "3"; | |||
| scalePoints[ 4].value = 4.0f; | |||
| scalePoints[ 4].label = "4"; | |||
| scalePoints[ 5].value = 5.0f; | |||
| scalePoints[ 5].label = "5"; | |||
| scalePoints[ 6].value = 6.0f; | |||
| scalePoints[ 6].label = "6"; | |||
| scalePoints[ 7].value = 7.0f; | |||
| scalePoints[ 7].label = "7"; | |||
| scalePoints[ 8].value = 8.0f; | |||
| scalePoints[ 8].label = "8"; | |||
| scalePoints[ 9].value = 9.0f; | |||
| scalePoints[ 9].label = "9"; | |||
| scalePoints[10].value = 10.0f; | |||
| scalePoints[10].label = "10"; | |||
| scalePoints[11].value = 11.0f; | |||
| scalePoints[11].label = "11"; | |||
| scalePoints[12].value = 12.0f; | |||
| scalePoints[12].label = "12"; | |||
| scalePoints[13].value = 13.0f; | |||
| scalePoints[13].label = "13"; | |||
| scalePoints[14].value = 14.0f; | |||
| scalePoints[14].label = "14"; | |||
| scalePoints[15].value = 15.0f; | |||
| scalePoints[15].label = "15"; | |||
| scalePoints[16].value = 16.0f; | |||
| scalePoints[16].label = "16"; | |||
| break; | |||
| } | |||
| param.hints = static_cast<NativeParameterHints>(hints); | |||
| return ¶m; | |||
| } | |||
| float getParameterValue(const uint32_t index) const override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kNumParameters, 0.0f); | |||
| return fParameters[index]; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin state calls | |||
| void setParameterValue(const uint32_t index, const float value) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kNumParameters,); | |||
| fParameters[index] = value; | |||
| Retuner* const retuner(jclient->retuner()); | |||
| switch (index) | |||
| { | |||
| case kParameterR_TUNE: | |||
| retuner->set_refpitch(value); | |||
| break; | |||
| case kParameterR_FILT: | |||
| retuner->set_corrfilt(value); | |||
| break; | |||
| case kParameterR_BIAS: | |||
| retuner->set_notebias(value); | |||
| break; | |||
| case kParameterR_CORR: | |||
| retuner->set_corrgain(value); | |||
| break; | |||
| case kParameterR_OFFS: | |||
| retuner->set_corroffs(value); | |||
| break; | |||
| case kParameterM_CHANNEL: | |||
| jclient->set_midichan(value-1.0f); | |||
| break; | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin process calls | |||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, | |||
| const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override | |||
| { | |||
| if (! fJackClient.active) | |||
| { | |||
| FloatVectorOperations::clear(outBuffer[0], static_cast<int>(frames)); | |||
| return; | |||
| } | |||
| fJackClient.portsAudioIn [0].buffer.audio = inBuffer [0]; | |||
| fJackClient.portsAudioOut[0].buffer.audio = outBuffer[0]; | |||
| fJackClient.portsMidiIn[0].buffer.midi.count = midiEventCount; | |||
| fJackClient.portsMidiIn[0].buffer.midi.events = const_cast<NativeMidiEvent*>(midiEvents); | |||
| fJackClient.processCallback(frames, fJackClient.processPtr); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin UI calls | |||
| void uiShow(const bool show) override | |||
| { | |||
| if (show) | |||
| { | |||
| if (display != nullptr) | |||
| return; | |||
| display = new X_display(nullptr); | |||
| if (display->dpy() == nullptr) | |||
| return hostUiUnavailable(); | |||
| styles_init(display, &xresman, getResourceDir()); | |||
| rootwin = new X_rootwin(display); | |||
| mainwin = new Mainwin(rootwin, &xresman, 0, 0, jclient, this); | |||
| rootwin->handle_event(); | |||
| mainwin->x_set_title(getUiName()); | |||
| handler = new X_handler(display, mainwin, EV_X11); | |||
| if (const uintptr_t winId = getUiParentId()) | |||
| XSetTransientForHint(display->dpy(), mainwin->win(), static_cast<Window>(winId)); | |||
| handler->next_event(); | |||
| XFlush(display->dpy()); | |||
| handlerThread.setupAndRun(handler, rootwin, mainwin); | |||
| } | |||
| else | |||
| { | |||
| if (handlerThread.isThreadRunning()) | |||
| handlerThread.stopThread(); | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| display = nullptr; | |||
| } | |||
| } | |||
| void uiIdle() override | |||
| { | |||
| if (mainwin == nullptr) | |||
| return; | |||
| if (handlerThread.wasClosed()) | |||
| { | |||
| { | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| display = nullptr; | |||
| } | |||
| uiClosed(); | |||
| } | |||
| } | |||
| void uiSetParameterValue(const uint32_t index, const float value) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kNumParameters,); | |||
| if (mainwin == nullptr) | |||
| return; | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| if (index < kParameterNROTARY) | |||
| { | |||
| mainwin->_rotary[index]->set_value(value); | |||
| return; | |||
| } | |||
| if (index == kParameterM_CHANNEL) | |||
| { | |||
| mainwin->setchan_ui(value); | |||
| return; | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin dispatcher calls | |||
| void bufferSizeChanged(const uint32_t bufferSize) override | |||
| { | |||
| fJackClient.bufferSize = bufferSize; | |||
| } | |||
| void sampleRateChanged(const double sampleRate) override | |||
| { | |||
| fJackClient.sampleRate = sampleRate; | |||
| } | |||
| void uiNameChanged(const char* const uiName) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(uiName != nullptr && uiName[0] != '\0',); | |||
| if (mainwin == nullptr) | |||
| return; | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| mainwin->x_set_title(uiName); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Mainwin callbacks | |||
| void valueChangedCallback(uint index, float value) override | |||
| { | |||
| fParameters[index] = value; | |||
| uiParameterChanged(index, value); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| // Fake jack client | |||
| jack_client_t fJackClient; | |||
| // Zita stuff (core) | |||
| X_resman xresman; | |||
| ScopedPointer<Jclient> jclient; | |||
| ScopedPointer<X_display> display; | |||
| ScopedPointer<X_rootwin> rootwin; | |||
| ScopedPointer<Mainwin> mainwin; | |||
| ScopedPointer<X_handler> handler; | |||
| X_handler_thread<Mainwin> handlerThread; | |||
| float fParameters[kNumParameters]; | |||
| PluginClassEND(AT1Plugin) | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AT1Plugin) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor at1Desc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_MODULATOR, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ 1, | |||
| /* audioOuts */ 1, | |||
| /* midiIns */ 1, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ AT1Plugin::kNumParameters, | |||
| /* paramOuts */ 0, | |||
| /* name */ "AT1", | |||
| /* label */ "at1", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| PluginDescriptorFILL(AT1Plugin) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zita_at1(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zita_at1() | |||
| { | |||
| carla_register_native_plugin(&at1Desc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,140 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <cairo/cairo.h> | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <math.h> | |||
| #include "button.h" | |||
| namespace AT1 { | |||
| int PushButton::_keymod = 0; | |||
| int PushButton::_button = 0; | |||
| PushButton::PushButton (X_window *parent, | |||
| X_callback *cbobj, | |||
| ButtonImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cbind) : | |||
| X_window (parent, | |||
| image->_x0 + xp, image->_y0 + yp, | |||
| image->_dx, image->_dy, | |||
| image->_backg->pixel), | |||
| _cbobj (cbobj), | |||
| _cbind (cbind), | |||
| _image (image), | |||
| _state (0) | |||
| { | |||
| x_add_events (ExposureMask | ButtonPressMask | ButtonReleaseMask); | |||
| } | |||
| PushButton::~PushButton (void) | |||
| { | |||
| } | |||
| void PushButton::init (X_display *disp) | |||
| { | |||
| } | |||
| void PushButton::fini (void) | |||
| { | |||
| } | |||
| void PushButton::handle_event (XEvent *E) | |||
| { | |||
| switch (E->type) | |||
| { | |||
| case Expose: | |||
| render (); | |||
| break; | |||
| case ButtonPress: | |||
| bpress ((XButtonEvent *) E); | |||
| break; | |||
| case ButtonRelease: | |||
| brelse ((XButtonEvent *) E); | |||
| break; | |||
| default: | |||
| fprintf (stderr, "PushButton: event %d\n", E->type ); | |||
| } | |||
| } | |||
| void PushButton::bpress (XButtonEvent *E) | |||
| { | |||
| int r = 0; | |||
| if (E->button < 4) | |||
| { | |||
| _keymod = E->state; | |||
| _button = E->button; | |||
| r = handle_press (); | |||
| } | |||
| render (); | |||
| if (r) callback (r); | |||
| } | |||
| void PushButton::brelse (XButtonEvent *E) | |||
| { | |||
| int r = 0; | |||
| if (E->button < 4) | |||
| { | |||
| _keymod = E->state; | |||
| _button = E->button; | |||
| r = handle_relse (); | |||
| } | |||
| render (); | |||
| if (r) callback (r); | |||
| } | |||
| void PushButton::set_state (int s) | |||
| { | |||
| if (_state != s) | |||
| { | |||
| _state = s; | |||
| render (); | |||
| } | |||
| } | |||
| void PushButton::render (void) | |||
| { | |||
| XPutImage (dpy (), win (), dgc (), _image->_ximage, | |||
| _image->_x0, _image->_y0 + _state * _image->_dy, 0, 0, _image->_dx, _image->_dy); | |||
| } | |||
| } | |||
| @@ -0,0 +1,97 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __BUTTON_H | |||
| #define __BUTTON_H | |||
| #include <cairo/cairo.h> | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <clxclient.h> | |||
| namespace AT1 { | |||
| class ButtonImg | |||
| { | |||
| public: | |||
| XftColor *_backg; | |||
| XImage *_ximage; | |||
| int _x0; | |||
| int _y0; | |||
| int _dx; | |||
| int _dy; | |||
| }; | |||
| class PushButton : public X_window | |||
| { | |||
| public: | |||
| PushButton (X_window *parent, | |||
| X_callback *cbobj, | |||
| ButtonImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cbind = 0); | |||
| virtual ~PushButton (void); | |||
| enum { NOP = 100, PRESS, RELSE }; | |||
| int cbind (void) { return _cbind; } | |||
| int state (void) { return _state; } | |||
| virtual void set_state (int s); | |||
| static void init (X_display *disp); | |||
| static void fini (void); | |||
| protected: | |||
| X_callback *_cbobj; | |||
| int _cbind; | |||
| ButtonImg *_image; | |||
| int _state; | |||
| void render (void); | |||
| void callback (int k) { _cbobj->handle_callb (k, this, 0); } | |||
| private: | |||
| void handle_event (XEvent *E); | |||
| void bpress (XButtonEvent *E); | |||
| void brelse (XButtonEvent *E); | |||
| virtual int handle_press (void) = 0; | |||
| virtual int handle_relse (void) = 0; | |||
| static int _keymod; | |||
| static int _button; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,32 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __GLOBAL_H | |||
| #define __GLOBAL_H | |||
| #define PROGNAME "zita-at1" | |||
| #define EV_X11 16 | |||
| #define EV_EXIT 31 | |||
| #endif | |||
| @@ -0,0 +1,186 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2014 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <math.h> | |||
| #include "guiclass.h" | |||
| namespace AT1 { | |||
| int Pbutt0::handle_press (void) | |||
| { | |||
| _state |= 2; | |||
| return PRESS; | |||
| } | |||
| int Pbutt0::handle_relse (void) | |||
| { | |||
| _state &= ~2; | |||
| return NOP; | |||
| } | |||
| int Pbutt1::handle_press (void) | |||
| { | |||
| _state ^= 1; | |||
| return PRESS; | |||
| } | |||
| int Pbutt1::handle_relse (void) | |||
| { | |||
| return NOP; | |||
| } | |||
| Rlinctl::Rlinctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| int cbind, | |||
| RotaryGeom *rgeom, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini) : | |||
| RotaryCtl (parent, cbobj, cbind, rgeom, xp, yp), | |||
| _cm (cm), | |||
| _dd (dd), | |||
| _vmin (vmin), | |||
| _vmax (vmax), | |||
| _form (0) | |||
| { | |||
| _count = -1; | |||
| set_value (vini); | |||
| } | |||
| void Rlinctl::get_string (char *p, int n) | |||
| { | |||
| if (_form) snprintf (p, n, _form, _value); | |||
| else *p = 0; | |||
| } | |||
| void Rlinctl::set_value (double v) | |||
| { | |||
| set_count ((int) floor (_cm * (v - _vmin) / (_vmax - _vmin) + 0.5)); | |||
| render (); | |||
| } | |||
| int Rlinctl::handle_button (void) | |||
| { | |||
| return PRESS; | |||
| } | |||
| int Rlinctl::handle_motion (int dx, int dy) | |||
| { | |||
| return set_count (_rcount + dx - dy); | |||
| } | |||
| int Rlinctl::handle_mwheel (int dw) | |||
| { | |||
| if (! (_keymod & ShiftMask)) dw *= _dd; | |||
| return set_count (_count + dw); | |||
| } | |||
| int Rlinctl::set_count (int u) | |||
| { | |||
| if (u < 0) u= 0; | |||
| if (u > _cm) u = _cm; | |||
| if (u != _count) | |||
| { | |||
| _count = u; | |||
| _value = _vmin + u * (_vmax - _vmin) / _cm; | |||
| _angle = 270.0 * ((double) u / _cm - 0.5); | |||
| return DELTA; | |||
| } | |||
| return 0; | |||
| } | |||
| Rlogctl::Rlogctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| int cbind, | |||
| RotaryGeom *rgeom, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini) : | |||
| RotaryCtl (parent, cbobj, cbind, rgeom, xp, yp), | |||
| _cm (cm), | |||
| _dd (dd), | |||
| _form (0) | |||
| { | |||
| _count = -1; | |||
| _vmin = log (vmin); | |||
| _vmax = log (vmax); | |||
| set_value (vini); | |||
| } | |||
| void Rlogctl::get_string (char *p, int n) | |||
| { | |||
| if (_form) snprintf (p, n, _form, _value); | |||
| else *p = 0; | |||
| } | |||
| void Rlogctl::set_value (double v) | |||
| { | |||
| set_count ((int) floor (_cm * (log (v) - _vmin) / (_vmax - _vmin) + 0.5)); | |||
| render (); | |||
| } | |||
| int Rlogctl::handle_button (void) | |||
| { | |||
| return PRESS; | |||
| } | |||
| int Rlogctl::handle_motion (int dx, int dy) | |||
| { | |||
| return set_count (_rcount + dx - dy); | |||
| } | |||
| int Rlogctl::handle_mwheel (int dw) | |||
| { | |||
| if (! (_keymod & ShiftMask)) dw *= _dd; | |||
| return set_count (_count + dw); | |||
| } | |||
| int Rlogctl::set_count (int u) | |||
| { | |||
| if (u < 0) u= 0; | |||
| if (u > _cm) u = _cm; | |||
| if (u != _count) | |||
| { | |||
| _count = u; | |||
| _value = exp (_vmin + u * (_vmax - _vmin) / _cm); | |||
| _angle = 270.0 * ((double) u / _cm - 0.5); | |||
| return DELTA; | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,145 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2014 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __GUICLASS_H | |||
| #define __GUICLASS_H | |||
| #include "button.h" | |||
| #include "rotary.h" | |||
| namespace AT1 { | |||
| class Pbutt0 : public PushButton | |||
| { | |||
| public: | |||
| Pbutt0 (X_window *parent, | |||
| X_callback *cbobj, | |||
| ButtonImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cbind = 0) : | |||
| PushButton (parent, cbobj, image, xp, yp, cbind) | |||
| { | |||
| } | |||
| private: | |||
| virtual int handle_press (void); | |||
| virtual int handle_relse (void); | |||
| }; | |||
| class Pbutt1 : public PushButton | |||
| { | |||
| public: | |||
| Pbutt1 (X_window *parent, | |||
| X_callback *cbobj, | |||
| ButtonImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cbind = 0) : | |||
| PushButton (parent, cbobj, image, xp, yp, cbind) | |||
| { | |||
| } | |||
| private: | |||
| virtual int handle_press (void); | |||
| virtual int handle_relse (void); | |||
| }; | |||
| class Rlinctl : public RotaryCtl | |||
| { | |||
| public: | |||
| Rlinctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| int cbind, | |||
| RotaryGeom *rgeom, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini); | |||
| virtual void set_value (double v); | |||
| virtual void get_string (char *p, int n); | |||
| private: | |||
| virtual int handle_button (void); | |||
| virtual int handle_motion (int dx, int dy); | |||
| virtual int handle_mwheel (int dw); | |||
| int set_count (int u); | |||
| int _cm; | |||
| int _dd; | |||
| double _vmin; | |||
| double _vmax; | |||
| const char *_form; | |||
| }; | |||
| class Rlogctl : public RotaryCtl | |||
| { | |||
| public: | |||
| Rlogctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| int cbind, | |||
| RotaryGeom *rgeom, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini); | |||
| virtual void set_value (double v); | |||
| virtual void get_string (char *p, int n); | |||
| private: | |||
| virtual int handle_button (void); | |||
| virtual int handle_motion (int dx, int dy); | |||
| virtual int handle_mwheel (int dw); | |||
| int set_count (int u); | |||
| int _cm; | |||
| int _dd; | |||
| double _vmin; | |||
| double _vmax; | |||
| const char *_form; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,162 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ----------------------------------------------------------------------- | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include "jclient.h" | |||
| #include "global.h" | |||
| namespace AT1 { | |||
| Jclient::Jclient (const char *jname, jack_client_t *jclient) : | |||
| A_thread ("jclient"), | |||
| _jack_client (jclient), | |||
| _active (false), | |||
| _jname (0) | |||
| { | |||
| init_jack (jname); | |||
| } | |||
| Jclient::~Jclient (void) | |||
| { | |||
| if (_jack_client) close_jack (); | |||
| } | |||
| void Jclient::init_jack (const char *jname) | |||
| { | |||
| jack_on_shutdown (_jack_client, jack_static_shutdown, (void *) this); | |||
| jack_set_process_callback (_jack_client, jack_static_process, (void *) this); | |||
| if (jack_activate (_jack_client)) | |||
| { | |||
| fprintf(stderr, "Can't activate JACK.\n"); | |||
| exit (1); | |||
| } | |||
| _jname = jack_get_client_name (_jack_client); | |||
| _fsamp = jack_get_sample_rate (_jack_client); | |||
| _fsize = jack_get_buffer_size (_jack_client); | |||
| _ainp_port = jack_port_register (_jack_client, "in", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| _aout_port = jack_port_register (_jack_client, "out", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| _midi_port = jack_port_register (_jack_client, "pitch", JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0); | |||
| _retuner = new Retuner (_fsamp); | |||
| _notemask = 0xFFF; | |||
| _midichan = -1; | |||
| clr_midimask (); | |||
| _active = true; | |||
| } | |||
| void Jclient::close_jack () | |||
| { | |||
| jack_deactivate (_jack_client); | |||
| jack_client_close (_jack_client); | |||
| delete _retuner; | |||
| } | |||
| void Jclient::jack_static_shutdown (void *arg) | |||
| { | |||
| ((Jclient *) arg)->jack_shutdown (); | |||
| } | |||
| int Jclient::jack_static_process (jack_nframes_t nframes, void *arg) | |||
| { | |||
| return ((Jclient *) arg)->jack_process (nframes); | |||
| } | |||
| void Jclient::jack_shutdown (void) | |||
| { | |||
| send_event (EV_EXIT, 1); | |||
| } | |||
| void Jclient::clr_midimask (void) | |||
| { | |||
| int i; | |||
| for (i = 0; i < 12; i++) _notes [i] = 0; | |||
| _midimask = 0; | |||
| } | |||
| void Jclient::midi_process (int nframes) | |||
| { | |||
| int i, b, n, t, v; | |||
| void *p; | |||
| jack_midi_event_t E; | |||
| p = jack_port_get_buffer (_midi_port, nframes); | |||
| i = 0; | |||
| while (jack_midi_event_get (&E, p, i) == 0) | |||
| { | |||
| t = E.buffer [0]; | |||
| n = E.buffer [1]; | |||
| v = E.buffer [2]; | |||
| if ((_midichan < 0) || ((t & 0x0F) == _midichan)) | |||
| { | |||
| switch (t & 0xF0) | |||
| { | |||
| case 0x80: | |||
| case 0x90: | |||
| if (v && (t & 0x10))_notes [n % 12] += 1; | |||
| else _notes [n % 12] -= 1; | |||
| break; | |||
| } | |||
| } | |||
| i++; | |||
| } | |||
| _midimask = 0; | |||
| for (i = 0, b = 1; i < 12; i++, b <<= 1) | |||
| { | |||
| if (_notes [i]) _midimask |= b; | |||
| } | |||
| } | |||
| int Jclient::jack_process (int nframes) | |||
| { | |||
| float *inpp; | |||
| float *outp; | |||
| if (!_active) return 0; | |||
| inpp = (float *) jack_port_get_buffer (_ainp_port, nframes); | |||
| outp = (float *) jack_port_get_buffer (_aout_port, nframes); | |||
| midi_process (nframes); | |||
| _retuner->set_notemask (_midimask ? _midimask : _notemask); | |||
| _retuner->process (nframes, inpp, outp); | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,82 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ----------------------------------------------------------------------- | |||
| #ifndef __JCLIENT_H | |||
| #define __JCLIENT_H | |||
| #include "CarlaNativeJack.h" | |||
| #include <clthreads.h> | |||
| #include "retuner.h" | |||
| namespace AT1 { | |||
| class Jclient : public A_thread | |||
| { | |||
| public: | |||
| Jclient (const char *jname, jack_client_t *jclient); | |||
| ~Jclient (void); | |||
| const char *jname (void) { return _jname; } | |||
| unsigned int fsize (void) const { return _fsize; } | |||
| unsigned int fsamp (void) const { return _fsamp; } | |||
| Retuner *retuner (void) { return _retuner; } | |||
| void set_notemask (int m) { _notemask = m; } | |||
| void set_midichan (int c) { _midichan = c; } | |||
| void clr_midimask (void); | |||
| int get_noteset (void) { return _retuner->get_noteset (); } | |||
| int get_midiset (void) { return _midimask; } | |||
| private: | |||
| virtual void thr_main (void) {} | |||
| void init_jack (const char *jname); | |||
| void close_jack (void); | |||
| void jack_shutdown (void); | |||
| int jack_process (int nframes); | |||
| void midi_process (int nframes); | |||
| jack_client_t *_jack_client; | |||
| jack_port_t *_ainp_port; | |||
| jack_port_t *_aout_port; | |||
| jack_port_t *_midi_port; | |||
| bool _active; | |||
| const char *_jname; | |||
| unsigned int _fsamp; | |||
| unsigned int _fsize; | |||
| Retuner *_retuner; | |||
| int _notes [12]; | |||
| int _notemask; | |||
| int _midimask; | |||
| int _midichan; | |||
| static void jack_static_shutdown (void *arg); | |||
| static int jack_static_process (jack_nframes_t nframes, void *arg); | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,359 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2014 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <math.h> | |||
| #include "styles.h" | |||
| #include "global.h" | |||
| #include "mainwin.h" | |||
| namespace AT1 { | |||
| Mainwin::Mainwin (X_rootwin *parent, X_resman *xres, int xp, int yp, Jclient *jclient, ValueChangedCallback* valuecb) : | |||
| A_thread ("Main"), | |||
| X_window (parent, xp, yp, XSIZE, YSIZE, XftColors [C_MAIN_BG]->pixel), | |||
| _stop (false), | |||
| _xres (xres), | |||
| _jclient (jclient), | |||
| _valuecb (valuecb) | |||
| { | |||
| X_hints H; | |||
| char s [256]; | |||
| int i, j, x, y; | |||
| _atom = XInternAtom (dpy (), "WM_DELETE_WINDOW", True); | |||
| XSetWMProtocols (dpy (), win (), &_atom, 1); | |||
| _atom = XInternAtom (dpy (), "WM_PROTOCOLS", True); | |||
| sprintf (s, "%s", jclient->jname ()); | |||
| x_set_title (s); | |||
| H.position (xp, yp); | |||
| H.minsize (XSIZE, YSIZE); | |||
| H.maxsize (XSIZE, YSIZE); | |||
| H.rname (xres->rname ()); | |||
| H.rclas (xres->rclas ()); | |||
| x_apply (&H); | |||
| x = 20; | |||
| _bmidi = new Pbutt0 (this, this, &b_midi_img, x, 12, B_MIDI); | |||
| _bmidi->x_map (); | |||
| bstyle1.size.x = 50; | |||
| bstyle1.size.y = 20; | |||
| _bchan = new X_tbutton (this, this, &bstyle1, x - 5, 40, "Omni", 0, B_CHAN); | |||
| _bchan->x_map (); | |||
| _midich = 0; | |||
| x = 100; | |||
| y = 23; | |||
| _tmeter = new Tmeter (this, x - 20, 53); | |||
| _tmeter->x_map (); | |||
| for (i = j = 0; i < 12; i++, j++) | |||
| { | |||
| _bnote [i] = new Pbutt1 (this, this, &b_note_img, x, y, i); | |||
| _bnote [i]->set_state (1); | |||
| _bnote [i]->x_map (); | |||
| if (j == 4) | |||
| { | |||
| x += 20; | |||
| j++; | |||
| } | |||
| else | |||
| { | |||
| x += 10; | |||
| if (j & 1) y += 18; | |||
| else y -= 18; | |||
| } | |||
| } | |||
| RotaryCtl::init (disp ()); | |||
| x = 270; | |||
| _rotary [R_TUNE] = new Rlinctl (this, this, R_TUNE, &r_tune_geom, x, 0, 400, 5, 400.0, 480.0, 440.0); | |||
| _rotary [R_BIAS] = new Rlinctl (this, this, R_BIAS, &r_bias_geom, x, 0, 270, 5, 0.0, 1.0, 0.5); | |||
| _rotary [R_FILT] = new Rlogctl (this, this, R_FILT, &r_filt_geom, x, 0, 200, 5, 0.50, 0.02, 0.1); | |||
| _rotary [R_CORR] = new Rlinctl (this, this, R_CORR, &r_corr_geom, x, 0, 270, 5, 0.0, 1.0, 1.0); | |||
| _rotary [R_OFFS] = new Rlinctl (this, this, R_OFFS, &r_offs_geom, x, 0, 400, 10, -2.0, 2.0, 0.0); | |||
| for (i = 0; i < NROTARY; i++) _rotary [i]->x_map (); | |||
| _textln = new X_textip (this, 0, &tstyle1, 0, 0, 50, 15, 15); | |||
| _textln->set_align (0); | |||
| _ttimer = 0; | |||
| _notes = 0xFFF; | |||
| x_add_events (ExposureMask); | |||
| x_map (); | |||
| set_time (0); | |||
| inc_time (500000); | |||
| } | |||
| Mainwin::~Mainwin (void) | |||
| { | |||
| RotaryCtl::fini (); | |||
| } | |||
| int Mainwin::process (void) | |||
| { | |||
| int e; | |||
| if (_stop) handle_stop (); | |||
| e = get_event_timed (); | |||
| switch (e) | |||
| { | |||
| case EV_TIME: | |||
| handle_time (); | |||
| break; | |||
| } | |||
| return e; | |||
| } | |||
| void Mainwin::setchan_ui (int chan) | |||
| { | |||
| char s [16]; | |||
| _midich = chan; | |||
| if (_midich) | |||
| { | |||
| sprintf (s, "Ch %d\n", _midich); | |||
| _bchan->set_text (s, 0); | |||
| } | |||
| else _bchan->set_text ("Omni", 0); | |||
| } | |||
| void Mainwin::handle_event (XEvent *E) | |||
| { | |||
| switch (E->type) | |||
| { | |||
| case Expose: | |||
| expose ((XExposeEvent *) E); | |||
| break; | |||
| case ClientMessage: | |||
| clmesg ((XClientMessageEvent *) E); | |||
| break; | |||
| } | |||
| } | |||
| void Mainwin::expose (XExposeEvent *E) | |||
| { | |||
| if (E->count) return; | |||
| redraw (); | |||
| } | |||
| void Mainwin::clmesg (XClientMessageEvent *E) | |||
| { | |||
| if (E->message_type == _atom) _stop = true; | |||
| } | |||
| void Mainwin::handle_time (void) | |||
| { | |||
| int i, k, s; | |||
| float v; | |||
| v = _jclient->retuner ()->get_error (); | |||
| _tmeter->update (v, v); | |||
| k = _jclient->retuner ()->get_noteset (); | |||
| for (i = 0; i < 12; i++) | |||
| { | |||
| s = _bnote [i]->state (); | |||
| if (k & 1) s |= 2; | |||
| else s &= ~2; | |||
| _bnote [i]->set_state (s); | |||
| k >>= 1; | |||
| } | |||
| k = _jclient->get_midiset(); | |||
| if (k) _bmidi->set_state (_bmidi->state () | 1); | |||
| else _bmidi->set_state (_bmidi->state () & ~1); | |||
| if (_ttimer) | |||
| { | |||
| if (--_ttimer == 0) _textln->x_unmap (); | |||
| } | |||
| inc_time (50000); | |||
| XFlush (dpy ()); | |||
| } | |||
| void Mainwin::handle_stop (void) | |||
| { | |||
| put_event (EV_EXIT, 1); | |||
| } | |||
| void Mainwin::handle_callb (int type, X_window *W, XEvent *E) | |||
| { | |||
| PushButton *B; | |||
| RotaryCtl *R; | |||
| int k; | |||
| float v; | |||
| switch (type) | |||
| { | |||
| case X_callback::BUTTON | X_button::PRESS: | |||
| { | |||
| X_button *Z = (X_button *) W; | |||
| XButtonEvent *X = (XButtonEvent *) E; | |||
| switch (Z->cbid ()) | |||
| { | |||
| case B_CHAN: | |||
| switch (X->button) | |||
| { | |||
| case 1: | |||
| case 4: | |||
| setchan (1); | |||
| break; | |||
| case 3: | |||
| case 5: | |||
| setchan (-1); | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| case PushButton::PRESS: | |||
| B = (PushButton *) W; | |||
| k = B->cbind (); | |||
| if (k < B_MIDI) | |||
| { | |||
| k = 1 << k; | |||
| if (B->state () & 1) _notes |= k; | |||
| else _notes &= ~k; | |||
| _jclient->set_notemask (_notes); | |||
| } | |||
| else if (k == B_MIDI) | |||
| { | |||
| _jclient->clr_midimask (); | |||
| } | |||
| break; | |||
| case RotaryCtl::PRESS: | |||
| R = (RotaryCtl *) W; | |||
| k = R->cbind (); | |||
| switch (k) | |||
| { | |||
| case R_TUNE: | |||
| case R_OFFS: | |||
| showval (k); | |||
| break; | |||
| } | |||
| break; | |||
| case RotaryCtl::DELTA: | |||
| R = (RotaryCtl *) W; | |||
| k = R->cbind (); | |||
| switch (k) | |||
| { | |||
| case R_TUNE: | |||
| v = _rotary [R_TUNE]->value (); | |||
| _jclient->retuner ()->set_refpitch (v); | |||
| _valuecb->valueChangedCallback (R_TUNE, v); | |||
| showval (k); | |||
| break; | |||
| case R_BIAS: | |||
| v = _rotary [R_BIAS]->value (); | |||
| _jclient->retuner ()->set_notebias (v); | |||
| _valuecb->valueChangedCallback (R_BIAS, v); | |||
| break; | |||
| case R_FILT: | |||
| v = _rotary [R_FILT]->value (); | |||
| _jclient->retuner ()->set_corrfilt (v); | |||
| _valuecb->valueChangedCallback (R_FILT, v); | |||
| break; | |||
| case R_CORR: | |||
| v = _rotary [R_CORR]->value (); | |||
| _jclient->retuner ()->set_corrgain (v); | |||
| _valuecb->valueChangedCallback (R_CORR, v); | |||
| break; | |||
| case R_OFFS: | |||
| v = _rotary [R_OFFS]->value (); | |||
| _jclient->retuner ()->set_corroffs (v); | |||
| _valuecb->valueChangedCallback (R_OFFS, v); | |||
| showval (k); | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| void Mainwin::setchan (int d) | |||
| { | |||
| char s [16]; | |||
| _midich += d; | |||
| if (_midich < 0) _midich = 0; | |||
| if (_midich > 16) _midich = 16; | |||
| if (_midich) | |||
| { | |||
| sprintf (s, "Ch %d\n", _midich); | |||
| _bchan->set_text (s, 0); | |||
| } | |||
| else _bchan->set_text ("Omni", 0); | |||
| _jclient->set_midichan (_midich - 1); | |||
| _valuecb->valueChangedCallback (NROTARY, _midich); | |||
| } | |||
| void Mainwin::showval (int k) | |||
| { | |||
| char s [16]; | |||
| switch (k) | |||
| { | |||
| case R_TUNE: | |||
| sprintf (s, "%5.1lf", _rotary [R_TUNE]->value ()); | |||
| _textln->x_move (222, 58); | |||
| break; | |||
| case R_OFFS: | |||
| sprintf (s, "%5.2lf", _rotary [R_OFFS]->value ()); | |||
| _textln->x_move (463, 58); | |||
| break; | |||
| } | |||
| _textln->set_text (s); | |||
| _textln->x_map (); | |||
| _ttimer = 40; | |||
| } | |||
| void Mainwin::redraw (void) | |||
| { | |||
| int x; | |||
| x = 80; | |||
| XPutImage (dpy (), win (), dgc (), notesect_img, 0, 0, x, 0, 190, 75); | |||
| x += 190; | |||
| XPutImage (dpy (), win (), dgc (), ctrlsect_img, 0, 0, x, 0, 315, 75); | |||
| } | |||
| } | |||
| @@ -0,0 +1,99 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2014 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __MAINWIN_H | |||
| #define __MAINWIN_H | |||
| #include <clxclient.h> | |||
| #include "guiclass.h" | |||
| #include "jclient.h" | |||
| #include "tmeter.h" | |||
| #include "global.h" | |||
| class AT1Plugin; | |||
| namespace AT1 { | |||
| class Mainwin : public A_thread, public X_window, public X_callback | |||
| { | |||
| public: | |||
| struct ValueChangedCallback { | |||
| virtual ~ValueChangedCallback() {} | |||
| virtual void valueChangedCallback(uint, float) = 0; | |||
| }; | |||
| enum { XSIZE = 600, YSIZE = 75 }; | |||
| Mainwin (X_rootwin *parent, X_resman *xres, int xp, int yp, Jclient *jclient, ValueChangedCallback* valuecb); | |||
| ~Mainwin (void); | |||
| Mainwin (const Mainwin&); | |||
| Mainwin& operator=(const Mainwin&); | |||
| void stop (void) { _stop = true; } | |||
| int process (void); | |||
| void setchan_ui (int chan); | |||
| private: | |||
| enum { B_MIDI = 12, B_CHAN = 13 }; | |||
| enum { R_TUNE, R_FILT, R_BIAS, R_CORR, R_OFFS, NROTARY }; | |||
| virtual void thr_main (void) {} | |||
| void handle_time (void); | |||
| void handle_stop (void); | |||
| void handle_event (XEvent *); | |||
| void handle_callb (int type, X_window *W, XEvent *E); | |||
| void showval (int k); | |||
| void expose (XExposeEvent *E); | |||
| void clmesg (XClientMessageEvent *E); | |||
| void redraw (void); | |||
| void setchan (int d); | |||
| Atom _atom; | |||
| bool _stop; | |||
| bool _ambis; | |||
| X_resman *_xres; | |||
| Jclient *_jclient; | |||
| int _notes; | |||
| PushButton *_bmidi; | |||
| PushButton *_bnote [12]; | |||
| RotaryCtl *_rotary [NROTARY]; | |||
| Tmeter *_tmeter; | |||
| X_textip *_textln; | |||
| X_tbutton *_bchan; | |||
| int _midich; | |||
| int _ttimer; | |||
| ValueChangedCallback* _valuecb; | |||
| friend class ::AT1Plugin; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,129 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2007-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <png.h> | |||
| #include <clxclient.h> | |||
| namespace AT1 { | |||
| XImage *png2img (const char *file, X_display *disp, XftColor *bgnd) | |||
| { | |||
| FILE *F; | |||
| png_byte hdr [8]; | |||
| png_structp png_ptr; | |||
| png_infop png_info; | |||
| const unsigned char **data, *p; | |||
| int r, dx, dy, x, y, dp; | |||
| float vr, vg, vb, va, br, bg, bb; | |||
| unsigned long mr, mg, mb, pix; | |||
| XImage *image; | |||
| F = fopen (file, "r"); | |||
| if (!F) | |||
| { | |||
| fprintf (stderr, "Can't open '%s'\n", file); | |||
| return 0; | |||
| } | |||
| r = fread (hdr, 8, 1, F ); | |||
| if ((r != 1) || png_sig_cmp (hdr, 0, 8)) | |||
| { | |||
| fprintf (stderr, "'%s' is not a PNG file\n", file); | |||
| return 0; | |||
| } | |||
| fseek (F, 0, SEEK_SET); | |||
| png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); | |||
| if (! png_ptr) | |||
| { | |||
| fclose (F); | |||
| return 0; | |||
| } | |||
| png_info = png_create_info_struct (png_ptr); | |||
| if (! png_info) | |||
| { | |||
| png_destroy_read_struct (&png_ptr, 0, 0); | |||
| fclose (F); | |||
| return 0; | |||
| } | |||
| if (setjmp (png_jmpbuf (png_ptr))) | |||
| { | |||
| png_destroy_read_struct (&png_ptr, &png_info, 0); | |||
| fclose (F); | |||
| fprintf (stderr, "png:longjmp()\n"); | |||
| return 0; | |||
| } | |||
| png_init_io (png_ptr, F); | |||
| png_read_png (png_ptr, png_info, | |||
| PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, | |||
| 0); | |||
| dx = png_get_image_width (png_ptr, png_info); | |||
| dy = png_get_image_height (png_ptr, png_info); | |||
| dp = (png_get_color_type (png_ptr, png_info) & PNG_COLOR_MASK_ALPHA) ? 4 : 3; | |||
| data = (const unsigned char **)(png_get_rows (png_ptr, png_info)); | |||
| image = XCreateImage (disp->dpy (), | |||
| disp->dvi (), | |||
| DefaultDepth (disp->dpy (), disp->dsn ()), | |||
| ZPixmap, 0, 0, dx, dy, 32, 0); | |||
| image->data = new char [image->height * image->bytes_per_line]; | |||
| mr = image->red_mask; | |||
| mg = image->green_mask; | |||
| mb = image->blue_mask; | |||
| vr = mr / 255.0f; | |||
| vg = mg / 255.0f; | |||
| vb = mb / 255.0f; | |||
| if (bgnd) | |||
| { | |||
| br = bgnd->color.red >> 8; | |||
| bg = bgnd->color.green >> 8; | |||
| bb = bgnd->color.blue >> 8; | |||
| } | |||
| else br = bg = bb = 0; | |||
| for (y = 0; y < dy; y++) | |||
| { | |||
| p = data [y]; | |||
| for (x = 0; x < dx; x++) | |||
| { | |||
| va = (dp == 4) ? (p [3] / 255.0f) : 1; | |||
| pix = ((unsigned long)((p [0] * va + (1 - va) * br) * vr) & mr) | |||
| | ((unsigned long)((p [1] * va + (1 - va) * bg) * vg) & mg) | |||
| | ((unsigned long)((p [2] * va + (1 - va) * bb) * vb) & mb); | |||
| XPutPixel (image, x, y, pix); | |||
| p += dp; | |||
| } | |||
| } | |||
| png_destroy_read_struct (&png_ptr, &png_info, 0); | |||
| fclose (F); | |||
| return image; | |||
| } | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2007-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __PNG2IMG_H | |||
| #define __PNG2IMG_H | |||
| #include <clxclient.h> | |||
| namespace AT1 { | |||
| extern XImage *png2img (const char *file, X_display *disp, XftColor *bgnd); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,449 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2009-2011 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ----------------------------------------------------------------------- | |||
| #include <stdlib.h> | |||
| #include <string.h> | |||
| #include <stdio.h> | |||
| #include <math.h> | |||
| #include "retuner.h" | |||
| namespace AT1 { | |||
| Retuner::Retuner (int fsamp) : | |||
| _fsamp (fsamp), | |||
| _refpitch (440.0f), | |||
| _notebias (0.0f), | |||
| _corrfilt (1.0f), | |||
| _corrgain (1.0f), | |||
| _corroffs (0.0f), | |||
| _notemask (0xFFF) | |||
| { | |||
| int i, h; | |||
| float t, x, y; | |||
| if (_fsamp < 64000) | |||
| { | |||
| // At 44.1 and 48 kHz resample to double rate. | |||
| _upsamp = true; | |||
| _ipsize = 4096; | |||
| _fftlen = 2048; | |||
| _frsize = 128; | |||
| _resampler.setup (1, 2, 1, 32); // 32 is medium quality. | |||
| // Prefeed some input samples to remove delay. | |||
| _resampler.inp_count = _resampler.filtlen () - 1; | |||
| _resampler.inp_data = 0; | |||
| _resampler.out_count = 0; | |||
| _resampler.out_data = 0; | |||
| _resampler.process (); | |||
| } | |||
| else if (_fsamp < 128000) | |||
| { | |||
| // 88.2 or 96 kHz. | |||
| _upsamp = false; | |||
| _ipsize = 4096; | |||
| _fftlen = 4096; | |||
| _frsize = 256; | |||
| } | |||
| else | |||
| { | |||
| // 192 kHz, double time domain buffers sizes. | |||
| _upsamp = false; | |||
| _ipsize = 8192; | |||
| _fftlen = 8192; | |||
| _frsize = 512; | |||
| } | |||
| // Accepted correlation peak range, corresponding to 60..1200 Hz. | |||
| _ifmin = _fsamp / 1200; | |||
| _ifmax = _fsamp / 60; | |||
| // Various buffers | |||
| _ipbuff = new float[_ipsize + 3]; // Resampled or filtered input | |||
| _xffunc = new float[_frsize]; // Crossfade function | |||
| _fftTwind = (float *) fftwf_malloc (_fftlen * sizeof (float)); // Window function | |||
| _fftWcorr = (float *) fftwf_malloc (_fftlen * sizeof (float)); // Autocorrelation of window | |||
| _fftTdata = (float *) fftwf_malloc (_fftlen * sizeof (float)); // Time domain data for FFT | |||
| _fftFdata = (fftwf_complex *) fftwf_malloc ((_fftlen / 2 + 1) * sizeof (fftwf_complex)); | |||
| // FFTW3 plans | |||
| _fwdplan = fftwf_plan_dft_r2c_1d (_fftlen, _fftTdata, _fftFdata, FFTW_ESTIMATE); | |||
| _invplan = fftwf_plan_dft_c2r_1d (_fftlen, _fftFdata, _fftTdata, FFTW_ESTIMATE); | |||
| // Clear input buffer. | |||
| memset (_ipbuff, 0, (_ipsize + 1) * sizeof (float)); | |||
| // Create crossfade function, half of raised cosine. | |||
| for (i = 0; i < _frsize; i++) | |||
| { | |||
| _xffunc [i] = 0.5 * (1 - cosf (M_PI * i / _frsize)); | |||
| } | |||
| // Create window, raised cosine. | |||
| for (i = 0; i < _fftlen; i++) | |||
| { | |||
| _fftTwind [i] = 0.5 * (1 - cosf (2 * M_PI * i / _fftlen)); | |||
| } | |||
| // Compute window autocorrelation and normalise it. | |||
| fftwf_execute_dft_r2c (_fwdplan, _fftTwind, _fftFdata); | |||
| h = _fftlen / 2; | |||
| for (i = 0; i < h; i++) | |||
| { | |||
| x = _fftFdata [i][0]; | |||
| y = _fftFdata [i][1]; | |||
| _fftFdata [i][0] = x * x + y * y; | |||
| _fftFdata [i][1] = 0; | |||
| } | |||
| _fftFdata [h][0] = 0; | |||
| _fftFdata [h][1] = 0; | |||
| fftwf_execute_dft_c2r (_invplan, _fftFdata, _fftWcorr); | |||
| t = _fftWcorr [0]; | |||
| for (i = 0; i < _fftlen; i++) | |||
| { | |||
| _fftWcorr [i] /= t; | |||
| } | |||
| // Initialise all counters and other state. | |||
| _notebits = 0; | |||
| _lastnote = -1; | |||
| _count = 0; | |||
| _cycle = _frsize; | |||
| _error = 0.0f; | |||
| _ratio = 1.0f; | |||
| _xfade = false; | |||
| _ipindex = 0; | |||
| _frindex = 0; | |||
| _frcount = 0; | |||
| _rindex1 = _ipsize / 2; | |||
| _rindex2 = 0; | |||
| } | |||
| Retuner::~Retuner (void) | |||
| { | |||
| delete[] _ipbuff; | |||
| delete[] _xffunc; | |||
| fftwf_free (_fftTwind); | |||
| fftwf_free (_fftWcorr); | |||
| fftwf_free (_fftTdata); | |||
| fftwf_free (_fftFdata); | |||
| fftwf_destroy_plan (_fwdplan); | |||
| fftwf_destroy_plan (_invplan); | |||
| } | |||
| int Retuner::process (int nfram, float *inp, float *out) | |||
| { | |||
| int i, k, fi; | |||
| float ph, dp, r1, r2, dr, u1, u2, v; | |||
| // Pitch shifting is done by resampling the input at the | |||
| // required ratio, and eventually jumping forward or back | |||
| // by one or more pitch period(s). Processing is done in | |||
| // fragments of '_frsize' frames, and the decision to jump | |||
| // forward or back is taken at the start of each fragment. | |||
| // If a jump happens we crossfade over one fragment size. | |||
| // Every 4 fragments a new pitch estimate is made. Since | |||
| // _fftsize = 16 * _frsize, the estimation window moves | |||
| // by 1/4 of the FFT length. | |||
| fi = _frindex; // Write index in current fragment. | |||
| r1 = _rindex1; // Read index for current input frame. | |||
| r2 = _rindex2; // Second read index while crossfading. | |||
| // No assumptions are made about fragments being aligned | |||
| // with process() calls, so we may be in the middle of | |||
| // a fragment here. | |||
| while (nfram) | |||
| { | |||
| // Don't go past the end of the current fragment. | |||
| k = _frsize - fi; | |||
| if (nfram < k) k = nfram; | |||
| nfram -= k; | |||
| // At 44.1 and 48 kHz upsample by 2. | |||
| if (_upsamp) | |||
| { | |||
| _resampler.inp_count = k; | |||
| _resampler.inp_data = inp; | |||
| _resampler.out_count = 2 * k; | |||
| _resampler.out_data = _ipbuff + _ipindex; | |||
| _resampler.process (); | |||
| _ipindex += 2 * k; | |||
| } | |||
| // At higher sample rates apply lowpass filter. | |||
| else | |||
| { | |||
| // Not implemented yet, just copy. | |||
| memcpy (_ipbuff + _ipindex, inp, k * sizeof (float)); | |||
| _ipindex += k; | |||
| } | |||
| // Extra samples for interpolation. | |||
| _ipbuff [_ipsize + 0] = _ipbuff [0]; | |||
| _ipbuff [_ipsize + 1] = _ipbuff [1]; | |||
| _ipbuff [_ipsize + 2] = _ipbuff [2]; | |||
| inp += k; | |||
| if (_ipindex == _ipsize) _ipindex = 0; | |||
| // Process available samples. | |||
| dr = _ratio; | |||
| if (_upsamp) dr *= 2; | |||
| if (_xfade) | |||
| { | |||
| // Interpolate and crossfade. | |||
| while (k--) | |||
| { | |||
| i = (int) r1; | |||
| u1 = cubic (_ipbuff + i, r1 - i); | |||
| i = (int) r2; | |||
| u2 = cubic (_ipbuff + i, r2 - i); | |||
| v = _xffunc [fi++]; | |||
| *out++ = (1 - v) * u1 + v * u2; | |||
| r1 += dr; | |||
| if (r1 >= _ipsize) r1 -= _ipsize; | |||
| r2 += dr; | |||
| if (r2 >= _ipsize) r2 -= _ipsize; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| // Interpolation only. | |||
| fi += k; | |||
| while (k--) | |||
| { | |||
| i = (int) r1; | |||
| *out++ = cubic (_ipbuff + i, r1 - i); | |||
| r1 += dr; | |||
| if (r1 >= _ipsize) r1 -= _ipsize; | |||
| } | |||
| } | |||
| // If at end of fragment check for jump. | |||
| if (fi == _frsize) | |||
| { | |||
| fi = 0; | |||
| // Estimate the pitch every 4th fragment. | |||
| if (++_frcount == 4) | |||
| { | |||
| _frcount = 0; | |||
| findcycle (); | |||
| if (_cycle) | |||
| { | |||
| // If the pitch estimate succeeds, find the | |||
| // nearest note and required resampling ratio. | |||
| _count = 0; | |||
| finderror (); | |||
| } | |||
| else if (++_count > 5) | |||
| { | |||
| // If the pitch estimate fails, the current | |||
| // ratio is kept for 5 fragments. After that | |||
| // the signal is considered unvoiced and the | |||
| // pitch error is reset. | |||
| _count = 5; | |||
| _cycle = _frsize; | |||
| _error = 0; | |||
| } | |||
| else if (_count == 2) | |||
| { | |||
| // Bias is removed after two unvoiced fragments. | |||
| _lastnote = -1; | |||
| } | |||
| _ratio = powf (2.0f, _corroffs / 12.0f - _error * _corrgain); | |||
| } | |||
| // If the previous fragment was crossfading, | |||
| // the end of the new fragment that was faded | |||
| // in becomes the current read position. | |||
| if (_xfade) r1 = r2; | |||
| // A jump must correspond to an integer number | |||
| // of pitch periods, and to avoid reading outside | |||
| // the circular input buffer limits it must be at | |||
| // least one fragment size. | |||
| dr = _cycle * (int)(ceilf (_frsize / _cycle)); | |||
| dp = dr / _frsize; | |||
| ph = r1 - _ipindex; | |||
| if (ph < 0) ph += _ipsize; | |||
| if (_upsamp) | |||
| { | |||
| ph /= 2; | |||
| dr *= 2; | |||
| } | |||
| ph = ph / _frsize + 2 * _ratio - 10; | |||
| if (ph > 0.5f) | |||
| { | |||
| // Jump back by 'dr' frames and crossfade. | |||
| _xfade = true; | |||
| r2 = r1 - dr; | |||
| if (r2 < 0) r2 += _ipsize; | |||
| } | |||
| else if (ph + dp < 0.5f) | |||
| { | |||
| // Jump forward by 'dr' frames and crossfade. | |||
| _xfade = true; | |||
| r2 = r1 + dr; | |||
| if (r2 >= _ipsize) r2 -= _ipsize; | |||
| } | |||
| else _xfade = false; | |||
| } | |||
| } | |||
| // Save local state. | |||
| _frindex = fi; | |||
| _rindex1 = r1; | |||
| _rindex2 = r2; | |||
| return 0; | |||
| } | |||
| void Retuner::findcycle (void) | |||
| { | |||
| int d, h, i, j, k; | |||
| float f, m, t, x, y, z; | |||
| d = _upsamp ? 2 : 1; | |||
| h = _fftlen / 2; | |||
| j = _ipindex; | |||
| k = _ipsize - 1; | |||
| for (i = 0; i < _fftlen; i++) | |||
| { | |||
| _fftTdata [i] = _fftTwind [i] * _ipbuff [j & k]; | |||
| j += d; | |||
| } | |||
| fftwf_execute_dft_r2c (_fwdplan, _fftTdata, _fftFdata); | |||
| f = _fsamp / (_fftlen * 3e3f); | |||
| for (i = 0; i < h; i++) | |||
| { | |||
| x = _fftFdata [i][0]; | |||
| y = _fftFdata [i][1]; | |||
| m = i * f; | |||
| _fftFdata [i][0] = (x * x + y * y) / (1 + m * m); | |||
| _fftFdata [i][1] = 0; | |||
| } | |||
| _fftFdata [h][0] = 0; | |||
| _fftFdata [h][1] = 0; | |||
| fftwf_execute_dft_c2r (_invplan, _fftFdata, _fftTdata); | |||
| t = _fftTdata [0] + 0.1f; | |||
| for (i = 0; i < h; i++) _fftTdata [i] /= (t * _fftWcorr [i]); | |||
| x = _fftTdata [0]; | |||
| for (i = 4; i < _ifmax; i += 4) | |||
| { | |||
| y = _fftTdata [i]; | |||
| if (y > x) break; | |||
| x = y; | |||
| } | |||
| i -= 4; | |||
| _cycle = 0; | |||
| if (i >= _ifmax) return; | |||
| if (i < _ifmin) i = _ifmin; | |||
| x = _fftTdata [--i]; | |||
| y = _fftTdata [++i]; | |||
| m = 0; | |||
| j = 0; | |||
| while (i <= _ifmax) | |||
| { | |||
| t = y * _fftWcorr [i]; | |||
| z = _fftTdata [++i]; | |||
| if ((t > m) && (y >= x) && (y >= z) && (y > 0.8f)) | |||
| { | |||
| j = i - 1; | |||
| m = t; | |||
| } | |||
| x = y; | |||
| y = z; | |||
| } | |||
| if (j) | |||
| { | |||
| x = _fftTdata [j - 1]; | |||
| y = _fftTdata [j]; | |||
| z = _fftTdata [j + 1]; | |||
| _cycle = j + 0.5f * (x - z) / (z - 2 * y + x - 1e-9f); | |||
| } | |||
| } | |||
| void Retuner::finderror (void) | |||
| { | |||
| int i, m, im; | |||
| float a, am, d, dm, f; | |||
| if (!_notemask) | |||
| { | |||
| _error = 0; | |||
| _lastnote = -1; | |||
| return; | |||
| } | |||
| f = log2f (_fsamp / (_cycle * _refpitch)); | |||
| dm = 0; | |||
| am = 1; | |||
| im = -1; | |||
| for (i = 0, m = 1; i < 12; i++, m <<= 1) | |||
| { | |||
| if (_notemask & m) | |||
| { | |||
| d = f - (i - 9) / 12.0f; | |||
| d -= floorf (d + 0.5f); | |||
| a = fabsf (d); | |||
| if (i == _lastnote) a -= _notebias; | |||
| if (a < am) | |||
| { | |||
| am = a; | |||
| dm = d; | |||
| im = i; | |||
| } | |||
| } | |||
| } | |||
| if (_lastnote == im) | |||
| { | |||
| _error += _corrfilt * (dm - _error); | |||
| } | |||
| else | |||
| { | |||
| _error = dm; | |||
| _lastnote = im; | |||
| } | |||
| // For display only. | |||
| _notebits |= 1 << im; | |||
| } | |||
| float Retuner::cubic (float *v, float a) | |||
| { | |||
| float b, c; | |||
| b = 1 - a; | |||
| c = a * b; | |||
| return (1.0f + 1.5f * c) * (v[1] * b + v[2] * a) | |||
| - 0.5f * c * (v[0] * b + v[1] + v[2] + v[3] * a); | |||
| } | |||
| } | |||
| @@ -0,0 +1,133 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2009-2011 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ----------------------------------------------------------------------- | |||
| #ifndef __RETUNER_H | |||
| #define __RETUNER_H | |||
| #include <fftw3.h> | |||
| #include <zita-resampler/resampler.h> | |||
| namespace AT1 { | |||
| class Retuner | |||
| { | |||
| public: | |||
| Retuner (int fsamp); | |||
| ~Retuner (void); | |||
| int process (int nfram, float *inp, float *out); | |||
| void set_refpitch (float v) | |||
| { | |||
| _refpitch = v; | |||
| } | |||
| void set_notebias (float v) | |||
| { | |||
| _notebias = v / 13.0f; | |||
| } | |||
| void set_corrfilt (float v) | |||
| { | |||
| _corrfilt = (4 * _frsize) / (v * _fsamp); | |||
| } | |||
| void set_corrgain (float v) | |||
| { | |||
| _corrgain = v; | |||
| } | |||
| void set_corroffs (float v) | |||
| { | |||
| _corroffs = v; | |||
| } | |||
| void set_notemask (int k) | |||
| { | |||
| _notemask = k; | |||
| } | |||
| int get_noteset (void) | |||
| { | |||
| int k; | |||
| k = _notebits; | |||
| _notebits = 0; | |||
| return k; | |||
| } | |||
| float get_error (void) | |||
| { | |||
| return 12.0f * _error; | |||
| } | |||
| private: | |||
| void findcycle (void); | |||
| void finderror (void); | |||
| float cubic (float *v, float a); | |||
| int _fsamp; | |||
| int _ifmin; | |||
| int _ifmax; | |||
| bool _upsamp; | |||
| int _fftlen; | |||
| int _ipsize; | |||
| int _frsize; | |||
| int _ipindex; | |||
| int _frindex; | |||
| int _frcount; | |||
| float _refpitch; | |||
| float _notebias; | |||
| float _corrfilt; | |||
| float _corrgain; | |||
| float _corroffs; | |||
| int _notemask; | |||
| int _notebits; | |||
| int _lastnote; | |||
| int _count; | |||
| float _cycle; | |||
| float _error; | |||
| float _ratio; | |||
| float _phase; | |||
| bool _xfade; | |||
| float _rindex1; | |||
| float _rindex2; | |||
| float *_ipbuff; | |||
| float *_xffunc; | |||
| float *_fftTwind; | |||
| float *_fftWcorr; | |||
| float *_fftTdata; | |||
| fftwf_complex *_fftFdata; | |||
| fftwf_plan _fwdplan; | |||
| fftwf_plan _invplan; | |||
| Resampler _resampler; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,211 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2012 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <cairo/cairo.h> | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <math.h> | |||
| #include "rotary.h" | |||
| namespace AT1 { | |||
| cairo_t *RotaryCtl::_cairotype = 0; | |||
| cairo_surface_t *RotaryCtl::_cairosurf = 0; | |||
| int RotaryCtl::_wb_up = 4; | |||
| int RotaryCtl::_wb_dn = 5; | |||
| int RotaryCtl::_keymod = 0; | |||
| int RotaryCtl::_button = 0; | |||
| int RotaryCtl::_rcount = 0; | |||
| int RotaryCtl::_rx = 0; | |||
| int RotaryCtl::_ry = 0; | |||
| RotaryCtl::RotaryCtl (X_window *parent, | |||
| X_callback *cbobj, | |||
| int cbind, | |||
| RotaryGeom *rgeom, | |||
| int xp, | |||
| int yp) : | |||
| X_window (parent, | |||
| rgeom->_x0 + xp, rgeom->_y0 + yp, | |||
| rgeom->_dx, rgeom->_dy, | |||
| rgeom->_backg->pixel), | |||
| _cbobj (cbobj), | |||
| _cbind (cbind), | |||
| _rgeom (rgeom), | |||
| _state (0), | |||
| _count (0), | |||
| _value (0), | |||
| _angle (0) | |||
| { | |||
| x_add_events ( ExposureMask | |||
| | Button1MotionMask | ButtonPressMask | ButtonReleaseMask); | |||
| } | |||
| RotaryCtl::~RotaryCtl (void) | |||
| { | |||
| } | |||
| void RotaryCtl::init (X_display *disp) | |||
| { | |||
| _cairosurf = cairo_xlib_surface_create (disp->dpy (), 0, disp->dvi (), 50, 50); | |||
| _cairotype = cairo_create (_cairosurf); | |||
| } | |||
| void RotaryCtl::fini (void) | |||
| { | |||
| cairo_destroy (_cairotype); | |||
| cairo_surface_destroy (_cairosurf); | |||
| } | |||
| void RotaryCtl::handle_event (XEvent *E) | |||
| { | |||
| switch (E->type) | |||
| { | |||
| case Expose: | |||
| render (); | |||
| break; | |||
| case ButtonPress: | |||
| bpress ((XButtonEvent *) E); | |||
| break; | |||
| case ButtonRelease: | |||
| brelse ((XButtonEvent *) E); | |||
| break; | |||
| case MotionNotify: | |||
| motion ((XMotionEvent *) E); | |||
| break; | |||
| default: | |||
| fprintf (stderr, "RotaryCtl: event %d\n", E->type ); | |||
| } | |||
| } | |||
| void RotaryCtl::bpress (XButtonEvent *E) | |||
| { | |||
| int r = 0; | |||
| double d; | |||
| d = hypot (E->x - _rgeom->_xref, E->y - _rgeom->_yref); | |||
| if (d > _rgeom->_rad + 3) return; | |||
| _keymod = E->state; | |||
| if (E->button < 4) | |||
| { | |||
| _rx = E->x; | |||
| _ry = E->y; | |||
| _button = E->button; | |||
| r = handle_button (); | |||
| _rcount = _count; | |||
| } | |||
| else if (_button) return; | |||
| else if ((int)E->button == _wb_up) | |||
| { | |||
| r = handle_mwheel (1); | |||
| } | |||
| else if ((int)E->button == _wb_dn) | |||
| { | |||
| r = handle_mwheel (-1); | |||
| } | |||
| if (r) | |||
| { | |||
| callback (r); | |||
| render (); | |||
| } | |||
| } | |||
| void RotaryCtl::brelse (XButtonEvent *E) | |||
| { | |||
| if (_button == (int)E->button) | |||
| { | |||
| _button = 0; | |||
| callback (RELSE); | |||
| } | |||
| } | |||
| void RotaryCtl::motion (XMotionEvent *E) | |||
| { | |||
| int dx, dy, r; | |||
| if (_button) | |||
| { | |||
| _keymod = E->state; | |||
| dx = E->x - _rx; | |||
| dy = E->y - _ry; | |||
| r = handle_motion (dx, dy); | |||
| if (r) | |||
| { | |||
| callback (r); | |||
| render (); | |||
| } | |||
| } | |||
| } | |||
| void RotaryCtl::set_state (int s) | |||
| { | |||
| if (_state != s) | |||
| { | |||
| _state = s; | |||
| render (); | |||
| } | |||
| } | |||
| void RotaryCtl::render (void) | |||
| { | |||
| XImage *I; | |||
| double a, c, r, x, y; | |||
| I = _rgeom->_image [_state]; | |||
| XPutImage (dpy (), win (), dgc (), I, | |||
| _rgeom->_x0, _rgeom->_y0, 0, 0, _rgeom->_dx, _rgeom->_dy); | |||
| cairo_xlib_surface_set_drawable (_cairosurf, win(), | |||
| _rgeom->_dx, _rgeom->_dy); | |||
| c = _rgeom->_lncol [_state] ? 1.0 : 0.0; | |||
| a = _angle * M_PI / 180; | |||
| r = _rgeom->_rad; | |||
| x = _rgeom->_xref; | |||
| y = _rgeom->_yref; | |||
| cairo_new_path (_cairotype); | |||
| cairo_move_to (_cairotype, x, y); | |||
| x += r * sin (a); | |||
| y -= r * cos (a); | |||
| cairo_line_to (_cairotype, x, y); | |||
| cairo_set_source_rgb (_cairotype, c, c, c); | |||
| cairo_set_line_width (_cairotype, 2.2); | |||
| cairo_stroke (_cairotype); | |||
| } | |||
| } | |||
| @@ -0,0 +1,119 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2012 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __ROTARY_H | |||
| #define __ROTARY_H | |||
| #include <cairo/cairo.h> | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <clxclient.h> | |||
| namespace AT1 { | |||
| class RotaryGeom | |||
| { | |||
| public: | |||
| XftColor *_backg; | |||
| XImage *_image [4]; | |||
| char _lncol [4]; | |||
| int _x0; | |||
| int _y0; | |||
| int _dx; | |||
| int _dy; | |||
| double _xref; | |||
| double _yref; | |||
| double _rad; | |||
| }; | |||
| class RotaryCtl : public X_window | |||
| { | |||
| public: | |||
| RotaryCtl (X_window *parent, | |||
| X_callback *cbobj, | |||
| int cbind, | |||
| RotaryGeom *rgeom, | |||
| int xp, | |||
| int yp); | |||
| virtual ~RotaryCtl (void); | |||
| enum { NOP = 200, PRESS, RELSE, DELTA }; | |||
| int cbind (void) { return _cbind; } | |||
| int state (void) { return _state; } | |||
| double value (void) { return _value; } | |||
| virtual void set_state (int s); | |||
| virtual void set_value (double v) = 0; | |||
| virtual void get_string (char *p, int n) {} | |||
| static void init (X_display *disp); | |||
| static void fini (void); | |||
| static int _wb_up; | |||
| static int _wb_dn; | |||
| protected: | |||
| X_callback *_cbobj; | |||
| int _cbind; | |||
| RotaryGeom *_rgeom; | |||
| int _state; | |||
| int _count; | |||
| int _range; | |||
| double _value; | |||
| double _angle; | |||
| void render (void); | |||
| void callback (int k) { _cbobj->handle_callb (k, this, 0); } | |||
| static int _keymod; | |||
| static int _button; | |||
| static int _rcount; | |||
| static int _rx; | |||
| static int _ry; | |||
| private: | |||
| void handle_event (XEvent *E); | |||
| void bpress (XButtonEvent *E); | |||
| void brelse (XButtonEvent *E); | |||
| void motion (XMotionEvent *E); | |||
| virtual int handle_button (void) = 0; | |||
| virtual int handle_motion (int dx, int dy) = 0; | |||
| virtual int handle_mwheel (int dw) = 0; | |||
| static cairo_t *_cairotype; | |||
| static cairo_surface_t *_cairosurf; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,163 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2014 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include "styles.h" | |||
| #include "tmeter.h" | |||
| #include "png2img.h" | |||
| #include "CarlaString.hpp" | |||
| namespace AT1 { | |||
| XftColor *XftColors [NXFTCOLORS]; | |||
| XftFont *XftFonts [NXFTFONTS]; | |||
| X_textln_style tstyle1; | |||
| X_button_style bstyle1; | |||
| XImage *notesect_img; | |||
| XImage *ctrlsect_img; | |||
| XImage *redzita_img; | |||
| ButtonImg b_note_img; | |||
| ButtonImg b_midi_img; | |||
| RotaryGeom r_tune_geom; | |||
| RotaryGeom r_filt_geom; | |||
| RotaryGeom r_bias_geom; | |||
| RotaryGeom r_corr_geom; | |||
| RotaryGeom r_offs_geom; | |||
| int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| { | |||
| XftColors [C_MAIN_BG] = disp->alloc_xftcolor (0.25f, 0.25f, 0.25f, 1.0f); | |||
| XftColors [C_MAIN_FG] = disp->alloc_xftcolor (1.0f, 1.0f, 1.0f, 1.0f); | |||
| XftColors [C_TEXT_BG] = disp->alloc_xftcolor (1.0f, 1.0f, 1.0f, 1.0f); | |||
| XftColors [C_TEXT_FG] = disp->alloc_xftcolor (0.1f, 0.1f, 0.1f, 1.0f); | |||
| XftFonts [F_TEXT] = disp->alloc_xftfont (xrm->get (".font.text", "luxi:bold::pixelsize=11")); | |||
| XftFonts [F_BUTT] = disp->alloc_xftfont (xrm->get (".font.butt", "luxi:bold::pixelsize=11")); | |||
| tstyle1.font = XftFonts [F_TEXT]; | |||
| tstyle1.color.normal.bgnd = XftColors [C_TEXT_BG]->pixel; | |||
| tstyle1.color.normal.text = XftColors [C_TEXT_FG]; | |||
| bstyle1.font = XftFonts [F_BUTT]; | |||
| bstyle1.color.bg[0] = XftColors [C_MAIN_BG]->pixel; | |||
| bstyle1.color.fg[0] = XftColors [C_MAIN_FG]; | |||
| bstyle1.type = X_button_style::PLAIN | X_button_style::ALEFT; | |||
| const CarlaString SHARED = CarlaString(resdir)+"/at1"; | |||
| notesect_img = png2img (SHARED+"/notesect.png", disp, XftColors [C_MAIN_BG]); | |||
| ctrlsect_img = png2img (SHARED+"/ctrlsect.png", disp, XftColors [C_MAIN_BG]); | |||
| Tmeter::_scale = png2img (SHARED+"/hscale.png", disp, XftColors [C_MAIN_BG]); | |||
| Tmeter::_imag0 = png2img (SHARED+"/hmeter0.png", disp, XftColors [C_MAIN_BG]); | |||
| Tmeter::_imag1 = png2img (SHARED+"/hmeter1.png", disp, XftColors [C_MAIN_BG]); | |||
| if ( !notesect_img || !ctrlsect_img | |||
| || !Tmeter::_scale || !Tmeter::_imag0 || !Tmeter::_imag1) | |||
| { | |||
| fprintf (stderr, "Can't load images from '%s'.\n", SHARED.buffer()); | |||
| return 1; | |||
| } | |||
| b_midi_img._backg = XftColors [C_MAIN_BG]; | |||
| b_midi_img._ximage = png2img (SHARED+"/midi.png", disp, XftColors [C_MAIN_BG]); | |||
| b_midi_img._x0 = 0; | |||
| b_midi_img._y0 = 0; | |||
| b_midi_img._dx = 40; | |||
| b_midi_img._dy = 24; | |||
| b_note_img._backg = XftColors [C_MAIN_BG]; | |||
| b_note_img._ximage = png2img (SHARED+"/note.png", disp, XftColors [C_MAIN_BG]); | |||
| b_note_img._x0 = 0; | |||
| b_note_img._y0 = 0; | |||
| b_note_img._dx = 16; | |||
| b_note_img._dy = 16; | |||
| r_tune_geom._backg = XftColors [C_MAIN_BG]; | |||
| r_tune_geom._image [0] = ctrlsect_img; | |||
| r_tune_geom._lncol [0] = 1; | |||
| r_tune_geom._x0 = 26; | |||
| r_tune_geom._y0 = 17; | |||
| r_tune_geom._dx = 23; | |||
| r_tune_geom._dy = 23; | |||
| r_tune_geom._xref = 11.5; | |||
| r_tune_geom._yref = 11.5; | |||
| r_tune_geom._rad = 11; | |||
| r_bias_geom._backg = XftColors [C_MAIN_BG]; | |||
| r_bias_geom._image [0] = ctrlsect_img; | |||
| r_bias_geom._lncol [0] = 0; | |||
| r_bias_geom._x0 = 86; | |||
| r_bias_geom._y0 = 17; | |||
| r_bias_geom._dx = 23; | |||
| r_bias_geom._dy = 23; | |||
| r_bias_geom._xref = 11.5; | |||
| r_bias_geom._yref = 11.5; | |||
| r_bias_geom._rad = 11; | |||
| r_filt_geom._backg = XftColors [C_MAIN_BG]; | |||
| r_filt_geom._image [0] = ctrlsect_img; | |||
| r_filt_geom._lncol [0] = 0; | |||
| r_filt_geom._x0 = 146; | |||
| r_filt_geom._y0 = 17; | |||
| r_filt_geom._dx = 23; | |||
| r_filt_geom._dy = 23; | |||
| r_filt_geom._xref = 11.5; | |||
| r_filt_geom._yref = 11.5; | |||
| r_filt_geom._rad = 11; | |||
| r_corr_geom._backg = XftColors [C_MAIN_BG]; | |||
| r_corr_geom._image [0] = ctrlsect_img; | |||
| r_corr_geom._lncol [0] = 0; | |||
| r_corr_geom._x0 = 206; | |||
| r_corr_geom._y0 = 17; | |||
| r_corr_geom._dx = 23; | |||
| r_corr_geom._dy = 23; | |||
| r_corr_geom._xref = 11.5; | |||
| r_corr_geom._yref = 11.5; | |||
| r_corr_geom._rad = 11; | |||
| r_offs_geom._backg = XftColors [C_MAIN_BG]; | |||
| r_offs_geom._image [0] = ctrlsect_img; | |||
| r_offs_geom._lncol [0] = 0; | |||
| r_offs_geom._x0 = 266; | |||
| r_offs_geom._y0 = 17; | |||
| r_offs_geom._dx = 23; | |||
| r_offs_geom._dy = 23; | |||
| r_offs_geom._xref = 11.5; | |||
| r_offs_geom._yref = 11.5; | |||
| r_offs_geom._rad = 11; | |||
| return 0; | |||
| } | |||
| void styles_fini (X_display *disp) | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,70 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010-2014 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __STYLES_H | |||
| #define __STYLES_H | |||
| #include <clxclient.h> | |||
| #include "button.h" | |||
| #include "rotary.h" | |||
| namespace AT1 { | |||
| enum | |||
| { | |||
| C_MAIN_BG, C_MAIN_FG, | |||
| C_TEXT_BG, C_TEXT_FG, | |||
| NXFTCOLORS | |||
| }; | |||
| enum | |||
| { | |||
| F_TEXT, | |||
| F_BUTT, | |||
| NXFTFONTS | |||
| }; | |||
| extern int styles_init (X_display *disp, X_resman *xrm, const char *resdir); | |||
| extern void styles_fini (X_display *disp); | |||
| extern XftColor *XftColors [NXFTCOLORS]; | |||
| extern XftFont *XftFonts [NXFTFONTS]; | |||
| extern X_textln_style tstyle1; | |||
| extern X_button_style bstyle1; | |||
| extern XImage *notesect_img; | |||
| extern XImage *ctrlsect_img; | |||
| extern ButtonImg b_midi_img; | |||
| extern ButtonImg b_note_img; | |||
| extern RotaryGeom r_tune_geom; | |||
| extern RotaryGeom r_filt_geom; | |||
| extern RotaryGeom r_bias_geom; | |||
| extern RotaryGeom r_corr_geom; | |||
| extern RotaryGeom r_offs_geom; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,86 @@ | |||
| /* | |||
| Copyright (C) 2009-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| 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 | |||
| (at your option) 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. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #include <math.h> | |||
| #include "tmeter.h" | |||
| namespace AT1 { | |||
| XImage *Tmeter::_scale = 0; | |||
| XImage *Tmeter::_imag0 = 0; | |||
| XImage *Tmeter::_imag1 = 0; | |||
| Tmeter::Tmeter (X_window *parent, int xpos, int ypos) : | |||
| X_window (parent, xpos, ypos, XS + 2 * XM, YS + 2 * YM, 0), | |||
| _k0 (86), | |||
| _k1 (86) | |||
| { | |||
| if (!_imag0 || !_imag1 || !_scale) return; | |||
| x_add_events (ExposureMask); | |||
| } | |||
| Tmeter::~Tmeter (void) | |||
| { | |||
| } | |||
| void Tmeter::handle_event (XEvent *E) | |||
| { | |||
| switch (E->type) | |||
| { | |||
| case Expose: | |||
| expose ((XExposeEvent *) E); | |||
| break; | |||
| } | |||
| } | |||
| void Tmeter::expose (XExposeEvent *E) | |||
| { | |||
| if (E->count) return; | |||
| XSetFunction (dpy (), dgc (), GXcopy); | |||
| XPutImage (dpy (), win (), dgc (), _imag0, 0, 0, XM, YM, XS, Y1); | |||
| XPutImage (dpy (), win (), dgc (), _imag1, _k0 - 2, 0, XM + _k0 - 2, YM, 5 + _k1 - _k0, Y1); | |||
| XPutImage (dpy (), win (), dgc (), _scale, 0, 0, XM, YM + Y1, XS, Y2); | |||
| } | |||
| void Tmeter::update (float v0, float v1) | |||
| { | |||
| int k0, k1; | |||
| k0 = (int)(floorf (86.0f + 80.0f * v0 + 0.5f)); | |||
| k1 = (int)(floorf (86.0f + 80.0f * v1 + 0.5f)); | |||
| if (k0 < 4) k0 = 4; | |||
| if (k0 > 168) k0 = 168; | |||
| if (k1 < 4) k1 = 4; | |||
| if (k1 > 168) k1 = 168; | |||
| XSetFunction (dpy (), dgc (), GXcopy); | |||
| XPutImage (dpy (), win (), dgc (), _imag0, _k0 - 2, 0, XM + _k0 - 2, YM, 5 + _k1 - _k0, Y1); | |||
| _k0 = k0; | |||
| _k1 = k1; | |||
| XPutImage (dpy (), win (), dgc (), _imag1, _k0 - 2, 0, XM + _k0 - 2, YM, 5 + _k1 - _k0, Y1); | |||
| } | |||
| } | |||
| @@ -0,0 +1,59 @@ | |||
| /* | |||
| Copyright (C) 2009-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| 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 | |||
| (at your option) 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. | |||
| You should have received a copy of the GNU General Public License | |||
| along with this program; if not, write to the Free Software | |||
| Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| */ | |||
| #ifndef __TMETER_H | |||
| #define __TMETER_H | |||
| #include <clxclient.h> | |||
| namespace AT1 { | |||
| class Tmeter : public X_window | |||
| { | |||
| public: | |||
| Tmeter (X_window *parent, int xpos, int ypos); | |||
| ~Tmeter (void); | |||
| Tmeter (const Tmeter&); | |||
| Tmeter& operator=(const Tmeter&); | |||
| void update (float v0, float v1); | |||
| static XImage *_scale; | |||
| static XImage *_imag0; | |||
| static XImage *_imag1; | |||
| private: | |||
| enum { XS = 173, YS = 17, XM = 0, YM = 0, Y1 = 7, Y2 = 10 }; | |||
| void handle_event (XEvent *E); | |||
| void expose (XExposeEvent *E); | |||
| int _k0; | |||
| int _k1; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -16,20 +16,18 @@ | |||
| */ | |||
| #include "CarlaNative.hpp" | |||
| #include "CarlaMutex.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "juce_audio_basics.h" | |||
| // this one needs to be first | |||
| #include "zita-bls1/png2img.cc" | |||
| #include "zita-common.hpp" | |||
| #include "zita-bls1/guiclass.cc" | |||
| #include "zita-bls1/hp3filt.cc" | |||
| #include "zita-bls1/jclient.cc" | |||
| #include "zita-bls1/lfshelf2.cc" | |||
| #include "zita-bls1/mainwin.cc" | |||
| #include "zita-bls1/png2img.cc" | |||
| #include "zita-bls1/rotary.cc" | |||
| #include "zita-bls1/shuffler.cc" | |||
| #include "zita-bls1/styles.cc" | |||
| @@ -37,6 +35,8 @@ | |||
| using juce::FloatVectorOperations; | |||
| using juce::ScopedPointer; | |||
| using namespace BLS1; | |||
| // ----------------------------------------------------------------------- | |||
| // BLS1 Plugin | |||
| @@ -66,6 +66,7 @@ public: | |||
| rootwin(nullptr), | |||
| mainwin(nullptr), | |||
| handler(nullptr), | |||
| handlerThread(), | |||
| leakDetector_BLS1Plugin() | |||
| { | |||
| CARLA_SAFE_ASSERT(host != nullptr); | |||
| @@ -228,10 +229,10 @@ public: | |||
| } | |||
| for (uint32_t i=0; i<kNumInputs; ++i) | |||
| fJackClient.portsAudioIn[i].buffer = inBuffer[i]; | |||
| fJackClient.portsAudioIn[i].buffer.audio = inBuffer[i]; | |||
| for (uint32_t i=0; i<kNumOutputs; ++i) | |||
| fJackClient.portsAudioOut[i].buffer = outBuffer[i]; | |||
| fJackClient.portsAudioOut[i].buffer.audio = outBuffer[i]; | |||
| fJackClient.processCallback(frames, fJackClient.processPtr); | |||
| } | |||
| @@ -243,31 +244,36 @@ public: | |||
| { | |||
| if (show) | |||
| { | |||
| if (display == nullptr) | |||
| { | |||
| display = new X_display(nullptr); | |||
| if (display != nullptr) | |||
| return; | |||
| display = new X_display(nullptr); | |||
| if (display->dpy() == nullptr) | |||
| return hostUiUnavailable(); | |||
| if (display->dpy() == nullptr) | |||
| return hostUiUnavailable(); | |||
| styles_init(display, &xresman, getResourceDir()); | |||
| styles_init(display, &xresman, getResourceDir()); | |||
| rootwin = new X_rootwin(display); | |||
| mainwin = new Mainwin(rootwin, &xresman, 0, 0, jclient, this); | |||
| rootwin->handle_event(); | |||
| mainwin->x_set_title(getUiName()); | |||
| rootwin = new X_rootwin(display); | |||
| mainwin = new Mainwin(rootwin, &xresman, 0, 0, jclient, this); | |||
| rootwin->handle_event(); | |||
| mainwin->x_set_title(getUiName()); | |||
| handler = new X_handler(display, mainwin, EV_X11); | |||
| handler = new X_handler(display, mainwin, EV_X11); | |||
| if (const uintptr_t winId = getUiParentId()) | |||
| XSetTransientForHint(display->dpy(), mainwin->win(), static_cast<Window>(winId)); | |||
| } | |||
| if (const uintptr_t winId = getUiParentId()) | |||
| XSetTransientForHint(display->dpy(), mainwin->win(), static_cast<Window>(winId)); | |||
| handler->next_event(); | |||
| XFlush(display->dpy()); | |||
| handlerThread.setupAndRun(handler, rootwin, mainwin); | |||
| } | |||
| else | |||
| { | |||
| if (handlerThread.isThreadRunning()) | |||
| handlerThread.stopThread(); | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| @@ -280,20 +286,15 @@ public: | |||
| if (mainwin == nullptr) | |||
| return; | |||
| int ev; | |||
| for (; (ev = mainwin->process()) == EV_X11;) | |||
| { | |||
| rootwin->handle_event(); | |||
| handler->next_event(); | |||
| } | |||
| if (ev == EV_EXIT) | |||
| if (handlerThread.wasClosed()) | |||
| { | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| display = nullptr; | |||
| { | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| display = nullptr; | |||
| } | |||
| uiClosed(); | |||
| } | |||
| } | |||
| @@ -305,6 +306,8 @@ public: | |||
| if (mainwin == nullptr) | |||
| return; | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| mainwin->_rotary[index]->set_value(value); | |||
| } | |||
| @@ -328,6 +331,8 @@ public: | |||
| if (mainwin == nullptr) | |||
| return; | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| mainwin->x_set_title(uiName); | |||
| } | |||
| @@ -353,6 +358,7 @@ private: | |||
| ScopedPointer<X_rootwin> rootwin; | |||
| ScopedPointer<Mainwin> mainwin; | |||
| ScopedPointer<X_handler> handler; | |||
| X_handler_thread<Mainwin> handlerThread; | |||
| float fParameters[kParameterNROTARY]; | |||
| @@ -23,6 +23,8 @@ | |||
| #include <math.h> | |||
| #include "guiclass.h" | |||
| namespace BLS1 { | |||
| Rlinctl::Rlinctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| @@ -153,3 +155,6 @@ int Rlogctl::set_count (int u) | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -26,6 +26,8 @@ | |||
| #include "rotary.h" | |||
| namespace BLS1 { | |||
| class Rlinctl : public RotaryCtl | |||
| { | |||
| @@ -95,4 +97,6 @@ private: | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -24,6 +24,8 @@ | |||
| #include <math.h> | |||
| #include "hp3filt.h" | |||
| namespace BLS1 { | |||
| HP3filt::HP3filt (void) : | |||
| _touch0 (0), | |||
| @@ -177,3 +179,6 @@ void HP3filt::process1 (int nsamp, int nchan, float *data[]) | |||
| } | |||
| if (_state == FADING) _a = a; | |||
| } | |||
| } | |||
| @@ -27,6 +27,8 @@ | |||
| #include <stdint.h> | |||
| #include "global.h" | |||
| namespace BLS1 { | |||
| class HP3filt | |||
| { | |||
| @@ -69,4 +71,6 @@ private: | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -23,6 +23,8 @@ | |||
| #include <string.h> | |||
| #include "jclient.h" | |||
| namespace BLS1 { | |||
| Jclient::Jclient (const char *jname, jack_client_t *jclient) : | |||
| A_thread ("Jclient"), | |||
| @@ -185,3 +187,4 @@ int Jclient::jack_process (int frames) | |||
| } | |||
| } | |||
| @@ -34,6 +34,8 @@ | |||
| #include "lfshelf2.h" | |||
| #include "global.h" | |||
| namespace BLS1 { | |||
| class Jclient : public A_thread | |||
| { | |||
| @@ -95,4 +97,6 @@ private: | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -24,6 +24,8 @@ | |||
| #include <string.h> | |||
| #include "lfshelf2.h" | |||
| namespace BLS1 { | |||
| LFshelf2::LFshelf2 (void) : | |||
| _touch0 (0), | |||
| @@ -247,3 +249,5 @@ void LFshelf2::process1 (int nsamp, int nchan, float *data[]) | |||
| } | |||
| } | |||
| } | |||
| @@ -27,6 +27,8 @@ | |||
| #include <stdint.h> | |||
| #include "global.h" | |||
| namespace BLS1 { | |||
| class LFshelf2 | |||
| { | |||
| @@ -86,4 +88,6 @@ private: | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -27,10 +27,12 @@ | |||
| #include "global.h" | |||
| #include "mainwin.h" | |||
| namespace BLS1 { | |||
| Mainwin::Mainwin (X_rootwin *parent, X_resman *xres, int xp, int yp, Jclient *jclient, ValueChangedCallback* valuecb) : | |||
| A_thread ("Main"), | |||
| X_window (parent, xp, yp, XSIZE, YSIZE, XftColors_bls1 [C_MAIN_BG]->pixel), | |||
| X_window (parent, xp, yp, XSIZE, YSIZE, XftColors [C_MAIN_BG]->pixel), | |||
| _stop (false), | |||
| _xres (xres), | |||
| _jclient (jclient), | |||
| @@ -260,3 +262,5 @@ void Mainwin::fmtfreq (int k) | |||
| _numtext->set_text (t); | |||
| } | |||
| } | |||
| @@ -29,6 +29,10 @@ | |||
| #include "jclient.h" | |||
| #include "global.h" | |||
| class BLS1Plugin; | |||
| namespace BLS1 { | |||
| class Mainwin : public A_thread, public X_window, public X_callback | |||
| { | |||
| @@ -77,8 +81,10 @@ private: | |||
| ValueChangedCallback* _valuecb; | |||
| friend class BLS1Plugin; | |||
| friend class ::BLS1Plugin; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -23,6 +23,7 @@ | |||
| #include <png.h> | |||
| #include <clxclient.h> | |||
| namespace BLS1 { | |||
| XImage *png2img (const char *file, X_display *disp, XftColor *bgnd) | |||
| @@ -130,3 +131,6 @@ XImage *png2img (const char *file, X_display *disp, XftColor *bgnd) | |||
| return image; | |||
| } | |||
| } | |||
| @@ -26,8 +26,10 @@ | |||
| #include <clxclient.h> | |||
| namespace BLS1 { | |||
| extern XImage *png2img (const char *file, X_display *disp, XftColor *bgnd); | |||
| } | |||
| #endif | |||
| @@ -25,6 +25,8 @@ | |||
| #include <math.h> | |||
| #include "rotary.h" | |||
| namespace BLS1 { | |||
| cairo_t *RotaryCtl::_cairotype = 0; | |||
| cairo_surface_t *RotaryCtl::_cairosurf = 0; | |||
| @@ -202,3 +204,4 @@ void RotaryCtl::render (void) | |||
| } | |||
| } | |||
| @@ -28,6 +28,8 @@ | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <clxclient.h> | |||
| namespace BLS1 { | |||
| class RotaryImg | |||
| { | |||
| @@ -113,4 +115,6 @@ private: | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -26,6 +26,8 @@ | |||
| #include <math.h> | |||
| #include "shuffler.h" | |||
| namespace BLS1 { | |||
| Shuffler::Shuffler (void) : | |||
| _fsamp (0), | |||
| @@ -181,3 +183,6 @@ void Shuffler::process (int nsamp, float *inp [], float *out []) | |||
| _del_wind = wi; | |||
| } | |||
| } | |||
| @@ -27,6 +27,8 @@ | |||
| #include <zita-convolver.h> | |||
| #include "global.h" | |||
| namespace BLS1 { | |||
| class Shuffler | |||
| { | |||
| @@ -65,4 +67,6 @@ private: | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -25,8 +25,11 @@ | |||
| #include "CarlaString.hpp" | |||
| XftColor *XftColors_bls1 [NXFTCOLORS]; | |||
| XftFont *XftFonts_bls1 [NXFTFONTS]; | |||
| namespace BLS1 { | |||
| XftColor *XftColors [NXFTCOLORS]; | |||
| XftFont *XftFonts [NXFTFONTS]; | |||
| X_textln_style tstyle1; | |||
| @@ -44,24 +47,24 @@ RotaryImg lfgain_img; | |||
| int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| { | |||
| XftColors_bls1 [C_MAIN_BG] = disp->alloc_xftcolor (0.25f, 0.25f, 0.25f, 1.0f); | |||
| XftColors_bls1 [C_MAIN_FG] = disp->alloc_xftcolor (1.0f, 1.0f, 1.0f, 1.0f); | |||
| XftColors_bls1 [C_TEXT_BG] = disp->alloc_xftcolor (1.0f, 1.0f, 0.0f, 1.0f); | |||
| XftColors_bls1 [C_TEXT_FG] = disp->alloc_xftcolor (0.0f, 0.0f, 0.0f, 1.0f); | |||
| XftColors [C_MAIN_BG] = disp->alloc_xftcolor (0.25f, 0.25f, 0.25f, 1.0f); | |||
| XftColors [C_MAIN_FG] = disp->alloc_xftcolor (1.0f, 1.0f, 1.0f, 1.0f); | |||
| XftColors [C_TEXT_BG] = disp->alloc_xftcolor (1.0f, 1.0f, 0.0f, 1.0f); | |||
| XftColors [C_TEXT_FG] = disp->alloc_xftcolor (0.0f, 0.0f, 0.0f, 1.0f); | |||
| XftFonts_bls1 [F_TEXT] = disp->alloc_xftfont (xrm->get (".font.text", "luxi:bold::pixelsize=11")); | |||
| XftFonts [F_TEXT] = disp->alloc_xftfont (xrm->get (".font.text", "luxi:bold::pixelsize=11")); | |||
| tstyle1.font = XftFonts_bls1 [F_TEXT]; | |||
| tstyle1.color.normal.bgnd = XftColors_bls1 [C_TEXT_BG]->pixel; | |||
| tstyle1.color.normal.text = XftColors_bls1 [C_TEXT_FG]; | |||
| tstyle1.font = XftFonts [F_TEXT]; | |||
| tstyle1.color.normal.bgnd = XftColors [C_TEXT_BG]->pixel; | |||
| tstyle1.color.normal.text = XftColors [C_TEXT_FG]; | |||
| const CarlaString SHARED = CarlaString(resdir)+"/bls1"; | |||
| inputsect = png2img (SHARED+"/inputsect.png", disp, XftColors_bls1 [C_MAIN_BG]); | |||
| shuffsect = png2img (SHARED+"/shuffsect.png", disp, XftColors_bls1 [C_MAIN_BG]); | |||
| lfshfsect = png2img (SHARED+"/lfshfsect.png", disp, XftColors_bls1 [C_MAIN_BG]); | |||
| inputsect = png2img (SHARED+"/inputsect.png", disp, XftColors [C_MAIN_BG]); | |||
| shuffsect = png2img (SHARED+"/shuffsect.png", disp, XftColors [C_MAIN_BG]); | |||
| lfshfsect = png2img (SHARED+"/lfshfsect.png", disp, XftColors [C_MAIN_BG]); | |||
| if (!inputsect || !shuffsect || !lfshfsect) return 1; | |||
| inpbal_img._backg = XftColors_bls1 [C_MAIN_BG]; | |||
| inpbal_img._backg = XftColors [C_MAIN_BG]; | |||
| inpbal_img._image [0] = inputsect; | |||
| inpbal_img._lncol [0] = 1; | |||
| inpbal_img._x0 = 28; | |||
| @@ -72,7 +75,7 @@ int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| inpbal_img._yref = 12.5; | |||
| inpbal_img._rad = 12; | |||
| hpfilt_img._backg = XftColors_bls1 [C_MAIN_BG]; | |||
| hpfilt_img._backg = XftColors [C_MAIN_BG]; | |||
| hpfilt_img._image [0] = inputsect; | |||
| hpfilt_img._lncol [0] = 0; | |||
| hpfilt_img._x0 = 87; | |||
| @@ -83,7 +86,7 @@ int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| hpfilt_img._yref = 12.5; | |||
| hpfilt_img._rad = 12; | |||
| shgain_img._backg = XftColors_bls1 [C_MAIN_BG]; | |||
| shgain_img._backg = XftColors [C_MAIN_BG]; | |||
| shgain_img._image [0] = shuffsect; | |||
| shgain_img._lncol [0] = 0; | |||
| shgain_img._x0 = 68; | |||
| @@ -94,7 +97,7 @@ int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| shgain_img._yref = 12.5; | |||
| shgain_img._rad = 12; | |||
| shfreq_img._backg = XftColors_bls1 [C_MAIN_BG]; | |||
| shfreq_img._backg = XftColors [C_MAIN_BG]; | |||
| shfreq_img._image [0] = shuffsect; | |||
| shfreq_img._lncol [0] = 0; | |||
| shfreq_img._x0 = 127; | |||
| @@ -105,7 +108,7 @@ int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| shfreq_img._yref = 12.5; | |||
| shfreq_img._rad = 12; | |||
| lffreq_img._backg = XftColors_bls1 [C_MAIN_BG]; | |||
| lffreq_img._backg = XftColors [C_MAIN_BG]; | |||
| lffreq_img._image [0] = lfshfsect; | |||
| lffreq_img._lncol [0] = 0; | |||
| lffreq_img._x0 = 14; | |||
| @@ -116,7 +119,7 @@ int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| lffreq_img._yref = 12.5; | |||
| lffreq_img._rad = 12; | |||
| lfgain_img._backg = XftColors_bls1 [C_MAIN_BG]; | |||
| lfgain_img._backg = XftColors [C_MAIN_BG]; | |||
| lfgain_img._image [0] = lfshfsect; | |||
| lfgain_img._lncol [0] = 1; | |||
| lfgain_img._x0 = 63; | |||
| @@ -134,3 +137,6 @@ int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| void styles_fini (X_display *disp) | |||
| { | |||
| } | |||
| } | |||
| @@ -26,6 +26,8 @@ | |||
| #include <clxclient.h> | |||
| #include "rotary.h" | |||
| namespace BLS1 { | |||
| enum | |||
| { | |||
| @@ -44,8 +46,8 @@ enum | |||
| extern int styles_init (X_display *disp, X_resman *xrm, const char *resdir); | |||
| extern void styles_fini (X_display *disp); | |||
| extern XftColor *XftColors_bls1 [NXFTCOLORS]; | |||
| extern XftFont *XftFonts_bls1 [NXFTFONTS]; | |||
| extern XftColor *XftColors [NXFTCOLORS]; | |||
| extern XftFont *XftFonts [NXFTFONTS]; | |||
| extern X_textln_style tstyle1; | |||
| @@ -60,4 +62,6 @@ extern RotaryImg lffreq_img; | |||
| extern RotaryImg lfgain_img; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,129 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #ifndef CARLA_ZITA_COMMON_HPP_INCLUDED | |||
| #define CARLA_ZITA_COMMON_HPP_INCLUDED | |||
| #include "CarlaMutex.hpp" | |||
| #include "CarlaThread.hpp" | |||
| #include <png.h> | |||
| #include <clxclient.h> | |||
| #define EV_X11 16 | |||
| #define EV_EXIT 31 | |||
| // ----------------------------------------------------------------------- | |||
| template<class MainwinType> | |||
| class X_handler_thread : public CarlaThread | |||
| { | |||
| public: | |||
| X_handler_thread() | |||
| : CarlaThread("X_handler"), | |||
| fMutex(), | |||
| fHandler(nullptr), | |||
| fRootwin(nullptr), | |||
| fMainwin(nullptr), | |||
| fClosed(false) {} | |||
| void setupAndRun(X_handler* const h, X_rootwin* const r, MainwinType* const m) noexcept | |||
| { | |||
| const CarlaMutexLocker cml(fMutex); | |||
| fHandler = h; | |||
| fRootwin = r; | |||
| fMainwin = m; | |||
| startThread(); | |||
| } | |||
| void stopThread() noexcept | |||
| { | |||
| signalThreadShouldExit(); | |||
| { | |||
| const CarlaMutexLocker cml(fMutex); | |||
| fHandler = nullptr; | |||
| fRootwin = nullptr; | |||
| fMainwin = nullptr; | |||
| } | |||
| CarlaThread::stopThread(1000); | |||
| } | |||
| CarlaMutex& getLock() noexcept | |||
| { | |||
| return fMutex; | |||
| } | |||
| bool wasClosed() noexcept | |||
| { | |||
| if (fClosed) | |||
| { | |||
| fClosed = false; | |||
| return true; | |||
| } | |||
| return false; | |||
| } | |||
| private: | |||
| CarlaMutex fMutex; | |||
| X_handler* fHandler; | |||
| X_rootwin* fRootwin; | |||
| MainwinType* fMainwin; | |||
| volatile bool fClosed; | |||
| void run() override | |||
| { | |||
| for (; ! shouldThreadExit();) | |||
| { | |||
| int ev; | |||
| { | |||
| const CarlaMutexLocker cml(fMutex); | |||
| CARLA_SAFE_ASSERT_RETURN(fMainwin != nullptr,); | |||
| for (; (ev = fMainwin->process()) == EV_X11;) | |||
| { | |||
| fRootwin->handle_event(); | |||
| fHandler->next_event(); | |||
| } | |||
| if (ev == Esync::EV_TIME) | |||
| { | |||
| fRootwin->handle_event(); | |||
| } | |||
| else if (ev == EV_EXIT) | |||
| { | |||
| fClosed = true; | |||
| fHandler = nullptr; | |||
| fMainwin = nullptr; | |||
| fRootwin = nullptr; | |||
| return; | |||
| } | |||
| } | |||
| carla_msleep(10); | |||
| } | |||
| } | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| #endif // CARLA_ZITA_COMMON_HPP_INCLUDED | |||
| @@ -0,0 +1,577 @@ | |||
| /* | |||
| * Carla Native Plugins | |||
| * Copyright (C) 2012-2015 Filipe Coelho <falktx@falktx.com> | |||
| * | |||
| * This program is free software; you can redistribute it and/or | |||
| * modify it under the terms of the GNU General Public License as | |||
| * published by the Free Software Foundation; either version 2 of | |||
| * the License, or any later version. | |||
| * | |||
| * This program is distributed in the hope that it will be useful, | |||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
| * GNU General Public License for more details. | |||
| * | |||
| * For a full copy of the GNU General Public License see the doc/GPL.txt file. | |||
| */ | |||
| #include "CarlaNative.hpp" | |||
| #include "CarlaMathUtils.hpp" | |||
| #include "CarlaJuceUtils.hpp" | |||
| #include "juce_audio_basics.h" | |||
| #include "zita-common.hpp" | |||
| #include "zita-rev1/guiclass.cc" | |||
| #include "zita-rev1/jclient.cc" | |||
| #include "zita-rev1/mainwin.cc" | |||
| #include "zita-rev1/pareq.cc" | |||
| #include "zita-rev1/png2img.cc" | |||
| #include "zita-rev1/reverb.cc" | |||
| #include "zita-rev1/rotary.cc" | |||
| #include "zita-rev1/styles.cc" | |||
| using juce::FloatVectorOperations; | |||
| using juce::ScopedPointer; | |||
| using namespace REV1; | |||
| // ----------------------------------------------------------------------- | |||
| // REV1 Plugin | |||
| class REV1Plugin : public NativePluginClass, | |||
| private Mainwin::ValueChangedCallback | |||
| { | |||
| public: | |||
| enum Parameters { | |||
| kParameterDELAY, | |||
| kParameterXOVER, | |||
| kParameterRTLOW, | |||
| kParameterRTMID, | |||
| kParameterFDAMP, | |||
| kParameterEQ1FR, | |||
| kParameterEQ1GN, | |||
| kParameterEQ2FR, | |||
| kParameterEQ2GN, | |||
| kParameterOPMIXorRGXYZ, | |||
| kParameterNROTARY | |||
| }; | |||
| REV1Plugin(const NativeHostDescriptor* const host, const bool isAmbisonic) | |||
| : NativePluginClass(host), | |||
| kIsAmbisonic(isAmbisonic), | |||
| kNumInputs(2), | |||
| kNumOutputs(isAmbisonic ? 4 : 2), | |||
| fJackClient(), | |||
| xresman(), | |||
| jclient(nullptr), | |||
| display(nullptr), | |||
| rootwin(nullptr), | |||
| mainwin(nullptr), | |||
| handler(nullptr), | |||
| handlerThread(), | |||
| leakDetector_REV1Plugin() | |||
| { | |||
| CARLA_SAFE_ASSERT(host != nullptr); | |||
| carla_zeroStruct(fJackClient); | |||
| fJackClient.clientName = "rev1"; | |||
| fJackClient.bufferSize = getBufferSize(); | |||
| fJackClient.sampleRate = getSampleRate(); | |||
| int argc = 1; | |||
| char* argv[] = { (char*)"rev1" }; | |||
| xresman.init(&argc, argv, (char*)"rev1", nullptr, 0); | |||
| jclient = new Jclient(xresman.rname(), &fJackClient, isAmbisonic); | |||
| // set initial values | |||
| fParameters[kParameterDELAY] = 0.04f; | |||
| fParameters[kParameterXOVER] = 200.0f; | |||
| fParameters[kParameterRTLOW] = 3.0f; | |||
| fParameters[kParameterRTMID] = 2.0f; | |||
| fParameters[kParameterFDAMP] = 6.0e3; | |||
| fParameters[kParameterEQ1FR] = 160.0f; | |||
| fParameters[kParameterEQ1GN] = 0.0f; | |||
| fParameters[kParameterEQ2FR] = 2.5e3; | |||
| fParameters[kParameterEQ2GN] = 0.0f; | |||
| if (isAmbisonic) | |||
| fParameters[kParameterOPMIXorRGXYZ] = 0.0f; | |||
| else | |||
| fParameters[kParameterOPMIXorRGXYZ] = 0.5f; | |||
| Reverb* const reverb(jclient->reverb()); | |||
| reverb->set_delay(fParameters[kParameterDELAY]); | |||
| reverb->set_xover(fParameters[kParameterXOVER]); | |||
| reverb->set_rtlow(fParameters[kParameterRTLOW]); | |||
| reverb->set_rtmid(fParameters[kParameterRTMID]); | |||
| reverb->set_fdamp(fParameters[kParameterFDAMP]); | |||
| if (isAmbisonic) | |||
| { | |||
| reverb->set_opmix(0.5); | |||
| reverb->set_rgxyz(fParameters[kParameterOPMIXorRGXYZ]); | |||
| } | |||
| else | |||
| { | |||
| reverb->set_opmix(fParameters[kParameterOPMIXorRGXYZ]); | |||
| reverb->set_rgxyz(0.0); | |||
| } | |||
| reverb->set_eq1(fParameters[kParameterEQ1FR], fParameters[kParameterEQ1GN]); | |||
| reverb->set_eq2(fParameters[kParameterEQ2FR], fParameters[kParameterEQ2GN]); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin parameter calls | |||
| uint32_t getParameterCount() const override | |||
| { | |||
| return kParameterNROTARY; | |||
| } | |||
| const NativeParameter* getParameterInfo(const uint32_t index) const override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kParameterNROTARY, nullptr); | |||
| static NativeParameter param; | |||
| int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_AUTOMABLE; | |||
| // reset | |||
| param.name = nullptr; | |||
| param.unit = nullptr; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = 0.0f; | |||
| param.ranges.max = 1.0f; | |||
| param.ranges.step = 1.0f; | |||
| param.ranges.stepSmall = 1.0f; | |||
| param.ranges.stepLarge = 1.0f; | |||
| param.scalePointCount = 0; | |||
| param.scalePoints = nullptr; | |||
| switch (index) | |||
| { | |||
| case kParameterDELAY: | |||
| param.name = "Delay"; | |||
| param.ranges.def = 0.04f; | |||
| param.ranges.min = 0.02f; | |||
| param.ranges.max = 0.100f; | |||
| break; | |||
| case kParameterXOVER: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "Crossover"; | |||
| param.ranges.def = 200.0f; | |||
| param.ranges.min = 50.0f; | |||
| param.ranges.max = 1000.0f; | |||
| break; | |||
| case kParameterRTLOW: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "RT60 Low"; | |||
| param.ranges.def = 3.0f; | |||
| param.ranges.min = 1.0f; | |||
| param.ranges.max = 8.0f; | |||
| break; | |||
| case kParameterRTMID: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "RT60 Mid"; | |||
| param.ranges.def = 2.0f; | |||
| param.ranges.min = 1.0f; | |||
| param.ranges.max = 8.0f; | |||
| break; | |||
| case kParameterFDAMP: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "HF Damping"; | |||
| param.ranges.def = 6.0e3; | |||
| param.ranges.min = 1.5e3; | |||
| param.ranges.max = 24.0e3; | |||
| break; | |||
| case kParameterEQ1FR: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "Eq1 Frequency"; | |||
| param.ranges.def = 160.0f; | |||
| param.ranges.min = 40.0f; | |||
| param.ranges.max = 2.5e3; | |||
| break; | |||
| case kParameterEQ1GN: | |||
| param.name = "Eq1 Gain"; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = -15.0; | |||
| param.ranges.max = 15.0f; | |||
| break; | |||
| case kParameterEQ2FR: | |||
| hints |= NATIVE_PARAMETER_IS_LOGARITHMIC; | |||
| param.name = "Eq2 Frequency"; | |||
| param.ranges.def = 2.5e3; | |||
| param.ranges.min = 160.0; | |||
| param.ranges.max = 10e3; | |||
| break; | |||
| case kParameterEQ2GN: | |||
| param.name = "Eq2 Gain"; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = -15.0; | |||
| param.ranges.max = 15.0f; | |||
| break; | |||
| case kParameterOPMIXorRGXYZ: | |||
| if (kIsAmbisonic) | |||
| { | |||
| param.name = "XYZ gain"; | |||
| param.ranges.def = 0.0f; | |||
| param.ranges.min = -9.0f; | |||
| param.ranges.max = 9.0f; | |||
| } | |||
| else | |||
| { | |||
| param.name = "Dry/wet mix"; | |||
| param.ranges.def = 0.5f; | |||
| param.ranges.min = 0.0f; | |||
| param.ranges.max = 1.0f; | |||
| } | |||
| break; | |||
| } | |||
| param.hints = static_cast<NativeParameterHints>(hints); | |||
| return ¶m; | |||
| } | |||
| float getParameterValue(const uint32_t index) const override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kParameterNROTARY, 0.0f); | |||
| return fParameters[index]; | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin state calls | |||
| void setParameterValue(const uint32_t index, const float value) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kParameterNROTARY,); | |||
| Reverb* const reverb(jclient->reverb()); | |||
| fParameters[index] = value; | |||
| switch (index) | |||
| { | |||
| case kParameterDELAY: | |||
| reverb->set_delay(value); | |||
| break; | |||
| case kParameterXOVER: | |||
| reverb->set_xover(value); | |||
| break; | |||
| case kParameterRTLOW: | |||
| reverb->set_rtlow(value); | |||
| break; | |||
| case kParameterRTMID: | |||
| reverb->set_rtmid(value); | |||
| break; | |||
| case kParameterFDAMP: | |||
| reverb->set_fdamp(value); | |||
| break; | |||
| case kParameterEQ1FR: | |||
| reverb->set_eq1(value, fParameters[kParameterEQ1GN]); | |||
| break; | |||
| case kParameterEQ1GN: | |||
| reverb->set_eq1(fParameters[kParameterEQ1FR], value); | |||
| break; | |||
| case kParameterEQ2FR: | |||
| reverb->set_eq2(value, fParameters[kParameterEQ2GN]); | |||
| break; | |||
| case kParameterEQ2GN: | |||
| reverb->set_eq2(fParameters[kParameterEQ2FR], value); | |||
| break; | |||
| case kParameterOPMIXorRGXYZ: | |||
| if (kIsAmbisonic) | |||
| reverb->set_rgxyz(value); | |||
| else | |||
| reverb->set_opmix(value); | |||
| break; | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin process calls | |||
| void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const, const uint32_t) override | |||
| { | |||
| if (! fJackClient.active) | |||
| { | |||
| const int iframes(static_cast<int>(frames)); | |||
| for (uint32_t i=0; i<kNumInputs; ++i) | |||
| FloatVectorOperations::clear(outBuffer[i], iframes); | |||
| return; | |||
| } | |||
| for (uint32_t i=0; i<kNumInputs; ++i) | |||
| fJackClient.portsAudioIn[i].buffer.audio = inBuffer[i]; | |||
| for (uint32_t i=0; i<kNumOutputs; ++i) | |||
| fJackClient.portsAudioOut[i].buffer.audio = outBuffer[i]; | |||
| fJackClient.processCallback(frames, fJackClient.processPtr); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin UI calls | |||
| void uiShow(const bool show) override | |||
| { | |||
| if (show) | |||
| { | |||
| if (display != nullptr) | |||
| return; | |||
| display = new X_display(nullptr); | |||
| if (display->dpy() == nullptr) | |||
| return hostUiUnavailable(); | |||
| styles_init(display, &xresman, getResourceDir()); | |||
| rootwin = new X_rootwin(display); | |||
| mainwin = new Mainwin(rootwin, &xresman, 0, 0, jclient, this); | |||
| rootwin->handle_event(); | |||
| mainwin->x_set_title(getUiName()); | |||
| handler = new X_handler(display, mainwin, EV_X11); | |||
| if (const uintptr_t winId = getUiParentId()) | |||
| XSetTransientForHint(display->dpy(), mainwin->win(), static_cast<Window>(winId)); | |||
| handler->next_event(); | |||
| XFlush(display->dpy()); | |||
| handlerThread.setupAndRun(handler, rootwin, mainwin); | |||
| } | |||
| else | |||
| { | |||
| if (handlerThread.isThreadRunning()) | |||
| handlerThread.stopThread(); | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| display = nullptr; | |||
| } | |||
| } | |||
| void uiIdle() override | |||
| { | |||
| if (mainwin == nullptr) | |||
| return; | |||
| if (handlerThread.wasClosed()) | |||
| { | |||
| { | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| handler = nullptr; | |||
| mainwin = nullptr; | |||
| rootwin = nullptr; | |||
| display = nullptr; | |||
| } | |||
| uiClosed(); | |||
| } | |||
| } | |||
| void uiSetParameterValue(const uint32_t index, const float value) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(index < kParameterNROTARY,); | |||
| if (mainwin == nullptr) | |||
| return; | |||
| uint32_t rindex = index; | |||
| if (kIsAmbisonic && index == kParameterOPMIXorRGXYZ) | |||
| rindex += 1; | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| mainwin->_rotary[rindex]->set_value(value); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Plugin dispatcher calls | |||
| void bufferSizeChanged(const uint32_t bufferSize) override | |||
| { | |||
| fJackClient.bufferSize = bufferSize; | |||
| } | |||
| void sampleRateChanged(const double sampleRate) override | |||
| { | |||
| fJackClient.sampleRate = sampleRate; | |||
| } | |||
| void uiNameChanged(const char* const uiName) override | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(uiName != nullptr && uiName[0] != '\0',); | |||
| if (mainwin == nullptr) | |||
| return; | |||
| const CarlaMutexLocker cml(handlerThread.getLock()); | |||
| mainwin->x_set_title(uiName); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| // Mainwin callbacks | |||
| void valueChangedCallback(uint rindex, double value) override | |||
| { | |||
| uint32_t index = rindex; | |||
| if (kIsAmbisonic && rindex == Mainwin::NROTARY) | |||
| index = kParameterOPMIXorRGXYZ; | |||
| fParameters[index] = value; | |||
| uiParameterChanged(index, value); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| private: | |||
| const bool kIsAmbisonic; | |||
| const uint32_t kNumInputs; | |||
| const uint32_t kNumOutputs; | |||
| // Fake jack client | |||
| jack_client_t fJackClient; | |||
| // Zita stuff (core) | |||
| X_resman xresman; | |||
| ScopedPointer<Jclient> jclient; | |||
| ScopedPointer<X_display> display; | |||
| ScopedPointer<X_rootwin> rootwin; | |||
| ScopedPointer<Mainwin> mainwin; | |||
| ScopedPointer<X_handler> handler; | |||
| X_handler_thread<Mainwin> handlerThread; | |||
| float fParameters[kParameterNROTARY]; | |||
| public: | |||
| static NativePluginHandle _instantiateAmbisonic(const NativeHostDescriptor* host) | |||
| { | |||
| return (host != nullptr) ? new REV1Plugin(host, true) : nullptr; | |||
| } | |||
| static NativePluginHandle _instantiateStereo(const NativeHostDescriptor* host) | |||
| { | |||
| return (host != nullptr) ? new REV1Plugin(host, false) : nullptr; | |||
| } | |||
| static void _cleanup(NativePluginHandle handle) | |||
| { | |||
| delete (REV1Plugin*)handle; | |||
| } | |||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(REV1Plugin) | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| static const NativePluginDescriptor rev1AmbisonicDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DELAY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 4, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ REV1Plugin::kParameterNROTARY, | |||
| /* paramOuts */ 0, | |||
| /* name */ "REV1 (Ambisonic)", | |||
| /* label */ "rev1-ambisonic", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| REV1Plugin::_instantiateAmbisonic, | |||
| REV1Plugin::_cleanup, | |||
| REV1Plugin::_get_parameter_count, | |||
| REV1Plugin::_get_parameter_info, | |||
| REV1Plugin::_get_parameter_value, | |||
| REV1Plugin::_get_parameter_text, | |||
| REV1Plugin::_get_midi_program_count, | |||
| REV1Plugin::_get_midi_program_info, | |||
| REV1Plugin::_set_parameter_value, | |||
| REV1Plugin::_set_midi_program, | |||
| REV1Plugin::_set_custom_data, | |||
| REV1Plugin::_ui_show, | |||
| REV1Plugin::_ui_idle, | |||
| REV1Plugin::_ui_set_parameter_value, | |||
| REV1Plugin::_ui_set_midi_program, | |||
| REV1Plugin::_ui_set_custom_data, | |||
| REV1Plugin::_activate, | |||
| REV1Plugin::_deactivate, | |||
| REV1Plugin::_process, | |||
| REV1Plugin::_get_state, | |||
| REV1Plugin::_set_state, | |||
| REV1Plugin::_dispatcher | |||
| }; | |||
| static const NativePluginDescriptor rev1StereoDesc = { | |||
| /* category */ NATIVE_PLUGIN_CATEGORY_DELAY, | |||
| /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_RTSAFE | |||
| |NATIVE_PLUGIN_HAS_UI | |||
| |NATIVE_PLUGIN_NEEDS_FIXED_BUFFERS | |||
| |NATIVE_PLUGIN_NEEDS_UI_MAIN_THREAD | |||
| |NATIVE_PLUGIN_USES_PARENT_ID), | |||
| /* supports */ static_cast<NativePluginSupports>(0x0), | |||
| /* audioIns */ 2, | |||
| /* audioOuts */ 2, | |||
| /* midiIns */ 0, | |||
| /* midiOuts */ 0, | |||
| /* paramIns */ REV1Plugin::kParameterNROTARY, | |||
| /* paramOuts */ 0, | |||
| /* name */ "REV1 (Stereo)", | |||
| /* label */ "rev1-stereo", | |||
| /* maker */ "falkTX, Fons Adriaensen", | |||
| /* copyright */ "GPL v2+", | |||
| REV1Plugin::_instantiateStereo, | |||
| REV1Plugin::_cleanup, | |||
| REV1Plugin::_get_parameter_count, | |||
| REV1Plugin::_get_parameter_info, | |||
| REV1Plugin::_get_parameter_value, | |||
| REV1Plugin::_get_parameter_text, | |||
| REV1Plugin::_get_midi_program_count, | |||
| REV1Plugin::_get_midi_program_info, | |||
| REV1Plugin::_set_parameter_value, | |||
| REV1Plugin::_set_midi_program, | |||
| REV1Plugin::_set_custom_data, | |||
| REV1Plugin::_ui_show, | |||
| REV1Plugin::_ui_idle, | |||
| REV1Plugin::_ui_set_parameter_value, | |||
| REV1Plugin::_ui_set_midi_program, | |||
| REV1Plugin::_ui_set_custom_data, | |||
| REV1Plugin::_activate, | |||
| REV1Plugin::_deactivate, | |||
| REV1Plugin::_process, | |||
| REV1Plugin::_get_state, | |||
| REV1Plugin::_set_state, | |||
| REV1Plugin::_dispatcher | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zita_rev1(); | |||
| CARLA_EXPORT | |||
| void carla_register_native_plugin_zita_rev1() | |||
| { | |||
| carla_register_native_plugin(&rev1AmbisonicDesc); | |||
| carla_register_native_plugin(&rev1StereoDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -0,0 +1,32 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@kokkinizita.net> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __GLOBAL_H | |||
| #define __GLOBAL_H | |||
| #define PROGNAME "zita-rev1" | |||
| #define EV_X11 16 | |||
| #define EV_EXIT 31 | |||
| #endif | |||
| @@ -0,0 +1,161 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <math.h> | |||
| #include "guiclass.h" | |||
| namespace REV1 { | |||
| Rlinctl::Rlinctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| RotaryImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini, | |||
| int cbind) : | |||
| RotaryCtl (parent, cbobj, image, xp, yp, cbind), | |||
| _cm (cm), | |||
| _dd (dd), | |||
| _vmin (vmin), | |||
| _vmax (vmax), | |||
| _form (0) | |||
| { | |||
| _count = -1; | |||
| set_value (vini); | |||
| } | |||
| void Rlinctl::get_string (char *p, int n) | |||
| { | |||
| if (_form) snprintf (p, n, _form, _value); | |||
| else *p = 0; | |||
| } | |||
| void Rlinctl::set_value (double v) | |||
| { | |||
| set_count ((int) floor (_cm * (v - _vmin) / (_vmax - _vmin) + 0.5)); | |||
| render (); | |||
| } | |||
| int Rlinctl::handle_button (void) | |||
| { | |||
| return PRESS; | |||
| } | |||
| int Rlinctl::handle_motion (int dx, int dy) | |||
| { | |||
| return set_count (_rcount + dx - dy); | |||
| } | |||
| int Rlinctl::handle_mwheel (int dw) | |||
| { | |||
| if (! (_keymod & ShiftMask)) dw *= _dd; | |||
| return set_count (_count + dw); | |||
| } | |||
| int Rlinctl::set_count (int u) | |||
| { | |||
| if (u < 0) u= 0; | |||
| if (u > _cm) u = _cm; | |||
| if (u != _count) | |||
| { | |||
| _count = u; | |||
| _value = _vmin + u * (_vmax - _vmin) / _cm; | |||
| _angle = 270.0 * ((double) u / _cm - 0.5); | |||
| return DELTA; | |||
| } | |||
| return 0; | |||
| } | |||
| Rlogctl::Rlogctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| RotaryImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini, | |||
| int cbind) : | |||
| RotaryCtl (parent, cbobj, image, xp, yp, cbind), | |||
| _cm (cm), | |||
| _dd (dd), | |||
| _form (0) | |||
| { | |||
| _count = -1; | |||
| _vmin = log (vmin); | |||
| _vmax = log (vmax); | |||
| set_value (vini); | |||
| } | |||
| void Rlogctl::get_string (char *p, int n) | |||
| { | |||
| if (_form) snprintf (p, n, _form, _value); | |||
| else *p = 0; | |||
| } | |||
| void Rlogctl::set_value (double v) | |||
| { | |||
| set_count ((int) floor (_cm * (log (v) - _vmin) / (_vmax - _vmin) + 0.5)); | |||
| render (); | |||
| } | |||
| int Rlogctl::handle_button (void) | |||
| { | |||
| return PRESS; | |||
| } | |||
| int Rlogctl::handle_motion (int dx, int dy) | |||
| { | |||
| return set_count (_rcount + dx - dy); | |||
| } | |||
| int Rlogctl::handle_mwheel (int dw) | |||
| { | |||
| if (! (_keymod & ShiftMask)) dw *= _dd; | |||
| return set_count (_count + dw); | |||
| } | |||
| int Rlogctl::set_count (int u) | |||
| { | |||
| if (u < 0) u= 0; | |||
| if (u > _cm) u = _cm; | |||
| if (u != _count) | |||
| { | |||
| _count = u; | |||
| _value = exp (_vmin + u * (_vmax - _vmin) / _cm); | |||
| _angle = 270.0 * ((double) u / _cm - 0.5); | |||
| return DELTA; | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,103 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __GUICLASS_H | |||
| #define __GUICLASS_H | |||
| #include "rotary.h" | |||
| namespace REV1 { | |||
| class Rlinctl : public RotaryCtl | |||
| { | |||
| public: | |||
| Rlinctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| RotaryImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini, | |||
| int cbind = 0); | |||
| virtual void set_value (double v); | |||
| virtual void get_string (char *p, int n); | |||
| private: | |||
| virtual int handle_button (void); | |||
| virtual int handle_motion (int dx, int dy); | |||
| virtual int handle_mwheel (int dw); | |||
| int set_count (int u); | |||
| int _cm; | |||
| int _dd; | |||
| double _vmin; | |||
| double _vmax; | |||
| const char *_form; | |||
| }; | |||
| class Rlogctl : public RotaryCtl | |||
| { | |||
| public: | |||
| Rlogctl (X_window *parent, | |||
| X_callback *cbobj, | |||
| RotaryImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cm, | |||
| int dd, | |||
| double vmin, | |||
| double vmax, | |||
| double vini, | |||
| int cbind = 0); | |||
| virtual void set_value (double v); | |||
| virtual void get_string (char *p, int n); | |||
| private: | |||
| virtual int handle_button (void); | |||
| virtual int handle_motion (int dx, int dy); | |||
| virtual int handle_mwheel (int dw); | |||
| int set_count (int u); | |||
| int _cm; | |||
| int _dd; | |||
| double _vmin; | |||
| double _vmax; | |||
| const char *_form; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,140 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include "jclient.h" | |||
| namespace REV1 { | |||
| Jclient::Jclient (const char *jname, jack_client_t *jclient, bool ambis) : | |||
| A_thread ("Jclient"), | |||
| _jack_client (jclient), | |||
| _active (false), | |||
| _jname (0), | |||
| _ambis (ambis) | |||
| { | |||
| init_jack (jname); | |||
| } | |||
| Jclient::~Jclient (void) | |||
| { | |||
| if (_jack_client) close_jack (); | |||
| } | |||
| void Jclient::init_jack (const char *jname) | |||
| { | |||
| jack_set_process_callback (_jack_client, jack_static_process, (void *) this); | |||
| jack_on_shutdown (_jack_client, jack_static_shutdown, (void *) this); | |||
| if (jack_activate (_jack_client)) | |||
| { | |||
| fprintf(stderr, "Can't activate JACK.\n"); | |||
| exit (1); | |||
| } | |||
| _jname = jack_get_client_name (_jack_client); | |||
| _fsamp = jack_get_sample_rate (_jack_client); | |||
| _fragm = 1024; | |||
| _nsamp = 0; | |||
| if (_ambis) | |||
| { | |||
| _inpports [0] = jack_port_register (_jack_client, "in.L", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| _inpports [1] = jack_port_register (_jack_client, "in.R", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| _outports [0] = jack_port_register (_jack_client, "out.W", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| _outports [1] = jack_port_register (_jack_client, "out.X", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| _outports [2] = jack_port_register (_jack_client, "out.Y", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| _outports [3] = jack_port_register (_jack_client, "out.Z", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| } | |||
| else | |||
| { | |||
| _inpports [0] = jack_port_register (_jack_client, "in.L", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| _inpports [1] = jack_port_register (_jack_client, "in.R", JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); | |||
| _outports [0] = jack_port_register (_jack_client, "out.L", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| _outports [1] = jack_port_register (_jack_client, "out.R", JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); | |||
| } | |||
| _reverb.init (_fsamp, _ambis); | |||
| _active = true; | |||
| } | |||
| void Jclient::close_jack () | |||
| { | |||
| jack_deactivate (_jack_client); | |||
| jack_client_close (_jack_client); | |||
| } | |||
| void Jclient::jack_static_shutdown (void *arg) | |||
| { | |||
| ((Jclient *) arg)->jack_shutdown (); | |||
| } | |||
| int Jclient::jack_static_process (jack_nframes_t nframes, void *arg) | |||
| { | |||
| return ((Jclient *) arg)->jack_process (nframes); | |||
| } | |||
| void Jclient::jack_shutdown (void) | |||
| { | |||
| send_event (EV_EXIT, 1); | |||
| } | |||
| int Jclient::jack_process (int frames) | |||
| { | |||
| int i, k, n_inp, n_out; | |||
| float *inp [2]; | |||
| float *out [4]; | |||
| if (!_active) return 0; | |||
| n_inp = 2; | |||
| n_out = _ambis ? 4 : 2; | |||
| for (i = 0; i < n_inp; i++) inp [i] = (float *) jack_port_get_buffer (_inpports [i], frames); | |||
| for (i = 0; i < n_out; i++) out [i] = (float *) jack_port_get_buffer (_outports [i], frames); | |||
| while (frames) | |||
| { | |||
| if (!_nsamp) | |||
| { | |||
| _reverb.prepare (_fragm); | |||
| _nsamp = _fragm; | |||
| } | |||
| k = (_nsamp < frames) ? _nsamp : frames; | |||
| _reverb.process (k, inp, out); | |||
| for (i = 0; i < n_inp; i++) inp [i] += k; | |||
| for (i = 0; i < n_out; i++) out [i] += k; | |||
| frames -= k; | |||
| _nsamp -= k; | |||
| } | |||
| return 0; | |||
| } | |||
| } | |||
| @@ -0,0 +1,72 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __JCLIENT_H | |||
| #define __JCLIENT_H | |||
| #include <clthreads.h> | |||
| #include "CarlaNativeJack.h" | |||
| #include "global.h" | |||
| #include "reverb.h" | |||
| namespace REV1 { | |||
| class Jclient : public A_thread | |||
| { | |||
| public: | |||
| Jclient (const char *jname, jack_client_t *jclient, bool ambis); | |||
| ~Jclient (void); | |||
| const char *jname (void) const { return _jname; } | |||
| Reverb *reverb (void) const { return (Reverb *) &_reverb; } | |||
| private: | |||
| void init_jack (const char *jname); | |||
| void close_jack (void); | |||
| void jack_shutdown (void); | |||
| int jack_process (int nframes); | |||
| virtual void thr_main (void) {} | |||
| jack_client_t *_jack_client; | |||
| jack_port_t *_inpports [2]; | |||
| jack_port_t *_outports [4]; | |||
| bool _active; | |||
| const char *_jname; | |||
| unsigned int _fsamp; | |||
| bool _ambis; | |||
| int _fragm; | |||
| int _nsamp; | |||
| Reverb _reverb; | |||
| static void jack_static_shutdown (void *arg); | |||
| static int jack_static_process (jack_nframes_t nframes, void *arg); | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,245 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <math.h> | |||
| #include "styles.h" | |||
| #include "global.h" | |||
| #include "mainwin.h" | |||
| namespace REV1 { | |||
| Mainwin::Mainwin (X_rootwin *parent, X_resman *xres, int xp, int yp, Jclient *jclient, ValueChangedCallback* valuecb) : | |||
| A_thread ("Main"), | |||
| X_window (parent, xp, yp, XSIZE, YSIZE, XftColors [C_MAIN_BG]->pixel), | |||
| _stop (false), | |||
| _xres (xres), | |||
| _jclient (jclient), | |||
| _valuecb (valuecb) | |||
| { | |||
| X_hints H; | |||
| char s [256]; | |||
| int i, x; | |||
| _atom = XInternAtom (dpy (), "WM_DELETE_WINDOW", True); | |||
| XSetWMProtocols (dpy (), win (), &_atom, 1); | |||
| _atom = XInternAtom (dpy (), "WM_PROTOCOLS", True); | |||
| sprintf (s, "%s", jclient->jname ()); | |||
| x_set_title (s); | |||
| H.position (xp, yp); | |||
| H.minsize (XSIZE, YSIZE); | |||
| H.maxsize (XSIZE, YSIZE); | |||
| H.rname (xres->rname ()); | |||
| H.rclas (xres->rclas ()); | |||
| x_apply (&H); | |||
| _ambis = xres->getb (".ambisonic", false); | |||
| RotaryCtl::init (disp ()); | |||
| x = 0; | |||
| _rotary [R_DELAY] = new Rlinctl (this, this, &r_delay_img, x, 0, 160, 5, 0.02, 0.100, 0.04, R_DELAY); | |||
| _rotary [R_XOVER] = new Rlogctl (this, this, &r_xover_img, x, 0, 200, 5, 50.0, 1000.0, 200.0, R_XOVER); | |||
| _rotary [R_RTLOW] = new Rlogctl (this, this, &r_rtlow_img, x, 0, 200, 5, 1.0, 8.0, 3.0, R_RTLOW); | |||
| _rotary [R_RTMID] = new Rlogctl (this, this, &r_rtmid_img, x, 0, 200, 5, 1.0, 8.0, 2.0, R_RTMID); | |||
| _rotary [R_FDAMP] = new Rlogctl (this, this, &r_fdamp_img, x, 0, 200, 5, 1.5e3, 24.0e3, 6.0e3, R_FDAMP); | |||
| x += 315; | |||
| _rotary [R_EQ1FR] = new Rlogctl (this, this, &r_parfr_img, x, 0, 180, 5, 40.0, 2.5e3, 160.0, R_EQ1FR); | |||
| _rotary [R_EQ1GN] = new Rlinctl (this, this, &r_pargn_img, x, 0, 150, 5, -15.0, 15.0, 0.0, R_EQ1GN); | |||
| x += 110; | |||
| _rotary [R_EQ2FR] = new Rlogctl (this, this, &r_parfr_img, x, 0, 180, 5, 160.0, 10e3, 2.5e3, R_EQ2FR); | |||
| _rotary [R_EQ2GN] = new Rlinctl (this, this, &r_pargn_img, x, 0, 150, 5, -15.0, 15.0, 0.0, R_EQ2GN); | |||
| x += 110; | |||
| _rotary [R_OPMIX] = new Rlinctl (this, this, &r_opmix_img, x, 0, 180, 5, 0.0 , 1.0, 0.5, R_OPMIX); | |||
| _rotary [R_RGXYZ] = new Rlinctl (this, this, &r_rgxyz_img, x, 0, 180, 5, -9.0 , 9.0, 0.0, R_RGXYZ); | |||
| for (i = 0; i < R_OPMIX; i++) _rotary [i]->x_map (); | |||
| if (_ambis) _rotary [R_RGXYZ]->x_map (); | |||
| else _rotary [R_OPMIX]->x_map (); | |||
| x_add_events (ExposureMask); | |||
| x_map (); | |||
| set_time (0); | |||
| inc_time (500000); | |||
| } | |||
| Mainwin::~Mainwin (void) | |||
| { | |||
| RotaryCtl::fini (); | |||
| } | |||
| int Mainwin::process (void) | |||
| { | |||
| int e; | |||
| if (_stop) handle_stop (); | |||
| e = get_event_timed (); | |||
| switch (e) | |||
| { | |||
| case EV_TIME: | |||
| handle_time (); | |||
| break; | |||
| } | |||
| return e; | |||
| } | |||
| void Mainwin::handle_event (XEvent *E) | |||
| { | |||
| switch (E->type) | |||
| { | |||
| case Expose: | |||
| expose ((XExposeEvent *) E); | |||
| break; | |||
| case ClientMessage: | |||
| clmesg ((XClientMessageEvent *) E); | |||
| break; | |||
| } | |||
| } | |||
| void Mainwin::expose (XExposeEvent *E) | |||
| { | |||
| if (E->count) return; | |||
| redraw (); | |||
| } | |||
| void Mainwin::clmesg (XClientMessageEvent *E) | |||
| { | |||
| if (E->message_type == _atom) _stop = true; | |||
| } | |||
| void Mainwin::handle_time (void) | |||
| { | |||
| inc_time (500000); | |||
| // XFlush (dpy ()); | |||
| } | |||
| void Mainwin::handle_stop (void) | |||
| { | |||
| put_event (EV_EXIT, 1); | |||
| } | |||
| void Mainwin::handle_callb (int type, X_window *W, XEvent *E) | |||
| { | |||
| RotaryCtl *R; | |||
| int k; | |||
| double v, v2; | |||
| switch (type) | |||
| { | |||
| case RotaryCtl::PRESS: | |||
| R = (RotaryCtl *) W; | |||
| k = R->cbind (); | |||
| switch (k) | |||
| { | |||
| default: | |||
| ; | |||
| } | |||
| break; | |||
| case RotaryCtl::DELTA: | |||
| R = (RotaryCtl *) W; | |||
| k = R->cbind (); | |||
| switch (k) | |||
| { | |||
| case R_DELAY: | |||
| v = _rotary [R_DELAY]->value (); | |||
| _jclient->reverb ()->set_delay (v); | |||
| _valuecb->valueChangedCallback (R_DELAY, v); | |||
| break; | |||
| case R_XOVER: | |||
| v = _rotary [R_XOVER]->value (); | |||
| _jclient->reverb ()->set_xover (v); | |||
| _valuecb->valueChangedCallback (R_XOVER, v); | |||
| break; | |||
| case R_RTLOW: | |||
| v = _rotary [R_RTLOW]->value (); | |||
| _jclient->reverb ()->set_rtlow (v); | |||
| _valuecb->valueChangedCallback (R_RTLOW, v); | |||
| break; | |||
| case R_RTMID: | |||
| v = _rotary [R_RTMID]->value (); | |||
| _jclient->reverb ()->set_rtmid (v); | |||
| _valuecb->valueChangedCallback (R_RTMID, v); | |||
| break; | |||
| case R_FDAMP: | |||
| v = _rotary [R_FDAMP]->value (); | |||
| _jclient->reverb ()->set_fdamp (v); | |||
| _valuecb->valueChangedCallback (R_FDAMP, v); | |||
| break; | |||
| case R_OPMIX: | |||
| v = _rotary [R_OPMIX]->value (); | |||
| _jclient->reverb ()->set_opmix (v); | |||
| _valuecb->valueChangedCallback (R_OPMIX, v); | |||
| break; | |||
| case R_RGXYZ: | |||
| v = _rotary [R_RGXYZ]->value (); | |||
| _jclient->reverb ()->set_rgxyz (v); | |||
| _valuecb->valueChangedCallback (R_RGXYZ, v); | |||
| break; | |||
| case R_EQ1FR: | |||
| case R_EQ1GN: | |||
| v = _rotary [R_EQ1FR]->value (), v2 = _rotary [R_EQ1GN]->value (); | |||
| _jclient->reverb ()->set_eq1 (v, v2); | |||
| _valuecb->valueChangedCallback (R_EQ1FR, v); | |||
| _valuecb->valueChangedCallback (R_EQ1GN, v2); | |||
| break; | |||
| case R_EQ2FR: | |||
| case R_EQ2GN: | |||
| v = _rotary [R_EQ2FR]->value (), v2 = _rotary [R_EQ2GN]->value (); | |||
| _jclient->reverb ()->set_eq2 (v, v2); | |||
| _valuecb->valueChangedCallback (R_EQ2FR, v); | |||
| _valuecb->valueChangedCallback (R_EQ2GN, v2); | |||
| break; | |||
| } | |||
| break; | |||
| } | |||
| } | |||
| void Mainwin::redraw (void) | |||
| { | |||
| int x; | |||
| x = 0; | |||
| XPutImage (dpy (), win (), dgc (), revsect_img, 0, 0, x, 0, 310, 75); | |||
| x += 315; | |||
| XPutImage (dpy (), win (), dgc (), eq1sect_img, 0, 0, x, 0, 110, 75); | |||
| x += 110; | |||
| XPutImage (dpy (), win (), dgc (), eq2sect_img, 0, 0, x, 0, 110, 75); | |||
| x += 110; | |||
| if (_ambis) XPutImage (dpy (), win (), dgc (), ambsect_img, 0, 0, x, 0, 70, 75); | |||
| else XPutImage (dpy (), win (), dgc (), mixsect_img, 0, 0, x, 0, 70, 75); | |||
| x += 70; | |||
| } | |||
| } | |||
| @@ -0,0 +1,88 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __MAINWIN_H | |||
| #define __MAINWIN_H | |||
| #include <clxclient.h> | |||
| #include "guiclass.h" | |||
| #include "jclient.h" | |||
| #include "global.h" | |||
| class REV1Plugin; | |||
| namespace REV1 { | |||
| class Mainwin : public A_thread, public X_window, public X_callback | |||
| { | |||
| public: | |||
| struct ValueChangedCallback { | |||
| virtual ~ValueChangedCallback() {} | |||
| virtual void valueChangedCallback(uint, double) = 0; | |||
| }; | |||
| enum { XSIZE = 540, YSIZE = 75 }; | |||
| Mainwin (X_rootwin *parent, X_resman *xres, int xp, int yp, Jclient *jclient, ValueChangedCallback* valuecb); | |||
| ~Mainwin (void); | |||
| Mainwin (const Mainwin&); | |||
| Mainwin& operator=(const Mainwin&); | |||
| void stop (void) { _stop = true; } | |||
| int process (void); | |||
| private: | |||
| enum { R_DELAY, R_XOVER, R_RTLOW, R_RTMID, R_FDAMP, | |||
| R_EQ1FR, R_EQ1GN, R_EQ2FR, R_EQ2GN, | |||
| R_OPMIX, R_RGXYZ, NROTARY }; | |||
| virtual void thr_main (void) {} | |||
| void handle_time (void); | |||
| void handle_stop (void); | |||
| void handle_event (XEvent *); | |||
| void handle_callb (int type, X_window *W, XEvent *E); | |||
| void expose (XExposeEvent *E); | |||
| void clmesg (XClientMessageEvent *E); | |||
| void redraw (void); | |||
| Atom _atom; | |||
| bool _stop; | |||
| bool _ambis; | |||
| X_resman *_xres; | |||
| Jclient *_jclient; | |||
| RotaryCtl *_rotary [NROTARY]; | |||
| ValueChangedCallback* _valuecb; | |||
| friend class ::REV1Plugin; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,200 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <math.h> | |||
| #include <string.h> | |||
| #include "pareq.h" | |||
| namespace REV1 { | |||
| Pareq::Pareq (void) : | |||
| _touch0 (0), | |||
| _touch1 (0), | |||
| _state (BYPASS), | |||
| _g0 (1), | |||
| _g1 (1), | |||
| _f0 (1e3f), | |||
| _f1 (1e3f) | |||
| { | |||
| setfsamp (0.0f); | |||
| } | |||
| Pareq::~Pareq (void) | |||
| { | |||
| } | |||
| void Pareq::setfsamp (float fsamp) | |||
| { | |||
| _fsamp = fsamp; | |||
| reset (); | |||
| } | |||
| void Pareq::reset (void) | |||
| { | |||
| memset (_z1, 0, sizeof (float) * MAXCH); | |||
| memset (_z2, 0, sizeof (float) * MAXCH); | |||
| } | |||
| void Pareq::prepare (int nsamp) | |||
| { | |||
| bool upd = false; | |||
| float g, f; | |||
| if (_touch1 != _touch0) | |||
| { | |||
| g = _g0; | |||
| f = _f0; | |||
| if (g != _g1) | |||
| { | |||
| upd = true; | |||
| if (g > 2 * _g1) _g1 *= 2; | |||
| else if (_g1 > 2 * g) _g1 /= 2; | |||
| else _g1 = g; | |||
| } | |||
| if (f != _f1) | |||
| { | |||
| upd = true; | |||
| if (f > 2 * _f1) _f1 *= 2; | |||
| else if (_f1 > 2 * f) _f1 /= 2; | |||
| else _f1 = f; | |||
| } | |||
| if (upd) | |||
| { | |||
| if ((_state == BYPASS) && (_g1 == 1)) | |||
| { | |||
| calcpar1 (0, _g1, _f1); | |||
| } | |||
| else | |||
| { | |||
| _state = SMOOTH; | |||
| calcpar1 (nsamp, _g1, _f1); | |||
| } | |||
| } | |||
| else | |||
| { | |||
| _touch1 = _touch0; | |||
| if (fabs (_g1 - 1) < 0.001f) | |||
| { | |||
| _state = BYPASS; | |||
| reset (); | |||
| } | |||
| else | |||
| { | |||
| _state = STATIC; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void Pareq::calcpar1 (int nsamp, float g, float f) | |||
| { | |||
| float b, c1, c2, gg; | |||
| f *= float (M_PI) / _fsamp; | |||
| b = 2 * f / sqrtf (g); | |||
| gg = 0.5f * (g - 1); | |||
| c1 = -cosf (2 * f); | |||
| c2 = (1 - b) / (1 + b); | |||
| if (nsamp) | |||
| { | |||
| _dc1 = (c1 - _c1) / nsamp + 1e-30f; | |||
| _dc2 = (c2 - _c2) / nsamp + 1e-30f; | |||
| _dgg = (gg - _gg) / nsamp + 1e-30f; | |||
| } | |||
| else | |||
| { | |||
| _c1 = c1; | |||
| _c2 = c2; | |||
| _gg = gg; | |||
| } | |||
| } | |||
| void Pareq::process1 (int nsamp, int nchan, float *data[]) | |||
| { | |||
| int i, j; | |||
| float c1, c2, gg; | |||
| float x, y, z1, z2; | |||
| float *p; | |||
| c1 = _c1; | |||
| c2 = _c2; | |||
| gg = _gg; | |||
| if (_state == SMOOTH) | |||
| { | |||
| for (i = 0; i < nchan; i++) | |||
| { | |||
| p = data [i]; | |||
| z1 = _z1 [i]; | |||
| z2 = _z2 [i]; | |||
| c1 = _c1; | |||
| c2 = _c2; | |||
| gg = _gg; | |||
| for (j = 0; j < nsamp; j++) | |||
| { | |||
| c1 += _dc1; | |||
| c2 += _dc2; | |||
| gg += _dgg; | |||
| x = *p; | |||
| y = x - c2 * z2; | |||
| *p++ = x - gg * (z2 + c2 * y - x); | |||
| y -= c1 * z1; | |||
| z2 = z1 + c1 * y; | |||
| z1 = y + 1e-20f; | |||
| } | |||
| _z1 [i] = z1; | |||
| _z2 [i] = z2; | |||
| } | |||
| _c1 = c1; | |||
| _c2 = c2; | |||
| _gg = gg; | |||
| } | |||
| else | |||
| { | |||
| for (i = 0; i < nchan; i++) | |||
| { | |||
| p = data [i]; | |||
| z1 = _z1 [i]; | |||
| z2 = _z2 [i]; | |||
| for (j = 0; j < nsamp; j++) | |||
| { | |||
| x = *p; | |||
| y = x - c2 * z2; | |||
| *p++ = x - gg * (z2 + c2 * y - x); | |||
| y -= c1 * z1; | |||
| z2 = z1 + c1 * y; | |||
| z1 = y + 1e-20f; | |||
| } | |||
| _z1 [i] = z1; | |||
| _z2 [i] = z2; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| @@ -0,0 +1,81 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __PAREQ_H | |||
| #define __PAREQ_H | |||
| #include <stdint.h> | |||
| #include <math.h> | |||
| #include "global.h" | |||
| namespace REV1 { | |||
| class Pareq | |||
| { | |||
| public: | |||
| Pareq (void); | |||
| ~Pareq (void); | |||
| void setfsamp (float fsamp); | |||
| void setparam (float f, float g) | |||
| { | |||
| _f0 = f; | |||
| _g0 = powf (10.0f, 0.05f * g); | |||
| _touch0++; | |||
| } | |||
| void reset (void); | |||
| void prepare (int nsamp); | |||
| void process (int nsamp, int nchan, float *data[]) | |||
| { | |||
| if (_state != BYPASS) process1 (nsamp, nchan, data); | |||
| } | |||
| private: | |||
| enum { BYPASS, STATIC, SMOOTH, MAXCH = 4 }; | |||
| void calcpar1 (int nsamp, float g, float f); | |||
| void process1 (int nsamp, int nchan, float *data[]); | |||
| volatile int16_t _touch0; | |||
| volatile int16_t _touch1; | |||
| bool _bypass; | |||
| int _state; | |||
| float _fsamp; | |||
| float _g0, _g1; | |||
| float _f0, _f1; | |||
| float _c1, _dc1; | |||
| float _c2, _dc2; | |||
| float _gg, _dgg; | |||
| float _z1 [MAXCH]; | |||
| float _z2 [MAXCH]; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,136 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2007-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <png.h> | |||
| #include <clxclient.h> | |||
| namespace REV1 { | |||
| XImage *png2img (const char *file, X_display *disp, XftColor *bgnd) | |||
| { | |||
| FILE *F; | |||
| png_byte hdr [8]; | |||
| png_structp png_ptr; | |||
| png_infop png_info; | |||
| const unsigned char **data, *p; | |||
| int dx, dy, x, y, dp; | |||
| float vr, vg, vb, va, br, bg, bb; | |||
| unsigned long mr, mg, mb, pix; | |||
| XImage *image; | |||
| F = fopen (file, "r"); | |||
| if (!F) | |||
| { | |||
| fprintf (stderr, "Can't open '%s'\n", file); | |||
| return 0; | |||
| } | |||
| fread (hdr, 1, 8, F); | |||
| if (png_sig_cmp (hdr, 0, 8)) | |||
| { | |||
| fprintf (stderr, "'%s' is not a PNG file\n", file); | |||
| return 0; | |||
| } | |||
| fseek (F, 0, SEEK_SET); | |||
| png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, 0, 0, 0); | |||
| if (! png_ptr) | |||
| { | |||
| fclose (F); | |||
| return 0; | |||
| } | |||
| png_info = png_create_info_struct (png_ptr); | |||
| if (! png_info) | |||
| { | |||
| png_destroy_read_struct (&png_ptr, 0, 0); | |||
| fclose (F); | |||
| return 0; | |||
| } | |||
| if (setjmp (png_jmpbuf (png_ptr))) | |||
| { | |||
| png_destroy_read_struct (&png_ptr, &png_info, 0); | |||
| fclose (F); | |||
| fprintf (stderr, "png:longjmp()\n"); | |||
| return 0; | |||
| } | |||
| png_init_io (png_ptr, F); | |||
| png_read_png (png_ptr, png_info, | |||
| PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_PACKING | PNG_TRANSFORM_EXPAND, | |||
| 0); | |||
| // This requires libpng14 or later. If you still have an | |||
| // older version, use the three commented lines instead. | |||
| dx = png_get_image_width (png_ptr, png_info); | |||
| dy = png_get_image_height (png_ptr, png_info); | |||
| dp = (png_get_color_type (png_ptr, png_info) & PNG_COLOR_MASK_ALPHA) ? 4 : 3; | |||
| // dx = png_info->width; | |||
| // dy = png_info->height; | |||
| // dp = (png_info->color_type & PNG_COLOR_MASK_ALPHA) ? 4 : 3; | |||
| data = (const unsigned char **)(png_get_rows (png_ptr, png_info)); | |||
| image = XCreateImage (disp->dpy (), | |||
| disp->dvi (), | |||
| DefaultDepth (disp->dpy (), disp->dsn ()), | |||
| ZPixmap, 0, 0, dx, dy, 32, 0); | |||
| image->data = new char [image->height * image->bytes_per_line]; | |||
| mr = image->red_mask; | |||
| mg = image->green_mask; | |||
| mb = image->blue_mask; | |||
| vr = mr / 255.0f; | |||
| vg = mg / 255.0f; | |||
| vb = mb / 255.0f; | |||
| if (bgnd) | |||
| { | |||
| br = bgnd->color.red >> 8; | |||
| bg = bgnd->color.green >> 8; | |||
| bb = bgnd->color.blue >> 8; | |||
| } | |||
| else br = bg = bb = 0; | |||
| for (y = 0; y < dy; y++) | |||
| { | |||
| p = data [y]; | |||
| for (x = 0; x < dx; x++) | |||
| { | |||
| va = (dp == 4) ? (p [3] / 255.0f) : 1; | |||
| pix = ((unsigned long)((p [0] * va + (1 - va) * br) * vr) & mr) | |||
| | ((unsigned long)((p [1] * va + (1 - va) * bg) * vg) & mg) | |||
| | ((unsigned long)((p [2] * va + (1 - va) * bb) * vb) & mb); | |||
| XPutPixel (image, x, y, pix); | |||
| p += dp; | |||
| } | |||
| } | |||
| png_destroy_read_struct (&png_ptr, &png_info, 0); | |||
| fclose (F); | |||
| return image; | |||
| } | |||
| } | |||
| @@ -0,0 +1,35 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2007-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __PNG2IMG_H | |||
| #define __PNG2IMG_H | |||
| #include <clxclient.h> | |||
| namespace REV1 { | |||
| extern XImage *png2img (const char *file, X_display *disp, XftColor *bgnd); | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,380 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2003-2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ----------------------------------------------------------------------- | |||
| #include <stdio.h> | |||
| #include <string.h> | |||
| #include <math.h> | |||
| #include "reverb.h" | |||
| namespace REV1 { | |||
| // ----------------------------------------------------------------------- | |||
| Diff1::Diff1 (void) : | |||
| _size (0), | |||
| _line (0) | |||
| { | |||
| } | |||
| Diff1::~Diff1 (void) | |||
| { | |||
| fini (); | |||
| } | |||
| void Diff1::init (int size, float c) | |||
| { | |||
| _size = size; | |||
| _line = new float [size]; | |||
| memset (_line, 0, size * sizeof (float)); | |||
| _i = 0; | |||
| _c = c; | |||
| } | |||
| void Diff1::fini (void) | |||
| { | |||
| delete[] _line; | |||
| _size = 0; | |||
| _line = 0; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Delay::Delay (void) : | |||
| _size (0), | |||
| _line (0) | |||
| { | |||
| } | |||
| Delay::~Delay (void) | |||
| { | |||
| fini (); | |||
| } | |||
| void Delay::init (int size) | |||
| { | |||
| _size = size; | |||
| _line = new float [size]; | |||
| memset (_line, 0, size * sizeof (float)); | |||
| _i = 0; | |||
| } | |||
| void Delay::fini (void) | |||
| { | |||
| delete[] _line; | |||
| _size = 0; | |||
| _line = 0; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| Vdelay::Vdelay (void) : | |||
| _size (0), | |||
| _line (0) | |||
| { | |||
| } | |||
| Vdelay::~Vdelay (void) | |||
| { | |||
| fini (); | |||
| } | |||
| void Vdelay::init (int size) | |||
| { | |||
| _size = size; | |||
| _line = new float [size]; | |||
| memset (_line, 0, size * sizeof (float)); | |||
| _ir = 0; | |||
| _iw = 0; | |||
| } | |||
| void Vdelay::fini (void) | |||
| { | |||
| delete[] _line; | |||
| _size = 0; | |||
| _line = 0; | |||
| } | |||
| void Vdelay::set_delay (int del) | |||
| { | |||
| _ir = _iw - del; | |||
| if (_ir < 0) _ir += _size; | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| void Filt1::set_params (float del, float tmf, float tlo, float wlo, float thi, float chi) | |||
| { | |||
| float g, t; | |||
| _gmf = powf (0.001f, del / tmf); | |||
| _glo = powf (0.001f, del / tlo) / _gmf - 1.0f; | |||
| _wlo = wlo; | |||
| g = powf (0.001f, del / thi) / _gmf; | |||
| t = (1 - g * g) / (2 * g * g * chi); | |||
| _whi = (sqrtf (1 + 4 * t) - 1) / (2 * t); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| float Reverb::_tdiff1 [8] = | |||
| { | |||
| 20346e-6f, | |||
| 24421e-6f, | |||
| 31604e-6f, | |||
| 27333e-6f, | |||
| 22904e-6f, | |||
| 29291e-6f, | |||
| 13458e-6f, | |||
| 19123e-6f | |||
| }; | |||
| float Reverb::_tdelay [8] = | |||
| { | |||
| 153129e-6f, | |||
| 210389e-6f, | |||
| 127837e-6f, | |||
| 256891e-6f, | |||
| 174713e-6f, | |||
| 192303e-6f, | |||
| 125000e-6f, | |||
| 219991e-6f | |||
| }; | |||
| Reverb::Reverb (void) | |||
| { | |||
| } | |||
| Reverb::~Reverb (void) | |||
| { | |||
| fini (); | |||
| } | |||
| void Reverb::init (float fsamp, bool ambis) | |||
| { | |||
| int i, k1, k2; | |||
| _fsamp = fsamp; | |||
| _ambis = ambis; | |||
| _cntA1 = 1; | |||
| _cntA2 = 0; | |||
| _cntB1 = 1; | |||
| _cntB2 = 0; | |||
| _cntC1 = 1; | |||
| _cntC2 = 0; | |||
| _ipdel = 0.04f; | |||
| _xover = 200.0f; | |||
| _rtlow = 3.0f; | |||
| _rtmid = 2.0f; | |||
| _fdamp = 3e3f; | |||
| _opmix = 0.5f; | |||
| _rgxyz = 0.0f; | |||
| _g0 = _d0 = 0; | |||
| _g1 = _d1 = 0; | |||
| _vdelay0.init ((int)(0.1f * _fsamp)); | |||
| _vdelay1.init ((int)(0.1f * _fsamp)); | |||
| for (i = 0; i < 8; i++) | |||
| { | |||
| k1 = (int)(floorf (_tdiff1 [i] * _fsamp + 0.5f)); | |||
| k2 = (int)(floorf (_tdelay [i] * _fsamp + 0.5f)); | |||
| _diff1 [i].init (k1, (i & 1) ? -0.6f : 0.6f); | |||
| _delay [i].init (k2 - k1); | |||
| } | |||
| _pareq1.setfsamp (fsamp); | |||
| _pareq2.setfsamp (fsamp); | |||
| } | |||
| void Reverb::fini (void) | |||
| { | |||
| for (int i = 0; i < 8; i++) _delay [i].fini (); | |||
| } | |||
| void Reverb::prepare (int nfram) | |||
| { | |||
| int a, b, c, i, k; | |||
| float t0, t1, wlo, chi; | |||
| a = _cntA1; | |||
| b = _cntB1; | |||
| c = _cntC1; | |||
| _d0 = _d1 = 0; | |||
| if (a != _cntA2) | |||
| { | |||
| k = (int)(floorf ((_ipdel - 0.020f) * _fsamp + 0.5f)); | |||
| _vdelay0.set_delay (k); | |||
| _vdelay1.set_delay (k); | |||
| _cntA2 = a; | |||
| } | |||
| if (b != _cntB2) | |||
| { | |||
| wlo = 6.2832f * _xover / _fsamp; | |||
| if (_fdamp > 0.49f * _fsamp) chi = 2; | |||
| else chi = 1 - cosf (6.2832f * _fdamp / _fsamp); | |||
| for (i = 0; i < 8; i++) | |||
| { | |||
| _filt1 [i].set_params (_tdelay [i], _rtmid, _rtlow, wlo, 0.5f * _rtmid, chi); | |||
| } | |||
| _cntB2 = b; | |||
| } | |||
| if (c != _cntC2) | |||
| { | |||
| if (_ambis) | |||
| { | |||
| t0 = 1.0f / sqrtf (_rtmid); | |||
| t1 = t0 * powf (10.0f, 0.05f * _rgxyz); | |||
| } | |||
| else | |||
| { | |||
| t0 = (1 - _opmix) * (1 + _opmix); | |||
| t1 = 0.7f * _opmix * (2 - _opmix) / sqrtf (_rtmid); | |||
| } | |||
| _d0 = (t0 - _g0) / nfram; | |||
| _d1 = (t1 - _g1) / nfram; | |||
| _cntC2 = c; | |||
| } | |||
| _pareq1.prepare (nfram); | |||
| _pareq2.prepare (nfram); | |||
| } | |||
| void Reverb::process (int nfram, float *inp [], float *out []) | |||
| { | |||
| int i, n; | |||
| float *p0, *p1; | |||
| float *q0, *q1, *q2, *q3; | |||
| float t, g, x0, x1, x2, x3, x4, x5, x6, x7; | |||
| g = sqrtf (0.125f); | |||
| p0 = inp [0]; | |||
| p1 = inp [1]; | |||
| q0 = out [0]; | |||
| q1 = out [1]; | |||
| q2 = out [2]; | |||
| q3 = out [3]; | |||
| for (i = 0; i < nfram; i++) | |||
| { | |||
| _vdelay0.write (p0 [i]); | |||
| _vdelay1.write (p1 [i]); | |||
| t = 0.3f * _vdelay0.read (); | |||
| x0 = _diff1 [0].process (_delay [0].read () + t); | |||
| x1 = _diff1 [1].process (_delay [1].read () + t); | |||
| x2 = _diff1 [2].process (_delay [2].read () - t); | |||
| x3 = _diff1 [3].process (_delay [3].read () - t); | |||
| t = 0.3f * _vdelay1.read (); | |||
| x4 = _diff1 [4].process (_delay [4].read () + t); | |||
| x5 = _diff1 [5].process (_delay [5].read () + t); | |||
| x6 = _diff1 [6].process (_delay [6].read () - t); | |||
| x7 = _diff1 [7].process (_delay [7].read () - t); | |||
| t = x0 - x1; x0 += x1; x1 = t; | |||
| t = x2 - x3; x2 += x3; x3 = t; | |||
| t = x4 - x5; x4 += x5; x5 = t; | |||
| t = x6 - x7; x6 += x7; x7 = t; | |||
| t = x0 - x2; x0 += x2; x2 = t; | |||
| t = x1 - x3; x1 += x3; x3 = t; | |||
| t = x4 - x6; x4 += x6; x6 = t; | |||
| t = x5 - x7; x5 += x7; x7 = t; | |||
| t = x0 - x4; x0 += x4; x4 = t; | |||
| t = x1 - x5; x1 += x5; x5 = t; | |||
| t = x2 - x6; x2 += x6; x6 = t; | |||
| t = x3 - x7; x3 += x7; x7 = t; | |||
| if (_ambis) | |||
| { | |||
| _g0 += _d0; | |||
| _g1 += _d1; | |||
| q0 [i] = _g0 * x0; | |||
| q1 [i] = _g1 * x1; | |||
| q2 [i] = _g1 * x4; | |||
| q3 [i] = _g1 * x2; | |||
| } | |||
| else | |||
| { | |||
| _g1 += _d1; | |||
| q0 [i] = _g1 * (x1 + x2); | |||
| q1 [i] = _g1 * (x1 - x2); | |||
| } | |||
| _delay [0].write (_filt1 [0].process (g * x0)); | |||
| _delay [1].write (_filt1 [1].process (g * x1)); | |||
| _delay [2].write (_filt1 [2].process (g * x2)); | |||
| _delay [3].write (_filt1 [3].process (g * x3)); | |||
| _delay [4].write (_filt1 [4].process (g * x4)); | |||
| _delay [5].write (_filt1 [5].process (g * x5)); | |||
| _delay [6].write (_filt1 [6].process (g * x6)); | |||
| _delay [7].write (_filt1 [7].process (g * x7)); | |||
| } | |||
| n = _ambis ? 4 : 2; | |||
| _pareq1.process (nfram, n, out); | |||
| _pareq2.process (nfram, n, out); | |||
| if (!_ambis) | |||
| { | |||
| for (i = 0; i < nfram; i++) | |||
| { | |||
| _g0 += _d0; | |||
| q0 [i] += _g0 * p0 [i]; | |||
| q1 [i] += _g0 * p1 [i]; | |||
| } | |||
| } | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| } | |||
| @@ -0,0 +1,228 @@ | |||
| // ----------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2003-2011 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ----------------------------------------------------------------------- | |||
| #ifndef __REVERB_H | |||
| #define __REVERB_H | |||
| #include "pareq.h" | |||
| namespace REV1 { | |||
| // ----------------------------------------------------------------------- | |||
| class Diff1 | |||
| { | |||
| private: | |||
| friend class Reverb; | |||
| Diff1 (void); | |||
| ~Diff1 (void); | |||
| void init (int size, float c); | |||
| void fini (void); | |||
| float process (float x) | |||
| { | |||
| float z = _line [_i]; | |||
| x -= _c * z; | |||
| _line [_i] = x; | |||
| if (++_i == _size) _i = 0; | |||
| return z + _c * x; | |||
| } | |||
| int _i; | |||
| float _c; | |||
| int _size; | |||
| float *_line; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| class Filt1 | |||
| { | |||
| private: | |||
| friend class Reverb; | |||
| Filt1 (void) : _slo (0), _shi (0) {} | |||
| ~Filt1 (void) {} | |||
| void set_params (float del, float tmf, float tlo, float wlo, float thi, float chi); | |||
| float process (float x) | |||
| { | |||
| _slo += _wlo * (x - _slo) + 1e-10f; | |||
| x += _glo * _slo; | |||
| _shi += _whi * (x - _shi); | |||
| return _gmf * _shi; | |||
| } | |||
| float _gmf; | |||
| float _glo; | |||
| float _wlo; | |||
| float _whi; | |||
| float _slo; | |||
| float _shi; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| class Delay | |||
| { | |||
| private: | |||
| friend class Reverb; | |||
| Delay (void); | |||
| ~Delay (void); | |||
| void init (int size); | |||
| void fini (void); | |||
| float read (void) | |||
| { | |||
| return _line [_i]; | |||
| } | |||
| void write (float x) | |||
| { | |||
| _line [_i++] = x; | |||
| if (_i == _size) _i = 0; | |||
| } | |||
| int _i; | |||
| int _size; | |||
| float *_line; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| class Vdelay | |||
| { | |||
| private: | |||
| friend class Reverb; | |||
| Vdelay (void); | |||
| ~Vdelay (void); | |||
| void init (int size); | |||
| void fini (void); | |||
| void set_delay (int del); | |||
| float read (void) | |||
| { | |||
| float x = _line [_ir++]; | |||
| if (_ir == _size) _ir = 0; | |||
| return x; | |||
| } | |||
| void write (float x) | |||
| { | |||
| _line [_iw++] = x; | |||
| if (_iw == _size) _iw = 0; | |||
| } | |||
| int _ir; | |||
| int _iw; | |||
| int _size; | |||
| float *_line; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| class Reverb | |||
| { | |||
| public: | |||
| Reverb (void); | |||
| ~Reverb (void); | |||
| void init (float fsamp, bool ambis); | |||
| void fini (void); | |||
| void prepare (int n); | |||
| void process (int n, float *inp [], float *out []); | |||
| void set_delay (float v) { _ipdel = v; _cntA1++; } | |||
| void set_xover (float v) { _xover = v; _cntB1++; } | |||
| void set_rtlow (float v) { _rtlow = v; _cntB1++; } | |||
| void set_rtmid (float v) { _rtmid = v; _cntB1++; _cntC1++; } | |||
| void set_fdamp (float v) { _fdamp = v; _cntB1++; } | |||
| void set_opmix (float v) { _opmix = v; _cntC1++; } | |||
| void set_rgxyz (float v) { _rgxyz = v; _cntC1++; } | |||
| void set_eq1 (float f, float g) { _pareq1.setparam (f, g); } | |||
| void set_eq2 (float f, float g) { _pareq2.setparam (f, g); } | |||
| private: | |||
| float _fsamp; | |||
| bool _ambis; | |||
| Vdelay _vdelay0; | |||
| Vdelay _vdelay1; | |||
| Diff1 _diff1 [8]; | |||
| Filt1 _filt1 [8]; | |||
| Delay _delay [8]; | |||
| volatile int _cntA1; | |||
| volatile int _cntB1; | |||
| volatile int _cntC1; | |||
| int _cntA2; | |||
| int _cntB2; | |||
| int _cntC2; | |||
| float _ipdel; | |||
| float _xover; | |||
| float _rtlow; | |||
| float _rtmid; | |||
| float _fdamp; | |||
| float _opmix; | |||
| float _rgxyz; | |||
| float _g0, _d0; | |||
| float _g1, _d1; | |||
| Pareq _pareq1; | |||
| Pareq _pareq2; | |||
| static float _tdiff1 [8]; | |||
| static float _tdelay [8]; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,207 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include <cairo/cairo.h> | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <math.h> | |||
| #include "rotary.h" | |||
| namespace REV1 { | |||
| cairo_t *RotaryCtl::_cairotype = 0; | |||
| cairo_surface_t *RotaryCtl::_cairosurf = 0; | |||
| int RotaryCtl::_wb_up = 4; | |||
| int RotaryCtl::_wb_dn = 5; | |||
| int RotaryCtl::_keymod = 0; | |||
| int RotaryCtl::_button = 0; | |||
| int RotaryCtl::_rcount = 0; | |||
| int RotaryCtl::_rx = 0; | |||
| int RotaryCtl::_ry = 0; | |||
| RotaryCtl::RotaryCtl (X_window *parent, | |||
| X_callback *cbobj, | |||
| RotaryImg *image, | |||
| int xp, | |||
| int yp, | |||
| int cbind) : | |||
| X_window (parent, | |||
| image->_x0 + xp, image->_y0 + yp, | |||
| image->_dx, image->_dy, | |||
| image->_backg->pixel), | |||
| _cbobj (cbobj), | |||
| _cbind (cbind), | |||
| _image (image), | |||
| _state (0), | |||
| _count (0), | |||
| _value (0), | |||
| _angle (0) | |||
| { | |||
| x_add_events ( ExposureMask | |||
| | Button1MotionMask | ButtonPressMask | ButtonReleaseMask); | |||
| } | |||
| RotaryCtl::~RotaryCtl (void) | |||
| { | |||
| } | |||
| void RotaryCtl::init (X_display *disp) | |||
| { | |||
| _cairosurf = cairo_xlib_surface_create (disp->dpy (), 0, disp->dvi (), 50, 50); | |||
| _cairotype = cairo_create (_cairosurf); | |||
| } | |||
| void RotaryCtl::fini (void) | |||
| { | |||
| cairo_destroy (_cairotype); | |||
| cairo_surface_destroy (_cairosurf); | |||
| } | |||
| void RotaryCtl::handle_event (XEvent *E) | |||
| { | |||
| switch (E->type) | |||
| { | |||
| case Expose: | |||
| render (); | |||
| break; | |||
| case ButtonPress: | |||
| bpress ((XButtonEvent *) E); | |||
| break; | |||
| case ButtonRelease: | |||
| brelse ((XButtonEvent *) E); | |||
| break; | |||
| case MotionNotify: | |||
| motion ((XMotionEvent *) E); | |||
| break; | |||
| default: | |||
| fprintf (stderr, "RotaryCtl: event %d\n", E->type ); | |||
| } | |||
| } | |||
| void RotaryCtl::bpress (XButtonEvent *E) | |||
| { | |||
| int r = 0; | |||
| double d; | |||
| d = hypot (E->x - _image->_xref, E->y - _image->_yref); | |||
| if (d > _image->_rad + 3) return; | |||
| _keymod = E->state; | |||
| if (E->button < 4) | |||
| { | |||
| _rx = E->x; | |||
| _ry = E->y; | |||
| _button = E->button; | |||
| r = handle_button (); | |||
| _rcount = _count; | |||
| } | |||
| else if (_button) return; | |||
| else if ((int)E->button == _wb_up) | |||
| { | |||
| r = handle_mwheel (1); | |||
| } | |||
| else if ((int)E->button == _wb_dn) | |||
| { | |||
| r = handle_mwheel (-1); | |||
| } | |||
| if (r) | |||
| { | |||
| callback (r); | |||
| render (); | |||
| } | |||
| } | |||
| void RotaryCtl::brelse (XButtonEvent *E) | |||
| { | |||
| if (_button == (int)E->button) | |||
| { | |||
| _button = 0; | |||
| callback (RELSE); | |||
| } | |||
| } | |||
| void RotaryCtl::motion (XMotionEvent *E) | |||
| { | |||
| int dx, dy, r; | |||
| if (_button) | |||
| { | |||
| _keymod = E->state; | |||
| dx = E->x - _rx; | |||
| dy = E->y - _ry; | |||
| r = handle_motion (dx, dy); | |||
| if (r) | |||
| { | |||
| callback (r); | |||
| render (); | |||
| } | |||
| } | |||
| } | |||
| void RotaryCtl::set_state (int s) | |||
| { | |||
| _state = s; | |||
| render (); | |||
| } | |||
| void RotaryCtl::render (void) | |||
| { | |||
| XImage *I; | |||
| double a, c, r, x, y; | |||
| I = _image->_image [_state]; | |||
| XPutImage (dpy (), win (), dgc (), I, | |||
| _image->_x0, _image->_y0, 0, 0, _image->_dx, _image->_dy); | |||
| cairo_xlib_surface_set_drawable (_cairosurf, win(), | |||
| _image->_dx, _image->_dy); | |||
| c = _image->_lncol [_state] ? 1.0 : 0.0; | |||
| a = _angle * M_PI / 180; | |||
| r = _image->_rad; | |||
| x = _image->_xref; | |||
| y = _image->_yref; | |||
| cairo_new_path (_cairotype); | |||
| cairo_move_to (_cairotype, x, y); | |||
| x += r * sin (a); | |||
| y -= r * cos (a); | |||
| cairo_line_to (_cairotype, x, y); | |||
| cairo_set_source_rgb (_cairotype, c, c, c); | |||
| cairo_set_line_width (_cairotype, 1.8); | |||
| cairo_stroke (_cairotype); | |||
| } | |||
| } | |||
| @@ -0,0 +1,119 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __ROTARY_H | |||
| #define __ROTARY_H | |||
| #include <cairo/cairo.h> | |||
| #include <cairo/cairo-xlib.h> | |||
| #include <clxclient.h> | |||
| namespace REV1 { | |||
| class RotaryImg | |||
| { | |||
| public: | |||
| XftColor *_backg; | |||
| XImage *_image [4]; | |||
| char _lncol [4]; | |||
| int _x0; | |||
| int _y0; | |||
| int _dx; | |||
| int _dy; | |||
| double _xref; | |||
| double _yref; | |||
| double _rad; | |||
| }; | |||
| class RotaryCtl : public X_window | |||
| { | |||
| public: | |||
| RotaryCtl (X_window *parent, | |||
| X_callback *cbobj, | |||
| RotaryImg *image, | |||
| int xp, int yp, | |||
| int cbind = 0); | |||
| virtual ~RotaryCtl (void); | |||
| enum { NOP = 200, PRESS, RELSE, DELTA }; | |||
| int cbind (void) { return _cbind; } | |||
| int state (void) { return _state; } | |||
| double value (void) { return _value; } | |||
| virtual void set_state (int s); | |||
| virtual void set_value (double v) = 0; | |||
| virtual void get_string (char *p, int n) {} | |||
| static void init (X_display *disp); | |||
| static void fini (void); | |||
| static int _wb_up; | |||
| static int _wb_dn; | |||
| protected: | |||
| X_callback *_cbobj; | |||
| int _cbind; | |||
| RotaryImg *_image; | |||
| int _state; | |||
| int _count; | |||
| int _range; | |||
| double _value; | |||
| double _angle; | |||
| void render (void); | |||
| void callback (int k) { _cbobj->handle_callb (k, this, 0); } | |||
| static int _keymod; | |||
| static int _button; | |||
| static int _rcount; | |||
| static int _rx; | |||
| static int _ry; | |||
| private: | |||
| void handle_event (XEvent *E); | |||
| void bpress (XButtonEvent *E); | |||
| void brelse (XButtonEvent *E); | |||
| void motion (XMotionEvent *E); | |||
| virtual int handle_button (void) = 0; | |||
| virtual int handle_motion (int dx, int dy) = 0; | |||
| virtual int handle_mwheel (int dw) = 0; | |||
| static cairo_t *_cairotype; | |||
| static cairo_surface_t *_cairosurf; | |||
| }; | |||
| } | |||
| #endif | |||
| @@ -0,0 +1,177 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #include "styles.h" | |||
| #include "png2img.h" | |||
| #include "CarlaString.hpp" | |||
| namespace REV1 { | |||
| XftColor *XftColors [NXFTCOLORS]; | |||
| XImage *revsect_img; | |||
| XImage *eq1sect_img; | |||
| XImage *eq2sect_img; | |||
| XImage *mixsect_img; | |||
| XImage *ambsect_img; | |||
| RotaryImg r_delay_img; | |||
| RotaryImg r_xover_img; | |||
| RotaryImg r_rtlow_img; | |||
| RotaryImg r_rtmid_img; | |||
| RotaryImg r_fdamp_img; | |||
| RotaryImg r_parfr_img; | |||
| RotaryImg r_pargn_img; | |||
| RotaryImg r_opmix_img; | |||
| RotaryImg r_rgxyz_img; | |||
| int styles_init (X_display *disp, X_resman *xrm, const char *resdir) | |||
| { | |||
| XftColors [C_MAIN_BG] = disp->alloc_xftcolor (0.25f, 0.25f, 0.25f, 1.0f); | |||
| XftColors [C_MAIN_FG] = disp->alloc_xftcolor (1.0f, 1.0f, 1.0f, 1.0f); | |||
| const CarlaString SHARED = CarlaString(resdir)+"/rev1"; | |||
| revsect_img = png2img (SHARED+"/revsect.png", disp, XftColors [C_MAIN_BG]); | |||
| eq1sect_img = png2img (SHARED+"/eq1sect.png", disp, XftColors [C_MAIN_BG]); | |||
| eq2sect_img = png2img (SHARED+"/eq2sect.png", disp, XftColors [C_MAIN_BG]); | |||
| mixsect_img = png2img (SHARED+"/mixsect.png", disp, XftColors [C_MAIN_BG]); | |||
| ambsect_img = png2img (SHARED+"/ambsect.png", disp, XftColors [C_MAIN_BG]); | |||
| if (!revsect_img || !mixsect_img || !ambsect_img | |||
| || !eq1sect_img || !eq2sect_img) | |||
| { | |||
| fprintf (stderr, "Can't load images from '%s'.\n", SHARED.buffer()); | |||
| return 1; | |||
| } | |||
| r_delay_img._backg = XftColors [C_MAIN_BG]; | |||
| r_delay_img._image [0] = revsect_img; | |||
| r_delay_img._lncol [0] = 0; | |||
| r_delay_img._x0 = 30; | |||
| r_delay_img._y0 = 32; | |||
| r_delay_img._dx = 23; | |||
| r_delay_img._dy = 23; | |||
| r_delay_img._xref = 11.5; | |||
| r_delay_img._yref = 11.5; | |||
| r_delay_img._rad = 11; | |||
| r_xover_img._backg = XftColors [C_MAIN_BG]; | |||
| r_xover_img._image [0] = revsect_img; | |||
| r_xover_img._lncol [0] = 0; | |||
| r_xover_img._x0 = 92; | |||
| r_xover_img._y0 = 17; | |||
| r_xover_img._dx = 23; | |||
| r_xover_img._dy = 23; | |||
| r_xover_img._xref = 11.5; | |||
| r_xover_img._yref = 11.5; | |||
| r_xover_img._rad = 11; | |||
| r_rtlow_img._backg = XftColors [C_MAIN_BG]; | |||
| r_rtlow_img._image [0] = revsect_img; | |||
| r_rtlow_img._lncol [0] = 0; | |||
| r_rtlow_img._x0 = 147; | |||
| r_rtlow_img._y0 = 17; | |||
| r_rtlow_img._dx = 23; | |||
| r_rtlow_img._dy = 23; | |||
| r_rtlow_img._xref = 11.5; | |||
| r_rtlow_img._yref = 11.5; | |||
| r_rtlow_img._rad = 11; | |||
| r_rtmid_img._backg = XftColors [C_MAIN_BG]; | |||
| r_rtmid_img._image [0] = revsect_img; | |||
| r_rtmid_img._lncol [0] = 0; | |||
| r_rtmid_img._x0 = 207; | |||
| r_rtmid_img._y0 = 17; | |||
| r_rtmid_img._dx = 23; | |||
| r_rtmid_img._dy = 23; | |||
| r_rtmid_img._xref = 11.5; | |||
| r_rtmid_img._yref = 11.5; | |||
| r_rtmid_img._rad = 11; | |||
| r_fdamp_img._backg = XftColors [C_MAIN_BG]; | |||
| r_fdamp_img._image [0] = revsect_img; | |||
| r_fdamp_img._lncol [0] = 0; | |||
| r_fdamp_img._x0 = 267; | |||
| r_fdamp_img._y0 = 17; | |||
| r_fdamp_img._dx = 23; | |||
| r_fdamp_img._dy = 23; | |||
| r_fdamp_img._xref = 11.5; | |||
| r_fdamp_img._yref = 11.5; | |||
| r_fdamp_img._rad = 11; | |||
| r_parfr_img._backg = XftColors [C_MAIN_BG]; | |||
| r_parfr_img._image [0] = eq1sect_img; | |||
| r_parfr_img._lncol [0] = 0; | |||
| r_parfr_img._x0 = 19; | |||
| r_parfr_img._y0 = 32; | |||
| r_parfr_img._dx = 23; | |||
| r_parfr_img._dy = 23; | |||
| r_parfr_img._xref = 11.5; | |||
| r_parfr_img._yref = 11.5; | |||
| r_parfr_img._rad = 11; | |||
| r_pargn_img._backg = XftColors [C_MAIN_BG]; | |||
| r_pargn_img._image [0] = eq1sect_img; | |||
| r_pargn_img._lncol [0] = 1; | |||
| r_pargn_img._x0 = 68; | |||
| r_pargn_img._y0 = 17; | |||
| r_pargn_img._dx = 23; | |||
| r_pargn_img._dy = 23; | |||
| r_pargn_img._xref = 11.5; | |||
| r_pargn_img._yref = 11.5; | |||
| r_pargn_img._rad = 11; | |||
| r_opmix_img._backg = XftColors [C_MAIN_BG]; | |||
| r_opmix_img._image [0] = mixsect_img; | |||
| r_opmix_img._lncol [0] = 0; | |||
| r_opmix_img._x0 = 23; | |||
| r_opmix_img._y0 = 32; | |||
| r_opmix_img._dx = 23; | |||
| r_opmix_img._dy = 23; | |||
| r_opmix_img._xref = 11.5; | |||
| r_opmix_img._yref = 11.5; | |||
| r_opmix_img._rad = 11; | |||
| r_rgxyz_img._backg = XftColors [C_MAIN_BG]; | |||
| r_rgxyz_img._image [0] = ambsect_img; | |||
| r_rgxyz_img._lncol [0] = 0; | |||
| r_rgxyz_img._x0 = 23; | |||
| r_rgxyz_img._y0 = 32; | |||
| r_rgxyz_img._dx = 23; | |||
| r_rgxyz_img._dy = 23; | |||
| r_rgxyz_img._xref = 11.5; | |||
| r_rgxyz_img._yref = 11.5; | |||
| r_rgxyz_img._rad = 11; | |||
| return 0; | |||
| } | |||
| void styles_fini (X_display *disp) | |||
| { | |||
| } | |||
| } | |||
| @@ -0,0 +1,73 @@ | |||
| // ---------------------------------------------------------------------- | |||
| // | |||
| // Copyright (C) 2010 Fons Adriaensen <fons@linuxaudio.org> | |||
| // Modified by falkTX on Jan 2015 for inclusion in Carla | |||
| // | |||
| // 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 | |||
| // (at your option) 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. | |||
| // | |||
| // You should have received a copy of the GNU General Public License | |||
| // along with this program; if not, write to the Free Software | |||
| // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
| // | |||
| // ---------------------------------------------------------------------- | |||
| #ifndef __STYLES_H | |||
| #define __STYLES_H | |||
| #include <clxclient.h> | |||
| #include "rotary.h" | |||
| namespace REV1 { | |||
| enum | |||
| { | |||
| C_MAIN_BG, C_MAIN_FG, | |||
| // C_TEXT_BG, C_TEXT_FG, | |||
| NXFTCOLORS | |||
| }; | |||
| enum | |||
| { | |||
| // F_TEXT, F_FILE, | |||
| NXFTFONTS | |||
| }; | |||
| extern int styles_init (X_display *disp, X_resman *xrm, const char *resdir); | |||
| extern void styles_fini (X_display *disp); | |||
| extern XftColor *XftColors [NXFTCOLORS]; | |||
| //extern XftFont *XftFonts [NXFTFONTS]; | |||
| extern X_textln_style tstyle1; | |||
| extern XImage *revsect_img; | |||
| extern XImage *eq1sect_img; | |||
| extern XImage *eq2sect_img; | |||
| extern XImage *mixsect_img; | |||
| extern XImage *ambsect_img; | |||
| extern RotaryImg r_delay_img; | |||
| extern RotaryImg r_xover_img; | |||
| extern RotaryImg r_rtlow_img; | |||
| extern RotaryImg r_rtmid_img; | |||
| extern RotaryImg r_fdamp_img; | |||
| extern RotaryImg r_parfr_img; | |||
| extern RotaryImg r_pargn_img; | |||
| extern RotaryImg r_opmix_img; | |||
| extern RotaryImg r_rgxyz_img; | |||
| } | |||
| #endif | |||
| @@ -40,7 +40,7 @@ public: | |||
| fUiState(UiNone), | |||
| leakDetector_CarlaExternalUI() {} | |||
| ~CarlaExternalUI() noexcept override | |||
| ~CarlaExternalUI() /*noexcept*/ override | |||
| { | |||
| CARLA_SAFE_ASSERT_INT(fUiState == UiNone, fUiState); | |||
| } | |||