Jack2  1.9.8
JackNetOneDriver.cpp
1 /*
2 Copyright (C) 2008-2011 Torben Horn
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 #ifdef WIN32
20 #include <malloc.h>
21 #endif
22 
23 #include "JackNetOneDriver.h"
24 #include "JackEngineControl.h"
25 #include "JackLockedEngine.h"
26 #include "JackGraphManager.h"
27 #include "JackWaitThreadedDriver.h"
28 #include "JackTools.h"
29 #include "driver_interface.h"
30 
31 #include "netjack.h"
32 #include "netjack_packet.h"
33 
34 #if HAVE_SAMPLERATE
35 #include <samplerate.h>
36 #endif
37 
38 #if HAVE_CELT
39 #include <celt/celt.h>
40 #endif
41 
42 #define MIN(x,y) ((x)<(y) ? (x) : (y))
43 
44 using namespace std;
45 
46 namespace Jack
47 {
48 JackNetOneDriver::JackNetOneDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
49  int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports,
50  int sample_rate, int period_size, int resample_factor,
51  const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig,
52  int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val)
53  : JackWaiterDriver(name, alias, engine, table)
54 {
55  jack_log("JackNetOneDriver::JackNetOneDriver port %d", port);
56 
57 #ifdef WIN32
58  WSADATA wsa;
59  int rc = WSAStartup(MAKEWORD(2, 0), &wsa);
60 #endif
61 
62  netjack_init(& (this->netj),
63  NULL, // client
64  name,
65  capture_ports,
66  playback_ports,
67  midi_input_ports,
68  midi_output_ports,
69  sample_rate,
70  period_size,
71  port,
72  transport_sync,
73  resample_factor,
74  0,
75  bitdepth,
76  use_autoconfig,
77  latency,
78  redundancy,
79  dont_htonl_floats,
80  always_deadline,
81  jitter_val);
82 }
83 
84 JackNetOneDriver::~JackNetOneDriver()
85 {
86  // No destructor yet.
87 }
88 
89 //open, close, attach and detach------------------------------------------------------
90 
91 int JackNetOneDriver::Close()
92 {
93  // Generic audio driver close
94  int res = JackWaiterDriver::Close();
95 
96  FreePorts();
97  netjack_release(&netj);
98  return res;
99 }
100 
101 int JackNetOneDriver::Attach()
102 {
103  return 0;
104 }
105 
106 int JackNetOneDriver::Detach()
107 {
108  return 0;
109 }
110 
111 int JackNetOneDriver::AllocPorts()
112 {
113  jack_port_id_t port_index;
114  char buf[64];
115  unsigned int chn;
116 
117  //if (netj.handle_transport_sync)
118  // jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
119 
120  for (chn = 0; chn < netj.capture_channels_audio; chn++) {
121  snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
122 
123  if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
124  CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
125  jack_error("driver: cannot register port for %s", buf);
126  return -1;
127  }
128  //port = fGraphManager->GetPort(port_index);
129 
130  netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
131 
132  if (netj.bitdepth == CELT_MODE) {
133 #if HAVE_CELT
134 #if HAVE_CELT_API_0_11
135  celt_int32 lookahead;
136  CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
137  netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create_custom(celt_mode, 1, NULL));
138 #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
139  celt_int32 lookahead;
140  CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
141  netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode, 1, NULL));
142 #else
143  celt_int32_t lookahead;
144  CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL);
145  netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode));
146 #endif
147  celt_mode_info(celt_mode, CELT_GET_LOOKAHEAD, &lookahead);
148  netj.codec_latency = 2 * lookahead;
149 #endif
150  } else {
151 #if HAVE_SAMPLERATE
152  netj.capture_srcs = jack_slist_append(netj.capture_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
153 #endif
154  }
155  }
156 
157  for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
158  snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
159 
160  if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
161  CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
162  jack_error("driver: cannot register port for %s", buf);
163  return -1;
164  }
165  //port = fGraphManager->GetPort(port_index);
166 
167  netj.capture_ports =
168  jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
169  }
170 
171  for (chn = 0; chn < netj.playback_channels_audio; chn++) {
172  snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
173 
174  if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
175  PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
176  jack_error("driver: cannot register port for %s", buf);
177  return -1;
178  }
179  //port = fGraphManager->GetPort(port_index);
180 
181  netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
182  if (netj.bitdepth == CELT_MODE) {
183 #if HAVE_CELT
184 #if HAVE_CELT_API_0_11
185  CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
186  netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom(celt_mode, 1, NULL));
187 #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
188  CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
189  netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode, 1, NULL));
190 #else
191  CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL);
192  netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode));
193 #endif
194 #endif
195  } else {
196 #if HAVE_SAMPLERATE
197  netj.playback_srcs = jack_slist_append(netj.playback_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
198 #endif
199  }
200  }
201  for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
202  snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
203 
204  if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
205  PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
206  jack_error("driver: cannot register port for %s", buf);
207  return -1;
208  }
209  //port = fGraphManager->GetPort(port_index);
210 
211  netj.playback_ports =
212  jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
213  }
214  return 0;
215 }
216 
217 //init and restart--------------------------------------------------------------------
218 bool JackNetOneDriver::Initialize()
219 {
220  jack_log("JackNetOneDriver::Init");
221 
222  FreePorts();
223  netjack_release(&netj);
224 
225  //display some additional infos
226  jack_info("NetOne driver started");
227  if (netjack_startup(&netj)) {
228  return false;
229  }
230 
231  //register jack ports
232  if (AllocPorts() != 0) {
233  jack_error("Can't allocate ports.");
234  return false;
235  }
236 
237  //monitor
238  //driver parametering
239  JackTimedDriver::SetBufferSize(netj.period_size);
240  JackTimedDriver::SetSampleRate(netj.sample_rate);
241 
242  JackDriver::NotifyBufferSize(netj.period_size);
243  JackDriver::NotifySampleRate(netj.sample_rate);
244 
245  //transport engine parametering
246  fEngineControl->fTransport.SetNetworkSync(true);
247  return true;
248 }
249 
250 
251 //jack ports and buffers--------------------------------------------------------------
252 
253 //driver processes--------------------------------------------------------------------
254 
255 int JackNetOneDriver::Read()
256 {
257  int delay;
258  delay = netjack_wait(&netj);
259  if (delay) {
260  NotifyXRun(fBeginDateUst, (float) delay);
261  jack_error("netxruns... duration: %dms", delay / 1000);
262  }
263 
264  if ((netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2)
265  JackTools::ThrowJackNetException();
266 
267  //netjack_read(&netj, netj.period_size);
268  JackDriver::CycleTakeBeginTime();
269 
270  jack_position_t local_trans_pos;
271  jack_transport_state_t local_trans_state;
272 
273  unsigned int *packet_buf, *packet_bufX;
274 
275  if (! netj.packet_data_valid) {
276  jack_log("data not valid");
277  render_payload_to_jack_ports (netj.bitdepth, NULL, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats);
278  return 0;
279  }
280  packet_buf = netj.rx_buf;
281 
282  jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
283 
284  packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
285 
286  netj.reply_port = pkthdr->reply_port;
287  netj.latency = pkthdr->latency;
288 
289  // Special handling for latency=0
290  if (netj.latency == 0)
291  netj.resync_threshold = 0;
292  else
293  netj.resync_threshold = MIN(15, pkthdr->latency - 1);
294 
295  // check whether, we should handle the transport sync stuff, or leave trnasports untouched.
296  if (netj.handle_transport_sync) {
297 #if 1
298  unsigned int compensated_tranport_pos = (pkthdr->transport_frame + (pkthdr->latency * netj.period_size) + netj.codec_latency);
299 
300  // read local transport info....
301  //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
302 
303  local_trans_state = fEngineControl->fTransport.Query(&local_trans_pos);
304 
305  // Now check if we have to start or stop local transport to sync to remote...
306  switch (pkthdr->transport_state) {
307 
308  case JackTransportStarting:
309  // the master transport is starting... so we set our reply to the sync_callback;
310  if (local_trans_state == JackTransportStopped) {
311  fEngineControl->fTransport.SetCommand(TransportCommandStart);
312  //jack_transport_start(netj.client);
313  //last_transport_state = JackTransportStopped;
314  netj.sync_state = 0;
315  jack_info("locally stopped... starting...");
316  }
317 
318  if (local_trans_pos.frame != compensated_tranport_pos) {
319  jack_position_t new_pos = local_trans_pos;
320  new_pos.frame = compensated_tranport_pos + 2 * netj.period_size;
321  new_pos.valid = (jack_position_bits_t) 0;
322 
323 
324  fEngineControl->fTransport.RequestNewPos(&new_pos);
325  //jack_transport_locate(netj.client, compensated_tranport_pos);
326  //last_transport_state = JackTransportRolling;
327  netj.sync_state = 0;
328  jack_info("starting locate to %d", compensated_tranport_pos);
329  }
330  break;
331 
332  case JackTransportStopped:
333  netj.sync_state = 1;
334  if (local_trans_pos.frame != (pkthdr->transport_frame)) {
335  jack_position_t new_pos = local_trans_pos;
336  new_pos.frame = pkthdr->transport_frame;
337  new_pos.valid = (jack_position_bits_t)0;
338  fEngineControl->fTransport.RequestNewPos(&new_pos);
339  //jack_transport_locate(netj.client, (pkthdr->transport_frame));
340  jack_info("transport is stopped locate to %d", pkthdr->transport_frame);
341  }
342  if (local_trans_state != JackTransportStopped)
343  //jack_transport_stop(netj.client);
344  fEngineControl->fTransport.SetCommand(TransportCommandStop);
345  break;
346 
347  case JackTransportRolling:
348  netj.sync_state = 1;
349  // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) {
350  // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size));
351  // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size);
352  // }
353  if (local_trans_state != JackTransportRolling)
354  fEngineControl->fTransport.SetState(JackTransportRolling);
355  break;
356 
357  case JackTransportLooping:
358  break;
359  }
360 #endif
361  }
362 
363  render_payload_to_jack_ports (netj.bitdepth, packet_bufX, netj.net_period_down, netj.capture_ports, netj.capture_srcs, netj.period_size, netj.dont_htonl_floats);
364  packet_cache_release_packet(netj.packcache, netj.expected_framecnt);
365  return 0;
366 }
367 
368 int JackNetOneDriver::Write()
369 {
370  int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0);
371  uint32_t *packet_buf, *packet_bufX;
372 
373  int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header);
374  jacknet_packet_header *pkthdr;
375 
376  packet_buf = (uint32_t *) alloca(packet_size);
377  pkthdr = (jacknet_packet_header *)packet_buf;
378 
379  if (netj.running_free) {
380  return 0;
381  }
382 
383  // offset packet_bufX by the packetheader.
384  packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
385 
386  pkthdr->sync_state = syncstate;;
387  pkthdr->latency = netj.time_to_deadline;
388  //printf("time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness);
389  pkthdr->framecnt = netj.expected_framecnt;
390 
391  render_jack_ports_to_payload(netj.bitdepth, netj.playback_ports, netj.playback_srcs, netj.period_size, packet_bufX, netj.net_period_up, netj.dont_htonl_floats);
392 
393  packet_header_hton(pkthdr);
394  if (netj.srcaddress_valid) {
395  unsigned int r;
396  static const int flag = 0;
397 
398  if (netj.reply_port)
399  netj.syncsource_address.sin_port = htons(netj.reply_port);
400 
401  for (r = 0; r < netj.redundancy; r++)
402  netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size,
403  flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu);
404  }
405  return 0;
406 }
407 
408 void
409 JackNetOneDriver::FreePorts ()
410 {
411  JSList *node = netj.capture_ports;
412 
413  while (node != NULL) {
414  JSList *this_node = node;
415  jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
416  node = jack_slist_remove_link(node, this_node);
417  jack_slist_free_1(this_node);
418  fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
419  }
420  netj.capture_ports = NULL;
421 
422  node = netj.playback_ports;
423  while (node != NULL) {
424  JSList *this_node = node;
425  jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
426  node = jack_slist_remove_link(node, this_node);
427  jack_slist_free_1(this_node);
428  fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
429  }
430  netj.playback_ports = NULL;
431 
432  if (netj.bitdepth == CELT_MODE) {
433 #if HAVE_CELT
434  node = netj.playback_srcs;
435  while (node != NULL) {
436  JSList *this_node = node;
437  CELTEncoder *enc = (CELTEncoder *) node->data;
438  node = jack_slist_remove_link(node, this_node);
439  jack_slist_free_1(this_node);
440  celt_encoder_destroy(enc);
441  }
442  netj.playback_srcs = NULL;
443 
444  node = netj.capture_srcs;
445  while (node != NULL) {
446  JSList *this_node = node;
447  CELTDecoder *dec = (CELTDecoder *) node->data;
448  node = jack_slist_remove_link(node, this_node);
449  jack_slist_free_1(this_node);
450  celt_decoder_destroy(dec);
451  }
452  netj.capture_srcs = NULL;
453 #endif
454  } else {
455 #if HAVE_SAMPLERATE
456  node = netj.playback_srcs;
457  while (node != NULL) {
458  JSList *this_node = node;
459  SRC_STATE *state = (SRC_STATE *) node->data;
460  node = jack_slist_remove_link(node, this_node);
461  jack_slist_free_1(this_node);
462  src_delete(state);
463  }
464  netj.playback_srcs = NULL;
465 
466  node = netj.capture_srcs;
467  while (node != NULL) {
468  JSList *this_node = node;
469  SRC_STATE *state = (SRC_STATE *) node->data;
470  node = jack_slist_remove_link(node, this_node);
471  jack_slist_free_1(this_node);
472  src_delete(state);
473  }
474  netj.capture_srcs = NULL;
475 #endif
476  }
477 }
478 
479 //Render functions--------------------------------------------------------------------
480 
481 // render functions for float
482 void
483 JackNetOneDriver::render_payload_to_jack_ports_float(void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats)
484 {
485  uint32_t chn = 0;
486  JSList *node = capture_ports;
487 #if HAVE_SAMPLERATE
488  JSList *src_node = capture_srcs;
489 #endif
490 
491  uint32_t *packet_bufX = (uint32_t *)packet_payload;
492 
493  if (!packet_payload)
494  return;
495 
496  while (node != NULL) {
497  unsigned int i;
498  int_float_t val;
499 #if HAVE_SAMPLERATE
500  SRC_DATA src;
501 #endif
502  jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
503  JackPort *port = fGraphManager->GetPort(port_index);
504 
505  jack_default_audio_sample_t* buf =
506  (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
507 
508  const char *porttype = port->GetType();
509 
510  if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
511 #if HAVE_SAMPLERATE
512  // audio port, resample if necessary
513  if (net_period_down != nframes) {
514  SRC_STATE *src_state = (SRC_STATE *)src_node->data;
515  for (i = 0; i < net_period_down; i++) {
516  packet_bufX[i] = ntohl (packet_bufX[i]);
517  }
518 
519  src.data_in = (float *) packet_bufX;
520  src.input_frames = net_period_down;
521 
522  src.data_out = buf;
523  src.output_frames = nframes;
524 
525  src.src_ratio = (float) nframes / (float) net_period_down;
526  src.end_of_input = 0;
527 
528  src_set_ratio (src_state, src.src_ratio);
529  src_process (src_state, &src);
530  src_node = jack_slist_next (src_node);
531  } else
532 #endif
533  {
534  if (dont_htonl_floats) {
535  memcpy(buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t));
536  } else {
537  for (i = 0; i < net_period_down; i++) {
538  val.i = packet_bufX[i];
539  val.i = ntohl (val.i);
540  buf[i] = val.f;
541  }
542  }
543  }
544  } else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
545  // midi port, decode midi events
546  // convert the data buffer to a standard format (uint32_t based)
547  unsigned int buffer_size_uint32 = net_period_down;
548  uint32_t * buffer_uint32 = (uint32_t*)packet_bufX;
549  decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
550  }
551  packet_bufX = (packet_bufX + net_period_down);
552  node = jack_slist_next (node);
553  chn++;
554  }
555 }
556 
557 void
558 JackNetOneDriver::render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats)
559 {
560  uint32_t chn = 0;
561  JSList *node = playback_ports;
562 #if HAVE_SAMPLERATE
563  JSList *src_node = playback_srcs;
564 #endif
565 
566  uint32_t *packet_bufX = (uint32_t *) packet_payload;
567 
568  while (node != NULL) {
569 #if HAVE_SAMPLERATE
570  SRC_DATA src;
571 #endif
572  unsigned int i;
573  int_float_t val;
574  jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
575  JackPort *port = fGraphManager->GetPort(port_index);
576 
577  jack_default_audio_sample_t* buf =
578  (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
579 
580  const char *porttype = port->GetType();
581 
582  if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
583  // audio port, resample if necessary
584 
585 #if HAVE_SAMPLERATE
586  if (net_period_up != nframes) {
587  SRC_STATE *src_state = (SRC_STATE *) src_node->data;
588  src.data_in = buf;
589  src.input_frames = nframes;
590 
591  src.data_out = (float *) packet_bufX;
592  src.output_frames = net_period_up;
593 
594  src.src_ratio = (float) net_period_up / (float) nframes;
595  src.end_of_input = 0;
596 
597  src_set_ratio (src_state, src.src_ratio);
598  src_process (src_state, &src);
599 
600  for (i = 0; i < net_period_up; i++) {
601  packet_bufX[i] = htonl (packet_bufX[i]);
602  }
603  src_node = jack_slist_next (src_node);
604  } else
605 #endif
606  {
607  if (dont_htonl_floats) {
608  memcpy(packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t));
609  } else {
610  for (i = 0; i < net_period_up; i++) {
611  val.f = buf[i];
612  val.i = htonl (val.i);
613  packet_bufX[i] = val.i;
614  }
615  }
616  }
617  } else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
618  // encode midi events from port to packet
619  // convert the data buffer to a standard format (uint32_t based)
620  unsigned int buffer_size_uint32 = net_period_up;
621  uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
622  encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
623  }
624  packet_bufX = (packet_bufX + net_period_up);
625  node = jack_slist_next (node);
626  chn++;
627  }
628 }
629 
630 #if HAVE_CELT
631 // render functions for celt.
632 void
633 JackNetOneDriver::render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes)
634 {
635  uint32_t chn = 0;
636  JSList *node = capture_ports;
637  JSList *src_node = capture_srcs;
638  unsigned char *packet_bufX = (unsigned char *)packet_payload;
639 
640  while (node != NULL) {
641  jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data;
642  JackPort *port = fGraphManager->GetPort(port_index);
643 
644  jack_default_audio_sample_t* buf =
645  (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
646 
647  const char *portname = port->GetType();
648 
649  if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
650  // audio port, decode celt data.
651  CELTDecoder *decoder = (CELTDecoder *)src_node->data;
652 
653 #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
654  if (!packet_payload)
655  celt_decode_float(decoder, NULL, net_period_down, buf, nframes);
656  else
657  celt_decode_float(decoder, packet_bufX, net_period_down, buf, nframes);
658 #else
659  if (!packet_payload)
660  celt_decode_float(decoder, NULL, net_period_down, buf);
661  else
662  celt_decode_float(decoder, packet_bufX, net_period_down, buf);
663 #endif
664 
665  src_node = jack_slist_next (src_node);
666  } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
667  // midi port, decode midi events
668  // convert the data buffer to a standard format (uint32_t based)
669  unsigned int buffer_size_uint32 = net_period_down / 2;
670  uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
671  if (packet_payload)
672  decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
673  }
674  packet_bufX = (packet_bufX + net_period_down);
675  node = jack_slist_next (node);
676  chn++;
677  }
678 }
679 
680 void
681 JackNetOneDriver::render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up)
682 {
683  uint32_t chn = 0;
684  JSList *node = playback_ports;
685  JSList *src_node = playback_srcs;
686 
687  unsigned char *packet_bufX = (unsigned char *)packet_payload;
688 
689  while (node != NULL) {
690  jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data;
691  JackPort *port = fGraphManager->GetPort(port_index);
692 
693  jack_default_audio_sample_t* buf =
694  (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
695 
696  const char *portname = port->GetType();
697 
698  if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
699  // audio port, encode celt data.
700 
701  int encoded_bytes;
702  jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes);
703  memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t));
704  CELTEncoder *encoder = (CELTEncoder *)src_node->data;
705 #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
706  encoded_bytes = celt_encode_float(encoder, floatbuf, nframes, packet_bufX, net_period_up);
707 #else
708  encoded_bytes = celt_encode_float(encoder, floatbuf, NULL, packet_bufX, net_period_up);
709 #endif
710  if (encoded_bytes != (int)net_period_up)
711  jack_error("something in celt changed. netjack needs to be changed to handle this.");
712  src_node = jack_slist_next(src_node);
713  } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
714  // encode midi events from port to packet
715  // convert the data buffer to a standard format (uint32_t based)
716  unsigned int buffer_size_uint32 = net_period_up / 2;
717  uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
718  encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
719  }
720  packet_bufX = (packet_bufX + net_period_up);
721  node = jack_slist_next (node);
722  chn++;
723  }
724 }
725 
726 #endif
727 /* Wrapper functions with bitdepth argument... */
728 void
729 JackNetOneDriver::render_payload_to_jack_ports (int bitdepth, void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes, int dont_htonl_floats)
730 {
731 #if HAVE_CELT
732  if (bitdepth == CELT_MODE)
733  render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
734  else
735 #endif
736  render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats);
737 }
738 
739 void
740 JackNetOneDriver::render_jack_ports_to_payload (int bitdepth, JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up, int dont_htonl_floats)
741 {
742 #if HAVE_CELT
743  if (bitdepth == CELT_MODE)
744  render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
745  else
746 #endif
747  render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats);
748 }
749 
750 //driver loader-----------------------------------------------------------------------
751 
752 #ifdef __cplusplus
753 extern "C"
754 {
755 #endif
756  SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
757  {
758  jack_driver_desc_t * desc;
761 
762  desc = jack_driver_descriptor_construct("netone", JackDriverMaster, "netjack one slave backend component", &filler);
763 
764  value.ui = 2U;
765  jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 2)", NULL);
766  jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 2)", NULL);
767 
768  value.ui = 1U;
769  jack_driver_descriptor_add_parameter(desc, &filler, "midi-ins", 'I', JackDriverParamUInt, &value, NULL, "Number of midi capture channels (defaults to 1)", NULL);
770  jack_driver_descriptor_add_parameter(desc, &filler, "midi-outs", 'O', JackDriverParamUInt, &value, NULL, "Number of midi playback channels (defaults to 1)", NULL);
771 
772  value.ui = 48000U;
773  jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
774 
775  value.ui = 1024U;
776  jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
777 
778  value.ui = 5U;
779  jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
780 
781  value.ui = 3000U;
782  jack_driver_descriptor_add_parameter(desc, &filler, "listen-port", 'l', JackDriverParamUInt, &value, NULL, "The socket port we are listening on for sync packets", NULL);
783 
784  value.ui = 1U;
785  jack_driver_descriptor_add_parameter(desc, &filler, "factor", 'f', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction", NULL);
786 
787  value.ui = 0U;
788  jack_driver_descriptor_add_parameter(desc, &filler, "upstream-factor", 'u', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction on the upstream", NULL);
789 
790 #if HAVE_CELT
791  value.ui = 0U;
792  jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamUInt, &value, NULL, "Set CELT encoding and number of kbits per channel", NULL);
793 #endif
794  value.ui = 0U;
795  jack_driver_descriptor_add_parameter(desc, &filler, "bit-depth", 'b', JackDriverParamUInt, &value, NULL, "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)", NULL);
796 
797  value.i = true;
798  jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamBool, &value, NULL, "Whether to slave the transport to the master transport", NULL);
799 
800  value.ui = true;
801  jack_driver_descriptor_add_parameter(desc, &filler, "autoconf", 'a', JackDriverParamBool, &value, NULL, "Whether to use Autoconfig, or just start", NULL);
802 
803  value.ui = 1U;
804  jack_driver_descriptor_add_parameter(desc, &filler, "redundancy", 'R', JackDriverParamUInt, &value, NULL, "Send packets N times", NULL);
805 
806  value.ui = false;
807  jack_driver_descriptor_add_parameter(desc, &filler, "native-endian", 'e', JackDriverParamBool, &value, NULL, "Dont convert samples to network byte order", NULL);
808 
809  value.i = 0;
810  jack_driver_descriptor_add_parameter(desc, &filler, "jitterval", 'J', JackDriverParamInt, &value, NULL, "Attempted jitterbuffer microseconds on master", NULL);
811 
812  value.i = false;
813  jack_driver_descriptor_add_parameter(desc, &filler, "always-deadline", 'D', JackDriverParamBool, &value, NULL, "Always use deadline", NULL);
814 
815  return desc;
816  }
817 
818  SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
819  {
820  jack_nframes_t sample_rate = 48000;
821  jack_nframes_t resample_factor = 1;
822  jack_nframes_t period_size = 1024;
823  unsigned int capture_ports = 2;
824  unsigned int playback_ports = 2;
825  unsigned int capture_ports_midi = 1;
826  unsigned int playback_ports_midi = 1;
827  unsigned int listen_port = 3000;
828  unsigned int bitdepth = 0;
829  unsigned int handle_transport_sync = 1;
830  unsigned int use_autoconfig = 1;
831  unsigned int latency = 5;
832  unsigned int redundancy = 1;
833  unsigned int mtu = 1400;
834 #if HAVE_SAMPLERATE
835  unsigned int resample_factor_up = 1;
836 #endif
837  int dont_htonl_floats = 0;
838  int always_deadline = 0;
839  int jitter_val = 0;
840  const JSList * node;
841  const jack_driver_param_t * param;
842 
843  for (node = params; node; node = jack_slist_next(node)) {
844  param = (const jack_driver_param_t*) node->data;
845  switch (param->character) {
846  case 'i':
847  capture_ports = param->value.ui;
848  break;
849 
850  case 'o':
851  playback_ports = param->value.ui;
852  break;
853 
854  case 'I':
855  capture_ports_midi = param->value.ui;
856  break;
857 
858  case 'O':
859  playback_ports_midi = param->value.ui;
860  break;
861 
862  case 'r':
863  sample_rate = param->value.ui;
864  break;
865 
866  case 'p':
867  period_size = param->value.ui;
868  break;
869 
870  case 'l':
871  listen_port = param->value.ui;
872  break;
873 
874  case 'f':
875 #if HAVE_SAMPLERATE
876  resample_factor = param->value.ui;
877 #else
878  jack_error("not built with libsamplerate support");
879  return NULL;
880 #endif
881  break;
882 
883  case 'u':
884 #if HAVE_SAMPLERATE
885  resample_factor_up = param->value.ui;
886 #else
887  jack_error("not built with libsamplerate support");
888  return NULL;
889 #endif
890  break;
891 
892  case 'b':
893  bitdepth = param->value.ui;
894  break;
895 
896  case 'c':
897 #if HAVE_CELT
898  bitdepth = CELT_MODE;
899  resample_factor = param->value.ui;
900 #else
901  jack_error("not built with celt support");
902  return NULL;
903 #endif
904  break;
905 
906  case 't':
907  handle_transport_sync = param->value.ui;
908  break;
909 
910  case 'a':
911  use_autoconfig = param->value.ui;
912  break;
913 
914  case 'n':
915  latency = param->value.ui;
916  break;
917 
918  case 'R':
919  redundancy = param->value.ui;
920  break;
921 
922  case 'H':
923  dont_htonl_floats = param->value.ui;
924  break;
925 
926  case 'J':
927  jitter_val = param->value.i;
928  break;
929 
930  case 'D':
931  always_deadline = param->value.ui;
932  break;
933  }
934  }
935 
936  try {
938  new Jack::JackNetOneDriver("system", "net_pcm", engine, table, listen_port, mtu,
939  capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
940  sample_rate, period_size, resample_factor,
941  "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
942  dont_htonl_floats, always_deadline, jitter_val));
943 
944  if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports,
945  0, "from_master_", "to_master_", 0, 0) == 0) {
946  return driver;
947  } else {
948  delete driver;
949  return NULL;
950  }
951 
952  } catch (...) {
953  return NULL;
954  }
955  }
956 
957 #ifdef __cplusplus
958 }
959 #endif
960 }