2 Copyright (C) 2001 Paul Davis
3 Copyright (C) 2008 Romain Moret at Grame
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "JackNetDriver.h"
21 #include "JackEngineControl.h"
22 #include "JackGraphManager.h"
23 #include "JackWaitThreadedDriver.h"
30 JackNetDriver::JackNetDriver ( const char* name
, const char* alias
, JackLockedEngine
* engine
, JackSynchro
* table
,
31 const char* ip
, int port
, int mtu
, int midi_input_ports
, int midi_output_ports
,
32 char* net_name
, uint transport_sync
, char network_mode
)
33 : JackAudioDriver ( name
, alias
, engine
, table
), JackNetSlaveInterface ( ip
, port
)
35 jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip
, port
);
37 // Use the hostname if no name parameter was given
38 if ( strcmp ( net_name
, "" ) == 0 )
39 GetHostName ( net_name
, JACK_CLIENT_NAME_SIZE
);
42 fParams
.fSendMidiChannels
= midi_input_ports
;
43 fParams
.fReturnMidiChannels
= midi_output_ports
;
44 strcpy ( fParams
.fName
, net_name
);
45 fSocket
.GetName ( fParams
.fSlaveNetName
);
46 fParams
.fTransportSync
= transport_sync
;
47 fParams
.fNetworkMode
= network_mode
;
48 fSendTransportData
.fState
= -1;
49 fReturnTransportData
.fState
= -1;
50 fLastTransportState
= -1;
51 fLastTimebaseMaster
= -1;
52 fMidiCapturePortList
= NULL
;
53 fMidiPlaybackPortList
= NULL
;
59 JackNetDriver::~JackNetDriver()
61 delete[] fMidiCapturePortList
;
62 delete[] fMidiPlaybackPortList
;
68 //open, close, attach and detach------------------------------------------------------
69 int JackNetDriver::Open ( jack_nframes_t buffer_size
, jack_nframes_t samplerate
, bool capturing
, bool playing
,
70 int inchannels
, int outchannels
, bool monitor
,
71 const char* capture_driver_name
, const char* playback_driver_name
,
72 jack_nframes_t capture_latency
, jack_nframes_t playback_latency
)
74 if ( JackAudioDriver::Open ( buffer_size
,
84 playback_latency
) == 0 )
86 fEngineControl
->fPeriod
= 0;
87 fEngineControl
->fComputation
= 500 * 1000;
88 fEngineControl
->fConstraint
= 500 * 1000;
97 int JackNetDriver::Close()
104 return JackDriver::Close();
107 // Attach and Detach are defined as empty methods: port allocation is done when driver actually start (that is in Init)
108 int JackNetDriver::Attach()
113 int JackNetDriver::Detach()
118 //init and restart--------------------------------------------------------------------
120 JackNetDriver is wrapped in a JackWaitThreadedDriver decorator that behaves
121 as a "dummy driver, until Init method returns.
124 bool JackNetDriver::Init()
126 jack_log ( "JackNetDriver::Init()" );
128 //new loading, but existing socket, restart the driver
129 if (fSocket
.IsSocket()) {
130 jack_info( "Restarting driver..." );
134 //set the parameters to send
135 fParams
.fSendAudioChannels
= fCaptureChannels
;
136 fParams
.fReturnAudioChannels
= fPlaybackChannels
;
137 fParams
.fSlaveSyncMode
= fEngineControl
->fSyncMode
;
139 //display some additional infos
140 jack_info ( "NetDriver started in %s mode %s Master's transport sync.",
141 ( fParams
.fSlaveSyncMode
) ? "sync" : "async", ( fParams
.fTransportSync
) ? "with" : "without" );
144 if ( !JackNetSlaveInterface::Init() )
147 //set global parameters
150 //allocate midi ports lists
151 fMidiCapturePortList
= new jack_port_id_t
[fParams
.fSendMidiChannels
];
152 fMidiPlaybackPortList
= new jack_port_id_t
[fParams
.fReturnMidiChannels
];
153 assert ( fMidiCapturePortList
);
154 assert ( fMidiPlaybackPortList
);
156 //register jack ports
157 if ( AllocPorts() != 0 )
159 jack_error ( "Can't allocate ports." );
163 //init done, display parameters
164 SessionParamsDisplay ( &fParams
);
170 plot_name
= string ( fParams
.fName
);
171 plot_name
+= string ( "_slave" );
172 plot_name
+= ( fEngineControl
->fSyncMode
) ? string ( "_sync" ) : string ( "_async" );
173 switch ( fParams
.fNetworkMode
)
176 plot_name
+= string ( "_slow" );
180 plot_name
+= string ( "_normal" );
184 plot_name
+= string ( "_fast" );
187 fNetTimeMon
= new JackGnuPlotMonitor
<float> ( 128, 5, plot_name
);
188 string net_time_mon_fields
[] =
190 string ( "sync decoded" ),
191 string ( "end of read" ),
192 string ( "start of write" ),
193 string ( "sync send" ),
194 string ( "end of write" )
196 string net_time_mon_options
[] =
198 string ( "set xlabel \"audio cycles\"" ),
199 string ( "set ylabel \"% of audio cycle\"" )
201 fNetTimeMon
->SetPlotFile ( net_time_mon_options
, 2, net_time_mon_fields
, 5 );
203 //driver parametering
204 JackAudioDriver::SetBufferSize ( fParams
.fPeriodSize
);
205 JackAudioDriver::SetSampleRate ( fParams
.fSampleRate
);
207 JackDriver::NotifyBufferSize ( fParams
.fPeriodSize
);
208 JackDriver::NotifySampleRate ( fParams
.fSampleRate
);
210 //transport engine parametering
211 fEngineControl
->fTransport
.SetNetworkSync ( true );
215 void JackNetDriver::FreeAll()
221 delete fNetAudioCaptureBuffer
;
222 delete fNetAudioPlaybackBuffer
;
223 delete fNetMidiCaptureBuffer
;
224 delete fNetMidiPlaybackBuffer
;
225 delete[] fMidiCapturePortList
;
226 delete[] fMidiPlaybackPortList
;
230 fNetAudioCaptureBuffer
= NULL
;
231 fNetAudioPlaybackBuffer
= NULL
;
232 fNetMidiCaptureBuffer
= NULL
;
233 fNetMidiPlaybackBuffer
= NULL
;
234 fMidiCapturePortList
= NULL
;
235 fMidiPlaybackPortList
= NULL
;
243 //jack ports and buffers--------------------------------------------------------------
244 int JackNetDriver::AllocPorts()
246 jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl
->fBufferSize
, fEngineControl
->fSampleRate
);
249 jack_port_id_t port_id
;
250 char name
[JACK_CLIENT_NAME_SIZE
+ JACK_PORT_NAME_SIZE
];
251 char alias
[JACK_CLIENT_NAME_SIZE
+ JACK_PORT_NAME_SIZE
];
252 unsigned long port_flags
;
253 int audio_port_index
;
254 uint midi_port_index
;
257 port_flags
= JackPortIsOutput
| JackPortIsPhysical
| JackPortIsTerminal
;
258 for ( audio_port_index
= 0; audio_port_index
< fCaptureChannels
; audio_port_index
++ )
260 snprintf ( alias
, sizeof ( alias
) - 1, "%s:%s:out%d", fAliasName
, fCaptureDriverName
, audio_port_index
+ 1 );
261 snprintf ( name
, sizeof ( name
) - 1, "%s:capture_%d", fClientControl
.fName
, audio_port_index
+ 1 );
262 if ( ( port_id
= fGraphManager
->AllocatePort ( fClientControl
.fRefNum
, name
, JACK_DEFAULT_AUDIO_TYPE
,
263 static_cast<JackPortFlags
> ( port_flags
), fEngineControl
->fBufferSize
) ) == NO_PORT
)
265 jack_error ( "driver: cannot register port for %s", name
);
268 port
= fGraphManager
->GetPort ( port_id
);
269 port
->SetAlias ( alias
);
271 port
->SetLatency ( fEngineControl
->fBufferSize
);
272 fCapturePortList
[audio_port_index
] = port_id
;
273 jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index
, port_id
, port
->GetLatency() );
275 port_flags
= JackPortIsInput
| JackPortIsPhysical
| JackPortIsTerminal
;
276 for ( audio_port_index
= 0; audio_port_index
< fPlaybackChannels
; audio_port_index
++ )
278 snprintf ( alias
, sizeof ( alias
) - 1, "%s:%s:in%d", fAliasName
, fPlaybackDriverName
, audio_port_index
+ 1 );
279 snprintf ( name
, sizeof ( name
) - 1, "%s:playback_%d",fClientControl
.fName
, audio_port_index
+ 1 );
280 if ( ( port_id
= fGraphManager
->AllocatePort ( fClientControl
.fRefNum
, name
, JACK_DEFAULT_AUDIO_TYPE
,
281 static_cast<JackPortFlags
> ( port_flags
), fEngineControl
->fBufferSize
) ) == NO_PORT
)
283 jack_error ( "driver: cannot register port for %s", name
);
286 port
= fGraphManager
->GetPort ( port_id
);
287 port
->SetAlias ( alias
);
289 switch ( fParams
.fNetworkMode
)
292 port
->SetLatency ( ( fEngineControl
->fSyncMode
) ? 0 : fEngineControl
->fBufferSize
);
295 port
->SetLatency ( fEngineControl
->fBufferSize
+ ( fEngineControl
->fSyncMode
) ? 0 : fEngineControl
->fBufferSize
);
298 port
->SetLatency ( 2 * fEngineControl
->fBufferSize
+ ( fEngineControl
->fSyncMode
) ? 0 : fEngineControl
->fBufferSize
);
301 fPlaybackPortList
[audio_port_index
] = port_id
;
302 jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index
, port_id
, port
->GetLatency() );
305 port_flags
= JackPortIsOutput
| JackPortIsPhysical
| JackPortIsTerminal
;
306 for ( midi_port_index
= 0; midi_port_index
< fParams
.fSendMidiChannels
; midi_port_index
++ )
308 snprintf ( alias
, sizeof ( alias
) - 1, "%s:%s:out%d", fAliasName
, fCaptureDriverName
, midi_port_index
+ 1 );
309 snprintf ( name
, sizeof ( name
) - 1, "%s:midi_capture_%d", fClientControl
.fName
, midi_port_index
+ 1 );
310 if ( ( port_id
= fGraphManager
->AllocatePort ( fClientControl
.fRefNum
, name
, JACK_DEFAULT_MIDI_TYPE
,
311 static_cast<JackPortFlags
> ( port_flags
), fEngineControl
->fBufferSize
) ) == NO_PORT
)
313 jack_error ( "driver: cannot register port for %s", name
);
316 port
= fGraphManager
->GetPort ( port_id
);
318 port
->SetLatency ( fEngineControl
->fBufferSize
);
319 fMidiCapturePortList
[midi_port_index
] = port_id
;
320 jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index
, port_id
, port
->GetLatency() );
323 port_flags
= JackPortIsInput
| JackPortIsPhysical
| JackPortIsTerminal
;
324 for ( midi_port_index
= 0; midi_port_index
< fParams
.fReturnMidiChannels
; midi_port_index
++ )
326 snprintf ( alias
, sizeof ( alias
) - 1, "%s:%s:in%d", fAliasName
, fPlaybackDriverName
, midi_port_index
+ 1 );
327 snprintf ( name
, sizeof ( name
) - 1, "%s:midi_playback_%d", fClientControl
.fName
, midi_port_index
+ 1 );
328 if ( ( port_id
= fGraphManager
->AllocatePort ( fClientControl
.fRefNum
, name
, JACK_DEFAULT_MIDI_TYPE
,
329 static_cast<JackPortFlags
> ( port_flags
), fEngineControl
->fBufferSize
) ) == NO_PORT
)
331 jack_error ( "driver: cannot register port for %s", name
);
334 port
= fGraphManager
->GetPort ( port_id
);
336 switch ( fParams
.fNetworkMode
)
339 port
->SetLatency ( ( fEngineControl
->fSyncMode
) ? 0 : fEngineControl
->fBufferSize
);
342 port
->SetLatency ( fEngineControl
->fBufferSize
+ ( fEngineControl
->fSyncMode
) ? 0 : fEngineControl
->fBufferSize
) ;
345 port
->SetLatency ( 2 * fEngineControl
->fBufferSize
+ ( fEngineControl
->fSyncMode
) ? 0 : fEngineControl
->fBufferSize
);
348 fMidiPlaybackPortList
[midi_port_index
] = port_id
;
349 jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index
, port_id
, port
->GetLatency() );
355 int JackNetDriver::FreePorts()
357 jack_log ( "JackNetDriver::FreePorts" );
359 int audio_port_index
;
360 uint midi_port_index
;
361 for ( audio_port_index
= 0; audio_port_index
< fCaptureChannels
; audio_port_index
++ )
362 if (fCapturePortList
[audio_port_index
] > 0)
363 fGraphManager
->ReleasePort ( fClientControl
.fRefNum
, fCapturePortList
[audio_port_index
] );
364 for ( audio_port_index
= 0; audio_port_index
< fPlaybackChannels
; audio_port_index
++ )
365 if (fPlaybackPortList
[audio_port_index
] > 0)
366 fGraphManager
->ReleasePort ( fClientControl
.fRefNum
, fPlaybackPortList
[audio_port_index
] );
367 for ( midi_port_index
= 0; midi_port_index
< fParams
.fSendMidiChannels
; midi_port_index
++ )
368 if (fMidiCapturePortList
[midi_port_index
] > 0)
369 fGraphManager
->ReleasePort ( fClientControl
.fRefNum
, fMidiCapturePortList
[midi_port_index
] );
370 for ( midi_port_index
= 0; midi_port_index
< fParams
.fReturnMidiChannels
; midi_port_index
++ )
371 if (fMidiPlaybackPortList
[midi_port_index
] > 0)
372 fGraphManager
->ReleasePort ( fClientControl
.fRefNum
, fMidiPlaybackPortList
[midi_port_index
] );
376 JackMidiBuffer
* JackNetDriver::GetMidiInputBuffer ( int port_index
)
378 return static_cast<JackMidiBuffer
*> ( fGraphManager
->GetBuffer ( fMidiCapturePortList
[port_index
], fEngineControl
->fBufferSize
) );
381 JackMidiBuffer
* JackNetDriver::GetMidiOutputBuffer ( int port_index
)
383 return static_cast<JackMidiBuffer
*> ( fGraphManager
->GetBuffer ( fMidiPlaybackPortList
[port_index
], fEngineControl
->fBufferSize
) );
386 //transport---------------------------------------------------------------------------
387 void JackNetDriver::DecodeTransportData()
389 //is there a new timebase master on the net master ?
390 // - release timebase master only if it's a non-conditional request
391 // - no change or no request : don't do anything
392 // - conditional request : don't change anything too, the master will know if this slave is actually the timebase master
395 if ( fSendTransportData
.fTimebaseMaster
== TIMEBASEMASTER
)
397 fEngineControl
->fTransport
.GetTimebaseMaster ( refnum
, conditional
);
399 fEngineControl
->fTransport
.ResetTimebase ( refnum
);
400 jack_info ( "The NetMaster is now the new timebase master." );
403 //is there a transport state change to handle ?
404 if ( fSendTransportData
.fNewState
&& ( fSendTransportData
.fState
!= fEngineControl
->fTransport
.GetState() ) )
407 switch ( fSendTransportData
.fState
)
409 case JackTransportStopped
:
410 fEngineControl
->fTransport
.SetCommand ( TransportCommandStop
);
411 jack_info ( "Master stops transport." );
414 case JackTransportStarting
:
415 fEngineControl
->fTransport
.RequestNewPos ( &fSendTransportData
.fPosition
);
416 fEngineControl
->fTransport
.SetCommand ( TransportCommandStart
);
417 jack_info ( "Master starts transport frame = %d", fSendTransportData
.fPosition
.frame
);
420 case JackTransportRolling
:
421 fEngineControl
->fTransport
.SetState ( JackTransportRolling
);
422 jack_info ( "Master is rolling." );
428 void JackNetDriver::EncodeTransportData()
430 //is there a timebase master change ?
433 fEngineControl
->fTransport
.GetTimebaseMaster ( refnum
, conditional
);
434 if ( refnum
!= fLastTimebaseMaster
)
436 //timebase master has released its function
439 fReturnTransportData
.fTimebaseMaster
= RELEASE_TIMEBASEMASTER
;
440 jack_info ( "Sending a timebase master release request." );
442 //there is a new timebase master
445 fReturnTransportData
.fTimebaseMaster
= ( conditional
) ? CONDITIONAL_TIMEBASEMASTER
: TIMEBASEMASTER
;
446 jack_info ( "Sending a %s timebase master request.", ( conditional
) ? "conditional" : "non-conditional" );
448 fLastTimebaseMaster
= refnum
;
451 fReturnTransportData
.fTimebaseMaster
= NO_CHANGE
;
453 //update transport state and position
454 fReturnTransportData
.fState
= fEngineControl
->fTransport
.Query ( &fReturnTransportData
.fPosition
);
456 //is it a new state (that the master need to know...) ?
457 fReturnTransportData
.fNewState
= ( ( fReturnTransportData
.fState
!= fLastTransportState
) &&
458 ( fReturnTransportData
.fState
!= fSendTransportData
.fState
) );
459 if ( fReturnTransportData
.fNewState
)
460 jack_info ( "Sending '%s'.", GetTransportState ( fReturnTransportData
.fState
) );
461 fLastTransportState
= fReturnTransportData
.fState
;
464 //driver processes--------------------------------------------------------------------
465 int JackNetDriver::Read()
467 uint midi_port_index
;
468 uint audio_port_index
;
471 for ( midi_port_index
= 0; midi_port_index
< fParams
.fSendMidiChannels
; midi_port_index
++ )
472 fNetMidiCaptureBuffer
->SetBuffer ( midi_port_index
, GetMidiInputBuffer ( midi_port_index
) );
473 for ( audio_port_index
= 0; audio_port_index
< fParams
.fSendAudioChannels
; audio_port_index
++ )
474 fNetAudioCaptureBuffer
->SetBuffer ( audio_port_index
, GetInputBuffer ( audio_port_index
) );
480 //receive sync (launch the cycle)
481 if ( SyncRecv() == SOCKET_ERROR
)
484 //take the time at the beginning of the cycle
485 JackDriver::CycleTakeBeginTime();
488 //if there is an error, don't return -1, it will skip Write() and the network error probably won't be identified
492 fNetTimeMon
->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst
) / ( float ) fEngineControl
->fPeriodUsecs
) * 100.f
);
494 //audio, midi or sync if driver is late
495 if ( DataRecv() == SOCKET_ERROR
)
499 fNetTimeMon
->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst
) / ( float ) fEngineControl
->fPeriodUsecs
) * 100.f
);
505 int JackNetDriver::Write()
507 uint midi_port_index
;
508 int audio_port_index
;
511 for ( midi_port_index
= 0; midi_port_index
< fParams
.fReturnMidiChannels
; midi_port_index
++ )
512 fNetMidiPlaybackBuffer
->SetBuffer ( midi_port_index
, GetMidiOutputBuffer ( midi_port_index
) );
513 for ( audio_port_index
= 0; audio_port_index
< fPlaybackChannels
; audio_port_index
++ )
514 fNetAudioPlaybackBuffer
->SetBuffer ( audio_port_index
, GetOutputBuffer ( audio_port_index
) );
517 fNetTimeMon
->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst
) / ( float ) fEngineControl
->fPeriodUsecs
) * 100.f
);
524 if ( SyncSend() == SOCKET_ERROR
)
528 fNetTimeMon
->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst
) / ( float ) fEngineControl
->fPeriodUsecs
) * 100.f
);
532 if ( DataSend() == SOCKET_ERROR
)
536 fNetTimeMon
->AddLast ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst
) / ( float ) fEngineControl
->fPeriodUsecs
) * 100.f
);
542 //driver loader-----------------------------------------------------------------------
548 SERVER_EXPORT jack_driver_desc_t
* driver_get_descriptor ()
550 jack_driver_desc_t
* desc
= ( jack_driver_desc_t
* ) calloc ( 1, sizeof ( jack_driver_desc_t
) );
552 strcpy ( desc
->name
, "net" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
553 strcpy ( desc
->desc
, "netjack slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
556 desc
->params
= ( jack_driver_param_desc_t
* ) calloc ( desc
->nparams
, sizeof ( jack_driver_param_desc_t
) );
559 strcpy ( desc
->params
[i
].name
, "multicast_ip" );
560 desc
->params
[i
].character
= 'a';
561 desc
->params
[i
].type
= JackDriverParamString
;
562 strcpy ( desc
->params
[i
].value
.str
, DEFAULT_MULTICAST_IP
);
563 strcpy ( desc
->params
[i
].short_desc
, "Multicast Address" );
564 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
567 strcpy ( desc
->params
[i
].name
, "udp_net_port" );
568 desc
->params
[i
].character
= 'p';
569 desc
->params
[i
].type
= JackDriverParamInt
;
570 desc
->params
[i
].value
.i
= DEFAULT_PORT
;
571 strcpy ( desc
->params
[i
].short_desc
, "UDP port" );
572 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
575 strcpy ( desc
->params
[i
].name
, "mtu" );
576 desc
->params
[i
].character
= 'M';
577 desc
->params
[i
].type
= JackDriverParamInt
;
578 desc
->params
[i
].value
.i
= DEFAULT_MTU
;
579 strcpy ( desc
->params
[i
].short_desc
, "MTU to the master" );
580 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
583 strcpy ( desc
->params
[i
].name
, "input_ports" );
584 desc
->params
[i
].character
= 'C';
585 desc
->params
[i
].type
= JackDriverParamInt
;
586 desc
->params
[i
].value
.i
= 2;
587 strcpy ( desc
->params
[i
].short_desc
, "Number of audio input ports" );
588 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
591 strcpy ( desc
->params
[i
].name
, "output_ports" );
592 desc
->params
[i
].character
= 'P';
593 desc
->params
[i
].type
= JackDriverParamInt
;
594 desc
->params
[i
].value
.i
= 2;
595 strcpy ( desc
->params
[i
].short_desc
, "Number of audio output ports" );
596 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
599 strcpy ( desc
->params
[i
].name
, "midi_in_ports" );
600 desc
->params
[i
].character
= 'i';
601 desc
->params
[i
].type
= JackDriverParamInt
;
602 desc
->params
[i
].value
.i
= 0;
603 strcpy ( desc
->params
[i
].short_desc
, "Number of midi input ports" );
604 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
607 strcpy ( desc
->params
[i
].name
, "midi_out_ports" );
608 desc
->params
[i
].character
= 'o';
609 desc
->params
[i
].type
= JackDriverParamUInt
;
610 desc
->params
[i
].value
.i
= 0;
611 strcpy ( desc
->params
[i
].short_desc
, "Number of midi output ports" );
612 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
615 strcpy ( desc
->params
[i
].name
, "client_name" );
616 desc
->params
[i
].character
= 'n';
617 desc
->params
[i
].type
= JackDriverParamString
;
618 strcpy ( desc
->params
[i
].value
.str
, "'hostname'" );
619 strcpy ( desc
->params
[i
].short_desc
, "Name of the jack client" );
620 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
623 strcpy ( desc
->params
[i
].name
, "transport_sync" );
624 desc
->params
[i
].character
= 't';
625 desc
->params
[i
].type
= JackDriverParamUInt
;
626 desc
->params
[i
].value
.ui
= 1U;
627 strcpy ( desc
->params
[i
].short_desc
, "Sync transport with master's" );
628 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
631 strcpy ( desc
->params
[i
].name
, "mode" );
632 desc
->params
[i
].character
= 'm';
633 desc
->params
[i
].type
= JackDriverParamString
;
634 strcpy ( desc
->params
[i
].value
.str
, "slow" );
635 strcpy ( desc
->params
[i
].short_desc
, "Slow, Normal or Fast mode." );
636 strcpy ( desc
->params
[i
].long_desc
, desc
->params
[i
].short_desc
);
641 SERVER_EXPORT
Jack::JackDriverClientInterface
* driver_initialize ( Jack::JackLockedEngine
* engine
, Jack::JackSynchro
* table
, const JSList
* params
)
643 char multicast_ip
[16];
644 strcpy ( multicast_ip
, DEFAULT_MULTICAST_IP
);
645 char net_name
[JACK_CLIENT_NAME_SIZE
+ 1];
646 int udp_port
= DEFAULT_PORT
;
647 int mtu
= DEFAULT_MTU
;
648 uint transport_sync
= 1;
649 jack_nframes_t period_size
= 128;
650 jack_nframes_t sample_rate
= 48000;
651 int audio_capture_ports
= 2;
652 int audio_playback_ports
= 2;
653 int midi_input_ports
= 0;
654 int midi_output_ports
= 0;
655 bool monitor
= false;
656 char network_mode
= 's';
658 const jack_driver_param_t
* param
;
662 for ( node
= params
; node
; node
= jack_slist_next ( node
) )
664 param
= ( const jack_driver_param_t
* ) node
->data
;
665 switch ( param
->character
)
668 strncpy ( multicast_ip
, param
->value
.str
, 15 );
671 udp_port
= param
->value
.ui
;
674 mtu
= param
->value
.i
;
677 audio_capture_ports
= param
->value
.i
;
680 audio_playback_ports
= param
->value
.i
;
683 midi_input_ports
= param
->value
.i
;
686 midi_output_ports
= param
->value
.i
;
689 strncpy ( net_name
, param
->value
.str
, JACK_CLIENT_NAME_SIZE
);
692 transport_sync
= param
->value
.ui
;
695 if ( strcmp ( param
->value
.str
, "normal" ) == 0 )
697 else if ( strcmp ( param
->value
.str
, "slow" ) == 0 )
699 else if ( strcmp ( param
->value
.str
, "fast" ) == 0 )
702 jack_error ( "Unknown network mode, using 'normal' mode." );
710 Jack::JackDriverClientInterface
* driver
=
711 new Jack::JackWaitThreadedDriver (
712 new Jack::JackNetDriver ( "system", "net_pcm", engine
, table
, multicast_ip
, udp_port
, mtu
,
713 midi_input_ports
, midi_output_ports
, net_name
, transport_sync
, network_mode
) );
714 if ( driver
->Open ( period_size
, sample_rate
, 1, 1, audio_capture_ports
, audio_playback_ports
,
715 monitor
, "from_master_", "to_master_", 0, 0 ) == 0 )