diff --git a/ChangeLog b/ChangeLog index 2bb4bb63d..e3fecf130 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +2008-05-19 Tobias Doerffel + + * configure.in: + * plugins/vst_base/lvsl_client.cpp: + call waitpid(...) when closing plugin - fixes zombie processes + + * plugins/vst_effect/vst_effect_controls.h: + * plugins/vst_effect/vst_subplugin_features.cpp: + * plugins/vst_effect/vst_subplugin_features.h: + * plugins/vst_effect/vst_effect_control_dialog.cpp: + * plugins/vst_effect/Makefile.am: + * plugins/vst_effect/vst_effect.cpp: + * plugins/vst_effect/vst_effect_controls.cpp: + * plugins/vst_effect/vst_effect_control_dialog.h: + * plugins/vst_effect/vst_effect.h: + * plugins/vst_base/lvsl_client.h: + * plugins/vst_base/lvsl_client.cpp: + finally made VST-effect plugin work + + * src/core/track_container.cpp: + * src/core/main.cpp: + when rendering from command-line, only create a QCoreApplication - needs + further work + + * include/config_mgr.h: + * src/gui/widgets/effect_rack_view.cpp: + minor coding-style stuff + + * plugins/singerbot/singerbot.h: + * plugins/singerbot/singerbot.cpp: + integrated patches from William Steidtmann + which makes Singerbot at least compile - doesn't seem to work yet though + 2008-05-19 Paul Giblock * triple_oscillator.cpp: diff --git a/configure.in b/configure.in index ee714d34a..f616e5e6d 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.50) -AC_INIT(lmms, 0.4.0-svn20080515, lmms-devel/at/lists/dot/sf/dot/net) -AM_INIT_AUTOMAKE(lmms, 0.4.0-svn20080515) +AC_INIT(lmms, 0.4.0-svn20080519, lmms-devel/at/lists/dot/sf/dot/net) +AM_INIT_AUTOMAKE(lmms, 0.4.0-svn20080519) AM_CONFIG_HEADER(config.h) @@ -73,7 +73,7 @@ gw_CHECK_QT # checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS([stdint.h sys/times.h fcntl.h memory.h string.h sys/ioctl.h unistd.h stdlib.h pthread.h sys/ipc.h sys/shm.h sys/time.h sys/select.h sys/types.h stdarg.h signal.h sched.h ctype.h]) +AC_CHECK_HEADERS([stdint.h sys/times.h fcntl.h memory.h string.h sys/ioctl.h unistd.h stdlib.h pthread.h sys/ipc.h sys/shm.h sys/time.h sys/select.h sys/types.h sys/wait.h stdarg.h signal.h sched.h ctype.h]) # checks for typedefs, structures, and compiler characteristics. AC_C_CONST diff --git a/include/config_mgr.h b/include/config_mgr.h index dc73d553e..66915723f 100644 --- a/include/config_mgr.h +++ b/include/config_mgr.h @@ -201,15 +201,10 @@ private: void createWidgets( void ); - void FASTCALL addPage( QWidget * _w, const QString & _title ); + void addPage( QWidget * _w, const QString & _title ); void loadStyleSheet( void ); -/* static void processFilesRecursively( const QString & _src_dir, - const QString & _dst_dir, - void( * _proc_func )( const QString & _src, const QString & - _dst ) );*/ - const QString m_lmmsRcFile; QString m_workingDir; diff --git a/plugins/singerbot/singerbot.cpp b/plugins/singerbot/singerbot.cpp index e1ab469e7..5529e3346 100644 --- a/plugins/singerbot/singerbot.cpp +++ b/plugins/singerbot/singerbot.cpp @@ -2,7 +2,7 @@ * singerbot.cpp - a singing bot instrument plugin * * Copyright (c) 2007 Javier Serrano Polo - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -40,12 +40,12 @@ #include "instrument_track.h" #include "note_play_handle.h" #include "pattern.h" -#include "song_editor.h" +#include "song.h" #undef SINGLE_SOURCE_COMPILE #include "embed.cpp" - +#include "singerbot.moc" extern "C" @@ -66,7 +66,7 @@ plugin::descriptor singerbot_plugin_descriptor = // neccessary for getting instance out of shared lib -plugin * lmms_plugin_main( void * _data ) +plugin * lmms_plugin_main( model *, void * _data ) { return( new singerBot( static_cast( _data ) ) ); } @@ -79,31 +79,52 @@ plugin * lmms_plugin_main( void * _data ) singerBot::singerBot( instrumentTrack * _track ) : instrument( _track, &singerbot_plugin_descriptor ) { - synth_init(); + printf("singerBot constructor begin...\n"); fflush(stdout); - setAutoFillBackground( TRUE ); - QPalette pal; - pal.setBrush( backgroundRole(), - PLUGIN_NAME::getIconPixmap( "artwork" ) ); - setPalette( pal ); + // Create a unique suffix for the /dev/shm device file names + static int suffix_index = 0; + m_file_suffix = '.' + QString::number( getpid() ) + '.' + + QString::number( suffix_index++, 16 ); - QVBoxLayout * vbox = new QVBoxLayout( this ); - vbox->setMargin( 10 ); - vbox->setSpacing( 0 ); - vbox->addSpacing( 45 ); + // This creates a (file) device in /dev/shm called lmms_singerbot.[pid].[suffix_index] + int fd = shm_open( addSuffix( "/lmms_singerbot" ), + O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR ); + m_shm = new File( fd ); - m_lyrics = new QTextEdit( this ); - m_lyrics->setAutoFillBackground( TRUE ); - pal.setColor( m_lyrics->backgroundRole(), QColor( 64, 64, 64 ) ); - m_lyrics->setPalette( pal ); - m_lyrics->setText( "Hello, world!" ); + // This creates a (file) device in /dev/shm called sem.lmms_singerbot_s1.[pid].[suffix_index] + m_handle_semaphore = sem_open( addSuffix( "/lmms_singerbot_s1" ), + O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0 ); - connect( m_lyrics, SIGNAL( textChanged( void ) ), - this, SLOT( lyricsChanged( void ) ) ); + // This creates a (file) device in /dev/shm called sem.lmms_singerbot_s2.[pid].[suffix_index] + m_synth_semaphore = sem_open( addSuffix( "/lmms_singerbot_s2" ), + O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0 ); - vbox->addWidget( m_lyrics ); + pid_t cpid = fork(); + if( cpid == -1 ) + { + perror( "fork" ); + exit( EXIT_FAILURE ); + } + else if( cpid == 0 ) + { + sem_close( m_handle_semaphore ); + sem_close( m_synth_semaphore ); + + QString proxy_exec = configManager::inst()->pluginDir() + + QDir::separator() + + "singerbot_proxy"; + execlp( proxy_exec.toAscii().constData(), + proxy_exec.toAscii().constData(), + m_file_suffix.toAscii().constData(), + NULL ); + exit( EXIT_FAILURE ); + } + + sem_wait( m_handle_semaphore ); + + // Set a default text string, but do not emit the dataChanged signal + setPlainText( "Hello world", FALSE ); - updateWords(); } @@ -111,14 +132,39 @@ singerBot::singerBot( instrumentTrack * _track ) : singerBot::~singerBot() { - synth_destroy(); + m_shm->rewind(); + float stop = -1.0; + m_shm->write( &stop ); + + sem_post( m_synth_semaphore ); + wait( NULL ); + + sem_close( m_handle_semaphore ); + sem_close( m_synth_semaphore ); + sem_unlink( addSuffix( "/lmms_singerbot_s1" ) ); + sem_unlink( addSuffix( "/lmms_singerbot_s2" ) ); + + delete m_shm; + shm_unlink( addSuffix( "/lmms_singerbot" ) ); + } -void singerBot::playNote( notePlayHandle * _n, bool ) +pluginView * singerBot::instantiateView( QWidget * _parent ) { + return( new singerBotView( this, _parent ) ); +} + + + + +void singerBot::playNote( notePlayHandle * _n, bool, + sampleFrame * _working_buf ) +{ + printf("singerBot::playNote begin...\n"); fflush(stdout); + const fpp_t frames = _n->framesLeftForCurrentPeriod(); if( !_n->m_pluginData ) @@ -132,10 +178,10 @@ void singerBot::playNote( notePlayHandle * _n, bool ) return; } - sampleFrame * buf = new sampleFrame[frames]; - play( buf, hdata, frames ); - getInstrumentTrack()->processAudioBuffer( buf, frames, _n ); - delete[] buf; + play( _working_buf, hdata, frames ); + getInstrumentTrack()->processAudioBuffer( _working_buf, frames, _n ); + + printf("singerBot::playNote end...\n"); fflush(stdout); } @@ -156,8 +202,8 @@ void singerBot::saveSettings( QDomDocument & _doc, QDomElement & _this ) { QDomElement element = _doc.createElement( "lyrics" ); _this.appendChild( element ); - QDomCDATASection ds = _doc.createCDATASection( - m_lyrics->toPlainText() ); + + QDomCDATASection ds = _doc.createCDATASection( m_plain_text ); element.appendChild( ds ); } @@ -166,8 +212,14 @@ void singerBot::saveSettings( QDomDocument & _doc, QDomElement & _this ) void singerBot::loadSettings( const QDomElement & _this ) { - m_lyrics->setPlainText( - _this.namedItem( "lyrics" ).toElement().text() ); + QString saved_lyrics = _this.namedItem( "lyrics" ).toElement().text() ; + + // TODO: What if the load fails? + // if (!failed) + // { + setPlainText( saved_lyrics ); + // } + } @@ -181,19 +233,25 @@ QString singerBot::nodeName( void ) const -void singerBot::lyricsChanged( void ) +void singerBot::setPlainText( const QString & _plain_text, bool _emitDataChanged ) { + m_plain_text = _plain_text; + + if (_emitDataChanged) + { + // m_plain_text changed so send out notification + emit ( dataChanged() ); + } + m_words_dirty = TRUE; } -void singerBot::updateWords( void ) +const QString & singerBot::getPlainText() { - m_words = m_lyrics->toPlainText().simplified().toLower(). - split( ' ' ); - m_words_dirty = FALSE; + return m_plain_text; } @@ -201,6 +259,8 @@ void singerBot::updateWords( void ) void singerBot::createWave( notePlayHandle * _n ) { + printf("singerBot::createWave begin...\n"); fflush(stdout); + handle_data * hdata = new handle_data; _n->m_pluginData = hdata; hdata->wave = NULL; @@ -209,21 +269,29 @@ void singerBot::createWave( notePlayHandle * _n ) if( m_words_dirty ) { - updateWords(); + m_words = m_plain_text.simplified().toLower().split( ' ' ); + + m_words_dirty = FALSE; } + if( m_words.empty() ) { return; } + printf("_n->frequency = %f\n", _n->frequency() ); fflush(stdout); + hdata->frequency = _n->frequency(); hdata->duration = _n->length() > 0 ? _n->length() * 60.0f * BEATS_PER_TACT - / 64.0f / engine::getSongEditor()->getTempo() : + / 64.0f / engine::getSong()->getTempo() : 0; int word_index = _n->patternIndex() % m_words.size(); hdata->text = m_words[word_index].toAscii().constData(); + // Debugging only + showHandleData( hdata ); + synth_send( hdata ); synth_read( hdata ); @@ -242,6 +310,8 @@ void singerBot::createWave( notePlayHandle * _n ) hdata->resampling_data.end_of_input = 0; hdata->remaining_frames = hdata->num_samples; + + printf("singerBot::createWave end...\n"); fflush(stdout); } @@ -250,9 +320,11 @@ void singerBot::createWave( notePlayHandle * _n ) void singerBot::play( sampleFrame * _ab, handle_data * _hdata, const fpp_t _frames ) { + printf("singerBot::play begin...\n"); fflush(stdout); + const f_cnt_t offset = _hdata->num_samples - _hdata->remaining_frames; - const double ratio = engine::getMixer()->sampleRate() + const double ratio = engine::getMixer()->processingSampleRate() / (double)_hdata->sample_rate; const f_cnt_t margin = 2; @@ -312,68 +384,8 @@ void singerBot::play( sampleFrame * _ab, handle_data * _hdata, delete[] sample_fragment; delete[] data; -} - - - -void singerBot::synth_init( void ) -{ - static int suffix_index = 0; - m_file_suffix = '.' + QString::number( getpid() ) + '.' - + QString::number( suffix_index++, 16 ); - - int fd = shm_open( addSuffix( "/lmms_singerbot" ), - O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR ); - m_shm = new File( fd ); - m_handle_semaphore = sem_open( addSuffix( "/lmms_singerbot_s1" ), - O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0 ); - m_synth_semaphore = sem_open( addSuffix( "/lmms_singerbot_s2" ), - O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0 ); - - pid_t cpid = fork(); - if( cpid == -1 ) - { - perror( "fork" ); - exit( EXIT_FAILURE ); - } - else if( cpid == 0 ) - { - sem_close( m_handle_semaphore ); - sem_close( m_synth_semaphore ); - - QString proxy_exec = configManager::inst()->pluginDir() + - QDir::separator() + - "singerbot_proxy"; - execlp( proxy_exec.toAscii().constData(), - proxy_exec.toAscii().constData(), - m_file_suffix.toAscii().constData(), - NULL ); - exit( EXIT_FAILURE ); - } - - sem_wait( m_handle_semaphore ); -} - - - - -void singerBot::synth_destroy( void ) -{ - m_shm->rewind(); - float stop = -1.0; - m_shm->write( &stop ); - - sem_post( m_synth_semaphore ); - wait( NULL ); - - sem_close( m_handle_semaphore ); - sem_close( m_synth_semaphore ); - sem_unlink( addSuffix( "/lmms_singerbot_s1" ) ); - sem_unlink( addSuffix( "/lmms_singerbot_s2" ) ); - - delete m_shm; - shm_unlink( addSuffix( "/lmms_singerbot" ) ); + printf("singerBot::play end...\n"); fflush(stdout); } @@ -381,6 +393,8 @@ void singerBot::synth_destroy( void ) void singerBot::synth_send( handle_data * _hdata ) { + printf("singerBot::synth_send begin...\n"); fflush(stdout); + m_shm->rewind(); m_shm->write( &_hdata->frequency ); m_shm->write( &_hdata->duration ); @@ -389,6 +403,8 @@ void singerBot::synth_send( handle_data * _hdata ) m_shm->write( _hdata->text, len ); sem_post( m_synth_semaphore ); + + printf("singerBot::synth_send end...\n"); fflush(stdout); } @@ -396,6 +412,8 @@ void singerBot::synth_send( handle_data * _hdata ) void singerBot::synth_read( handle_data * _hdata ) { + printf("singerBot::synth_read begin...\n"); fflush(stdout); + sem_wait( m_handle_semaphore ); m_shm->rewind(); @@ -407,6 +425,8 @@ void singerBot::synth_read( handle_data * _hdata ) m_shm->read( &_hdata->sample_rate ); _hdata->wave = new short[_hdata->num_samples]; m_shm->read( _hdata->wave, _hdata->num_samples ); + + printf("singerBot::synth_read end...\n"); fflush(stdout); } @@ -419,5 +439,92 @@ const char * singerBot::addSuffix( const char * _s ) +// For debugging only +void singerBot::showHandleData( handle_data * _hdata ) +{ + printf("Show Handle Data:\n"); + printf("wave = %u\n", (unsigned int)_hdata->wave); + printf("num_samples = %d\n", _hdata->num_samples); + printf("sample_rate = %d\n", _hdata->sample_rate); + printf("remaining_frames = %d\n", _hdata->remaining_frames); + printf("frequency = %f\n", _hdata->frequency); + printf("duration = %f\n", _hdata->duration); + //const char * text; + //SRC_STATE * resampling_state; + //SRC_DATA resampling_data; -#include "singerbot.moc" + fflush(stdout); +} + + +// ******** The View ********* + +singerBotView::singerBotView( instrument * _instrument, + QWidget * _parent ) : + instrumentView( _instrument, _parent ) +{ + setAutoFillBackground( TRUE ); + QPalette pal; + pal.setBrush( backgroundRole(), + PLUGIN_NAME::getIconPixmap( "artwork" ) ); + setPalette( pal ); + + QVBoxLayout * vbox = new QVBoxLayout( this ); + vbox->setMargin( 10 ); + vbox->setSpacing( 0 ); + vbox->addSpacing( 45 ); + + m_lyrics = new QTextEdit( this ); + m_lyrics->setAutoFillBackground( TRUE ); + pal.setColor( m_lyrics->backgroundRole(), QColor( 64, 64, 64 ) ); + m_lyrics->setPalette( pal ); + + // Connect the QTextEdit textChanged signal to the viewTextChanged slot + connect( m_lyrics, SIGNAL( textChanged( void ) ), + this, SLOT( viewTextChanged( void ) ) ); + + // Need to set the view's text the same as the model, so just run the handler + // that would have run if we had gotten dataChanged() signal from the model + modelTextChanged(); + + vbox->addWidget( m_lyrics ); + + // Connect the model dataChanged event to the view's handler + // (see example from audio_file_processor.cpp line 585) + connect( castModel(), SIGNAL( dataChanged() ), + this, SLOT( modelTextChanged() ) ); + +} + + + + +// This slot is connected to the QTextEdit textChanged singal +void singerBotView::viewTextChanged( void ) +{ + QString modelText = castModel()->getPlainText(); + + // If the model text is already the same then stop updating + // (otherwise there would be a infinite loop of model -> view -> model -> etc + if (m_lyrics->toPlainText() != modelText) + { + // Call the model to set the new text that changed via UI + castModel()->setPlainText( m_lyrics->toPlainText() ); + } + +} + + + +void singerBotView::modelTextChanged( void ) +{ + // Set the view's text the same as the model + m_lyrics->setText( castModel()->getPlainText() ); +} + + + + +singerBotView::~singerBotView() +{ +} diff --git a/plugins/singerbot/singerbot.h b/plugins/singerbot/singerbot.h index 8f40cf05e..170889206 100644 --- a/plugins/singerbot/singerbot.h +++ b/plugins/singerbot/singerbot.h @@ -2,7 +2,7 @@ * singerbot.h - declaration of class singerBot, a singing bot instrument plugin * * Copyright (c) 2007 Javier Serrano Polo - * + * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * * This program is free software; you can redistribute it and/or @@ -39,36 +39,37 @@ #include #include "instrument.h" +#include "instrument_view.h" #include "mixer.h" class File; class QTextEdit; class sampleBuffer; - +class singerBotView; class singerBot : public instrument { - Q_OBJECT + Q_OBJECT public: singerBot( instrumentTrack * _track ); virtual ~singerBot(); - virtual void FASTCALL playNote( notePlayHandle * _n, - bool _try_parallelizing ); - virtual void FASTCALL deleteNotePluginData( notePlayHandle * _n ); + virtual void playNote( notePlayHandle * _n, bool _try_parallelizing, + sampleFrame * _working_buf ); + virtual void deleteNotePluginData( notePlayHandle * _n ); - virtual void FASTCALL saveSettings( QDomDocument & _doc, - QDomElement & _this ); - virtual void FASTCALL loadSettings( const QDomElement & _this ); + virtual void saveSettings( QDomDocument & _doc, + QDomElement & _parent ); + virtual void loadSettings( const QDomElement & _this ); virtual QString nodeName( void ) const; + virtual pluginView * instantiateView( QWidget * _parent ); -public slots: - void lyricsChanged( void ); - + void setPlainText( const QString & _plain_text, bool _emitDataChanged = TRUE ); + const QString & getPlainText(); private: typedef struct @@ -91,26 +92,43 @@ private: sem_t * m_handle_semaphore; sem_t * m_synth_semaphore; - QTextEdit * m_lyrics; + // m_plain_text is the model, and m_words is parsed list of the words in m_plain_text + QString m_plain_text; QStringList m_words; bool m_words_dirty; void createWave( notePlayHandle * _n ); void play( sampleFrame * _ab, handle_data * _hdata, const fpp_t _frames ); - void updateWords( void ); - - void synth_init( void ); - void synth_destroy( void ); void synth_send( handle_data * _hdata ); void synth_read( handle_data * _hdata ); const char * addSuffix( const char * _s ); + void showHandleData( handle_data * _hdata ); + + friend class singerBotView; } ; +class singerBotView : public instrumentView +{ + Q_OBJECT +public: + singerBotView( instrument * _instrument, QWidget * _parent ); + virtual ~singerBotView(); + +public slots: + void viewTextChanged( void ); + void modelTextChanged( void ); + +private: + QTextEdit * m_lyrics; + +} ; + + #endif diff --git a/plugins/vst_base/lvsl_client.cpp b/plugins/vst_base/lvsl_client.cpp index 3876aed05..f327d0d9e 100644 --- a/plugins/vst_base/lvsl_client.cpp +++ b/plugins/vst_base/lvsl_client.cpp @@ -63,6 +63,10 @@ #include #endif +#ifdef HAVE_SYS_WAIT_H +#include +#endif + #include "config_mgr.h" #include "engine.h" @@ -110,7 +114,7 @@ remoteVSTPlugin::remoteVSTPlugin( const QString & _plugin ) : "lvsl_server"; execlp( lvsl_server_exec.toAscii().constData(), lvsl_server_exec.toAscii().constData(), - "", NULL ); + NULL ); return; } m_serverInFD = m_pipes[1][0]; @@ -182,16 +186,21 @@ remoteVSTPlugin::~remoteVSTPlugin() break; } } - if( m_pluginWidget != NULL ) + if( m_pluginWidget != NULL && + m_pluginWidget->parentWidget() != NULL && + dynamic_cast( + m_pluginWidget->parentWidget() ) != NULL ) { - m_pluginWidget->parentWidget()->hide(); delete m_pluginWidget->parentWidget(); } // timeout? /* if( m_pluginPID != 0 ) {*/ kill( m_pluginPID, SIGTERM ); + kill( m_pluginPID, SIGKILL ); //} + // remove process from PCB + waitpid( m_pluginPID, NULL, 0 ); // close all sides of our pipes close( m_pipes[0][0] ); @@ -206,23 +215,30 @@ remoteVSTPlugin::~remoteVSTPlugin() -void remoteVSTPlugin::showEditor( void ) +QWidget * remoteVSTPlugin::showEditor( QWidget * _parent ) { if( m_pluginWidget != NULL ) { - m_pluginWidget->parentWidget()->show(); - return; + if( m_pluginWidget->parentWidget() ) + { + m_pluginWidget->parentWidget()->show(); + } + return( m_pluginWidget ); } if( m_pluginXID == 0 ) { - return; + return( NULL ); } - m_pluginWidget = new QWidget;//( engine::getMainWindow()->workspace() ); + m_pluginWidget = new QWidget( _parent ); m_pluginWidget->setFixedSize( m_pluginGeometry ); m_pluginWidget->setWindowTitle( name() ); - engine::getMainWindow()->workspace()->addSubWindow( m_pluginWidget )->setAttribute( Qt::WA_DeleteOnClose, FALSE ); + if( _parent == NULL ) + { + engine::getMainWindow()->workspace()->addSubWindow( m_pluginWidget ) + ->setAttribute( Qt::WA_DeleteOnClose, FALSE ); + } QX11EmbedContainer * xe = new QX11EmbedContainer( m_pluginWidget ); xe->embedClient( m_pluginXID ); @@ -234,6 +250,8 @@ void remoteVSTPlugin::showEditor( void ) lock(); writeValueS( VST_SHOW_EDITOR ); unlock(); + + return( m_pluginWidget ); } @@ -241,7 +259,7 @@ void remoteVSTPlugin::showEditor( void ) void remoteVSTPlugin::hideEditor( void ) { - if( m_pluginWidget != NULL ) + if( m_pluginWidget != NULL && m_pluginWidget->parentWidget() ) { m_pluginWidget->parentWidget()->hide(); } diff --git a/plugins/vst_base/lvsl_client.h b/plugins/vst_base/lvsl_client.h index 8d75d718e..7a6640b59 100644 --- a/plugins/vst_base/lvsl_client.h +++ b/plugins/vst_base/lvsl_client.h @@ -45,7 +45,7 @@ public: remoteVSTPlugin( const QString & _plugin ); virtual ~remoteVSTPlugin(); - void showEditor( void ); + QWidget * showEditor( QWidget * _parent = NULL ); void hideEditor( void ); inline const QString & name( void ) const @@ -71,13 +71,12 @@ public: // if _wait == TRUE, process() calls waitForProcessingFinished() // immediately, otherwise, _out_buf can be zero and you've to call // waitForProcessingFinished() on your own - bool FASTCALL process( const sampleFrame * _in_buf, - sampleFrame * _out_buf, - bool _wait ); - bool FASTCALL waitForProcessingFinished( sampleFrame * _out_buf ); + bool process( const sampleFrame * _in_buf, sampleFrame * _out_buf, + bool _wait ); + bool waitForProcessingFinished( sampleFrame * _out_buf ); - void FASTCALL enqueueMidiEvent( const midiEvent & _event, + void enqueueMidiEvent( const midiEvent & _event, const f_cnt_t _frames_ahead ); const QMap & parameterDump( void ); @@ -155,7 +154,7 @@ private: bool messagesLeft( void ) const; Sint16 processNextMessage( void ); - void FASTCALL setShmKeyAndSize( const Uint16 _key, const size_t _size ); + void setShmKeyAndSize( const Uint16 _key, const size_t _size ); bool m_failed; diff --git a/plugins/vst_effect/Makefile.am b/plugins/vst_effect/Makefile.am index a4569b622..aa69b3690 100644 --- a/plugins/vst_effect/Makefile.am +++ b/plugins/vst_effect/Makefile.am @@ -11,7 +11,7 @@ AM_CXXFLAGS := $(AM_CXXFLAGS) $(QT_CXXFLAGS) -DPLUGIN_NAME="vsteffect" $(MOC) -o $@ $< -#MOC_FILES = ./vst_control_dialog.moc +MOC_FILES = ./vst_effect_controls.moc BUILT_SOURCES = $(MOC_FILES) ./embedded_resources.h @@ -27,14 +27,16 @@ CLEANFILES = $(MOC_FILES) ./embedded_resources.h -pkglib_LTLIBRARIES= libvsteffect.la +pkglib_LTLIBRARIES = libvsteffect.la libvsteffect_la_SOURCES = vst_effect.cpp \ - vst_control_dialog.cpp \ + vst_effect_controls.cpp \ + vst_effect_control_dialog.cpp \ vst_subplugin_features.cpp \ vst_subplugin_features.h \ vst_effect.h \ - vst_control_dialog.h + vst_effect_controls.h \ + vst_effect_control_dialog.h libvsteffect_la_LIBADD = -L../vst_base -lvstbase $(libvsteffect_la_SOURCES): ./embedded_resources.h diff --git a/plugins/vst_effect/vst_effect.cpp b/plugins/vst_effect/vst_effect.cpp index 22b3f46d6..1dac04ed4 100644 --- a/plugins/vst_effect/vst_effect.cpp +++ b/plugins/vst_effect/vst_effect.cpp @@ -1,7 +1,7 @@ /* * vst_effect.cpp - class for handling VST effect plugins * - * Copyright (c) 2006-2007 Tobias Doerffel + * Copyright (c) 2006-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -27,7 +27,7 @@ #include -#include "song_editor.h" +#include "song.h" #include "text_float.h" #include "vst_subplugin_features.h" @@ -47,7 +47,7 @@ plugin::descriptor vsteffect_plugin_descriptor = "plugin for using arbitrary VST-effects " "inside LMMS." ), "Tobias Doerffel ", - 0x0100, + 0x0200, plugin::Effect, new QPixmap( PLUGIN_NAME::getIconPixmap( "logo" ) ), new vstSubPluginFeatures( plugin::Effect ) @@ -56,11 +56,13 @@ plugin::descriptor vsteffect_plugin_descriptor = } -vstEffect::vstEffect( const descriptor::subPluginFeatures::key * _key ) : - effect( &vsteffect_plugin_descriptor, _key ), +vstEffect::vstEffect( model * _parent, + const descriptor::subPluginFeatures::key * _key ) : + effect( &vsteffect_plugin_descriptor, _parent, _key ), m_plugin( NULL ), m_pluginMutex(), - m_key( *_key ) + m_key( *_key ), + m_vstControls( this ) { if( !m_key.user.toString().isEmpty() ) { @@ -79,8 +81,7 @@ vstEffect::~vstEffect() -bool FASTCALL vstEffect::processAudioBuffer( surroundSampleFrame * _buf, - const fpp_t _frames ) +bool vstEffect::processAudioBuffer( sampleFrame * _buf, const fpp_t _frames ) { if( !isEnabled() || !isRunning () ) { @@ -100,31 +101,19 @@ bool FASTCALL vstEffect::processAudioBuffer( surroundSampleFrame * _buf, m_pluginMutex.lock(); m_plugin->process( buf, buf, TRUE ); m_pluginMutex.unlock(); + double out_sum = 0.0; + const float d = getDryLevel(); + const float w = getWetLevel(); for( fpp_t f = 0; f < _frames; ++f ) { - for( ch_cnt_t ch = 0; ch < SURROUND_CHANNELS; ++ch ) - { - _buf[f][ch] = getDryLevel() * _buf[f][ch] + - getWetLevel() * - buf[f][ch%DEFAULT_CHANNELS]; - out_sum += _buf[f][ch]*_buf[f][ch]; - } + _buf[f][0] = d * _buf[f][0] + w * buf[f][0]; + _buf[f][1] = d * _buf[f][1] + w * buf[f][1]; + out_sum += _buf[f][0]*_buf[f][0] + _buf[f][1]*_buf[f][1]; } delete[] buf; - if( out_sum <= getGate() ) - { - incrementBufferCount(); - if( getBufferCount() > getTimeout() ) - { - stopRunning(); - resetBufferCount(); - } - } - else - { - resetBufferCount(); - } + + checkGate( out_sum / _frames ); } return( isRunning() ); } @@ -157,15 +146,10 @@ void vstEffect::openPlugin( const QString & _plugin ) QMessageBox::Ok ); return; } - m_plugin->showEditor(); - remoteVSTPlugin::connect( engine::getSongEditor(), + remoteVSTPlugin::connect( engine::getSong(), SIGNAL( tempoChanged( bpm_t ) ), m_plugin, SLOT( setTempo( bpm_t ) ) ); - m_plugin->setTempo( engine::getSongEditor()->getTempo() ); - if( m_plugin->pluginWidget() != NULL ) - { - m_plugin->hideEditor(); - } + m_plugin->setTempo( engine::getSong()->getTempo() ); m_pluginMutex.unlock(); delete tf; } @@ -182,13 +166,15 @@ void vstEffect::closePlugin( void ) + + extern "C" { // neccessary for getting instance out of shared lib -plugin * lmms_plugin_main( void * _data ) +plugin * lmms_plugin_main( model * _parent, void * _data ) { - return( new vstEffect( + return( new vstEffect( _parent, static_cast( _data ) ) ); } diff --git a/plugins/vst_effect/vst_effect.h b/plugins/vst_effect/vst_effect.h index 25ee7cef2..97181d943 100644 --- a/plugins/vst_effect/vst_effect.h +++ b/plugins/vst_effect/vst_effect.h @@ -1,7 +1,7 @@ /* * vst_effect.h - class for handling VST effect plugins * - * Copyright (c) 2006-2007 Tobias Doerffel + * Copyright (c) 2006-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -27,36 +27,35 @@ #define _VST_EFFECT_H #include -#include #include "effect.h" -#include "engine.h" -#include "main_window.h" #include "lvsl_client.h" -#include "vst_control_dialog.h" +#include "vst_effect_control_dialog.h" +#include "vst_effect_controls.h" + class vstEffect : public effect { public: - vstEffect( const descriptor::subPluginFeatures::key * _key ); + vstEffect( model * _parent, + const descriptor::subPluginFeatures::key * _key ); virtual ~vstEffect(); - virtual bool FASTCALL processAudioBuffer( surroundSampleFrame * _buf, + virtual bool processAudioBuffer( sampleFrame * _buf, const fpp_t _frames ); + virtual effectControls * getControls( void ) + { + return( &m_vstControls ); + } + + virtual inline QString publicName( void ) const { return( m_plugin->name() ); } - virtual inline effectControlDialog * createControlDialog( track * ) - { - return( new vstControlDialog( - engine::getMainWindow()->workspace(), - this ) ); - } - private: void openPlugin( const QString & _plugin ); @@ -66,9 +65,14 @@ private: QMutex m_pluginMutex; effectKey m_key; - friend class vstControlDialog; + vstEffectControls m_vstControls; + + + friend class vstEffectControls; + friend class vstEffectControlDialog; } ; + #endif diff --git a/plugins/vst_effect/vst_effect_control_dialog.cpp b/plugins/vst_effect/vst_effect_control_dialog.cpp index 9b686d5d0..2dde3cdaf 100644 --- a/plugins/vst_effect/vst_effect_control_dialog.cpp +++ b/plugins/vst_effect/vst_effect_control_dialog.cpp @@ -1,7 +1,7 @@ /* - * vst_control_dialog.cpp - dialog for displaying GUI of VST-effect-plugin + * vst_effect_control_dialog.cpp - dialog for displaying VST-effect GUI * - * Copyright (c) 2006-2007 Tobias Doerffel + * Copyright (c) 2006-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -22,66 +22,32 @@ * */ - -#include "vst_control_dialog.h" - #include +#include +#include "vst_effect_control_dialog.h" #include "vst_effect.h" +#include "main_window.h" -vstControlDialog::vstControlDialog( QWidget * _parent, - vstEffect * _eff ) : - effectControlDialog( _parent, _eff ), - m_effect( _eff ) + +vstEffectControlDialog::vstEffectControlDialog( vstEffectControls * _ctl ) : + effectControlDialog( _ctl ) { QVBoxLayout * l = new QVBoxLayout( this ); - QWidget * pw = m_effect->m_plugin->pluginWidget(); - if( pw ) + QWidget * w = _ctl->m_effect->m_plugin->showEditor( this ); + if( w ) { - pw->setParent( this ); - pw->show(); - l->addWidget( pw ); + w->show(); + l->addWidget( w ); } } -vstControlDialog::~vstControlDialog() +vstEffectControlDialog::~vstEffectControlDialog() { } - - -void FASTCALL vstControlDialog::loadSettings( const QDomElement & _this ) -{ - m_effect->closePlugin(); - m_effect->openPlugin( _this.attribute( "plugin" ) ); - m_effect->m_pluginMutex.lock(); - if( m_effect->m_plugin != NULL ) - { - m_effect->m_plugin->loadSettings( _this ); - } - m_effect->m_pluginMutex.unlock(); -} - - - - -void FASTCALL vstControlDialog::saveSettings( QDomDocument & _doc, - QDomElement & _this ) -{ - _this.setAttribute( "plugin", m_effect->m_key.user.toString() ); - m_effect->m_pluginMutex.lock(); - if( m_effect->m_plugin != NULL ) - { - m_effect->m_plugin->saveSettings( _doc, _this ); - } - m_effect->m_pluginMutex.unlock(); -} - - - - diff --git a/plugins/vst_effect/vst_effect_control_dialog.h b/plugins/vst_effect/vst_effect_control_dialog.h index 0eb37afcf..3302f838e 100644 --- a/plugins/vst_effect/vst_effect_control_dialog.h +++ b/plugins/vst_effect/vst_effect_control_dialog.h @@ -1,7 +1,7 @@ /* - * vst_control_dialog.h - dialog for displaying GUI of VST-effect-plugin + * vst_effect_control_dialog.h - dialog for displaying GUI of VST-effect-plugin * - * Copyright (c) 2006 Tobias Doerffel + * Copyright (c) 2006-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -22,37 +22,20 @@ * */ -#ifndef _VST_CONTROL_DIALOG_H -#define _VST_CONTROL_DIALOG_H +#ifndef _VST_EFFECT_CONTROL_DIALOG_H +#define _VST_EFFECT_CONTROL_DIALOG_H #include "effect_control_dialog.h" -class vstEffect; +class vstEffectControls; -class vstControlDialog : public effectControlDialog +class vstEffectControlDialog : public effectControlDialog { public: - vstControlDialog( QWidget * _parent, vstEffect * _eff ); - virtual ~vstControlDialog(); - -/* virtual void saveSettings( QDomDocument & _doc, - QDomElement & _parent ); - virtual void loadSettings( const QDomElement & _this ); - inline virtual QString nodeName( void ) const - { - return( "vstcontrols" ); - }*/ - - virtual ch_cnt_t getControlCount( void ) - { - return( 1 ); - } - - -private: - vstEffect * m_effect; + vstEffectControlDialog( vstEffectControls * _controls ); + virtual ~vstEffectControlDialog(); } ; diff --git a/plugins/vst_effect/vst_effect_controls.cpp b/plugins/vst_effect/vst_effect_controls.cpp new file mode 100755 index 000000000..7c3c8a8a9 --- /dev/null +++ b/plugins/vst_effect/vst_effect_controls.cpp @@ -0,0 +1,69 @@ +/* + * vst_effect_controls.cpp - controls for VST effect plugins + * + * Copyright (c) 2008 Tobias Doerffel + * + * 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 "vst_effect_controls.h" +#include "vst_effect.h" + + + +vstEffectControls::vstEffectControls( vstEffect * _eff ) : + effectControls( _eff ), + m_effect( _eff ) +{ +} + + + + +void vstEffectControls::loadSettings( const QDomElement & _this ) +{ + m_effect->closePlugin(); + m_effect->openPlugin( _this.attribute( "plugin" ) ); + m_effect->m_pluginMutex.lock(); + if( m_effect->m_plugin != NULL ) + { + m_effect->m_plugin->loadSettings( _this ); + } + m_effect->m_pluginMutex.unlock(); +} + + + + +void vstEffectControls::saveSettings( QDomDocument & _doc, QDomElement & _this ) +{ + _this.setAttribute( "plugin", m_effect->m_key.user.toString() ); + m_effect->m_pluginMutex.lock(); + if( m_effect->m_plugin != NULL ) + { + m_effect->m_plugin->saveSettings( _doc, _this ); + } + m_effect->m_pluginMutex.unlock(); +} + + + +#include "vst_effect_controls.moc" + diff --git a/plugins/vst_effect/vst_effect_controls.h b/plugins/vst_effect/vst_effect_controls.h new file mode 100755 index 000000000..a8a1d64dd --- /dev/null +++ b/plugins/vst_effect/vst_effect_controls.h @@ -0,0 +1,72 @@ +/* + * vst_effect_controls.h - controls for VST effect plugins + * + * Copyright (c) 2008 Tobias Doerffel + * + * 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 _VST_EFFECT_CONTROLS_H +#define _VST_EFFECT_CONTROLS_H + +#include "effect_controls.h" +#include "vst_effect_control_dialog.h" + + +class vstEffect; + + +class vstEffectControls : public effectControls +{ + Q_OBJECT +public: + vstEffectControls( vstEffect * _eff ); + virtual ~vstEffectControls() + { + } + + virtual void saveSettings( QDomDocument & _doc, QDomElement & _parent ); + virtual void loadSettings( const QDomElement & _this ); + inline virtual QString nodeName( void ) const + { + return( "vsteffectcontrols" ); + } + + virtual ch_cnt_t getControlCount( void ) + { + return( 1 ); + } + + virtual effectControlDialog * createView( void ) + { + return( new vstEffectControlDialog( this ) ); + } + + +private: + vstEffect * m_effect; + + + friend class vstEffectControlDialog; + +} ; + + +#endif diff --git a/plugins/vst_effect/vst_subplugin_features.cpp b/plugins/vst_effect/vst_subplugin_features.cpp index d815487ea..1f3dd05b9 100644 --- a/plugins/vst_effect/vst_subplugin_features.cpp +++ b/plugins/vst_effect/vst_subplugin_features.cpp @@ -3,7 +3,7 @@ * plugin::descriptor::subPluginFeatures for * hosting VST-plugins * - * Copyright (c) 2006-2007 Tobias Doerffel + * Copyright (c) 2006-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -33,7 +33,7 @@ #include "config_mgr.h" -vstSubPluginFeatures::vstSubPluginFeatures( plugin::pluginTypes _type ) : +vstSubPluginFeatures::vstSubPluginFeatures( plugin::PluginTypes _type ) : subPluginFeatures( _type ) { } diff --git a/plugins/vst_effect/vst_subplugin_features.h b/plugins/vst_effect/vst_subplugin_features.h index df2c6ac76..0a7dd3c98 100644 --- a/plugins/vst_effect/vst_subplugin_features.h +++ b/plugins/vst_effect/vst_subplugin_features.h @@ -3,7 +3,7 @@ * plugin::descriptor::subPluginFeatures for * hosting VST-plugins * - * Copyright (c) 2006-2007 Tobias Doerffel + * Copyright (c) 2006-2008 Tobias Doerffel * * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net * @@ -34,7 +34,7 @@ class vstSubPluginFeatures : public plugin::descriptor::subPluginFeatures { public: - vstSubPluginFeatures( plugin::pluginTypes _type ); + vstSubPluginFeatures( plugin::PluginTypes _type ); virtual void fillDescriptionWidget( QWidget * _parent, const key * _key ); diff --git a/src/core/main.cpp b/src/core/main.cpp index 8242de2a5..80c4c702d 100644 --- a/src/core/main.cpp +++ b/src/core/main.cpp @@ -65,7 +65,7 @@ inline void loadTranslation( const QString & _tname, t->load( name, _dir ); - qApp->installTranslator( t ); + QCoreApplication::instance()->installTranslator( t ); } @@ -82,7 +82,21 @@ int main( int argc, char * * argv ) } #endif - QApplication app( argc, argv ); + bool core_only = FALSE; + + for( int i = 1; i < argc; ++i ) + { + if( argc > i && ( QString( argv[i] ) == "--render" || + QString( argv[i] ) == "-r" ) ) + { + core_only = TRUE; + break; + } + } + + QCoreApplication * app = core_only ? + new QCoreApplication( argc, argv ) : + new QApplication( argc, argv ) ; QString file_to_load, render_out; @@ -294,7 +308,7 @@ int main( int argc, char * * argv ) QApplication::setStyle( new lmmsStyle() ); // set palette - QPalette pal = app.palette(); + QPalette pal = qApp->palette(); //pal.setColor( QPalette::Background, QColor( 72, 76 ,88 ) ); pal.setColor( QPalette::Background, QColor( 72, 76, 88 ) ); //pal.setColor( QPalette::Background, QColor( 127, 134 ,154 ) ); @@ -315,7 +329,7 @@ int main( int argc, char * * argv ) pal.setColor( QPalette::ButtonText, QColor( 255, 255, 255 ) ); pal.setColor( QPalette::Highlight, QColor( 224, 224, 224 ) ); pal.setColor( QPalette::HighlightedText, QColor( 0, 0, 0 ) ); - app.setPalette( pal ); + qApp->setPalette( pal ); // init splash screen @@ -383,7 +397,7 @@ int main( int argc, char * * argv ) r->startProcessing(); } - return( app.exec() ); + return( app->exec() ); } diff --git a/src/core/track_container.cpp b/src/core/track_container.cpp index 77d025578..399bce539 100644 --- a/src/core/track_container.cpp +++ b/src/core/track_container.cpp @@ -76,30 +76,36 @@ void trackContainer::loadSettings( const QDomElement & _this ) static QProgressDialog * pd = NULL; bool was_null = ( pd == NULL ); int start_val = 0; - if( pd == NULL ) + if( engine::hasGUI() ) { - pd = new QProgressDialog( tr( "Loading project..." ), + if( pd == NULL ) + { + pd = new QProgressDialog( tr( "Loading project..." ), tr( "Cancel" ), 0, _this.childNodes().count() ); - pd->setWindowModality( Qt::ApplicationModal ); - pd->setWindowTitle( tr( "Please wait..." ) ); - pd->show(); - } - else - { - start_val = pd->value(); - pd->setMaximum( pd->maximum() + _this.childNodes().count() ); + pd->setWindowModality( Qt::ApplicationModal ); + pd->setWindowTitle( tr( "Please wait..." ) ); + pd->show(); + } + else + { + start_val = pd->value(); + pd->setMaximum( pd->maximum() + _this.childNodes().count() ); + } } QDomNode node = _this.firstChild(); while( !node.isNull() ) { - pd->setValue( pd->value() + 1 ); - qApp->processEvents( QEventLoop::AllEvents, 100 ); - - if( pd->wasCanceled() ) + if( pd != NULL ) { - break; + pd->setValue( pd->value() + 1 ); + QCoreApplication::instance()->processEvents( + QEventLoop::AllEvents, 100 ); + if( pd->wasCanceled() ) + { + break; + } } if( node.isElement() && @@ -114,12 +120,14 @@ void trackContainer::loadSettings( const QDomElement & _this ) // mainWindow::restoreWidgetState( this, _this ); - pd->setValue( start_val + _this.childNodes().count() ); - - if( was_null ) + if( pd != NULL ) { - delete pd; - pd = NULL; + pd->setValue( start_val + _this.childNodes().count() ); + if( was_null ) + { + delete pd; + pd = NULL; + } } } diff --git a/src/gui/widgets/effect_rack_view.cpp b/src/gui/widgets/effect_rack_view.cpp index a3561dd93..1f081a87f 100644 --- a/src/gui/widgets/effect_rack_view.cpp +++ b/src/gui/widgets/effect_rack_view.cpp @@ -226,9 +226,8 @@ void effectRackView::addEffect( void ) update(); // Find the effectView, and show the controls - for( QVector::iterator vit = - m_effectViews.begin(); - vit != m_effectViews.end(); ++vit ) + for( QVector::iterator vit = m_effectViews.begin(); + vit != m_effectViews.end(); ++vit ) { if( ( *vit )->getEffect() == fx ) {