[debian-edu-commits] debian-edu/pkg-team/ 01/04: Enable vst plugin on i386 and amd64
Javier Serrano Polo
jasp00-guest at moszumanska.debian.org
Wed Apr 20 19:05:03 UTC 2016
This is an automated email from the git hooks/post-receive script.
jasp00-guest pushed a commit to branch master
in repository lmms.
commit 8346491e2d10181a8d4f46fe3e69efe6fa1a5135
Author: Javier Serrano Polo <javier at jasp.net>
Date: Sun Apr 17 00:00:40 2016 +0200
Enable vst plugin on i386 and amd64
---
debian/changelog | 7 +
debian/control | 14 +-
debian/lmms-vst-server.install | 1 +
debian/lmms.install | 4 +-
debian/patches/find-vst_base.patch | 49 ++
debian/patches/series | 4 +
debian/patches/sync-socket.patch | 1085 ++++++++++++++++++++++++++++++++++++
debian/patches/vst-no-wine.patch | 54 ++
debian/patches/wine-runpath.patch | 18 +
debian/rules | 12 +
10 files changed, 1244 insertions(+), 4 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 754d98c..6885b84 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,10 @@
+lmms (1.1.3-1.1) unstable; urgency=low
+
+ * Non-maintainer upload.
+ * Enabled vst plugin on i386 and amd64 (Closes: #763720).
+
+ -- Javier Serrano Polo <javier at jasp.net> Mon, 04 Apr 2016 19:42:09 +0200
+
lmms (1.1.3-1) unstable; urgency=low
* New upstream version 1.1.3 (Closes: #788457).
diff --git a/debian/control b/debian/control
index 41ecc49..4715d07 100644
--- a/debian/control
+++ b/debian/control
@@ -9,8 +9,6 @@ Uploaders:
Build-Depends:
cmake,
debhelper (>= 9.0.0),
- gcc-multilib [amd64],
- g++-multilib [amd64],
imagemagick,
ladspa-sdk,
libsdl-sound1.2-dev,
@@ -32,6 +30,7 @@ Build-Depends:
libxft-dev,
portaudio19-dev,
qt4-qmake,
+ wine32-tools [i386]
Standards-Version: 3.9.6
Homepage: http://lmms.io/
Vcs-Browser: http://anonscm.debian.org/cgit/debian-edu/pkg-team/lmms.git/
@@ -40,7 +39,8 @@ Vcs-Git: git://anonscm.debian.org/debian-edu/pkg-team/lmms.git
Package: lmms
Architecture: any
Depends: lmms-common (>= ${source:Version}) , ${shlibs:Depends}, ${misc:Depends}, stk
-Recommends: tap-plugins, caps
+Recommends: calf-plugins, caps, cmt, swh-plugins, tap-plugins,
+ lmms-vst-server:i386 (>= ${source:Version})
Suggests: fil-plugins, mcp-plugins, omins, freepats, fluid-soundfont-gm
Replaces: lmms-common (<< 1.0.0-1)
Breaks: lmms-common (<< 1.0.0-1)
@@ -71,3 +71,11 @@ Description: Linux Multimedia Studio - common files
.
This package contains the platform independent files such as samples, presets
and some example projects.
+
+Package: lmms-vst-server
+Architecture: i386
+# Order matters to avoid wine64
+Depends: wine32, wine, ${shlibs:Depends}, ${misc:Depends}
+Recommends: lmms
+Description: Linux Multimedia Studio - VST server
+ This package contains a helper application that loads VST plugins.
diff --git a/debian/lmms-vst-server.install b/debian/lmms-vst-server.install
new file mode 100644
index 0000000..1b52047
--- /dev/null
+++ b/debian/lmms-vst-server.install
@@ -0,0 +1 @@
+usr/lib/*/lmms/RemoteVstPlugin*
diff --git a/debian/lmms.install b/debian/lmms.install
index 34a54ff..e6d3667 100644
--- a/debian/lmms.install
+++ b/debian/lmms.install
@@ -1,5 +1,7 @@
usr/bin/lmms
-usr/lib/*/lmms
+usr/lib/*/lmms/ladspa
+usr/lib/*/lmms/lib*
+usr/lib/*/lmms/RemoteZynAddSubFx
usr/share/man/*
usr/share/applications/*
data/application-x-lmms-project.svg usr/share/icons/gnome/scalable/mimetypes
diff --git a/debian/patches/find-vst_base.patch b/debian/patches/find-vst_base.patch
new file mode 100644
index 0000000..49b2d98
--- /dev/null
+++ b/debian/patches/find-vst_base.patch
@@ -0,0 +1,49 @@
+Description: Find vstbase library at runtime
+ The NEEDED entry was ../vst_base/libvstbase.so. The library was searched in
+ ../vst_base, which is relative to the invocation directory. The patch sets the
+ RUNPATH entry.
+Author: Javier Serrano Polo <javier at jasp.net>
+
+Index: lmms-1.1.3/plugins/CMakeLists.txt
+===================================================================
+--- lmms-1.1.3.orig/plugins/CMakeLists.txt 2016-04-05 23:41:16.000000000 +0200
++++ lmms-1.1.3/plugins/CMakeLists.txt 2016-04-05 23:52:36.000000000 +0200
+@@ -33,8 +33,9 @@
+ ADD_SUBDIRECTORY(stereo_matrix)
+ ADD_SUBDIRECTORY(stk)
+ ADD_SUBDIRECTORY(triple_oscillator)
+-ADD_SUBDIRECTORY(vestige)
++# dependency is not detected
+ ADD_SUBDIRECTORY(vst_base)
++ADD_SUBDIRECTORY(vestige)
+ ADD_SUBDIRECTORY(VstEffect)
+ ADD_SUBDIRECTORY(watsyn)
+ ADD_SUBDIRECTORY(waveshaper)
+Index: lmms-1.1.3/plugins/VstEffect/CMakeLists.txt
+===================================================================
+--- lmms-1.1.3.orig/plugins/VstEffect/CMakeLists.txt 2015-03-08 03:47:14.000000000 +0100
++++ lmms-1.1.3/plugins/VstEffect/CMakeLists.txt 2016-04-05 23:27:04.000000000 +0200
+@@ -2,7 +2,8 @@
+ INCLUDE(BuildPlugin)
+ INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../vst_base")
+ LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../vst_base")
+-LINK_LIBRARIES(vstbase)
++LINK_LIBRARIES(-lvstbase -Wl,--enable-new-dtags)
++SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
+ BUILD_PLUGIN(vsteffect VstEffect.cpp VstEffectControls.cpp VstEffectControlDialog.cpp VstSubPluginFeatures.cpp VstEffect.h VstEffectControls.h VstEffectControlDialog.h VstSubPluginFeatures.h MOCFILES VstEffectControlDialog.h VstEffectControls.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")
+ SET_TARGET_PROPERTIES(vsteffect PROPERTIES COMPILE_FLAGS "-Wno-attributes")
+
+Index: lmms-1.1.3/plugins/vestige/CMakeLists.txt
+===================================================================
+--- lmms-1.1.3.orig/plugins/vestige/CMakeLists.txt 2015-03-08 03:47:14.000000000 +0100
++++ lmms-1.1.3/plugins/vestige/CMakeLists.txt 2016-04-05 23:51:23.000000000 +0200
+@@ -2,7 +2,8 @@
+ INCLUDE(BuildPlugin)
+ INCLUDE_DIRECTORIES("${CMAKE_CURRENT_SOURCE_DIR}/../vst_base")
+ LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/../vst_base")
+- LINK_LIBRARIES(vstbase)
++ LINK_LIBRARIES(-lvstbase -Wl,--enable-new-dtags)
++ SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${PLUGIN_DIR}")
+ BUILD_PLUGIN(vestige vestige.cpp vestige.h MOCFILES vestige.h EMBEDDED_RESOURCES "${CMAKE_CURRENT_SOURCE_DIR}/*.png")
+ ENDIF(LMMS_SUPPORT_VST)
+
diff --git a/debian/patches/series b/debian/patches/series
index ee07457..48fcb46 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -2,3 +2,7 @@ desktop-argument.patch
find-fluid.patch
gcc5.patch
man-page-adjustment.patch
+find-vst_base.patch
+vst-no-wine.patch
+wine-runpath.patch
+sync-socket.patch
diff --git a/debian/patches/sync-socket.patch b/debian/patches/sync-socket.patch
new file mode 100644
index 0000000..5e9250d
--- /dev/null
+++ b/debian/patches/sync-socket.patch
@@ -0,0 +1,1085 @@
+Description: Synchronize with remote plugins using local sockets
+ VST plugins are i386 code and an i386 remote plugin is needed. Previous
+ implementation used semaphores; communication with amd64 hosts did not work.
+Author: Javier Serrano Polo <javier at jasp.net>
+
+Index: lmms-1.1.3/include/RemotePlugin.h
+===================================================================
+--- lmms-1.1.3.orig/include/RemotePlugin.h 2016-04-09 01:09:22.000000000 +0200
++++ lmms-1.1.3/include/RemotePlugin.h 2016-04-14 21:10:40.000000000 +0200
+@@ -37,41 +37,9 @@
+ #include <cassert>
+
+ #ifdef LMMS_BUILD_WIN32
+-#define USE_QT_SEMAPHORES
+ #define USE_QT_SHMEM
+ #endif
+
+-#ifdef LMMS_BUILD_APPLE
+-#define USE_QT_SEMAPHORES
+-#endif
+-
+-
+-#ifdef USE_QT_SEMAPHORES
+-
+-#ifdef LMMS_HAVE_PROCESS_H
+-#include <process.h>
+-#endif
+-
+-#include <QtCore/QtGlobal>
+-
+-#if QT_VERSION >= 0x040400
+-#include <QtCore/QSystemSemaphore>
+-#else
+-#error building LMMS on this platform requires at least Qt 4.4.0
+-#endif
+-
+-#else /* USE_QT_SEMAPHORES */
+-
+-#ifdef LMMS_HAVE_SYS_IPC_H
+-#include <sys/ipc.h>
+-#endif
+-
+-#ifdef LMMS_HAVE_SEMAPHORE_H
+-#include <semaphore.h>
+-#endif
+-
+-#endif
+-
+
+ #ifdef USE_QT_SHMEM
+
+@@ -108,385 +76,15 @@
+ #undef EXPORT
+ #define EXPORT
+ #define COMPILE_REMOTE_PLUGIN_BASE
++#include <sys/socket.h>
++#include <sys/un.h>
+ #else
++#include <poll.h>
+ #include <QtCore/QMutex>
+ #include <QtCore/QProcess>
+ #include <QtCore/QThread>
+ #endif
+
+-// sometimes we need to exchange bigger messages (e.g. for VST parameter dumps)
+-// so set a usable value here
+-const int SHM_FIFO_SIZE = 512*1024;
+-
+-
+-// implements a FIFO inside a shared memory segment
+-class shmFifo
+-{
+- // need this union to handle different sizes of sem_t on 32 bit
+- // and 64 bit platforms
+- union sem32_t
+- {
+-#ifndef USE_QT_SEMAPHORES
+- sem_t sem;
+-#endif
+- int semKey;
+- char fill[32];
+- } ;
+- struct shmData
+- {
+- sem32_t dataSem; // semaphore for locking this
+- // FIFO management data
+- sem32_t messageSem; // semaphore for incoming messages
+- volatile int32_t startPtr; // current start of FIFO in memory
+- volatile int32_t endPtr; // current end of FIFO in memory
+- char data[SHM_FIFO_SIZE]; // actual data
+- } ;
+-
+-public:
+- // constructor for master-side
+- shmFifo() :
+- m_invalid( false ),
+- m_master( true ),
+- m_shmKey( 0 ),
+-#ifdef USE_QT_SHMEM
+- m_shmObj(),
+-#else
+- m_shmID( -1 ),
+-#endif
+- m_data( NULL ),
+-#ifdef USE_QT_SEMAPHORES
+- m_dataSem( QString::null ),
+- m_messageSem( QString::null ),
+-#else
+- m_dataSem( NULL ),
+- m_messageSem( NULL ),
+-#endif
+- m_lockDepth( 0 )
+- {
+-#ifdef USE_QT_SHMEM
+- do
+- {
+- m_shmObj.setKey( QString( "%1" ).arg( ++m_shmKey ) );
+- m_shmObj.create( sizeof( shmData ) );
+- } while( m_shmObj.error() != QSharedMemory::NoError );
+-
+- m_data = (shmData *) m_shmObj.data();
+-#else
+- while( ( m_shmID = shmget( ++m_shmKey, sizeof( shmData ),
+- IPC_CREAT | IPC_EXCL | 0600 ) ) == -1 )
+- {
+- }
+- m_data = (shmData *) shmat( m_shmID, 0, 0 );
+-#endif
+- assert( m_data != NULL );
+- m_data->startPtr = m_data->endPtr = 0;
+-#ifdef USE_QT_SEMAPHORES
+- static int k = 0;
+- m_data->dataSem.semKey = ( getpid()<<10 ) + ++k;
+- m_data->messageSem.semKey = ( getpid()<<10 ) + ++k;
+- m_dataSem.setKey( QString::number( m_data->dataSem.semKey ),
+- 1, QSystemSemaphore::Create );
+- m_messageSem.setKey( QString::number(
+- m_data->messageSem.semKey ),
+- 0, QSystemSemaphore::Create );
+-#else
+- m_dataSem = &m_data->dataSem.sem;
+- m_messageSem = &m_data->messageSem.sem;
+-
+- if( sem_init( m_dataSem, 1, 1 ) )
+- {
+- fprintf( stderr, "could not initialize m_dataSem\n" );
+- }
+- if( sem_init( m_messageSem, 1, 0 ) )
+- {
+- fprintf( stderr, "could not initialize "
+- "m_messageSem\n" );
+- }
+-#endif
+- }
+-
+- // constructor for remote-/client-side - use _shm_key for making up
+- // the connection to master
+- shmFifo( key_t _shm_key ) :
+- m_invalid( false ),
+- m_master( false ),
+- m_shmKey( 0 ),
+-#ifdef USE_QT_SHMEM
+- m_shmObj( QString::number( _shm_key ) ),
+-#else
+- m_shmID( shmget( _shm_key, 0, 0 ) ),
+-#endif
+- m_data( NULL ),
+-#ifdef USE_QT_SEMAPHORES
+- m_dataSem( QString::null ),
+- m_messageSem( QString::null ),
+-#else
+- m_dataSem( NULL ),
+- m_messageSem( NULL ),
+-#endif
+- m_lockDepth( 0 )
+- {
+-#ifdef USE_QT_SHMEM
+- if( m_shmObj.attach() )
+- {
+- m_data = (shmData *) m_shmObj.data();
+- }
+-#else
+- if( m_shmID != -1 )
+- {
+- m_data = (shmData *) shmat( m_shmID, 0, 0 );
+- }
+-#endif
+- assert( m_data != NULL );
+-#ifdef USE_QT_SEMAPHORES
+- m_dataSem.setKey( QString::number( m_data->dataSem.semKey ) );
+- m_messageSem.setKey( QString::number(
+- m_data->messageSem.semKey ) );
+-#else
+- m_dataSem = &m_data->dataSem.sem;
+- m_messageSem = &m_data->messageSem.sem;
+-#endif
+- }
+-
+- ~shmFifo()
+- {
+-#ifndef USE_QT_SHMEM
+- shmdt( m_data );
+-#endif
+- // master?
+- if( m_master )
+- {
+-#ifndef USE_QT_SHMEM
+- shmctl( m_shmID, IPC_RMID, NULL );
+-#endif
+-#ifndef USE_QT_SEMAPHORES
+- sem_destroy( m_dataSem );
+- sem_destroy( m_messageSem );
+-#endif
+- }
+- }
+-
+- inline bool isInvalid() const
+- {
+- return m_invalid;
+- }
+-
+- void invalidate()
+- {
+- m_invalid = true;
+- }
+-
+- // do we act as master (i.e. not as remote-process?)
+- inline bool isMaster() const
+- {
+- return m_master;
+- }
+-
+- // recursive lock
+- inline void lock()
+- {
+- if( !isInvalid() && __sync_add_and_fetch( &m_lockDepth, 1 ) == 1 )
+- {
+-#ifdef USE_QT_SEMAPHORES
+- m_dataSem.acquire();
+-#else
+- sem_wait( m_dataSem );
+-#endif
+- }
+- }
+-
+- // recursive unlock
+- inline void unlock()
+- {
+- if( __sync_sub_and_fetch( &m_lockDepth, 1) <= 0 )
+- {
+-#ifdef USE_QT_SEMAPHORES
+- m_dataSem.release();
+-#else
+- sem_post( m_dataSem );
+-#endif
+- }
+- }
+-
+- // wait until message-semaphore is available
+- inline void waitForMessage()
+- {
+- if( !isInvalid() )
+- {
+-#ifdef USE_QT_SEMAPHORES
+- m_messageSem.acquire();
+-#else
+- sem_wait( m_messageSem );
+-#endif
+- }
+- }
+-
+- // increase message-semaphore
+- inline void messageSent()
+- {
+-#ifdef USE_QT_SEMAPHORES
+- m_messageSem.release();
+-#else
+- sem_post( m_messageSem );
+-#endif
+- }
+-
+-
+- inline int32_t readInt()
+- {
+- int32_t i;
+- read( &i, sizeof( i ) );
+- return i;
+- }
+-
+- inline void writeInt( const int32_t & _i )
+- {
+- write( &_i, sizeof( _i ) );
+- }
+-
+- inline std::string readString()
+- {
+- const int len = readInt();
+- if( len )
+- {
+- char * sc = new char[len + 1];
+- read( sc, len );
+- sc[len] = 0;
+- std::string s( sc );
+- delete[] sc;
+- return s;
+- }
+- return std::string();
+- }
+-
+-
+- inline void writeString( const std::string & _s )
+- {
+- const int len = _s.size();
+- writeInt( len );
+- write( _s.c_str(), len );
+- }
+-
+-
+- inline bool messagesLeft()
+- {
+- if( isInvalid() )
+- {
+- return false;
+- }
+-#ifdef USE_QT_SEMAPHORES
+- lock();
+- const bool empty = ( m_data->startPtr == m_data->endPtr );
+- unlock();
+- return !empty;
+-#else
+- int v;
+- sem_getvalue( m_messageSem, &v );
+- return v > 0;
+-#endif
+- }
+-
+-
+- inline int shmKey() const
+- {
+- return m_shmKey;
+- }
+-
+-
+-private:
+- static inline void fastMemCpy( void * _dest, const void * _src,
+- const int _len )
+- {
+- // calling memcpy() for just an integer is obsolete overhead
+- if( _len == 4 )
+- {
+- *( (int32_t *) _dest ) = *( (int32_t *) _src );
+- }
+- else
+- {
+- memcpy( _dest, _src, _len );
+- }
+- }
+-
+- void read( void * _buf, int _len )
+- {
+- if( isInvalid() )
+- {
+- memset( _buf, 0, _len );
+- return;
+- }
+- lock();
+- while( isInvalid() == false &&
+- _len > m_data->endPtr - m_data->startPtr )
+- {
+- unlock();
+-#ifndef LMMS_BUILD_WIN32
+- usleep( 5 );
+-#endif
+- lock();
+- }
+- fastMemCpy( _buf, m_data->data + m_data->startPtr, _len );
+- m_data->startPtr += _len;
+- // nothing left?
+- if( m_data->startPtr == m_data->endPtr )
+- {
+- // then reset to 0
+- m_data->startPtr = m_data->endPtr = 0;
+- }
+- unlock();
+- }
+-
+- void write( const void * _buf, int _len )
+- {
+- if( isInvalid() || _len > SHM_FIFO_SIZE )
+- {
+- return;
+- }
+- lock();
+- while( _len > SHM_FIFO_SIZE - m_data->endPtr )
+- {
+- // if no space is left, try to move data to front
+- if( m_data->startPtr > 0 )
+- {
+- memmove( m_data->data,
+- m_data->data + m_data->startPtr,
+- m_data->endPtr - m_data->startPtr );
+- m_data->endPtr = m_data->endPtr -
+- m_data->startPtr;
+- m_data->startPtr = 0;
+- }
+- unlock();
+-#ifndef LMMS_BUILD_WIN32
+- usleep( 5 );
+-#endif
+- lock();
+- }
+- fastMemCpy( m_data->data + m_data->endPtr, _buf, _len );
+- m_data->endPtr += _len;
+- unlock();
+- }
+-
+- volatile bool m_invalid;
+- bool m_master;
+- key_t m_shmKey;
+-#ifdef USE_QT_SHMEM
+- QSharedMemory m_shmObj;
+-#else
+- int m_shmID;
+-#endif
+- shmData * m_data;
+-#ifdef USE_QT_SEMAPHORES
+- QSystemSemaphore m_dataSem;
+- QSystemSemaphore m_messageSem;
+-#else
+- sem_t * m_dataSem;
+- sem_t * m_messageSem;
+-#endif
+- volatile int m_lockDepth;
+-
+-} ;
+-
+-
+
+ enum RemoteMessageIDs
+ {
+@@ -596,30 +194,51 @@
+
+ } ;
+
+- RemotePluginBase( shmFifo * _in, shmFifo * _out );
++ RemotePluginBase();
+ virtual ~RemotePluginBase();
+
+- void reset( shmFifo *in, shmFifo *out )
++ inline int32_t readInt()
+ {
+- delete m_in;
+- delete m_out;
+- m_in = in;
+- m_out = out;
++ int32_t i;
++ read( &i, sizeof( i ) );
++ return i;
+ }
+
+- int sendMessage( const message & _m );
+- message receiveMessage();
++ inline void writeInt( const int32_t & _i )
++ {
++ write( &_i, sizeof( _i ) );
++ }
+
+- inline bool isInvalid() const
++ inline std::string readString()
+ {
+- return m_in->isInvalid() || m_out->isInvalid();
++ const int len = readInt();
++ if( len )
++ {
++ char * sc = new char[len + 1];
++ read( sc, len );
++ sc[len] = 0;
++ std::string s( sc );
++ delete[] sc;
++ return s;
++ }
++ return std::string();
+ }
+
+- inline bool messagesLeft()
++
++ inline void writeString( const std::string & _s )
+ {
+- return m_in->messagesLeft();
++ const int len = _s.size();
++ writeInt( len );
++ write( _s.c_str(), len );
+ }
+
++ int sendMessage( const message & _m );
++ message receiveMessage();
++
++ inline bool isInvalid() const
++ {
++ return m_invalid;
++ }
+
+ message waitForMessage( const message & _m,
+ bool _busy_waiting = false );
+@@ -631,6 +250,7 @@
+ return m;
+ }
+
++#ifndef BUILD_REMOTE_PLUGIN_CLIENT
+ inline void fetchAndProcessAllMessages()
+ {
+ while( messagesLeft() )
+@@ -639,31 +259,96 @@
+ }
+ }
+
++ inline bool messagesLeft()
++ {
++ struct pollfd pollin;
++ pollin.fd = m_socket;
++ pollin.events = POLLIN;
++
++ if ( poll( &pollin, 1, 0 ) == -1 )
++ {
++ qWarning( "Unexpected poll error." );
++ }
++ return pollin.revents & POLLIN;
++ }
++#endif
++
+ virtual bool processMessage( const message & _m ) = 0;
+
+
+ protected:
+- inline const shmFifo * in() const
++ void invalidate()
+ {
+- return m_in;
++ m_invalid = true;
+ }
+
+- inline const shmFifo * out() const
++
++ int m_socket;
++
++
++private:
++ void read( void * _buf, int _len )
+ {
+- return m_out;
++ if( isInvalid() )
++ {
++ memset( _buf, 0, _len );
++ return;
++ }
++ char * buf = (char *) _buf;
++ int remaining = _len;
++ while ( remaining )
++ {
++ ssize_t nread = ::read( m_socket, buf, remaining );
++ switch ( nread )
++ {
++ case -1:
++ fprintf( stderr,
++ "Error while reading.\n" );
++ case 0:
++ invalidate();
++ memset( _buf, 0, _len );
++ return;
++ }
++ remaining -= nread;
++ if ( remaining )
++ {
++ buf += nread;
++ sched_yield();
++ }
++ }
+ }
+
+- inline void invalidate()
++ void write( const void * _buf, int _len )
+ {
+- m_in->invalidate();
+- m_out->invalidate();
+- m_in->messageSent();
++ if( isInvalid() )
++ {
++ return;
++ }
++ const char * buf = (const char *) _buf;
++ int remaining = _len;
++ while ( remaining )
++ {
++ ssize_t nwritten = ::write( m_socket, buf, remaining );
++ switch ( nwritten )
++ {
++ case -1:
++ fprintf( stderr,
++ "Error while writing.\n" );
++ case 0:
++ invalidate();
++ return;
++ }
++ remaining -= nwritten;
++ if ( remaining )
++ {
++ buf += nwritten;
++ sched_yield();
++ }
++ }
+ }
+
+
+-private:
+- shmFifo * m_in;
+- shmFifo * m_out;
++ bool m_invalid;
+
+ } ;
+
+@@ -697,8 +382,9 @@
+ } ;
+
+
+-class EXPORT RemotePlugin : public RemotePluginBase
++class EXPORT RemotePlugin : public QObject, public RemotePluginBase
+ {
++ Q_OBJECT
+ public:
+ RemotePlugin();
+ virtual ~RemotePlugin();
+@@ -797,7 +483,14 @@
+ int m_inputCount;
+ int m_outputCount;
+
++ int m_server;
++ QString m_socketFile;
++
+ friend class ProcessWatcher;
++
++
++private slots:
++ void processFinished( int exitCode, QProcess::ExitStatus exitStatus );
+ } ;
+
+ #endif
+@@ -808,7 +501,7 @@
+ class RemotePluginClient : public RemotePluginBase
+ {
+ public:
+- RemotePluginClient( key_t _shm_in, key_t _shm_out );
++ RemotePluginClient( const char * socketPath );
+ virtual ~RemotePluginClient();
+ #ifdef USE_QT_SHMEM
+ VstSyncData * getQtVSTshm();
+@@ -905,9 +598,9 @@
+ #endif
+
+
+-RemotePluginBase::RemotePluginBase( shmFifo * _in, shmFifo * _out ) :
+- m_in( _in ),
+- m_out( _out )
++RemotePluginBase::RemotePluginBase() :
++ m_socket( -1 ),
++ m_invalid( false )
+ {
+ #ifdef LMMS_HAVE_LOCALE_H
+ // make sure, we're using common ways to print/scan
+@@ -921,8 +614,6 @@
+
+ RemotePluginBase::~RemotePluginBase()
+ {
+- delete m_in;
+- delete m_out;
+ }
+
+
+@@ -930,17 +621,14 @@
+
+ int RemotePluginBase::sendMessage( const message & _m )
+ {
+- m_out->lock();
+- m_out->writeInt( _m.id );
+- m_out->writeInt( _m.data.size() );
++ writeInt( _m.id );
++ writeInt( _m.data.size() );
+ int j = 8;
+ for( unsigned int i = 0; i < _m.data.size(); ++i )
+ {
+- m_out->writeString( _m.data[i] );
++ writeString( _m.data[i] );
+ j += 4 + _m.data[i].size();
+ }
+- m_out->unlock();
+- m_out->messageSent();
+
+ return j;
+ }
+@@ -950,16 +638,13 @@
+
+ RemotePluginBase::message RemotePluginBase::receiveMessage()
+ {
+- m_in->waitForMessage();
+- m_in->lock();
+ message m;
+- m.id = m_in->readInt();
+- const int s = m_in->readInt();
++ m.id = readInt();
++ const int s = readInt();
+ for( int i = 0; i < s; ++i )
+ {
+- m.data.push_back( m_in->readString() );
++ m.data.push_back( readString() );
+ }
+- m_in->unlock();
+ return m;
+ }
+
+@@ -1005,8 +690,8 @@
+ #ifdef BUILD_REMOTE_PLUGIN_CLIENT
+
+
+-RemotePluginClient::RemotePluginClient( key_t _shm_in, key_t _shm_out ) :
+- RemotePluginBase( new shmFifo( _shm_in ), new shmFifo( _shm_out ) ),
++RemotePluginClient::RemotePluginClient( const char * socketPath ) :
++ RemotePluginBase(),
+ #ifdef USE_QT_SHMEM
+ m_shmObj(),
+ m_shmQtID( "/usr/bin/lmms" ),
+@@ -1062,6 +747,26 @@
+ }
+ }
+ #endif
++
++ struct sockaddr_un sa;
++ sa.sun_family = AF_LOCAL;
++
++ if ( strlen( socketPath ) >= sizeof sa.sun_path )
++ {
++ fprintf( stderr, "Socket path too long.\n" );
++ }
++ strcpy( sa.sun_path, socketPath );
++
++ m_socket = socket( PF_LOCAL, SOCK_STREAM, 0 );
++ if ( m_socket == -1 )
++ {
++ fprintf( stderr, "Could not connect to local server.\n" );
++ }
++ if ( ::connect( m_socket, (struct sockaddr *) &sa, sizeof sa ) == -1 )
++ {
++ fprintf( stderr, "Could not connect to local server.\n" );
++ }
++
+ // if attaching shared memory fails
+ sendMessage( IdSampleRateInformation );
+ sendMessage( IdBufferSizeInformation );
+@@ -1080,6 +785,11 @@
+ #ifndef USE_QT_SHMEM
+ shmdt( m_shm );
+ #endif
++
++ if ( close( m_socket ) == -1)
++ {
++ fprintf( stderr, "Error freeing resources.\n" );
++ }
+ }
+
+
+Index: lmms-1.1.3/plugins/vst_base/RemoteVstPlugin.cpp
+===================================================================
+--- lmms-1.1.3.orig/plugins/vst_base/RemoteVstPlugin.cpp 2016-04-09 00:44:21.000000000 +0200
++++ lmms-1.1.3/plugins/vst_base/RemoteVstPlugin.cpp 2016-04-14 21:09:56.000000000 +0200
+@@ -56,6 +56,7 @@
+
+ #endif
+
++#define USE_WS_PREFIX
+ #include <windows.h>
+
+ #ifdef LMMS_BUILD_WIN32
+@@ -121,7 +122,7 @@
+ class RemoteVstPlugin : public RemotePluginClient
+ {
+ public:
+- RemoteVstPlugin( key_t _shm_in, key_t _shm_out );
++ RemoteVstPlugin( const char * socketPath );
+ virtual ~RemoteVstPlugin();
+
+ virtual bool processMessage( const message & _m );
+@@ -332,8 +333,8 @@
+
+
+
+-RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) :
+- RemotePluginClient( _shm_in, _shm_out ),
++RemoteVstPlugin::RemoteVstPlugin( const char * socketPath ) :
++ RemotePluginClient( socketPath ),
+ m_shortName( "" ),
+ m_libInst( NULL ),
+ m_plugin( NULL ),
+@@ -1014,7 +1015,7 @@
+ if( len > 0 )
+ {
+ int fd = open( _file.c_str(), O_WRONLY | O_BINARY );
+- write( fd, chunk, len );
++ ::write( fd, chunk, len );
+ close( fd );
+ }
+ }
+@@ -1331,7 +1332,7 @@
+ }
+
+ const int fd = open( _file.c_str(), O_RDONLY | O_BINARY );
+- read( fd, chunk, _len );
++ ::read( fd, chunk, _len );
+ close( fd );
+ pluginDispatch( 24, 0, _len, chunk );
+
+@@ -1853,7 +1854,7 @@
+
+ int main( int _argc, char * * _argv )
+ {
+- if( _argc < 3 )
++ if( _argc < 2 )
+ {
+ fprintf( stderr, "not enough arguments\n" );
+ return -1;
+@@ -1879,7 +1880,7 @@
+
+ // constructor automatically will process messages until it receives
+ // a IdVstLoadPlugin message and processes it
+- __plugin = new RemoteVstPlugin( atoi( _argv[1] ), atoi( _argv[2] ) );
++ __plugin = new RemoteVstPlugin( _argv[1] );
+
+ if( __plugin->isInitialized() )
+ {
+Index: lmms-1.1.3/plugins/vst_base/VstPlugin.cpp
+===================================================================
+--- lmms-1.1.3.orig/plugins/vst_base/VstPlugin.cpp 2016-04-09 12:55:05.000000000 +0200
++++ lmms-1.1.3/plugins/vst_base/VstPlugin.cpp 2016-04-13 22:02:05.000000000 +0200
+@@ -78,9 +78,8 @@
+
+
+ VstPlugin::VstPlugin( const QString & _plugin ) :
+- QObject(),
+- JournallingObject(),
+ RemotePlugin(),
++ JournallingObject(),
+ m_plugin( _plugin ),
+ m_pluginWidget( NULL ),
+ m_pluginWindowID( 0 ),
+Index: lmms-1.1.3/plugins/vst_base/VstPlugin.h
+===================================================================
+--- lmms-1.1.3.orig/plugins/vst_base/VstPlugin.h 2016-04-10 18:53:28.000000000 +0200
++++ lmms-1.1.3/plugins/vst_base/VstPlugin.h 2016-04-10 19:03:28.000000000 +0200
+@@ -37,8 +37,7 @@
+ #include "communication.h"
+
+
+-class PLUGIN_EXPORT VstPlugin : public QObject, public JournallingObject,
+- public RemotePlugin
++class PLUGIN_EXPORT VstPlugin : public RemotePlugin, public JournallingObject
+ {
+ Q_OBJECT
+ public:
+Index: lmms-1.1.3/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp
+===================================================================
+--- lmms-1.1.3.orig/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp 2016-04-10 21:05:46.000000000 +0200
++++ lmms-1.1.3/plugins/zynaddsubfx/RemoteZynAddSubFx.cpp 2016-04-13 23:34:46.000000000 +0200
+@@ -44,8 +44,8 @@
+ class RemoteZynAddSubFx : public RemotePluginClient, public LocalZynAddSubFx
+ {
+ public:
+- RemoteZynAddSubFx( int _shm_in, int _shm_out ) :
+- RemotePluginClient( _shm_in, _shm_out ),
++ RemoteZynAddSubFx( const char * socketPath ) :
++ RemotePluginClient( socketPath ),
+ LocalZynAddSubFx(),
+ m_guiSleepTime( 100 ),
+ m_guiExit( false )
+@@ -261,7 +261,7 @@
+
+ int main( int _argc, char * * _argv )
+ {
+- if( _argc < 3 )
++ if( _argc < 2 )
+ {
+ fprintf( stderr, "not enough arguments\n" );
+ return -1;
+@@ -276,8 +276,7 @@
+ #endif
+
+
+- RemoteZynAddSubFx * remoteZASF =
+- new RemoteZynAddSubFx( atoi( _argv[1] ), atoi( _argv[2] ) );
++ RemoteZynAddSubFx * remoteZASF = new RemoteZynAddSubFx( _argv[1] );
+
+ remoteZASF->run();
+
+Index: lmms-1.1.3/plugins/zynaddsubfx/ZynAddSubFx.cpp
+===================================================================
+--- lmms-1.1.3.orig/plugins/zynaddsubfx/ZynAddSubFx.cpp 2016-04-10 19:05:45.000000000 +0200
++++ lmms-1.1.3/plugins/zynaddsubfx/ZynAddSubFx.cpp 2016-04-10 19:05:57.000000000 +0200
+@@ -74,7 +74,6 @@
+
+
+ ZynAddSubFxRemotePlugin::ZynAddSubFxRemotePlugin() :
+- QObject(),
+ RemotePlugin()
+ {
+ init( "RemoteZynAddSubFx", false );
+Index: lmms-1.1.3/plugins/zynaddsubfx/ZynAddSubFx.h
+===================================================================
+--- lmms-1.1.3.orig/plugins/zynaddsubfx/ZynAddSubFx.h 2016-04-10 19:05:10.000000000 +0200
++++ lmms-1.1.3/plugins/zynaddsubfx/ZynAddSubFx.h 2016-04-10 19:05:35.000000000 +0200
+@@ -44,7 +44,7 @@
+ class ledCheckBox;
+
+
+-class ZynAddSubFxRemotePlugin : public QObject, public RemotePlugin
++class ZynAddSubFxRemotePlugin : public RemotePlugin
+ {
+ Q_OBJECT
+ public:
+Index: lmms-1.1.3/src/core/RemotePlugin.cpp
+===================================================================
+--- lmms-1.1.3.orig/src/core/RemotePlugin.cpp 2016-04-09 19:17:15.000000000 +0200
++++ lmms-1.1.3/src/core/RemotePlugin.cpp 2016-04-14 21:11:40.000000000 +0200
+@@ -34,6 +34,9 @@
+ #include "config_mgr.h"
+
+ #include <QtCore/QDir>
++#include <QtCore/QUuid>
++#include <sys/socket.h>
++#include <sys/un.h>
+
+ #ifdef LMMS_HAVE_UNISTD_H
+ #include <unistd.h>
+@@ -69,7 +72,8 @@
+
+
+ RemotePlugin::RemotePlugin() :
+- RemotePluginBase( new shmFifo(), new shmFifo() ),
++ QObject(),
++ RemotePluginBase(),
+ m_failed( true ),
+ m_process(),
+ m_watcher( this ),
+@@ -85,6 +89,28 @@
+ m_inputCount( DEFAULT_CHANNELS ),
+ m_outputCount( DEFAULT_CHANNELS )
+ {
++ struct sockaddr_un sa;
++ sa.sun_family = AF_LOCAL;
++
++ m_socketFile = QDir::tempPath() + QDir::separator() +
++ QUuid::createUuid().toString();
++ const char * path = m_socketFile.toUtf8().data();
++ if ( strlen( path ) >= sizeof sa.sun_path )
++ {
++ qWarning( "Socket path too long." );
++ }
++ strcpy( sa.sun_path, path );
++ m_server = socket( PF_LOCAL, SOCK_STREAM | SOCK_NONBLOCK, 0 );
++ if ( m_server == -1 )
++ {
++ qWarning( "Unable to start the server." );
++ }
++ remove( path );
++ int ret = bind( m_server, (struct sockaddr *) &sa, sizeof sa );
++ if ( ret == -1 || listen( m_server, 1 ) == -1 )
++ {
++ qWarning( "Unable to start the server." );
++ }
+ }
+
+
+@@ -116,6 +142,12 @@
+ shmctl( m_shmID, IPC_RMID, NULL );
+ #endif
+ }
++
++ if ( close( m_server ) == -1)
++ {
++ qWarning( "Error freeing resources." );
++ }
++ remove( m_socketFile.toUtf8().data() );
+ }
+
+
+@@ -127,16 +159,13 @@
+ lock();
+ if( m_failed )
+ {
+- reset( new shmFifo(), new shmFifo() );
+ m_failed = false;
+ }
+ QString exec = configManager::inst()->pluginDir() +
+ QDir::separator() + pluginExecutable;
+
+ QStringList args;
+- // swap in and out for bidirectional communication
+- args << QString::number( out()->shmKey() );
+- args << QString::number( in()->shmKey() );
++ args << m_socketFile;
+ #ifndef DEBUG_REMOTE_PLUGIN
+ m_process.setProcessChannelMode( QProcess::ForwardedChannels );
+ m_process.setWorkingDirectory( QCoreApplication::applicationDirPath() );
+@@ -146,6 +175,28 @@
+ qDebug() << exec << args;
+ #endif
+
++ connect( &m_process, SIGNAL( finished( int, QProcess::ExitStatus ) ),
++ this, SLOT( processFinished( int, QProcess::ExitStatus ) ) );
++
++ struct pollfd pollin;
++ pollin.fd = m_server;
++ pollin.events = POLLIN;
++
++ if ( poll( &pollin, 1, -1 ) == -1 )
++ {
++ qWarning( "Unexpected poll error." );
++ }
++ if ( ! ( pollin.revents & POLLIN ) )
++ {
++ qWarning( "Unexpected poll error." );
++ }
++
++ m_socket = accept( m_server, NULL, NULL );
++ if ( m_socket == -1 )
++ {
++ qWarning( "Unexpected socket error." );
++ }
++
+ resizeSharedProcessingMemory();
+
+ if( waitForInitDoneMsg )
+@@ -337,6 +388,15 @@
+ }
+
+
++
++
++void RemotePlugin::processFinished( int exitCode,
++ QProcess::ExitStatus exitStatus )
++{
++ invalidate();
++}
++
++
+
+
+ bool RemotePlugin::processMessage( const message & _m )
+Index: lmms-1.1.3/src/core/main.cpp
+===================================================================
+--- lmms-1.1.3.orig/src/core/main.cpp 2016-04-13 20:33:13.000000000 +0200
++++ lmms-1.1.3/src/core/main.cpp 2016-04-13 20:43:35.000000000 +0200
+@@ -64,6 +64,8 @@
+ #include <unistd.h>
+ #endif
+
++#include <signal.h>
++
+ #include "config_mgr.h"
+ #include "embed.h"
+ #include "engine.h"
+@@ -408,6 +410,18 @@
+ #endif
+ #endif
+
++ struct sigaction sa;
++ sa.sa_handler = SIG_IGN;
++ sa.sa_flags = SA_SIGINFO;
++ if ( sigemptyset( &sa.sa_mask ) )
++ {
++ fprintf( stderr, "Signal initialization failed.\n" );
++ }
++ if ( sigaction( SIGPIPE, &sa, NULL ) )
++ {
++ fprintf( stderr, "Signal initialization failed.\n" );
++ }
++
+ configManager::inst()->loadConfigFile();
+
+ if( render_out.isEmpty() )
diff --git a/debian/patches/vst-no-wine.patch b/debian/patches/vst-no-wine.patch
new file mode 100644
index 0000000..fd5e84a
--- /dev/null
+++ b/debian/patches/vst-no-wine.patch
@@ -0,0 +1,54 @@
+Description: Compile VST plugins without Wine
+ This configuration is meant for non-i386 architectures to use the i386
+ RemoteVstPlugin.
+Author: Javier Serrano Polo <javier at jasp.net>
+
+Index: lmms-1.1.3/CMakeLists.txt
+===================================================================
+--- lmms-1.1.3.orig/CMakeLists.txt 2016-04-06 21:25:00.000000000 +0200
++++ lmms-1.1.3/CMakeLists.txt 2016-04-08 01:46:06.000000000 +0200
+@@ -45,6 +45,9 @@
+ OPTION(WANT_WINMM "Include WinMM MIDI support" OFF)
+
+
++SET(REMOTE_VST_PLUGIN_FILEPATH "RemoteVstPlugin" CACHE STRING "Relative file path to RemoteVstPlugin")
++
++
+ IF(LMMS_BUILD_APPLE)
+ SET(WANT_SF2 OFF)
+ SET(WANT_ALSA OFF)
+@@ -313,6 +316,9 @@
+ IF(WINE_FOUND)
+ SET(LMMS_SUPPORT_VST TRUE)
+ SET(STATUS_VST "OK")
++ ELSEIF(WANT_VST_NOWINE)
++ SET(LMMS_SUPPORT_VST TRUE)
++ SET(STATUS_VST "OK")
+ ELSE(WINE_FOUND)
+ SET(STATUS_VST "not found, please install (lib)wine-dev (or similiar) - 64 bit systems additionally need gcc-multilib and g++-multilib")
+ ENDIF(WINE_FOUND)
+Index: lmms-1.1.3/plugins/vst_base/CMakeLists.txt
+===================================================================
+--- lmms-1.1.3.orig/plugins/vst_base/CMakeLists.txt 2016-04-08 01:06:56.000000000 +0200
++++ lmms-1.1.3/plugins/vst_base/CMakeLists.txt 2016-04-08 01:27:46.000000000 +0200
+@@ -17,6 +17,7 @@
+ ENDIF(LMMS_BUILD_WIN64)
+ ENDIF(LMMS_BUILD_WIN32)
+
++ADD_DEFINITIONS(-DREMOTE_VST_PLUGIN_FILEPATH="${REMOTE_VST_PLUGIN_FILEPATH}")
+ BUILD_PLUGIN(vstbase vst_base.cpp VstPlugin.cpp VstPlugin.h communication.h MOCFILES VstPlugin.h)
+
+
+Index: lmms-1.1.3/plugins/vst_base/VstPlugin.cpp
+===================================================================
+--- lmms-1.1.3.orig/plugins/vst_base/VstPlugin.cpp 2016-04-08 00:50:15.000000000 +0200
++++ lmms-1.1.3/plugins/vst_base/VstPlugin.cpp 2016-04-08 00:51:17.000000000 +0200
+@@ -97,7 +97,7 @@
+ {
+ setSplittedChannels( true );
+
+- tryLoad( "RemoteVstPlugin" );
++ tryLoad( REMOTE_VST_PLUGIN_FILEPATH );
+ #ifdef LMMS_BUILD_WIN64
+ if( m_badDllFormat )
+ {
diff --git a/debian/patches/wine-runpath.patch b/debian/patches/wine-runpath.patch
new file mode 100644
index 0000000..3ba6574
--- /dev/null
+++ b/debian/patches/wine-runpath.patch
@@ -0,0 +1,18 @@
+Description: Define RUNPATH to find wine library
+ Debian does not ship the wine library in a directory expected by the dynamic
+ linker. WINE_CXX_FLAGS allows to set RUNPATH information.
+Author: Javier Serrano Polo <javier at jasp.net>
+
+Index: lmms-1.1.3/plugins/vst_base/CMakeLists.txt
+===================================================================
+--- lmms-1.1.3.orig/plugins/vst_base/CMakeLists.txt 2016-04-08 19:46:33.000000000 +0200
++++ lmms-1.1.3/plugins/vst_base/CMakeLists.txt 2016-04-08 20:27:37.000000000 +0200
+@@ -36,7 +36,7 @@
+ ADD_CUSTOM_COMMAND(
+ SOURCE "${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp"
+ COMMAND ${WINE_CXX}
+- ARGS "-I\"${CMAKE_BINARY_DIR}\"" "-I\"${CMAKE_SOURCE_DIR}/include\"" "-I\"${CMAKE_INSTALL_PREFIX}/include/wine/windows\"" "-I\"${CMAKE_INSTALL_PREFIX}/include\"" -I/usr/include/wine/windows "\"${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp\"" -ansi -mwindows -lpthread ${EXTRA_FLAGS} -o RemoteVstPlugin
++ ARGS "-I\"${CMAKE_BINARY_DIR}\"" "-I\"${CMAKE_SOURCE_DIR}/include\"" "-I\"${CMAKE_INSTALL_PREFIX}/include/wine/windows\"" "-I\"${CMAKE_INSTALL_PREFIX}/include\"" -I/usr/include/wine/windows "\"${CMAKE_CURRENT_SOURCE_DIR}/RemoteVstPlugin.cpp\"" -ansi -mwindows -lpthread ${EXTRA_FLAGS} ${WINE_CXX_FLAGS} -o RemoteVstPlugin
+ COMMAND find -name RemoteVstPlugin.exe -exec mv "'{}'" RemoteVstPlugin "';'"
+ TARGET vstbase
+ OUTPUTS RemoteVstPlugin
diff --git a/debian/rules b/debian/rules
index 9001a74..739d13b 100755
--- a/debian/rules
+++ b/debian/rules
@@ -4,13 +4,25 @@
DH_CMAKE_BUILD_DIR=obj -${DEB_BUILD_GNU_TYPE}
DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH)
+DEB_HOST_ARCH ?= $(shell dpkg-architecture -qDEB_HOST_ARCH)
DEB_HOST_ARCH_OS ?= $(shell dpkg-architecture -qDEB_HOST_ARCH_OS)
+# Pending: Do not build convenience copies of LADSPA plugins.
+#CMAKE_OPTS=-DWANT_CALF=0 -DWANT_CAPS=0 -DWANT_CMT=0 -DWANT_SWH=0 -DWANT_TAP=0
CMAKE_OPTS=
ifneq ($(DEB_HOST_ARCH_OS),linux)
CMAKE_OPTS+= -DWANT_ALSA=0
endif
+ifeq ($(DEB_HOST_ARCH),i386)
+WINE_PATH := /usr/lib/$(DEB_HOST_MULTIARCH)/wine
+export PATH := $(PATH):$(WINE_PATH)
+CMAKE_OPTS+= -DWINE_CXX_FLAGS=-Wl,--enable-new-dtags,-rpath=$(WINE_PATH)
+else
+CMAKE_OPTS+= -DWANT_VST_NOWINE=1 \
+ -DREMOTE_VST_PLUGIN_FILEPATH=../../i386-linux-gnu/lmms/RemoteVstPlugin
+endif
+
%:
dh $@ --buildsystem cmake
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-edu/pkg-team/lmms.git
More information about the debian-edu-commits
mailing list