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