jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

594 lines
24KB

  1. /*
  2. Copyright (C) 2001 Paul Davis
  3. Copyright (C) 2008 Romain Moret at Grame
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. */
  16. #include "JackNetDriver.h"
  17. #include "JackEngineControl.h"
  18. #include "JackClientControl.h"
  19. #include "JackGraphManager.h"
  20. #include "JackDriverLoader.h"
  21. #include "JackThreadedDriver.h"
  22. #include "JackWaitThreadedDriver.h"
  23. #define DEFAULT_MULTICAST_IP "225.3.19.154"
  24. #define DEFAULT_PORT 19000
  25. using namespace std;
  26. namespace Jack
  27. {
  28. JackNetDriver::JackNetDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
  29. const char* ip, int port, int mtu, int midi_input_ports, int midi_output_ports,
  30. const char* net_name, uint transport_sync, char network_mode )
  31. : JackAudioDriver ( name, alias, engine, table ), JackNetSlaveInterface ( ip, port )
  32. {
  33. jack_log ( "JackNetDriver::JackNetDriver ip %s, port %d", ip, port );
  34. fMulticastIP = new char[strlen ( ip ) + 1];
  35. strcpy ( fMulticastIP, ip );
  36. fParams.fMtu = mtu;
  37. fParams.fSendMidiChannels = midi_input_ports;
  38. fParams.fReturnMidiChannels = midi_output_ports;
  39. strcpy ( fParams.fName, net_name );
  40. fSocket.GetName ( fParams.fSlaveNetName );
  41. fParams.fTransportSync = transport_sync;
  42. fParams.fNetworkMode = network_mode;
  43. #ifdef JACK_MONITOR
  44. fNetTimeMon = NULL;
  45. fCycleTimeMon = NULL;
  46. #endif
  47. }
  48. JackNetDriver::~JackNetDriver()
  49. {
  50. fSocket.Close();
  51. delete[] fMidiCapturePortList;
  52. delete[] fMidiPlaybackPortList;
  53. #ifdef JACK_MONITOR
  54. delete fNetTimeMon;
  55. delete fCycleTimeMon;
  56. #endif
  57. }
  58. //*************************************initialization***********************************************************************
  59. int JackNetDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing,
  60. int inchannels, int outchannels, bool monitor,
  61. const char* capture_driver_name, const char* playback_driver_name,
  62. jack_nframes_t capture_latency, jack_nframes_t playback_latency )
  63. {
  64. int res = JackAudioDriver::Open ( buffer_size, samplerate, capturing, playing, inchannels, outchannels, monitor,
  65. capture_driver_name, playback_driver_name, capture_latency, playback_latency );
  66. fEngineControl->fPeriod = 0;
  67. fEngineControl->fComputation = 500 * 1000;
  68. fEngineControl->fConstraint = 500 * 1000;
  69. return res;
  70. }
  71. #ifdef JACK_MONITOR
  72. int JackNetDriver::Close()
  73. {
  74. if ( fNetTimeMon )
  75. fNetTimeMon->Save();
  76. if ( fCycleTimeMon )
  77. fCycleTimeMon->Save();
  78. return JackDriver::Close();
  79. }
  80. #endif
  81. int JackNetDriver::Attach()
  82. {
  83. return 0;
  84. }
  85. int JackNetDriver::Detach()
  86. {
  87. return 0;
  88. }
  89. bool JackNetDriver::Init()
  90. {
  91. jack_log ( "JackNetDriver::Init()" );
  92. //new loading, but existing socket, restart the driver
  93. if ( fSocket.IsSocket() )
  94. Restart();
  95. //set the parameters to send
  96. fParams.fSendAudioChannels = fCaptureChannels;
  97. fParams.fReturnAudioChannels = fPlaybackChannels;
  98. fParams.fSlaveSyncMode = fEngineControl->fSyncMode;
  99. //display some additional infos
  100. jack_info ( "NetAdapter started in %s mode %s Master's transport sync.",
  101. ( fParams.fSlaveSyncMode ) ? "sync" : "async", ( fParams.fTransportSync ) ? "with" : "without" );
  102. if ( !JackNetSlaveInterface::Init() )
  103. return false;;
  104. //driver parametering
  105. JackAudioDriver::SetBufferSize ( fParams.fPeriodSize );
  106. JackAudioDriver::SetSampleRate ( fParams.fSampleRate );
  107. JackDriver::NotifyBufferSize ( fParams.fPeriodSize );
  108. JackDriver::NotifySampleRate ( fParams.fSampleRate );
  109. //allocate midi ports lists
  110. fMidiCapturePortList = new jack_port_id_t [fParams.fSendMidiChannels];
  111. fMidiPlaybackPortList = new jack_port_id_t [fParams.fReturnMidiChannels];
  112. //register jack ports
  113. if ( AllocPorts() != 0 )
  114. {
  115. jack_error ( "Can't allocate ports." );
  116. return false;
  117. }
  118. //set global paramaters
  119. SetParams();
  120. //init done, display parameters
  121. SessionParamsDisplay ( &fParams );
  122. //monitor
  123. #ifdef JACK_MONITOR
  124. string plot_name;
  125. //NetTimeMon
  126. plot_name = string ( fParams.fName );
  127. plot_name += string ( "_slave" );
  128. plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" );
  129. plot_name += ( fParams.fNetworkMode == 'f' ) ? string ( "_fast" ) : string ( "_normal" );
  130. fNetTimeMon = new JackGnuPlotMonitor<float> ( 128, 4, plot_name );
  131. string net_time_mon_fields[] =
  132. {
  133. string ( "end of read" ),
  134. string ( "start of write" ),
  135. string ( "sync send" ),
  136. string ( "end of write" )
  137. };
  138. string net_time_mon_options[] =
  139. {
  140. string ( "set xlabel \"audio cycles\"" ),
  141. string ( "set ylabel \"% of audio cycle\"" )
  142. };
  143. fNetTimeMon->SetPlotFile ( net_time_mon_options, 2, net_time_mon_fields, 4 );
  144. //CycleTimeMon
  145. plot_name.clear();
  146. plot_name = string ( fParams.fName );
  147. plot_name += string ( "_slave_cycle_duration" );
  148. plot_name += ( fEngineControl->fSyncMode ) ? string ( "_sync" ) : string ( "_async" );
  149. plot_name += ( fParams.fNetworkMode == 'f' ) ? string ( "_fast" ) : string ( "_normal" );
  150. fCycleTimeMon = new JackGnuPlotMonitor<jack_time_t> ( 2048, 1, plot_name );
  151. string cycle_time_mon_field = string ( "cycle duration" );
  152. string cycle_time_mon_options[] =
  153. {
  154. string ( "set xlabel \"audio cycles\"" ),
  155. string ( "set ylabel \"usecs\"" )
  156. };
  157. fCycleTimeMon->SetPlotFile ( cycle_time_mon_options, 2, &cycle_time_mon_field, 1 );
  158. fLastCycleBeginDate = GetMicroSeconds();
  159. #endif
  160. return true;
  161. }
  162. void JackNetDriver::Restart()
  163. {
  164. jack_log ( "JackNetDriver::Restart" );
  165. jack_info ( "Restarting driver..." );
  166. delete[] fTxBuffer;
  167. fTxBuffer = NULL;
  168. delete[] fRxBuffer;
  169. fRxBuffer = NULL;
  170. delete fNetAudioCaptureBuffer;
  171. fNetAudioCaptureBuffer = NULL;
  172. delete fNetAudioPlaybackBuffer;
  173. fNetAudioPlaybackBuffer = NULL;
  174. delete fNetMidiCaptureBuffer;
  175. fNetMidiCaptureBuffer = NULL;
  176. delete fNetMidiPlaybackBuffer;
  177. fNetMidiPlaybackBuffer = NULL;
  178. FreePorts();
  179. delete[] fMidiCapturePortList;
  180. fMidiCapturePortList = NULL;
  181. delete[] fMidiPlaybackPortList;
  182. fMidiPlaybackPortList = NULL;
  183. #ifdef JACK_MONITOR
  184. delete fNetTimeMon;
  185. fNetTimeMon = NULL;
  186. delete fCycleTimeMon;
  187. fCycleTimeMon = NULL;
  188. #endif
  189. }
  190. int JackNetDriver::AllocPorts()
  191. {
  192. jack_log ( "JackNetDriver::AllocPorts fBufferSize = %ld fSampleRate = %ld", fEngineControl->fBufferSize, fEngineControl->fSampleRate );
  193. JackPort* port;
  194. jack_port_id_t port_id;
  195. char name[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  196. char alias[JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE];
  197. unsigned long port_flags;
  198. int audio_port_index;
  199. uint midi_port_index;
  200. //audio
  201. port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
  202. for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
  203. {
  204. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, audio_port_index + 1 );
  205. snprintf ( name, sizeof ( name ) - 1, "%s:capture_%d", fClientControl.fName, audio_port_index + 1 );
  206. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
  207. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  208. {
  209. jack_error ( "driver: cannot register port for %s", name );
  210. return -1;
  211. }
  212. port = fGraphManager->GetPort ( port_id );
  213. port->SetAlias ( alias );
  214. port->SetLatency ( fEngineControl->fBufferSize );
  215. fCapturePortList[audio_port_index] = port_id;
  216. jack_log ( "JackNetDriver::AllocPorts() fCapturePortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
  217. }
  218. port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
  219. for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
  220. {
  221. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, audio_port_index + 1 );
  222. snprintf ( name, sizeof ( name ) - 1, "%s:playback_%d",fClientControl.fName, audio_port_index + 1 );
  223. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_AUDIO_TYPE,
  224. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  225. {
  226. jack_error ( "driver: cannot register port for %s", name );
  227. return -1;
  228. }
  229. port = fGraphManager->GetPort ( port_id );
  230. port->SetAlias ( alias );
  231. port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
  232. fPlaybackPortList[audio_port_index] = port_id;
  233. jack_log ( "JackNetDriver::AllocPorts() fPlaybackPortList[%d] audio_port_index = %ld fPortLatency = %ld", audio_port_index, port_id, port->GetLatency() );
  234. }
  235. //midi
  236. port_flags = JackPortIsOutput | JackPortIsPhysical | JackPortIsTerminal;
  237. for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
  238. {
  239. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:out%d", fAliasName, fCaptureDriverName, midi_port_index + 1 );
  240. snprintf ( name, sizeof ( name ) - 1, "%s:midi_capture_%d", fClientControl.fName, midi_port_index + 1 );
  241. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
  242. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  243. {
  244. jack_error ( "driver: cannot register port for %s", name );
  245. return -1;
  246. }
  247. port = fGraphManager->GetPort ( port_id );
  248. port->SetLatency ( fEngineControl->fBufferSize );
  249. fMidiCapturePortList[midi_port_index] = port_id;
  250. jack_log ( "JackNetDriver::AllocPorts() fMidiCapturePortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
  251. }
  252. port_flags = JackPortIsInput | JackPortIsPhysical | JackPortIsTerminal;
  253. for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
  254. {
  255. snprintf ( alias, sizeof ( alias ) - 1, "%s:%s:in%d", fAliasName, fPlaybackDriverName, midi_port_index + 1 );
  256. snprintf ( name, sizeof ( name ) - 1, "%s:midi_playback_%d", fClientControl.fName, midi_port_index + 1 );
  257. if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, name, JACK_DEFAULT_MIDI_TYPE,
  258. static_cast<JackPortFlags> ( port_flags ), fEngineControl->fBufferSize ) ) == NO_PORT )
  259. {
  260. jack_error ( "driver: cannot register port for %s", name );
  261. return -1;
  262. }
  263. port = fGraphManager->GetPort ( port_id );
  264. port->SetLatency ( ( fParams.fNetworkMode == 'f' ) ? 0 : fEngineControl->fBufferSize + ( ( fEngineControl->fSyncMode ) ? 0 : fEngineControl->fBufferSize ) );
  265. fMidiPlaybackPortList[midi_port_index] = port_id;
  266. jack_log ( "JackNetDriver::AllocPorts() fMidiPlaybackPortList[%d] midi_port_index = %ld fPortLatency = %ld", midi_port_index, port_id, port->GetLatency() );
  267. }
  268. return 0;
  269. }
  270. int JackNetDriver::FreePorts()
  271. {
  272. jack_log ( "JackNetDriver::FreePorts" );
  273. int audio_port_index;
  274. uint midi_port_index;
  275. for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
  276. fGraphManager->ReleasePort ( fClientControl.fRefNum, fCapturePortList[audio_port_index] );
  277. for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
  278. fGraphManager->ReleasePort ( fClientControl.fRefNum, fPlaybackPortList[audio_port_index] );
  279. for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
  280. fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiCapturePortList[midi_port_index] );
  281. for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
  282. fGraphManager->ReleasePort ( fClientControl.fRefNum, fMidiPlaybackPortList[midi_port_index] );
  283. return 0;
  284. }
  285. JackMidiBuffer* JackNetDriver::GetMidiInputBuffer ( int port_index )
  286. {
  287. return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiCapturePortList[port_index], fEngineControl->fBufferSize ) );
  288. }
  289. JackMidiBuffer* JackNetDriver::GetMidiOutputBuffer ( int port_index )
  290. {
  291. return static_cast<JackMidiBuffer*> ( fGraphManager->GetBuffer ( fMidiPlaybackPortList[port_index], fEngineControl->fBufferSize ) );
  292. }
  293. int JackNetDriver::SetSyncPacket()
  294. {
  295. if ( fParams.fTransportSync )
  296. {
  297. //set the TransportData
  298. //copy to TxBuffer
  299. memcpy ( fTxData, &fTransportData, sizeof ( net_transport_data_t ) );
  300. }
  301. return 0;
  302. }
  303. //*************************************process************************************************************************
  304. int JackNetDriver::Read()
  305. {
  306. uint midi_port_index;
  307. int audio_port_index;
  308. //buffers
  309. for ( midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++ )
  310. fNetMidiCaptureBuffer->SetBuffer ( midi_port_index, GetMidiInputBuffer ( midi_port_index ) );
  311. for ( audio_port_index = 0; audio_port_index < fCaptureChannels; audio_port_index++ )
  312. fNetAudioCaptureBuffer->SetBuffer ( audio_port_index, GetInputBuffer ( audio_port_index ) );
  313. #ifdef JACK_MONITOR
  314. fNetTimeMon->New();
  315. #endif
  316. //receive sync (launch the cycle)
  317. if ( SyncRecv() == SOCKET_ERROR )
  318. return 0;
  319. //take the time at the beginning of the cycle
  320. JackDriver::CycleTakeBeginTime();
  321. #ifdef JACK_MONITOR
  322. fCycleTimeMon->AddNew ( JackDriver::fBeginDateUst - fLastCycleBeginDate );
  323. fCycleTimeMon->Write();
  324. fLastCycleBeginDate = JackDriver::fBeginDateUst;
  325. #endif
  326. //audio, midi or sync if driver is late
  327. if ( DataRecv() == SOCKET_ERROR )
  328. return SOCKET_ERROR;
  329. #ifdef JACK_MONITOR
  330. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  331. #endif
  332. return 0;
  333. }
  334. int JackNetDriver::Write()
  335. {
  336. uint midi_port_index;
  337. int audio_port_index;
  338. //buffers
  339. for ( midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++ )
  340. fNetMidiPlaybackBuffer->SetBuffer ( midi_port_index, GetMidiOutputBuffer ( midi_port_index ) );
  341. for ( audio_port_index = 0; audio_port_index < fPlaybackChannels; audio_port_index++ )
  342. fNetAudioPlaybackBuffer->SetBuffer ( audio_port_index, GetOutputBuffer ( audio_port_index ) );
  343. #ifdef JACK_MONITOR
  344. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  345. #endif
  346. //sync
  347. memset ( fTxData, 0, fPayloadSize );
  348. SetSyncPacket();
  349. //send sync
  350. if ( SyncSend() == SOCKET_ERROR )
  351. return SOCKET_ERROR;
  352. #ifdef JACK_MONITOR
  353. fNetTimeMon->Add ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  354. #endif
  355. //send data
  356. if ( DataSend() == SOCKET_ERROR )
  357. return SOCKET_ERROR;
  358. #ifdef JACK_MONITOR
  359. fNetTimeMon->AddLast ( ( ( float ) ( GetMicroSeconds() - JackDriver::fBeginDateUst ) / ( float ) fEngineControl->fPeriodUsecs ) * 100.f );
  360. #endif
  361. return 0;
  362. }
  363. //*************************************loader*******************************************************
  364. #ifdef __cplusplus
  365. extern "C"
  366. {
  367. #endif
  368. EXPORT jack_driver_desc_t* driver_get_descriptor ()
  369. {
  370. jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
  371. strcpy ( desc->name, "net" );
  372. desc->nparams = 10;
  373. desc->params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
  374. int i = 0;
  375. strcpy ( desc->params[i].name, "multicast_ip" );
  376. desc->params[i].character = 'a';
  377. desc->params[i].type = JackDriverParamString;
  378. strcpy ( desc->params[i].value.str, DEFAULT_MULTICAST_IP );
  379. strcpy ( desc->params[i].short_desc, "Multicast Address" );
  380. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  381. i++;
  382. strcpy ( desc->params[i].name, "udp_net_port" );
  383. desc->params[i].character = 'p';
  384. desc->params[i].type = JackDriverParamInt;
  385. desc->params[i].value.i = 19000;
  386. strcpy ( desc->params[i].short_desc, "UDP port" );
  387. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  388. i++;
  389. strcpy ( desc->params[i].name, "mtu" );
  390. desc->params[i].character = 'M';
  391. desc->params[i].type = JackDriverParamInt;
  392. desc->params[i].value.i = 1500;
  393. strcpy ( desc->params[i].short_desc, "MTU to the master" );
  394. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  395. i++;
  396. strcpy ( desc->params[i].name, "input_ports" );
  397. desc->params[i].character = 'C';
  398. desc->params[i].type = JackDriverParamInt;
  399. desc->params[i].value.i = 2;
  400. strcpy ( desc->params[i].short_desc, "Number of audio input ports" );
  401. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  402. i++;
  403. strcpy ( desc->params[i].name, "output_ports" );
  404. desc->params[i].character = 'P';
  405. desc->params[i].type = JackDriverParamInt;
  406. desc->params[i].value.i = 2;
  407. strcpy ( desc->params[i].short_desc, "Number of audio output ports" );
  408. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  409. i++;
  410. strcpy ( desc->params[i].name, "midi_in_ports" );
  411. desc->params[i].character = 'i';
  412. desc->params[i].type = JackDriverParamInt;
  413. desc->params[i].value.i = 0;
  414. strcpy ( desc->params[i].short_desc, "Number of midi input ports" );
  415. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  416. i++;
  417. strcpy ( desc->params[i].name, "midi_out_ports" );
  418. desc->params[i].character = 'o';
  419. desc->params[i].type = JackDriverParamUInt;
  420. desc->params[i].value.i = 0;
  421. strcpy ( desc->params[i].short_desc, "Number of midi output ports" );
  422. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  423. i++;
  424. strcpy ( desc->params[i].name, "client_name" );
  425. desc->params[i].character = 'n';
  426. desc->params[i].type = JackDriverParamString;
  427. strcpy ( desc->params[i].value.str, "'hostname'" );
  428. strcpy ( desc->params[i].short_desc, "Name of the jack client" );
  429. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  430. i++;
  431. strcpy ( desc->params[i].name, "transport_sync" );
  432. desc->params[i].character = 't';
  433. desc->params[i].type = JackDriverParamUInt;
  434. desc->params[i].value.ui = 1U;
  435. strcpy ( desc->params[i].short_desc, "Sync transport with master's" );
  436. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  437. i++;
  438. strcpy ( desc->params[i].name, "fast_mode" );
  439. desc->params[i].character = 'f';
  440. desc->params[i].type = JackDriverParamString;
  441. strcpy ( desc->params[i].value.str, "" );
  442. strcpy ( desc->params[i].short_desc, "Fast mode allows a zero latency transmission." );
  443. strcpy ( desc->params[i].long_desc, desc->params[i].short_desc );
  444. return desc;
  445. }
  446. EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
  447. {
  448. if ( SocketAPIInit() < 0 )
  449. {
  450. jack_error ( "Can't init Socket API, exiting..." );
  451. return NULL;
  452. }
  453. const char* multicast_ip = DEFAULT_MULTICAST_IP;
  454. char name[JACK_CLIENT_NAME_SIZE];
  455. GetHostName ( name, JACK_CLIENT_NAME_SIZE );
  456. int udp_port = DEFAULT_PORT;
  457. int mtu = 1500;
  458. uint transport_sync = 1;
  459. jack_nframes_t period_size = 128;
  460. jack_nframes_t sample_rate = 48000;
  461. int audio_capture_ports = 2;
  462. int audio_playback_ports = 2;
  463. int midi_input_ports = 0;
  464. int midi_output_ports = 0;
  465. bool monitor = false;
  466. char network_mode = 'n';
  467. const JSList* node;
  468. const jack_driver_param_t* param;
  469. for ( node = params; node; node = jack_slist_next ( node ) )
  470. {
  471. param = ( const jack_driver_param_t* ) node->data;
  472. switch ( param->character )
  473. {
  474. case 'a' :
  475. multicast_ip = strdup ( param->value.str );
  476. break;
  477. case 'p':
  478. udp_port = param->value.ui;
  479. break;
  480. case 'M':
  481. mtu = param->value.i;
  482. break;
  483. case 'C':
  484. audio_capture_ports = param->value.i;
  485. break;
  486. case 'P':
  487. audio_playback_ports = param->value.i;
  488. break;
  489. case 'i':
  490. midi_input_ports = param->value.i;
  491. break;
  492. case 'o':
  493. midi_output_ports = param->value.i;
  494. break;
  495. case 'n' :
  496. strncpy ( name, param->value.str, JACK_CLIENT_NAME_SIZE );
  497. break;
  498. case 't' :
  499. transport_sync = param->value.ui;
  500. break;
  501. case 'f' :
  502. network_mode = 'f';
  503. break;
  504. }
  505. }
  506. Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
  507. new Jack::JackNetDriver ( "system", "net_pcm", engine, table, multicast_ip, udp_port, mtu,
  508. midi_input_ports, midi_output_ports, name, transport_sync, network_mode ) );
  509. if ( driver->Open ( period_size, sample_rate, 1, 1, audio_capture_ports, audio_playback_ports,
  510. monitor, "from_master_", "to_master_", 0, 0 ) == 0 )
  511. return driver;
  512. delete driver;
  513. return NULL;
  514. }
  515. #ifdef __cplusplus
  516. }
  517. #endif
  518. }