Correct netjack2 components help.
[jack2.git] / common / JackNetOneDriver.cpp
blobfd213bacc1785f69504abd59101aab42cd25e962
1 /*
2 Copyright (C) 2008-2011 Torben Horn
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.
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.
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.
19 #ifdef WIN32
20 #include <malloc.h>
21 #endif
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"
31 #include "netjack.h"
32 #include "netjack_packet.h"
34 #if HAVE_SAMPLERATE
35 #include <samplerate.h>
36 #endif
38 #if HAVE_CELT
39 #include <celt/celt.h>
40 #endif
42 #define MIN(x,y) ((x)<(y) ? (x) : (y))
44 using namespace std;
46 namespace Jack
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)
55 jack_log("JackNetOneDriver::JackNetOneDriver port %d", port);
57 #ifdef WIN32
58 WSADATA wsa;
59 WSAStartup(MAKEWORD(2, 0), &wsa);
60 #endif
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,
75 bitdepth,
76 use_autoconfig,
77 latency,
78 redundancy,
79 dont_htonl_floats,
80 always_deadline,
81 jitter_val);
84 JackNetOneDriver::~JackNetOneDriver()
86 // No destructor yet.
89 //open, close, attach and detach------------------------------------------------------
91 int JackNetOneDriver::Close()
93 // Generic audio driver close
94 int res = JackWaiterDriver::Close();
96 FreePorts();
97 netjack_release(&netj);
98 return res;
101 int JackNetOneDriver::Attach()
103 return 0;
106 int JackNetOneDriver::Detach()
108 return 0;
111 int JackNetOneDriver::AllocPorts()
113 jack_port_id_t port_index;
114 char buf[64];
115 unsigned int chn;
117 //if (netj.handle_transport_sync)
118 // jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
120 for (chn = 0; chn < netj.capture_channels_audio; chn++) {
121 snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
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;
128 //port = fGraphManager->GetPort(port_index);
130 netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
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
157 for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
158 snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
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;
165 //port = fGraphManager->GetPort(port_index);
167 netj.capture_ports =
168 jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
171 for (chn = 0; chn < netj.playback_channels_audio; chn++) {
172 snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
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;
179 //port = fGraphManager->GetPort(port_index);
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
201 for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
202 snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
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;
209 //port = fGraphManager->GetPort(port_index);
211 netj.playback_ports =
212 jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
214 return 0;
217 //init and restart--------------------------------------------------------------------
218 bool JackNetOneDriver::Initialize()
220 jack_log("JackNetOneDriver::Init");
222 FreePorts();
223 netjack_release(&netj);
225 //display some additional infos
226 jack_info("NetOne driver started");
227 if (netjack_startup(&netj)) {
228 return false;
231 //register jack ports
232 if (AllocPorts() != 0) {
233 jack_error("Can't allocate ports.");
234 return false;
237 //monitor
238 //driver parametering
239 JackTimedDriver::SetBufferSize(netj.period_size);
240 JackTimedDriver::SetSampleRate(netj.sample_rate);
242 JackDriver::NotifyBufferSize(netj.period_size);
243 JackDriver::NotifySampleRate(netj.sample_rate);
245 //transport engine parametering
246 fEngineControl->fTransport.SetNetworkSync(true);
247 return true;
251 //jack ports and buffers--------------------------------------------------------------
253 //driver processes--------------------------------------------------------------------
255 int JackNetOneDriver::Read()
257 int delay;
258 delay = netjack_wait(&netj);
259 if (delay) {
260 NotifyXRun(fBeginDateUst, (float) delay);
261 jack_error("netxruns... duration: %dms", delay / 1000);
264 if ((netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2)
265 JackTools::ThrowJackNetException();
267 //netjack_read(&netj, netj.period_size);
268 JackDriver::CycleTakeBeginTime();
270 jack_position_t local_trans_pos;
271 jack_transport_state_t local_trans_state;
273 unsigned int *packet_buf, *packet_bufX;
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;
280 packet_buf = netj.rx_buf;
282 jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
284 packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
286 netj.reply_port = pkthdr->reply_port;
287 netj.latency = pkthdr->latency;
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);
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);
300 // read local transport info....
301 //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
303 local_trans_state = fEngineControl->fTransport.Query(&local_trans_pos);
305 // Now check if we have to start or stop local transport to sync to remote...
306 switch (pkthdr->transport_state) {
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...");
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;
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);
330 break;
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);
342 if (local_trans_state != JackTransportStopped)
343 //jack_transport_stop(netj.client);
344 fEngineControl->fTransport.SetCommand(TransportCommandStop);
345 break;
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;
357 case JackTransportLooping:
358 break;
360 #endif
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;
368 int JackNetOneDriver::Write()
370 int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0);
371 uint32_t *packet_buf, *packet_bufX;
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;
376 packet_buf = (uint32_t *) alloca(packet_size);
377 pkthdr = (jacknet_packet_header *)packet_buf;
379 if (netj.running_free) {
380 return 0;
383 // offset packet_bufX by the packetheader.
384 packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
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;
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);
393 packet_header_hton(pkthdr);
394 if (netj.srcaddress_valid) {
395 unsigned int r;
396 static const int flag = 0;
398 if (netj.reply_port)
399 netj.syncsource_address.sin_port = htons(netj.reply_port);
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);
405 return 0;
408 void
409 JackNetOneDriver::FreePorts ()
411 JSList *node = netj.capture_ports;
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);
420 netj.capture_ports = NULL;
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);
430 netj.playback_ports = NULL;
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);
442 netj.playback_srcs = NULL;
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);
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);
464 netj.playback_srcs = NULL;
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);
474 netj.capture_srcs = NULL;
475 #endif
479 //Render functions--------------------------------------------------------------------
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)
485 uint32_t chn = 0;
486 JSList *node = capture_ports;
487 #if HAVE_SAMPLERATE
488 JSList *src_node = capture_srcs;
489 #endif
491 uint32_t *packet_bufX = (uint32_t *)packet_payload;
493 if (!packet_payload)
494 return;
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);
505 jack_default_audio_sample_t* buf =
506 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
508 const char *porttype = port->GetType();
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]);
519 src.data_in = (float *) packet_bufX;
520 src.input_frames = net_period_down;
522 src.data_out = buf;
523 src.output_frames = nframes;
525 src.src_ratio = (float) nframes / (float) net_period_down;
526 src.end_of_input = 0;
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
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;
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);
551 packet_bufX = (packet_bufX + net_period_down);
552 node = jack_slist_next (node);
553 chn++;
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)
560 uint32_t chn = 0;
561 JSList *node = playback_ports;
562 #if HAVE_SAMPLERATE
563 JSList *src_node = playback_srcs;
564 #endif
566 uint32_t *packet_bufX = (uint32_t *) packet_payload;
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);
577 jack_default_audio_sample_t* buf =
578 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
580 const char *porttype = port->GetType();
582 if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
583 // audio port, resample if necessary
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;
591 src.data_out = (float *) packet_bufX;
592 src.output_frames = net_period_up;
594 src.src_ratio = (float) net_period_up / (float) nframes;
595 src.end_of_input = 0;
597 src_set_ratio (src_state, src.src_ratio);
598 src_process (src_state, &src);
600 for (i = 0; i < net_period_up; i++) {
601 packet_bufX[i] = htonl (packet_bufX[i]);
603 src_node = jack_slist_next (src_node);
604 } else
605 #endif
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;
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);
624 packet_bufX = (packet_bufX + net_period_up);
625 node = jack_slist_next (node);
626 chn++;
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)
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;
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);
644 jack_default_audio_sample_t* buf =
645 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
647 const char *portname = port->GetType();
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;
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
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);
674 packet_bufX = (packet_bufX + net_period_down);
675 node = jack_slist_next (node);
676 chn++;
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)
683 uint32_t chn = 0;
684 JSList *node = playback_ports;
685 JSList *src_node = playback_srcs;
687 unsigned char *packet_bufX = (unsigned char *)packet_payload;
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);
693 jack_default_audio_sample_t* buf =
694 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
696 const char *portname = port->GetType();
698 if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
699 // audio port, encode celt data.
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);
720 packet_bufX = (packet_bufX + net_period_up);
721 node = jack_slist_next (node);
722 chn++;
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)
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);
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)
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);
750 //driver loader-----------------------------------------------------------------------
752 #ifdef __cplusplus
753 extern "C"
755 #endif
757 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
759 jack_driver_desc_t * desc;
760 jack_driver_desc_filler_t filler;
761 jack_driver_param_value_t value;
763 desc = jack_driver_descriptor_construct("netone", JackDriverMaster, "netjack one slave backend component", &filler);
765 value.ui = 2U;
766 jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 2)", NULL);
767 jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 2)", NULL);
769 value.ui = 1U;
770 jack_driver_descriptor_add_parameter(desc, &filler, "midi-ins", 'I', JackDriverParamUInt, &value, NULL, "Number of midi capture channels (defaults to 1)", NULL);
771 jack_driver_descriptor_add_parameter(desc, &filler, "midi-outs", 'O', JackDriverParamUInt, &value, NULL, "Number of midi playback channels (defaults to 1)", NULL);
773 value.ui = 48000U;
774 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
776 value.ui = 1024U;
777 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
779 value.ui = 5U;
780 jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
782 value.ui = 3000U;
783 jack_driver_descriptor_add_parameter(desc, &filler, "listen-port", 'l', JackDriverParamUInt, &value, NULL, "The socket port we are listening on for sync packets", NULL);
785 value.ui = 1U;
786 jack_driver_descriptor_add_parameter(desc, &filler, "factor", 'f', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction", NULL);
788 value.ui = 0U;
789 jack_driver_descriptor_add_parameter(desc, &filler, "upstream-factor", 'u', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction on the upstream", NULL);
791 #if HAVE_CELT
792 value.ui = 0U;
793 jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamUInt, &value, NULL, "Set CELT encoding and number of kbits per channel", NULL);
794 #endif
795 value.ui = 0U;
796 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);
798 value.i = true;
799 jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamBool, &value, NULL, "Whether to slave the transport to the master transport", NULL);
801 value.ui = true;
802 jack_driver_descriptor_add_parameter(desc, &filler, "autoconf", 'a', JackDriverParamBool, &value, NULL, "Whether to use Autoconfig, or just start", NULL);
804 value.ui = 1U;
805 jack_driver_descriptor_add_parameter(desc, &filler, "redundancy", 'R', JackDriverParamUInt, &value, NULL, "Send packets N times", NULL);
807 value.ui = false;
808 jack_driver_descriptor_add_parameter(desc, &filler, "native-endian", 'e', JackDriverParamBool, &value, NULL, "Dont convert samples to network byte order", NULL);
810 value.i = 0;
811 jack_driver_descriptor_add_parameter(desc, &filler, "jitterval", 'J', JackDriverParamInt, &value, NULL, "Attempted jitterbuffer microseconds on master", NULL);
813 value.i = false;
814 jack_driver_descriptor_add_parameter(desc, &filler, "always-deadline", 'D', JackDriverParamBool, &value, NULL, "Always use deadline", NULL);
816 return desc;
819 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
821 jack_nframes_t sample_rate = 48000;
822 jack_nframes_t resample_factor = 1;
823 jack_nframes_t period_size = 1024;
824 unsigned int capture_ports = 2;
825 unsigned int playback_ports = 2;
826 unsigned int capture_ports_midi = 1;
827 unsigned int playback_ports_midi = 1;
828 unsigned int listen_port = 3000;
829 unsigned int bitdepth = 0;
830 unsigned int handle_transport_sync = 1;
831 unsigned int use_autoconfig = 1;
832 unsigned int latency = 5;
833 unsigned int redundancy = 1;
834 unsigned int mtu = 1400;
835 #if HAVE_SAMPLERATE
836 unsigned int resample_factor_up = 1;
837 #endif
838 int dont_htonl_floats = 0;
839 int always_deadline = 0;
840 int jitter_val = 0;
841 const JSList * node;
842 const jack_driver_param_t * param;
844 for (node = params; node; node = jack_slist_next(node)) {
845 param = (const jack_driver_param_t*) node->data;
846 switch (param->character) {
847 case 'i':
848 capture_ports = param->value.ui;
849 break;
851 case 'o':
852 playback_ports = param->value.ui;
853 break;
855 case 'I':
856 capture_ports_midi = param->value.ui;
857 break;
859 case 'O':
860 playback_ports_midi = param->value.ui;
861 break;
863 case 'r':
864 sample_rate = param->value.ui;
865 break;
867 case 'p':
868 period_size = param->value.ui;
869 break;
871 case 'l':
872 listen_port = param->value.ui;
873 break;
875 case 'f':
876 #if HAVE_SAMPLERATE
877 resample_factor = param->value.ui;
878 #else
879 jack_error("not built with libsamplerate support");
880 return NULL;
881 #endif
882 break;
884 case 'u':
885 #if HAVE_SAMPLERATE
886 resample_factor_up = param->value.ui;
887 #else
888 jack_error("not built with libsamplerate support");
889 return NULL;
890 #endif
891 break;
893 case 'b':
894 bitdepth = param->value.ui;
895 break;
897 case 'c':
898 #if HAVE_CELT
899 bitdepth = CELT_MODE;
900 resample_factor = param->value.ui;
901 #else
902 jack_error("not built with celt support");
903 return NULL;
904 #endif
905 break;
907 case 't':
908 handle_transport_sync = param->value.ui;
909 break;
911 case 'a':
912 use_autoconfig = param->value.ui;
913 break;
915 case 'n':
916 latency = param->value.ui;
917 break;
919 case 'R':
920 redundancy = param->value.ui;
921 break;
923 case 'H':
924 dont_htonl_floats = param->value.ui;
925 break;
927 case 'J':
928 jitter_val = param->value.i;
929 break;
931 case 'D':
932 always_deadline = param->value.ui;
933 break;
937 try {
938 Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
939 new Jack::JackNetOneDriver("system", "net_pcm", engine, table, listen_port, mtu,
940 capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
941 sample_rate, period_size, resample_factor,
942 "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
943 dont_htonl_floats, always_deadline, jitter_val));
945 if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports,
946 0, "from_master_", "to_master_", 0, 0) == 0) {
947 return driver;
948 } else {
949 delete driver;
950 return NULL;
953 } catch (...) {
954 return NULL;
958 #ifdef __cplusplus
960 #endif