Jack2  1.9.12
JackNetManager.cpp
1 /*
2 Copyright(C) 2008-2011 Romain Moret at Grame
3 
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 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 #include "JackNetManager.h"
20 #include "JackArgParser.h"
21 #include "JackServerGlobals.h"
22 #include "JackLockedEngine.h"
23 #include "thread.h"
24 
25 using namespace std;
26 
27 namespace Jack
28 {
29 //JackNetMaster******************************************************************************************************
30 
31  JackNetMaster::JackNetMaster(JackNetSocket& socket, session_params_t& params, const char* multicast_ip)
32  : JackNetMasterInterface(params, socket, multicast_ip)
33  {
34  jack_log("JackNetMaster::JackNetMaster");
35 
36  //settings
37  fName = const_cast<char*>(fParams.fName);
38  fClient = NULL;
39  fSendTransportData.fState = -1;
40  fReturnTransportData.fState = -1;
41  fLastTransportState = -1;
42  int port_index;
43 
44  //jack audio ports
45  fAudioCapturePorts = new jack_port_t* [fParams.fSendAudioChannels];
46  for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) {
47  fAudioCapturePorts[port_index] = NULL;
48  }
49 
50  fAudioPlaybackPorts = new jack_port_t* [fParams.fReturnAudioChannels];
51  for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) {
52  fAudioPlaybackPorts[port_index] = NULL;
53  }
54 
55  //jack midi ports
56  fMidiCapturePorts = new jack_port_t* [fParams.fSendMidiChannels];
57  for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) {
58  fMidiCapturePorts[port_index] = NULL;
59  }
60 
61  fMidiPlaybackPorts = new jack_port_t* [fParams.fReturnMidiChannels];
62  for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) {
63  fMidiPlaybackPorts[port_index] = NULL;
64  }
65 
66  //monitor
67 #ifdef JACK_MONITOR
68  fPeriodUsecs = (int)(1000000.f * ((float) fParams.fPeriodSize / (float) fParams.fSampleRate));
69  string plot_name;
70  plot_name = string(fParams.fName);
71  plot_name += string("_master");
72  plot_name += string((fParams.fSlaveSyncMode) ? "_sync" : "_async");
73  plot_name += string("_latency");
74  fNetTimeMon = new JackGnuPlotMonitor<float>(128, 4, plot_name);
75  string net_time_mon_fields[] =
76  {
77  string("sync send"),
78  string("end of send"),
79  string("sync recv"),
80  string("end of cycle")
81  };
82  string net_time_mon_options[] =
83  {
84  string("set xlabel \"audio cycles\""),
85  string("set ylabel \"% of audio cycle\"")
86  };
87  fNetTimeMon->SetPlotFile(net_time_mon_options, 2, net_time_mon_fields, 4);
88 #endif
89  }
90 
91  JackNetMaster::~JackNetMaster()
92  {
93  jack_log("JackNetMaster::~JackNetMaster ID = %u", fParams.fID);
94 
95  if (fClient) {
96  jack_deactivate(fClient);
97  FreePorts();
98  jack_client_close(fClient);
99  }
100  delete[] fAudioCapturePorts;
101  delete[] fAudioPlaybackPorts;
102  delete[] fMidiCapturePorts;
103  delete[] fMidiPlaybackPorts;
104 #ifdef JACK_MONITOR
105  fNetTimeMon->Save();
106  delete fNetTimeMon;
107 #endif
108  }
109 //init--------------------------------------------------------------------------------
110  bool JackNetMaster::Init(bool auto_connect)
111  {
112  //network init
113  if (!JackNetMasterInterface::Init()) {
114  jack_error("JackNetMasterInterface::Init() error...");
115  return false;
116  }
117 
118  //set global parameters
119  if (!SetParams()) {
120  jack_error("SetParams error...");
121  return false;
122  }
123 
124  //jack client and process
125  jack_status_t status;
126  if ((fClient = jack_client_open(fName, JackNullOption, &status, NULL)) == NULL) {
127  jack_error("Can't open a new JACK client");
128  return false;
129  }
130 
131  if (jack_set_process_callback(fClient, SetProcess, this) < 0) {
132  goto fail;
133  }
134 
135  if (jack_set_buffer_size_callback(fClient, SetBufferSize, this) < 0) {
136  goto fail;
137  }
138 
139  if (jack_set_sample_rate_callback(fClient, SetSampleRate, this) < 0) {
140  goto fail;
141  }
142 
143  if (jack_set_latency_callback(fClient, LatencyCallback, this) < 0) {
144  goto fail;
145  }
146 
147  /*
148  if (jack_set_port_connect_callback(fClient, SetConnectCallback, this) < 0) {
149  goto fail;
150  }
151  */
152 
153  if (AllocPorts() != 0) {
154  jack_error("Can't allocate JACK ports");
155  goto fail;
156  }
157 
158  //process can now run
159  fRunning = true;
160 
161  //finally activate jack client
162  if (jack_activate(fClient) != 0) {
163  jack_error("Can't activate JACK client");
164  goto fail;
165  }
166 
167  if (auto_connect) {
168  ConnectPorts();
169  }
170  jack_info("New NetMaster started");
171  return true;
172 
173  fail:
174  FreePorts();
175  jack_client_close(fClient);
176  fClient = NULL;
177  return false;
178  }
179 
180 //jack ports--------------------------------------------------------------------------
181  int JackNetMaster::AllocPorts()
182  {
183  int i;
184  char name[32];
185  jack_log("JackNetMaster::AllocPorts");
186 
187  //audio
188  for (i = 0; i < fParams.fSendAudioChannels; i++) {
189  snprintf(name, sizeof(name), "to_slave_%d", i+1);
190  if ((fAudioCapturePorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) {
191  return -1;
192  }
193  }
194 
195  for (i = 0; i < fParams.fReturnAudioChannels; i++) {
196  snprintf(name, sizeof(name), "from_slave_%d", i+1);
197  if ((fAudioPlaybackPorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) {
198  return -1;
199  }
200  }
201 
202  //midi
203  for (i = 0; i < fParams.fSendMidiChannels; i++) {
204  snprintf(name, sizeof(name), "midi_to_slave_%d", i+1);
205  if ((fMidiCapturePorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput | JackPortIsTerminal, 0)) == NULL) {
206  return -1;
207  }
208  }
209 
210  for (i = 0; i < fParams.fReturnMidiChannels; i++) {
211  snprintf(name, sizeof(name), "midi_from_slave_%d", i+1);
212  if ((fMidiPlaybackPorts[i] = jack_port_register(fClient, name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput | JackPortIsTerminal, 0)) == NULL) {
213  return -1;
214  }
215  }
216  return 0;
217  }
218 
219  void JackNetMaster::ConnectPorts()
220  {
221  const char** ports = jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
222  if (ports != NULL) {
223  for (int i = 0; i < fParams.fSendAudioChannels && ports[i]; i++) {
224  jack_connect(fClient, ports[i], jack_port_name(fAudioCapturePorts[i]));
225  }
226  jack_free(ports);
227  }
228 
229  ports = jack_get_ports(fClient, NULL, JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
230  if (ports != NULL) {
231  for (int i = 0; i < fParams.fReturnAudioChannels && ports[i]; i++) {
232  jack_connect(fClient, jack_port_name(fAudioPlaybackPorts[i]), ports[i]);
233  }
234  jack_free(ports);
235  }
236  }
237 
238  void JackNetMaster::FreePorts()
239  {
240  jack_log("JackNetMaster::FreePorts ID = %u", fParams.fID);
241 
242  int port_index;
243  for (port_index = 0; port_index < fParams.fSendAudioChannels; port_index++) {
244  if (fAudioCapturePorts[port_index]) {
245  jack_port_unregister(fClient, fAudioCapturePorts[port_index]);
246  }
247  }
248  for (port_index = 0; port_index < fParams.fReturnAudioChannels; port_index++) {
249  if (fAudioPlaybackPorts[port_index]) {
250  jack_port_unregister(fClient, fAudioPlaybackPorts[port_index]);
251  }
252  }
253  for (port_index = 0; port_index < fParams.fSendMidiChannels; port_index++) {
254  if (fMidiCapturePorts[port_index]) {
255  jack_port_unregister(fClient, fMidiCapturePorts[port_index]);
256  }
257  }
258  for (port_index = 0; port_index < fParams.fReturnMidiChannels; port_index++) {
259  if (fMidiPlaybackPorts[port_index]) {
260  jack_port_unregister(fClient, fMidiPlaybackPorts[port_index]);
261  }
262  }
263  }
264 
265 //transport---------------------------------------------------------------------------
266  void JackNetMaster::EncodeTransportData()
267  {
268  //is there a new timebase master ?
269  //TODO : check if any timebase callback has been called (and if it's conditional or not) and set correct value...
270  fSendTransportData.fTimebaseMaster = NO_CHANGE;
271 
272  //update state and position
273  fSendTransportData.fState = static_cast<uint>(jack_transport_query(fClient, &fSendTransportData.fPosition));
274 
275  //is it a new state ?
276  fSendTransportData.fNewState = ((fSendTransportData.fState != fLastTransportState) && (fSendTransportData.fState != fReturnTransportData.fState));
277  if (fSendTransportData.fNewState) {
278  jack_info("Sending '%s' to '%s' frame = %ld", GetTransportState(fSendTransportData.fState), fParams.fName, fSendTransportData.fPosition.frame);
279  }
280  fLastTransportState = fSendTransportData.fState;
281  }
282 
283  void JackNetMaster::DecodeTransportData()
284  {
285  //is there timebase master change ?
286  if (fReturnTransportData.fTimebaseMaster != NO_CHANGE) {
287 
288  int timebase = 0;
289  switch (fReturnTransportData.fTimebaseMaster)
290  {
291  case RELEASE_TIMEBASEMASTER :
292  timebase = jack_release_timebase(fClient);
293  if (timebase < 0) {
294  jack_error("Can't release timebase master");
295  } else {
296  jack_info("'%s' isn't the timebase master anymore", fParams.fName);
297  }
298  break;
299 
300  case TIMEBASEMASTER :
301  timebase = jack_set_timebase_callback(fClient, 0, SetTimebaseCallback, this);
302  if (timebase < 0) {
303  jack_error("Can't set a new timebase master");
304  } else {
305  jack_info("'%s' is the new timebase master", fParams.fName);
306  }
307  break;
308 
309  case CONDITIONAL_TIMEBASEMASTER :
310  timebase = jack_set_timebase_callback(fClient, 1, SetTimebaseCallback, this);
311  if (timebase != EBUSY) {
312  if (timebase < 0)
313  jack_error("Can't set a new timebase master");
314  else
315  jack_info("'%s' is the new timebase master", fParams.fName);
316  }
317  break;
318  }
319  }
320 
321  //is the slave in a new transport state and is this state different from master's ?
322  if (fReturnTransportData.fNewState && (fReturnTransportData.fState != jack_transport_query(fClient, NULL))) {
323 
324  switch (fReturnTransportData.fState)
325  {
326  case JackTransportStopped :
327  jack_transport_stop(fClient);
328  jack_info("'%s' stops transport", fParams.fName);
329  break;
330 
331  case JackTransportStarting :
332  if (jack_transport_reposition(fClient, &fReturnTransportData.fPosition) == EINVAL)
333  jack_error("Can't set new position");
334  jack_transport_start(fClient);
335  jack_info("'%s' starts transport frame = %d", fParams.fName, fReturnTransportData.fPosition.frame);
336  break;
337 
338  case JackTransportNetStarting :
339  jack_info("'%s' is ready to roll...", fParams.fName);
340  break;
341 
342  case JackTransportRolling :
343  jack_info("'%s' is rolling", fParams.fName);
344  break;
345  }
346  }
347  }
348 
349  void JackNetMaster::SetTimebaseCallback(jack_transport_state_t state, jack_nframes_t nframes, jack_position_t* pos, int new_pos, void* arg)
350  {
351  static_cast<JackNetMaster*>(arg)->TimebaseCallback(pos);
352  }
353 
354  void JackNetMaster::TimebaseCallback(jack_position_t* pos)
355  {
356  pos->bar = fReturnTransportData.fPosition.bar;
357  pos->beat = fReturnTransportData.fPosition.beat;
358  pos->tick = fReturnTransportData.fPosition.tick;
359  pos->bar_start_tick = fReturnTransportData.fPosition.bar_start_tick;
360  pos->beats_per_bar = fReturnTransportData.fPosition.beats_per_bar;
361  pos->beat_type = fReturnTransportData.fPosition.beat_type;
362  pos->ticks_per_beat = fReturnTransportData.fPosition.ticks_per_beat;
363  pos->beats_per_minute = fReturnTransportData.fPosition.beats_per_minute;
364  }
365 
366 //sync--------------------------------------------------------------------------------
367 
368  bool JackNetMaster::IsSlaveReadyToRoll()
369  {
370  return (fReturnTransportData.fState == JackTransportNetStarting);
371  }
372 
373  int JackNetMaster::SetBufferSize(jack_nframes_t nframes, void* arg)
374  {
375  JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
376  if (nframes != obj->fParams.fPeriodSize) {
377  jack_error("Cannot currently handle buffer size change, so JackNetMaster proxy will be removed...");
378  obj->Exit();
379  }
380  return 0;
381  }
382 
383  int JackNetMaster::SetSampleRate(jack_nframes_t nframes, void* arg)
384  {
385  JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
386  if (nframes != obj->fParams.fSampleRate) {
387  jack_error("Cannot currently handle sample rate change, so JackNetMaster proxy will be removed...");
388  obj->Exit();
389  }
390  return 0;
391  }
392 
393  void JackNetMaster::LatencyCallback(jack_latency_callback_mode_t mode, void* arg)
394  {
395  JackNetMaster* obj = static_cast<JackNetMaster*>(arg);
396  jack_nframes_t port_latency = jack_get_buffer_size(obj->fClient);
397  jack_latency_range_t range;
398 
399  //audio
400  for (int i = 0; i < obj->fParams.fSendAudioChannels; i++) {
401  //port latency
402  range.min = range.max = float(obj->fParams.fNetworkLatency * port_latency) / 2.f;
403  jack_port_set_latency_range(obj->fAudioCapturePorts[i], JackPlaybackLatency, &range);
404  }
405 
406  //audio
407  for (int i = 0; i < obj->fParams.fReturnAudioChannels; i++) {
408  //port latency
409  range.min = range.max = float(obj->fParams.fNetworkLatency * port_latency) / 2.f + ((obj->fParams.fSlaveSyncMode) ? 0 : port_latency);
410  jack_port_set_latency_range(obj->fAudioPlaybackPorts[i], JackCaptureLatency, &range);
411  }
412 
413  //midi
414  for (int i = 0; i < obj->fParams.fSendMidiChannels; i++) {
415  //port latency
416  range.min = range.max = float(obj->fParams.fNetworkLatency * port_latency) / 2.f;
417  jack_port_set_latency_range(obj->fMidiCapturePorts[i], JackPlaybackLatency, &range);
418  }
419 
420  //midi
421  for (int i = 0; i < obj->fParams.fReturnMidiChannels; i++) {
422  //port latency
423  range.min = range.max = obj->fParams.fNetworkLatency * port_latency + ((obj->fParams.fSlaveSyncMode) ? 0 : port_latency);
424  jack_port_set_latency_range(obj->fMidiPlaybackPorts[i], JackCaptureLatency, &range);
425  }
426  }
427 
428 //process-----------------------------------------------------------------------------
429  int JackNetMaster::SetProcess(jack_nframes_t nframes, void* arg)
430  {
431  try {
432  return static_cast<JackNetMaster*>(arg)->Process();
433  } catch (JackNetException& e) {
434  return 0;
435  }
436  }
437 
438  void JackNetMaster::SetConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect, void* arg)
439  {
440  static_cast<JackNetMaster*>(arg)->ConnectCallback(a, b, connect);
441  }
442 
443  void JackNetMaster::ConnectCallback(jack_port_id_t a, jack_port_id_t b, int connect)
444  {
445  jack_info("JackNetMaster::ConnectCallback a = %d b = %d connect = %d", a, b, connect);
446  if (connect) {
447  jack_connect(fClient, jack_port_name(jack_port_by_id(fClient, a)), "system:playback_1");
448  }
449  }
450 
451  int JackNetMaster::Process()
452  {
453  if (!fRunning) {
454  return 0;
455  }
456 
457 #ifdef JACK_MONITOR
458  jack_time_t begin_time = GetMicroSeconds();
459  fNetTimeMon->New();
460 #endif
461 
462  //buffers
463  for (int midi_port_index = 0; midi_port_index < fParams.fSendMidiChannels; midi_port_index++) {
464  fNetMidiCaptureBuffer->SetBuffer(midi_port_index,
465  static_cast<JackMidiBuffer*>(jack_port_get_buffer(fMidiCapturePorts[midi_port_index],
466  fParams.fPeriodSize)));
467  }
468  for (int audio_port_index = 0; audio_port_index < fParams.fSendAudioChannels; audio_port_index++) {
469 
470  #ifdef OPTIMIZED_PROTOCOL
471  if (fNetAudioCaptureBuffer->GetConnected(audio_port_index)) {
472  // Port is connected on other side...
473  fNetAudioCaptureBuffer->SetBuffer(audio_port_index,
474  ((jack_port_connected(fAudioCapturePorts[audio_port_index]) > 0)
475  ? static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index], fParams.fPeriodSize))
476  : NULL));
477  } else {
478  fNetAudioCaptureBuffer->SetBuffer(audio_port_index, NULL);
479  }
480  #else
481  fNetAudioCaptureBuffer->SetBuffer(audio_port_index,
482  static_cast<sample_t*>(jack_port_get_buffer(fAudioCapturePorts[audio_port_index],
483  fParams.fPeriodSize)));
484  #endif
485  // TODO
486  }
487 
488  for (int midi_port_index = 0; midi_port_index < fParams.fReturnMidiChannels; midi_port_index++) {
489  fNetMidiPlaybackBuffer->SetBuffer(midi_port_index,
490  static_cast<JackMidiBuffer*>(jack_port_get_buffer(fMidiPlaybackPorts[midi_port_index],
491  fParams.fPeriodSize)));
492  }
493  for (int audio_port_index = 0; audio_port_index < fParams.fReturnAudioChannels; audio_port_index++) {
494 
495  #ifdef OPTIMIZED_PROTOCOL
496  sample_t* out = (jack_port_connected(fAudioPlaybackPorts[audio_port_index]) > 0)
497  ? static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize))
498  : NULL;
499  if (out) {
500  memset(out, 0, sizeof(float) * fParams.fPeriodSize);
501  }
502  fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out);
503  #else
504  sample_t* out = static_cast<sample_t*>(jack_port_get_buffer(fAudioPlaybackPorts[audio_port_index], fParams.fPeriodSize));
505  if (out) {
506  memset(out, 0, sizeof(float) * fParams.fPeriodSize);
507  }
508  fNetAudioPlaybackBuffer->SetBuffer(audio_port_index, out)));
509  #endif
510  }
511 
512  // encode the first packet
513  EncodeSyncPacket();
514 
515  if (SyncSend() == SOCKET_ERROR) {
516  return SOCKET_ERROR;
517  }
518 
519 #ifdef JACK_MONITOR
520  fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
521 #endif
522 
523  // send data
524  if (DataSend() == SOCKET_ERROR) {
525  return SOCKET_ERROR;
526  }
527 
528 #ifdef JACK_MONITOR
529  fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
530 #endif
531 
532  // receive sync
533  int res = SyncRecv();
534  switch (res) {
535 
536  case NET_SYNCHING:
537  case SOCKET_ERROR:
538  return res;
539 
540  case SYNC_PACKET_ERROR:
541  // Since sync packet is incorrect, don't decode it and continue with data
542  break;
543 
544  default:
545  // Decode sync
546  int unused_frames;
547  DecodeSyncPacket(unused_frames);
548  break;
549  }
550 
551 #ifdef JACK_MONITOR
552  fNetTimeMon->Add((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
553 #endif
554 
555  // receive data
556  res = DataRecv();
557  switch (res) {
558 
559  case 0:
560  case SOCKET_ERROR:
561  return res;
562 
563  case DATA_PACKET_ERROR:
564  // Well not a real XRun...
565  JackServerGlobals::fInstance->GetEngine()->NotifyClientXRun(ALL_CLIENTS);
566  break;
567  }
568 
569 #ifdef JACK_MONITOR
570  fNetTimeMon->AddLast((((float)(GetMicroSeconds() - begin_time)) / (float) fPeriodUsecs) * 100.f);
571 #endif
572  return 0;
573  }
574 
575  void JackNetMaster::SaveConnections(connections_list_t& connections)
576  {
577  // Audio
578  for (int i = 0; i < fParams.fSendAudioChannels; i++) {
579  const char** connected_port = jack_port_get_all_connections(fClient, fAudioCapturePorts[i]);
580  if (connected_port != NULL) {
581  for (int port = 0; connected_port[port]; port++) {
582  connections.push_back(make_pair(connected_port[port], jack_port_name(fAudioCapturePorts[i])));
583  jack_log("INPUT %s ==> %s", connected_port[port], jack_port_name(fAudioCapturePorts[i]));
584  }
585  jack_free(connected_port);
586  }
587  }
588 
589  for (int i = 0; i < fParams.fReturnAudioChannels; i++) {
590  const char** connected_port = jack_port_get_all_connections(fClient, fAudioPlaybackPorts[i]);
591  if (connected_port != NULL) {
592  for (int port = 0; connected_port[port]; port++) {
593  connections.push_back(make_pair(jack_port_name(fAudioPlaybackPorts[i]), connected_port[port]));
594  jack_log("OUTPUT %s ==> %s", jack_port_name(fAudioPlaybackPorts[i]), connected_port[port]);
595  }
596  jack_free(connected_port);
597  }
598  }
599 
600  // MIDI
601  for (int i = 0; i < fParams.fSendMidiChannels; i++) {
602  const char** connected_port = jack_port_get_all_connections(fClient, fMidiCapturePorts[i]);
603  if (connected_port != NULL) {
604  for (int port = 0; connected_port[port]; port++) {
605  connections.push_back(make_pair(connected_port[port], jack_port_name(fMidiCapturePorts[i])));
606  jack_log("INPUT %s ==> %s", connected_port[port], jack_port_name(fMidiCapturePorts[i]));
607  }
608  jack_free(connected_port);
609  }
610  }
611 
612  for (int i = 0; i < fParams.fReturnMidiChannels; i++) {
613  const char** connected_port = jack_port_get_all_connections(fClient, fMidiPlaybackPorts[i]);
614  if (connected_port != NULL) {
615  for (int port = 0; connected_port[port]; port++) {
616  connections.push_back(make_pair(jack_port_name(fMidiPlaybackPorts[i]), connected_port[port]));
617  jack_log("OUTPUT %s ==> %s", jack_port_name(fMidiPlaybackPorts[i]), connected_port[port]);
618  }
619  jack_free(connected_port);
620  }
621  }
622  }
623 
624  void JackNetMaster::LoadConnections(const connections_list_t& connections)
625  {
626  list<pair<string, string> >::const_iterator it;
627  for (it = connections.begin(); it != connections.end(); it++) {
628  pair<string, string> connection = *it;
629  jack_connect(fClient, connection.first.c_str(), connection.second.c_str());
630  }
631  }
632 
633 
634 //JackNetMasterManager***********************************************************************************************
635 
636  JackNetMasterManager::JackNetMasterManager(jack_client_t* client, const JSList* params) : fSocket()
637  {
638  jack_log("JackNetMasterManager::JackNetMasterManager");
639 
640  fClient = client;
641  fName = jack_get_client_name(fClient);
642  fGlobalID = 0;
643  fRunning = true;
644  fAutoConnect = false;
645  fAutoSave = false;
646 
647  const JSList* node;
648  const jack_driver_param_t* param;
649 
650  jack_on_shutdown(fClient, SetShutDown, this);
651 
652  // Possibly use env variable
653  const char* default_udp_port = getenv("JACK_NETJACK_PORT");
654  fSocket.SetPort((default_udp_port) ? atoi(default_udp_port) : DEFAULT_PORT);
655 
656  const char* default_multicast_ip = getenv("JACK_NETJACK_MULTICAST");
657  if (default_multicast_ip) {
658  strcpy(fMulticastIP, default_multicast_ip);
659  } else {
660  strcpy(fMulticastIP, DEFAULT_MULTICAST_IP);
661  }
662 
663  for (node = params; node; node = jack_slist_next(node)) {
664 
665  param = (const jack_driver_param_t*) node->data;
666  switch (param->character) {
667  case 'a' :
668  if (strlen(param->value.str) < 32) {
669  strcpy(fMulticastIP, param->value.str);
670  } else {
671  jack_error("Can't use multicast address %s, using default %s", param->value.ui, DEFAULT_MULTICAST_IP);
672  }
673  break;
674 
675  case 'p':
676  fSocket.SetPort(param->value.ui);
677  break;
678 
679  case 'c':
680  fAutoConnect = true;
681  break;
682 
683  case 's':
684  fAutoSave = true;
685  break;
686  }
687  }
688 
689  //set sync callback
690  jack_set_sync_callback(fClient, SetSyncCallback, this);
691 
692  //activate the client (for sync callback)
693  if (jack_activate(fClient) != 0) {
694  jack_error("Can't activate the NetManager client, transport disabled");
695  }
696 
697  //launch the manager thread
698  if (jack_client_create_thread(fClient, &fThread, 0, 0, NetManagerThread, this)) {
699  jack_error("Can't create the NetManager control thread");
700  }
701  }
702 
703  JackNetMasterManager::~JackNetMasterManager()
704  {
705  jack_log("JackNetMasterManager::~JackNetMasterManager");
706  ShutDown();
707  }
708 
709  int JackNetMasterManager::CountIO(const char* type, int flags)
710  {
711  int count = 0;
712  const char** ports = jack_get_ports(fClient, NULL, type, flags);
713  if (ports != NULL) {
714  while (ports[count]) { count++; }
715  jack_free(ports);
716  }
717  return count;
718  }
719 
720  void JackNetMasterManager::SetShutDown(void* arg)
721  {
722  static_cast<JackNetMasterManager*>(arg)->ShutDown();
723  }
724 
725  void JackNetMasterManager::ShutDown()
726  {
727  jack_log("JackNetMasterManager::ShutDown");
728  if (fRunning) {
729  jack_client_kill_thread(fClient, fThread);
730  fRunning = false;
731  }
732  master_list_t::iterator it;
733  for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
734  delete (*it);
735  }
736  fMasterList.clear();
737  fSocket.Close();
738  SocketAPIEnd();
739  }
740 
741  int JackNetMasterManager::SetSyncCallback(jack_transport_state_t state, jack_position_t* pos, void* arg)
742  {
743  return static_cast<JackNetMasterManager*>(arg)->SyncCallback(state, pos);
744  }
745 
746  int JackNetMasterManager::SyncCallback(jack_transport_state_t state, jack_position_t* pos)
747  {
748  //check if each slave is ready to roll
749  int res = 1;
750  master_list_it_t it;
751  for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
752  if (!(*it)->IsSlaveReadyToRoll()) {
753  res = 0;
754  }
755  }
756  jack_log("JackNetMasterManager::SyncCallback returns '%s'", (res) ? "true" : "false");
757  return res;
758  }
759 
760  void* JackNetMasterManager::NetManagerThread(void* arg)
761  {
762  JackNetMasterManager* master_manager = static_cast<JackNetMasterManager*>(arg);
763  jack_info("Starting Jack NetManager");
764  jack_info("Listening on '%s:%d'", master_manager->fMulticastIP, master_manager->fSocket.GetPort());
765  master_manager->Run();
766  return NULL;
767  }
768 
769  void JackNetMasterManager::Run()
770  {
771  jack_log("JackNetMasterManager::Run");
772  //utility variables
773  int attempt = 0;
774 
775  //data
776  session_params_t host_params;
777  int rx_bytes = 0;
778  JackNetMaster* net_master;
779 
780  //init socket API (win32)
781  if (SocketAPIInit() < 0) {
782  jack_error("Can't init Socket API, exiting...");
783  return;
784  }
785 
786  //socket
787  if (fSocket.NewSocket() == SOCKET_ERROR) {
788  jack_error("Can't create NetManager input socket : %s", StrError(NET_ERROR_CODE));
789  return;
790  }
791 
792  //bind the socket to the local port
793  if (fSocket.Bind() == SOCKET_ERROR) {
794  jack_error("Can't bind NetManager socket : %s", StrError(NET_ERROR_CODE));
795  fSocket.Close();
796  return;
797  }
798 
799  //join multicast group
800  if (fSocket.JoinMCastGroup(fMulticastIP) == SOCKET_ERROR) {
801  jack_error("Can't join multicast group : %s", StrError(NET_ERROR_CODE));
802  }
803 
804  //local loop
805  if (fSocket.SetLocalLoop() == SOCKET_ERROR) {
806  jack_error("Can't set local loop : %s", StrError(NET_ERROR_CODE));
807  }
808 
809  //set a timeout on the multicast receive (the thread can now be cancelled)
810  if (fSocket.SetTimeOut(MANAGER_INIT_TIMEOUT) == SOCKET_ERROR) {
811  jack_error("Can't set timeout : %s", StrError(NET_ERROR_CODE));
812  }
813 
814  //main loop, wait for data, deal with it and wait again
815  do
816  {
817  session_params_t net_params;
818  rx_bytes = fSocket.CatchHost(&net_params, sizeof(session_params_t), 0);
819  SessionParamsNToH(&net_params, &host_params);
820 
821  if ((rx_bytes == SOCKET_ERROR) && (fSocket.GetError() != NET_NO_DATA)) {
822  jack_error("Error in receive : %s", StrError(NET_ERROR_CODE));
823  if (++attempt == 10) {
824  jack_error("Can't receive on the socket, exiting net manager");
825  return;
826  }
827  }
828 
829  if (rx_bytes == sizeof(session_params_t)) {
830  switch (GetPacketType(&host_params))
831  {
832  case SLAVE_AVAILABLE:
833  if ((net_master = InitMaster(host_params))) {
834  SessionParamsDisplay(&net_master->fParams);
835  } else {
836  jack_error("Can't init new NetMaster...");
837  }
838  jack_info("Waiting for a slave...");
839  break;
840  case KILL_MASTER:
841  if (KillMaster(&host_params)) {
842  jack_info("Waiting for a slave...");
843  }
844  break;
845  default:
846  break;
847  }
848  }
849  }
850  while (fRunning);
851  }
852 
853  JackNetMaster* JackNetMasterManager::InitMaster(session_params_t& params)
854  {
855  jack_log("JackNetMasterManager::InitMaster slave : %s", params.fName);
856 
857  //check MASTER <<==> SLAVE network protocol coherency
858  if (params.fProtocolVersion != NETWORK_PROTOCOL) {
859  jack_error("Error : slave '%s' is running with a different protocol %d != %d", params.fName, params.fProtocolVersion, NETWORK_PROTOCOL);
860  return NULL;
861  }
862 
863  //settings
864  fSocket.GetName(params.fMasterNetName);
865  params.fID = ++fGlobalID;
866  params.fSampleRate = jack_get_sample_rate(fClient);
867  params.fPeriodSize = jack_get_buffer_size(fClient);
868 
869  if (params.fSendAudioChannels == -1) {
870  params.fSendAudioChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsOutput);
871  jack_info("Takes physical %d audio input(s) for slave", params.fSendAudioChannels);
872  }
873 
874  if (params.fReturnAudioChannels == -1) {
875  params.fReturnAudioChannels = CountIO(JACK_DEFAULT_AUDIO_TYPE, JackPortIsPhysical | JackPortIsInput);
876  jack_info("Takes physical %d audio output(s) for slave", params.fReturnAudioChannels);
877  }
878 
879  if (params.fSendMidiChannels == -1) {
880  params.fSendMidiChannels = CountIO(JACK_DEFAULT_MIDI_TYPE, JackPortIsPhysical | JackPortIsOutput);
881  jack_info("Takes physical %d MIDI input(s) for slave", params.fSendMidiChannels);
882  }
883 
884  if (params.fReturnMidiChannels == -1) {
885  params.fReturnMidiChannels = CountIO(JACK_DEFAULT_MIDI_TYPE, JackPortIsPhysical | JackPortIsInput);
886  jack_info("Takes physical %d MIDI output(s) for slave", params.fReturnMidiChannels);
887  }
888 
889  //create a new master and add it to the list
890  JackNetMaster* master = new JackNetMaster(fSocket, params, fMulticastIP);
891  if (master->Init(fAutoConnect)) {
892  fMasterList.push_back(master);
893  if (fAutoSave && fMasterConnectionList.find(params.fName) != fMasterConnectionList.end()) {
894  master->LoadConnections(fMasterConnectionList[params.fName]);
895  }
896  return master;
897  } else {
898  delete master;
899  return NULL;
900  }
901  }
902 
903  master_list_it_t JackNetMasterManager::FindMaster(uint32_t id)
904  {
905  jack_log("JackNetMasterManager::FindMaster ID = %u", id);
906 
907  master_list_it_t it;
908  for (it = fMasterList.begin(); it != fMasterList.end(); it++) {
909  if ((*it)->fParams.fID == id) {
910  return it;
911  }
912  }
913  return it;
914  }
915 
916  int JackNetMasterManager::KillMaster(session_params_t* params)
917  {
918  jack_log("JackNetMasterManager::KillMaster ID = %u", params->fID);
919 
920  master_list_it_t master_it = FindMaster(params->fID);
921  if (master_it != fMasterList.end()) {
922  if (fAutoSave) {
923  fMasterConnectionList[params->fName].clear();
924  (*master_it)->SaveConnections(fMasterConnectionList[params->fName]);
925  }
926  fMasterList.erase(master_it);
927  delete (*master_it);
928  return 1;
929  }
930  return 0;
931  }
932 }//namespace
933 
934 static Jack::JackNetMasterManager* master_manager = NULL;
935 
936 #ifdef __cplusplus
937 extern "C"
938 {
939 #endif
940 
941  SERVER_EXPORT jack_driver_desc_t* jack_get_descriptor()
942  {
943  jack_driver_desc_t * desc;
946 
947  desc = jack_driver_descriptor_construct("netmanager", JackDriverNone, "netjack multi-cast master component", &filler);
948 
949  strcpy(value.str, DEFAULT_MULTICAST_IP);
950  jack_driver_descriptor_add_parameter(desc, &filler, "multicast-ip", 'a', JackDriverParamString, &value, NULL, "Multicast address", NULL);
951 
952  value.i = DEFAULT_PORT;
953  jack_driver_descriptor_add_parameter(desc, &filler, "udp-net-port", 'p', JackDriverParamInt, &value, NULL, "UDP port", NULL);
954 
955  value.i = false;
956  jack_driver_descriptor_add_parameter(desc, &filler, "auto-connect", 'c', JackDriverParamBool, &value, NULL, "Auto connect netmaster to system ports", NULL);
957 
958  value.i = false;
959  jack_driver_descriptor_add_parameter(desc, &filler, "auto-save", 's', JackDriverParamBool, &value, NULL, "Save/restore netmaster connection state when restarted", NULL);
960 
961  return desc;
962  }
963 
964  SERVER_EXPORT int jack_internal_initialize(jack_client_t* jack_client, const JSList* params)
965  {
966  if (master_manager) {
967  jack_error("Master Manager already loaded");
968  return 1;
969  } else {
970  jack_log("Loading Master Manager");
971  master_manager = new Jack::JackNetMasterManager(jack_client, params);
972  return (master_manager) ? 0 : 1;
973  }
974  }
975 
976  SERVER_EXPORT int jack_initialize(jack_client_t* jack_client, const char* load_init)
977  {
978  JSList* params = NULL;
979  bool parse_params = true;
980  int res = 1;
981  jack_driver_desc_t* desc = jack_get_descriptor();
982 
983  Jack::JackArgParser parser(load_init);
984  if (parser.GetArgc() > 0) {
985  parse_params = parser.ParseParams(desc, &params);
986  }
987 
988  if (parse_params) {
989  res = jack_internal_initialize(jack_client, params);
990  parser.FreeParams(params);
991  }
992  return res;
993  }
994 
995  SERVER_EXPORT void jack_finish(void* arg)
996  {
997  if (master_manager) {
998  jack_log("Unloading Master Manager");
999  delete master_manager;
1000  master_manager = NULL;
1001  }
1002  }
1003 
1004 #ifdef __cplusplus
1005 }
1006 #endif
LIB_EXPORT int jack_port_unregister(jack_client_t *, jack_port_t *)
Definition: JackAPI.cpp:1109
LIB_EXPORT jack_port_t * jack_port_by_id(jack_client_t *client, jack_port_id_t port_id)
Definition: JackAPI.cpp:1326
LIB_EXPORT jack_transport_state_t jack_transport_query(const jack_client_t *client, jack_position_t *pos)
Definition: JackAPI.cpp:1583
LIB_EXPORT int jack_set_process_callback(jack_client_t *client, JackProcessCallback process_callback, void *arg)
Definition: JackAPI.cpp:829
LIB_EXPORT int jack_activate(jack_client_t *client)
Definition: JackAPI.cpp:1067
SERVER_EXPORT void jack_error(const char *fmt,...)
Definition: JackError.cpp:92
LIB_EXPORT void jack_port_set_latency_range(jack_port_t *port, jack_latency_callback_mode_t mode, jack_latency_range_t *range)
Definition: JackAPI.cpp:586
LIB_EXPORT int jack_connect(jack_client_t *, const char *source_port, const char *destination_port)
Definition: JackAPI.cpp:1211
float beat_type
Definition: types.h:571
jack_nframes_t min
Definition: types.h:270
LIB_EXPORT jack_port_t * jack_port_register(jack_client_t *client, const char *port_name, const char *port_type, unsigned long flags, unsigned long buffer_size)
Definition: JackAPI.cpp:1093
LIB_EXPORT int jack_release_timebase(jack_client_t *client)
Definition: JackAPI.cpp:1517
LIB_EXPORT const char ** jack_port_get_all_connections(const jack_client_t *client, const jack_port_t *port)
Definition: JackAPI.cpp:1162
SERVER_EXPORT void jack_info(const char *fmt,...)
Definition: JackError.cpp:100
LIB_EXPORT void jack_on_shutdown(jack_client_t *client, JackShutdownCallback shutdown_callback, void *arg)
Definition: JackAPI.cpp:805
LIB_EXPORT jack_client_t * jack_client_open(const char *client_name, jack_options_t options, jack_status_t *status,...)
Definition: JackLibAPI.cpp:167
int32_t tick
Definition: types.h:567
LIB_EXPORT char * jack_get_client_name(jack_client_t *client)
Definition: JackAPI.cpp:1469
LIB_EXPORT void jack_transport_start(jack_client_t *client)
Definition: JackAPI.cpp:1623
jack_nframes_t max
Definition: types.h:274
float beats_per_bar
Definition: types.h:570
LIB_EXPORT jack_nframes_t jack_get_buffer_size(jack_client_t *)
Definition: JackAPI.cpp:1275
LIB_EXPORT int jack_set_sample_rate_callback(jack_client_t *client, JackSampleRateCallback srate_callback, void *arg)
Definition: JackAPI.cpp:948
LIB_EXPORT void * jack_port_get_buffer(jack_port_t *, jack_nframes_t)
Definition: JackAPI.cpp:363
LIB_EXPORT void jack_transport_stop(jack_client_t *client)
Definition: JackAPI.cpp:1635
LIB_EXPORT int jack_client_create_thread(jack_client_t *client, jack_native_thread_t *thread, int priority, int realtime, thread_routine routine, void *arg)
Definition: JackAPI.cpp:1745
LIB_EXPORT int jack_transport_reposition(jack_client_t *client, const jack_position_t *pos)
Definition: JackAPI.cpp:1609
jack_nframes_t frame
Definition: types.h:560
LIB_EXPORT jack_nframes_t jack_get_sample_rate(jack_client_t *)
Definition: JackAPI.cpp:1261
int32_t beat
Definition: types.h:566
LIB_EXPORT int jack_set_timebase_callback(jack_client_t *client, int conditional, JackTimebaseCallback timebase_callback, void *arg)
Definition: JackAPI.cpp:1556
int32_t bar
Definition: types.h:565
LIB_EXPORT int jack_set_buffer_size_callback(jack_client_t *client, JackBufferSizeCallback bufsize_callback, void *arg)
Definition: JackAPI.cpp:935
LIB_EXPORT int jack_set_sync_callback(jack_client_t *client, JackSyncCallback sync_callback, void *arg)
Definition: JackAPI.cpp:1530
LIB_EXPORT int jack_port_connected(const jack_port_t *port)
Definition: JackAPI.cpp:458
LIB_EXPORT const char * jack_port_name(const jack_port_t *port)
Definition: JackAPI.cpp:383
LIB_EXPORT const char ** jack_get_ports(jack_client_t *, const char *port_name_pattern, const char *type_name_pattern, unsigned long flags)
Definition: JackAPI.cpp:1289
LIB_EXPORT int jack_deactivate(jack_client_t *client)
Definition: JackAPI.cpp:1080
SERVER_EXPORT void jack_log(const char *fmt,...)
Definition: JackError.cpp:108
LIB_EXPORT int jack_client_kill_thread(jack_client_t *client, jack_native_thread_t thread)
Definition: JackAPI.cpp:1772
LIB_EXPORT int jack_client_close(jack_client_t *client)
Definition: JackLibAPI.cpp:189