JackNetDriver.cpp 23.9 KB
Newer Older
sletz's avatar
sletz committed
1
2
/*
Copyright (C) 2001 Paul Davis
sletz's avatar
sletz committed
3
Copyright (C) 2008 Romain Moret at Grame
sletz's avatar
sletz committed
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

*/

#include "JackNetDriver.h"
#include "JackEngineControl.h"
#include "JackClientControl.h"
#include "JackGraphManager.h"
#include "JackDriverLoader.h"
#include "JackThreadedDriver.h"
27
#include "JackWaitThreadedDriver.h"
sletz's avatar
sletz committed
28

sletz's avatar
Cleanup    
sletz committed
29
#define DEFAULT_MULTICAST_IP "225.3.19.154"
sletz's avatar
sletz committed
30
31
#define DEFAULT_PORT 19000

32
33
using namespace std;

sletz's avatar
sletz committed
34
35
namespace Jack
{
36
    JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
37
                                   const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
38
                                   const char* net_name, uint transport_sync, char network_mode )
39
            : JackAudioDriver ( name, alias, engine, table ), JackNetSlaveInterface ( ip, port )
40
    {
moret's avatar
moret committed
41
        jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port );
42

43
44
45
46
47
        fParams.fMtu = mtu;
        fParams.fSendMidiChannels = midi_input_ports;
        fParams.fReturnMidiChannels = midi_output_ports;
        strcpy ( fParams.fName, net_name );
        fSocket.GetName ( fParams.fSlaveNetName );
48
        fParams.fTransportSync = transport_sync;
49
        fParams.fNetworkMode = network_mode;
moret's avatar
moret committed
50
#ifdef JACK_MONITOR
moret's avatar
moret committed
51
        fNetTimeMon = NULL;
moret's avatar
Cleanup    
moret committed
52
#endif
53
54
55
56
57
58
    }

    JackNetDriver::~JackNetDriver()
    {
        delete[] fMidiCapturePortList;
        delete[] fMidiPlaybackPortList;
moret's avatar
moret committed
59
#ifdef JACK_MONITOR
moret's avatar
moret committed
60
        delete fNetTimeMon;
moret's avatar
moret committed
61
#endif
62
    }
sletz's avatar
sletz committed
63
64
65

//*************************************initialization***********************************************************************

sletz's avatar
sletz committed
66
    int JackNetDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing,
67
68
69
70
                              int inchannels, int outchannels, bool monitor,
                              const char* capture_driver_name, const char* playback_driver_name,
                              jack_nframes_t capture_latency, jack_nframes_t playback_latency )
    {
sletz's avatar
sletz committed
71
        int res = JackAudioDriver::Open ( buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor,
72
73
74
75
76
77
78
                                          capture_driver_name, playback_driver_name, capture_latency, playback_latency );
        fEngineControl->fPeriod = 0;
        fEngineControl->fComputation = 500 * 1000;
        fEngineControl->fConstraint = 500 * 1000;
        return res;
    }

moret's avatar
Cleanup    
moret committed
79
80
81
#ifdef JACK_MONITOR
    int JackNetDriver::Close()
    {
moret's avatar
moret committed
82
83
        if ( fNetTimeMon )
            fNetTimeMon->Save();
moret's avatar
Cleanup    
moret committed
84
85
86
87
        return JackDriver::Close();
    }
#endif

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
    int JackNetDriver::Attach()
    {
        return 0;
    }

    int JackNetDriver::Detach()
    {
        return 0;
    }

    bool JackNetDriver::Init()
    {
        jack_log ( "JackNetDriver::Init()" );

        //new loading, but existing socket, restart the driver
        if ( fSocket.IsSocket() )
            Restart();

        //set the parameters to send
        fParams.fSendAudioChannels = fCaptureChannels;
        fParams.fReturnAudioChannels = fPlaybackChannels;
moret's avatar
moret committed
109
        fParams.fSlaveSyncMode = fEngineControl->fSyncMode;
110

moret's avatar
moret committed
111
        //display some additional infos
moret's avatar
moret committed
112
        jack_info ( "Net driver started in %s mode %s Master's transport sync.",
moret's avatar
moret committed
113
                    ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
114

moret's avatar
moret committed
115
		//init network
116
117
        if ( !JackNetSlaveInterface::Init() )
            return false;;
118

moret's avatar
moret committed
119
120
121
        //set global paramaters
        SetParams();

122
        //driver parametering
moret's avatar
moret committed
123
124
        JackAudioDriver::SetBufferSize ( fParams.fPeriodSize );
        JackAudioDriver::SetSampleRate ( fParams.fSampleRate );
125

moret's avatar
moret committed
126
127
        JackDriver::NotifyBufferSize ( fParams.fPeriodSize );
        JackDriver::NotifySampleRate ( fParams.fSampleRate );
sletz's avatar
sletz committed
128

129
130
131
132
        //allocate midi ports lists
        fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels];
        fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels];

moret's avatar
moret committed
133
        //register jack ports
134
135
136
137
138
139
140
141
142
        if ( AllocPorts() != 0 )
        {
            jack_error ( "Can't allocate ports." );
            return false;
        }

        //init done, display parameters
        SessionParamsDisplay ( &fParams );

143
144
        //monitor
#ifdef JACK_MONITOR
moret's avatar
moret committed
145
146
147
        string plot_name;
        //NetTimeMon
        plot_name = string ( fParams.fName );
moret's avatar
moret committed
148
149
        plot_name += string ( "_slave" );
        plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" );
moret's avatar
moret committed
150
151
        switch ( fParams.fNetworkMode )
        {
moret's avatar
moret committed
152
153
154
155
156
157
158
159
160
            case 's' :
                plot_name += string ( "_slow" );
                break;
            case 'n' :
                plot_name += string ( "_normal" );
                break;
            case 'f' :
                plot_name += string ( "_fast" );
                break;
moret's avatar
moret committed
161
        }
moret's avatar
moret committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
        fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
        string net_time_mon_fields[] =
        {
            string ( "end of read" ),
            string ( "start of write" ),
            string ( "sync send" ),
            string ( "end of write" )
        };
        string net_time_mon_options[] =
        {
            string ( "set xlabel \"audio cycles\"" ),
            string ( "set ylabel \"% of audio cycle\"" )
        };
        fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
176
177
#endif

178
179
180
181
182
183
        return true;
    }

    void JackNetDriver::Restart()
    {
        jack_log ( "JackNetDriver::Restart" );
moret's avatar
moret committed
184

185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
        jack_info ( "Restarting driver..." );
        delete[] fTxBuffer;
        fTxBuffer = NULL;
        delete[] fRxBuffer;
        fRxBuffer = NULL;
        delete fNetAudioCaptureBuffer;
        fNetAudioCaptureBuffer = NULL;
        delete fNetAudioPlaybackBuffer;
        fNetAudioPlaybackBuffer = NULL;
        delete fNetMidiCaptureBuffer;
        fNetMidiCaptureBuffer = NULL;
        delete fNetMidiPlaybackBuffer;
        fNetMidiPlaybackBuffer = NULL;
        FreePorts();
        delete[] fMidiCapturePortList;
        fMidiCapturePortList = NULL;
        delete[] fMidiPlaybackPortList;
        fMidiPlaybackPortList = NULL;
#ifdef JACK_MONITOR
        delete fNetTimeMon;
        fNetTimeMon = NULL;
#endif
207
208
209
210
211
    }

    int JackNetDriver::AllocPorts()
    {
        jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate );
moret's avatar
moret committed
212

213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
        JackPort* port;
        jack_port_id_t port_id;
        char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
        char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
        unsigned long port_flags;
        int audio_port_index;
        uint midi_port_index;

        //audio
        port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
        for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
        {
            snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1 );
            snprintf ( name, sizeof ( name ) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1 );
            if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
                             static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
            {
                jack_error ( "driver: cannot register port for %s", name );
                return -1;
            }
            port = fGraphManager->GetPort ( port_id );
            port->SetAlias ( alias );
235
            port->SetLatency ( fEngineControl->fBufferSize );
236
            fCapturePortList[audio_port_index] = port_id;
237
            jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
238
239
240
241
242
243
244
245
246
247
248
249
250
251
        }
        port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
        for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
        {
            snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1 );
            snprintf ( name, sizeof ( name ) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1 );
            if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
                             static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
            {
                jack_error ( "driver: cannot register port for %s", name );
                return -1;
            }
            port = fGraphManager->GetPort ( port_id );
            port->SetAlias ( alias );
252
            port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
253
            fPlaybackPortList[audio_port_index] = port_id;
254
            jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
255
256
257
258
259
260
261
262
263
264
265
266
267
        }
        //midi
        port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
        for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
        {
            snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1 );
            snprintf ( name, sizeof ( name ) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1 );
            if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
                             static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
            {
                jack_error ( "driver: cannot register port for %s", name );
                return -1;
            }
268
269
            port = fGraphManager->GetPort ( port_id );
            port->SetLatency ( fEngineControl->fBufferSize );
270
            fMidiCapturePortList[midi_port_index] = port_id;
271
            jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
272
273
274
275
276
277
278
279
280
281
282
283
284
        }

        port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
        for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
        {
            snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1 );
            snprintf ( name, sizeof ( name ) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1 );
            if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
                             static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
            {
                jack_error ( "driver: cannot register port for %s", name );
                return -1;
            }
285
            port = fGraphManager->GetPort ( port_id );
286
            port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
287
            fMidiPlaybackPortList[midi_port_index] = port_id;
288
            jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
289
290
291
292
293
294
295
296
        }

        return 0;
    }

    int JackNetDriver::FreePorts()
    {
        jack_log ( "JackNetDriver::FreePorts" );
moret's avatar
moret committed
297

298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
        int audio_port_index;
        uint midi_port_index;
        for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
            fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index] );
        for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
            fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index] );
        for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
            fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index] );
        for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
            fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index] );
        return 0;
    }

    JackMidiBuffer* JackNetDriver::GetMidiInputBuffer ( int port_index )
    {
        return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiCapturePortList[port_index], fEngineControl->fBufferSize ) );
    }

    JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer ( int port_index )
    {
        return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
    }

321
322
323
324
325
326
327
328
329
330
331
332
    int JackNetDriver::SetSyncPacket()
    {
        if ( fParams.fTransportSync )
        {
            //set the TransportData

            //copy to TxBuffer
            memcpy ( fTxData, &fTransportData, sizeof ( net_transport_data_t ) );
        }
        return 0;
    }

sletz's avatar
sletz committed
333
334
//*************************************process************************************************************************

335
336
337
    int JackNetDriver::Read()
    {
        uint midi_port_index;
moret's avatar
moret committed
338
        uint audio_port_index;
339
340
341

        //buffers
        for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
moret's avatar
moret committed
342
            fNetMidiCaptureBuffer->SetBuffer ( midi_port_index, GetMidiInputBuffer ( midi_port_index ) );
moret's avatar
moret committed
343
        for ( audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++ )
moret's avatar
moret committed
344
            fNetAudioCaptureBuffer->SetBuffer ( audio_port_index, GetInputBuffer ( audio_port_index ) );
345

moret's avatar
moret committed
346
#ifdef JACK_MONITOR
moret's avatar
Cleanup    
moret committed
347
        fNetTimeMon->New();
moret's avatar
moret committed
348
349
#endif

350
        //receive sync (launch the cycle)
351
352
        if ( SyncRecv() == SOCKET_ERROR )
            return 0;
353

354
        //take the time at the beginning of the cycle
355
356
357
        JackDriver::CycleTakeBeginTime();

        //audio, midi or sync if driver is late
358
359
        if ( DataRecv() == SOCKET_ERROR )
            return SOCKET_ERROR;
moret's avatar
moret committed
360

361
#ifdef JACK_MONITOR
moret's avatar
Cleanup    
moret committed
362
        fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
moret's avatar
moret committed
363
#endif
moret's avatar
moret committed
364

365
366
367
368
369
        return 0;
    }

    int JackNetDriver::Write()
    {
moret's avatar
moret committed
370
        uint midi_port_index;
371
        int audio_port_index;
372
373
374

        //buffers
        for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
moret's avatar
moret committed
375
            fNetMidiPlaybackBuffer->SetBuffer ( midi_port_index, GetMidiOutputBuffer ( midi_port_index ) );
376
        for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
moret's avatar
moret committed
377
            fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) );
378

379
#ifdef JACK_MONITOR
moret's avatar
Cleanup    
moret committed
380
        fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
moret's avatar
moret committed
381
382
#endif

383
        //sync
moret's avatar
moret committed
384
385
        memset ( fTxData, 0, fPayloadSize );
        SetSyncPacket();
386

moret's avatar
moret committed
387
        //send sync
388
389
        if ( SyncSend() == SOCKET_ERROR )
            return SOCKET_ERROR;
390

391
#ifdef JACK_MONITOR
moret's avatar
Cleanup    
moret committed
392
        fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
moret's avatar
moret committed
393
394
#endif

moret's avatar
moret committed
395
        //send data
396
397
        if ( DataSend() == SOCKET_ERROR )
            return SOCKET_ERROR;
moret's avatar
moret committed
398

399
#ifdef JACK_MONITOR
moret's avatar
Cleanup    
moret committed
400
        fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
moret's avatar
moret committed
401
402
#endif

403
404
        return 0;
    }
sletz's avatar
sletz committed
405
406
407
408

//*************************************loader*******************************************************

#ifdef __cplusplus
409
410
    extern "C"
    {
sletz's avatar
sletz committed
411
#endif
412
413
414
415
        EXPORT jack_driver_desc_t* driver_get_descriptor ()
        {
            jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
            strcpy ( desc->name, "net" );
moret's avatar
moret committed
416
            desc->nparams = 10;
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
            desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );

            int i = 0;
            strcpy ( desc->params[i].name, "multicast_ip" );
            desc->params[i].character = 'a';
            desc->params[i].type = JackDriverParamString;
            strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
            strcpy ( desc->params[i].short_desc, "Multicast Address" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "udp_net_port" );
            desc->params[i].character = 'p';
            desc->params[i].type = JackDriverParamInt;
            desc->params[i].value.i = 19000;
            strcpy ( desc->params[i].short_desc, "UDP port" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "mtu" );
            desc->params[i].character = 'M';
            desc->params[i].type = JackDriverParamInt;
            desc->params[i].value.i = 1500;
            strcpy ( desc->params[i].short_desc, "MTU to the master" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "input_ports" );
            desc->params[i].character = 'C';
            desc->params[i].type = JackDriverParamInt;
            desc->params[i].value.i = 2;
            strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "output_ports" );
            desc->params[i].character = 'P';
            desc->params[i].type = JackDriverParamInt;
            desc->params[i].value.i = 2;
            strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "midi_in_ports" );
            desc->params[i].character = 'i';
            desc->params[i].type = JackDriverParamInt;
            desc->params[i].value.i = 0;
            strcpy ( desc->params[i].short_desc, "Number of midi input ports" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "midi_out_ports" );
            desc->params[i].character = 'o';
            desc->params[i].type = JackDriverParamUInt;
            desc->params[i].value.i = 0;
            strcpy ( desc->params[i].short_desc, "Number of midi output ports" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

            i++;
            strcpy ( desc->params[i].name, "client_name" );
            desc->params[i].character = 'n';
            desc->params[i].type = JackDriverParamString;
            strcpy ( desc->params[i].value.str, "'hostname'" );
            strcpy ( desc->params[i].short_desc, "Name of the jack client" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

483
484
485
486
487
488
489
490
            i++;
            strcpy ( desc->params[i].name, "transport_sync" );
            desc->params[i].character  = 't';
            desc->params[i].type = JackDriverParamUInt;
            desc->params[i].value.ui = 1U;
            strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );

491
            i++;
492
493
            strcpy ( desc->params[i].name, "mode" );
            desc->params[i].character  = 'm';
moret's avatar
moret committed
494
495
            desc->params[i].type = JackDriverParamString;
            strcpy ( desc->params[i].value.str, "normal" );
moret's avatar
moret committed
496
            strcpy ( desc->params[i].short_desc, "Slow, Normal or Fast mode." );
moret's avatar
moret committed
497
            strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
498

499
500
501
502
503
504
505
506
507
508
            return desc;
        }

        EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
        {
            if ( SocketAPIInit() < 0 )
            {
                jack_error ( "Can't init Socket API, exiting..." );
                return NULL;
            }
moret's avatar
moret committed
509
510
            char multicast_ip[16];
            strcpy ( multicast_ip, DEFAULT_MULTICAST_IP );
511
512
513
514
            char name[JACK_CLIENT_NAME_SIZE];
            GetHostName ( name, JACK_CLIENT_NAME_SIZE );
            int udp_port = DEFAULT_PORT;
            int mtu = 1500;
515
            uint transport_sync = 1;
516
517
518
519
520
521
522
            jack_nframes_t period_size = 128;
            jack_nframes_t sample_rate = 48000;
            int audio_capture_ports = 2;
            int audio_playback_ports = 2;
            int midi_input_ports = 0;
            int midi_output_ports = 0;
            bool monitor = false;
523
            char network_mode = 'n';
524
525
526
527
528
529
530
531

            const JSList* node;
            const jack_driver_param_t* param;
            for ( node = params; node; node = jack_slist_next ( node ) )
            {
                param = ( const jack_driver_param_t* ) node->data;
                switch ( param->character )
                {
moret's avatar
moret committed
532
                    case 'a' :
moret's avatar
moret committed
533
                        strncpy ( multicast_ip, param->value.str, 15 );
moret's avatar
moret committed
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
                        break;
                    case 'p':
                        udp_port = param->value.ui;
                        break;
                    case 'M':
                        mtu = param->value.i;
                        break;
                    case 'C':
                        audio_capture_ports = param->value.i;
                        break;
                    case 'P':
                        audio_playback_ports = param->value.i;
                        break;
                    case 'i':
                        midi_input_ports = param->value.i;
                        break;
                    case 'o':
                        midi_output_ports = param->value.i;
                        break;
                    case 'n' :
                        strncpy ( name, param->value.str, JACK_CLIENT_NAME_SIZE );
                        break;
                    case 't' :
                        transport_sync = param->value.ui;
                        break;
559
                    case 'm' :
moret's avatar
moret committed
560
                        if ( strcmp ( param->value.str, "normal" ) == 0 )
moret's avatar
moret committed
561
                            network_mode = 'n';
moret's avatar
moret committed
562
563
                        else if ( strcmp ( param->value.str, "slow" ) == 0 )
                            network_mode = 's';
moret's avatar
moret committed
564
565
                        else if ( strcmp ( param->value.str, "fast" ) == 0 )
                            network_mode = 'f';
moret's avatar
moret committed
566
                        break;
567
568
569
570
571
                }
            }

            Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
                new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
572
                                          midi_input_ports, midi_output_ports, name, transport_sync, network_mode ) );
573
574
575
576
577
578
579
            if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports,
                                monitor, "from_master_", "to_master_", 0, 0 ) == 0 )
                return driver;

            delete driver;
            return NULL;
        }
sletz's avatar
sletz committed
580
581

#ifdef __cplusplus
582
    }
sletz's avatar
sletz committed
583
584
#endif
}