Jack2  1.9.10
JackNetOneDriver.cpp
00001 /*
00002 Copyright (C) 2008-2011 Torben Horn
00003 
00004 This program is free software; you can redistribute it and/or modify
00005 it under the terms of the GNU General Public License as published by
00006 the Free Software Foundation; either version 2 of the License, or
00007 (at your option) any later version.
00008 
00009 This program is distributed in the hope that it will be useful,
00010 but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012 GNU General Public License for more details.
00013 
00014 You should have received a copy of the GNU General Public License
00015 along with this program; if not, write to the Free Software
00016 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifdef WIN32
00020 #include <malloc.h>
00021 #endif
00022 
00023 #include "JackNetOneDriver.h"
00024 #include "JackEngineControl.h"
00025 #include "JackLockedEngine.h"
00026 #include "JackGraphManager.h"
00027 #include "JackWaitThreadedDriver.h"
00028 #include "JackTools.h"
00029 #include "driver_interface.h"
00030 
00031 #include "netjack.h"
00032 #include "netjack_packet.h"
00033 
00034 #if HAVE_SAMPLERATE
00035 #include <samplerate.h>
00036 #endif
00037 
00038 #if HAVE_CELT
00039 #include <celt/celt.h>
00040 #endif
00041 
00042 #if HAVE_OPUS
00043 #include <opus/opus.h>
00044 #include <opus/opus_custom.h>
00045 #endif
00046 
00047 #define MIN(x,y) ((x)<(y) ? (x) : (y))
00048 
00049 using namespace std;
00050 
00051 namespace Jack
00052 {
00053 JackNetOneDriver::JackNetOneDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
00054                                      int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports,
00055                                      int sample_rate, int period_size, int resample_factor,
00056                                      const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig,
00057                                      int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val)
00058     : JackWaiterDriver(name, alias, engine, table)
00059 {
00060     jack_log("JackNetOneDriver::JackNetOneDriver port %d", port);
00061 
00062 #ifdef WIN32
00063     WSADATA wsa;
00064     WSAStartup(MAKEWORD(2, 0), &wsa);
00065 #endif
00066 
00067     netjack_init(& (this->netj),
00068                   NULL, // client
00069                   name,
00070                   capture_ports,
00071                   playback_ports,
00072                   midi_input_ports,
00073                   midi_output_ports,
00074                   sample_rate,
00075                   period_size,
00076                   port,
00077                   transport_sync,
00078                   resample_factor,
00079                   0,
00080                   bitdepth,
00081                   use_autoconfig,
00082                   latency,
00083                   redundancy,
00084                   dont_htonl_floats,
00085                   always_deadline,
00086                   jitter_val);
00087 }
00088 
00089 JackNetOneDriver::~JackNetOneDriver()
00090 {
00091     // No destructor yet.
00092 }
00093 
00094 //open, close, attach and detach------------------------------------------------------
00095 
00096 int JackNetOneDriver::Close()
00097 {
00098     // Generic audio driver close
00099     int res = JackWaiterDriver::Close();
00100 
00101     FreePorts();
00102     netjack_release(&netj);
00103     return res;
00104 }
00105 
00106 int JackNetOneDriver::Attach()
00107 {
00108     return 0;
00109 }
00110 
00111 int JackNetOneDriver::Detach()
00112 {
00113     return 0;
00114 }
00115 
00116 int JackNetOneDriver::AllocPorts()
00117 {
00118     jack_port_id_t port_index;
00119     char buf[64];
00120     unsigned int chn;
00121 
00122     //if (netj.handle_transport_sync)
00123     //    jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
00124 
00125     for (chn = 0; chn < netj.capture_channels_audio; chn++) {
00126         snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
00127 
00128         if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
00129             CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00130             jack_error("driver: cannot register port for %s", buf);
00131             return -1;
00132         }
00133         //port = fGraphManager->GetPort(port_index);
00134 
00135         netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
00136 
00137         if (netj.bitdepth == CELT_MODE) {
00138 #if HAVE_CELT
00139 #if HAVE_CELT_API_0_11
00140             celt_int32 lookahead;
00141             CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
00142             netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create_custom(celt_mode, 1, NULL));
00143 #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
00144             celt_int32 lookahead;
00145             CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
00146             netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode, 1, NULL));
00147 #else
00148             celt_int32_t lookahead;
00149             CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL);
00150             netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create(celt_mode));
00151 #endif
00152             celt_mode_info(celt_mode, CELT_GET_LOOKAHEAD, &lookahead);
00153             netj.codec_latency = 2 * lookahead;
00154 #endif
00155         } else if (netj.bitdepth == OPUS_MODE) {
00156 #if HAVE_OPUS
00157             OpusCustomMode *opus_mode = opus_custom_mode_create(netj.sample_rate, netj.period_size, NULL); // XXX free me in the end
00158             OpusCustomDecoder *decoder = opus_custom_decoder_create( opus_mode, 1, NULL );
00159             netj.capture_srcs = jack_slist_append(netj.capture_srcs, decoder);
00160 #endif
00161         } else {
00162 #if HAVE_SAMPLERATE
00163             netj.capture_srcs = jack_slist_append(netj.capture_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
00164 #endif
00165         }
00166     }
00167 
00168     for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
00169         snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
00170 
00171         if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
00172             CaptureDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00173             jack_error("driver: cannot register port for %s", buf);
00174             return -1;
00175         }
00176         //port = fGraphManager->GetPort(port_index);
00177 
00178         netj.capture_ports =
00179             jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_index);
00180     }
00181 
00182     for (chn = 0; chn < netj.playback_channels_audio; chn++) {
00183         snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
00184 
00185         if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
00186             PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00187             jack_error("driver: cannot register port for %s", buf);
00188             return -1;
00189         }
00190         //port = fGraphManager->GetPort(port_index);
00191 
00192         netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
00193         if (netj.bitdepth == CELT_MODE) {
00194 #if HAVE_CELT
00195 #if HAVE_CELT_API_0_11
00196             CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
00197             netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom(celt_mode, 1, NULL));
00198 #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
00199             CELTMode *celt_mode = celt_mode_create(netj.sample_rate, netj.period_size, NULL);
00200             netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode, 1, NULL));
00201 #else
00202             CELTMode *celt_mode = celt_mode_create(netj.sample_rate, 1, netj.period_size, NULL);
00203             netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create(celt_mode));
00204 #endif
00205 #endif
00206         } else if (netj.bitdepth == OPUS_MODE) {
00207 #if HAVE_OPUS
00208             const int kbps = netj.resample_factor;
00209             jack_error("NEW ONE OPUS ENCODER 128  <> %d!!", kbps);
00210             int err;
00211             OpusCustomMode *opus_mode = opus_custom_mode_create( netj.sample_rate, netj.period_size, &err ); // XXX free me in the end
00212             if (err != OPUS_OK) { jack_error("opus mode failed"); }
00213             OpusCustomEncoder *oe = opus_custom_encoder_create( opus_mode, 1, &err );
00214             if (err != OPUS_OK) { jack_error("opus mode failed"); }
00215             opus_custom_encoder_ctl(oe, OPUS_SET_BITRATE(kbps*1024)); // bits per second
00216             opus_custom_encoder_ctl(oe, OPUS_SET_COMPLEXITY(10));
00217             opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_SIGNAL_MUSIC));
00218             opus_custom_encoder_ctl(oe, OPUS_SET_SIGNAL(OPUS_APPLICATION_RESTRICTED_LOWDELAY));
00219             netj.playback_srcs = jack_slist_append(netj.playback_srcs, oe);
00220 #endif
00221         } else {
00222 #if HAVE_SAMPLERATE
00223             netj.playback_srcs = jack_slist_append(netj.playback_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
00224 #endif
00225         }
00226     }
00227     for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
00228         snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
00229 
00230         if (fEngine->PortRegister(fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
00231             PlaybackDriverFlags, fEngineControl->fBufferSize, &port_index) < 0) {
00232             jack_error("driver: cannot register port for %s", buf);
00233             return -1;
00234         }
00235         //port = fGraphManager->GetPort(port_index);
00236 
00237         netj.playback_ports =
00238             jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_index);
00239     }
00240     return 0;
00241 }
00242 
00243 //init and restart--------------------------------------------------------------------
00244 bool JackNetOneDriver::Initialize()
00245 {
00246     jack_log("JackNetOneDriver::Init");
00247 
00248     FreePorts();
00249     netjack_release(&netj);
00250 
00251     //display some additional infos
00252     jack_info("NetOne driver started");
00253     if (netjack_startup(&netj)) {
00254         return false;
00255     }
00256 
00257     //register jack ports
00258     if (AllocPorts() != 0) {
00259         jack_error("Can't allocate ports.");
00260         return false;
00261     }
00262 
00263     //monitor
00264     //driver parametering
00265     JackTimedDriver::SetBufferSize(netj.period_size);
00266     JackTimedDriver::SetSampleRate(netj.sample_rate);
00267 
00268     JackDriver::NotifyBufferSize(netj.period_size);
00269     JackDriver::NotifySampleRate(netj.sample_rate);
00270 
00271     //transport engine parametering
00272     fEngineControl->fTransport.SetNetworkSync(true);
00273     return true;
00274 }
00275 
00276 
00277 //jack ports and buffers--------------------------------------------------------------
00278 
00279 //driver processes--------------------------------------------------------------------
00280 
00281 int JackNetOneDriver::Read()
00282 {
00283     int delay;
00284     delay = netjack_wait(&netj);
00285     if (delay) {
00286         NotifyXRun(fBeginDateUst, (float) delay);
00287         jack_error("netxruns... duration: %dms", delay / 1000);
00288     }
00289 
00290     if ((netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2)
00291         JackTools::ThrowJackNetException();
00292 
00293     //netjack_read(&netj, netj.period_size);
00294     JackDriver::CycleTakeBeginTime();
00295 
00296     jack_position_t local_trans_pos;
00297     jack_transport_state_t local_trans_state;
00298 
00299     unsigned int *packet_buf, *packet_bufX;
00300 
00301     if (! netj.packet_data_valid) {
00302         jack_log("data not valid");
00303         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);
00304         return 0;
00305     }
00306     packet_buf = netj.rx_buf;
00307 
00308     jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
00309 
00310     packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
00311 
00312     netj.reply_port = pkthdr->reply_port;
00313     netj.latency = pkthdr->latency;
00314 
00315     // Special handling for latency=0
00316     if (netj.latency == 0)
00317         netj.resync_threshold = 0;
00318     else
00319         netj.resync_threshold = MIN(15, pkthdr->latency - 1);
00320 
00321     // check whether, we should handle the transport sync stuff, or leave trnasports untouched.
00322     if (netj.handle_transport_sync) {
00323 #if 1
00324         unsigned int compensated_tranport_pos = (pkthdr->transport_frame + (pkthdr->latency * netj.period_size) + netj.codec_latency);
00325 
00326         // read local transport info....
00327         //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
00328 
00329         local_trans_state = fEngineControl->fTransport.Query(&local_trans_pos);
00330 
00331         // Now check if we have to start or stop local transport to sync to remote...
00332         switch (pkthdr->transport_state) {
00333 
00334             case JackTransportStarting:
00335                 // the master transport is starting... so we set our reply to the sync_callback;
00336                 if (local_trans_state == JackTransportStopped) {
00337                     fEngineControl->fTransport.SetCommand(TransportCommandStart);
00338                     //jack_transport_start(netj.client);
00339                     //last_transport_state = JackTransportStopped;
00340                     netj.sync_state = 0;
00341                     jack_info("locally stopped... starting...");
00342                 }
00343 
00344                 if (local_trans_pos.frame != compensated_tranport_pos) {
00345                     jack_position_t new_pos = local_trans_pos;
00346                     new_pos.frame = compensated_tranport_pos + 2 * netj.period_size;
00347                     new_pos.valid = (jack_position_bits_t) 0;
00348 
00349 
00350                     fEngineControl->fTransport.RequestNewPos(&new_pos);
00351                     //jack_transport_locate(netj.client, compensated_tranport_pos);
00352                     //last_transport_state = JackTransportRolling;
00353                     netj.sync_state = 0;
00354                     jack_info("starting locate to %d", compensated_tranport_pos);
00355                 }
00356                 break;
00357 
00358             case JackTransportStopped:
00359                 netj.sync_state = 1;
00360                 if (local_trans_pos.frame != (pkthdr->transport_frame)) {
00361                     jack_position_t new_pos = local_trans_pos;
00362                     new_pos.frame = pkthdr->transport_frame;
00363                     new_pos.valid = (jack_position_bits_t)0;
00364                     fEngineControl->fTransport.RequestNewPos(&new_pos);
00365                     //jack_transport_locate(netj.client, (pkthdr->transport_frame));
00366                     jack_info("transport is stopped locate to %d", pkthdr->transport_frame);
00367                 }
00368                 if (local_trans_state != JackTransportStopped)
00369                     //jack_transport_stop(netj.client);
00370                     fEngineControl->fTransport.SetCommand(TransportCommandStop);
00371                 break;
00372 
00373             case JackTransportRolling:
00374                 netj.sync_state = 1;
00375                 //                  if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) {
00376                 //                      jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size));
00377                 //                      jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size);
00378                 //                              }
00379                 if (local_trans_state != JackTransportRolling)
00380                     fEngineControl->fTransport.SetState(JackTransportRolling);
00381                 break;
00382 
00383             case JackTransportLooping:
00384                 break;
00385         }
00386 #endif
00387     }
00388 
00389     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);
00390     packet_cache_release_packet(netj.packcache, netj.expected_framecnt);
00391     return 0;
00392 }
00393 
00394 int JackNetOneDriver::Write()
00395 {
00396     int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0);
00397     uint32_t *packet_buf, *packet_bufX;
00398 
00399     int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header);
00400     jacknet_packet_header *pkthdr;
00401 
00402     packet_buf = (uint32_t *) alloca(packet_size);
00403     pkthdr = (jacknet_packet_header *)packet_buf;
00404 
00405     if (netj.running_free) {
00406         return 0;
00407     }
00408 
00409     // offset packet_bufX by the packetheader.
00410     packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
00411 
00412     pkthdr->sync_state = syncstate;;
00413     pkthdr->latency = netj.time_to_deadline;
00414     //printf("time to deadline = %d  goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness);
00415     pkthdr->framecnt = netj.expected_framecnt;
00416 
00417     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);
00418 
00419     packet_header_hton(pkthdr);
00420     if (netj.srcaddress_valid) {
00421         unsigned int r;
00422         static const int flag = 0;
00423 
00424         if (netj.reply_port)
00425             netj.syncsource_address.sin_port = htons(netj.reply_port);
00426 
00427         for (r = 0; r < netj.redundancy; r++)
00428             netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size,
00429                            flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu);
00430     }
00431     return 0;
00432 }
00433 
00434 void
00435 JackNetOneDriver::FreePorts ()
00436 {
00437     JSList *node = netj.capture_ports;
00438 
00439     while (node != NULL) {
00440         JSList *this_node = node;
00441         jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
00442         node = jack_slist_remove_link(node, this_node);
00443         jack_slist_free_1(this_node);
00444         fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
00445     }
00446     netj.capture_ports = NULL;
00447 
00448     node = netj.playback_ports;
00449     while (node != NULL) {
00450         JSList *this_node = node;
00451         jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
00452         node = jack_slist_remove_link(node, this_node);
00453         jack_slist_free_1(this_node);
00454         fEngine->PortUnRegister(fClientControl.fRefNum, port_index);
00455     }
00456     netj.playback_ports = NULL;
00457 
00458     if (netj.bitdepth == CELT_MODE) {
00459 #if HAVE_CELT
00460         node = netj.playback_srcs;
00461         while (node != NULL) {
00462             JSList *this_node = node;
00463             CELTEncoder *enc = (CELTEncoder *) node->data;
00464             node = jack_slist_remove_link(node, this_node);
00465             jack_slist_free_1(this_node);
00466             celt_encoder_destroy(enc);
00467         }
00468         netj.playback_srcs = NULL;
00469 
00470         node = netj.capture_srcs;
00471         while (node != NULL) {
00472             JSList *this_node = node;
00473             CELTDecoder *dec = (CELTDecoder *) node->data;
00474             node = jack_slist_remove_link(node, this_node);
00475             jack_slist_free_1(this_node);
00476             celt_decoder_destroy(dec);
00477         }
00478         netj.capture_srcs = NULL;
00479 #endif
00480     } else if (netj.bitdepth == OPUS_MODE) {
00481 #if HAVE_OPUS
00482         node = netj.playback_srcs;
00483         while (node != NULL) {
00484             JSList *this_node = node;
00485             OpusCustomEncoder *enc = (OpusCustomEncoder *) node->data;
00486             node = jack_slist_remove_link(node, this_node);
00487             jack_slist_free_1(this_node);
00488             opus_custom_encoder_destroy(enc);
00489         }
00490         netj.playback_srcs = NULL;
00491 
00492         node = netj.capture_srcs;
00493         while (node != NULL) {
00494             JSList *this_node = node;
00495             OpusCustomDecoder *dec = (OpusCustomDecoder *) node->data;
00496             node = jack_slist_remove_link(node, this_node);
00497             jack_slist_free_1(this_node);
00498             opus_custom_decoder_destroy(dec);
00499         }
00500         netj.capture_srcs = NULL;
00501 #endif
00502     } else {
00503 #if HAVE_SAMPLERATE
00504         node = netj.playback_srcs;
00505         while (node != NULL) {
00506             JSList *this_node = node;
00507             SRC_STATE *state = (SRC_STATE *) node->data;
00508             node = jack_slist_remove_link(node, this_node);
00509             jack_slist_free_1(this_node);
00510             src_delete(state);
00511         }
00512         netj.playback_srcs = NULL;
00513 
00514         node = netj.capture_srcs;
00515         while (node != NULL) {
00516             JSList *this_node = node;
00517             SRC_STATE *state = (SRC_STATE *) node->data;
00518             node = jack_slist_remove_link(node, this_node);
00519             jack_slist_free_1(this_node);
00520             src_delete(state);
00521         }
00522         netj.capture_srcs = NULL;
00523 #endif
00524     }
00525 }
00526 
00527 //Render functions--------------------------------------------------------------------
00528 
00529 // render functions for float
00530 void
00531 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)
00532 {
00533     uint32_t chn = 0;
00534     JSList *node = capture_ports;
00535 #if HAVE_SAMPLERATE
00536     JSList *src_node = capture_srcs;
00537 #endif
00538 
00539     uint32_t *packet_bufX = (uint32_t *)packet_payload;
00540 
00541     if (!packet_payload)
00542         return;
00543 
00544     while (node != NULL) {
00545         unsigned int i;
00546         int_float_t val;
00547 #if HAVE_SAMPLERATE
00548         SRC_DATA src;
00549 #endif
00550         jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
00551         JackPort *port = fGraphManager->GetPort(port_index);
00552 
00553         jack_default_audio_sample_t* buf =
00554             (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
00555 
00556         const char *porttype = port->GetType();
00557 
00558         if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
00559 #if HAVE_SAMPLERATE
00560             // audio port, resample if necessary
00561             if (net_period_down != nframes) {
00562                 SRC_STATE *src_state = (SRC_STATE *)src_node->data;
00563                 for (i = 0; i < net_period_down; i++) {
00564                     packet_bufX[i] = ntohl (packet_bufX[i]);
00565                 }
00566 
00567                 src.data_in = (float *) packet_bufX;
00568                 src.input_frames = net_period_down;
00569 
00570                 src.data_out = buf;
00571                 src.output_frames = nframes;
00572 
00573                 src.src_ratio = (float) nframes / (float) net_period_down;
00574                 src.end_of_input = 0;
00575 
00576                 src_set_ratio (src_state, src.src_ratio);
00577                 src_process (src_state, &src);
00578                 src_node = jack_slist_next (src_node);
00579             } else
00580 #endif
00581             {
00582                 if (dont_htonl_floats) {
00583                     memcpy(buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t));
00584                 } else {
00585                     for (i = 0; i < net_period_down; i++) {
00586                         val.i = packet_bufX[i];
00587                         val.i = ntohl (val.i);
00588                         buf[i] = val.f;
00589                     }
00590                 }
00591             }
00592         } else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
00593             // midi port, decode midi events
00594             // convert the data buffer to a standard format (uint32_t based)
00595             unsigned int buffer_size_uint32 = net_period_down;
00596             uint32_t * buffer_uint32 = (uint32_t*)packet_bufX;
00597             decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
00598         }
00599         packet_bufX = (packet_bufX + net_period_down);
00600         node = jack_slist_next (node);
00601         chn++;
00602     }
00603 }
00604 
00605 void
00606 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)
00607 {
00608     uint32_t chn = 0;
00609     JSList *node = playback_ports;
00610 #if HAVE_SAMPLERATE
00611     JSList *src_node = playback_srcs;
00612 #endif
00613 
00614     uint32_t *packet_bufX = (uint32_t *) packet_payload;
00615 
00616     while (node != NULL) {
00617 #if HAVE_SAMPLERATE
00618         SRC_DATA src;
00619 #endif
00620         unsigned int i;
00621         int_float_t val;
00622         jack_port_id_t port_index = (jack_port_id_t)(intptr_t) node->data;
00623         JackPort *port = fGraphManager->GetPort(port_index);
00624 
00625         jack_default_audio_sample_t* buf =
00626             (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
00627 
00628         const char *porttype = port->GetType();
00629 
00630         if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
00631             // audio port, resample if necessary
00632 
00633 #if HAVE_SAMPLERATE
00634             if (net_period_up != nframes) {
00635                 SRC_STATE *src_state = (SRC_STATE *) src_node->data;
00636                 src.data_in = buf;
00637                 src.input_frames = nframes;
00638 
00639                 src.data_out = (float *) packet_bufX;
00640                 src.output_frames = net_period_up;
00641 
00642                 src.src_ratio = (float) net_period_up / (float) nframes;
00643                 src.end_of_input = 0;
00644 
00645                 src_set_ratio (src_state, src.src_ratio);
00646                 src_process (src_state, &src);
00647 
00648                 for (i = 0; i < net_period_up; i++) {
00649                     packet_bufX[i] = htonl (packet_bufX[i]);
00650                 }
00651                 src_node = jack_slist_next (src_node);
00652             } else
00653 #endif
00654             {
00655                 if (dont_htonl_floats) {
00656                     memcpy(packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t));
00657                 } else {
00658                     for (i = 0; i < net_period_up; i++) {
00659                         val.f = buf[i];
00660                         val.i = htonl (val.i);
00661                         packet_bufX[i] = val.i;
00662                     }
00663                 }
00664             }
00665         } else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
00666             // encode midi events from port to packet
00667             // convert the data buffer to a standard format (uint32_t based)
00668             unsigned int buffer_size_uint32 = net_period_up;
00669             uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
00670             encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
00671         }
00672         packet_bufX = (packet_bufX + net_period_up);
00673         node = jack_slist_next (node);
00674         chn++;
00675     }
00676 }
00677 
00678 #if HAVE_CELT
00679 // render functions for celt.
00680 void
00681 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)
00682 {
00683     uint32_t chn = 0;
00684     JSList *node = capture_ports;
00685     JSList *src_node = capture_srcs;
00686     unsigned char *packet_bufX = (unsigned char *)packet_payload;
00687 
00688     while (node != NULL) {
00689         jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data;
00690         JackPort *port = fGraphManager->GetPort(port_index);
00691 
00692         jack_default_audio_sample_t* buf =
00693             (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
00694 
00695         const char *portname = port->GetType();
00696 
00697         if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
00698             // audio port, decode celt data.
00699             CELTDecoder *decoder = (CELTDecoder *)src_node->data;
00700 
00701 #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
00702             if (!packet_payload)
00703                 celt_decode_float(decoder, NULL, net_period_down, buf, nframes);
00704             else
00705                 celt_decode_float(decoder, packet_bufX, net_period_down, buf, nframes);
00706 #else
00707             if (!packet_payload)
00708                 celt_decode_float(decoder, NULL, net_period_down, buf);
00709             else
00710                 celt_decode_float(decoder, packet_bufX, net_period_down, buf);
00711 #endif
00712 
00713             src_node = jack_slist_next (src_node);
00714         } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
00715             // midi port, decode midi events
00716             // convert the data buffer to a standard format (uint32_t based)
00717             unsigned int buffer_size_uint32 = net_period_down / 2;
00718             uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
00719             if (packet_payload)
00720                 decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
00721         }
00722         packet_bufX = (packet_bufX + net_period_down);
00723         node = jack_slist_next (node);
00724         chn++;
00725     }
00726 }
00727 
00728 void
00729 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)
00730 {
00731     uint32_t chn = 0;
00732     JSList *node = playback_ports;
00733     JSList *src_node = playback_srcs;
00734 
00735     unsigned char *packet_bufX = (unsigned char *)packet_payload;
00736 
00737     while (node != NULL) {
00738         jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data;
00739         JackPort *port = fGraphManager->GetPort(port_index);
00740 
00741         jack_default_audio_sample_t* buf =
00742             (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
00743 
00744         const char *portname = port->GetType();
00745 
00746         if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
00747             // audio port, encode celt data.
00748 
00749             int encoded_bytes;
00750             jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes);
00751             memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t));
00752             CELTEncoder *encoder = (CELTEncoder *)src_node->data;
00753 #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
00754             encoded_bytes = celt_encode_float(encoder, floatbuf, nframes, packet_bufX, net_period_up);
00755 #else
00756             encoded_bytes = celt_encode_float(encoder, floatbuf, NULL, packet_bufX, net_period_up);
00757 #endif
00758             if (encoded_bytes != (int)net_period_up)
00759                 jack_error("something in celt changed. netjack needs to be changed to handle this.");
00760             src_node = jack_slist_next(src_node);
00761         } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
00762             // encode midi events from port to packet
00763             // convert the data buffer to a standard format (uint32_t based)
00764             unsigned int buffer_size_uint32 = net_period_up / 2;
00765             uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
00766             encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
00767         }
00768         packet_bufX = (packet_bufX + net_period_up);
00769         node = jack_slist_next (node);
00770         chn++;
00771     }
00772 }
00773 
00774 #endif
00775 
00776 #if HAVE_OPUS
00777 #define CDO (sizeof(short)) ///< compressed data offset (first 2 bytes are length)
00778 // render functions for Opus.
00779 void
00780 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)
00781 {
00782     int chn = 0;
00783     JSList *node = capture_ports;
00784     JSList *src_node = capture_srcs;
00785 
00786     unsigned char *packet_bufX = (unsigned char *)packet_payload;
00787 
00788     while (node != NULL) {
00789         jack_port_id_t port_index = (jack_port_id_t) (intptr_t)node->data;
00790         JackPort *port = fGraphManager->GetPort(port_index);
00791 
00792         jack_default_audio_sample_t* buf =
00793             (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
00794 
00795         const char *portname = port->GetType();
00796 
00797         if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
00798             // audio port, decode opus data.
00799             OpusCustomDecoder *decoder = (OpusCustomDecoder*) src_node->data;
00800             if( !packet_payload )
00801                 memset(buf, 0, nframes * sizeof(float));
00802             else {
00803                 unsigned short len;
00804                 memcpy(&len, packet_bufX, CDO);
00805                 len = ntohs(len);
00806                 opus_custom_decode_float( decoder, packet_bufX + CDO, len, buf, nframes );
00807             }
00808 
00809             src_node = jack_slist_next (src_node);
00810         } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
00811             // midi port, decode midi events
00812             // convert the data buffer to a standard format (uint32_t based)
00813             unsigned int buffer_size_uint32 = net_period_down / 2;
00814             uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
00815             if( packet_payload )
00816                 decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
00817         }
00818         packet_bufX = (packet_bufX + net_period_down);
00819         node = jack_slist_next (node);
00820         chn++;
00821     }
00822 }
00823 
00824 void
00825 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)
00826 {
00827     int chn = 0;
00828     JSList *node = playback_ports;
00829     JSList *src_node = playback_srcs;
00830 
00831     unsigned char *packet_bufX = (unsigned char *)packet_payload;
00832 
00833     while (node != NULL) {
00834         jack_port_id_t port_index = (jack_port_id_t) (intptr_t) node->data;
00835         JackPort *port = fGraphManager->GetPort(port_index);
00836 
00837         jack_default_audio_sample_t* buf =
00838             (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_index, fEngineControl->fBufferSize);
00839 
00840         const char *portname = port->GetType();
00841 
00842         if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
00843             // audio port, encode opus data.
00844 
00845             int encoded_bytes;
00846             jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes);
00847             memcpy(floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t));
00848             OpusCustomEncoder *encoder = (OpusCustomEncoder*) src_node->data;
00849             encoded_bytes = opus_custom_encode_float( encoder, floatbuf, nframes, packet_bufX + CDO, net_period_up - CDO );
00850             unsigned short len = htons(encoded_bytes);
00851             memcpy(packet_bufX, &len, CDO);
00852             src_node = jack_slist_next( src_node );
00853         } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
00854             // encode midi events from port to packet
00855             // convert the data buffer to a standard format (uint32_t based)
00856             unsigned int buffer_size_uint32 = net_period_up / 2;
00857             uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
00858             encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
00859         }
00860         packet_bufX = (packet_bufX + net_period_up);
00861         node = jack_slist_next (node);
00862         chn++;
00863     }
00864 }
00865 #endif
00866 
00867 /* Wrapper functions with bitdepth argument... */
00868 void
00869 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)
00870 {
00871 #if HAVE_CELT
00872     if (bitdepth == CELT_MODE)
00873         render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
00874     else
00875 #endif
00876 #if HAVE_OPUS
00877     if (bitdepth == OPUS_MODE)
00878         render_payload_to_jack_ports_opus (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
00879     else
00880 #endif
00881         render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats);
00882 }
00883 
00884 void
00885 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)
00886 {
00887 #if HAVE_CELT
00888     if (bitdepth == CELT_MODE)
00889         render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
00890     else
00891 #endif
00892 #if HAVE_OPUS
00893     if (bitdepth == OPUS_MODE)
00894         render_jack_ports_to_payload_opus (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
00895     else
00896 #endif
00897         render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats);
00898 }
00899 
00900 //driver loader-----------------------------------------------------------------------
00901 
00902 #ifdef __cplusplus
00903 extern "C"
00904 {
00905 #endif
00906 
00907     SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
00908     {
00909         jack_driver_desc_t * desc;
00910         jack_driver_desc_filler_t filler;
00911         jack_driver_param_value_t value;
00912 
00913         desc = jack_driver_descriptor_construct("netone", JackDriverMaster, "netjack one slave backend component", &filler);
00914 
00915         value.ui = 2U;
00916         jack_driver_descriptor_add_parameter(desc, &filler, "audio-ins", 'i', JackDriverParamUInt, &value, NULL, "Number of capture channels (defaults to 2)", NULL);
00917         jack_driver_descriptor_add_parameter(desc, &filler, "audio-outs", 'o', JackDriverParamUInt, &value, NULL, "Number of playback channels (defaults to 2)", NULL);
00918 
00919         value.ui = 1U;
00920         jack_driver_descriptor_add_parameter(desc, &filler, "midi-ins", 'I', JackDriverParamUInt, &value, NULL, "Number of midi capture channels (defaults to 1)", NULL);
00921         jack_driver_descriptor_add_parameter(desc, &filler, "midi-outs", 'O', JackDriverParamUInt, &value, NULL, "Number of midi playback channels (defaults to 1)", NULL);
00922 
00923         value.ui = 48000U;
00924         jack_driver_descriptor_add_parameter(desc, &filler, "rate", 'r', JackDriverParamUInt, &value, NULL, "Sample rate", NULL);
00925 
00926         value.ui = 1024U;
00927         jack_driver_descriptor_add_parameter(desc, &filler, "period", 'p', JackDriverParamUInt, &value, NULL, "Frames per period", NULL);
00928 
00929         value.ui = 5U;
00930         jack_driver_descriptor_add_parameter(desc, &filler, "num-periods", 'n', JackDriverParamUInt, &value, NULL, "Network latency setting in no. of periods", NULL);
00931 
00932         value.ui = 3000U;
00933         jack_driver_descriptor_add_parameter(desc, &filler, "listen-port", 'l', JackDriverParamUInt, &value, NULL, "The socket port we are listening on for sync packets", NULL);
00934 
00935         value.ui = 1U;
00936         jack_driver_descriptor_add_parameter(desc, &filler, "factor", 'f', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction", NULL);
00937 
00938         value.ui = 0U;
00939         jack_driver_descriptor_add_parameter(desc, &filler, "upstream-factor", 'u', JackDriverParamUInt, &value, NULL, "Factor for sample rate reduction on the upstream", NULL);
00940 
00941 #if HAVE_CELT
00942         value.ui = 0U;
00943         jack_driver_descriptor_add_parameter(desc, &filler, "celt", 'c', JackDriverParamUInt, &value, NULL, "Set CELT encoding and number of kbits per channel", NULL);
00944 #endif
00945 #if HAVE_OPUS
00946         value.ui = 0U;
00947         jack_driver_descriptor_add_parameter(desc, &filler, "opus", 'P', JackDriverParamUInt, &value, NULL, "Set Opus encoding and number of kbits per channel", NULL);
00948 #endif
00949         value.ui = 0U;
00950         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);
00951 
00952         value.i = true;
00953         jack_driver_descriptor_add_parameter(desc, &filler, "transport-sync", 't', JackDriverParamBool, &value, NULL, "Whether to slave the transport to the master transport", NULL);
00954 
00955         value.ui = true;
00956         jack_driver_descriptor_add_parameter(desc, &filler, "autoconf", 'a', JackDriverParamBool, &value, NULL, "Whether to use Autoconfig, or just start", NULL);
00957 
00958         value.ui = 1U;
00959         jack_driver_descriptor_add_parameter(desc, &filler, "redundancy", 'R', JackDriverParamUInt, &value, NULL, "Send packets N times", NULL);
00960 
00961         value.ui = false;
00962         jack_driver_descriptor_add_parameter(desc, &filler, "native-endian", 'e', JackDriverParamBool, &value, NULL, "Dont convert samples to network byte order", NULL);
00963 
00964         value.i = 0;
00965         jack_driver_descriptor_add_parameter(desc, &filler, "jitterval", 'J', JackDriverParamInt, &value, NULL, "Attempted jitterbuffer microseconds on master", NULL);
00966 
00967         value.i = false;
00968         jack_driver_descriptor_add_parameter(desc, &filler, "always-deadline", 'D', JackDriverParamBool, &value, NULL, "Always use deadline", NULL);
00969 
00970         return desc;
00971     }
00972 
00973     SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize(Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params)
00974     {
00975         jack_nframes_t sample_rate = 48000;
00976         jack_nframes_t resample_factor = 1;
00977         jack_nframes_t period_size = 1024;
00978         unsigned int capture_ports = 2;
00979         unsigned int playback_ports = 2;
00980         unsigned int capture_ports_midi = 1;
00981         unsigned int playback_ports_midi = 1;
00982         unsigned int listen_port = 3000;
00983         unsigned int bitdepth = 0;
00984         unsigned int handle_transport_sync = 1;
00985         unsigned int use_autoconfig = 1;
00986         unsigned int latency = 5;
00987         unsigned int redundancy = 1;
00988         unsigned int mtu = 1400;
00989 #if HAVE_SAMPLERATE
00990         unsigned int resample_factor_up = 1;
00991 #endif
00992         int dont_htonl_floats = 0;
00993         int always_deadline = 0;
00994         int jitter_val = 0;
00995         const JSList * node;
00996         const jack_driver_param_t * param;
00997 
00998         for (node = params; node; node = jack_slist_next(node)) {
00999             param = (const jack_driver_param_t*) node->data;
01000             switch (param->character) {
01001                 case 'i':
01002                     capture_ports = param->value.ui;
01003                     break;
01004 
01005                 case 'o':
01006                     playback_ports = param->value.ui;
01007                     break;
01008 
01009                 case 'I':
01010                     capture_ports_midi = param->value.ui;
01011                     break;
01012 
01013                 case 'O':
01014                     playback_ports_midi = param->value.ui;
01015                     break;
01016 
01017                 case 'r':
01018                     sample_rate = param->value.ui;
01019                     break;
01020 
01021                 case 'p':
01022                     period_size = param->value.ui;
01023                     break;
01024 
01025                 case 'l':
01026                     listen_port = param->value.ui;
01027                     break;
01028 
01029                 case 'f':
01030 #if HAVE_SAMPLERATE
01031                     resample_factor = param->value.ui;
01032 #else
01033                     jack_error("not built with libsamplerate support");
01034                     return NULL;
01035 #endif
01036                     break;
01037 
01038                 case 'u':
01039 #if HAVE_SAMPLERATE
01040                     resample_factor_up = param->value.ui;
01041 #else
01042                     jack_error("not built with libsamplerate support");
01043                     return NULL;
01044 #endif
01045                     break;
01046 
01047                 case 'b':
01048                     bitdepth = param->value.ui;
01049                     break;
01050 
01051                 case 'c':
01052 #if HAVE_CELT
01053                     bitdepth = CELT_MODE;
01054                     resample_factor = param->value.ui;
01055 #else
01056                     jack_error("not built with celt support");
01057                     return NULL;
01058 #endif
01059                     break;
01060 
01061                 case 'P':
01062 #if HAVE_OPUS
01063                     bitdepth = OPUS_MODE;
01064                     resample_factor = param->value.ui;
01065                     jack_error("OPUS: %d\n", resample_factor);
01066 #else
01067                     jack_error("not built with Opus support");
01068                     return NULL;
01069 #endif
01070                     break;
01071 
01072                 case 't':
01073                     handle_transport_sync = param->value.ui;
01074                     break;
01075 
01076                 case 'a':
01077                     use_autoconfig = param->value.ui;
01078                     break;
01079 
01080                 case 'n':
01081                     latency = param->value.ui;
01082                     break;
01083 
01084                 case 'R':
01085                     redundancy = param->value.ui;
01086                     break;
01087 
01088                 case 'H':
01089                     dont_htonl_floats = param->value.ui;
01090                     break;
01091 
01092                 case 'J':
01093                     jitter_val = param->value.i;
01094                     break;
01095 
01096                 case 'D':
01097                     always_deadline = param->value.ui;
01098                     break;
01099             }
01100         }
01101 
01102         try {
01103             Jack::JackDriverClientInterface* driver = new Jack::JackWaitThreadedDriver (
01104                 new Jack::JackNetOneDriver("system", "net_pcm", engine, table, listen_port, mtu,
01105                                              capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
01106                                              sample_rate, period_size, resample_factor,
01107                                              "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
01108                                              dont_htonl_floats, always_deadline, jitter_val));
01109 
01110             if (driver->Open(period_size, sample_rate, 1, 1, capture_ports, playback_ports,
01111                                 0, "from_master", "to_master", 0, 0) == 0) {
01112                 return driver;
01113             } else {
01114                 delete driver;
01115                 return NULL;
01116             }
01117 
01118         } catch (...) {
01119             return NULL;
01120         }
01121     }
01122 
01123 #ifdef __cplusplus
01124 }
01125 #endif
01126 }