Remove non-jackdbus man pages
[jackdbus.git] / common / JackNetOneDriver.cpp
blob3985e47571cd90d3c2d5ac74b52a165c9e1168d4
1 /*
2 Copyright (C) 2018 Karl Linden <karl.j.linden@gmail.com>
3 Copyright (C) 2008-2011 Torben Horn
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include <alloca.h>
22 #include "JackNetOneDriver.h"
23 #include "JackEngineControl.h"
24 #include "JackLockedEngine.h"
25 #include "JackGraphManager.h"
26 #include "JackWaitThreadedDriver.h"
27 #include "JackTools.h"
28 #include "driver_interface.h"
30 #include "netjack.h"
31 #include "netjack_packet.h"
33 #if HAVE_SAMPLERATE
34 #include <samplerate.h>
35 #endif
37 #if HAVE_CELT
38 #include <celt/celt.h>
39 #endif
41 #if HAVE_OPUS
42 #include <opus/opus.h>
43 #include <opus/opus_custom.h>
44 #endif
46 #define MIN(x,y) ((x)<(y) ? (x) : (y))
48 using namespace std;
50 namespace Jack
52 JackNetOneDriver::JackNetOneDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
53 int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports,
54 int sample_rate, int period_size, int resample_factor,
55 const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig,
56 int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val)
57 : JackWaiterDriver(name, alias, engine, table)
59 jack_log("JackNetOneDriver::JackNetOneDriver port %d", port);
61 #ifdef WIN32
62 WSADATA wsa;
63 WSAStartup(MAKEWORD(2, 0), &wsa);
64 #endif
66 netjack_init(& (this->netj),
67 NULL, // client
68 name,
69 capture_ports,
70 playback_ports,
71 midi_input_ports,
72 midi_output_ports,
73 sample_rate,
74 period_size,
75 port,
76 transport_sync,
77 resample_factor,
79 bitdepth,
80 use_autoconfig,
81 latency,
82 redundancy,
83 dont_htonl_floats,
84 always_deadline,
85 jitter_val);
88 JackNetOneDriver::~JackNetOneDriver()
90 // No destructor yet.
93 //open, close, attach and detach------------------------------------------------------
95 int JackNetOneDriver::Close()
97 // Generic audio driver close
98 int res = JackWaiterDriver::Close();
100 FreePorts();
101 netjack_release(&netj);
102 return res;
105 int JackNetOneDriver::Attach()
107 return 0;
110 int JackNetOneDriver::Detach()
112 return 0;
115 int JackNetOneDriver::AllocPorts()
117 jack_port_id_t port_index;
118 char buf[64];
119 unsigned int chn;
121 //if (netj.handle_transport_sync)
122 // jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
124 for (chn = 0; chn < netj.capture_channels_audio; chn++) {
125 snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
127 if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
128 CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
129 jack_error("driver: cannot register port for %s", buf);
130 return -1;
132 //port = fGraphManager->GetPort(port_index);
134 netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
136 if (netj.bitdepth == CELT_MODE) {
137 #if HAVE_CELT
138 #if HAVE_CELT_API_0_11
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_custom(celt_mode, 1, NULL));
142 #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
143 celt_int32 lookahead;
144 CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
145 netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode, 1, NULL));
146 #else
147 celt_int32_t lookahead;
148 CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL);
149 netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode));
150 #endif
151 celt_mode_info(celt_mode, CELT_GET_LOOKAHEAD, &lookahead);
152 netj.codec_latency = 2 * lookahead;
153 #endif
154 } else if (netj.bitdepth == OPUS_MODE) {
155 #if HAVE_OPUS
156 OpusCustomMode *opus_mode = opus_custom_mode_create(netj.sample_rate, netj.period_size, NULL); // XXX free me in the end
157 OpusCustomDecoder *decoder = opus_custom_decoder_create( opus_mode, 1, NULL );
158 netj.capture_srcs = jack_slist_append(netj.capture_srcs, decoder);
159 #endif
160 } else {
161 #if HAVE_SAMPLERATE
162 netj.capture_srcs = jack_slist_append(netj.capture_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
163 #endif
167 for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
168 snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
170 if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
171 CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
172 jack_error("driver: cannot register port for %s", buf);
173 return -1;
175 //port = fGraphManager->GetPort(port_index);
177 netj.capture_ports =
178 jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
181 for (chn = 0; chn < netj.playback_channels_audio; chn++) {
182 snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
184 if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
185 PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
186 jack_error("driver: cannot register port for %s", buf);
187 return -1;
189 //port = fGraphManager->GetPort(port_index);
191 netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
192 if (netj.bitdepth == CELT_MODE) {
193 #if HAVE_CELT
194 #if HAVE_CELT_API_0_11
195 CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
196 netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom(celt_mode, 1, NULL));
197 #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
198 CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
199 netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode, 1, NULL));
200 #else
201 CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL);
202 netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode));
203 #endif
204 #endif
205 } else if (netj.bitdepth == OPUS_MODE) {
206 #if HAVE_OPUS
207 const int kbps = netj.resample_factor;
208 jack_error("NEW ONE OPUS ENCODER 128 <> %d!!", kbps);
209 int err;
210 OpusCustomMode *opus_mode = opus_custom_mode_create( netj.sample_rate, netj.period_size, &err ); // XXX free me in the end
211 if (err != OPUS_OK) { jack_error("opus mode failed"); }
212 OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, &err );
213 if (err != OPUS_OK) { jack_error("opus mode failed"); }
214 opus_custom_encoder_ctl(oe, OPUS_SET_BITRATE(kbps*1024)); // bits per second
215 opus_custom_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10));
216 opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
217 opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY));
218 netj.playback_srcs = jack_slist_append(netj.playback_srcs, oe);
219 #endif
220 } else {
221 #if HAVE_SAMPLERATE
222 netj.playback_srcs = jack_slist_append(netj.playback_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
223 #endif
226 for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
227 snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
229 if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
230 PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
231 jack_error("driver: cannot register port for %s", buf);
232 return -1;
234 //port = fGraphManager->GetPort(port_index);
236 netj.playback_ports =
237 jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
239 return 0;
242 //init and restart--------------------------------------------------------------------
243 bool JackNetOneDriver::Initialize()
245 jack_log("JackNetOneDriver::Init");
247 FreePorts();
248 netjack_release(&netj);
250 //display some additional infos
251 jack_info("NetOne driver started");
252 if (netjack_startup(&netj)) {
253 return false;
256 //register jack ports
257 if (AllocPorts() != 0) {
258 jack_error("Can't allocate ports.");
259 return false;
262 //monitor
263 //driver parametering
264 JackTimedDriver::SetBufferSize(netj.period_size);
265 JackTimedDriver::SetSampleRate(netj.sample_rate);
267 JackDriver::NotifyBufferSize(netj.period_size);
268 JackDriver::NotifySampleRate(netj.sample_rate);
270 //transport engine parametering
271 fEngineControl->fTransport.SetNetworkSync(true);
272 return true;
276 //jack ports and buffers--------------------------------------------------------------
278 //driver processes--------------------------------------------------------------------
280 int JackNetOneDriver::Read()
282 int delay;
283 delay = netjack_wait(&netj);
284 if (delay) {
285 NotifyXRun(fBeginDateUst, (float) delay);
286 jack_error("netxruns... duration: %dms", delay / 1000);
289 if ((netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2)
290 throw JackNetException();
292 //netjack_read(&netj, netj.period_size);
293 JackDriver::CycleTakeBeginTime();
295 jack_position_t local_trans_pos;
296 jack_transport_state_t local_trans_state;
298 unsigned int *packet_buf, *packet_bufX;
300 if (! netj.packet_data_valid) {
301 jack_log("data not valid");
302 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);
303 return 0;
305 packet_buf = netj.rx_buf;
307 jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
309 packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
311 netj.reply_port = pkthdr->reply_port;
312 netj.latency = pkthdr->latency;
314 // Special handling for latency=0
315 if (netj.latency == 0)
316 netj.resync_threshold = 0;
317 else
318 netj.resync_threshold = MIN(15, pkthdr->latency - 1);
320 // check whether, we should handle the transport sync stuff, or leave trnasports untouched.
321 if (netj.handle_transport_sync) {
322 #if 1
323 unsigned int compensated_tranport_pos = (pkthdr->transport_frame + (pkthdr->latency * netj.period_size) + netj.codec_latency);
325 // read local transport info....
326 //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
328 local_trans_state = fEngineControl->fTransport.Query(&local_trans_pos);
330 // Now check if we have to start or stop local transport to sync to remote...
331 switch (pkthdr->transport_state) {
333 case JackTransportStarting:
334 // the master transport is starting... so we set our reply to the sync_callback;
335 if (local_trans_state == JackTransportStopped) {
336 fEngineControl->fTransport.SetCommand(TransportCommandStart);
337 //jack_transport_start(netj.client);
338 //last_transport_state = JackTransportStopped;
339 netj.sync_state = 0;
340 jack_info("locally stopped... starting...");
343 if (local_trans_pos.frame != compensated_tranport_pos) {
344 jack_position_t new_pos = local_trans_pos;
345 new_pos.frame = compensated_tranport_pos + 2 * netj.period_size;
346 new_pos.valid = (jack_position_bits_t) 0;
349 fEngineControl->fTransport.RequestNewPos(&new_pos);
350 //jack_transport_locate(netj.client, compensated_tranport_pos);
351 //last_transport_state = JackTransportRolling;
352 netj.sync_state = 0;
353 jack_info("starting locate to %d", compensated_tranport_pos);
355 break;
357 case JackTransportStopped:
358 netj.sync_state = 1;
359 if (local_trans_pos.frame != (pkthdr->transport_frame)) {
360 jack_position_t new_pos = local_trans_pos;
361 new_pos.frame = pkthdr->transport_frame;
362 new_pos.valid = (jack_position_bits_t)0;
363 fEngineControl->fTransport.RequestNewPos(&new_pos);
364 //jack_transport_locate(netj.client, (pkthdr->transport_frame));
365 jack_info("transport is stopped locate to %d", pkthdr->transport_frame);
367 if (local_trans_state != JackTransportStopped)
368 //jack_transport_stop(netj.client);
369 fEngineControl->fTransport.SetCommand(TransportCommandStop);
370 break;
372 case JackTransportRolling:
373 netj.sync_state = 1;
374 // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) {
375 // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size));
376 // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size);
377 // }
378 if (local_trans_state != JackTransportRolling)
379 fEngineControl->fTransport.SetState(JackTransportRolling);
380 break;
382 case JackTransportLooping:
383 break;
385 #endif
388 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);
389 packet_cache_release_packet(netj.packcache, netj.expected_framecnt);
390 return 0;
393 int JackNetOneDriver::Write()
395 int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0);
396 uint32_t *packet_buf, *packet_bufX;
398 int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header);
399 jacknet_packet_header *pkthdr;
401 packet_buf = (uint32_t *) alloca(packet_size);
402 pkthdr = (jacknet_packet_header *)packet_buf;
404 if (netj.running_free) {
405 return 0;
408 // offset packet_bufX by the packetheader.
409 packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
411 pkthdr->sync_state = syncstate;;
412 pkthdr->latency = netj.time_to_deadline;
413 //printf("time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness);
414 pkthdr->framecnt = netj.expected_framecnt;
416 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);
418 packet_header_hton(pkthdr);
419 if (netj.srcaddress_valid) {
420 unsigned int r;
421 static const int flag = 0;
423 if (netj.reply_port)
424 netj.syncsource_address.sin_port = htons(netj.reply_port);
426 for (r = 0; r < netj.redundancy; r++)
427 netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size,
428 flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu);
430 return 0;
433 void
434 JackNetOneDriver::FreePorts ()
436 JSList *node = netj.capture_ports;
438 while (node != NULL) {
439 JSList *this_node = node;
440 jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
441 node = jack_slist_remove_link(node, this_node);
442 jack_slist_free_1(this_node);
443 fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
445 netj.capture_ports = NULL;
447 node = netj.playback_ports;
448 while (node != NULL) {
449 JSList *this_node = node;
450 jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
451 node = jack_slist_remove_link(node, this_node);
452 jack_slist_free_1(this_node);
453 fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
455 netj.playback_ports = NULL;
457 if (netj.bitdepth == CELT_MODE) {
458 #if HAVE_CELT
459 node = netj.playback_srcs;
460 while (node != NULL) {
461 JSList *this_node = node;
462 CELTEncoder *enc = (CELTEncoder *) node->data;
463 node = jack_slist_remove_link(node, this_node);
464 jack_slist_free_1(this_node);
465 celt_encoder_destroy(enc);
467 netj.playback_srcs = NULL;
469 node = netj.capture_srcs;
470 while (node != NULL) {
471 JSList *this_node = node;
472 CELTDecoder *dec = (CELTDecoder *) node->data;
473 node = jack_slist_remove_link(node, this_node);
474 jack_slist_free_1(this_node);
475 celt_decoder_destroy(dec);
477 netj.capture_srcs = NULL;
478 #endif
479 } else if (netj.bitdepth == OPUS_MODE) {
480 #if HAVE_OPUS
481 node = netj.playback_srcs;
482 while (node != NULL) {
483 JSList *this_node = node;
484 OpusCustomEncoder *enc = (OpusCustomEncoder *) node->data;
485 node = jack_slist_remove_link(node, this_node);
486 jack_slist_free_1(this_node);
487 opus_custom_encoder_destroy(enc);
489 netj.playback_srcs = NULL;
491 node = netj.capture_srcs;
492 while (node != NULL) {
493 JSList *this_node = node;
494 OpusCustomDecoder *dec = (OpusCustomDecoder *) node->data;
495 node = jack_slist_remove_link(node, this_node);
496 jack_slist_free_1(this_node);
497 opus_custom_decoder_destroy(dec);
499 netj.capture_srcs = NULL;
500 #endif
501 } else {
502 #if HAVE_SAMPLERATE
503 node = netj.playback_srcs;
504 while (node != NULL) {
505 JSList *this_node = node;
506 SRC_STATE *state = (SRC_STATE *) node->data;
507 node = jack_slist_remove_link(node, this_node);
508 jack_slist_free_1(this_node);
509 src_delete(state);
511 netj.playback_srcs = NULL;
513 node = netj.capture_srcs;
514 while (node != NULL) {
515 JSList *this_node = node;
516 SRC_STATE *state = (SRC_STATE *) node->data;
517 node = jack_slist_remove_link(node, this_node);
518 jack_slist_free_1(this_node);
519 src_delete(state);
521 netj.capture_srcs = NULL;
522 #endif
526 //Render functions--------------------------------------------------------------------
528 // render functions for float
529 void
530 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)
532 uint32_t chn = 0;
533 JSList *node = capture_ports;
534 #if HAVE_SAMPLERATE
535 JSList *src_node = capture_srcs;
536 #endif
538 uint32_t *packet_bufX = (uint32_t *)packet_payload;
540 if (!packet_payload)
541 return;
543 while (node != NULL) {
544 unsigned int i;
545 int_float_t val;
546 #if HAVE_SAMPLERATE
547 SRC_DATA src;
548 #endif
549 jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
550 JackPort *port = fGraphManager->GetPort(port_index);
552 jack_default_audio_sample_t* buf =
553 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
555 const char *porttype = port->GetType();
557 if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
558 #if HAVE_SAMPLERATE
559 // audio port, resample if necessary
560 if (net_period_down != nframes) {
561 SRC_STATE *src_state = (SRC_STATE *)src_node->data;
562 for (i = 0; i < net_period_down; i++) {
563 packet_bufX[i] = ntohl (packet_bufX[i]);
566 src.data_in = (float *) packet_bufX;
567 src.input_frames = net_period_down;
569 src.data_out = buf;
570 src.output_frames = nframes;
572 src.src_ratio = (float) nframes / (float) net_period_down;
573 src.end_of_input = 0;
575 src_set_ratio (src_state, src.src_ratio);
576 src_process (src_state, &src);
577 src_node = jack_slist_next (src_node);
578 } else
579 #endif
581 if (dont_htonl_floats) {
582 memcpy(buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t));
583 } else {
584 for (i = 0; i < net_period_down; i++) {
585 val.i = packet_bufX[i];
586 val.i = ntohl (val.i);
587 buf[i] = val.f;
591 } else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
592 // midi port, decode midi events
593 // convert the data buffer to a standard format (uint32_t based)
594 unsigned int buffer_size_uint32 = net_period_down;
595 uint32_t * buffer_uint32 = (uint32_t*)packet_bufX;
596 decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
598 packet_bufX = (packet_bufX + net_period_down);
599 node = jack_slist_next (node);
600 chn++;
604 void
605 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)
607 uint32_t chn = 0;
608 JSList *node = playback_ports;
609 #if HAVE_SAMPLERATE
610 JSList *src_node = playback_srcs;
611 #endif
613 uint32_t *packet_bufX = (uint32_t *) packet_payload;
615 while (node != NULL) {
616 #if HAVE_SAMPLERATE
617 SRC_DATA src;
618 #endif
619 unsigned int i;
620 int_float_t val;
621 jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
622 JackPort *port = fGraphManager->GetPort(port_index);
624 jack_default_audio_sample_t* buf =
625 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
627 const char *porttype = port->GetType();
629 if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
630 // audio port, resample if necessary
632 #if HAVE_SAMPLERATE
633 if (net_period_up != nframes) {
634 SRC_STATE *src_state = (SRC_STATE *) src_node->data;
635 src.data_in = buf;
636 src.input_frames = nframes;
638 src.data_out = (float *) packet_bufX;
639 src.output_frames = net_period_up;
641 src.src_ratio = (float) net_period_up / (float) nframes;
642 src.end_of_input = 0;
644 src_set_ratio (src_state, src.src_ratio);
645 src_process (src_state, &src);
647 for (i = 0; i < net_period_up; i++) {
648 packet_bufX[i] = htonl (packet_bufX[i]);
650 src_node = jack_slist_next (src_node);
651 } else
652 #endif
654 if (dont_htonl_floats) {
655 memcpy(packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t));
656 } else {
657 for (i = 0; i < net_period_up; i++) {
658 val.f = buf[i];
659 val.i = htonl (val.i);
660 packet_bufX[i] = val.i;
664 } else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
665 // encode midi events from port to packet
666 // convert the data buffer to a standard format (uint32_t based)
667 unsigned int buffer_size_uint32 = net_period_up;
668 uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
669 encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
671 packet_bufX = (packet_bufX + net_period_up);
672 node = jack_slist_next (node);
673 chn++;
677 #if HAVE_CELT
678 // render functions for celt.
679 void
680 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)
682 uint32_t chn = 0;
683 JSList *node = capture_ports;
684 JSList *src_node = capture_srcs;
685 unsigned char *packet_bufX = (unsigned char *)packet_payload;
687 while (node != NULL) {
688 jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data;
689 JackPort *port = fGraphManager->GetPort(port_index);
691 jack_default_audio_sample_t* buf =
692 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
694 const char *portname = port->GetType();
696 if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
697 // audio port, decode celt data.
698 CELTDecoder *decoder = (CELTDecoder *)src_node->data;
700 #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
701 if (!packet_payload)
702 celt_decode_float(decoder, NULL, net_period_down, buf, nframes);
703 else
704 celt_decode_float(decoder, packet_bufX, net_period_down, buf, nframes);
705 #else
706 if (!packet_payload)
707 celt_decode_float(decoder, NULL, net_period_down, buf);
708 else
709 celt_decode_float(decoder, packet_bufX, net_period_down, buf);
710 #endif
712 src_node = jack_slist_next (src_node);
713 } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
714 // midi port, decode midi events
715 // convert the data buffer to a standard format (uint32_t based)
716 unsigned int buffer_size_uint32 = net_period_down / 2;
717 uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
718 if (packet_payload)
719 decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
721 packet_bufX = (packet_bufX + net_period_down);
722 node = jack_slist_next (node);
723 chn++;
727 void
728 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)
730 uint32_t chn = 0;
731 JSList *node = playback_ports;
732 JSList *src_node = playback_srcs;
734 unsigned char *packet_bufX = (unsigned char *)packet_payload;
736 while (node != NULL) {
737 jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data;
738 JackPort *port = fGraphManager->GetPort(port_index);
740 jack_default_audio_sample_t* buf =
741 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
743 const char *portname = port->GetType();
745 if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
746 // audio port, encode celt data.
748 int encoded_bytes;
749 jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes);
750 memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t));
751 CELTEncoder *encoder = (CELTEncoder *)src_node->data;
752 #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
753 encoded_bytes = celt_encode_float(encoder, floatbuf, nframes, packet_bufX, net_period_up);
754 #else
755 encoded_bytes = celt_encode_float(encoder, floatbuf, NULL, packet_bufX, net_period_up);
756 #endif
757 if (encoded_bytes != (int)net_period_up)
758 jack_error("something in celt changed. netjack needs to be changed to handle this.");
759 src_node = jack_slist_next(src_node);
760 } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
761 // encode midi events from port to packet
762 // convert the data buffer to a standard format (uint32_t based)
763 unsigned int buffer_size_uint32 = net_period_up / 2;
764 uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
765 encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
767 packet_bufX = (packet_bufX + net_period_up);
768 node = jack_slist_next (node);
769 chn++;
773 #endif
775 #if HAVE_OPUS
776 #define CDO (sizeof(short)) ///< compressed data offset (first 2 bytes are length)
777 // render functions for Opus.
778 void
779 JackNetOneDriver::render_payload_to_jack_ports_opus (void *packet_payload, jack_nframes_t net_period_down, JSList *capture_ports, JSList *capture_srcs, jack_nframes_t nframes)
781 int chn = 0;
782 JSList *node = capture_ports;
783 JSList *src_node = capture_srcs;
785 unsigned char *packet_bufX = (unsigned char *)packet_payload;
787 while (node != NULL) {
788 jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data;
789 JackPort *port = fGraphManager->GetPort(port_index);
791 jack_default_audio_sample_t* buf =
792 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
794 const char *portname = port->GetType();
796 if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
797 // audio port, decode opus data.
798 OpusCustomDecoder *decoder = (OpusCustomDecoder*) src_node->data;
799 if( !packet_payload )
800 memset(buf, 0, nframes * sizeof(float));
801 else {
802 unsigned short len;
803 memcpy(&len, packet_bufX, CDO);
804 len = ntohs(len);
805 opus_custom_decode_float( decoder, packet_bufX + CDO, len, buf, nframes );
808 src_node = jack_slist_next (src_node);
809 } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
810 // midi port, decode midi events
811 // convert the data buffer to a standard format (uint32_t based)
812 unsigned int buffer_size_uint32 = net_period_down / 2;
813 uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
814 if( packet_payload )
815 decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
817 packet_bufX = (packet_bufX + net_period_down);
818 node = jack_slist_next (node);
819 chn++;
823 void
824 JackNetOneDriver::render_jack_ports_to_payload_opus (JSList *playback_ports, JSList *playback_srcs, jack_nframes_t nframes, void *packet_payload, jack_nframes_t net_period_up)
826 int chn = 0;
827 JSList *node = playback_ports;
828 JSList *src_node = playback_srcs;
830 unsigned char *packet_bufX = (unsigned char *)packet_payload;
832 while (node != NULL) {
833 jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data;
834 JackPort *port = fGraphManager->GetPort(port_index);
836 jack_default_audio_sample_t* buf =
837 (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
839 const char *portname = port->GetType();
841 if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
842 // audio port, encode opus data.
844 int encoded_bytes;
845 jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes);
846 memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t));
847 OpusCustomEncoder *encoder = (OpusCustomEncoder*) src_node->data;
848 encoded_bytes = opus_custom_encode_float( encoder, floatbuf, nframes, packet_bufX + CDO, net_period_up - CDO );
849 unsigned short len = htons(encoded_bytes);
850 memcpy(packet_bufX, &len, CDO);
851 src_node = jack_slist_next( src_node );
852 } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
853 // encode midi events from port to packet
854 // convert the data buffer to a standard format (uint32_t based)
855 unsigned int buffer_size_uint32 = net_period_up / 2;
856 uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
857 encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
859 packet_bufX = (packet_bufX + net_period_up);
860 node = jack_slist_next (node);
861 chn++;
864 #endif
866 /* Wrapper functions with bitdepth argument... */
867 void
868 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)
870 #if HAVE_CELT
871 if (bitdepth == CELT_MODE)
872 render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
873 else
874 #endif
875 #if HAVE_OPUS
876 if (bitdepth == OPUS_MODE)
877 render_payload_to_jack_ports_opus (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
878 else
879 #endif
880 render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats);
883 void
884 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)
886 #if HAVE_CELT
887 if (bitdepth == CELT_MODE)
888 render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
889 else
890 #endif
891 #if HAVE_OPUS
892 if (bitdepth == OPUS_MODE)
893 render_jack_ports_to_payload_opus (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
894 else
895 #endif
896 render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats);
899 //driver loader-----------------------------------------------------------------------
901 #ifdef __cplusplus
902 extern "C"
904 #endif
906 SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
908 jack_driver_desc_t * desc;
909 jack_driver_desc_filler_t filler;
910 jack_driver_param_value_t value;
912 desc = jack_driver_descriptor_construct("netone", JackDriverMaster, "netjack one slave backend component", &filler);
914 value.ui = 2U;
915 jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 2)", NULL);
916 jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 2)", NULL);
918 value.ui = 1U;
919 jack_driver_descriptor_add_parameter(desc, &filler, "midi-ins", 'I', JackDriverParamUInt, &value, NULL, "Number of midi capture channels (defaults to 1)", NULL);
920 jack_driver_descriptor_add_parameter(desc, &filler, "midi-outs", 'O', JackDriverParamUInt, &value, NULL, "Number of midi playback channels (defaults to 1)", NULL);
922 value.ui = 48000U;
923 jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
925 value.ui = 1024U;
926 jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
928 value.ui = 5U;
929 jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
931 value.ui = 3000U;
932 jack_driver_descriptor_add_parameter(desc, &filler, "listen-port", 'l', JackDriverParamUInt, &value, NULL, "The socket port we are listening on for sync packets", NULL);
934 value.ui = 1U;
935 jack_driver_descriptor_add_parameter(desc, &filler, "factor", 'f', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction", NULL);
937 value.ui = 0U;
938 jack_driver_descriptor_add_parameter(desc, &filler, "upstream-factor", 'u', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction on the upstream", NULL);
940 #if HAVE_CELT
941 value.ui = 0U;
942 jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamUInt, &value, NULL, "Set CELT encoding and number of kbits per channel", NULL);
943 #endif
944 #if HAVE_OPUS
945 value.ui = 0U;
946 jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'P', JackDriverParamUInt, &value, NULL, "Set Opus encoding and number of kbits per channel", NULL);
947 #endif
948 value.ui = 0U;
949 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);
951 value.i = true;
952 jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamBool, &value, NULL, "Whether to slave the transport to the master transport", NULL);
954 value.ui = true;
955 jack_driver_descriptor_add_parameter(desc, &filler, "autoconf", 'a', JackDriverParamBool, &value, NULL, "Whether to use Autoconfig, or just start", NULL);
957 value.ui = 1U;
958 jack_driver_descriptor_add_parameter(desc, &filler, "redundancy", 'R', JackDriverParamUInt, &value, NULL, "Send packets N times", NULL);
960 value.ui = false;
961 jack_driver_descriptor_add_parameter(desc, &filler, "native-endian", 'e', JackDriverParamBool, &value, NULL, "Don't convert samples to network byte order", NULL);
963 value.i = 0;
964 jack_driver_descriptor_add_parameter(desc, &filler, "jitterval", 'J', JackDriverParamInt, &value, NULL, "Attempted jitterbuffer microseconds on master", NULL);
966 value.i = false;
967 jack_driver_descriptor_add_parameter(desc, &filler, "always-deadline", 'D', JackDriverParamBool, &value, NULL, "Always use deadline", NULL);
969 return desc;
972 SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
974 jack_nframes_t sample_rate = 48000;
975 jack_nframes_t resample_factor = 1;
976 jack_nframes_t period_size = 1024;
977 unsigned int capture_ports = 2;
978 unsigned int playback_ports = 2;
979 unsigned int capture_ports_midi = 1;
980 unsigned int playback_ports_midi = 1;
981 unsigned int listen_port = 3000;
982 unsigned int bitdepth = 0;
983 unsigned int handle_transport_sync = 1;
984 unsigned int use_autoconfig = 1;
985 unsigned int latency = 5;
986 unsigned int redundancy = 1;
987 unsigned int mtu = 1400;
988 #if HAVE_SAMPLERATE
989 unsigned int resample_factor_up = 1;
990 #endif
991 int dont_htonl_floats = 0;
992 int always_deadline = 0;
993 int jitter_val = 0;
994 const JSList * node;
995 const jack_driver_param_t * param;
997 for (node = params; node; node = jack_slist_next(node)) {
998 param = (const jack_driver_param_t*) node->data;
999 switch (param->character) {
1000 case 'i':
1001 capture_ports = param->value.ui;
1002 break;
1004 case 'o':
1005 playback_ports = param->value.ui;
1006 break;
1008 case 'I':
1009 capture_ports_midi = param->value.ui;
1010 break;
1012 case 'O':
1013 playback_ports_midi = param->value.ui;
1014 break;
1016 case 'r':
1017 sample_rate = param->value.ui;
1018 break;
1020 case 'p':
1021 period_size = param->value.ui;
1022 break;
1024 case 'l':
1025 listen_port = param->value.ui;
1026 break;
1028 case 'f':
1029 #if HAVE_SAMPLERATE
1030 resample_factor = param->value.ui;
1031 #else
1032 jack_error("not built with libsamplerate support");
1033 return NULL;
1034 #endif
1035 break;
1037 case 'u':
1038 #if HAVE_SAMPLERATE
1039 resample_factor_up = param->value.ui;
1040 #else
1041 jack_error("not built with libsamplerate support");
1042 return NULL;
1043 #endif
1044 break;
1046 case 'b':
1047 bitdepth = param->value.ui;
1048 break;
1050 case 'c':
1051 #if HAVE_CELT
1052 bitdepth = CELT_MODE;
1053 resample_factor = param->value.ui;
1054 #else
1055 jack_error("not built with celt support");
1056 return NULL;
1057 #endif
1058 break;
1060 case 'P':
1061 #if HAVE_OPUS
1062 bitdepth = OPUS_MODE;
1063 resample_factor = param->value.ui;
1064 jack_error("OPUS: %d\n", resample_factor);
1065 #else
1066 jack_error("not built with Opus support");
1067 return NULL;
1068 #endif
1069 break;
1071 case 't':
1072 handle_transport_sync = param->value.ui;
1073 break;
1075 case 'a':
1076 use_autoconfig = param->value.ui;
1077 break;
1079 case 'n':
1080 latency = param->value.ui;
1081 break;
1083 case 'R':
1084 redundancy = param->value.ui;
1085 break;
1087 case 'H':
1088 dont_htonl_floats = param->value.ui;
1089 break;
1091 case 'J':
1092 jitter_val = param->value.i;
1093 break;
1095 case 'D':
1096 always_deadline = param->value.ui;
1097 break;
1101 try {
1102 Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
1103 new Jack::JackNetOneDriver("system", "net_pcm", engine, table, listen_port, mtu,
1104 capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
1105 sample_rate, period_size, resample_factor,
1106 "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
1107 dont_htonl_floats, always_deadline, jitter_val));
1109 if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports,
1110 0, "from_master", "to_master", 0, 0) == 0) {
1111 return driver;
1112 } else {
1113 delete driver;
1114 return NULL;
1117 } catch (...) {
1118 return NULL;
1121 #if HAVE_SAMPLERATE
1122 // unused
1123 (void)resample_factor_up;
1124 #endif
1127 #ifdef __cplusplus
1129 #endif