~ubuntu-branches/ubuntu/oneiric/lmms/oneiric

« back to all changes in this revision

Viewing changes to plugins/vst_base/remote_vst_plugin.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Артём Попов
  • Date: 2011-02-14 20:58:36 UTC
  • mfrom: (1.1.10 upstream) (3.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110214205836-2u41xus1d2mj8nfz
Tags: 0.4.10-1ubuntu1
* Merge from debian unstable (LP: #718801).  Remaining changes:
  - Replace build-dep on libwine-dev with wine1.2-dev to build
    against the newer Wine.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * remote_vst_plugin.cpp - LMMS VST Support Layer (RemotePlugin client)
3
 
 *
4
 
 * Copyright (c) 2005-2009 Tobias Doerffel <tobydox/at/users.sourceforge.net>
5
 
 * 
6
 
 * This file is part of Linux MultiMedia Studio - http://lmms.sourceforge.net
7
 
 *
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
12
 
 *
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.
17
 
 *
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.
22
 
 *
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.
27
 
 *
28
 
 */
29
 
 
30
 
 
31
 
#include "lmmsconfig.h"
32
 
 
33
 
#define BUILD_REMOTE_PLUGIN_CLIENT
34
 
 
35
 
#include "RemotePlugin.h"
36
 
 
37
 
#ifdef LMMS_HAVE_PTHREAD_H
38
 
#include <pthread.h>
39
 
#endif
40
 
 
41
 
#ifdef LMMS_HAVE_FCNTL_H
42
 
#include <fcntl.h>
43
 
#endif
44
 
 
45
 
#ifdef LMMS_BUILD_LINUX
46
 
 
47
 
#ifndef O_BINARY
48
 
#define O_BINARY 0
49
 
#endif
50
 
 
51
 
#ifdef LMMS_HAVE_SCHED_H
52
 
#include <sched.h>
53
 
#endif
54
 
 
55
 
#include <wine/exception.h>
56
 
 
57
 
#endif
58
 
 
59
 
#include <windows.h>
60
 
 
61
 
#ifdef LMMS_BUILD_WIN32
62
 
#ifdef LMMS_BUILD_WIN64
63
 
#include "basename.c"
64
 
#else
65
 
#include <libgen.h>
66
 
#endif
67
 
#endif
68
 
 
69
 
 
70
 
#include <vector>
71
 
#include <string>
72
 
 
73
 
 
74
 
#include <aeffectx.h>
75
 
 
76
 
#if kVstVersion < 2400
77
 
 
78
 
#define OLD_VST_SDK
79
 
 
80
 
#define VstInt32 long int
81
 
#define VstIntPtr long int
82
 
 
83
 
struct ERect
84
 
{
85
 
    short top;
86
 
    short left;
87
 
    short bottom;
88
 
    short right;
89
 
} ;
90
 
 
91
 
#endif
92
 
 
93
 
 
94
 
#include "lmms_basics.h"
95
 
#include "midi.h"
96
 
#include "communication.h"
97
 
 
98
 
 
99
 
 
100
 
static VstHostLanguages hlang = LanguageEnglish;
101
 
 
102
 
 
103
 
class RemoteVstPlugin;
104
 
 
105
 
RemoteVstPlugin * __plugin = NULL;
106
 
 
107
 
DWORD __GuiThreadID = 0;
108
 
 
109
 
 
110
 
 
111
 
class RemoteVstPlugin : public RemotePluginClient
112
 
{
113
 
public:
114
 
        RemoteVstPlugin( key_t _shm_in, key_t _shm_out );
115
 
        virtual ~RemoteVstPlugin();
116
 
 
117
 
        virtual bool processMessage( const message & _m );
118
 
 
119
 
        void init( const std::string & _plugin_file );
120
 
        void initEditor();
121
 
 
122
 
        virtual void process( const sampleFrame * _in, sampleFrame * _out );
123
 
 
124
 
 
125
 
        virtual void processMidiEvent( const midiEvent & _event,
126
 
                                                        const f_cnt_t _offset );
127
 
 
128
 
        // set given sample-rate for plugin
129
 
        virtual void updateSampleRate()
130
 
        {
131
 
                pluginDispatch( effSetSampleRate, 0, 0,
132
 
                                                NULL, (float) sampleRate() );
133
 
        }
134
 
 
135
 
        // set given buffer-size for plugin
136
 
        virtual void updateBufferSize()
137
 
        {
138
 
                pluginDispatch( effSetBlockSize, 0, bufferSize() );
139
 
        }
140
 
 
141
 
 
142
 
        inline bool isInitialized() const
143
 
        {
144
 
                return m_initialized;
145
 
        }
146
 
 
147
 
 
148
 
        // set given tempo
149
 
        void setBPM( const bpm_t _bpm )
150
 
        {
151
 
                m_bpm = _bpm;
152
 
        }
153
 
 
154
 
        // determine VST-version the plugin uses
155
 
        inline int pluginVersion()
156
 
        {
157
 
                return pluginDispatch( effGetVendorVersion );
158
 
        }
159
 
 
160
 
        // determine name of plugin
161
 
        const char * pluginName();
162
 
 
163
 
        // determine vendor of plugin
164
 
        const char * pluginVendorString();
165
 
 
166
 
        // determine product-string of plugin
167
 
        const char * pluginProductString();
168
 
 
169
 
        // do a complete parameter-dump and post it
170
 
        void getParameterDump();
171
 
 
172
 
        // read parameter-dump and set it for plugin
173
 
        void setParameterDump( const message & _m );
174
 
 
175
 
        // post properties of specified parameter
176
 
        void getParameterProperties( const int _idx );
177
 
 
178
 
        // save settings chunk of plugin into file
179
 
        void saveChunkToFile( const std::string & _file );
180
 
 
181
 
        // restore settings chunk of plugin from file
182
 
        void loadChunkFromFile( const std::string & _file, int _len );
183
 
 
184
 
        // number of inputs
185
 
        virtual int inputCount() const
186
 
        {
187
 
                if( m_plugin )
188
 
                {
189
 
                        return m_plugin->numInputs;
190
 
                }
191
 
                return 0;
192
 
        }
193
 
 
194
 
        // number of outputs
195
 
        virtual int outputCount() const
196
 
        {
197
 
                if( m_plugin )
198
 
                {
199
 
                        return m_plugin->numOutputs;
200
 
                }
201
 
                return 0;
202
 
        }
203
 
 
204
 
        // has to be called as soon as input- or output-count changes
205
 
        void updateInOutCount();
206
 
 
207
 
        inline void lock()
208
 
        {
209
 
                pthread_mutex_lock( &m_pluginLock );
210
 
        }
211
 
 
212
 
        inline void unlock()
213
 
        {
214
 
                pthread_mutex_unlock( &m_pluginLock );
215
 
        }
216
 
 
217
 
        static DWORD WINAPI processingThread( LPVOID _param );
218
 
        static DWORD WINAPI guiEventLoop( LPVOID _param );
219
 
 
220
 
 
221
 
private:
222
 
        enum GuiThreadMessages
223
 
        {
224
 
                None,
225
 
                ProcessPluginMessage,
226
 
                GiveIdle,
227
 
                ClosePlugin
228
 
        } ;
229
 
 
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 );
234
 
 
235
 
 
236
 
        bool load( const std::string & _plugin_file );
237
 
 
238
 
        // thread-safe dispatching of plugin
239
 
        int pluginDispatch( int cmd, int param1 = 0, int param2 = 0,
240
 
                                        void * p = NULL, float f = 0 )
241
 
        {
242
 
                int ret = 0;
243
 
                lock();
244
 
                if( m_plugin )
245
 
                {
246
 
                        ret = m_plugin->dispatcher( m_plugin, cmd, param1,
247
 
                                                        param2, p, f );
248
 
                }
249
 
                unlock();
250
 
                return ret;
251
 
        }
252
 
 
253
 
        std::string m_shortName;
254
 
 
255
 
        HINSTANCE m_libInst;
256
 
 
257
 
        AEffect * m_plugin;
258
 
        HWND m_window;
259
 
        Sint32 m_windowID;
260
 
        int m_windowWidth;
261
 
        int m_windowHeight;
262
 
 
263
 
        bool m_initialized;
264
 
 
265
 
        pthread_mutex_t m_pluginLock;
266
 
 
267
 
 
268
 
        float * * m_inputs;
269
 
        float * * m_outputs;
270
 
 
271
 
        typedef std::vector<VstMidiEvent> VstMidiEventList;
272
 
        VstMidiEventList m_midiEvents;
273
 
 
274
 
        bpm_t m_bpm;
275
 
        double m_currentSamplePos;
276
 
 
277
 
} ;
278
 
 
279
 
 
280
 
 
281
 
 
282
 
RemoteVstPlugin::RemoteVstPlugin( key_t _shm_in, key_t _shm_out ) :
283
 
        RemotePluginClient( _shm_in, _shm_out ),
284
 
        m_shortName( "" ),
285
 
        m_libInst( NULL ),
286
 
        m_plugin( NULL ),
287
 
        m_window( NULL ),
288
 
        m_windowID( 0 ),
289
 
        m_windowWidth( 0 ),
290
 
        m_windowHeight( 0 ),
291
 
        m_initialized( false ),
292
 
        m_pluginLock(),
293
 
        m_inputs( NULL ),
294
 
        m_outputs( NULL ),
295
 
        m_midiEvents(),
296
 
        m_bpm( 0 ),
297
 
        m_currentSamplePos( 0 )
298
 
{
299
 
        pthread_mutex_init( &m_pluginLock, NULL );
300
 
 
301
 
        __plugin = this;
302
 
 
303
 
        // process until we have loaded the plugin
304
 
        while( 1 )
305
 
        {
306
 
                message m = receiveMessage();
307
 
                processMessage( m );
308
 
                if( m.id == IdVstLoadPlugin || m.id == IdQuit )
309
 
                {
310
 
                        break;
311
 
                }
312
 
        }
313
 
}
314
 
 
315
 
 
316
 
 
317
 
 
318
 
RemoteVstPlugin::~RemoteVstPlugin()
319
 
{
320
 
        if( m_window != NULL )
321
 
        {
322
 
                pluginDispatch( effEditClose );
323
 
#ifdef LMMS_BUILD_LINUX
324
 
                CloseWindow( m_window );
325
 
#endif
326
 
                m_window = NULL;
327
 
        }
328
 
 
329
 
        if( m_libInst != NULL )
330
 
        {
331
 
                FreeLibrary( m_libInst );
332
 
                m_libInst = NULL;
333
 
        }
334
 
 
335
 
        delete[] m_inputs;
336
 
        delete[] m_outputs;
337
 
 
338
 
        pthread_mutex_destroy( &m_pluginLock );
339
 
}
340
 
 
341
 
 
342
 
 
343
 
 
344
 
bool RemoteVstPlugin::processMessage( const message & _m )
345
 
{
346
 
        switch( _m.id )
347
 
        {
348
 
                case IdVstLoadPlugin:
349
 
                        init( _m.getString() );
350
 
                        break;
351
 
 
352
 
#ifdef LMMS_BUILD_WIN32
353
 
                case IdVstPluginWindowInformation:
354
 
                {
355
 
                        HWND top = FindWindowEx( NULL, NULL, NULL,
356
 
                                                _m.getString().c_str() );
357
 
                        m_window = FindWindowEx( top, NULL, NULL, NULL );
358
 
                        break;
359
 
                }
360
 
#endif
361
 
 
362
 
                case IdVstSetTempo:
363
 
                        setBPM( _m.getInt() );
364
 
                        break;
365
 
 
366
 
                case IdVstSetLanguage:
367
 
                        hlang = static_cast<VstHostLanguages>( _m.getInt() );
368
 
                        break;
369
 
 
370
 
                case IdVstGetParameterDump:
371
 
                        getParameterDump();
372
 
                        break;
373
 
 
374
 
                case IdVstSetParameterDump:
375
 
                        setParameterDump( _m );
376
 
                        break;
377
 
 
378
 
                case IdVstGetParameterProperties:
379
 
                        getParameterProperties( _m.getInt() );
380
 
                        break;
381
 
 
382
 
                case IdSaveSettingsToFile:
383
 
                        saveChunkToFile( _m.getString() );
384
 
                        sendMessage( IdSaveSettingsToFile );
385
 
                        break;
386
 
 
387
 
                case IdLoadSettingsFromFile:
388
 
                        loadChunkFromFile( _m.getString( 0 ), _m.getInt( 1 ) );
389
 
                        sendMessage( IdLoadSettingsFromFile );
390
 
                        break;
391
 
 
392
 
                default:
393
 
                        return RemotePluginClient::processMessage( _m );
394
 
        }
395
 
        return true;
396
 
}
397
 
 
398
 
 
399
 
 
400
 
 
401
 
void RemoteVstPlugin::init( const std::string & _plugin_file )
402
 
{
403
 
        if( load( _plugin_file ) == false )
404
 
        {
405
 
                sendMessage( IdVstFailedLoadingPlugin );
406
 
                return;
407
 
        }
408
 
 
409
 
        updateInOutCount();
410
 
 
411
 
        /* set program to zero */
412
 
        /* i comment this out because it breaks dfx Geometer
413
 
         * looks like we cant set programs for it
414
 
         *
415
 
        pluginDispatch( effSetProgram, 0, 0 ); */
416
 
        // request rate and blocksize
417
 
 
418
 
        pluginDispatch( effMainsChanged, 0, 1 );
419
 
 
420
 
        debugMessage( "creating editor\n" );
421
 
        initEditor();
422
 
        debugMessage( "editor successfully created\n" );
423
 
 
424
 
 
425
 
        // now post some information about our plugin
426
 
        sendMessage( message( IdVstPluginWindowID ).addInt( m_windowID ) );
427
 
 
428
 
        sendMessage( message( IdVstPluginEditorGeometry ).
429
 
                                                addInt( m_windowWidth ).
430
 
                                                addInt( m_windowHeight ) );
431
 
 
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 ) );
440
 
 
441
 
        sendMessage( IdInitDone );
442
 
 
443
 
        m_initialized = true;
444
 
}
445
 
 
446
 
 
447
 
 
448
 
 
449
 
void RemoteVstPlugin::initEditor()
450
 
{
451
 
        if( !( m_plugin->flags & effFlagsHasEditor ) )
452
 
        {
453
 
                return;
454
 
        }
455
 
 
456
 
 
457
 
        HMODULE hInst = GetModuleHandle( NULL );
458
 
        if( hInst == NULL )
459
 
        {
460
 
                debugMessage( "initEditor(): can't get module handle\n" );
461
 
                return;
462
 
        }
463
 
 
464
 
 
465
 
        WNDCLASS wc;
466
 
        wc.style = CS_HREDRAW | CS_VREDRAW;
467
 
        wc.lpfnWndProc = DefWindowProc;
468
 
        wc.cbClsExtra = 0;
469
 
        wc.cbWndExtra = 0;
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";
476
 
 
477
 
        if( !RegisterClass( &wc ) )
478
 
        {
479
 
                return;
480
 
        }
481
 
 
482
 
#ifdef LMMS_BUILD_LINUX
483
 
        m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
484
 
                               ( WS_OVERLAPPEDWINDOW | WS_THICKFRAME ) &
485
 
                                                        ~WS_MAXIMIZEBOX,
486
 
                               0, 0, 10, 10, NULL, NULL, hInst, NULL );
487
 
 
488
 
#else
489
 
        m_windowID = 1; // arbitrary value on win32 to signal
490
 
                        // vstPlugin-class that we have an editor
491
 
 
492
 
        m_window = CreateWindowEx( 0, "LVSL", m_shortName.c_str(),
493
 
                                        WS_CHILD, 0, 0, 10, 10,
494
 
                                        m_window, NULL, hInst, NULL );
495
 
#endif
496
 
        if( m_window == NULL )
497
 
        {
498
 
                debugMessage( "initEditor(): cannot create editor window\n" );
499
 
                return;
500
 
        }
501
 
 
502
 
 
503
 
        pluginDispatch( effEditOpen, 0, 0, m_window );
504
 
 
505
 
        ERect * er;
506
 
        pluginDispatch( effEditGetRect, 0, 0, &er );
507
 
 
508
 
        m_windowWidth = er->right - er->left;
509
 
        m_windowHeight = er->bottom - er->top;
510
 
 
511
 
        SetWindowPos( m_window, 0, 0, 0, m_windowWidth + 8,
512
 
                        m_windowHeight + 26, SWP_NOACTIVATE |
513
 
                                                SWP_NOMOVE | SWP_NOZORDER );
514
 
        pluginDispatch( effEditTop );
515
 
 
516
 
        ShowWindow( m_window, SW_SHOWNORMAL );
517
 
        UpdateWindow( m_window );
518
 
 
519
 
#ifdef LMMS_BUILD_LINUX
520
 
        m_windowID = (Sint32) GetProp( m_window, "__wine_x11_whole_window" );
521
 
#endif
522
 
}
523
 
 
524
 
 
525
 
 
526
 
 
527
 
bool RemoteVstPlugin::load( const std::string & _plugin_file )
528
 
{
529
 
        if( ( m_libInst = LoadLibrary( _plugin_file.c_str() ) ) == NULL )
530
 
        {
531
 
                return false;
532
 
        }
533
 
 
534
 
        char * tmp = strdup( _plugin_file.c_str() );
535
 
        m_shortName = basename( tmp );
536
 
        free( tmp );
537
 
 
538
 
        typedef AEffect * ( __stdcall * mainEntryPointer )
539
 
                                                ( audioMasterCallback );
540
 
        mainEntryPointer mainEntry = (mainEntryPointer)
541
 
                                GetProcAddress( m_libInst, "VSTPluginMain" );
542
 
        if( mainEntry == NULL )
543
 
        {
544
 
                mainEntry = (mainEntryPointer)
545
 
                                GetProcAddress( m_libInst, "VstPluginMain" );
546
 
        }
547
 
        if( mainEntry == NULL )
548
 
        {
549
 
                mainEntry = (mainEntryPointer)
550
 
                                GetProcAddress( m_libInst, "main" );
551
 
        }
552
 
        if( mainEntry == NULL )
553
 
        {
554
 
                debugMessage( "could not find entry point\n" );
555
 
                return false;
556
 
        }
557
 
 
558
 
        m_plugin = mainEntry( hostCallback );
559
 
        if( m_plugin == NULL )
560
 
        {
561
 
                debugMessage( "mainEntry prodecure returned NULL\n" );
562
 
                return false;
563
 
        }
564
 
 
565
 
        m_plugin->user = this;
566
 
 
567
 
        if( m_plugin->magic != kEffectMagic )
568
 
        {
569
 
                char buf[256];
570
 
                sprintf( buf, "%s is not a VST plugin\n",
571
 
                                                        _plugin_file.c_str() );
572
 
                debugMessage( buf );
573
 
                return false;
574
 
        }
575
 
 
576
 
 
577
 
        char id[5];
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] );
582
 
        id[4] = 0;
583
 
        sendMessage( message( IdVstPluginUniqueID ).addString( id ) );
584
 
 
585
 
        pluginDispatch( effOpen );
586
 
 
587
 
        return true;
588
 
}
589
 
 
590
 
 
591
 
 
592
 
 
593
 
void RemoteVstPlugin::process( const sampleFrame * _in, sampleFrame * _out )
594
 
{
595
 
        // first we gonna post all MIDI-events we enqueued so far
596
 
        if( m_midiEvents.size() )
597
 
        {
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();
610
 
                int idx = 0;
611
 
                for( VstMidiEventList::iterator it = m_midiEvents.begin();
612
 
                                        it != m_midiEvents.end(); ++it, ++idx )
613
 
                {
614
 
                        memcpy( &vme[idx], &*it, sizeof( VstMidiEvent ) );
615
 
                        events->events[idx] = (VstEvent *) &vme[idx];
616
 
                }
617
 
 
618
 
                m_midiEvents.clear();
619
 
                pluginDispatch( effProcessEvents, 0, 0, events );
620
 
        }
621
 
 
622
 
        // now we're ready to fetch sound from VST-plugin
623
 
 
624
 
        for( int i = 0; i < inputCount(); ++i )
625
 
        {
626
 
                m_inputs[i] = &((float *) _in)[i * bufferSize()];
627
 
        }
628
 
 
629
 
        for( int i = 0; i < outputCount(); ++i )
630
 
        {
631
 
                m_outputs[i] = &((float *) _out)[i * bufferSize()];
632
 
                memset( m_outputs[i], 0, bufferSize() * sizeof( float ) );
633
 
        }
634
 
 
635
 
#ifdef OLD_VST_SDK
636
 
        if( m_plugin->flags & effFlagsCanReplacing )
637
 
        {
638
 
#endif
639
 
                m_plugin->processReplacing( m_plugin, m_inputs, m_outputs,
640
 
                                                                bufferSize() );
641
 
#ifdef OLD_VST_SDK
642
 
        }
643
 
        else
644
 
        {
645
 
                m_plugin->process( m_plugin, m_inputs, m_outputs,
646
 
                                                                bufferSize() );
647
 
        }
648
 
#endif
649
 
 
650
 
        m_currentSamplePos += bufferSize();
651
 
 
652
 
}
653
 
 
654
 
 
655
 
 
656
 
 
657
 
void RemoteVstPlugin::processMidiEvent( const midiEvent & _event,
658
 
                                                        const f_cnt_t _offset )
659
 
{
660
 
        VstMidiEvent event;
661
 
 
662
 
        event.type = kVstMidiType;
663
 
        event.byteSize = 24;
664
 
        event.deltaFrames = _offset;
665
 
        event.flags = 0;
666
 
        event.detune = 0;
667
 
        event.noteLength = 0;
668
 
        event.noteOffset = 0;
669
 
        event.noteOffVelocity = 0;
670
 
        event.reserved1 = 0;
671
 
        event.reserved2 = 0;
672
 
        event.midiData[0] = _event.m_type + _event.m_channel;
673
 
        switch( _event.m_type )
674
 
        {
675
 
                case MidiPitchBend:
676
 
                        event.midiData[1] = _event.m_data.m_param[0] & 0x7f;
677
 
                        event.midiData[2] = _event.m_data.m_param[0] >> 7;
678
 
                        break;
679
 
                // TODO: handle more special cases
680
 
                default:
681
 
                        event.midiData[1] = _event.key();
682
 
                        event.midiData[2] = _event.velocity();
683
 
                        break;
684
 
        }
685
 
        event.midiData[3] = 0;
686
 
        m_midiEvents.push_back( event );
687
 
}
688
 
 
689
 
 
690
 
 
691
 
 
692
 
const char * RemoteVstPlugin::pluginName()
693
 
{
694
 
        static char buf[32];
695
 
        buf[0] = 0;
696
 
        pluginDispatch( effGetEffectName, 0, 0, buf );
697
 
        buf[31] = 0;
698
 
        return buf;
699
 
}
700
 
 
701
 
 
702
 
 
703
 
 
704
 
const char * RemoteVstPlugin::pluginVendorString()
705
 
{
706
 
        static char buf[64];
707
 
        buf[0] = 0;
708
 
        pluginDispatch( effGetVendorString, 0, 0, buf );
709
 
        buf[63] = 0;
710
 
        return buf;
711
 
}
712
 
 
713
 
 
714
 
 
715
 
 
716
 
const char * RemoteVstPlugin::pluginProductString()
717
 
{
718
 
        static char buf[64];
719
 
        buf[0] = 0;
720
 
        pluginDispatch( effGetProductString, 0, 0, buf );
721
 
        buf[63] = 0;
722
 
        return buf;
723
 
}
724
 
 
725
 
 
726
 
 
727
 
 
728
 
void RemoteVstPlugin::getParameterDump()
729
 
{
730
 
        VstParameterProperties vst_props;
731
 
        message m( IdVstParameterDump );
732
 
        m.addInt( m_plugin->numParams );
733
 
        for( int i = 0; i < m_plugin->numParams; ++i )
734
 
        {
735
 
                pluginDispatch( effGetParameterProperties, i, 0, &vst_props );
736
 
                m.addInt( i );
737
 
                m.addString( vst_props.shortLabel );
738
 
                m.addFloat( m_plugin->getParameter( m_plugin, i ) );
739
 
        }
740
 
        sendMessage( m );
741
 
}
742
 
 
743
 
 
744
 
 
745
 
 
746
 
void RemoteVstPlugin::setParameterDump( const message & _m )
747
 
{
748
 
        const int n = _m.getInt( 0 );
749
 
        const int params = ( n > m_plugin->numParams ) ?
750
 
                                        m_plugin->numParams : n;
751
 
        int p = 0;
752
 
        for( int i = 0; i < params; ++i )
753
 
        {
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 );
759
 
        }
760
 
}
761
 
 
762
 
 
763
 
 
764
 
 
765
 
void RemoteVstPlugin::getParameterProperties( const int _idx )
766
 
{
767
 
        VstParameterProperties p;
768
 
        pluginDispatch( effGetParameterProperties, _idx, 0, &p );
769
 
        message m( IdVstParameterProperties );
770
 
        m.addString( p.label );
771
 
        m.addString( p.shortLabel );
772
 
        m.addString(
773
 
#if kVstVersion > 2
774
 
                        p.categoryLabel
775
 
#else
776
 
                        ""
777
 
#endif
778
 
                                        );
779
 
        m.addFloat( p.minInteger );
780
 
        m.addFloat( p.maxInteger );
781
 
        m.addFloat( ( p.flags & kVstParameterUsesFloatStep ) ?
782
 
                                                p.stepFloat : p.stepInteger );
783
 
        m.addInt(
784
 
#if kVstVersion > 2
785
 
                        p.category
786
 
#else
787
 
                        0
788
 
#endif
789
 
                                );
790
 
        sendMessage( m );
791
 
}
792
 
 
793
 
 
794
 
 
795
 
 
796
 
void RemoteVstPlugin::saveChunkToFile( const std::string & _file )
797
 
{
798
 
        if( m_plugin->flags & 32 )
799
 
        {
800
 
                void * chunk = NULL;
801
 
                const int len = pluginDispatch( 23, 0, 0, &chunk );
802
 
                if( len > 0 )
803
 
                {
804
 
                        int fd = open( _file.c_str(), O_WRONLY | O_BINARY );
805
 
                        write( fd, chunk, len );
806
 
                        close( fd );
807
 
                }
808
 
        }
809
 
}
810
 
 
811
 
 
812
 
 
813
 
 
814
 
void RemoteVstPlugin::loadChunkFromFile( const std::string & _file, int _len )
815
 
{
816
 
        char * buf = NULL;
817
 
 
818
 
        void * chunk = NULL;
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 );
822
 
 
823
 
        // allocated buffer big enough?
824
 
        if( _len > actualLen )
825
 
        {
826
 
                // no, then manually allocate a buffer
827
 
                buf = new char[_len];
828
 
                chunk = buf;
829
 
        }
830
 
 
831
 
        const int fd = open( _file.c_str(), O_RDONLY | O_BINARY );
832
 
        read( fd, chunk, _len );
833
 
        close( fd );
834
 
        pluginDispatch( 24, 0, _len, chunk );
835
 
 
836
 
        delete[] buf;
837
 
}
838
 
 
839
 
 
840
 
 
841
 
 
842
 
void RemoteVstPlugin::updateInOutCount()
843
 
{
844
 
        delete[] m_inputs;
845
 
        delete[] m_outputs;
846
 
 
847
 
        m_inputs = NULL;
848
 
        m_outputs = NULL;
849
 
 
850
 
        setInputCount( inputCount() );
851
 
        setOutputCount( outputCount() );
852
 
 
853
 
        char buf[64];
854
 
        sprintf( buf, "inputs: %d  output: %d\n", inputCount(), outputCount() );
855
 
        debugMessage( buf );
856
 
 
857
 
        if( inputCount() > 0 )
858
 
        {
859
 
                m_inputs = new float * [inputCount()];
860
 
        }
861
 
 
862
 
        if( outputCount() > 0 )
863
 
        {
864
 
                m_outputs = new float * [outputCount()];
865
 
        }
866
 
}
867
 
 
868
 
 
869
 
 
870
 
//#define DEBUG_CALLBACKS
871
 
#ifdef DEBUG_CALLBACKS
872
 
#define SHOW_CALLBACK __plugin->debugMessage
873
 
#else
874
 
#define SHOW_CALLBACK(...)
875
 
#endif
876
 
 
877
 
 
878
 
/* TODO:
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?
884
 
 */
885
 
VstIntPtr RemoteVstPlugin::hostCallback( AEffect * _effect, VstInt32 _opcode,
886
 
                                        VstInt32 _index, VstIntPtr _value,
887
 
                                                void * _ptr, float _opt )
888
 
{
889
 
        static VstTimeInfo _timeInfo;
890
 
#ifdef DEBUG_CALLBACKS
891
 
        char buf[64];
892
 
        sprintf( buf, "host-callback, opcode = %d\n", (int) _opcode );
893
 
        SHOW_CALLBACK( buf );
894
 
#endif
895
 
 
896
 
        // workaround for early callbacks by some plugins
897
 
        if( __plugin && __plugin->m_plugin == NULL )
898
 
        {
899
 
                __plugin->m_plugin = _effect;
900
 
        }
901
 
 
902
 
        switch( _opcode )
903
 
        {
904
 
                case audioMasterAutomate:
905
 
                        SHOW_CALLBACK( "amc: audioMasterAutomate\n" );
906
 
                        // index, value, returns 0
907
 
                        _effect->setParameter( _effect, _index, _opt );
908
 
                        return 0;
909
 
 
910
 
                case audioMasterVersion:
911
 
                        SHOW_CALLBACK( "amc: audioMasterVersion\n" );
912
 
                        return 2300;
913
 
 
914
 
                case audioMasterCurrentId:      
915
 
                        SHOW_CALLBACK( "amc: audioMasterCurrentId\n" );
916
 
                        // returns the unique id of a plug that's currently
917
 
                        // loading
918
 
                        return 0;
919
 
                
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 );
926
 
                        return 0;
927
 
 
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.
935
 
                        return 1;
936
 
 
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
943
 
 
944
 
                        memset( &_timeInfo, 0, sizeof( _timeInfo ) );
945
 
 
946
 
                        _timeInfo.samplePos = __plugin->m_currentSamplePos;
947
 
                        _timeInfo.sampleRate = __plugin->sampleRate();
948
 
                        _timeInfo.flags = 0;
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;
956
 
#else
957
 
                        return (long) &_timeInfo;
958
 
#endif
959
 
 
960
 
                case audioMasterProcessEvents:
961
 
                        SHOW_CALLBACK( "amc: audioMasterProcessEvents\n" );
962
 
                        // VstEvents* in <ptr>
963
 
                        return 0;
964
 
 
965
 
                case audioMasterIOChanged:
966
 
                        __plugin->updateInOutCount();
967
 
                        SHOW_CALLBACK( "amc: audioMasterIOChanged\n" );
968
 
                        // numInputs and/or numOutputs has changed
969
 
                        return 0;
970
 
 
971
 
#ifdef OLD_VST_SDK
972
 
                case audioMasterWantMidi:
973
 
                        SHOW_CALLBACK( "amc: audioMasterWantMidi\n" );
974
 
                        // <value> is a filter which is currently ignored
975
 
                        return 1;
976
 
 
977
 
                case audioMasterSetTime:
978
 
                        SHOW_CALLBACK( "amc: audioMasterSetTime\n" );
979
 
                        // VstTimenfo* in <ptr>, filter in <value>, not
980
 
                        // supported
981
 
                        return 0;
982
 
 
983
 
                case audioMasterTempoAt:
984
 
                        SHOW_CALLBACK( "amc: audioMasterTempoAt\n" );
985
 
                        return __plugin->m_bpm * 10000;
986
 
 
987
 
                case audioMasterGetNumAutomatableParameters:
988
 
                        SHOW_CALLBACK( "amc: audioMasterGetNumAutomatable"
989
 
                                                        "Parameters\n" );
990
 
                        return 5000;
991
 
 
992
 
                case audioMasterGetParameterQuantization:       
993
 
                        SHOW_CALLBACK( "amc: audioMasterGetParameter\n"
994
 
                                                        "Quantization\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,
998
 
                        // any)
999
 
                        return 1;
1000
 
 
1001
 
                case audioMasterNeedIdle:
1002
 
                        SHOW_CALLBACK( "amc: audioMasterNeedIdle\n" );
1003
 
                        // plug needs idle calls (outside its editor window)
1004
 
                        return 1;
1005
 
 
1006
 
                case audioMasterGetPreviousPlug:
1007
 
                        SHOW_CALLBACK( "amc: audioMasterGetPreviousPlug\n" );
1008
 
                        // input pin in <value> (-1: first to come), returns
1009
 
                        // cEffect*
1010
 
                        return 0;
1011
 
 
1012
 
                case audioMasterGetNextPlug:
1013
 
                        SHOW_CALLBACK( "amc: audioMasterGetNextPlug\n" );
1014
 
                        // output pin in <value> (-1: first to come), returns
1015
 
                        // cEffect*
1016
 
                        return 0;
1017
 
 
1018
 
                case audioMasterWillReplaceOrAccumulate:
1019
 
                        SHOW_CALLBACK( "amc: audioMasterWillReplaceOr"
1020
 
                                                        "Accumulate\n" );
1021
 
                        // returns: 0: not supported, 1: replace, 2: accumulate
1022
 
                        return 1;
1023
 
 
1024
 
                case audioMasterGetSpeakerArrangement:
1025
 
                        SHOW_CALLBACK( "amc: audioMasterGetSpeaker"
1026
 
                                                        "Arrangement\n" );
1027
 
                        // (long)input in <value>, output in <ptr>
1028
 
                        return 0;
1029
 
 
1030
 
                case audioMasterSetOutputSampleRate:
1031
 
                        SHOW_CALLBACK( "amc: audioMasterSetOutputSample"
1032
 
                                                                "Rate\n" );
1033
 
                        // for variable i/o, sample rate in <opt>
1034
 
                        return 0;
1035
 
 
1036
 
                case audioMasterSetIcon:
1037
 
                        SHOW_CALLBACK( "amc: audioMasterSetIcon\n" );
1038
 
                        // TODO
1039
 
                        // void* in <ptr>, format not defined yet
1040
 
                        return 0;
1041
 
 
1042
 
                case audioMasterOpenWindow:
1043
 
                        SHOW_CALLBACK( "amc: audioMasterOpenWindow\n" );
1044
 
                        // TODO
1045
 
                        // returns platform specific ptr
1046
 
                        return 0;
1047
 
                
1048
 
                case audioMasterCloseWindow:
1049
 
                        SHOW_CALLBACK( "amc: audioMasterCloseWindow\n" );
1050
 
                        // TODO
1051
 
                        // close window, platform specific handle in <ptr>
1052
 
                        return 0;
1053
 
#endif
1054
 
 
1055
 
                case audioMasterSizeWindow:
1056
 
                        SHOW_CALLBACK( "amc: audioMasterSizeWindow\n" );
1057
 
                        if( __plugin->m_window == 0 )
1058
 
                        {
1059
 
                                return 0;
1060
 
                        }
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 ) );
1071
 
                        return 1;
1072
 
 
1073
 
                case audioMasterGetSampleRate:
1074
 
                        SHOW_CALLBACK( "amc: audioMasterGetSampleRate\n" );
1075
 
                        return __plugin->sampleRate();
1076
 
 
1077
 
                case audioMasterGetBlockSize:
1078
 
                        SHOW_CALLBACK( "amc: audioMasterGetBlockSize\n" );
1079
 
 
1080
 
                        return __plugin->bufferSize();
1081
 
 
1082
 
                case audioMasterGetInputLatency:
1083
 
                        SHOW_CALLBACK( "amc: audioMasterGetInputLatency\n" );
1084
 
                        return __plugin->bufferSize();
1085
 
 
1086
 
                case audioMasterGetOutputLatency:
1087
 
                        SHOW_CALLBACK( "amc: audioMasterGetOutputLatency\n" );
1088
 
                        return __plugin->bufferSize();
1089
 
 
1090
 
                case audioMasterGetCurrentProcessLevel:
1091
 
                        SHOW_CALLBACK( "amc: audioMasterGetCurrentProcess"
1092
 
                                                                "Level\n" );
1093
 
                        // returns: 0: not supported,
1094
 
                        // 1: currently in user thread (gui)
1095
 
                        // 2: currently in audio thread (where process is
1096
 
                        //    called)
1097
 
                        // 3: currently in 'sequencer' thread (midi, timer etc)
1098
 
                        // 4: currently offline processing and thus in user
1099
 
                        //    thread
1100
 
                        // other: not defined, but probably pre-empting user
1101
 
                        //        thread.
1102
 
                        return 0;
1103
 
 
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
1108
 
                        return 0;
1109
 
 
1110
 
                case audioMasterOfflineStart:
1111
 
                        SHOW_CALLBACK( "amc: audioMasterOfflineStart\n" );
1112
 
                        return 0;
1113
 
 
1114
 
                case audioMasterOfflineRead:
1115
 
                        SHOW_CALLBACK( "amc: audioMasterOfflineRead\n" );
1116
 
                        // ptr points to offline structure, see below.
1117
 
                        // return 0: error, 1 ok
1118
 
                        return 0;
1119
 
 
1120
 
                case audioMasterOfflineWrite:
1121
 
                        SHOW_CALLBACK( "amc: audioMasterOfflineWrite\n" );
1122
 
                        // same as read
1123
 
                        return 0;
1124
 
 
1125
 
                case audioMasterOfflineGetCurrentPass:
1126
 
                        SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrent"
1127
 
                                                                "Pass\n" );
1128
 
                        return 0;
1129
 
 
1130
 
                case audioMasterOfflineGetCurrentMetaPass:
1131
 
                        SHOW_CALLBACK( "amc: audioMasterOfflineGetCurrentMeta"
1132
 
                                                                "Pass\n");
1133
 
                        return 0;
1134
 
 
1135
 
                case audioMasterGetVendorString:
1136
 
                        SHOW_CALLBACK( "amc: audioMasterGetVendorString\n" );
1137
 
                        // fills <ptr> with a string identifying the vendor
1138
 
                        // (max 64 char)
1139
 
                        strcpy( (char *) _ptr, "Tobias Doerffel" );
1140
 
                        return 1;
1141
 
 
1142
 
                case audioMasterGetProductString:
1143
 
                        SHOW_CALLBACK( "amc: audioMasterGetProductString\n" );
1144
 
                        // fills <ptr> with a string with product name
1145
 
                        // (max 64 char)
1146
 
                        strcpy( (char *) _ptr,
1147
 
                                        "LMMS VST Support Layer (LVSL)" );
1148
 
                        return 1;
1149
 
 
1150
 
                case audioMasterGetVendorVersion:
1151
 
                        SHOW_CALLBACK( "amc: audioMasterGetVendorVersion\n" );
1152
 
                        // returns vendor-specific version
1153
 
                        return 1000;
1154
 
 
1155
 
                case audioMasterVendorSpecific:
1156
 
                        SHOW_CALLBACK( "amc: audioMasterVendorSpecific\n" );
1157
 
                        // no definition, vendor specific handling
1158
 
                        return 0;
1159
 
                
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" );
1167
 
 
1168
 
                case audioMasterGetLanguage:
1169
 
                        SHOW_CALLBACK( "amc: audioMasterGetLanguage\n" );
1170
 
                        return hlang;
1171
 
 
1172
 
                case audioMasterGetDirectory:
1173
 
                        SHOW_CALLBACK( "amc: audioMasterGetDirectory\n" );
1174
 
                        // get plug directory, FSSpec on MAC, else char*
1175
 
                        return 0;
1176
 
                
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 );
1182
 
                        return 0;
1183
 
 
1184
 
#if kVstVersion > 2
1185
 
                case audioMasterBeginEdit:
1186
 
                        SHOW_CALLBACK( "amc: audioMasterBeginEdit\n" );
1187
 
                        // begin of automation session (when mouse down),       
1188
 
                        // parameter index in <index>
1189
 
                        return 0;
1190
 
 
1191
 
                case audioMasterEndEdit:
1192
 
                        SHOW_CALLBACK( "amc: audioMasterEndEdit\n" );
1193
 
                        // end of automation session (when mouse up),
1194
 
                        // parameter index in <index>
1195
 
                        return 0;
1196
 
 
1197
 
                case audioMasterOpenFileSelector:
1198
 
                        SHOW_CALLBACK( "amc: audioMasterOpenFileSelector\n" );
1199
 
                        // open a fileselector window with VstFileSelect*
1200
 
                        // in <ptr>
1201
 
                        return 0;
1202
 
#endif
1203
 
                default:
1204
 
                        SHOW_CALLBACK( "amd: not handled" );
1205
 
                        break;
1206
 
        }
1207
 
 
1208
 
        return 0;
1209
 
}
1210
 
 
1211
 
 
1212
 
 
1213
 
 
1214
 
DWORD WINAPI RemoteVstPlugin::processingThread( LPVOID _param )
1215
 
{
1216
 
        RemoteVstPlugin * _this = static_cast<RemoteVstPlugin *>( _param );
1217
 
 
1218
 
        RemotePluginClient::message m;
1219
 
        while( ( m = _this->receiveMessage() ).id != IdQuit )
1220
 
        {
1221
 
                if( m.id == IdStartProcessing || m.id == IdMidiEvent )
1222
 
                {
1223
 
                        _this->processMessage( m );
1224
 
                }
1225
 
                else
1226
 
                {
1227
 
                        PostThreadMessage( __GuiThreadID,
1228
 
                                        WM_USER,
1229
 
                                        ProcessPluginMessage,
1230
 
                                        (LPARAM) new message( m ) );
1231
 
                }
1232
 
        }
1233
 
 
1234
 
        // notify GUI thread about shutdown
1235
 
        PostThreadMessage( __GuiThreadID, WM_USER, ClosePlugin, 0 );
1236
 
 
1237
 
        return 0;
1238
 
}
1239
 
 
1240
 
 
1241
 
 
1242
 
 
1243
 
DWORD WINAPI RemoteVstPlugin::guiEventLoop( LPVOID _param )
1244
 
{
1245
 
        RemoteVstPlugin * _this = static_cast<RemoteVstPlugin *>( _param );
1246
 
 
1247
 
        HMODULE hInst = GetModuleHandle( NULL );
1248
 
        if( hInst == NULL )
1249
 
        {
1250
 
                _this->debugMessage( "guiEventLoop(): can't get "
1251
 
                                                        "module handle\n" );
1252
 
                return -1;
1253
 
        }
1254
 
 
1255
 
        HWND timerWindow = CreateWindowEx( 0, "LVSL", "dummy",
1256
 
                                                0, 0, 0, 0, 0, NULL, NULL,
1257
 
                                                                hInst, NULL );
1258
 
        // install GUI update timer
1259
 
        SetTimer( timerWindow, 1000, 50, NULL );
1260
 
 
1261
 
        MSG msg;
1262
 
 
1263
 
        bool quit = false;
1264
 
        while( quit == false && GetMessage( &msg, NULL, 0, 0 ) )
1265
 
        {
1266
 
                TranslateMessage( &msg );
1267
 
                DispatchMessage( &msg );
1268
 
 
1269
 
                if( msg.message == WM_TIMER && _this->isInitialized() )
1270
 
                {
1271
 
                        // give plugin some idle-time for GUI-update
1272
 
                        _this->pluginDispatch( effEditIdle );
1273
 
                }
1274
 
                else if( msg.message == WM_USER )
1275
 
                {
1276
 
                        switch( msg.wParam )
1277
 
                        {
1278
 
                                case ProcessPluginMessage:
1279
 
                                {
1280
 
                                        message * m = (message *) msg.lParam;
1281
 
                                        _this->processMessage( *m );
1282
 
                                        delete m;
1283
 
                                        break;
1284
 
                                }
1285
 
 
1286
 
                                case GiveIdle:
1287
 
                                        _this->pluginDispatch( effEditIdle );
1288
 
                                        break;
1289
 
 
1290
 
                                case ClosePlugin:
1291
 
                                        quit = true;
1292
 
                                        break;
1293
 
 
1294
 
                                default:
1295
 
                                        break;
1296
 
                        }
1297
 
                }
1298
 
        }
1299
 
 
1300
 
        return 0;
1301
 
}
1302
 
 
1303
 
 
1304
 
 
1305
 
 
1306
 
int main( int _argc, char * * _argv )
1307
 
{
1308
 
        if( _argc < 3 )
1309
 
        {
1310
 
                fprintf( stderr, "not enough arguments\n" );
1311
 
                return -1;
1312
 
        }
1313
 
 
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();
1318
 
#endif
1319
 
 
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 );
1327
 
#endif
1328
 
#endif
1329
 
 
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] ) );
1333
 
 
1334
 
        if( __plugin->isInitialized() )
1335
 
        {
1336
 
                __GuiThreadID = GetCurrentThreadId();
1337
 
                if( CreateThread( NULL, 0, RemoteVstPlugin::processingThread,
1338
 
                                                __plugin, 0, NULL ) == NULL )
1339
 
                {
1340
 
                        __plugin->debugMessage( "could not create "
1341
 
                                                        "processingThread\n" );
1342
 
                        return -1;
1343
 
                }
1344
 
                RemoteVstPlugin::guiEventLoop( __plugin );
1345
 
        }
1346
 
 
1347
 
 
1348
 
        delete __plugin;
1349
 
 
1350
 
 
1351
 
#ifdef LMMS_BUILD_WIN32
1352
 
        pthread_win32_thread_detach_np();
1353
 
        pthread_win32_process_detach_np();
1354
 
#endif
1355
 
 
1356
 
        return 0;
1357
 
 
1358
 
}
1359