Jack2 1.9.6

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