diff --git a/CMakeLists.txt b/CMakeLists.txt index 9726c7cda..31670495a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -29,6 +29,7 @@ INCLUDE(DetectMachine) OPTION(WANT_ALSA "Include ALSA (Advanced Linux Sound Architecture) support" ON) OPTION(WANT_CALF "Include CALF LADSPA plugins" ON) OPTION(WANT_CAPS "Include C* Audio Plugin Suite (LADSPA plugins)" ON) +OPTION(WANT_CARLA "Include Carla plugin" ON) OPTION(WANT_CMT "Include Computer Music Toolkit LADSPA plugins" ON) OPTION(WANT_JACK "Include JACK (Jack Audio Connection Kit) support" ON) OPTION(WANT_OGGVORBIS "Include OGG/Vorbis support" ON) @@ -157,6 +158,18 @@ SET(STATUS_TAP "not built as requested") ENDIF(WANT_TAP) +# check for CARLA +IF(WANT_CARLA) + PKG_CHECK_MODULES(CARLA carla-standalone>=1.9.5) + IF(CARLA_FOUND) + SET(LMMS_HAVE_CARLA TRUE) + SET(STATUS_CARLA "OK") + ELSE(CARLA_FOUND) + SET(STATUS_CARLA "not found, please install the latest carla") + ENDIF(CARLA_FOUND) +ENDIF(WANT_CARLA) + + # check for SDL IF(WANT_SDL) SET(SDL_BUILDING_LIBRARY TRUE) @@ -606,6 +619,7 @@ MESSAGE( MESSAGE( "Optional plugins\n" "----------------\n" +"* Carla Patchbay & Rack : ${STATUS_CARLA}\n" "* SoundFont2 player : ${STATUS_FLUIDSYNTH}\n" "* Stk Mallets : ${STATUS_STK}\n" "* VST-instrument hoster : ${STATUS_VST}\n" diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 76990491d..24eeef641 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -2,6 +2,9 @@ ADD_SUBDIRECTORY(Amplifier) ADD_SUBDIRECTORY(audio_file_processor) ADD_SUBDIRECTORY(BassBooster) ADD_SUBDIRECTORY(bit_invader) +ADD_SUBDIRECTORY(carlabase) +ADD_SUBDIRECTORY(carlapatchbay) +ADD_SUBDIRECTORY(carlarack) ADD_SUBDIRECTORY(DualFilter) ADD_SUBDIRECTORY(dynamics_processor) ADD_SUBDIRECTORY(flp_import) diff --git a/plugins/carlabase/CMakeLists.txt b/plugins/carlabase/CMakeLists.txt new file mode 100644 index 000000000..82c31dbd0 --- /dev/null +++ b/plugins/carlabase/CMakeLists.txt @@ -0,0 +1,12 @@ +if(LMMS_HAVE_CARLA) + INCLUDE(BuildPlugin) + INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS}) + LINK_DIRECTORIES(${CARLA_LIBRARY_DIRS}) + LINK_LIBRARIES(${CARLA_LIBRARIES}) + BUILD_PLUGIN(carlabase carla.cpp carla.h MOCFILES carla.h) + SET_TARGET_PROPERTIES(carlabase + PROPERTIES SKIP_BUILD_RPATH TRUE + BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH_USE_LINK_PATH TRUE + INSTALL_RPATH "${CARLA_RPATH}") +endif(LMMS_HAVE_CARLA) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp new file mode 100644 index 000000000..81f724473 --- /dev/null +++ b/plugins/carlabase/carla.cpp @@ -0,0 +1,528 @@ +/* + * carla.cpp - Carla for LMMS + * + * Copyright (C) 2014 Filipe Coelho + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "carla.h" + +#define REAL_BUILD // FIXME this shouldn't be needed +#include "CarlaHost.h" + +#include "engine.h" +#include "song.h" +#include "InstrumentPlayHandle.h" +#include "InstrumentTrack.h" + +#include +#include +#include +#include +#include + +#include + +// this doesn't seem to be defined anywhere +static const double ticksPerBeat = 48.0; + +/* + * Current TODO items: + * - get plugin instance name (to use in external window title) + * - offline mode change callback + * - midi output + * - background artwork + * + * All other items are to be done in Carla itself. + */ + +// ----------------------------------------------------------------------- + +#define handlePtr ((CarlaInstrument*)handle) + +static uint32_t host_get_buffer_size(NativeHostHandle handle) +{ + return handlePtr->handleGetBufferSize(); +} + +static double host_get_sample_rate(NativeHostHandle handle) +{ + return handlePtr->handleGetSampleRate(); +} + +static bool host_is_offline(NativeHostHandle handle) +{ + return handlePtr->handleIsOffline(); +} + +static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle) +{ + return handlePtr->handleGetTimeInfo(); +} + +static bool host_write_midi_event(NativeHostHandle, const NativeMidiEvent*) +{ + return false; // unsupported? +} + +static void host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value) +{ + handlePtr->handleUiParameterChanged(index, value); +} + +static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value) +{ + // unused +} + +static void host_ui_closed(NativeHostHandle handle) +{ + handlePtr->handleUiClosed(); +} + +static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpcode opcode, int32_t index, intptr_t value, void* ptr, float opt) +{ + return handlePtr->handleDispatcher(opcode, index, value, ptr, opt); +} + +#undef handlePtr + +// ----------------------------------------------------------------------- + +static const char* host_ui_open_file(NativeHostHandle, bool isDir, const char* title, const char* filter) +{ + static QByteArray retStr; + const QFileDialog::Options options(isDir ? QFileDialog::ShowDirsOnly : 0x0); + + retStr = QFileDialog::getOpenFileName(QApplication::activeWindow(), title, "", filter, NULL, options).toUtf8(); + + return retStr.isEmpty() ? NULL : retStr.constData(); +} + +static const char* host_ui_save_file(NativeHostHandle, bool isDir, const char* title, const char* filter) +{ + static QByteArray retStr; + const QFileDialog::Options options(isDir ? QFileDialog::ShowDirsOnly : 0x0); + + retStr = QFileDialog::getSaveFileName(QApplication::activeWindow(), title, "", filter, NULL, options).toUtf8(); + + return retStr.isEmpty() ? NULL : retStr.constData(); +} + +// ----------------------------------------------------------------------- + +CARLA_EXPORT +const NativePluginDescriptor* carla_get_native_patchbay_plugin(); + +CARLA_EXPORT +const NativePluginDescriptor* carla_get_native_rack_plugin(); + +// ----------------------------------------------------------------------- + +CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const Descriptor* const descriptor, const bool isPatchbay) + : Instrument(instrumentTrack, descriptor), + kIsPatchbay(isPatchbay), + fHandle(NULL), + fDescriptor(isPatchbay ? carla_get_native_patchbay_plugin() : carla_get_native_rack_plugin()), + fMidiEventCount(0) +{ + fHost.handle = this; + fHost.uiName = NULL; + fHost.uiParentId = 0; + + // figure out prefix from dll filename + QString dllName(carla_get_library_filename()); + +#if defined(CARLA_OS_LINUX) + fHost.resourceDir = strdup(QString(dllName.split("/lib/carla")[0] + "/share/carla/resources/").toUtf8().constData()); +#else + fHost.resourceDir = NULL; +#endif + + fHost.get_buffer_size = host_get_buffer_size; + fHost.get_sample_rate = host_get_sample_rate; + fHost.is_offline = host_is_offline; + fHost.get_time_info = host_get_time_info; + fHost.write_midi_event = host_write_midi_event; + fHost.ui_parameter_changed = host_ui_parameter_changed; + fHost.ui_custom_data_changed = host_ui_custom_data_changed; + fHost.ui_closed = host_ui_closed; + fHost.ui_open_file = host_ui_open_file; + fHost.ui_save_file = host_ui_save_file; + fHost.dispatcher = host_dispatcher; + + std::memset(&fTimeInfo, 0, sizeof(NativeTimeInfo)); + fTimeInfo.bbt.valid = true; // always valid + + fHandle = fDescriptor->instantiate(&fHost); + Q_ASSERT(fHandle != NULL); + + if (fHandle != NULL && fDescriptor->activate != NULL) + fDescriptor->activate(fHandle); + + // we need a play-handle which cares for calling play() + InstrumentPlayHandle * iph = new InstrumentPlayHandle( this ); + engine::mixer()->addPlayHandle( iph ); + + connect(engine::mixer(), SIGNAL(sampleRateChanged()), this, SLOT(sampleRateChanged())); +} + +CarlaInstrument::~CarlaInstrument() +{ + engine::mixer()->removePlayHandles( instrumentTrack() ); + + if (fHost.resourceDir != NULL) + { + std::free((char*)fHost.resourceDir); + fHost.resourceDir = NULL; + } + + if (fHost.uiName != NULL) + { + std::free((char*)fHost.uiName); + fHost.uiName = NULL; + } + + if (fHandle == NULL) + return; + + if (fDescriptor->deactivate != NULL) + fDescriptor->deactivate(fHandle); + + if (fDescriptor->cleanup != NULL) + fDescriptor->cleanup(fHandle); + + fHandle = NULL; +} + +// ------------------------------------------------------------------- + +uint32_t CarlaInstrument::handleGetBufferSize() const +{ + return engine::mixer()->framesPerPeriod(); +} + +double CarlaInstrument::handleGetSampleRate() const +{ + return engine::mixer()->processingSampleRate(); +} + +bool CarlaInstrument::handleIsOffline() const +{ + return false; // TODO +} + +const NativeTimeInfo* CarlaInstrument::handleGetTimeInfo() const +{ + return &fTimeInfo; +} + +void CarlaInstrument::handleUiParameterChanged(const uint32_t /*index*/, const float /*value*/) const +{ +} + +void CarlaInstrument::handleUiClosed() +{ + emit uiClosed(); +} + +intptr_t CarlaInstrument::handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt) +{ + intptr_t ret = 0; + + switch (opcode) + { + case HOST_OPCODE_NULL: + break; + case HOST_OPCODE_UPDATE_PARAMETER: + case HOST_OPCODE_UPDATE_MIDI_PROGRAM: + case HOST_OPCODE_RELOAD_PARAMETERS: + case HOST_OPCODE_RELOAD_MIDI_PROGRAMS: + case HOST_OPCODE_RELOAD_ALL: + // nothing + break; + case HOST_OPCODE_UI_UNAVAILABLE: + handleUiClosed(); + break; + } + + return ret; + + // unused for now + (void)index; (void)value; (void)ptr; (void)opt; +} + +// ------------------------------------------------------------------- + +Instrument::Flags CarlaInstrument::flags() const +{ + return IsSingleStreamed|IsMidiBased|IsNotBendable; +} + +QString CarlaInstrument::nodeName() const +{ + return descriptor()->name; +} + +void CarlaInstrument::saveSettings(QDomDocument& doc, QDomElement& parent) +{ + if (fHandle == NULL || fDescriptor->get_state == NULL) + return; + + char* const state = fDescriptor->get_state(fHandle); + + if (state == NULL) + return; + + QDomDocument carlaDoc("carla"); + + if (carlaDoc.setContent(QString(state))) + { + QDomNode n = doc.importNode(carlaDoc.documentElement(), true); + parent.appendChild(n); + } + + std::free(state); +} + +void CarlaInstrument::loadSettings(const QDomElement& elem) +{ + if (fHandle == NULL || fDescriptor->set_state == NULL) + return; + + QDomDocument carlaDoc("carla"); + carlaDoc.appendChild(carlaDoc.importNode(elem.firstChildElement(), true )); + + fDescriptor->set_state(fHandle, carlaDoc.toString(0).toUtf8().constData()); +} + +void CarlaInstrument::play(sampleFrame* workingBuffer) +{ + const uint bufsize = engine::mixer()->framesPerPeriod(); + + std::memset(workingBuffer, 0, sizeof(sample_t)*bufsize*DEFAULT_CHANNELS); + + if (fHandle == NULL) + { + instrumentTrack()->processAudioBuffer(workingBuffer, bufsize, NULL); + return; + } + + // set time info + song* const s = engine::getSong(); + fTimeInfo.playing = s->isPlaying(); + fTimeInfo.frame = s->getPlayPos(s->playMode()).frames(engine::framesPerTick()); + fTimeInfo.usecs = s->getMilliseconds()*1000; + fTimeInfo.bbt.bar = s->getTacts() + 1; + fTimeInfo.bbt.beat = s->getBeat() + 1; + fTimeInfo.bbt.tick = s->getBeatTicks(); + fTimeInfo.bbt.barStartTick = ticksPerBeat*s->getTimeSigModel().getNumerator()*s->getTacts(); + fTimeInfo.bbt.beatsPerBar = s->getTimeSigModel().getNumerator(); + fTimeInfo.bbt.beatType = s->getTimeSigModel().getDenominator(); + fTimeInfo.bbt.ticksPerBeat = ticksPerBeat; + fTimeInfo.bbt.beatsPerMinute = s->getTempo(); + + float buf1[bufsize]; + float buf2[bufsize]; + float* rBuf[] = { buf1, buf2 }; + std::memset(buf1, 0, sizeof(float)*bufsize); + std::memset(buf2, 0, sizeof(float)*bufsize); + + { + const QMutexLocker ml(&fMutex); + fDescriptor->process(fHandle, rBuf, rBuf, bufsize, fMidiEvents, fMidiEventCount); + fMidiEventCount = 0; + } + + for (uint i=0; i < bufsize; ++i) + { + workingBuffer[i][0] = buf1[i]; + workingBuffer[i][1] = buf2[i]; + } + + instrumentTrack()->processAudioBuffer(workingBuffer, bufsize, NULL); +} + +bool CarlaInstrument::handleMidiEvent(const MidiEvent& event, const MidiTime&, f_cnt_t offset) +{ + const QMutexLocker ml(&fMutex); + + if (fMidiEventCount >= kMaxMidiEvents) + return false; + + NativeMidiEvent& nEvent(fMidiEvents[fMidiEventCount++]); + std::memset(&nEvent, 0, sizeof(NativeMidiEvent)); + + nEvent.port = 0; + nEvent.time = offset; + nEvent.data[0] = event.type() | (event.channel() & 0x0F); + + switch (event.type()) + { + case MidiNoteOn: + if (event.velocity() > 0) + { + if (event.key() < 0 || event.key() > MidiMaxKey) + break; + + nEvent.data[1] = event.key(); + nEvent.data[2] = event.velocity(); + nEvent.size = 3; + break; + } + else + { + nEvent.data[0] = MidiNoteOff | (event.channel() & 0x0F); + // nobreak + } + + case MidiNoteOff: + if (event.key() < 0 || event.key() > MidiMaxKey) + break; + + nEvent.data[1] = event.key(); + nEvent.data[2] = event.velocity(); + nEvent.size = 3; + break; + + case MidiKeyPressure: + nEvent.data[1] = event.key(); + nEvent.data[2] = event.velocity(); + nEvent.size = 3; + break; + + case MidiControlChange: + nEvent.data[1] = event.controllerNumber(); + nEvent.data[2] = event.controllerValue(); + nEvent.size = 3; + break; + + case MidiProgramChange: + nEvent.data[1] = event.program(); + nEvent.size = 2; + break; + + case MidiChannelPressure: + nEvent.data[1] = event.channelPressure(); + nEvent.size = 2; + break; + + case MidiPitchBend: + nEvent.data[1] = event.pitchBend() & 0x7f; + nEvent.data[2] = event.pitchBend() >> 7; + nEvent.size = 3; + break; + + default: + // unhandled + --fMidiEventCount; + break; + } + + return true; +} + +PluginView* CarlaInstrument::instantiateView(QWidget* parent) +{ + if (QWidget* const window = parent->window()) + fHost.uiParentId = window->winId(); + else + fHost.uiParentId = 0; + + std::free((char*)fHost.uiName); + + // TODO - get plugin instance name + //fHost.uiName = strdup(parent->windowTitle().toUtf8().constData()); + fHost.uiName = strdup(kIsPatchbay ? "CarlaPatchbay-LMMS" : "CarlaRack-LMMS"); + + return new CarlaInstrumentView(this, parent); +} + +void CarlaInstrument::sampleRateChanged() +{ + fDescriptor->dispatcher(fHandle, PLUGIN_OPCODE_SAMPLE_RATE_CHANGED, 0, 0, nullptr, handleGetSampleRate()); +} + +// ------------------------------------------------------------------- + +CarlaInstrumentView::CarlaInstrumentView(CarlaInstrument* const instrument, QWidget* const parent) + : InstrumentView(instrument, parent), + fHandle(instrument->fHandle), + fDescriptor(instrument->fDescriptor), + fTimerId(fHandle != NULL && fDescriptor->ui_idle != NULL ? startTimer(30) : 0) +{ + setAutoFillBackground(true); + + //QPalette pal; + //pal.setBrush(backgroundRole(), PLUGIN_NAME::getIconPixmap("artwork")); + //setPalette(pal); + + QVBoxLayout * l = new QVBoxLayout( this ); + l->setContentsMargins( 20, 80, 10, 10 ); + l->setSpacing( 10 ); + + m_toggleUIButton = new QPushButton( tr( "Show GUI" ), this ); + m_toggleUIButton->setCheckable( true ); + m_toggleUIButton->setChecked( false ); + //m_toggleUIButton->setIcon( embed::getIconPixmap( "zoom" ) ); + //m_toggleUIButton->setFont( pointSize<8>( m_toggleUIButton->font() ) ); + connect( m_toggleUIButton, SIGNAL( clicked(bool) ), this, SLOT( toggleUI( bool ) ) ); + + m_toggleUIButton->setWhatsThis( + tr( "Click here to show or hide the graphical user interface (GUI) of Carla." ) ); + + l->addWidget( m_toggleUIButton ); + l->addStretch(); + + connect(instrument, SIGNAL(uiClosed()), this, SLOT(uiClosed())); +} + +CarlaInstrumentView::~CarlaInstrumentView() +{ + if (m_toggleUIButton->isChecked()) + toggleUI(false); +} + +void CarlaInstrumentView::toggleUI(bool visible) +{ + if (fHandle != NULL && fDescriptor->ui_show != NULL) + fDescriptor->ui_show(fHandle, visible); +} + +void CarlaInstrumentView::uiClosed() +{ + m_toggleUIButton->setChecked(false); +} + +void CarlaInstrumentView::modelChanged() +{ +} + +void CarlaInstrumentView::timerEvent(QTimerEvent* event) +{ + if (event->timerId() == fTimerId) + fDescriptor->ui_idle(fHandle); + + InstrumentView::timerEvent(event); +} + +// ------------------------------------------------------------------- + +#include "moc_carla.cxx" diff --git a/plugins/carlabase/carla.h b/plugins/carlabase/carla.h new file mode 100644 index 000000000..e809c001a --- /dev/null +++ b/plugins/carlabase/carla.h @@ -0,0 +1,109 @@ +/* + * carla.h - Carla for LMMS + * + * Copyright (C) 2014 Filipe Coelho + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#ifndef CARLA_H +#define CARLA_H + +#include "CarlaNative.h" + +#include "Instrument.h" +#include "InstrumentView.h" + +class QPushButton; + +class PLUGIN_EXPORT CarlaInstrument : public Instrument +{ + Q_OBJECT + +public: + static const uint32_t kMaxMidiEvents = 512; + + CarlaInstrument(InstrumentTrack* const instrumentTrack, const Descriptor* const descriptor, const bool isPatchbay); + virtual ~CarlaInstrument(); + + // CarlaNative functions + uint32_t handleGetBufferSize() const; + double handleGetSampleRate() const; + bool handleIsOffline() const; + const NativeTimeInfo* handleGetTimeInfo() const; + void handleUiParameterChanged(const uint32_t index, const float value) const; + void handleUiClosed(); + intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt); + + // LMMS functions + virtual Flags flags() const; + virtual QString nodeName() const; + virtual void saveSettings(QDomDocument& doc, QDomElement& parent); + virtual void loadSettings(const QDomElement& elem); + virtual void play(sampleFrame* workingBuffer); + virtual bool handleMidiEvent(const MidiEvent& event, const MidiTime& time, f_cnt_t offset); + virtual PluginView* instantiateView(QWidget* parent); + +signals: + void uiClosed(); + +private slots: + void sampleRateChanged(); + +private: + const bool kIsPatchbay; + + NativePluginHandle fHandle; + NativeHostDescriptor fHost; + const NativePluginDescriptor* fDescriptor; + + uint32_t fMidiEventCount; + NativeMidiEvent fMidiEvents[kMaxMidiEvents]; + NativeTimeInfo fTimeInfo; + + // this is only needed because note-offs are being sent during play + QMutex fMutex; + + friend class CarlaInstrumentView; +}; + +class CarlaInstrumentView : public InstrumentView +{ + Q_OBJECT + +public: + CarlaInstrumentView(CarlaInstrument* const instrument, QWidget* const parent); + virtual ~CarlaInstrumentView(); + +private slots: + void toggleUI(bool); + void uiClosed(); + +private: + virtual void modelChanged(); + virtual void timerEvent(QTimerEvent*); + + NativePluginHandle fHandle; + const NativePluginDescriptor* fDescriptor; + int fTimerId; + + QPushButton * m_toggleUIButton; +}; + +#endif diff --git a/plugins/carlapatchbay/CMakeLists.txt b/plugins/carlapatchbay/CMakeLists.txt new file mode 100644 index 000000000..878415ea0 --- /dev/null +++ b/plugins/carlapatchbay/CMakeLists.txt @@ -0,0 +1,8 @@ +if(LMMS_HAVE_CARLA) + ADD_DEFINITIONS(-DCARLA_PLUGIN_PATCHBAY -DCARLA_PLUGIN_SYNTH) + INCLUDE(BuildPlugin) + INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../carlabase") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../carlabase") + LINK_LIBRARIES(carlabase) + BUILD_PLUGIN(carlapatchbay carlapatchbay.cpp EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") +endif(LMMS_HAVE_CARLA) diff --git a/plugins/carlapatchbay/carlapatchbay.cpp b/plugins/carlapatchbay/carlapatchbay.cpp new file mode 100644 index 000000000..4c990994d --- /dev/null +++ b/plugins/carlapatchbay/carlapatchbay.cpp @@ -0,0 +1,51 @@ +/* + * carlapatchbay.cpp - Carla for LMMS (Patchbay) + * + * Copyright (C) 2014 Filipe Coelho + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "carla.h" + +#include "embed.cpp" + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT carlapatchbay_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Carla Patchbay", + QT_TRANSLATE_NOOP( "pluginBrowser", + "Carla Patchbay Instrument" ), + "falkTX ", + 0x0195, + Plugin::Instrument, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +} ; + +Plugin* PLUGIN_EXPORT lmms_plugin_main(Model*, void* data) +{ + return new CarlaInstrument(static_cast(data), &carlapatchbay_plugin_descriptor, true); +} + +} diff --git a/plugins/carlapatchbay/logo.png b/plugins/carlapatchbay/logo.png new file mode 100644 index 000000000..353d5d718 Binary files /dev/null and b/plugins/carlapatchbay/logo.png differ diff --git a/plugins/carlarack/CMakeLists.txt b/plugins/carlarack/CMakeLists.txt new file mode 100644 index 000000000..2655fa89b --- /dev/null +++ b/plugins/carlarack/CMakeLists.txt @@ -0,0 +1,8 @@ +if(LMMS_HAVE_CARLA) + ADD_DEFINITIONS(-DCARLA_PLUGIN_RACK -DCARLA_PLUGIN_SYNTH) + INCLUDE(BuildPlugin) + INCLUDE_DIRECTORIES(${CARLA_INCLUDE_DIRS} "${CMAKE_CURRENT_SOURCE_DIR}/../carlabase") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../carlabase") + LINK_LIBRARIES(carlabase) + BUILD_PLUGIN(carlarack carlarack.cpp EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png") +endif(LMMS_HAVE_CARLA) diff --git a/plugins/carlarack/carlarack.cpp b/plugins/carlarack/carlarack.cpp new file mode 100644 index 000000000..a2b2e0570 --- /dev/null +++ b/plugins/carlarack/carlarack.cpp @@ -0,0 +1,51 @@ +/* + * carlarack.cpp - Carla for LMMS (Rack) + * + * Copyright (C) 2014 Filipe Coelho + * + * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net + * + * 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 (see COPYING); if not, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301 USA. + * + */ + +#include "carla.h" + +#include "embed.cpp" + +extern "C" +{ + +Plugin::Descriptor PLUGIN_EXPORT carlarack_plugin_descriptor = +{ + STRINGIFY( PLUGIN_NAME ), + "Carla Rack", + QT_TRANSLATE_NOOP( "pluginBrowser", + "Carla Rack Instrument" ), + "falkTX ", + 0x0195, + Plugin::Instrument, + new PluginPixmapLoader( "logo" ), + NULL, + NULL +} ; + +Plugin* PLUGIN_EXPORT lmms_plugin_main(Model*, void* data) +{ + return new CarlaInstrument(static_cast(data), &carlarack_plugin_descriptor, false); +} + +} diff --git a/plugins/carlarack/logo.png b/plugins/carlarack/logo.png new file mode 100644 index 000000000..353d5d718 Binary files /dev/null and b/plugins/carlarack/logo.png differ