|
- /*
- Copyright (C) 2001 Paul Davis
- Copyright (C) 2008 Romain Moret at Grame
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #ifdef WIN32
- #include <malloc.h>
- #endif
-
- #include "JackNetOneDriver.h"
- #include "JackEngineControl.h"
- #include "JackGraphManager.h"
- #include "JackWaitThreadedDriver.h"
- #include "JackTools.h"
- #include "driver_interface.h"
-
- #include "netjack.h"
- #include "netjack_packet.h"
-
- #if HAVE_SAMPLERATE
- #include "samplerate.h"
- #endif
-
- #if HAVE_CELT
- #include <celt/celt.h>
- #endif
-
- #define MIN(x,y) ((x)<(y) ? (x) : (y))
-
- using namespace std;
-
- namespace Jack
- {
- JackNetOneDriver::JackNetOneDriver ( const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table,
- int port, int mtu, int capture_ports, int playback_ports, int midi_input_ports, int midi_output_ports,
- int sample_rate, int period_size, int resample_factor,
- const char* net_name, uint transport_sync, int bitdepth, int use_autoconfig,
- int latency, int redundancy, int dont_htonl_floats, int always_deadline, int jitter_val )
- : JackAudioDriver ( name, alias, engine, table )
- {
- jack_log ( "JackNetOneDriver::JackNetOneDriver port %d", port );
-
- #ifdef WIN32
- WSADATA wsa;
- int rc = WSAStartup(MAKEWORD(2, 0), &wsa);
- #endif
-
- netjack_init( & (this->netj),
- NULL, // client
- name,
- capture_ports,
- playback_ports,
- midi_input_ports,
- midi_output_ports,
- sample_rate,
- period_size,
- port,
- transport_sync,
- resample_factor,
- 0,
- bitdepth,
- use_autoconfig,
- latency,
- redundancy,
- dont_htonl_floats,
- always_deadline,
- jitter_val);
- }
-
- JackNetOneDriver::~JackNetOneDriver()
- {
- // No destructor yet.
- }
-
- //open, close, attach and detach------------------------------------------------------
- int JackNetOneDriver::Open ( jack_nframes_t buffer_size, jack_nframes_t samplerate, bool capturing, bool playing,
- int inchannels, int outchannels, bool monitor,
- const char* capture_driver_name, const char* playback_driver_name,
- jack_nframes_t capture_latency, jack_nframes_t playback_latency )
- {
- if ( JackAudioDriver::Open ( buffer_size,
- samplerate,
- capturing,
- playing,
- inchannels,
- outchannels,
- monitor,
- capture_driver_name,
- playback_driver_name,
- capture_latency,
- playback_latency ) == 0 ) {
- fEngineControl->fPeriod = 0;
- fEngineControl->fComputation = 500 * 1000;
- fEngineControl->fConstraint = 500 * 1000;
- return 0;
- } else {
- jack_error( "open fail" );
- return -1;
- }
- }
-
- int JackNetOneDriver::Close()
- {
- // Generic audio driver close
- int res = JackAudioDriver::Close();
-
- FreePorts();
- netjack_release(&netj);
- return res;
- }
-
- int JackNetOneDriver::Attach()
- {
- return 0;
- }
-
- int JackNetOneDriver::Detach()
- {
- return 0;
- }
-
- int JackNetOneDriver::AllocPorts()
- {
- jack_port_id_t port_id;
- char buf[64];
- unsigned int chn;
-
- //if (netj.handle_transport_sync)
- // jack_set_sync_callback(netj.client, (JackSyncCallback) net_driver_sync_cb, NULL);
-
- for (chn = 0; chn < netj.capture_channels_audio; chn++) {
- snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
-
- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
- CaptureDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT ) {
- jack_error ( "driver: cannot register port for %s", buf );
- return -1;
- }
- //port = fGraphManager->GetPort ( port_id );
-
- netj.capture_ports = jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id);
-
- if( netj.bitdepth == CELT_MODE ) {
- #if HAVE_CELT
- #if HAVE_CELT_API_0_11
- celt_int32 lookahead;
- CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL );
- netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) );
- #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
- celt_int32 lookahead;
- CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL );
- netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) );
- #else
- celt_int32_t lookahead;
- CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL );
- netj.capture_srcs = jack_slist_append(netj.capture_srcs, celt_decoder_create( celt_mode ) );
- #endif
- celt_mode_info( celt_mode, CELT_GET_LOOKAHEAD, &lookahead );
- netj.codec_latency = 2 * lookahead;
- #endif
- } else {
- #if HAVE_SAMPLERATE
- netj.capture_srcs = jack_slist_append(netj.capture_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
- #endif
- }
- }
- for (chn = netj.capture_channels_audio; chn < netj.capture_channels; chn++) {
- snprintf (buf, sizeof(buf) - 1, "system:capture_%u", chn + 1);
-
- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
- CaptureDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT ) {
- jack_error ( "driver: cannot register port for %s", buf );
- return -1;
- }
- //port = fGraphManager->GetPort ( port_id );
-
- netj.capture_ports =
- jack_slist_append (netj.capture_ports, (void *)(intptr_t)port_id);
- }
-
- for (chn = 0; chn < netj.playback_channels_audio; chn++) {
- snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
-
- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_AUDIO_TYPE,
- PlaybackDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT ) {
- jack_error ( "driver: cannot register port for %s", buf );
- return -1;
- }
- //port = fGraphManager->GetPort ( port_id );
-
- netj.playback_ports = jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id);
- if( netj.bitdepth == CELT_MODE ) {
- #if HAVE_CELT
- #if HAVE_CELT_API_0_11
- CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL );
- netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create_custom( celt_mode, 1, NULL ) );
- #elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8
- CELTMode *celt_mode = celt_mode_create( netj.sample_rate, netj.period_size, NULL );
- netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) );
- #else
- CELTMode *celt_mode = celt_mode_create( netj.sample_rate, 1, netj.period_size, NULL );
- netj.playback_srcs = jack_slist_append(netj.playback_srcs, celt_encoder_create( celt_mode ) );
- #endif
- #endif
- } else {
- #if HAVE_SAMPLERATE
- netj.playback_srcs = jack_slist_append(netj.playback_srcs, (void *)src_new(SRC_LINEAR, 1, NULL));
- #endif
- }
- }
- for (chn = netj.playback_channels_audio; chn < netj.playback_channels; chn++) {
- snprintf (buf, sizeof(buf) - 1, "system:playback_%u", chn + 1);
-
- if ( ( port_id = fGraphManager->AllocatePort ( fClientControl.fRefNum, buf, JACK_DEFAULT_MIDI_TYPE,
- PlaybackDriverFlags, fEngineControl->fBufferSize ) ) == NO_PORT ) {
- jack_error ( "driver: cannot register port for %s", buf );
- return -1;
- }
- //port = fGraphManager->GetPort ( port_id );
-
- netj.playback_ports =
- jack_slist_append (netj.playback_ports, (void *)(intptr_t)port_id);
- }
- return 0;
- }
-
- //init and restart--------------------------------------------------------------------
- bool JackNetOneDriver::Initialize()
- {
- jack_log ( "JackNetOneDriver::Init()" );
-
- FreePorts();
- netjack_release( &netj );
-
- //display some additional infos
- jack_info ( "NetOne driver started" );
- if( netjack_startup( &netj ) ) {
- return false;
- }
-
- //register jack ports
- if ( AllocPorts() != 0 ) {
- jack_error ( "Can't allocate ports." );
- return false;
- }
-
- //monitor
- //driver parametering
- JackAudioDriver::SetBufferSize ( netj.period_size );
- JackAudioDriver::SetSampleRate ( netj.sample_rate );
-
- JackDriver::NotifyBufferSize ( netj.period_size );
- JackDriver::NotifySampleRate ( netj.sample_rate );
-
- //transport engine parametering
- fEngineControl->fTransport.SetNetworkSync ( true );
- return true;
- }
-
-
- //jack ports and buffers--------------------------------------------------------------
-
- //driver processes--------------------------------------------------------------------
- int JackNetOneDriver::Read()
- {
- int delay;
- delay = netjack_wait( &netj );
- if( delay ) {
- NotifyXRun(fBeginDateUst, (float) delay);
- jack_error( "netxruns... duration: %dms", delay / 1000 );
- }
-
- if( (netj.num_lost_packets * netj.period_size / netj.sample_rate) > 2 )
- JackTools::ThrowJackNetException();
-
- //netjack_read( &netj, netj.period_size );
- JackDriver::CycleTakeBeginTime();
-
- jack_position_t local_trans_pos;
- jack_transport_state_t local_trans_state;
-
- unsigned int *packet_buf, *packet_bufX;
-
- if( ! netj.packet_data_valid ) {
- jack_log( "data not valid" );
- 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 );
- return 0;
- }
- packet_buf = netj.rx_buf;
-
- jacknet_packet_header *pkthdr = (jacknet_packet_header *)packet_buf;
-
- packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
-
- netj.reply_port = pkthdr->reply_port;
- netj.latency = pkthdr->latency;
-
- // Special handling for latency=0
- if( netj.latency == 0 )
- netj.resync_threshold = 0;
- else
- netj.resync_threshold = MIN( 15, pkthdr->latency - 1 );
-
- // check whether, we should handle the transport sync stuff, or leave trnasports untouched.
- if (netj.handle_transport_sync) {
- #if 1
- unsigned int compensated_tranport_pos = (pkthdr->transport_frame + (pkthdr->latency * netj.period_size) + netj.codec_latency);
-
- // read local transport info....
- //local_trans_state = jack_transport_query(netj.client, &local_trans_pos);
-
- local_trans_state = fEngineControl->fTransport.Query ( &local_trans_pos );
-
- // Now check if we have to start or stop local transport to sync to remote...
- switch (pkthdr->transport_state) {
-
- case JackTransportStarting:
- // the master transport is starting... so we set our reply to the sync_callback;
- if (local_trans_state == JackTransportStopped) {
- fEngineControl->fTransport.SetCommand ( TransportCommandStart );
- //jack_transport_start(netj.client);
- //last_transport_state = JackTransportStopped;
- netj.sync_state = 0;
- jack_info("locally stopped... starting...");
- }
-
- if (local_trans_pos.frame != compensated_tranport_pos) {
- jack_position_t new_pos = local_trans_pos;
- new_pos.frame = compensated_tranport_pos + 2 * netj.period_size;
- new_pos.valid = (jack_position_bits_t) 0;
-
-
- fEngineControl->fTransport.RequestNewPos ( &new_pos );
- //jack_transport_locate(netj.client, compensated_tranport_pos);
- //last_transport_state = JackTransportRolling;
- netj.sync_state = 0;
- jack_info("starting locate to %d", compensated_tranport_pos );
- }
- break;
-
- case JackTransportStopped:
- netj.sync_state = 1;
- if (local_trans_pos.frame != (pkthdr->transport_frame)) {
- jack_position_t new_pos = local_trans_pos;
- new_pos.frame = pkthdr->transport_frame;
- new_pos.valid = (jack_position_bits_t)0;
- fEngineControl->fTransport.RequestNewPos ( &new_pos );
- //jack_transport_locate(netj.client, (pkthdr->transport_frame));
- jack_info("transport is stopped locate to %d", pkthdr->transport_frame);
- }
- if (local_trans_state != JackTransportStopped)
- //jack_transport_stop(netj.client);
- fEngineControl->fTransport.SetCommand ( TransportCommandStop );
- break;
-
- case JackTransportRolling:
- netj.sync_state = 1;
- // if(local_trans_pos.frame != (pkthdr->transport_frame + (pkthdr->latency) * netj.period_size)) {
- // jack_transport_locate(netj.client, (pkthdr->transport_frame + (pkthdr->latency + 2) * netj.period_size));
- // jack_info("running locate to %d", pkthdr->transport_frame + (pkthdr->latency)*netj.period_size);
- // }
- if (local_trans_state != JackTransportRolling)
- fEngineControl->fTransport.SetState ( JackTransportRolling );
- break;
-
- case JackTransportLooping:
- break;
- }
- #endif
- }
-
- 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 );
- packet_cache_release_packet(netj.packcache, netj.expected_framecnt );
- return 0;
- }
-
- int JackNetOneDriver::Write()
- {
- int syncstate = netj.sync_state | ((fEngineControl->fTransport.GetState() == JackTransportNetStarting) ? 1 : 0 );
- uint32_t *packet_buf, *packet_bufX;
-
- int packet_size = get_sample_size(netj.bitdepth) * netj.playback_channels * netj.net_period_up + sizeof(jacknet_packet_header);
- jacknet_packet_header *pkthdr;
-
- packet_buf = (uint32_t *) alloca(packet_size);
- pkthdr = (jacknet_packet_header *)packet_buf;
-
- if( netj.running_free ) {
- return 0;
- }
-
- // offset packet_bufX by the packetheader.
- packet_bufX = packet_buf + sizeof(jacknet_packet_header) / sizeof(jack_default_audio_sample_t);
-
- pkthdr->sync_state = syncstate;;
- pkthdr->latency = netj.time_to_deadline;
- //printf( "time to deadline = %d goodness=%d\n", (int)netj.time_to_deadline, netj.deadline_goodness );
- pkthdr->framecnt = netj.expected_framecnt;
-
- 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 );
-
- packet_header_hton(pkthdr);
- if (netj.srcaddress_valid) {
- unsigned int r;
- static const int flag = 0;
-
- if (netj.reply_port)
- netj.syncsource_address.sin_port = htons(netj.reply_port);
-
- for( r = 0; r < netj.redundancy; r++ )
- netjack_sendto(netj.sockfd, (char *)packet_buf, packet_size,
- flag, (struct sockaddr*) & (netj.syncsource_address), sizeof(struct sockaddr_in), netj.mtu);
- }
- return 0;
- }
-
- void
- JackNetOneDriver::FreePorts ()
- {
- JSList *node = netj.capture_ports;
-
- while( node != NULL ) {
- JSList *this_node = node;
- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
- node = jack_slist_remove_link( node, this_node );
- jack_slist_free_1( this_node );
- fGraphManager->ReleasePort( fClientControl.fRefNum, port_id );
- }
- netj.capture_ports = NULL;
-
- node = netj.playback_ports;
- while( node != NULL ) {
- JSList *this_node = node;
- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
- node = jack_slist_remove_link( node, this_node );
- jack_slist_free_1( this_node );
- fGraphManager->ReleasePort( fClientControl.fRefNum, port_id );
- }
- netj.playback_ports = NULL;
-
- if( netj.bitdepth == CELT_MODE ) {
- #if HAVE_CELT
- node = netj.playback_srcs;
- while( node != NULL ) {
- JSList *this_node = node;
- CELTEncoder *enc = (CELTEncoder *) node->data;
- node = jack_slist_remove_link( node, this_node );
- jack_slist_free_1( this_node );
- celt_encoder_destroy( enc );
- }
- netj.playback_srcs = NULL;
-
- node = netj.capture_srcs;
- while( node != NULL ) {
- JSList *this_node = node;
- CELTDecoder *dec = (CELTDecoder *) node->data;
- node = jack_slist_remove_link( node, this_node );
- jack_slist_free_1( this_node );
- celt_decoder_destroy( dec );
- }
- netj.capture_srcs = NULL;
- #endif
- } else {
- #if HAVE_SAMPLERATE
- node = netj.playback_srcs;
- while( node != NULL ) {
- JSList *this_node = node;
- SRC_STATE *state = (SRC_STATE *) node->data;
- node = jack_slist_remove_link( node, this_node );
- jack_slist_free_1( this_node );
- src_delete( state );
- }
- netj.playback_srcs = NULL;
-
- node = netj.capture_srcs;
- while( node != NULL ) {
- JSList *this_node = node;
- SRC_STATE *state = (SRC_STATE *) node->data;
- node = jack_slist_remove_link( node, this_node );
- jack_slist_free_1( this_node );
- src_delete( state );
- }
- netj.capture_srcs = NULL;
- #endif
- }
- }
-
- //Render functions--------------------------------------------------------------------
-
- // render functions for float
- void
- 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)
- {
- uint32_t chn = 0;
- JSList *node = capture_ports;
- #if HAVE_SAMPLERATE
- JSList *src_node = capture_srcs;
- #endif
-
- uint32_t *packet_bufX = (uint32_t *)packet_payload;
-
- if( !packet_payload )
- return;
-
- while (node != NULL) {
- unsigned int i;
- int_float_t val;
- #if HAVE_SAMPLERATE
- SRC_DATA src;
- #endif
- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
- JackPort *port = fGraphManager->GetPort( port_id );
-
- jack_default_audio_sample_t* buf =
- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
-
- const char *porttype = port->GetType();
-
- if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
- #if HAVE_SAMPLERATE
- // audio port, resample if necessary
- if (net_period_down != nframes) {
- SRC_STATE *src_state = (SRC_STATE *)src_node->data;
- for (i = 0; i < net_period_down; i++) {
- packet_bufX[i] = ntohl (packet_bufX[i]);
- }
-
- src.data_in = (float *) packet_bufX;
- src.input_frames = net_period_down;
-
- src.data_out = buf;
- src.output_frames = nframes;
-
- src.src_ratio = (float) nframes / (float) net_period_down;
- src.end_of_input = 0;
-
- src_set_ratio (src_state, src.src_ratio);
- src_process (src_state, &src);
- src_node = jack_slist_next (src_node);
- } else
- #endif
- {
- if( dont_htonl_floats ) {
- memcpy( buf, packet_bufX, net_period_down * sizeof(jack_default_audio_sample_t));
- } else {
- for (i = 0; i < net_period_down; i++) {
- val.i = packet_bufX[i];
- val.i = ntohl (val.i);
- buf[i] = val.f;
- }
- }
- }
- } else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
- // midi port, decode midi events
- // convert the data buffer to a standard format (uint32_t based)
- unsigned int buffer_size_uint32 = net_period_down;
- uint32_t * buffer_uint32 = (uint32_t*)packet_bufX;
- decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
- }
- packet_bufX = (packet_bufX + net_period_down);
- node = jack_slist_next (node);
- chn++;
- }
- }
-
- void
- 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 )
- {
- uint32_t chn = 0;
- JSList *node = playback_ports;
- #if HAVE_SAMPLERATE
- JSList *src_node = playback_srcs;
- #endif
-
- uint32_t *packet_bufX = (uint32_t *) packet_payload;
-
- while (node != NULL) {
- #if HAVE_SAMPLERATE
- SRC_DATA src;
- #endif
- unsigned int i;
- int_float_t val;
- jack_port_id_t port_id = (jack_port_id_t)(intptr_t) node->data;
- JackPort *port = fGraphManager->GetPort( port_id );
-
- jack_default_audio_sample_t* buf =
- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
-
- const char *porttype = port->GetType();
-
- if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
- // audio port, resample if necessary
-
- #if HAVE_SAMPLERATE
- if (net_period_up != nframes) {
- SRC_STATE *src_state = (SRC_STATE *) src_node->data;
- src.data_in = buf;
- src.input_frames = nframes;
-
- src.data_out = (float *) packet_bufX;
- src.output_frames = net_period_up;
-
- src.src_ratio = (float) net_period_up / (float) nframes;
- src.end_of_input = 0;
-
- src_set_ratio (src_state, src.src_ratio);
- src_process (src_state, &src);
-
- for (i = 0; i < net_period_up; i++) {
- packet_bufX[i] = htonl (packet_bufX[i]);
- }
- src_node = jack_slist_next (src_node);
- } else
- #endif
- {
- if( dont_htonl_floats ) {
- memcpy( packet_bufX, buf, net_period_up * sizeof(jack_default_audio_sample_t) );
- } else {
- for (i = 0; i < net_period_up; i++) {
- val.f = buf[i];
- val.i = htonl (val.i);
- packet_bufX[i] = val.i;
- }
- }
- }
- } else if (strncmp(porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
- // encode midi events from port to packet
- // convert the data buffer to a standard format (uint32_t based)
- unsigned int buffer_size_uint32 = net_period_up;
- uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
- encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
- }
- packet_bufX = (packet_bufX + net_period_up);
- node = jack_slist_next (node);
- chn++;
- }
- }
-
- #if HAVE_CELT
- // render functions for celt.
- void
- 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)
- {
- uint32_t chn = 0;
- JSList *node = capture_ports;
- JSList *src_node = capture_srcs;
- unsigned char *packet_bufX = (unsigned char *)packet_payload;
-
- while (node != NULL) {
- jack_port_id_t port_id = (jack_port_id_t) (intptr_t)node->data;
- JackPort *port = fGraphManager->GetPort( port_id );
-
- jack_default_audio_sample_t* buf =
- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
-
- const char *portname = port->GetType();
-
- if (strncmp(portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
- // audio port, decode celt data.
- CELTDecoder *decoder = (CELTDecoder *)src_node->data;
-
- #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
- if( !packet_payload )
- celt_decode_float( decoder, NULL, net_period_down, buf, nframes );
- else
- celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes );
- #else
- if( !packet_payload )
- celt_decode_float( decoder, NULL, net_period_down, buf );
- else
- celt_decode_float( decoder, packet_bufX, net_period_down, buf );
- #endif
-
- src_node = jack_slist_next (src_node);
- } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
- // midi port, decode midi events
- // convert the data buffer to a standard format (uint32_t based)
- unsigned int buffer_size_uint32 = net_period_down / 2;
- uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
- if( packet_payload )
- decode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
- }
- packet_bufX = (packet_bufX + net_period_down);
- node = jack_slist_next (node);
- chn++;
- }
- }
-
- void
- 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)
- {
- uint32_t chn = 0;
- JSList *node = playback_ports;
- JSList *src_node = playback_srcs;
-
- unsigned char *packet_bufX = (unsigned char *)packet_payload;
-
- while (node != NULL) {
- jack_port_id_t port_id = (jack_port_id_t) (intptr_t) node->data;
- JackPort *port = fGraphManager->GetPort( port_id );
-
- jack_default_audio_sample_t* buf =
- (jack_default_audio_sample_t*)fGraphManager->GetBuffer(port_id, fEngineControl->fBufferSize);
-
- const char *portname = port->GetType();
-
- if (strncmp (portname, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size()) == 0) {
- // audio port, encode celt data.
-
- int encoded_bytes;
- jack_default_audio_sample_t *floatbuf = (jack_default_audio_sample_t *)alloca (sizeof(jack_default_audio_sample_t) * nframes );
- memcpy( floatbuf, buf, nframes * sizeof(jack_default_audio_sample_t) );
- CELTEncoder *encoder = (CELTEncoder *)src_node->data;
- #if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11
- encoded_bytes = celt_encode_float( encoder, floatbuf, nframes, packet_bufX, net_period_up );
- #else
- encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up );
- #endif
- if( encoded_bytes != (int)net_period_up )
- jack_error( "something in celt changed. netjack needs to be changed to handle this." );
- src_node = jack_slist_next( src_node );
- } else if (strncmp(portname, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size()) == 0) {
- // encode midi events from port to packet
- // convert the data buffer to a standard format (uint32_t based)
- unsigned int buffer_size_uint32 = net_period_up / 2;
- uint32_t * buffer_uint32 = (uint32_t*) packet_bufX;
- encode_midi_buffer (buffer_uint32, buffer_size_uint32, buf);
- }
- packet_bufX = (packet_bufX + net_period_up);
- node = jack_slist_next (node);
- chn++;
- }
- }
-
- #endif
- /* Wrapper functions with bitdepth argument... */
- void
- 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)
- {
- #if HAVE_CELT
- if (bitdepth == CELT_MODE)
- render_payload_to_jack_ports_celt (packet_payload, net_period_down, capture_ports, capture_srcs, nframes);
- else
- #endif
- render_payload_to_jack_ports_float (packet_payload, net_period_down, capture_ports, capture_srcs, nframes, dont_htonl_floats);
- }
-
- void
- 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)
- {
- #if HAVE_CELT
- if (bitdepth == CELT_MODE)
- render_jack_ports_to_payload_celt (playback_ports, playback_srcs, nframes, packet_payload, net_period_up);
- else
- #endif
- render_jack_ports_to_payload_float (playback_ports, playback_srcs, nframes, packet_payload, net_period_up, dont_htonl_floats);
- }
-
- //driver loader-----------------------------------------------------------------------
-
- #ifdef __cplusplus
- extern "C"
- {
- #endif
- SERVER_EXPORT jack_driver_desc_t* driver_get_descriptor ()
- {
- jack_driver_desc_t* desc = ( jack_driver_desc_t* ) calloc ( 1, sizeof ( jack_driver_desc_t ) );
- jack_driver_param_desc_t * params;
-
- strcpy ( desc->name, "netone" ); // size MUST be less then JACK_DRIVER_NAME_MAX + 1
- strcpy ( desc->desc, "netjack one slave backend component" ); // size MUST be less then JACK_DRIVER_PARAM_DESC + 1
-
- desc->nparams = 18;
- params = ( jack_driver_param_desc_t* ) calloc ( desc->nparams, sizeof ( jack_driver_param_desc_t ) );
-
- int i = 0;
- strcpy (params[i].name, "audio-ins");
- params[i].character = 'i';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 2U;
- strcpy (params[i].short_desc, "Number of capture channels (defaults to 2)");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "audio-outs");
- params[i].character = 'o';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 2U;
- strcpy (params[i].short_desc, "Number of playback channels (defaults to 2)");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "midi-ins");
- params[i].character = 'I';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 1U;
- strcpy (params[i].short_desc, "Number of midi capture channels (defaults to 1)");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "midi-outs");
- params[i].character = 'O';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 1U;
- strcpy (params[i].short_desc, "Number of midi playback channels (defaults to 1)");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "rate");
- params[i].character = 'r';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 48000U;
- strcpy (params[i].short_desc, "Sample rate");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "period");
- params[i].character = 'p';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 1024U;
- strcpy (params[i].short_desc, "Frames per period");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "num-periods");
- params[i].character = 'n';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 5U;
- strcpy (params[i].short_desc,
- "Network latency setting in no. of periods");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "listen-port");
- params[i].character = 'l';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 3000U;
- strcpy (params[i].short_desc,
- "The socket port we are listening on for sync packets");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "factor");
- params[i].character = 'f';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 1U;
- strcpy (params[i].short_desc,
- "Factor for sample rate reduction");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "upstream-factor");
- params[i].character = 'u';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 0U;
- strcpy (params[i].short_desc,
- "Factor for sample rate reduction on the upstream");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "celt");
- params[i].character = 'c';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 0U;
- strcpy (params[i].short_desc,
- "sets celt encoding and number of kbits per channel");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "bit-depth");
- params[i].character = 'b';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 0U;
- strcpy (params[i].short_desc,
- "Sample bit-depth (0 for float, 8 for 8bit and 16 for 16bit)");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "transport-sync");
- params[i].character = 't';
- params[i].type = JackDriverParamBool;
- params[i].value.ui = 1U;
- strcpy (params[i].short_desc,
- "Whether to slave the transport to the master transport");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "autoconf");
- params[i].character = 'a';
- params[i].type = JackDriverParamBool;
- params[i].value.ui = 1U;
- strcpy (params[i].short_desc,
- "Whether to use Autoconfig, or just start.");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "redundancy");
- params[i].character = 'R';
- params[i].type = JackDriverParamUInt;
- params[i].value.ui = 1U;
- strcpy (params[i].short_desc,
- "Send packets N times");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "native-endian");
- params[i].character = 'e';
- params[i].type = JackDriverParamBool;
- params[i].value.ui = 0U;
- strcpy (params[i].short_desc,
- "Dont convert samples to network byte order.");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "jitterval");
- params[i].character = 'J';
- params[i].type = JackDriverParamInt;
- params[i].value.i = 0;
- strcpy (params[i].short_desc,
- "attempted jitterbuffer microseconds on master");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- i++;
- strcpy (params[i].name, "always-deadline");
- params[i].character = 'D';
- params[i].type = JackDriverParamBool;
- params[i].value.ui = 0U;
- strcpy (params[i].short_desc,
- "always use deadline");
- strcpy (params[i].long_desc, params[i].short_desc);
-
- desc->params = params;
-
- return desc;
- }
-
- SERVER_EXPORT Jack::JackDriverClientInterface* driver_initialize ( Jack::JackLockedEngine* engine, Jack::JackSynchro* table, const JSList* params )
- {
- jack_nframes_t sample_rate = 48000;
- jack_nframes_t resample_factor = 1;
- jack_nframes_t period_size = 1024;
- unsigned int capture_ports = 2;
- unsigned int playback_ports = 2;
- unsigned int capture_ports_midi = 1;
- unsigned int playback_ports_midi = 1;
- unsigned int listen_port = 3000;
- unsigned int bitdepth = 0;
- unsigned int handle_transport_sync = 1;
- unsigned int use_autoconfig = 1;
- unsigned int latency = 5;
- unsigned int redundancy = 1;
- unsigned int mtu = 1400;
- #if HAVE_SAMPLERATE
- unsigned int resample_factor_up = 1;
- #endif
- int dont_htonl_floats = 0;
- int always_deadline = 0;
- int jitter_val = 0;
- const JSList * node;
- const jack_driver_param_t * param;
-
- for ( node = params; node; node = jack_slist_next ( node ) ) {
- param = ( const jack_driver_param_t* ) node->data;
- switch ( param->character ) {
- case 'i':
- capture_ports = param->value.ui;
- break;
-
- case 'o':
- playback_ports = param->value.ui;
- break;
-
- case 'I':
- capture_ports_midi = param->value.ui;
- break;
-
- case 'O':
- playback_ports_midi = param->value.ui;
- break;
-
- case 'r':
- sample_rate = param->value.ui;
- break;
-
- case 'p':
- period_size = param->value.ui;
- break;
-
- case 'l':
- listen_port = param->value.ui;
- break;
-
- case 'f':
- #if HAVE_SAMPLERATE
- resample_factor = param->value.ui;
- #else
- jack_error( "not built with libsamplerate support" );
- return NULL;
- #endif
- break;
-
- case 'u':
- #if HAVE_SAMPLERATE
- resample_factor_up = param->value.ui;
- #else
- jack_error( "not built with libsamplerate support" );
- return NULL;
- #endif
- break;
-
- case 'b':
- bitdepth = param->value.ui;
- break;
-
- case 'c':
- #if HAVE_CELT
- bitdepth = CELT_MODE;
- resample_factor = param->value.ui;
- #else
- jack_error( "not built with celt support" );
- return NULL;
- #endif
- break;
-
- case 't':
- handle_transport_sync = param->value.ui;
- break;
-
- case 'a':
- use_autoconfig = param->value.ui;
- break;
-
- case 'n':
- latency = param->value.ui;
- break;
-
- case 'R':
- redundancy = param->value.ui;
- break;
-
- case 'H':
- dont_htonl_floats = param->value.ui;
- break;
-
- case 'J':
- jitter_val = param->value.i;
- break;
-
- case 'D':
- always_deadline = param->value.ui;
- break;
- }
- }
-
- try {
- Jack::JackDriverClientInterface* driver =
- new Jack::JackWaitThreadedDriver (
- new Jack::JackNetOneDriver ( "system", "net_pcm", engine, table, listen_port, mtu,
- capture_ports_midi, playback_ports_midi, capture_ports, playback_ports,
- sample_rate, period_size, resample_factor,
- "net_pcm", handle_transport_sync, bitdepth, use_autoconfig, latency, redundancy,
- dont_htonl_floats, always_deadline, jitter_val ) );
-
- if ( driver->Open ( period_size, sample_rate, 1, 1, capture_ports, playback_ports,
- 0, "from_master_", "to_master_", 0, 0 ) == 0 ) {
- return driver;
- } else {
- delete driver;
- return NULL;
- }
-
- } catch ( ... ) {
- return NULL;
- }
- }
-
- #ifdef __cplusplus
- }
- #endif
- }
|