2
* remote_vst_plugin.cpp - LMMS VST Support Layer (RemotePlugin client)
4
* Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
6
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
8
* Code partly taken from (X)FST:
9
* Copyright (c) 2004 Paul Davis
10
* Copyright (c) 2004 Torben Hohn
11
* Copyright (c) 2002 Kjetil S. Matheussen
13
* This program is free software; you can redistribute it and/or
14
* modify it under the terms of the GNU General Public
15
* License as published by the Free Software Foundation; either
16
* version 2 of the License, or (at your option) any later version.
18
* This program is distributed in the hope that it will be useful,
19
* but WITHOUT ANY WARRANTY; without even the implied warranty of
20
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21
* General Public License for more details.
23
* You should have received a copy of the GNU General Public
24
* License along with this program (see COPYING); if not, write to the
25
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
26
* Boston, MA 02110-1301 USA.
31
#include "lmmsconfig.h"
33
#define BUILD_REMOTE_PLUGIN_CLIENT
35
#include "RemotePlugin.h"
37
#ifdef LMMS_HAVE_PTHREAD_H
41
#ifdef LMMS_HAVE_FCNTL_H
45
#ifdef LMMS_BUILD_LINUX
51
#ifdef LMMS_HAVE_SCHED_H
55
#include <wine/exception.h>
61
#ifdef LMMS_BUILD_WIN32
62
#ifdef LMMS_BUILD_WIN64
76
#if kVstVersion < 2400
80
#define VstInt32 long int
81
#define VstIntPtr long int
94
#include "lmms_basics.h"
96
#include "communication.h"
100
static VstHostLanguages hlang = LanguageEnglish;
103
class RemoteVstPlugin;
105
RemoteVstPlugin * __plugin = NULL;
107
DWORD __GuiThreadID = 0;
111
class RemoteVstPlugin : public RemotePluginClient
114
RemoteVstPlugin( key_t _shm_in, key_t _shm_out );
115
virtual ~RemoteVstPlugin();
117
virtual bool processMessage( const message & _m );
119
void init( const std::string & _plugin_file );
122
virtual void process( const sampleFrame * _in, sampleFrame * _out );
125
virtual void processMidiEvent( const midiEvent & _event,
126
const f_cnt_t _offset );
128
// set given sample-rate for plugin
129
virtual void updateSampleRate()
131
pluginDispatch( effSetSampleRate, 0, 0,
132
NULL, (float) sampleRate() );
135
// set given buffer-size for plugin
136
virtual void updateBufferSize()
138
pluginDispatch( effSetBlockSize, 0, bufferSize() );
142
inline bool isInitialized() const
144
return m_initialized;
149
void setBPM( const bpm_t _bpm )
154
// determine VST-version the plugin uses
155
inline int pluginVersion()
157
return pluginDispatch( effGetVendorVersion );
160
// determine name of plugin
161
const char * pluginName();
163
// determine vendor of plugin
164
const char * pluginVendorString();
166
// determine product-string of plugin
167
const char * pluginProductString();
169
// do a complete parameter-dump and post it
170
void getParameterDump();
172
// read parameter-dump and set it for plugin
173
void setParameterDump( const message & _m );
175
// post properties of specified parameter
176
void getParameterProperties( const int _idx );
178
// save settings chunk of plugin into file
179
void saveChunkToFile( const std::string & _file );
181
// restore settings chunk of plugin from file
182
void loadChunkFromFile( const std::string & _file, int _len );
185
virtual int inputCount() const
189
return m_plugin->numInputs;
195
virtual int outputCount() const
199
return m_plugin->numOutputs;
204
// has to be called as soon as input- or output-count changes
205
void updateInOutCount();
209
pthread_mutex_lock( &m_pluginLock );
214
pthread_mutex_unlock( &m_pluginLock );
217
static DWORD WINAPI processingThread( LPVOID _param );
218
static DWORD WINAPI guiEventLoop( LPVOID _param );
222
enum GuiThreadMessages
225
ProcessPluginMessage,
230
// callback used by plugin for being able to communicate with it's host
231
static VstIntPtr hostCallback( AEffect * _effect, VstInt32 _opcode,
232
VstInt32 _index, VstIntPtr _value,
233
void * _ptr, float _opt );
236
bool load( const std::string & _plugin_file );
238
// thread-safe dispatching of plugin
239
int pluginDispatch( int cmd, int param1 = 0, int param2 = 0,
240
void * p = NULL, float f = 0 )
246
ret = m_plugin->dispatcher( m_plugin, cmd, param1,
253
std::string m_shortName;
265
pthread_mutex_t m_pluginLock;
271
typedef std::vector<VstMidiEvent> VstMidiEventList;
272
VstMidiEventList m_midiEvents;
275
double m_currentSamplePos;
282
RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) :
283
RemotePluginClient( _shm_in, _shm_out ),
291
m_initialized( false ),
297
m_currentSamplePos( 0 )
299
pthread_mutex_init( &m_pluginLock, NULL );
303
// process until we have loaded the plugin
306
message m = receiveMessage();
308
if( m.id == IdVstLoadPlugin || m.id == IdQuit )
318
RemoteVstPlugin::~RemoteVstPlugin()
320
if( m_window != NULL )
322
pluginDispatch( effEditClose );
323
#ifdef LMMS_BUILD_LINUX
324
CloseWindow( m_window );
329
if( m_libInst != NULL )
331
FreeLibrary( m_libInst );
338
pthread_mutex_destroy( &m_pluginLock );
344
bool RemoteVstPlugin::processMessage( const message & _m )
348
case IdVstLoadPlugin:
349
init( _m.getString() );
352
#ifdef LMMS_BUILD_WIN32
353
case IdVstPluginWindowInformation:
355
HWND top = FindWindowEx( NULL, NULL, NULL,
356
_m.getString().c_str() );
357
m_window = FindWindowEx( top, NULL, NULL, NULL );
363
setBPM( _m.getInt() );
366
case IdVstSetLanguage:
367
hlang = static_cast<VstHostLanguages>( _m.getInt() );
370
case IdVstGetParameterDump:
374
case IdVstSetParameterDump:
375
setParameterDump( _m );
378
case IdVstGetParameterProperties:
379
getParameterProperties( _m.getInt() );
382
case IdSaveSettingsToFile:
383
saveChunkToFile( _m.getString() );
384
sendMessage( IdSaveSettingsToFile );
387
case IdLoadSettingsFromFile:
388
loadChunkFromFile( _m.getString( 0 ), _m.getInt( 1 ) );
389
sendMessage( IdLoadSettingsFromFile );
393
return RemotePluginClient::processMessage( _m );
401
void RemoteVstPlugin::init( const std::string & _plugin_file )
403
if( load( _plugin_file ) == false )
405
sendMessage( IdVstFailedLoadingPlugin );
411
/* set program to zero */
412
/* i comment this out because it breaks dfx Geometer
413
* looks like we cant set programs for it
415
pluginDispatch( effSetProgram, 0, 0 ); */
416
// request rate and blocksize
418
pluginDispatch( effMainsChanged, 0, 1 );
420
debugMessage( "creating editor\n" );
422
debugMessage( "editor successfully created\n" );
425
// now post some information about our plugin
426
sendMessage( message( IdVstPluginWindowID ).addInt( m_windowID ) );
428
sendMessage( message( IdVstPluginEditorGeometry ).
429
addInt( m_windowWidth ).
430
addInt( m_windowHeight ) );
432
sendMessage( message( IdVstPluginName ).addString( pluginName() ) );
433
sendMessage( message( IdVstPluginVersion ).addInt( pluginVersion() ) );
434
sendMessage( message( IdVstPluginVendorString ).
435
addString( pluginVendorString() ) );
436
sendMessage( message( IdVstPluginProductString ).
437
addString( pluginProductString() ) );
438
sendMessage( message( IdVstParameterCount ).
439
addInt( m_plugin->numParams ) );
441
sendMessage( IdInitDone );
443
m_initialized = true;
449
void RemoteVstPlugin::initEditor()
451
if( !( m_plugin->flags & effFlagsHasEditor ) )
457
HMODULE hInst = GetModuleHandle( NULL );
460
debugMessage( "initEditor(): can't get module handle\n" );
466
wc.style = CS_HREDRAW | CS_VREDRAW;
467
wc.lpfnWndProc = DefWindowProc;
470
wc.hInstance = hInst;
471
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
472
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
473
wc.hbrBackground = (HBRUSH) GetStockObject( BLACK_BRUSH );
474
wc.lpszMenuName = NULL;
475
wc.lpszClassName = "LVSL";
477
if( !RegisterClass( &wc ) )
482
#ifdef LMMS_BUILD_LINUX
483
m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
484
( WS_OVERLAPPEDWINDOW | WS_THICKFRAME ) &
486
0, 0, 10, 10, NULL, NULL, hInst, NULL );
489
m_windowID = 1; // arbitrary value on win32 to signal
490
// vstPlugin-class that we have an editor
492
m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
493
WS_CHILD, 0, 0, 10, 10,
494
m_window, NULL, hInst, NULL );
496
if( m_window == NULL )
498
debugMessage( "initEditor(): cannot create editor window\n" );
503
pluginDispatch( effEditOpen, 0, 0, m_window );
506
pluginDispatch( effEditGetRect, 0, 0, &er );
508
m_windowWidth = er->right - er->left;
509
m_windowHeight = er->bottom - er->top;
511
SetWindowPos( m_window, 0, 0, 0, m_windowWidth + 8,
512
m_windowHeight + 26, SWP_NOACTIVATE |
513
SWP_NOMOVE | SWP_NOZORDER );
514
pluginDispatch( effEditTop );
516
ShowWindow( m_window, SW_SHOWNORMAL );
517
UpdateWindow( m_window );
519
#ifdef LMMS_BUILD_LINUX
520
m_windowID = (Sint32) GetProp( m_window, "__wine_x11_whole_window" );
527
bool RemoteVstPlugin::load( const std::string & _plugin_file )
529
if( ( m_libInst = LoadLibrary( _plugin_file.c_str() ) ) == NULL )
534
char * tmp = strdup( _plugin_file.c_str() );
535
m_shortName = basename( tmp );
538
typedef AEffect * ( __stdcall * mainEntryPointer )
539
( audioMasterCallback );
540
mainEntryPointer mainEntry = (mainEntryPointer)
541
GetProcAddress( m_libInst, "VSTPluginMain" );
542
if( mainEntry == NULL )
544
mainEntry = (mainEntryPointer)
545
GetProcAddress( m_libInst, "VstPluginMain" );
547
if( mainEntry == NULL )
549
mainEntry = (mainEntryPointer)
550
GetProcAddress( m_libInst, "main" );
552
if( mainEntry == NULL )
554
debugMessage( "could not find entry point\n" );
558
m_plugin = mainEntry( hostCallback );
559
if( m_plugin == NULL )
561
debugMessage( "mainEntry prodecure returned NULL\n" );
565
m_plugin->user = this;
567
if( m_plugin->magic != kEffectMagic )
570
sprintf( buf, "%s is not a VST plugin\n",
571
_plugin_file.c_str() );
578
sprintf( id, "%c%c%c%c", ((char *)&m_plugin->uniqueID)[3],
579
((char *)&m_plugin->uniqueID)[2],
580
((char *)&m_plugin->uniqueID)[1],
581
((char *)&m_plugin->uniqueID)[0] );
583
sendMessage( message( IdVstPluginUniqueID ).addString( id ) );
585
pluginDispatch( effOpen );
593
void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out )
595
// first we gonna post all MIDI-events we enqueued so far
596
if( m_midiEvents.size() )
598
// since MIDI-events are not received immediately, we
599
// have to have them stored somewhere even after
600
// dispatcher-call, so we create static copies of the
601
// data and post them
602
#define MIDI_EVENT_BUFFER_COUNT 1024
603
static char event_buf[sizeof( VstMidiEvent * ) *
604
MIDI_EVENT_BUFFER_COUNT +
605
sizeof( VstEvents )];
606
static VstMidiEvent vme[MIDI_EVENT_BUFFER_COUNT];
607
VstEvents * events = (VstEvents *) event_buf;
608
events->reserved = 0;
609
events->numEvents = m_midiEvents.size();
611
for( VstMidiEventList::iterator it = m_midiEvents.begin();
612
it != m_midiEvents.end(); ++it, ++idx )
614
memcpy( &vme[idx], &*it, sizeof( VstMidiEvent ) );
615
events->events[idx] = (VstEvent *) &vme[idx];
618
m_midiEvents.clear();
619
pluginDispatch( effProcessEvents, 0, 0, events );
622
// now we're ready to fetch sound from VST-plugin
624
for( int i = 0; i < inputCount(); ++i )
626
m_inputs[i] = &((float *) _in)[i * bufferSize()];
629
for( int i = 0; i < outputCount(); ++i )
631
m_outputs[i] = &((float *) _out)[i * bufferSize()];
632
memset( m_outputs[i], 0, bufferSize() * sizeof( float ) );
636
if( m_plugin->flags & effFlagsCanReplacing )
639
m_plugin->processReplacing( m_plugin, m_inputs, m_outputs,
645
m_plugin->process( m_plugin, m_inputs, m_outputs,
650
m_currentSamplePos += bufferSize();
657
void RemoteVstPlugin::processMidiEvent( const midiEvent & _event,
658
const f_cnt_t _offset )
662
event.type = kVstMidiType;
664
event.deltaFrames = _offset;
667
event.noteLength = 0;
668
event.noteOffset = 0;
669
event.noteOffVelocity = 0;
672
event.midiData[0] = _event.m_type + _event.m_channel;
673
switch( _event.m_type )
676
event.midiData[1] = _event.m_data.m_param[0] & 0x7f;
677
event.midiData[2] = _event.m_data.m_param[0] >> 7;
679
// TODO: handle more special cases
681
event.midiData[1] = _event.key();
682
event.midiData[2] = _event.velocity();
685
event.midiData[3] = 0;
686
m_midiEvents.push_back( event );
692
const char * RemoteVstPlugin::pluginName()
696
pluginDispatch( effGetEffectName, 0, 0, buf );
704
const char * RemoteVstPlugin::pluginVendorString()
708
pluginDispatch( effGetVendorString, 0, 0, buf );
716
const char * RemoteVstPlugin::pluginProductString()
720
pluginDispatch( effGetProductString, 0, 0, buf );
728
void RemoteVstPlugin::getParameterDump()
730
VstParameterProperties vst_props;
731
message m( IdVstParameterDump );
732
m.addInt( m_plugin->numParams );
733
for( int i = 0; i < m_plugin->numParams; ++i )
735
pluginDispatch( effGetParameterProperties, i, 0, &vst_props );
737
m.addString( vst_props.shortLabel );
738
m.addFloat( m_plugin->getParameter( m_plugin, i ) );
746
void RemoteVstPlugin::setParameterDump( const message & _m )
748
const int n = _m.getInt( 0 );
749
const int params = ( n > m_plugin->numParams ) ?
750
m_plugin->numParams : n;
752
for( int i = 0; i < params; ++i )
754
VstParameterDumpItem item;
755
item.index = _m.getInt( ++p );
756
item.shortLabel = _m.getString( ++p );
757
item.value = _m.getFloat( ++p );
758
m_plugin->setParameter( m_plugin, item.index, item.value );
765
void RemoteVstPlugin::getParameterProperties( const int _idx )
767
VstParameterProperties p;
768
pluginDispatch( effGetParameterProperties, _idx, 0, &p );
769
message m( IdVstParameterProperties );
770
m.addString( p.label );
771
m.addString( p.shortLabel );
779
m.addFloat( p.minInteger );
780
m.addFloat( p.maxInteger );
781
m.addFloat( ( p.flags & kVstParameterUsesFloatStep ) ?
782
p.stepFloat : p.stepInteger );
796
void RemoteVstPlugin::saveChunkToFile( const std::string & _file )
798
if( m_plugin->flags & 32 )
801
const int len = pluginDispatch( 23, 0, 0, &chunk );
804
int fd = open( _file.c_str(), O_WRONLY | O_BINARY );
805
write( fd, chunk, len );
814
void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len )
819
// various plugins need this in order to not crash when setting
820
// chunk (also we let the plugin allocate "safe" memory this way)
821
const int actualLen = pluginDispatch( 23, 0, 0, &chunk );
823
// allocated buffer big enough?
824
if( _len > actualLen )
826
// no, then manually allocate a buffer
827
buf = new char[_len];
831
const int fd = open( _file.c_str(), O_RDONLY | O_BINARY );
832
read( fd, chunk, _len );
834
pluginDispatch( 24, 0, _len, chunk );
842
void RemoteVstPlugin::updateInOutCount()
850
setInputCount( inputCount() );
851
setOutputCount( outputCount() );
854
sprintf( buf, "inputs: %d output: %d\n", inputCount(), outputCount() );
857
if( inputCount() > 0 )
859
m_inputs = new float * [inputCount()];
862
if( outputCount() > 0 )
864
m_outputs = new float * [outputCount()];
870
//#define DEBUG_CALLBACKS
871
#ifdef DEBUG_CALLBACKS
872
#define SHOW_CALLBACK __plugin->debugMessage
874
#define SHOW_CALLBACK(...)
879
* - complete audioMasterGetTime-handling (bars etc.)
880
* - implement audioMasterProcessEvents
881
* - audioMasterGetVendorVersion: return LMMS-version (config.h!)
882
* - audioMasterGetDirectory: return either VST-plugin-dir or LMMS-workingdir
883
* - audioMasterOpenFileSelector: show QFileDialog?
885
VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
886
VstInt32 _index, VstIntPtr _value,
887
void * _ptr, float _opt )
889
static VstTimeInfo _timeInfo;
890
#ifdef DEBUG_CALLBACKS
892
sprintf( buf, "host-callback, opcode = %d\n", (int) _opcode );
893
SHOW_CALLBACK( buf );
896
// workaround for early callbacks by some plugins
897
if( __plugin && __plugin->m_plugin == NULL )
899
__plugin->m_plugin = _effect;
904
case audioMasterAutomate:
905
SHOW_CALLBACK( "amc: audioMasterAutomate\n" );
906
// index, value, returns 0
907
_effect->setParameter( _effect, _index, _opt );
910
case audioMasterVersion:
911
SHOW_CALLBACK( "amc: audioMasterVersion\n" );
914
case audioMasterCurrentId:
915
SHOW_CALLBACK( "amc: audioMasterCurrentId\n" );
916
// returns the unique id of a plug that's currently
920
case audioMasterIdle:
921
SHOW_CALLBACK ("amc: audioMasterIdle\n" );
922
// call application idle routine (this will
923
// call effEditIdle for all open editors too)
924
PostThreadMessage( __GuiThreadID,
925
WM_USER, GiveIdle, 0 );
928
case audioMasterPinConnected:
929
SHOW_CALLBACK( "amc: audioMasterPinConnected\n" );
930
// inquire if an input or output is beeing connected;
931
// index enumerates input or output counting from zero:
932
// value is 0 for input and != 0 otherwise. note: the
933
// return value is 0 for <true> such that older versions
934
// will always return true.
937
case audioMasterGetTime:
938
SHOW_CALLBACK( "amc: audioMasterGetTime\n" );
939
// returns const VstTimeInfo* (or 0 if not supported)
940
// <value> should contain a mask indicating which
941
// fields are required (see valid masks above), as some
942
// items may require extensive conversions
944
memset( &_timeInfo, 0, sizeof( _timeInfo ) );
946
_timeInfo.samplePos = __plugin->m_currentSamplePos;
947
_timeInfo.sampleRate = __plugin->sampleRate();
949
_timeInfo.tempo = __plugin->m_bpm;
950
_timeInfo.timeSigNumerator = 4;
951
_timeInfo.timeSigDenominator = 4;
952
_timeInfo.flags |= (/* kVstBarsValid|*/kVstTempoValid );
953
_timeInfo.flags |= kVstTransportPlaying;
954
#ifdef LMMS_BUILD_WIN64
955
return (long long) &_timeInfo;
957
return (long) &_timeInfo;
960
case audioMasterProcessEvents:
961
SHOW_CALLBACK( "amc: audioMasterProcessEvents\n" );
962
// VstEvents* in <ptr>
965
case audioMasterIOChanged:
966
__plugin->updateInOutCount();
967
SHOW_CALLBACK( "amc: audioMasterIOChanged\n" );
968
// numInputs and/or numOutputs has changed
972
case audioMasterWantMidi:
973
SHOW_CALLBACK( "amc: audioMasterWantMidi\n" );
974
// <value> is a filter which is currently ignored
977
case audioMasterSetTime:
978
SHOW_CALLBACK( "amc: audioMasterSetTime\n" );
979
// VstTimenfo* in <ptr>, filter in <value>, not
983
case audioMasterTempoAt:
984
SHOW_CALLBACK( "amc: audioMasterTempoAt\n" );
985
return __plugin->m_bpm * 10000;
987
case audioMasterGetNumAutomatableParameters:
988
SHOW_CALLBACK( "amc: audioMasterGetNumAutomatable"
992
case audioMasterGetParameterQuantization:
993
SHOW_CALLBACK( "amc: audioMasterGetParameter\n"
995
// returns the integer value for +1.0 representation,
996
// or 1 if full single float precision is maintained
997
// in automation. parameter index in <value> (-1: all,
1001
case audioMasterNeedIdle:
1002
SHOW_CALLBACK( "amc: audioMasterNeedIdle\n" );
1003
// plug needs idle calls (outside its editor window)
1006
case audioMasterGetPreviousPlug:
1007
SHOW_CALLBACK( "amc: audioMasterGetPreviousPlug\n" );
1008
// input pin in <value> (-1: first to come), returns
1012
case audioMasterGetNextPlug:
1013
SHOW_CALLBACK( "amc: audioMasterGetNextPlug\n" );
1014
// output pin in <value> (-1: first to come), returns
1018
case audioMasterWillReplaceOrAccumulate:
1019
SHOW_CALLBACK( "amc: audioMasterWillReplaceOr"
1021
// returns: 0: not supported, 1: replace, 2: accumulate
1024
case audioMasterGetSpeakerArrangement:
1025
SHOW_CALLBACK( "amc: audioMasterGetSpeaker"
1027
// (long)input in <value>, output in <ptr>
1030
case audioMasterSetOutputSampleRate:
1031
SHOW_CALLBACK( "amc: audioMasterSetOutputSample"
1033
// for variable i/o, sample rate in <opt>
1036
case audioMasterSetIcon:
1037
SHOW_CALLBACK( "amc: audioMasterSetIcon\n" );
1039
// void* in <ptr>, format not defined yet
1042
case audioMasterOpenWindow:
1043
SHOW_CALLBACK( "amc: audioMasterOpenWindow\n" );
1045
// returns platform specific ptr
1048
case audioMasterCloseWindow:
1049
SHOW_CALLBACK( "amc: audioMasterCloseWindow\n" );
1051
// close window, platform specific handle in <ptr>
1055
case audioMasterSizeWindow:
1056
SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" );
1057
if( __plugin->m_window == 0 )
1061
__plugin->m_windowWidth = _index;
1062
__plugin->m_windowHeight = _value;
1063
SetWindowPos( __plugin->m_window, 0, 0, 0,
1064
_index + 8, _value + 26,
1065
SWP_NOACTIVATE | SWP_NOMOVE |
1066
SWP_NOOWNERZORDER | SWP_NOZORDER );
1067
__plugin->sendMessage(
1068
message( IdVstPluginEditorGeometry ).
1069
addInt( __plugin->m_windowWidth ).
1070
addInt( __plugin->m_windowHeight ) );
1073
case audioMasterGetSampleRate:
1074
SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" );
1075
return __plugin->sampleRate();
1077
case audioMasterGetBlockSize:
1078
SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" );
1080
return __plugin->bufferSize();
1082
case audioMasterGetInputLatency:
1083
SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" );
1084
return __plugin->bufferSize();
1086
case audioMasterGetOutputLatency:
1087
SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" );
1088
return __plugin->bufferSize();
1090
case audioMasterGetCurrentProcessLevel:
1091
SHOW_CALLBACK( "amc: audioMasterGetCurrentProcess"
1093
// returns: 0: not supported,
1094
// 1: currently in user thread (gui)
1095
// 2: currently in audio thread (where process is
1097
// 3: currently in 'sequencer' thread (midi, timer etc)
1098
// 4: currently offline processing and thus in user
1100
// other: not defined, but probably pre-empting user
1104
case audioMasterGetAutomationState:
1105
SHOW_CALLBACK( "amc: audioMasterGetAutomationState\n" );
1106
// returns 0: not supported, 1: off, 2:read, 3:write,
1107
// 4:read/write offline
1110
case audioMasterOfflineStart:
1111
SHOW_CALLBACK( "amc: audioMasterOfflineStart\n" );
1114
case audioMasterOfflineRead:
1115
SHOW_CALLBACK( "amc: audioMasterOfflineRead\n" );
1116
// ptr points to offline structure, see below.
1117
// return 0: error, 1 ok
1120
case audioMasterOfflineWrite:
1121
SHOW_CALLBACK( "amc: audioMasterOfflineWrite\n" );
1125
case audioMasterOfflineGetCurrentPass:
1126
SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrent"
1130
case audioMasterOfflineGetCurrentMetaPass:
1131
SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrentMeta"
1135
case audioMasterGetVendorString:
1136
SHOW_CALLBACK( "amc: audioMasterGetVendorString\n" );
1137
// fills <ptr> with a string identifying the vendor
1139
strcpy( (char *) _ptr, "Tobias Doerffel" );
1142
case audioMasterGetProductString:
1143
SHOW_CALLBACK( "amc: audioMasterGetProductString\n" );
1144
// fills <ptr> with a string with product name
1146
strcpy( (char *) _ptr,
1147
"LMMS VST Support Layer (LVSL)" );
1150
case audioMasterGetVendorVersion:
1151
SHOW_CALLBACK( "amc: audioMasterGetVendorVersion\n" );
1152
// returns vendor-specific version
1155
case audioMasterVendorSpecific:
1156
SHOW_CALLBACK( "amc: audioMasterVendorSpecific\n" );
1157
// no definition, vendor specific handling
1160
case audioMasterCanDo:
1161
SHOW_CALLBACK( "amc: audioMasterCanDo\n" );
1162
return !strcmp( (char *) _ptr, "sendVstEvents" ) ||
1163
!strcmp( (char *) _ptr, "sendVstMidiEvent" ) ||
1164
!strcmp( (char *) _ptr, "sendVstTimeInfo" ) ||
1165
!strcmp( (char *) _ptr, "sizeWindow" ) ||
1166
!strcmp( (char *) _ptr, "supplyIdle" );
1168
case audioMasterGetLanguage:
1169
SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" );
1172
case audioMasterGetDirectory:
1173
SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" );
1174
// get plug directory, FSSpec on MAC, else char*
1177
case audioMasterUpdateDisplay:
1178
SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" );
1179
// something has changed, update 'multi-fx' display
1180
PostThreadMessage( __GuiThreadID,
1181
WM_USER, GiveIdle, 0 );
1185
case audioMasterBeginEdit:
1186
SHOW_CALLBACK( "amc: audioMasterBeginEdit\n" );
1187
// begin of automation session (when mouse down),
1188
// parameter index in <index>
1191
case audioMasterEndEdit:
1192
SHOW_CALLBACK( "amc: audioMasterEndEdit\n" );
1193
// end of automation session (when mouse up),
1194
// parameter index in <index>
1197
case audioMasterOpenFileSelector:
1198
SHOW_CALLBACK( "amc: audioMasterOpenFileSelector\n" );
1199
// open a fileselector window with VstFileSelect*
1204
SHOW_CALLBACK( "amd: not handled" );
1214
DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param )
1216
RemoteVstPlugin * _this = static_cast<RemoteVstPlugin *>( _param );
1218
RemotePluginClient::message m;
1219
while( ( m = _this->receiveMessage() ).id != IdQuit )
1221
if( m.id == IdStartProcessing || m.id == IdMidiEvent )
1223
_this->processMessage( m );
1227
PostThreadMessage( __GuiThreadID,
1229
ProcessPluginMessage,
1230
(LPARAM) new message( m ) );
1234
// notify GUI thread about shutdown
1235
PostThreadMessage( __GuiThreadID, WM_USER, ClosePlugin, 0 );
1243
DWORD WINAPI RemoteVstPlugin::guiEventLoop( LPVOID _param )
1245
RemoteVstPlugin * _this = static_cast<RemoteVstPlugin *>( _param );
1247
HMODULE hInst = GetModuleHandle( NULL );
1250
_this->debugMessage( "guiEventLoop(): can't get "
1251
"module handle\n" );
1255
HWND timerWindow = CreateWindowEx( 0, "LVSL", "dummy",
1256
0, 0, 0, 0, 0, NULL, NULL,
1258
// install GUI update timer
1259
SetTimer( timerWindow, 1000, 50, NULL );
1264
while( quit == false && GetMessage( &msg, NULL, 0, 0 ) )
1266
TranslateMessage( &msg );
1267
DispatchMessage( &msg );
1269
if( msg.message == WM_TIMER && _this->isInitialized() )
1271
// give plugin some idle-time for GUI-update
1272
_this->pluginDispatch( effEditIdle );
1274
else if( msg.message == WM_USER )
1276
switch( msg.wParam )
1278
case ProcessPluginMessage:
1280
message * m = (message *) msg.lParam;
1281
_this->processMessage( *m );
1287
_this->pluginDispatch( effEditIdle );
1306
int main( int _argc, char * * _argv )
1310
fprintf( stderr, "not enough arguments\n" );
1314
#ifdef LMMS_BUILD_WIN32
1315
// (non-portable) initialization of statically linked pthread library
1316
pthread_win32_process_attach_np();
1317
pthread_win32_thread_attach_np();
1320
#ifdef LMMS_BUILD_LINUX
1321
#ifdef LMMS_HAVE_SCHED_H
1322
// try to set realtime-priority
1323
struct sched_param sparam;
1324
sparam.sched_priority = ( sched_get_priority_max( SCHED_FIFO ) +
1325
sched_get_priority_min( SCHED_FIFO ) ) / 2;
1326
sched_setscheduler( 0, SCHED_FIFO, &sparam );
1330
// constructor automatically will process messages until it receives
1331
// a IdVstLoadPlugin message and processes it
1332
__plugin = new RemoteVstPlugin( atoi( _argv[1] ), atoi( _argv[2] ) );
1334
if( __plugin->isInitialized() )
1336
__GuiThreadID = GetCurrentThreadId();
1337
if( CreateThread( NULL, 0, RemoteVstPlugin::processingThread,
1338
__plugin, 0, NULL ) == NULL )
1340
__plugin->debugMessage( "could not create "
1341
"processingThread\n" );
1344
RemoteVstPlugin::guiEventLoop( __plugin );
1351
#ifdef LMMS_BUILD_WIN32
1352
pthread_win32_thread_detach_np();
1353
pthread_win32_process_detach_np();