From 09656a46e730eb0098fa60a8999b8478c7869f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stian=20J=C3=B8rgensrud?= Date: Thu, 11 Sep 2014 11:54:58 +0200 Subject: [PATCH 01/16] Corrected name error in Cool Songs From Skeissi to Skiessi --- .../{Skeissi => Skiessi}/Skiessi-Onion.mmpz | Bin .../Skiessi-RandomProjectNumber14253.mmpz | Bin .../{Skeissi => Skiessi}/Skiessi-TurningPoint.mmpz | Bin 3 files changed, 0 insertions(+), 0 deletions(-) rename data/projects/CoolSongs/{Skeissi => Skiessi}/Skiessi-Onion.mmpz (100%) rename data/projects/CoolSongs/{Skeissi => Skiessi}/Skiessi-RandomProjectNumber14253.mmpz (100%) rename data/projects/CoolSongs/{Skeissi => Skiessi}/Skiessi-TurningPoint.mmpz (100%) diff --git a/data/projects/CoolSongs/Skeissi/Skiessi-Onion.mmpz b/data/projects/CoolSongs/Skiessi/Skiessi-Onion.mmpz similarity index 100% rename from data/projects/CoolSongs/Skeissi/Skiessi-Onion.mmpz rename to data/projects/CoolSongs/Skiessi/Skiessi-Onion.mmpz diff --git a/data/projects/CoolSongs/Skeissi/Skiessi-RandomProjectNumber14253.mmpz b/data/projects/CoolSongs/Skiessi/Skiessi-RandomProjectNumber14253.mmpz similarity index 100% rename from data/projects/CoolSongs/Skeissi/Skiessi-RandomProjectNumber14253.mmpz rename to data/projects/CoolSongs/Skiessi/Skiessi-RandomProjectNumber14253.mmpz diff --git a/data/projects/CoolSongs/Skeissi/Skiessi-TurningPoint.mmpz b/data/projects/CoolSongs/Skiessi/Skiessi-TurningPoint.mmpz similarity index 100% rename from data/projects/CoolSongs/Skeissi/Skiessi-TurningPoint.mmpz rename to data/projects/CoolSongs/Skiessi/Skiessi-TurningPoint.mmpz From 849d08c6efe0fd61d99935ecd7db745392216968 Mon Sep 17 00:00:00 2001 From: falkTX Date: Thu, 11 Sep 2014 16:54:31 +0100 Subject: [PATCH 02/16] Initial version of Carla plugin for LMMS --- CMakeLists.txt | 14 + plugins/CMakeLists.txt | 3 + plugins/carlabase/CMakeLists.txt | 7 + plugins/carlabase/carla.cpp | 483 ++++++++++++++++++++++++ plugins/carlabase/carla.h | 112 ++++++ plugins/carlapatchbay/CMakeLists.txt | 8 + plugins/carlapatchbay/carlapatchbay.cpp | 51 +++ plugins/carlapatchbay/logo.png | Bin 0 -> 3313 bytes plugins/carlarack/CMakeLists.txt | 8 + plugins/carlarack/carlarack.cpp | 51 +++ plugins/carlarack/logo.png | Bin 0 -> 3313 bytes 11 files changed, 737 insertions(+) create mode 100644 plugins/carlabase/CMakeLists.txt create mode 100644 plugins/carlabase/carla.cpp create mode 100644 plugins/carlabase/carla.h create mode 100644 plugins/carlapatchbay/CMakeLists.txt create mode 100644 plugins/carlapatchbay/carlapatchbay.cpp create mode 100644 plugins/carlapatchbay/logo.png create mode 100644 plugins/carlarack/CMakeLists.txt create mode 100644 plugins/carlarack/carlarack.cpp create mode 100644 plugins/carlarack/logo.png 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..c23082ba6 --- /dev/null +++ b/plugins/carlabase/CMakeLists.txt @@ -0,0 +1,7 @@ +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) +endif(LMMS_HAVE_CARLA) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp new file mode 100644 index 000000000..b46a8d626 --- /dev/null +++ b/plugins/carlabase/carla.cpp @@ -0,0 +1,483 @@ +/* + * 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 "CarlaDefines.h" + +#include "engine.h" +#include "InstrumentPlayHandle.h" +#include "InstrumentTrack.h" + +#include +#include +#include +#include + +// ----------------------------------------------------------------------- + +#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) +{ + handlePtr->handleUiCustomDataChanged(key, value); +} + +static void host_ui_closed(NativeHostHandle handle) +{ + handlePtr->handleUiClosed(); +} + +static const char* host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter) +{ + return handlePtr->handleUiOpenFile(isDir, title, filter); +} + +static const char* host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter) +{ + return handlePtr->handleUiSaveFile(isDir, title, filter); +} + +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 + +// ----------------------------------------------------------------------- + +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.resourceDir = strdup("/usr/share/carla/resources/"); // TODO + fHost.uiName = NULL; + fHost.uiParentId = 0; + + 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)); + + 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() ); + + std::free((char*)fHost.resourceDir); + fHost.resourceDir = 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::handleUiCustomDataChanged(const char* const /*key*/, const char* const /*value*/) const +{ +} + +void CarlaInstrument::handleUiClosed() +{ + emit uiClosed(); +} + +const char* CarlaInstrument::handleUiOpenFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const +{ + // TODO + return NULL; +} + +const char* CarlaInstrument::handleUiSaveFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const +{ + // TODO + return NULL; +} + +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->get_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; + } + + 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); + fHost.uiName = strdup(parent->windowTitle().toUtf8().constData()); + + 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(50) : 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..bd9ce5193 --- /dev/null +++ b/plugins/carlabase/carla.h @@ -0,0 +1,112 @@ +/* + * 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 handleUiCustomDataChanged(const char* const key, const char* const value) const; + void handleUiClosed(); + const char* handleUiOpenFile(const bool isDir, const char* const title, const char* const filter) const; + const char* handleUiSaveFile(const bool isDir, const char* const title, const char* const filter) const; + 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 0000000000000000000000000000000000000000..353d5d718d6fef054ff4fed2932f4f45df7f792c GIT binary patch literal 3313 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..353d5d718d6fef054ff4fed2932f4f45df7f792c GIT binary patch literal 3313 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 literal 0 HcmV?d00001 From af1b351dd21ebe9b290f07fc7351fd1c9798b4eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stian=20J=C3=B8rgensrud?= Date: Sun, 14 Sep 2014 21:09:45 +0200 Subject: [PATCH 03/16] Added Popsip-Electric Dancer to CoolSongs --- .../CoolSongs/Popsip-Electric Dancer.mmpz | Bin 0 -> 25916 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 data/projects/CoolSongs/Popsip-Electric Dancer.mmpz diff --git a/data/projects/CoolSongs/Popsip-Electric Dancer.mmpz b/data/projects/CoolSongs/Popsip-Electric Dancer.mmpz new file mode 100644 index 0000000000000000000000000000000000000000..4db5d0d9a104ba289f043396eff1220192d5132f GIT binary patch literal 25916 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 literal 0 HcmV?d00001 From b88225ffc86e72485805fd332ca89d8f9811f983 Mon Sep 17 00:00:00 2001 From: falkTX Date: Tue, 16 Sep 2014 17:22:23 +0100 Subject: [PATCH 04/16] Carla: Fix link (rpath) and finding binary dir (needs latest carla) --- plugins/carlabase/CMakeLists.txt | 15 ++++++++++----- plugins/carlabase/carla.cpp | 14 +++++++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/plugins/carlabase/CMakeLists.txt b/plugins/carlabase/CMakeLists.txt index c23082ba6..82c31dbd0 100644 --- a/plugins/carlabase/CMakeLists.txt +++ b/plugins/carlabase/CMakeLists.txt @@ -1,7 +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) + 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 index b46a8d626..ec5cff9e2 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -25,7 +25,7 @@ #include "carla.h" #define REAL_BUILD // FIXME this shouldn't be needed -#include "CarlaDefines.h" +#include "CarlaHost.h" #include "engine.h" #include "InstrumentPlayHandle.h" @@ -115,10 +115,18 @@ CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const D fMidiEventCount(0) { fHost.handle = this; - fHost.resourceDir = strdup("/usr/share/carla/resources/"); // TODO 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; @@ -421,7 +429,7 @@ CarlaInstrumentView::CarlaInstrumentView(CarlaInstrument* const instrument, QWid : InstrumentView(instrument, parent), fHandle(instrument->fHandle), fDescriptor(instrument->fDescriptor), - fTimerId(fHandle != NULL && fDescriptor->ui_idle != NULL ? startTimer(50) : 0) + fTimerId(fHandle != NULL && fDescriptor->ui_idle != NULL ? startTimer(30) : 0) { setAutoFillBackground(true); From b0fab3d3c2abb3a22744f51d0b16ca7d99a24220 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 26 Sep 2014 10:31:08 +0100 Subject: [PATCH 05/16] Carla: Implement UI Save/Open for plugins; Misc fixes --- plugins/carlabase/carla.cpp | 78 +++++++++++++++++++++---------------- plugins/carlabase/carla.h | 3 -- 2 files changed, 44 insertions(+), 37 deletions(-) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index ec5cff9e2..ad061fe83 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -31,9 +31,12 @@ #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" +#include +#include #include #include #include + #include // ----------------------------------------------------------------------- @@ -62,7 +65,7 @@ static const NativeTimeInfo* host_get_time_info(NativeHostHandle handle) static bool host_write_midi_event(NativeHostHandle, const NativeMidiEvent*) { - return false; // unsupported + return false; // unsupported? } static void host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, float value) @@ -72,7 +75,7 @@ static void host_ui_parameter_changed(NativeHostHandle handle, uint32_t index, f static void host_ui_custom_data_changed(NativeHostHandle handle, const char* key, const char* value) { - handlePtr->handleUiCustomDataChanged(key, value); + // unused } static void host_ui_closed(NativeHostHandle handle) @@ -80,16 +83,6 @@ static void host_ui_closed(NativeHostHandle handle) handlePtr->handleUiClosed(); } -static const char* host_ui_open_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter) -{ - return handlePtr->handleUiOpenFile(isDir, title, filter); -} - -static const char* host_ui_save_file(NativeHostHandle handle, bool isDir, const char* title, const char* filter) -{ - return handlePtr->handleUiSaveFile(isDir, title, filter); -} - 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); @@ -99,6 +92,28 @@ static intptr_t host_dispatcher(NativeHostHandle handle, NativeHostDispatcherOpc // ----------------------------------------------------------------------- +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(); @@ -158,11 +173,17 @@ CarlaInstrument::~CarlaInstrument() { engine::mixer()->removePlayHandles( instrumentTrack() ); - std::free((char*)fHost.resourceDir); - fHost.resourceDir = NULL; + if (fHost.resourceDir != NULL) + { + std::free((char*)fHost.resourceDir); + fHost.resourceDir = NULL; + } - std::free((char*)fHost.uiName); - fHost.uiName = NULL; + if (fHost.uiName != NULL) + { + std::free((char*)fHost.uiName); + fHost.uiName = NULL; + } if (fHandle == NULL) return; @@ -202,27 +223,11 @@ void CarlaInstrument::handleUiParameterChanged(const uint32_t /*index*/, const f { } -void CarlaInstrument::handleUiCustomDataChanged(const char* const /*key*/, const char* const /*value*/) const -{ -} - void CarlaInstrument::handleUiClosed() { emit uiClosed(); } -const char* CarlaInstrument::handleUiOpenFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const -{ - // TODO - return NULL; -} - -const char* CarlaInstrument::handleUiSaveFile(const bool /*isDir*/, const char* const /*title*/, const char* const /*filter*/) const -{ - // TODO - return NULL; -} - 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; @@ -284,7 +289,7 @@ void CarlaInstrument::saveSettings(QDomDocument& doc, QDomElement& parent) void CarlaInstrument::loadSettings(const QDomElement& elem) { - if (fHandle == NULL || fDescriptor->get_state == NULL) + if (fHandle == NULL || fDescriptor->set_state == NULL) return; QDomDocument carlaDoc("carla"); @@ -305,6 +310,8 @@ void CarlaInstrument::play(sampleFrame* workingBuffer) return; } + // TODO - set time info + float buf1[bufsize]; float buf2[bufsize]; float* rBuf[] = { buf1, buf2 }; @@ -413,7 +420,10 @@ PluginView* CarlaInstrument::instantiateView(QWidget* parent) fHost.uiParentId = 0; std::free((char*)fHost.uiName); - fHost.uiName = strdup(parent->windowTitle().toUtf8().constData()); + + // 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); } diff --git a/plugins/carlabase/carla.h b/plugins/carlabase/carla.h index bd9ce5193..f53f16c74 100644 --- a/plugins/carlabase/carla.h +++ b/plugins/carlabase/carla.h @@ -48,10 +48,7 @@ public: bool handleIsOffline() const; const NativeTimeInfo* handleGetTimeInfo() const; void handleUiParameterChanged(const uint32_t index, const float value) const; - void handleUiCustomDataChanged(const char* const key, const char* const value) const; void handleUiClosed(); - const char* handleUiOpenFile(const bool isDir, const char* const title, const char* const filter) const; - const char* handleUiSaveFile(const bool isDir, const char* const title, const char* const filter) const; intptr_t handleDispatcher(const NativeHostDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float opt); // LMMS functions From 8aa29bb4ba67885b62d8901f149a4bde5b743583 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 26 Sep 2014 10:38:05 +0100 Subject: [PATCH 06/16] Add TODO items for carla --- plugins/carlabase/carla.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index ad061fe83..e1a4ad368 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -39,6 +39,18 @@ #include +/* + * Current TODO items: + * - get plugin instance name (to use in external window title) + * - buffer-size change callback + * - offline mode change callback + * - set time info + * - midi output + * - background artwork + * + * All other items are to be done in Carla itself. + */ + // ----------------------------------------------------------------------- #define handlePtr ((CarlaInstrument*)handle) From 5dddbe7c306291c769bd03d144ed546315966354 Mon Sep 17 00:00:00 2001 From: falkTX Date: Fri, 26 Sep 2014 11:58:42 +0100 Subject: [PATCH 07/16] Pass timeInfo to Carla plugin --- plugins/carlabase/carla.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index e1a4ad368..5b590e012 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -28,6 +28,7 @@ #include "CarlaHost.h" #include "engine.h" +#include "song.h" #include "InstrumentPlayHandle.h" #include "InstrumentTrack.h" @@ -39,12 +40,14 @@ #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) * - buffer-size change callback * - offline mode change callback - * - set time info * - midi output * - background artwork * @@ -167,6 +170,7 @@ CarlaInstrument::CarlaInstrument(InstrumentTrack* const instrumentTrack, const D fHost.dispatcher = host_dispatcher; std::memset(&fTimeInfo, 0, sizeof(NativeTimeInfo)); + fTimeInfo.bbt.valid = true; // always valid fHandle = fDescriptor->instantiate(&fHost); Q_ASSERT(fHandle != NULL); @@ -322,7 +326,19 @@ void CarlaInstrument::play(sampleFrame* workingBuffer) return; } - // TODO - set time info + // 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]; From 9f6c9d96eff1d905d9779de518d1a2e92c0b012e Mon Sep 17 00:00:00 2001 From: falkTX Date: Sat, 27 Sep 2014 00:31:28 +0100 Subject: [PATCH 08/16] Carla: Misc fixing --- plugins/carlabase/carla.cpp | 3 +-- plugins/carlabase/carla.h | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/carlabase/carla.cpp b/plugins/carlabase/carla.cpp index 5b590e012..81f724473 100644 --- a/plugins/carlabase/carla.cpp +++ b/plugins/carlabase/carla.cpp @@ -46,7 +46,6 @@ static const double ticksPerBeat = 48.0; /* * Current TODO items: * - get plugin instance name (to use in external window title) - * - buffer-size change callback * - offline mode change callback * - midi output * - background artwork @@ -330,7 +329,7 @@ void CarlaInstrument::play(sampleFrame* workingBuffer) song* const s = engine::getSong(); fTimeInfo.playing = s->isPlaying(); fTimeInfo.frame = s->getPlayPos(s->playMode()).frames(engine::framesPerTick()); - fTimeInfo.usecs = s->getMilliseconds()/1000; + fTimeInfo.usecs = s->getMilliseconds()*1000; fTimeInfo.bbt.bar = s->getTacts() + 1; fTimeInfo.bbt.beat = s->getBeat() + 1; fTimeInfo.bbt.tick = s->getBeatTicks(); diff --git a/plugins/carlabase/carla.h b/plugins/carlabase/carla.h index f53f16c74..e809c001a 100644 --- a/plugins/carlabase/carla.h +++ b/plugins/carlabase/carla.h @@ -22,8 +22,8 @@ * */ -#ifndef _CARLA_H -#define _CARLA_H +#ifndef CARLA_H +#define CARLA_H #include "CarlaNative.h" From 6b54a4bcc18aabe5e2df86fec8cc252a54a3ec18 Mon Sep 17 00:00:00 2001 From: Spekular Date: Sun, 28 Sep 2014 10:04:02 +0200 Subject: [PATCH 09/16] Background Art Fix Fixes Background art and provides .svg source --- data/themes/default/background_artwork.png | Bin 989 -> 689 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/themes/default/background_artwork.png b/data/themes/default/background_artwork.png index 8725e664f69a56b14192a435374ba912470922ff..918fc27af192168a7fb26dbfc2400974f6ee625d 100644 GIT binary patch literal 689 zcmeAS@N?(olHy`uVBq!ia0vp^0U*r51|<6gKdl8)EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4l@>!cU%shP7X8Oxb&?0mjFX!4>nnhDM&hhKj^2erP(a6dM-znf7$h~=i+z0 zK;44a>%oQ5Uu-p1I}LZu?LEp=x^mhH>tE69PyY&gaJNX;^*D#(j;L$PndS?Xo8)<& z>^xXiOF;BcIl`cqxuScJ~fZ}O(fXKNo!RnZkIZ?X}Y zn$>uElgR$?^cC$h%iON&#VO}^cYX2LZuFzXbUy3v+9L^Ftczyv{hCzhRw#JU=|YgD zceQhONa({`k8dpZGd8}shke-;z4-rZl}f!#-b*W{s~^(hac)!);c#kHux?yhdoNac zv+VI=L(4bJ$vw++JXSFN`vp9l^Q zoVO(RYusWU; z_CUu{Y%)_ike|II{q)8ea~f5@oZ7fU_=ffIq&&`eL#5-7ycC?WO_w_em@~OQjkqH+ zG0;-XoXPdrlZZPy56i2bM#ONvnVDRuxj`N5B@vD!zXv%$Lu()SfQ)v1c5>qk(G@-C nHqN-soZigj2##fB;)!_9_gQajyHk3A$&10$)z4*}Q$iB}fKL}F delta 967 zcmV;&133J#1>FabB!3BTNLh0L01FcU01FcV0GgZ_00007bV*G`2i^e|0vQLY5+2zA z000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000A5Nkl3@Ja{m(r=uhRRr;5d~YmkC}+PZcUCNtXbxYz4dU>_eJv44~`@pI0p0MKs^Z2;1%#vN>EBUK*QflDd4?7&TRmN+i_V-??K;NqojRr0hEDf7dmneEpcjbQ$-zE zV-`KvVrmbZUbd%ULKBD{KP;6hT}&&$b9PGij{w5oM}J)skv=pnfLp;G0g~EAC%JG=T2L!#?#tZURto@p44DBRZEg3DMC5Bo7(T@i9J7d?^Fz{-8 z;xW?VaCK-bas^21BN;8jJNZxS1^M zoP!wS0e=>br_Ll1dJlqXX{#LJ1t2 z(JefPbSefSqj0A!gdl>3bz*JnlS&ry#Z7(OqhAB?qk^uy!hpA0Cx=R z%j`dWEYUJ}Pxx5O0{E1V#aor@NCv;d#}X|7H`B)wwF5WX$D$U%ReUT_6Wcg|EBIKv zMt|^Xpv~~HsOW`P_OYm7U~2(0eJsv7J$2xUJ{A?jgq3|PDj2xBk41eeH`~Xex|LhO z$6{_8^R$n}YiHl5vFomTO-T4EP*;2`Cgy=NeJp!Z>EhuvGj0VRi`p2tijPHg7GA-} zVxkV5>0>dMM4o Date: Sun, 28 Sep 2014 10:06:18 +0200 Subject: [PATCH 10/16] Update .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 45d3a7e96..25c79bb60 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,6 @@ /plugins/zynaddsubfx/zynaddsubfx/ExternalPrograms/Spliter/Makefile /plugins/zynaddsubfx/zynaddsubfx/doc/Makefile /plugins/zynaddsubfx/zynaddsubfx/doc/gen/Makefile +/data/backgrounds/Thumbs.db +/data/themes/default/Thumbs.db +/data/Thumbs.db From e8c6062f9a0d2804a0983e17599f70360a8ee72c Mon Sep 17 00:00:00 2001 From: Spekular Date: Sun, 28 Sep 2014 10:07:10 +0200 Subject: [PATCH 11/16] Update .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 25c79bb60..5b01e1231 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ /data/backgrounds/Thumbs.db /data/themes/default/Thumbs.db /data/Thumbs.db +/gitignore From 6e2d803e0911944bc575a5b8b344f4e2c57cfbae Mon Sep 17 00:00:00 2001 From: Spekular Date: Sun, 28 Sep 2014 10:18:26 +0200 Subject: [PATCH 12/16] Revert "Update .gitignore" This reverts commit e8c6062f9a0d2804a0983e17599f70360a8ee72c. --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5b01e1231..25c79bb60 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,3 @@ /data/backgrounds/Thumbs.db /data/themes/default/Thumbs.db /data/Thumbs.db -/gitignore From ee359207f4dc59dcd46cbba55cb49b97f7e8a186 Mon Sep 17 00:00:00 2001 From: Spekular Date: Sun, 28 Sep 2014 10:18:35 +0200 Subject: [PATCH 13/16] Revert "Update .gitignore" This reverts commit 18bd03118f83a7010485ded10ccc0a0fe5eb54d0. --- .gitignore | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitignore b/.gitignore index 25c79bb60..45d3a7e96 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,3 @@ /plugins/zynaddsubfx/zynaddsubfx/ExternalPrograms/Spliter/Makefile /plugins/zynaddsubfx/zynaddsubfx/doc/Makefile /plugins/zynaddsubfx/zynaddsubfx/doc/gen/Makefile -/data/backgrounds/Thumbs.db -/data/themes/default/Thumbs.db -/data/Thumbs.db From d39d1b3840a9e916a5d3a38405c2ef69181d5ccf Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 28 Sep 2014 18:05:31 +0200 Subject: [PATCH 14/16] ZynAddSubFX: added explicit check for FLTK's fluid binary Closes #954. --- plugins/zynaddsubfx/CMakeLists.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/zynaddsubfx/CMakeLists.txt b/plugins/zynaddsubfx/CMakeLists.txt index 3fd07c891..886480455 100644 --- a/plugins/zynaddsubfx/CMakeLists.txt +++ b/plugins/zynaddsubfx/CMakeLists.txt @@ -38,6 +38,10 @@ IF(MINGW_PREFIX) SET(FLTK_FLUID_EXECUTABLE "${MINGW_PREFIX}/bin/fluid") ENDIF() +IF(NOT EXISTS ${FLTK_FLUID_EXECUTABLE}) + MESSAGE(FATAL_ERROR "Please install the fluid binary which is part of FLTK.") +ENDIF() + INCLUDE_DIRECTORIES("${FLTK_INCLUDE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}" ${FFTW3F_INCLUDE_DIRS} From 75a979b9a0a0dba3cfaba1d38df7abd08d212665 Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 28 Sep 2014 18:07:53 +0200 Subject: [PATCH 15/16] Merge pull request #1174 from DaAwesomeP/master Update Readme --- README.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a76d20354..534066029 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,19 @@ -Linux MultiMedia Studio +![LMMS Logo](http://lmms.sourceforge.net/Lmms_logo.png) Linux MultiMedia Studio (LMMS) ======================= [![Build Status](https://travis-ci.org/LMMS/lmms.png)](https://travis-ci.org/LMMS/lmms) What is LMMS? -------------- -LMMS is a free cross-platform alternative to commercial programs like FL Studio (R), which allow you to produce music with your computer. This includes the creation of melodies and beats, the synthesis and mixing of sounds, and arranging of samples. You can have fun with your MIDI-keyboard and much more; all in a user-friendly and modern interface. +LMMS is a free cross-platform alternative to commercial programs like FL Studio®, which allow you to produce music with your computer. This includes the creation of melodies and beats, the synthesis and mixing of sounds, and arranging of samples. You can have fun with your MIDI-keyboard and much more; all in a user-friendly and modern interface. +[Homepage](http://lmms.sf.net)
+[Downloads/Releases](https://github.com/LMMS/lmms/releases)
+[Developer Wiki](https://github.com/LMMS/lmms/wiki)
+[Artist & User Wiki/Documentation](http://lmms.sourceforge.net/wiki/index.php/Main_Page) This still has some useful pages.
+[Screenshots](http://lmms.sourceforge.net/screenshots.php)
+[Sound Demos](http://lmms.sourceforge.net/demos.php)
+[LMMS Sharing Platform](http://lmms.sourceforge.net/lsp/index.php) Share your songs! Features --------- @@ -18,8 +25,15 @@ Features * Many powerful instrument and effect-plugins out of the box * Full user-defined track-based automation and computer-controlled automation sources * Compatible with many standards such as SoundFont2, VST(i), LADSPA, GUS Patches, and full MIDI support -* Import of MIDI and FLP (Fruityloops(R) Project) files +* Import of MIDI and FLP (FL Studio®/Fruityloops® Project) files +[Latest Stable Release (1.0.3)](https://github.com/LMMS/lmms/releases/tag/v1.0.3) +--------------------- +* Fix zyn GUI crash on win32 +* Fix SF2 note volume +* Localization updates +* Updated LADSPA search paths +* Bugfixes in plugins Building --------- From 613bcc981fc510ae2fa841d9d05cf109902c44ba Mon Sep 17 00:00:00 2001 From: Tobias Doerffel Date: Sun, 28 Sep 2014 18:09:47 +0200 Subject: [PATCH 16/16] README.md: stripped old full program name --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 534066029..83706fc61 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![LMMS Logo](http://lmms.sourceforge.net/Lmms_logo.png) Linux MultiMedia Studio (LMMS) +![LMMS Logo](http://lmms.sourceforge.net/Lmms_logo.png) LMMS ======================= [![Build Status](https://travis-ci.org/LMMS/lmms.png)](https://travis-ci.org/LMMS/lmms)