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