2
* fstserver.cpp - XFST-server
4
* Copyright (c) 2005 Tobias Doerffel <tobydox/at/users.sourceforge.net>
6
* This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU General Public
10
* License as published by the Free Software Foundation; either
11
* version 2 of the License, or (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
* General Public License for more details.
18
* You should have received a copy of the GNU General Public
19
* License along with this program (see COPYING); if not, write to the
20
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21
* Boston, MA 02111-1307, USA.
26
#include <sys/types.h>
34
#include <vst/aeffectx.h>
39
#include "fstserver.h"
42
#include "communication.h"
49
void wine_shared_premain( void );
52
void debugMsg( const char * _str )
54
writeValue<Sint16>( DEBUG_MSG, 1 );
55
writeString( _str, 1 );
60
fst_error (const char *fmt, ...)
66
vsnprintf (buffer, sizeof(buffer), fmt, ap);
67
fst_error_callback (buffer);
72
default_fst_error_callback (const char *desc)
77
void (*fst_error_callback)(const char *desc) = &default_fst_error_callback;
88
VSTPlugin( const char * _plugin ) :
96
if( ( m_handle = fst_load( _plugin ) ) == NULL )
98
sprintf( debugout, "can't load plugin %s\n", _plugin );
103
if( ( m_fst = fst_instantiate( m_handle, hostCallback,
106
sprintf( debugout, "can't instantiate plugin %s\n",
108
debugMsg( debugout );
112
m_plugin = m_fst->plugin;
114
/* set program to zero */
115
/* i comment this out because it breaks dfx Geometer
116
* looks like we cant set programs for it
118
m_plugin->dispatcher( m_plugin, effSetProgram, 0, 0, NULL, 0.0f); */
119
// request rate and blocksize
120
writeValue<Sint16>( GET_SAMPLE_RATE );
121
writeValue<Sint16>( GET_BUFFER_SIZE );
124
m_plugin->dispatcher( m_plugin, effMainsChanged, 0, 1, NULL,
126
if( fst_run_editor( m_fst ) )
128
sprintf( debugout, "cannot create editor\n" );
129
debugMsg( debugout );
132
writeValue<Sint16>( SET_XID );
133
writeValue<Sint32>( fst_get_XID( m_fst ) );
138
writeValue<Sint16>( QUIT_ACK );
140
fst_unload( m_handle );
151
// first we gonna post all MIDI-events we enqueued so far
152
if( m_midiEvents.size() )
154
// since MIDI-events are not received immediately, we
155
// have to have them stored somewhere even after
156
// dispatcher-call, so we create static copies of the
157
// data and post them
158
static VstEvents events;
159
static std::vector<VstMidiEvent> cur_events;
160
cur_events = m_midiEvents;
161
m_midiEvents.clear();
162
for( unsigned int i = 0; i < cur_events.size(); ++i )
164
events.events[i] = (VstEvent *) &cur_events[i];
166
events.numEvents = cur_events.size();
168
m_plugin->dispatcher( m_fst->plugin, effProcessEvents,
169
0, 0, &events, 0.0f );
172
// now we're ready to fetch sound from VST-plugin
174
for( int i = 0; i < inputCount(); ++i )
176
m_inputs[i] = &m_shm[i * m_blockSize];
178
for( int i = 0; i < outputCount(); ++i )
180
m_outputs[i] = &m_shm[( i + inputCount() ) *
184
if( m_fst->plugin->flags & effFlagsCanReplacing )
186
m_plugin->processReplacing( m_plugin, m_inputs,
192
m_plugin->process( m_plugin, m_inputs, m_outputs,
195
writeValue<Sint16>( PROCESS_DONE );
196
// give plugin some idle-time for graphics-update and so on...
197
m_plugin->dispatcher( m_plugin, effEditIdle, 0, 0, NULL, 0 );
201
void enqueueMidiEvent( const midiEvent & _event,
202
const Uint32 _frames_ahead )
206
event.type = kVstMidiType;
208
event.deltaFrames = _frames_ahead;
211
event.noteLength = 0;
212
event.noteOffset = 0;
213
event.noteOffVelocity = 0;
216
event.midiData[0] = _event.m_type + _event.m_channel;
217
event.midiData[1] = _event.key();
218
event.midiData[2] = _event.velocity();
219
event.midiData[3] = 0;
220
m_midiEvents.push_back( event );
223
void setSampleRate( Sint32 _rate )
225
m_plugin->dispatcher( m_plugin, effSetSampleRate, 0, 0, NULL,
229
void setBlockSize( Uint32 _bsize )
231
if( _bsize == m_blockSize )
235
m_blockSize = _bsize;
236
resizeSharedMemory();
237
m_plugin->dispatcher( m_plugin, effSetBlockSize, 0, _bsize,
241
Sint32 vstVersion( void ) const
243
return( m_plugin->dispatcher( m_plugin,
244
effGetVstVersion, 0, 0, NULL, 0.0f ) );
247
const char * vstName( void ) const
251
m_plugin->dispatcher( m_plugin,
252
effGetEffectName, 0, 0, buf, 0.0f );
257
const char * vstVendorString( void ) const
261
m_plugin->dispatcher( m_plugin,
262
effGetVendorString, 0, 0, buf, 0.0f );
267
const char * vstProductString( void ) const
271
m_plugin->dispatcher( m_plugin,
272
effGetProductString, 0, 0, buf, 0.0f );
277
Uint8 inputCount( void ) const
279
return( m_plugin->numInputs );
282
Uint8 outputCount( void ) const
284
return( m_plugin->numOutputs );
287
void resizeSharedMemory( void )
292
size_t s = ( inputCount() + outputCount() ) * m_blockSize *
300
while( ( shm_id = shmget( ++shm_key, s, IPC_CREAT | IPC_EXCL |
304
m_shm = (float *) shmat( shm_id, 0, 0 );
306
if( inputCount() > 0 )
308
m_inputs = new float * [inputCount()];
310
if( outputCount() > 0 )
312
m_outputs = new float * [outputCount()];
315
writeValue<Sint16>( SET_INPUT_COUNT );
316
writeValue<Uint8>( inputCount() );
318
writeValue<Sint16>( SET_OUTPUT_COUNT );
319
writeValue<Uint8>( outputCount() );
321
writeValue<Sint16>( SET_SHM_KEY_AND_SIZE );
322
writeValue<Uint16>( shm_key );
323
writeValue<size_t>( s );
325
writeValue<Sint16>( INITIALIZATION_DONE );
330
static long hostCallback( AEffect * _effect, long _opcode, long _index,
331
long _value, void * _ptr, float _opt );
333
FSTHandle * m_handle;
343
std::vector<VstMidiEvent> m_midiEvents;
349
VSTPlugin * plugin = NULL;
352
#define DEBUG_CALLBACKS
353
#ifdef DEBUG_CALLBACKS
354
#define SHOW_CALLBACK debugMsg
356
#define SHOW_CALLBACK(...)
360
long VSTPlugin::hostCallback( AEffect * _effect, long _opcode, long _index,
361
long _value, void * _ptr, float _opt )
363
static VstTimeInfo _timeInfo;
364
/* sprintf( debugout, "host-callback, opcode = %d\n", (int) _opcode );
365
SHOW_CALLBACK( debugout );*/
369
case audioMasterAutomate:
370
/*SHOW_CALLBACK( "amc: audioMasterAutomate\n" );*/
371
// index, value, returns 0
372
_effect->setParameter( _effect, _index, _opt );
375
case audioMasterVersion:
376
SHOW_CALLBACK( "amc: audioMasterVersion\n" );
377
// vst version, currently 2 (0 for older)
380
case audioMasterCurrentId:
381
SHOW_CALLBACK( "amc: audioMasterCurrentId\n" );
382
// returns the unique id of a plug that's currently
386
case audioMasterIdle:
387
SHOW_CALLBACK ("amc: audioMasterIdle\n" );
388
// call application idle routine (this will
389
// call effEditIdle for all open editors too)
390
_effect->dispatcher( _effect, effEditIdle, 0, 0, NULL,
394
case audioMasterPinConnected:
395
SHOW_CALLBACK( "amc: audioMasterPinConnected\n" );
396
// inquire if an input or output is beeing connected;
397
// index enumerates input or output counting from zero:
398
// value is 0 for input and != 0 otherwise. note: the
399
// return value is 0 for <true> such that older versions
400
// will always return true.
403
case audioMasterWantMidi:
404
SHOW_CALLBACK( "amc: audioMasterWantMidi\n" );
405
// <value> is a filter which is currently ignored
408
case audioMasterGetTime:
409
//SHOW_CALLBACK( "amc: audioMasterGetTime\n" );
410
// returns const VstTimeInfo* (or 0 if not supported)
411
// <value> should contain a mask indicating which
412
// fields are required (see valid masks above), as some
413
// items may require extensive conversions
415
memset( &_timeInfo, 0, sizeof( _timeInfo ) );
417
_timeInfo.samplePos = 0;
418
// TODO: _timeInfo.sampleRate = mixer::inst()->sampleRate();
420
// TODO: _timeInfo.tempo = songEditor::inst()->getBPM();
421
_timeInfo.timeSigNumerator = 4;
422
_timeInfo.timeSigDenominator = 4;
423
_timeInfo.flags |= ( kVstBarsValid | kVstTempoValid );
424
_timeInfo.flags |= kVstTransportPlaying;
426
return( (long)&_timeInfo );
428
case audioMasterProcessEvents:
429
SHOW_CALLBACK( "amc: audioMasterProcessEvents\n" );
430
// VstEvents* in <ptr>
433
case audioMasterSetTime:
434
SHOW_CALLBACK( "amc: audioMasterSetTime\n" );
435
// VstTimenfo* in <ptr>, filter in <value>, not
438
case audioMasterTempoAt:
439
SHOW_CALLBACK( "amc: audioMasterTempoAt\n" );
440
// returns tempo (in bpm * 10000) at sample frame
441
// location passed in <value>
444
case audioMasterGetNumAutomatableParameters:
445
SHOW_CALLBACK( "amc: audioMasterGetNumAutomatable"
449
case audioMasterGetParameterQuantization:
450
SHOW_CALLBACK( "amc: audioMasterGetParameter\n"
452
// returns the integer value for +1.0 representation,
453
// or 1 if full single float precision is maintained
454
// in automation. parameter index in <value> (-1: all,
458
case audioMasterIOChanged:
459
plugin->resizeSharedMemory();
460
SHOW_CALLBACK( "amc: audioMasterIOChanged\n" );
461
// numInputs and/or numOutputs has changed
464
case audioMasterNeedIdle:
465
SHOW_CALLBACK( "amc: audioMasterNeedIdle\n" );
466
// plug needs idle calls (outside its editor window)
469
case audioMasterSizeWindow:
470
// TODO using lmms-main-window-size
471
SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" );
472
// index: width, value: height
475
case audioMasterGetSampleRate:
476
// TODO using mixer-call
477
SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" );
480
case audioMasterGetBlockSize:
481
// TODO using mixer-call
482
SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" );
485
case audioMasterGetInputLatency:
486
// TODO using mixer-call
487
SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" );
490
case audioMasterGetOutputLatency:
491
// TODO using mixer-call
492
SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" );
495
case audioMasterGetPreviousPlug:
496
SHOW_CALLBACK( "amc: audioMasterGetPreviousPlug\n" );
497
// input pin in <value> (-1: first to come), returns
501
case audioMasterGetNextPlug:
502
SHOW_CALLBACK( "amc: audioMasterGetNextPlug\n" );
503
// output pin in <value> (-1: first to come), returns
507
case audioMasterWillReplaceOrAccumulate:
508
SHOW_CALLBACK( "amc: audioMasterWillReplaceOr"
510
// returns: 0: not supported, 1: replace, 2: accumulate
513
case audioMasterGetCurrentProcessLevel:
514
SHOW_CALLBACK( "amc: audioMasterGetCurrentProcess"
516
// returns: 0: not supported,
517
// 1: currently in user thread (gui)
518
// 2: currently in audio thread (where process is
520
// 3: currently in 'sequencer' thread (midi, timer etc)
521
// 4: currently offline processing and thus in user
523
// other: not defined, but probably pre-empting user
527
case audioMasterGetAutomationState:
528
SHOW_CALLBACK( "amc: audioMasterGetAutomationState\n" );
529
// returns 0: not supported, 1: off, 2:read, 3:write,
530
// 4:read/write offline
533
case audioMasterOfflineStart:
534
SHOW_CALLBACK( "amc: audioMasterOfflineStart\n" );
537
case audioMasterOfflineRead:
538
SHOW_CALLBACK( "amc: audioMasterOfflineRead\n" );
539
// ptr points to offline structure, see below.
540
// return 0: error, 1 ok
543
case audioMasterOfflineWrite:
544
SHOW_CALLBACK( "amc: audioMasterOfflineWrite\n" );
548
case audioMasterOfflineGetCurrentPass:
549
SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrent"
553
case audioMasterOfflineGetCurrentMetaPass:
554
SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrentMeta"
558
case audioMasterSetOutputSampleRate:
559
SHOW_CALLBACK( "amc: audioMasterSetOutputSample"
561
// for variable i/o, sample rate in <opt>
564
case audioMasterGetSpeakerArrangement:
565
SHOW_CALLBACK( "amc: audioMasterGetSpeaker"
567
// (long)input in <value>, output in <ptr>
570
case audioMasterGetVendorString:
571
SHOW_CALLBACK( "amc: audioMasterGetVendorString\n" );
572
// fills <ptr> with a string identifying the vendor
574
strcpy( (char *) _ptr, "LAD");
577
case audioMasterGetProductString:
578
SHOW_CALLBACK( "amc: audioMasterGetProductString\n" );
579
// fills <ptr> with a string with product name
581
strcpy( (char *) _ptr, "XFST-Server" );
584
case audioMasterGetVendorVersion:
585
SHOW_CALLBACK( "amc: audioMasterGetVendorVersion\n" );
587
// returns vendor-specific version
590
case audioMasterVendorSpecific:
591
SHOW_CALLBACK( "amc: audioMasterVendorSpecific\n" );
592
// no definition, vendor specific handling
595
case audioMasterSetIcon:
596
SHOW_CALLBACK( "amc: audioMasterSetIcon\n" );
598
// void* in <ptr>, format not defined yet
601
case audioMasterCanDo:
602
SHOW_CALLBACK( "amc: audioMasterCanDo\n" );
603
// string in ptr, see below
606
case audioMasterGetLanguage:
607
SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" );
612
case audioMasterOpenWindow:
613
SHOW_CALLBACK( "amc: audioMasterOpenWindow\n" );
615
// returns platform specific ptr
618
case audioMasterCloseWindow:
619
SHOW_CALLBACK( "amc: audioMasterCloseWindow\n" );
621
// close window, platform specific handle in <ptr>
624
case audioMasterGetDirectory:
625
SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" );
627
// get plug directory, FSSpec on MAC, else char*
630
case audioMasterUpdateDisplay:
631
SHOW_CALLBACK( "amc: audioMasterUpdateDisplay\n" );
632
// something has changed, update 'multi-fx' display
633
_effect->dispatcher( _effect, effEditIdle, 0, 0, NULL,
637
case audioMasterBeginEdit:
638
SHOW_CALLBACK( "amc: audioMasterBeginEdit\n" );
639
// begin of automation session (when mouse down),
640
// parameter index in <index>
643
case audioMasterEndEdit:
644
SHOW_CALLBACK( "amc: audioMasterEndEdit\n" );
645
// end of automation session (when mouse up),
646
// parameter index in <index>
649
case audioMasterOpenFileSelector:
650
SHOW_CALLBACK( "amc: audioMasterOpenFileSelector\n" );
651
// open a fileselector window with VstFileSelect*
656
sprintf( debugout, "VST master dispatcher: undefed: "
657
"%d, %d\n", (int) _opcode, effKeysRequired );
658
SHOW_CALLBACK( debugout );
669
main( int argc, char * * argv )
671
wine_shared_premain();
674
while( ( cmd = readValue<Sint16>() ) != CLOSE_VST_PLUGIN )
678
case LOAD_VST_PLUGIN:
679
plugin = new VSTPlugin( readString().c_str() );
686
case ENQUEUE_MIDI_EVENT:
688
const midiEvent ev = readValue<midiEvent>();
689
const Uint32 fr_ahead = readValue<Uint32>();
690
plugin->enqueueMidiEvent( ev, fr_ahead );
694
case SET_SAMPLE_RATE:
695
plugin->setSampleRate( readValue<Sint32>() );
699
case SET_BUFFER_SIZE:
700
plugin->setBlockSize( readValue<Uint32>() );
703
case GET_VST_VERSION:
704
writeValue<Sint16>( SET_VST_VERSION );
705
writeValue<Sint32>( plugin->vstVersion() );
709
writeValue<Sint16>( SET_NAME );
710
writeString( plugin->vstName() );
713
case GET_VENDOR_STRING:
714
writeValue<Sint16>( SET_VENDOR_STRING );
715
writeString( plugin->vstVendorString() );
718
case GET_PRODUCT_STRING:
719
writeValue<Sint16>( SET_PRODUCT_STRING );
720
writeString( plugin->vstProductString() );
724
debugMsg( "unhandled message!" );