@@ -90,6 +90,7 @@ class JackNetOneDriver : public JackAudioDriver | |||
} | |||
}; | |||
} | |||
#endif |
@@ -86,26 +86,25 @@ int netjack_wait( netjack_driver_state_t *netj ) | |||
jacknet_packet_header *pkthdr; | |||
if( !netj->next_deadline_valid ) { | |||
netj->next_deadline = jack_get_time() + netj->period_usecs; | |||
netj->next_deadline_valid = 1; | |||
netj->next_deadline = jack_get_time() + netj->period_usecs; | |||
netj->next_deadline_valid = 1; | |||
} | |||
// Increment expected frame here. | |||
if( netj->expected_framecnt_valid ) { | |||
netj->expected_framecnt += 1; | |||
netj->expected_framecnt += 1; | |||
} else { | |||
// starting up.... lets look into the packetcache, and fetch the highest packet. | |||
packet_cache_drain_socket( netj->packcache, netj->sockfd ); | |||
if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail ) ) { | |||
netj->expected_framecnt = next_frame_avail; | |||
netj->expected_framecnt_valid = 1; | |||
} else { | |||
// no packets there... start normally. | |||
netj->expected_framecnt = 0; | |||
netj->expected_framecnt_valid = 1; | |||
} | |||
// starting up.... lets look into the packetcache, and fetch the highest packet. | |||
packet_cache_drain_socket( netj->packcache, netj->sockfd ); | |||
if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail ) ) { | |||
netj->expected_framecnt = next_frame_avail; | |||
netj->expected_framecnt_valid = 1; | |||
} else { | |||
// no packets there... start normally. | |||
netj->expected_framecnt = 0; | |||
netj->expected_framecnt_valid = 1; | |||
} | |||
} | |||
//jack_log( "expect %d", netj->expected_framecnt ); | |||
@@ -113,26 +112,26 @@ int netjack_wait( netjack_driver_state_t *netj ) | |||
// then poll (have deadline calculated) | |||
// then drain socket, rinse and repeat. | |||
while(1) { | |||
if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) { | |||
if( next_frame_avail == netj->expected_framecnt ) { | |||
we_have_the_expected_frame = 1; | |||
if( !netj->always_deadline ) | |||
break; | |||
} | |||
} | |||
if( ! netjack_poll_deadline( netj->sockfd, netj->next_deadline ) ) { | |||
break; | |||
} | |||
packet_cache_drain_socket( netj->packcache, netj->sockfd ); | |||
if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) { | |||
if( next_frame_avail == netj->expected_framecnt ) { | |||
we_have_the_expected_frame = 1; | |||
if( !netj->always_deadline ) | |||
break; | |||
} | |||
} | |||
if( ! netjack_poll_deadline( netj->sockfd, netj->next_deadline ) ) { | |||
break; | |||
} | |||
packet_cache_drain_socket( netj->packcache, netj->sockfd ); | |||
} | |||
// check if we know who to send our packets too. | |||
if (!netj->srcaddress_valid) | |||
if( netj->packcache->master_address_valid ) { | |||
memcpy (&(netj->syncsource_address), &(netj->packcache->master_address), sizeof( struct sockaddr_in ) ); | |||
netj->srcaddress_valid = 1; | |||
} | |||
if( netj->packcache->master_address_valid ) { | |||
memcpy (&(netj->syncsource_address), &(netj->packcache->master_address), sizeof( struct sockaddr_in ) ); | |||
netj->srcaddress_valid = 1; | |||
} | |||
// XXX: switching mode unconditionally is stupid. | |||
// if we were running free perhaps we like to behave differently | |||
@@ -146,169 +145,168 @@ int netjack_wait( netjack_driver_state_t *netj ) | |||
if( we_have_the_expected_frame ) { | |||
jack_time_t now = jack_get_time(); | |||
if( now < netj->next_deadline ) | |||
netj->time_to_deadline = netj->next_deadline - now; | |||
else | |||
netj->time_to_deadline = 0; | |||
packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize , &packet_recv_time_stamp); | |||
pkthdr = (jacknet_packet_header *) netj->rx_buf; | |||
packet_header_ntoh(pkthdr); | |||
netj->deadline_goodness = (int)pkthdr->sync_state; | |||
netj->packet_data_valid = 1; | |||
int want_deadline; | |||
if( netj->jitter_val != 0 ) | |||
want_deadline = netj->jitter_val; | |||
else if( netj->latency < 4 ) | |||
want_deadline = -netj->period_usecs/2; | |||
else | |||
want_deadline = (netj->period_usecs/4+10*(int)netj->period_usecs*netj->latency/100); | |||
if( netj->deadline_goodness != MASTER_FREEWHEELS ) { | |||
if( netj->deadline_goodness < want_deadline ) { | |||
netj->next_deadline -= netj->period_usecs/100; | |||
//jack_log( "goodness: %d, Adjust deadline: --- %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 ); | |||
} | |||
if( netj->deadline_goodness > want_deadline ) { | |||
netj->next_deadline += netj->period_usecs/100; | |||
//jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 ); | |||
} | |||
} | |||
jack_time_t now = jack_get_time(); | |||
if( now < netj->next_deadline ) | |||
netj->time_to_deadline = netj->next_deadline - now; | |||
else | |||
netj->time_to_deadline = 0; | |||
packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) & (netj->rx_buf), netj->rx_bufsize , &packet_recv_time_stamp); | |||
pkthdr = (jacknet_packet_header *) netj->rx_buf; | |||
packet_header_ntoh(pkthdr); | |||
netj->deadline_goodness = (int)pkthdr->sync_state; | |||
netj->packet_data_valid = 1; | |||
int want_deadline; | |||
if( netj->jitter_val != 0 ) | |||
want_deadline = netj->jitter_val; | |||
else if( netj->latency < 4 ) | |||
want_deadline = -netj->period_usecs / 2; | |||
else | |||
want_deadline = (netj->period_usecs / 4 + 10 * (int)netj->period_usecs * netj->latency / 100); | |||
if( netj->deadline_goodness != MASTER_FREEWHEELS ) { | |||
if( netj->deadline_goodness < want_deadline ) { | |||
netj->next_deadline -= netj->period_usecs / 100; | |||
//jack_log( "goodness: %d, Adjust deadline: --- %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 ); | |||
} | |||
if( netj->deadline_goodness > want_deadline ) { | |||
netj->next_deadline += netj->period_usecs / 100; | |||
//jack_log( "goodness: %d, Adjust deadline: +++ %d\n", netj->deadline_goodness, (int) netj->period_usecs*netj->latency/100 ); | |||
} | |||
} | |||
// if( netj->next_deadline < (netj->period_usecs*70/100) ) { | |||
// jack_error( "master is forcing deadline_offset to below 70%% of period_usecs... increase latency setting on master" ); | |||
// netj->deadline_offset = (netj->period_usecs*90/100); | |||
// } | |||
netj->next_deadline += netj->period_usecs; | |||
netj->next_deadline += netj->period_usecs; | |||
} else { | |||
netj->time_to_deadline = 0; | |||
netj->next_deadline += netj->period_usecs; | |||
// bah... the packet is not there. | |||
// either | |||
// - it got lost. | |||
// - its late | |||
// - sync source is not sending anymore. | |||
// lets check if we have the next packets, we will just run a cycle without data. | |||
// in that case. | |||
if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) | |||
{ | |||
jack_nframes_t offset = next_frame_avail - netj->expected_framecnt; | |||
//XXX: hmm... i need to remember why resync_threshold wasnt right. | |||
//if( offset < netj->resync_threshold ) | |||
if( offset < 10 ) { | |||
// ok. dont do nothing. we will run without data. | |||
// this seems to be one or 2 lost packets. | |||
// | |||
// this can also be reordered packet jitter. | |||
// (maybe this is not happening in real live) | |||
// but it happens in netem. | |||
netj->packet_data_valid = 0; | |||
// I also found this happening, when the packet queue, is too full. | |||
// but wtf ? use a smaller latency. this link can handle that ;S | |||
if( packet_cache_get_fill( netj->packcache, netj->expected_framecnt ) > 80.0 ) | |||
netj->next_deadline -= netj->period_usecs/2; | |||
} else { | |||
// the diff is too high. but we have a packet in the future. | |||
// lets resync. | |||
netj->expected_framecnt = next_frame_avail; | |||
packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL ); | |||
pkthdr = (jacknet_packet_header *) netj->rx_buf; | |||
packet_header_ntoh(pkthdr); | |||
//netj->deadline_goodness = 0; | |||
netj->deadline_goodness = (int)pkthdr->sync_state - (int)netj->period_usecs * offset; | |||
netj->next_deadline_valid = 0; | |||
netj->packet_data_valid = 1; | |||
} | |||
} else { | |||
// no packets in buffer. | |||
netj->packet_data_valid = 0; | |||
//printf( "frame %d No Packet in queue. num_lost_packets = %d \n", netj->expected_framecnt, netj->num_lost_packets ); | |||
if( netj->num_lost_packets < 5 ) { | |||
// ok. No Packet in queue. The packet was either lost, | |||
// or we are running too fast. | |||
// | |||
// Adjusting the deadline unconditionally resulted in | |||
// too many xruns on master. | |||
// But we need to adjust for the case we are running too fast. | |||
// So lets check if the last packet is there now. | |||
// | |||
// It would not be in the queue anymore, if it had been | |||
// retrieved. This might break for redundancy, but | |||
// i will make the packet cache drop redundant packets, | |||
// that have already been retreived. | |||
// | |||
if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) { | |||
if( next_frame_avail == (netj->expected_framecnt - 1) ) { | |||
// Ok. the last packet is there now. | |||
// and it had not been retrieved. | |||
// | |||
// TODO: We are still dropping 2 packets. | |||
// perhaps we can adjust the deadline | |||
// when (num_packets lost == 0) | |||
// This might still be too much. | |||
netj->next_deadline += netj->period_usecs; | |||
} | |||
} | |||
} else if( (netj->num_lost_packets <= 100) ) { | |||
// lets try adjusting the deadline harder, for some packets, we might have just ran 2 fast. | |||
netj->next_deadline += netj->period_usecs*netj->latency/8; | |||
} else { | |||
// But now we can check for any new frame available. | |||
// | |||
if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) { | |||
netj->expected_framecnt = next_frame_avail; | |||
packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) &(netj->rx_buf), netj->rx_bufsize, NULL ); | |||
pkthdr = (jacknet_packet_header *) netj->rx_buf; | |||
packet_header_ntoh(pkthdr); | |||
netj->deadline_goodness = pkthdr->sync_state; | |||
netj->next_deadline_valid = 0; | |||
netj->packet_data_valid = 1; | |||
netj->running_free = 0; | |||
jack_info( "resync after freerun... %d", netj->expected_framecnt ); | |||
} else { | |||
if( netj->num_lost_packets == 101 ) { | |||
jack_info( "master seems gone... entering freerun mode", netj->expected_framecnt ); | |||
} | |||
netj->running_free = 1; | |||
// when we really dont see packets. | |||
// reset source address. and open possibility for new master. | |||
// maybe dsl reconnect. Also restart of netsource without fix | |||
// reply address changes port. | |||
if (netj->num_lost_packets > 200 ) { | |||
netj->srcaddress_valid = 0; | |||
packet_cache_reset_master_address( netj->packcache ); | |||
} | |||
} | |||
} | |||
} | |||
netj->time_to_deadline = 0; | |||
netj->next_deadline += netj->period_usecs; | |||
// bah... the packet is not there. | |||
// either | |||
// - it got lost. | |||
// - its late | |||
// - sync source is not sending anymore. | |||
// lets check if we have the next packets, we will just run a cycle without data. | |||
// in that case. | |||
if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) { | |||
jack_nframes_t offset = next_frame_avail - netj->expected_framecnt; | |||
//XXX: hmm... i need to remember why resync_threshold wasnt right. | |||
//if( offset < netj->resync_threshold ) | |||
if( offset < 10 ) { | |||
// ok. dont do nothing. we will run without data. | |||
// this seems to be one or 2 lost packets. | |||
// | |||
// this can also be reordered packet jitter. | |||
// (maybe this is not happening in real live) | |||
// but it happens in netem. | |||
netj->packet_data_valid = 0; | |||
// I also found this happening, when the packet queue, is too full. | |||
// but wtf ? use a smaller latency. this link can handle that ;S | |||
if( packet_cache_get_fill( netj->packcache, netj->expected_framecnt ) > 80.0 ) | |||
netj->next_deadline -= netj->period_usecs / 2; | |||
} else { | |||
// the diff is too high. but we have a packet in the future. | |||
// lets resync. | |||
netj->expected_framecnt = next_frame_avail; | |||
packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) & (netj->rx_buf), netj->rx_bufsize, NULL ); | |||
pkthdr = (jacknet_packet_header *) netj->rx_buf; | |||
packet_header_ntoh(pkthdr); | |||
//netj->deadline_goodness = 0; | |||
netj->deadline_goodness = (int)pkthdr->sync_state - (int)netj->period_usecs * offset; | |||
netj->next_deadline_valid = 0; | |||
netj->packet_data_valid = 1; | |||
} | |||
} else { | |||
// no packets in buffer. | |||
netj->packet_data_valid = 0; | |||
//printf( "frame %d No Packet in queue. num_lost_packets = %d \n", netj->expected_framecnt, netj->num_lost_packets ); | |||
if( netj->num_lost_packets < 5 ) { | |||
// ok. No Packet in queue. The packet was either lost, | |||
// or we are running too fast. | |||
// | |||
// Adjusting the deadline unconditionally resulted in | |||
// too many xruns on master. | |||
// But we need to adjust for the case we are running too fast. | |||
// So lets check if the last packet is there now. | |||
// | |||
// It would not be in the queue anymore, if it had been | |||
// retrieved. This might break for redundancy, but | |||
// i will make the packet cache drop redundant packets, | |||
// that have already been retreived. | |||
// | |||
if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) { | |||
if( next_frame_avail == (netj->expected_framecnt - 1) ) { | |||
// Ok. the last packet is there now. | |||
// and it had not been retrieved. | |||
// | |||
// TODO: We are still dropping 2 packets. | |||
// perhaps we can adjust the deadline | |||
// when (num_packets lost == 0) | |||
// This might still be too much. | |||
netj->next_deadline += netj->period_usecs; | |||
} | |||
} | |||
} else if( (netj->num_lost_packets <= 100) ) { | |||
// lets try adjusting the deadline harder, for some packets, we might have just ran 2 fast. | |||
netj->next_deadline += netj->period_usecs * netj->latency / 8; | |||
} else { | |||
// But now we can check for any new frame available. | |||
// | |||
if( packet_cache_get_highest_available_framecnt( netj->packcache, &next_frame_avail) ) { | |||
netj->expected_framecnt = next_frame_avail; | |||
packet_cache_retreive_packet_pointer( netj->packcache, netj->expected_framecnt, (char **) & (netj->rx_buf), netj->rx_bufsize, NULL ); | |||
pkthdr = (jacknet_packet_header *) netj->rx_buf; | |||
packet_header_ntoh(pkthdr); | |||
netj->deadline_goodness = pkthdr->sync_state; | |||
netj->next_deadline_valid = 0; | |||
netj->packet_data_valid = 1; | |||
netj->running_free = 0; | |||
jack_info( "resync after freerun... %d", netj->expected_framecnt ); | |||
} else { | |||
if( netj->num_lost_packets == 101 ) { | |||
jack_info( "master seems gone... entering freerun mode", netj->expected_framecnt ); | |||
} | |||
netj->running_free = 1; | |||
// when we really dont see packets. | |||
// reset source address. and open possibility for new master. | |||
// maybe dsl reconnect. Also restart of netsource without fix | |||
// reply address changes port. | |||
if (netj->num_lost_packets > 200 ) { | |||
netj->srcaddress_valid = 0; | |||
packet_cache_reset_master_address( netj->packcache ); | |||
} | |||
} | |||
} | |||
} | |||
} | |||
int retval = 0; | |||
if( !netj->packet_data_valid ) { | |||
netj->num_lost_packets += 1; | |||
if( netj->num_lost_packets == 1 ) | |||
retval = netj->period_usecs; | |||
netj->num_lost_packets += 1; | |||
if( netj->num_lost_packets == 1 ) | |||
retval = netj->period_usecs; | |||
} else { | |||
if( (netj->num_lost_packets>1) && !netj->running_free ) | |||
retval = (netj->num_lost_packets-1) * netj->period_usecs; | |||
if( (netj->num_lost_packets > 1) && !netj->running_free ) | |||
retval = (netj->num_lost_packets - 1) * netj->period_usecs; | |||
netj->num_lost_packets = 0; | |||
netj->num_lost_packets = 0; | |||
} | |||
return retval; | |||
@@ -338,19 +336,17 @@ void netjack_send_silence( netjack_driver_state_t *netj, int syncstate ) | |||
memset(packet_bufX, 0, payload_size); | |||
packet_header_hton(tx_pkthdr); | |||
if (netj->srcaddress_valid) | |||
{ | |||
int r; | |||
if (netj->reply_port) | |||
netj->syncsource_address.sin_port = htons(netj->reply_port); | |||
for( r=0; r<netj->redundancy; r++ ) | |||
netjack_sendto(netj->outsockfd, (char *)packet_buf, tx_size, | |||
0, (struct sockaddr*)&(netj->syncsource_address), sizeof(struct sockaddr_in), netj->mtu); | |||
if (netj->srcaddress_valid) { | |||
int r; | |||
if (netj->reply_port) | |||
netj->syncsource_address.sin_port = htons(netj->reply_port); | |||
for( r = 0; r < netj->redundancy; r++ ) | |||
netjack_sendto(netj->outsockfd, (char *)packet_buf, tx_size, | |||
0, (struct sockaddr*) & (netj->syncsource_address), sizeof(struct sockaddr_in), netj->mtu); | |||
} | |||
} | |||
void netjack_attach( netjack_driver_state_t *netj ) | |||
{ | |||
//puts ("net_driver_attach"); | |||
@@ -359,19 +355,17 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||
unsigned int chn; | |||
int port_flags; | |||
if( netj->bitdepth == CELT_MODE ) | |||
{ | |||
if( netj->bitdepth == CELT_MODE ) { | |||
#if HAVE_CELT | |||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||
celt_int32 lookahead; | |||
netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | |||
celt_int32 lookahead; | |||
netj->celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | |||
#else | |||
celt_int32_t lookahead; | |||
netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); | |||
celt_int32_t lookahead; | |||
netj->celt_mode = celt_mode_create( netj->sample_rate, 1, netj->period_size, NULL ); | |||
#endif | |||
celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); | |||
netj->codec_latency = 2*lookahead; | |||
celt_mode_info( netj->celt_mode, CELT_GET_LOOKAHEAD, &lookahead ); | |||
netj->codec_latency = 2 * lookahead; | |||
#endif | |||
} | |||
@@ -394,21 +388,21 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||
netj->capture_ports = | |||
jack_slist_append (netj->capture_ports, port); | |||
if( netj->bitdepth == CELT_MODE ) { | |||
if( netj->bitdepth == CELT_MODE ) { | |||
#if HAVE_CELT | |||
#if HAVE_CELT_API_0_11 | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create_custom( netj->celt_mode, 1, NULL ) ); | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create_custom( netj->celt_mode, 1, NULL ) ); | |||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode, 1, NULL ) ); | |||
#else | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, celt_decoder_create( netj->celt_mode ) ); | |||
#endif | |||
#endif | |||
} else { | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, src_new(SRC_LINEAR, 1, NULL)); | |||
netj->capture_srcs = jack_slist_append(netj->capture_srcs, src_new(SRC_LINEAR, 1, NULL)); | |||
#endif | |||
} | |||
} | |||
} | |||
for (chn = netj->capture_channels_audio; chn < netj->capture_channels; chn++) { | |||
@@ -442,24 +436,24 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||
netj->playback_ports = | |||
jack_slist_append (netj->playback_ports, port); | |||
if( netj->bitdepth == CELT_MODE ) { | |||
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_decoder_create_custom( celt_mode, 1, NULL ) ); | |||
CELTMode *celt_mode = celt_mode_create( netj->sample_rate, netj->period_size, NULL ); | |||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, celt_decoder_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 ) ); | |||
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 ) ); | |||
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 { | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, src_new(SRC_LINEAR, 1, NULL)); | |||
netj->playback_srcs = jack_slist_append(netj->playback_srcs, src_new(SRC_LINEAR, 1, NULL)); | |||
#endif | |||
} | |||
} | |||
} | |||
for (chn = netj->playback_channels_audio; chn < netj->playback_channels; chn++) { | |||
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); | |||
@@ -492,15 +486,12 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||
jack_slist_free (netj->capture_ports); | |||
netj->capture_ports = NULL; | |||
for (node = netj->capture_srcs; node; node = jack_slist_next (node)) | |||
{ | |||
for (node = netj->capture_srcs; node; node = jack_slist_next (node)) { | |||
#if HAVE_CELT | |||
if( netj->bitdepth == CELT_MODE ) | |||
{ | |||
if( netj->bitdepth == CELT_MODE ) { | |||
CELTDecoder * decoder = node->data; | |||
celt_decoder_destroy(decoder); | |||
} | |||
else | |||
} else | |||
#endif | |||
{ | |||
#if HAVE_SAMPLERATE | |||
@@ -519,15 +510,12 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||
jack_slist_free (netj->playback_ports); | |||
netj->playback_ports = NULL; | |||
for (node = netj->playback_srcs; node; node = jack_slist_next (node)) | |||
{ | |||
for (node = netj->playback_srcs; node; node = jack_slist_next (node)) { | |||
#if HAVE_CELT | |||
if( netj->bitdepth == CELT_MODE ) | |||
{ | |||
if( netj->bitdepth == CELT_MODE ) { | |||
CELTEncoder * encoder = node->data; | |||
celt_encoder_destroy(encoder); | |||
} | |||
else | |||
} else | |||
#endif | |||
{ | |||
#if HAVE_SAMPLERATE | |||
@@ -540,32 +528,32 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||
netj->playback_srcs = NULL; | |||
#if HAVE_CELT | |||
if( netj->bitdepth == CELT_MODE ) | |||
celt_mode_destroy(netj->celt_mode); | |||
if( netj->bitdepth == CELT_MODE ) | |||
celt_mode_destroy(netj->celt_mode); | |||
#endif | |||
} | |||
netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | |||
jack_client_t * client, | |||
const char *name, | |||
unsigned int capture_ports, | |||
unsigned int playback_ports, | |||
unsigned int capture_ports_midi, | |||
unsigned int playback_ports_midi, | |||
jack_nframes_t sample_rate, | |||
jack_nframes_t period_size, | |||
unsigned int listen_port, | |||
unsigned int transport_sync, | |||
unsigned int resample_factor, | |||
unsigned int resample_factor_up, | |||
unsigned int bitdepth, | |||
unsigned int use_autoconfig, | |||
unsigned int latency, | |||
unsigned int redundancy, | |||
int dont_htonl_floats, | |||
int always_deadline, | |||
int jitter_val ) | |||
jack_client_t * client, | |||
const char *name, | |||
unsigned int capture_ports, | |||
unsigned int playback_ports, | |||
unsigned int capture_ports_midi, | |||
unsigned int playback_ports_midi, | |||
jack_nframes_t sample_rate, | |||
jack_nframes_t period_size, | |||
unsigned int listen_port, | |||
unsigned int transport_sync, | |||
unsigned int resample_factor, | |||
unsigned int resample_factor_up, | |||
unsigned int bitdepth, | |||
unsigned int use_autoconfig, | |||
unsigned int latency, | |||
unsigned int redundancy, | |||
int dont_htonl_floats, | |||
int always_deadline, | |||
int jitter_val ) | |||
{ | |||
// Fill in netj values. | |||
@@ -600,8 +588,7 @@ netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | |||
netj->client = client; | |||
if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE)) | |||
{ | |||
if ((bitdepth != 0) && (bitdepth != 8) && (bitdepth != 16) && (bitdepth != CELT_MODE)) { | |||
jack_info ("Invalid bitdepth: %d (8, 16 or 0 for float) !!!", bitdepth); | |||
return NULL; | |||
} | |||
@@ -647,8 +634,7 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
address.sin_family = AF_INET; | |||
address.sin_port = htons(netj->listen_port); | |||
address.sin_addr.s_addr = htonl(INADDR_ANY); | |||
if (bind (netj->sockfd, (struct sockaddr *) &address, sizeof (address)) < 0) | |||
{ | |||
if (bind (netj->sockfd, (struct sockaddr *) &address, sizeof (address)) < 0) { | |||
jack_info("bind error"); | |||
return -1; | |||
} | |||
@@ -664,14 +650,13 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
return -1; | |||
} | |||
netj->srcaddress_valid = 0; | |||
if (netj->use_autoconfig) | |||
{ | |||
if (netj->use_autoconfig) { | |||
jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header)); | |||
#ifdef WIN32 | |||
#ifdef WIN32 | |||
int address_size = sizeof( struct sockaddr_in ); | |||
#else | |||
#else | |||
socklen_t address_size = sizeof (struct sockaddr_in); | |||
#endif | |||
#endif | |||
//jack_info ("Waiting for an incoming packet !!!"); | |||
//jack_info ("*** IMPORTANT *** Dont connect a client to jackd until the driver is attached to a clock source !!!"); | |||
@@ -681,51 +666,44 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
return -1; | |||
} | |||
first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size); | |||
#ifdef WIN32 | |||
if( first_pack_len == -1 ) { | |||
first_pack_len = sizeof(jacknet_packet_header); | |||
break; | |||
} | |||
#else | |||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||
break; | |||
#endif | |||
#ifdef WIN32 | |||
if( first_pack_len == -1 ) { | |||
first_pack_len = sizeof(jacknet_packet_header); | |||
break; | |||
} | |||
#else | |||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||
break; | |||
#endif | |||
} | |||
netj->srcaddress_valid = 1; | |||
if (first_pack_len == sizeof (jacknet_packet_header)) | |||
{ | |||
if (first_pack_len == sizeof (jacknet_packet_header)) { | |||
packet_header_ntoh (first_packet); | |||
jack_info ("AutoConfig Override !!!"); | |||
if (netj->sample_rate != first_packet->sample_rate) | |||
{ | |||
if (netj->sample_rate != first_packet->sample_rate) { | |||
jack_info ("AutoConfig Override: Master JACK sample rate = %d", first_packet->sample_rate); | |||
netj->sample_rate = first_packet->sample_rate; | |||
} | |||
} | |||
if (netj->period_size != first_packet->period_size) | |||
{ | |||
if (netj->period_size != first_packet->period_size) { | |||
jack_info ("AutoConfig Override: Master JACK period size is %d", first_packet->period_size); | |||
netj->period_size = first_packet->period_size; | |||
} | |||
if (netj->capture_channels_audio != first_packet->capture_channels_audio) | |||
{ | |||
} | |||
if (netj->capture_channels_audio != first_packet->capture_channels_audio) { | |||
jack_info ("AutoConfig Override: capture_channels_audio = %d", first_packet->capture_channels_audio); | |||
netj->capture_channels_audio = first_packet->capture_channels_audio; | |||
} | |||
if (netj->capture_channels_midi != first_packet->capture_channels_midi) | |||
{ | |||
if (netj->capture_channels_midi != first_packet->capture_channels_midi) { | |||
jack_info ("AutoConfig Override: capture_channels_midi = %d", first_packet->capture_channels_midi); | |||
netj->capture_channels_midi = first_packet->capture_channels_midi; | |||
} | |||
if (netj->playback_channels_audio != first_packet->playback_channels_audio) | |||
{ | |||
if (netj->playback_channels_audio != first_packet->playback_channels_audio) { | |||
jack_info ("AutoConfig Override: playback_channels_audio = %d", first_packet->playback_channels_audio); | |||
netj->playback_channels_audio = first_packet->playback_channels_audio; | |||
} | |||
if (netj->playback_channels_midi != first_packet->playback_channels_midi) | |||
{ | |||
} | |||
if (netj->playback_channels_midi != first_packet->playback_channels_midi) { | |||
jack_info ("AutoConfig Override: playback_channels_midi = %d", first_packet->playback_channels_midi); | |||
netj->playback_channels_midi = first_packet->playback_channels_midi; | |||
} | |||
@@ -739,24 +717,24 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi; | |||
if( (netj->capture_channels * netj->period_size * netj->latency * 4) > 100000000 ) { | |||
jack_error( "autoconfig requests more than 100MB packet cache... bailing out" ); | |||
exit(1); | |||
jack_error( "autoconfig requests more than 100MB packet cache... bailing out" ); | |||
exit(1); | |||
} | |||
if( netj->playback_channels > 1000 ) { | |||
jack_error( "autoconfig requests more than 1000 playback channels... bailing out" ); | |||
exit(1); | |||
jack_error( "autoconfig requests more than 1000 playback channels... bailing out" ); | |||
exit(1); | |||
} | |||
if( netj->mtu < (2*sizeof( jacknet_packet_header )) ) { | |||
jack_error( "bullshit mtu requested by autoconfig" ); | |||
exit(1); | |||
if( netj->mtu < (2 * sizeof( jacknet_packet_header )) ) { | |||
jack_error( "bullshit mtu requested by autoconfig" ); | |||
exit(1); | |||
} | |||
if( netj->sample_rate == 0 ) { | |||
jack_error( "sample_rate 0 requested by autoconfig" ); | |||
exit(1); | |||
jack_error( "sample_rate 0 requested by autoconfig" ); | |||
exit(1); | |||
} | |||
// After possible Autoconfig: do all calculations... | |||
@@ -765,15 +743,15 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
* 1000000.0f); | |||
if( netj->latency == 0 ) | |||
netj->deadline_offset = 50*netj->period_usecs; | |||
netj->deadline_offset = 50 * netj->period_usecs; | |||
else | |||
netj->deadline_offset = netj->period_usecs + 10*netj->latency*netj->period_usecs/100; | |||
netj->deadline_offset = netj->period_usecs + 10 * netj->latency * netj->period_usecs / 100; | |||
if( netj->bitdepth == CELT_MODE ) { | |||
// celt mode. | |||
// TODO: this is a hack. But i dont want to change the packet header. | |||
netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); | |||
netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8)&(~1); | |||
netj->resample_factor = (netj->resample_factor * netj->period_size * 1024 / netj->sample_rate / 8) & (~1); | |||
netj->resample_factor_up = (netj->resample_factor_up * netj->period_size * 1024 / netj->sample_rate / 8) & (~1); | |||
netj->net_period_down = netj->resample_factor; | |||
netj->net_period_up = netj->resample_factor_up; | |||
@@ -795,7 +773,7 @@ netjack_startup( netjack_driver_state_t *netj ) | |||
if( netj->latency == 0 ) | |||
netj->resync_threshold = 0; | |||
else | |||
netj->resync_threshold = MIN( 15, netj->latency-1 ); | |||
netj->resync_threshold = MIN( 15, netj->latency - 1 ); | |||
netj->running_free = 0; | |||
@@ -37,113 +37,113 @@ extern "C" | |||
{ | |||
#endif | |||
struct _packet_cache; | |||
struct _packet_cache; | |||
typedef struct _netjack_driver_state netjack_driver_state_t; | |||
typedef struct _netjack_driver_state netjack_driver_state_t; | |||
struct _netjack_driver_state { | |||
jack_nframes_t net_period_up; | |||
jack_nframes_t net_period_down; | |||
struct _netjack_driver_state { | |||
jack_nframes_t net_period_up; | |||
jack_nframes_t net_period_down; | |||
jack_nframes_t sample_rate; | |||
jack_nframes_t bitdepth; | |||
jack_nframes_t period_size; | |||
jack_time_t period_usecs; | |||
int dont_htonl_floats; | |||
int always_deadline; | |||
jack_nframes_t sample_rate; | |||
jack_nframes_t bitdepth; | |||
jack_nframes_t period_size; | |||
jack_time_t period_usecs; | |||
int dont_htonl_floats; | |||
int always_deadline; | |||
jack_nframes_t codec_latency; | |||
jack_nframes_t codec_latency; | |||
unsigned int listen_port; | |||
unsigned int listen_port; | |||
unsigned int capture_channels; | |||
unsigned int playback_channels; | |||
unsigned int capture_channels_audio; | |||
unsigned int playback_channels_audio; | |||
unsigned int capture_channels_midi; | |||
unsigned int playback_channels_midi; | |||
unsigned int capture_channels; | |||
unsigned int playback_channels; | |||
unsigned int capture_channels_audio; | |||
unsigned int playback_channels_audio; | |||
unsigned int capture_channels_midi; | |||
unsigned int playback_channels_midi; | |||
JSList *capture_ports; | |||
JSList *playback_ports; | |||
JSList *playback_srcs; | |||
JSList *capture_srcs; | |||
JSList *capture_ports; | |||
JSList *playback_ports; | |||
JSList *playback_srcs; | |||
JSList *capture_srcs; | |||
jack_client_t *client; | |||
jack_client_t *client; | |||
#ifdef WIN32 | |||
SOCKET sockfd; | |||
SOCKET outsockfd; | |||
SOCKET sockfd; | |||
SOCKET outsockfd; | |||
#else | |||
int sockfd; | |||
int outsockfd; | |||
int sockfd; | |||
int outsockfd; | |||
#endif | |||
struct sockaddr_in syncsource_address; | |||
int reply_port; | |||
int srcaddress_valid; | |||
int sync_state; | |||
unsigned int handle_transport_sync; | |||
unsigned int *rx_buf; | |||
unsigned int rx_bufsize; | |||
//unsigned int tx_bufsize; | |||
unsigned int mtu; | |||
unsigned int latency; | |||
unsigned int redundancy; | |||
jack_nframes_t expected_framecnt; | |||
int expected_framecnt_valid; | |||
unsigned int num_lost_packets; | |||
jack_time_t next_deadline; | |||
jack_time_t deadline_offset; | |||
int next_deadline_valid; | |||
int packet_data_valid; | |||
int resync_threshold; | |||
int running_free; | |||
int deadline_goodness; | |||
jack_time_t time_to_deadline; | |||
unsigned int use_autoconfig; | |||
unsigned int resample_factor; | |||
unsigned int resample_factor_up; | |||
int jitter_val; | |||
struct _packet_cache * packcache; | |||
struct sockaddr_in syncsource_address; | |||
int reply_port; | |||
int srcaddress_valid; | |||
int sync_state; | |||
unsigned int handle_transport_sync; | |||
unsigned int *rx_buf; | |||
unsigned int rx_bufsize; | |||
//unsigned int tx_bufsize; | |||
unsigned int mtu; | |||
unsigned int latency; | |||
unsigned int redundancy; | |||
jack_nframes_t expected_framecnt; | |||
int expected_framecnt_valid; | |||
unsigned int num_lost_packets; | |||
jack_time_t next_deadline; | |||
jack_time_t deadline_offset; | |||
int next_deadline_valid; | |||
int packet_data_valid; | |||
int resync_threshold; | |||
int running_free; | |||
int deadline_goodness; | |||
jack_time_t time_to_deadline; | |||
unsigned int use_autoconfig; | |||
unsigned int resample_factor; | |||
unsigned int resample_factor_up; | |||
int jitter_val; | |||
struct _packet_cache * packcache; | |||
#if HAVE_CELT | |||
CELTMode *celt_mode; | |||
CELTMode *celt_mode; | |||
#endif | |||
}; | |||
int netjack_wait( netjack_driver_state_t *netj ); | |||
void netjack_send_silence( netjack_driver_state_t *netj, int syncstate ); | |||
void netjack_read( netjack_driver_state_t *netj, jack_nframes_t nframes ) ; | |||
void netjack_write( netjack_driver_state_t *netj, jack_nframes_t nframes, int syncstate ); | |||
void netjack_attach( netjack_driver_state_t *netj ); | |||
void netjack_detach( netjack_driver_state_t *netj ); | |||
netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | |||
jack_client_t * client, | |||
const char *name, | |||
unsigned int capture_ports, | |||
unsigned int playback_ports, | |||
unsigned int capture_ports_midi, | |||
unsigned int playback_ports_midi, | |||
jack_nframes_t sample_rate, | |||
jack_nframes_t period_size, | |||
unsigned int listen_port, | |||
unsigned int transport_sync, | |||
unsigned int resample_factor, | |||
unsigned int resample_factor_up, | |||
unsigned int bitdepth, | |||
unsigned int use_autoconfig, | |||
unsigned int latency, | |||
unsigned int redundancy, | |||
int dont_htonl_floats, | |||
int always_deadline, | |||
int jitter_val ); | |||
void netjack_release( netjack_driver_state_t *netj ); | |||
int netjack_startup( netjack_driver_state_t *netj ); | |||
}; | |||
int netjack_wait( netjack_driver_state_t *netj ); | |||
void netjack_send_silence( netjack_driver_state_t *netj, int syncstate ); | |||
void netjack_read( netjack_driver_state_t *netj, jack_nframes_t nframes ) ; | |||
void netjack_write( netjack_driver_state_t *netj, jack_nframes_t nframes, int syncstate ); | |||
void netjack_attach( netjack_driver_state_t *netj ); | |||
void netjack_detach( netjack_driver_state_t *netj ); | |||
netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | |||
jack_client_t * client, | |||
const char *name, | |||
unsigned int capture_ports, | |||
unsigned int playback_ports, | |||
unsigned int capture_ports_midi, | |||
unsigned int playback_ports_midi, | |||
jack_nframes_t sample_rate, | |||
jack_nframes_t period_size, | |||
unsigned int listen_port, | |||
unsigned int transport_sync, | |||
unsigned int resample_factor, | |||
unsigned int resample_factor_up, | |||
unsigned int bitdepth, | |||
unsigned int use_autoconfig, | |||
unsigned int latency, | |||
unsigned int redundancy, | |||
int dont_htonl_floats, | |||
int always_deadline, | |||
int jitter_val ); | |||
void netjack_release( netjack_driver_state_t *netj ); | |||
int netjack_startup( netjack_driver_state_t *netj ); | |||
#ifdef __cplusplus | |||
} | |||
@@ -152,13 +152,12 @@ packet_cache | |||
int i, fragment_number; | |||
if( pkt_size == sizeof(jacknet_packet_header) ) | |||
fragment_number = 1; | |||
fragment_number = 1; | |||
else | |||
fragment_number = (pkt_size - sizeof (jacknet_packet_header) - 1) / fragment_payload_size + 1; | |||
fragment_number = (pkt_size - sizeof (jacknet_packet_header) - 1) / fragment_payload_size + 1; | |||
packet_cache *pcache = malloc (sizeof (packet_cache)); | |||
if (pcache == NULL) | |||
{ | |||
if (pcache == NULL) { | |||
jack_error ("could not allocate packet cache (1)"); | |||
return NULL; | |||
} | |||
@@ -169,14 +168,12 @@ packet_cache | |||
pcache->last_framecnt_retreived = 0; | |||
pcache->last_framecnt_retreived_valid = 0; | |||
if (pcache->packets == NULL) | |||
{ | |||
if (pcache->packets == NULL) { | |||
jack_error ("could not allocate packet cache (2)"); | |||
return NULL; | |||
} | |||
for (i = 0; i < num_packets; i++) | |||
{ | |||
for (i = 0; i < num_packets; i++) { | |||
pcache->packets[i].valid = 0; | |||
pcache->packets[i].num_fragments = fragment_number; | |||
pcache->packets[i].packet_size = pkt_size; | |||
@@ -184,8 +181,7 @@ packet_cache | |||
pcache->packets[i].framecnt = 0; | |||
pcache->packets[i].fragment_array = malloc (sizeof (char) * fragment_number); | |||
pcache->packets[i].packet_buf = malloc (pkt_size); | |||
if ((pcache->packets[i].fragment_array == NULL) || (pcache->packets[i].packet_buf == NULL)) | |||
{ | |||
if ((pcache->packets[i].fragment_array == NULL) || (pcache->packets[i].packet_buf == NULL)) { | |||
jack_error ("could not allocate packet cache (3)"); | |||
return NULL; | |||
} | |||
@@ -200,10 +196,9 @@ packet_cache_free (packet_cache *pcache) | |||
{ | |||
int i; | |||
if( pcache == NULL ) | |||
return; | |||
return; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
free (pcache->packets[i].fragment_array); | |||
free (pcache->packets[i].packet_buf); | |||
} | |||
@@ -218,8 +213,7 @@ cache_packet | |||
int i; | |||
cache_packet *retval; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) | |||
return &(pcache->packets[i]); | |||
} | |||
@@ -228,8 +222,7 @@ cache_packet | |||
// find a free packet. | |||
retval = packet_cache_get_free_packet (pcache); | |||
if (retval != NULL) | |||
{ | |||
if (retval != NULL) { | |||
cache_packet_set_framecnt (retval, framecnt); | |||
return retval; | |||
} | |||
@@ -257,10 +250,8 @@ cache_packet | |||
cache_packet *retval = &(pcache->packets[0]); | |||
int i; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt < minimal_frame)) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt < minimal_frame)) { | |||
minimal_frame = pcache->packets[i].framecnt; | |||
retval = &(pcache->packets[i]); | |||
} | |||
@@ -274,8 +265,7 @@ cache_packet | |||
{ | |||
int i; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
if (pcache->packets[i].valid == 0) | |||
return &(pcache->packets[i]); | |||
} | |||
@@ -320,28 +310,23 @@ cache_packet_add_fragment (cache_packet *pack, char *packet_buf, int rcv_len) | |||
jack_nframes_t fragment_nr = ntohl (pkthdr->fragment_nr); | |||
jack_nframes_t framecnt = ntohl (pkthdr->framecnt); | |||
if (framecnt != pack->framecnt) | |||
{ | |||
if (framecnt != pack->framecnt) { | |||
jack_error ("errror. framecnts dont match"); | |||
return; | |||
} | |||
if (fragment_nr == 0) | |||
{ | |||
if (fragment_nr == 0) { | |||
memcpy (pack->packet_buf, packet_buf, rcv_len); | |||
pack->fragment_array[0] = 1; | |||
return; | |||
} | |||
if ((fragment_nr < pack->num_fragments) && (fragment_nr > 0)) | |||
{ | |||
if ((fragment_nr * fragment_payload_size + rcv_len - sizeof (jacknet_packet_header)) <= (pack->packet_size - sizeof (jacknet_packet_header))) | |||
{ | |||
if ((fragment_nr < pack->num_fragments) && (fragment_nr > 0)) { | |||
if ((fragment_nr * fragment_payload_size + rcv_len - sizeof (jacknet_packet_header)) <= (pack->packet_size - sizeof (jacknet_packet_header))) { | |||
memcpy (packet_bufX + fragment_nr * fragment_payload_size, dataX, rcv_len - sizeof (jacknet_packet_header)); | |||
pack->fragment_array[fragment_nr] = 1; | |||
} | |||
else | |||
} else | |||
jack_error ("too long packet received..."); | |||
} | |||
} | |||
@@ -373,11 +358,11 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||
jack_time_t now = jack_get_time(); | |||
if( now >= deadline ) | |||
return 0; | |||
return 0; | |||
if( (deadline-now) >= 1000000 ) { | |||
jack_error( "deadline more than 1 second in the future, trimming it." ); | |||
deadline = now+500000; | |||
if( (deadline - now) >= 1000000 ) { | |||
jack_error( "deadline more than 1 second in the future, trimming it." ); | |||
deadline = now + 500000; | |||
} | |||
#if HAVE_PPOLL | |||
timeout_spec.tv_nsec = (deadline - now) * 1000; | |||
@@ -394,25 +379,23 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||
poll_err = poll (&fds, 1, timeout); | |||
#endif | |||
if (poll_err == -1) | |||
{ | |||
switch (errno) | |||
{ | |||
if (poll_err == -1) { | |||
switch (errno) { | |||
case EBADF: | |||
jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno); | |||
break; | |||
jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno); | |||
break; | |||
case EFAULT: | |||
jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno); | |||
break; | |||
jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno); | |||
break; | |||
case EINTR: | |||
jack_error ("Error %d: A signal occurred before any requested event", errno); | |||
break; | |||
jack_error ("Error %d: A signal occurred before any requested event", errno); | |||
break; | |||
case EINVAL: | |||
jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno); | |||
break; | |||
jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno); | |||
break; | |||
case ENOMEM: | |||
jack_error ("Error %d: There was no space to allocate file descriptor tables", errno); | |||
break; | |||
jack_error ("Error %d: There was no space to allocate file descriptor tables", errno); | |||
break; | |||
} | |||
} | |||
return poll_err; | |||
@@ -427,17 +410,17 @@ netjack_poll (int sockfd, int timeout) | |||
struct sigaction action; | |||
sigemptyset(&sigmask); | |||
sigaddset(&sigmask, SIGHUP); | |||
sigaddset(&sigmask, SIGINT); | |||
sigaddset(&sigmask, SIGQUIT); | |||
sigaddset(&sigmask, SIGPIPE); | |||
sigaddset(&sigmask, SIGTERM); | |||
sigaddset(&sigmask, SIGUSR1); | |||
sigaddset(&sigmask, SIGUSR2); | |||
action.sa_handler = SIG_DFL; | |||
action.sa_mask = sigmask; | |||
action.sa_flags = SA_RESTART; | |||
sigaddset(&sigmask, SIGHUP); | |||
sigaddset(&sigmask, SIGINT); | |||
sigaddset(&sigmask, SIGQUIT); | |||
sigaddset(&sigmask, SIGPIPE); | |||
sigaddset(&sigmask, SIGTERM); | |||
sigaddset(&sigmask, SIGUSR1); | |||
sigaddset(&sigmask, SIGUSR2); | |||
action.sa_handler = SIG_DFL; | |||
action.sa_mask = sigmask; | |||
action.sa_flags = SA_RESTART; | |||
for (i = 1; i < NSIG; i++) | |||
if (sigismember (&sigmask, i)) | |||
@@ -447,31 +430,28 @@ netjack_poll (int sockfd, int timeout) | |||
fds.events = POLLIN; | |||
sigprocmask(SIG_UNBLOCK, &sigmask, &rsigmask); | |||
while (poll_err == 0) | |||
{ | |||
while (poll_err == 0) { | |||
poll_err = poll (&fds, 1, timeout); | |||
} | |||
sigprocmask(SIG_SETMASK, &rsigmask, NULL); | |||
if (poll_err == -1) | |||
{ | |||
switch (errno) | |||
{ | |||
if (poll_err == -1) { | |||
switch (errno) { | |||
case EBADF: | |||
jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno); | |||
break; | |||
jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno); | |||
break; | |||
case EFAULT: | |||
jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno); | |||
break; | |||
jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno); | |||
break; | |||
case EINTR: | |||
jack_error ("Error %d: A signal occurred before any requested event", errno); | |||
break; | |||
jack_error ("Error %d: A signal occurred before any requested event", errno); | |||
break; | |||
case EINVAL: | |||
jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno); | |||
break; | |||
jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno); | |||
break; | |||
case ENOMEM: | |||
jack_error ("Error %d: There was no space to allocate file descriptor tables", errno); | |||
break; | |||
jack_error ("Error %d: There was no space to allocate file descriptor tables", errno); | |||
break; | |||
} | |||
return 0; | |||
} | |||
@@ -496,10 +476,10 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||
while( 1 ) { | |||
jack_time_t now = jack_get_time(); | |||
if( now >= deadline ) | |||
return 0; | |||
return 0; | |||
int timeout_usecs = (deadline - now); | |||
//jack_error( "timeout = %d", timeout_usecs ); | |||
//jack_error( "timeout = %d", timeout_usecs ); | |||
timeout.tv_sec = 0; | |||
timeout.tv_usec = (timeout_usecs < 500) ? 500 : timeout_usecs; | |||
timeout.tv_usec = (timeout_usecs > 1000000) ? 500000 : timeout_usecs; | |||
@@ -531,36 +511,35 @@ packet_cache_drain_socket( packet_cache *pcache, int sockfd ) | |||
#else | |||
socklen_t senderlen = sizeof( struct sockaddr_in ); | |||
#endif | |||
while (1) | |||
{ | |||
while (1) { | |||
#ifdef WIN32 | |||
rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, 0, | |||
(struct sockaddr*) &sender_address, &senderlen); | |||
(struct sockaddr*) &sender_address, &senderlen); | |||
#else | |||
rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, MSG_DONTWAIT, | |||
(struct sockaddr*) &sender_address, &senderlen); | |||
(struct sockaddr*) &sender_address, &senderlen); | |||
#endif | |||
if (rcv_len < 0) | |||
return; | |||
if (pcache->master_address_valid) { | |||
// Verify its from our master. | |||
if (memcmp (&sender_address, &(pcache->master_address), senderlen) != 0) | |||
continue; | |||
} else { | |||
// Setup this one as master | |||
//printf( "setup master...\n" ); | |||
memcpy ( &(pcache->master_address), &sender_address, senderlen ); | |||
pcache->master_address_valid = 1; | |||
} | |||
if (pcache->master_address_valid) { | |||
// Verify its from our master. | |||
if (memcmp (&sender_address, &(pcache->master_address), senderlen) != 0) | |||
continue; | |||
} else { | |||
// Setup this one as master | |||
//printf( "setup master...\n" ); | |||
memcpy ( &(pcache->master_address), &sender_address, senderlen ); | |||
pcache->master_address_valid = 1; | |||
} | |||
framecnt = ntohl (pkthdr->framecnt); | |||
if( pcache->last_framecnt_retreived_valid && (framecnt <= pcache->last_framecnt_retreived )) | |||
continue; | |||
if( pcache->last_framecnt_retreived_valid && (framecnt <= pcache->last_framecnt_retreived )) | |||
continue; | |||
cpack = packet_cache_get_packet (pcache, framecnt); | |||
cache_packet_add_fragment (cpack, rx_packet, rcv_len); | |||
cpack->recv_timestamp = jack_get_time(); | |||
cpack->recv_timestamp = jack_get_time(); | |||
} | |||
} | |||
@@ -577,10 +556,8 @@ packet_cache_clear_old_packets (packet_cache *pcache, jack_nframes_t framecnt ) | |||
{ | |||
int i; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt < framecnt)) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
if (pcache->packets[i].valid && (pcache->packets[i].framecnt < framecnt)) { | |||
cache_packet_reset (&(pcache->packets[i])); | |||
} | |||
} | |||
@@ -654,8 +631,7 @@ packet_cache_get_fill( packet_cache *pcache, jack_nframes_t expected_framecnt ) | |||
int num_packets_before_us = 0; | |||
int i; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
cache_packet *cpack = &(pcache->packets[i]); | |||
if (cpack->valid && cache_packet_is_complete( cpack )) | |||
if( cpack->framecnt >= expected_framecnt ) | |||
@@ -670,11 +646,10 @@ int | |||
packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ) | |||
{ | |||
int i; | |||
jack_nframes_t best_offset = JACK_MAX_FRAMES/2-1; | |||
jack_nframes_t best_offset = JACK_MAX_FRAMES / 2 - 1; | |||
int retval = 0; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
cache_packet *cpack = &(pcache->packets[i]); | |||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||
@@ -688,13 +663,13 @@ packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t e | |||
if( (cpack->framecnt - expected_framecnt) > best_offset ) { | |||
continue; | |||
} | |||
} | |||
best_offset = cpack->framecnt - expected_framecnt; | |||
retval = 1; | |||
best_offset = cpack->framecnt - expected_framecnt; | |||
retval = 1; | |||
if (best_offset == 0) | |||
break; | |||
if (best_offset == 0) | |||
break; | |||
} | |||
if (retval && framecnt) | |||
*framecnt = expected_framecnt + best_offset; | |||
@@ -709,22 +684,21 @@ packet_cache_get_highest_available_framecnt( packet_cache *pcache, jack_nframes_ | |||
jack_nframes_t best_value = 0; | |||
int retval = 0; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
cache_packet *cpack = &(pcache->packets[i]); | |||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | |||
//printf( "invalid\n" ); | |||
continue; | |||
} | |||
} | |||
if (cpack->framecnt < best_value) { | |||
continue; | |||
} | |||
if (cpack->framecnt < best_value) { | |||
continue; | |||
} | |||
best_value = cpack->framecnt; | |||
retval = 1; | |||
best_value = cpack->framecnt; | |||
retval = 1; | |||
} | |||
if (retval && framecnt) | |||
@@ -741,25 +715,24 @@ packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecn | |||
jack_nframes_t best_offset = 0; | |||
int retval = 0; | |||
for (i = 0; i < pcache->size; i++) | |||
{ | |||
for (i = 0; i < pcache->size; i++) { | |||
cache_packet *cpack = &(pcache->packets[i]); | |||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | |||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | |||
//printf( "invalid\n" ); | |||
continue; | |||
} | |||
} | |||
if ((cpack->framecnt - expected_framecnt) < best_offset) { | |||
continue; | |||
} | |||
if ((cpack->framecnt - expected_framecnt) < best_offset) { | |||
continue; | |||
} | |||
best_offset = cpack->framecnt - expected_framecnt; | |||
retval = 1; | |||
best_offset = cpack->framecnt - expected_framecnt; | |||
retval = 1; | |||
if( best_offset == 0 ) | |||
break; | |||
if( best_offset == 0 ) | |||
break; | |||
} | |||
if (retval && framecnt) | |||
*framecnt = JACK_MAX_FRAMES - best_offset; | |||
@@ -785,13 +758,11 @@ netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct so | |||
pkthdr = (jacknet_packet_header *) packet_buf; | |||
pkthdr->fragment_nr = htonl (0); | |||
err = sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size); | |||
if( err<0 ) { | |||
if( err < 0 ) { | |||
//printf( "error in send\n" ); | |||
perror( "send" ); | |||
} | |||
} | |||
else | |||
{ | |||
} else { | |||
int err; | |||
// Copy the packet header to the tx pack first. | |||
memcpy(tx_packet, packet_buf, sizeof (jacknet_packet_header)); | |||
@@ -799,8 +770,7 @@ netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct so | |||
// Now loop and send all | |||
char *packet_bufX = packet_buf + sizeof (jacknet_packet_header); | |||
while (packet_bufX < (packet_buf + pkt_size - fragment_payload_size)) | |||
{ | |||
while (packet_bufX < (packet_buf + pkt_size - fragment_payload_size)) { | |||
pkthdr->fragment_nr = htonl (frag_cnt++); | |||
memcpy (dataX, packet_bufX, fragment_payload_size); | |||
sendto (sockfd, tx_packet, mtu, flags, addr, addr_size); | |||
@@ -814,7 +784,7 @@ netjack_sendto (int sockfd, char *packet_buf, int pkt_size, int flags, struct so | |||
// sendto(last_pack_size); | |||
err = sendto(sockfd, tx_packet, last_payload_size + sizeof(jacknet_packet_header), flags, addr, addr_size); | |||
if( err<0 ) { | |||
if( err < 0 ) { | |||
//printf( "error in send\n" ); | |||
perror( "send" ); | |||
} | |||
@@ -826,24 +796,21 @@ decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, ja | |||
{ | |||
int i; | |||
jack_midi_clear_buffer (buf); | |||
for (i = 0; i < buffer_size_uint32 - 3;) | |||
{ | |||
for (i = 0; i < buffer_size_uint32 - 3;) { | |||
uint32_t payload_size; | |||
payload_size = buffer_uint32[i]; | |||
payload_size = ntohl (payload_size); | |||
if (payload_size) | |||
{ | |||
if (payload_size) { | |||
jack_midi_event_t event; | |||
event.time = ntohl (buffer_uint32[i+1]); | |||
event.size = ntohl (buffer_uint32[i+2]); | |||
event.buffer = (jack_midi_data_t*) (&(buffer_uint32[i+3])); | |||
event.time = ntohl (buffer_uint32[i + 1]); | |||
event.size = ntohl (buffer_uint32[i + 2]); | |||
event.buffer = (jack_midi_data_t*) (&(buffer_uint32[i + 3])); | |||
jack_midi_event_write (buf, event.time, event.buffer, event.size); | |||
// skip to the next event | |||
unsigned int nb_data_quads = (((event.size-1) & ~0x3) >> 2)+1; | |||
i += 3+nb_data_quads; | |||
} | |||
else | |||
unsigned int nb_data_quads = (((event.size - 1) & ~0x3) >> 2) + 1; | |||
i += 3 + nb_data_quads; | |||
} else | |||
break; // no events can follow an empty event, we're done | |||
} | |||
} | |||
@@ -855,38 +822,34 @@ encode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, ja | |||
unsigned int written = 0; | |||
// midi port, encode midi events | |||
unsigned int nevents = jack_midi_get_event_count (buf); | |||
for (i = 0; i < nevents; ++i) | |||
{ | |||
for (i = 0; i < nevents; ++i) { | |||
jack_midi_event_t event; | |||
jack_midi_event_get (&event, buf, i); | |||
unsigned int nb_data_quads = (((event.size - 1) & ~0x3) >> 2) + 1; | |||
unsigned int payload_size = 3 + nb_data_quads; | |||
// only write if we have sufficient space for the event | |||
// otherwise drop it | |||
if (written + payload_size < buffer_size_uint32 - 1) | |||
{ | |||
if (written + payload_size < buffer_size_uint32 - 1) { | |||
// write header | |||
buffer_uint32[written]=htonl (payload_size); | |||
buffer_uint32[written] = htonl (payload_size); | |||
written++; | |||
buffer_uint32[written]=htonl (event.time); | |||
buffer_uint32[written] = htonl (event.time); | |||
written++; | |||
buffer_uint32[written]=htonl (event.size); | |||
buffer_uint32[written] = htonl (event.size); | |||
written++; | |||
// write data | |||
jack_midi_data_t* tmpbuff = (jack_midi_data_t*)(&(buffer_uint32[written])); | |||
memcpy (tmpbuff, event.buffer, event.size); | |||
written += nb_data_quads; | |||
} | |||
else | |||
{ | |||
} else { | |||
// buffer overflow | |||
jack_error ("midi buffer overflow"); | |||
break; | |||
} | |||
} | |||
// now put a netjack_midi 'no-payload' event, signaling EOF | |||
buffer_uint32[written]=0; | |||
buffer_uint32[written] = 0; | |||
} | |||
// render functions for float | |||
@@ -904,8 +867,7 @@ render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_pe | |||
if (!packet_payload) | |||
return; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
int i; | |||
int_float_t val; | |||
#if HAVE_SAMPLERATE | |||
@@ -917,15 +879,12 @@ render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_pe | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
#if HAVE_SAMPLERATE | |||
// audio port, resample if necessary | |||
if (net_period_down != nframes) | |||
{ | |||
if (net_period_down != nframes) { | |||
SRC_STATE *src_state = src_node->data; | |||
for (i = 0; i < net_period_down; i++) | |||
{ | |||
for (i = 0; i < net_period_down; i++) { | |||
packet_bufX[i] = ntohl (packet_bufX[i]); | |||
} | |||
@@ -941,27 +900,20 @@ render_payload_to_jack_ports_float ( void *packet_payload, jack_nframes_t net_pe | |||
src_set_ratio (src_state, src.src_ratio); | |||
src_process (src_state, &src); | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else | |||
} 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; | |||
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 (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// midi port, decode midi events | |||
// convert the data buffer to a standard format (uint32_t based) | |||
unsigned int buffer_size_uint32 = net_period_down; | |||
@@ -985,8 +937,7 @@ render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_src | |||
uint32_t *packet_bufX = (uint32_t *) packet_payload; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
#if HAVE_SAMPLERATE | |||
SRC_DATA src; | |||
#endif | |||
@@ -997,8 +948,7 @@ render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_src | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, resample if necessary | |||
#if HAVE_SAMPLERATE | |||
@@ -1016,32 +966,24 @@ render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_src | |||
src_set_ratio (src_state, src.src_ratio); | |||
src_process (src_state, &src); | |||
for (i = 0; i < net_period_up; i++) | |||
{ | |||
for (i = 0; i < net_period_up; i++) { | |||
packet_bufX[i] = htonl (packet_bufX[i]); | |||
} | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else | |||
} 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; | |||
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 (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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; | |||
@@ -1067,10 +1009,9 @@ render_payload_to_jack_ports_16bit (void *packet_payload, jack_nframes_t net_per | |||
uint16_t *packet_bufX = (uint16_t *)packet_payload; | |||
if( !packet_payload ) | |||
return; | |||
return; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
int i; | |||
//uint32_t val; | |||
#if HAVE_SAMPLERATE | |||
@@ -1085,16 +1026,13 @@ render_payload_to_jack_ports_16bit (void *packet_payload, jack_nframes_t net_per | |||
#endif | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, resample if necessary | |||
#if HAVE_SAMPLERATE | |||
if (net_period_down != nframes) | |||
{ | |||
if (net_period_down != nframes) { | |||
SRC_STATE *src_state = src_node->data; | |||
for (i = 0; i < net_period_down; i++) | |||
{ | |||
for (i = 0; i < net_period_down; i++) { | |||
floatbuf[i] = ((float) ntohs(packet_bufX[i])) / 32767.0 - 1.0; | |||
} | |||
@@ -1110,14 +1048,11 @@ render_payload_to_jack_ports_16bit (void *packet_payload, jack_nframes_t net_per | |||
src_set_ratio (src_state, src.src_ratio); | |||
src_process (src_state, &src); | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else | |||
} else | |||
#endif | |||
for (i = 0; i < net_period_down; i++) | |||
buf[i] = ((float) ntohs (packet_bufX[i])) / 32768.0 - 1.0; | |||
} | |||
else if (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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; | |||
@@ -1141,8 +1076,7 @@ render_jack_ports_to_payload_16bit (JSList *playback_ports, JSList *playback_src | |||
uint16_t *packet_bufX = (uint16_t *)packet_payload; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
#if HAVE_SAMPLERATE | |||
SRC_DATA src; | |||
#endif | |||
@@ -1151,13 +1085,11 @@ render_jack_ports_to_payload_16bit (JSList *playback_ports, JSList *playback_src | |||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, resample if necessary | |||
#if HAVE_SAMPLERATE | |||
if (net_period_up != nframes) | |||
{ | |||
if (net_period_up != nframes) { | |||
SRC_STATE *src_state = src_node->data; | |||
float *floatbuf = alloca (sizeof(float) * net_period_up); | |||
@@ -1174,19 +1106,15 @@ render_jack_ports_to_payload_16bit (JSList *playback_ports, JSList *playback_src | |||
src_set_ratio (src_state, src.src_ratio); | |||
src_process (src_state, &src); | |||
for (i = 0; i < net_period_up; i++) | |||
{ | |||
for (i = 0; i < net_period_up; i++) { | |||
packet_bufX[i] = htons (((uint16_t)((floatbuf[i] + 1.0) * 32767.0))); | |||
} | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else | |||
} else | |||
#endif | |||
for (i = 0; i < net_period_up; i++) | |||
packet_bufX[i] = htons(((uint16_t)((buf[i] + 1.0) * 32767.0))); | |||
} | |||
else if (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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; | |||
@@ -1215,8 +1143,7 @@ render_payload_to_jack_ports_8bit (void *packet_payload, jack_nframes_t net_peri | |||
if (!packet_payload) | |||
return; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
int i; | |||
//uint32_t val; | |||
#if HAVE_SAMPLERATE | |||
@@ -1231,12 +1158,10 @@ render_payload_to_jack_ports_8bit (void *packet_payload, jack_nframes_t net_peri | |||
#endif | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio(porttype)) | |||
{ | |||
if (jack_port_is_audio(porttype)) { | |||
#if HAVE_SAMPLERATE | |||
// audio port, resample if necessary | |||
if (net_period_down != nframes) | |||
{ | |||
if (net_period_down != nframes) { | |||
SRC_STATE *src_state = src_node->data; | |||
for (i = 0; i < net_period_down; i++) | |||
floatbuf[i] = ((float) packet_bufX[i]) / 127.0; | |||
@@ -1253,14 +1178,11 @@ render_payload_to_jack_ports_8bit (void *packet_payload, jack_nframes_t net_peri | |||
src_set_ratio (src_state, src.src_ratio); | |||
src_process (src_state, &src); | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else | |||
} else | |||
#endif | |||
for (i = 0; i < net_period_down; i++) | |||
buf[i] = ((float) packet_bufX[i]) / 127.0; | |||
} | |||
else if (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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; | |||
@@ -1284,8 +1206,7 @@ render_jack_ports_to_payload_8bit (JSList *playback_ports, JSList *playback_srcs | |||
int8_t *packet_bufX = (int8_t *)packet_payload; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
#if HAVE_SAMPLERATE | |||
SRC_DATA src; | |||
#endif | |||
@@ -1295,12 +1216,10 @@ render_jack_ports_to_payload_8bit (JSList *playback_ports, JSList *playback_srcs | |||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
#if HAVE_SAMPLERATE | |||
// audio port, resample if necessary | |||
if (net_period_up != nframes) | |||
{ | |||
if (net_period_up != nframes) { | |||
SRC_STATE *src_state = src_node->data; | |||
@@ -1321,14 +1240,11 @@ render_jack_ports_to_payload_8bit (JSList *playback_ports, JSList *playback_srcs | |||
for (i = 0; i < net_period_up; i++) | |||
packet_bufX[i] = floatbuf[i] * 127.0; | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else | |||
} else | |||
#endif | |||
for (i = 0; i < net_period_up; i++) | |||
packet_bufX[i] = buf[i] * 127.0; | |||
} | |||
else if (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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 / 4; | |||
@@ -1352,33 +1268,29 @@ render_payload_to_jack_ports_celt (void *packet_payload, jack_nframes_t net_peri | |||
unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
jack_port_t *port = (jack_port_t *) node->data; | |||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, decode celt data. | |||
CELTDecoder *decoder = src_node->data; | |||
#if HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | |||
#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 | |||
#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 | |||
#endif | |||
src_node = jack_slist_next (src_node); | |||
} | |||
else if (jack_port_is_midi (porttype)) | |||
{ | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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; | |||
@@ -1401,31 +1313,27 @@ render_jack_ports_to_payload_celt (JSList *playback_ports, JSList *playback_srcs | |||
unsigned char *packet_bufX = (unsigned char *)packet_payload; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
jack_port_t *port = (jack_port_t *) node->data; | |||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | |||
const char *porttype = jack_port_type (port); | |||
if (jack_port_is_audio (porttype)) | |||
{ | |||
if (jack_port_is_audio (porttype)) { | |||
// audio port, encode celt data. | |||
int encoded_bytes; | |||
float *floatbuf = alloca (sizeof(float) * nframes ); | |||
memcpy( floatbuf, buf, nframes*sizeof(float) ); | |||
CELTEncoder *encoder = src_node->data; | |||
int encoded_bytes; | |||
float *floatbuf = alloca (sizeof(float) * nframes ); | |||
memcpy( floatbuf, buf, nframes * sizeof(float) ); | |||
CELTEncoder *encoder = 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 ); | |||
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 ); | |||
encoded_bytes = celt_encode_float( encoder, floatbuf, NULL, packet_bufX, net_period_up ); | |||
#endif | |||
if( encoded_bytes != net_period_up ) | |||
printf( "something in celt changed. netjack needs to be changed to handle this.\n" ); | |||
src_node = jack_slist_next( src_node ); | |||
} | |||
else if (jack_port_is_midi (porttype)) | |||
{ | |||
if( encoded_bytes != net_period_up ) | |||
printf( "something in celt changed. netjack needs to be changed to handle this.\n" ); | |||
src_node = jack_slist_next( src_node ); | |||
} else if (jack_port_is_midi (porttype)) { | |||
// 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; | |||
@@ -28,8 +28,8 @@ | |||
#define __JACK_NET_PACKET_H__ | |||
#ifdef __cplusplus | |||
extern "C" | |||
{ | |||
extern "C" | |||
{ | |||
#endif | |||
#include <jack/jack.h> | |||
@@ -42,115 +42,106 @@ | |||
#define CELT_MODE 1000 // Magic bitdepth value that indicates CELT compression | |||
#define MASTER_FREEWHEELS 0x80000000 | |||
typedef struct _jacknet_packet_header jacknet_packet_header; | |||
struct _jacknet_packet_header | |||
{ | |||
// General AutoConf Data | |||
jack_nframes_t capture_channels_audio; | |||
jack_nframes_t playback_channels_audio; | |||
jack_nframes_t capture_channels_midi; | |||
jack_nframes_t playback_channels_midi; | |||
jack_nframes_t period_size; | |||
jack_nframes_t sample_rate; | |||
// Transport Sync | |||
jack_nframes_t sync_state; | |||
jack_nframes_t transport_frame; | |||
jack_nframes_t transport_state; | |||
// Packet loss Detection, and latency reduction | |||
jack_nframes_t framecnt; | |||
jack_nframes_t latency; | |||
jack_nframes_t reply_port; | |||
jack_nframes_t mtu; | |||
jack_nframes_t fragment_nr; | |||
}; | |||
typedef union _int_float int_float_t; | |||
union _int_float | |||
{ | |||
uint32_t i; | |||
float f; | |||
}; | |||
// fragment reorder cache. | |||
typedef struct _cache_packet cache_packet; | |||
struct _cache_packet | |||
{ | |||
int valid; | |||
int num_fragments; | |||
int packet_size; | |||
int mtu; | |||
jack_time_t recv_timestamp; | |||
jack_nframes_t framecnt; | |||
char * fragment_array; | |||
char * packet_buf; | |||
}; | |||
typedef struct _packet_cache packet_cache; | |||
struct _packet_cache | |||
{ | |||
int size; | |||
cache_packet *packets; | |||
int mtu; | |||
struct sockaddr_in master_address; | |||
int master_address_valid; | |||
jack_nframes_t last_framecnt_retreived; | |||
int last_framecnt_retreived_valid; | |||
}; | |||
// fragment cache function prototypes | |||
// XXX: Some of these are private. | |||
packet_cache *packet_cache_new(int num_packets, int pkt_size, int mtu); | |||
void packet_cache_free(packet_cache *pkt_cache); | |||
cache_packet *packet_cache_get_packet(packet_cache *pkt_cache, jack_nframes_t framecnt); | |||
cache_packet *packet_cache_get_oldest_packet(packet_cache *pkt_cache); | |||
cache_packet *packet_cache_get_free_packet(packet_cache *pkt_cache); | |||
void cache_packet_reset(cache_packet *pack); | |||
void cache_packet_set_framecnt(cache_packet *pack, jack_nframes_t framecnt); | |||
void cache_packet_add_fragment(cache_packet *pack, char *packet_buf, int rcv_len); | |||
int cache_packet_is_complete(cache_packet *pack); | |||
void packet_cache_drain_socket( packet_cache *pcache, int sockfd ); | |||
void packet_cache_reset_master_address( packet_cache *pcache ); | |||
float packet_cache_get_fill( packet_cache *pcache, jack_nframes_t expected_framecnt ); | |||
int packet_cache_retreive_packet_pointer( packet_cache *pcache, jack_nframes_t framecnt, char **packet_buf, int pkt_size, jack_time_t *timestamp ); | |||
int packet_cache_release_packet( packet_cache *pcache, jack_nframes_t framecnt ); | |||
int packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ); | |||
int packet_cache_get_highest_available_framecnt( packet_cache *pcache, jack_nframes_t *framecnt ); | |||
int packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ); | |||
// Function Prototypes | |||
int netjack_poll_deadline (int sockfd, jack_time_t deadline); | |||
void netjack_sendto(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, int addr_size, int mtu); | |||
int get_sample_size(int bitdepth); | |||
void packet_header_hton(jacknet_packet_header *pkthdr); | |||
void packet_header_ntoh(jacknet_packet_header *pkthdr); | |||
void 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 ); | |||
void 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 ); | |||
// XXX: This is sort of deprecated: | |||
// This one waits forever. an is not using ppoll | |||
int netjack_poll(int sockfd, int timeout); | |||
typedef struct _jacknet_packet_header jacknet_packet_header; | |||
struct _jacknet_packet_header { | |||
// General AutoConf Data | |||
jack_nframes_t capture_channels_audio; | |||
jack_nframes_t playback_channels_audio; | |||
jack_nframes_t capture_channels_midi; | |||
jack_nframes_t playback_channels_midi; | |||
jack_nframes_t period_size; | |||
jack_nframes_t sample_rate; | |||
// Transport Sync | |||
jack_nframes_t sync_state; | |||
jack_nframes_t transport_frame; | |||
jack_nframes_t transport_state; | |||
// Packet loss Detection, and latency reduction | |||
jack_nframes_t framecnt; | |||
jack_nframes_t latency; | |||
jack_nframes_t reply_port; | |||
jack_nframes_t mtu; | |||
jack_nframes_t fragment_nr; | |||
}; | |||
typedef union _int_float int_float_t; | |||
union _int_float { | |||
uint32_t i; | |||
float f; | |||
}; | |||
// fragment reorder cache. | |||
typedef struct _cache_packet cache_packet; | |||
struct _cache_packet { | |||
int valid; | |||
int num_fragments; | |||
int packet_size; | |||
int mtu; | |||
jack_time_t recv_timestamp; | |||
jack_nframes_t framecnt; | |||
char * fragment_array; | |||
char * packet_buf; | |||
}; | |||
typedef struct _packet_cache packet_cache; | |||
struct _packet_cache { | |||
int size; | |||
cache_packet *packets; | |||
int mtu; | |||
struct sockaddr_in master_address; | |||
int master_address_valid; | |||
jack_nframes_t last_framecnt_retreived; | |||
int last_framecnt_retreived_valid; | |||
}; | |||
// fragment cache function prototypes | |||
// XXX: Some of these are private. | |||
packet_cache *packet_cache_new(int num_packets, int pkt_size, int mtu); | |||
void packet_cache_free(packet_cache *pkt_cache); | |||
cache_packet *packet_cache_get_packet(packet_cache *pkt_cache, jack_nframes_t framecnt); | |||
cache_packet *packet_cache_get_oldest_packet(packet_cache *pkt_cache); | |||
cache_packet *packet_cache_get_free_packet(packet_cache *pkt_cache); | |||
void cache_packet_reset(cache_packet *pack); | |||
void cache_packet_set_framecnt(cache_packet *pack, jack_nframes_t framecnt); | |||
void cache_packet_add_fragment(cache_packet *pack, char *packet_buf, int rcv_len); | |||
int cache_packet_is_complete(cache_packet *pack); | |||
void packet_cache_drain_socket( packet_cache *pcache, int sockfd ); | |||
void packet_cache_reset_master_address( packet_cache *pcache ); | |||
float packet_cache_get_fill( packet_cache *pcache, jack_nframes_t expected_framecnt ); | |||
int packet_cache_retreive_packet_pointer( packet_cache *pcache, jack_nframes_t framecnt, char **packet_buf, int pkt_size, jack_time_t *timestamp ); | |||
int packet_cache_release_packet( packet_cache *pcache, jack_nframes_t framecnt ); | |||
int packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ); | |||
int packet_cache_get_highest_available_framecnt( packet_cache *pcache, jack_nframes_t *framecnt ); | |||
int packet_cache_find_latency( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ); | |||
// Function Prototypes | |||
int netjack_poll_deadline (int sockfd, jack_time_t deadline); | |||
void netjack_sendto(int sockfd, char *packet_buf, int pkt_size, int flags, struct sockaddr *addr, int addr_size, int mtu); | |||
int get_sample_size(int bitdepth); | |||
void packet_header_hton(jacknet_packet_header *pkthdr); | |||
void packet_header_ntoh(jacknet_packet_header *pkthdr); | |||
void 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 ); | |||
void 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 ); | |||
// XXX: This is sort of deprecated: | |||
// This one waits forever. an is not using ppoll | |||
int netjack_poll(int sockfd, int timeout); | |||
void decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf); | |||
void encode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf); | |||
void decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf); | |||
void encode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, jack_default_audio_sample_t* buf); | |||
#ifdef __cplusplus | |||
} | |||
} | |||
#endif | |||
#endif | |||
@@ -92,7 +92,7 @@ int state_netxruns = 0; | |||
int state_currentframe = 0; | |||
int state_recv_packet_queue_time = 0; | |||
int quit=0; | |||
int quit = 0; | |||
int outsockfd; | |||
@@ -128,43 +128,39 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||
capture_ports = NULL; | |||
/* Allocate audio capture channels */ | |||
for (chn = 0; chn < n_capture_audio; chn++) | |||
{ | |||
for (chn = 0; chn < n_capture_audio; chn++) { | |||
snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); | |||
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | |||
if (!port) | |||
{ | |||
if (!port) { | |||
printf( "jack_netsource: cannot register %s port\n", buf); | |||
break; | |||
} | |||
if (bitdepth == 1000) { | |||
#if HAVE_CELT | |||
#if HAVE_CELT_API_0_11 | |||
if (bitdepth == 1000) { | |||
#if HAVE_CELT | |||
#if HAVE_CELT_API_0_11 | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); | |||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create_custom( celt_mode, 1, NULL ) ); | |||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), jack_get_buffer_size(client), NULL ); | |||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode, 1, NULL ) ); | |||
#else | |||
#else | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate( client ), 1, jack_get_buffer_size(client), NULL ); | |||
capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); | |||
#endif | |||
#endif | |||
#endif | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||
#endif | |||
#if HAVE_SAMPLERATE | |||
capture_srcs = jack_slist_append (capture_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||
#endif | |||
} | |||
capture_ports = jack_slist_append (capture_ports, port); | |||
} | |||
/* Allocate midi capture channels */ | |||
for (chn = n_capture_audio; chn < n_capture_midi + n_capture_audio; chn++) | |||
{ | |||
for (chn = n_capture_audio; chn < n_capture_midi + n_capture_audio; chn++) { | |||
snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); | |||
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); | |||
if (!port) | |||
{ | |||
if (!port) { | |||
printf ("jack_netsource: cannot register %s port\n", buf); | |||
break; | |||
} | |||
@@ -174,43 +170,39 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||
/* Allocate audio playback channels */ | |||
port_flags = JackPortIsInput; | |||
playback_ports = NULL; | |||
for (chn = 0; chn < n_playback_audio; chn++) | |||
{ | |||
for (chn = 0; chn < n_playback_audio; chn++) { | |||
snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); | |||
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | |||
if (!port) | |||
{ | |||
if (!port) { | |||
printf ("jack_netsource: cannot register %s port\n", buf); | |||
break; | |||
} | |||
if( bitdepth == 1000 ) { | |||
#if HAVE_CELT | |||
#if HAVE_CELT_API_0_11 | |||
#if HAVE_CELT | |||
#if HAVE_CELT_API_0_11 | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); | |||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create_custom( celt_mode, 1, NULL ) ); | |||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||
#elif HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), jack_get_buffer_size(client), NULL ); | |||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode, 1, NULL ) ); | |||
#else | |||
#else | |||
CELTMode *celt_mode = celt_mode_create( jack_get_sample_rate (client), 1, jack_get_buffer_size(client), NULL ); | |||
playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); | |||
#endif | |||
#endif | |||
#endif | |||
#endif | |||
} else { | |||
#if HAVE_SAMPLERATE | |||
#if HAVE_SAMPLERATE | |||
playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); | |||
#endif | |||
#endif | |||
} | |||
playback_ports = jack_slist_append (playback_ports, port); | |||
} | |||
/* Allocate midi playback channels */ | |||
for (chn = n_playback_audio; chn < n_playback_midi + n_playback_audio; chn++) | |||
{ | |||
for (chn = n_playback_audio; chn < n_playback_midi + n_playback_audio; chn++) { | |||
snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); | |||
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); | |||
if (!port) | |||
{ | |||
if (!port) { | |||
printf ("jack_netsource: cannot register %s port\n", buf); | |||
break; | |||
} | |||
@@ -237,8 +229,7 @@ sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) | |||
retval = 0; | |||
} | |||
else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) | |||
{ | |||
else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) { | |||
retval = 0; | |||
latency_count = latency - 1; | |||
} | |||
@@ -250,10 +241,10 @@ sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) | |||
void | |||
freewheel_cb (int starting, void *arg) | |||
{ | |||
freewheeling = starting; | |||
freewheeling = starting; | |||
} | |||
int deadline_goodness=0; | |||
int deadline_goodness = 0; | |||
/** | |||
* The process callback for this JACK application. | |||
* It is called by JACK at the appropriate times. | |||
@@ -279,7 +270,7 @@ process (jack_nframes_t nframes, void *arg) | |||
jack_time_t packet_recv_timestamp; | |||
if( bitdepth == 1000 ) | |||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; | |||
else | |||
net_period = (float) nframes / (float) factor; | |||
@@ -299,47 +290,45 @@ process (jack_nframes_t nframes, void *arg) | |||
*/ | |||
if( latency == 0 ) { | |||
/* reset packet_bufX... */ | |||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||
/* ---------- Send ---------- */ | |||
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, | |||
packet_bufX, net_period, dont_htonl_floats); | |||
/* fill in packet hdr */ | |||
pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); | |||
pkthdr_tx->transport_frame = local_trans_pos.frame; | |||
pkthdr_tx->framecnt = framecnt; | |||
pkthdr_tx->latency = latency; | |||
pkthdr_tx->reply_port = reply_port; | |||
pkthdr_tx->sample_rate = jack_get_sample_rate (client); | |||
pkthdr_tx->period_size = nframes; | |||
/* playback for us is capture on the other side */ | |||
pkthdr_tx->capture_channels_audio = playback_channels_audio; | |||
pkthdr_tx->playback_channels_audio = capture_channels_audio; | |||
pkthdr_tx->capture_channels_midi = playback_channels_midi; | |||
pkthdr_tx->playback_channels_midi = capture_channels_midi; | |||
pkthdr_tx->mtu = mtu; | |||
if( freewheeling!= 0 ) | |||
pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; | |||
else | |||
pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; | |||
//printf("goodness=%d\n", deadline_goodness ); | |||
packet_header_hton (pkthdr_tx); | |||
if (cont_miss < 3*latency+5) { | |||
int r; | |||
for( r=0; r<redundancy; r++ ) | |||
netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||
} | |||
else if (cont_miss > 50+5*latency) | |||
{ | |||
state_connected = 0; | |||
packet_cache_reset_master_address( packcache ); | |||
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||
cont_miss = 0; | |||
} | |||
/* reset packet_bufX... */ | |||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||
/* ---------- Send ---------- */ | |||
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, | |||
packet_bufX, net_period, dont_htonl_floats); | |||
/* fill in packet hdr */ | |||
pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); | |||
pkthdr_tx->transport_frame = local_trans_pos.frame; | |||
pkthdr_tx->framecnt = framecnt; | |||
pkthdr_tx->latency = latency; | |||
pkthdr_tx->reply_port = reply_port; | |||
pkthdr_tx->sample_rate = jack_get_sample_rate (client); | |||
pkthdr_tx->period_size = nframes; | |||
/* playback for us is capture on the other side */ | |||
pkthdr_tx->capture_channels_audio = playback_channels_audio; | |||
pkthdr_tx->playback_channels_audio = capture_channels_audio; | |||
pkthdr_tx->capture_channels_midi = playback_channels_midi; | |||
pkthdr_tx->playback_channels_midi = capture_channels_midi; | |||
pkthdr_tx->mtu = mtu; | |||
if( freewheeling != 0 ) | |||
pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; | |||
else | |||
pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; | |||
//printf("goodness=%d\n", deadline_goodness ); | |||
packet_header_hton (pkthdr_tx); | |||
if (cont_miss < 3 * latency + 5) { | |||
int r; | |||
for( r = 0; r < redundancy; r++ ) | |||
netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||
} else if (cont_miss > 50 + 5 * latency) { | |||
state_connected = 0; | |||
packet_cache_reset_master_address( packcache ); | |||
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||
cont_miss = 0; | |||
} | |||
} | |||
/* | |||
@@ -354,19 +343,19 @@ process (jack_nframes_t nframes, void *arg) | |||
input_fd = outsockfd; | |||
// for latency == 0 we can poll. | |||
if( (latency == 0) || (freewheeling!=0) ) { | |||
jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client)/jack_get_sample_rate(client); | |||
if( (latency == 0) || (freewheeling != 0) ) { | |||
jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client) / jack_get_sample_rate(client); | |||
// Now loop until we get the right packet. | |||
while(1) { | |||
jack_nframes_t got_frame; | |||
if ( ! netjack_poll_deadline( input_fd, deadline ) ) | |||
break; | |||
break; | |||
packet_cache_drain_socket(packcache, input_fd); | |||
if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) | |||
if( got_frame == (framecnt - latency) ) | |||
break; | |||
if( got_frame == (framecnt - latency) ) | |||
break; | |||
} | |||
} else { | |||
// normally: | |||
@@ -377,8 +366,7 @@ process (jack_nframes_t nframes, void *arg) | |||
size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp ); | |||
/* First alternative : we received what we expected. Render the data | |||
* to the JACK ports so it can be played. */ | |||
if (size == rx_bufsize) | |||
{ | |||
if (size == rx_bufsize) { | |||
uint32_t *packet_buf_rx = rx_packet_ptr; | |||
jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; | |||
packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||
@@ -389,13 +377,12 @@ process (jack_nframes_t nframes, void *arg) | |||
deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; | |||
//printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); | |||
if (cont_miss) | |||
{ | |||
if (cont_miss) { | |||
//printf("Frame %d \tRecovered from dropouts\n", framecnt); | |||
cont_miss = 0; | |||
} | |||
render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, | |||
capture_ports, capture_srcs, nframes, dont_htonl_floats); | |||
capture_ports, capture_srcs, nframes, dont_htonl_floats); | |||
state_currentframe = framecnt; | |||
state_recv_packet_queue_time = recv_time_offset; | |||
@@ -406,8 +393,7 @@ process (jack_nframes_t nframes, void *arg) | |||
/* Second alternative : we've received something that's not | |||
* as big as expected or we missed a packet. We render silence | |||
* to the ouput ports */ | |||
else | |||
{ | |||
else { | |||
jack_nframes_t latency_estimate; | |||
if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) | |||
//if( (state_latency == 0) || (latency_estimate < state_latency) ) | |||
@@ -423,8 +409,7 @@ process (jack_nframes_t nframes, void *arg) | |||
cont_miss += 1; | |||
chn = 0; | |||
node = capture_ports; | |||
while (node != NULL) | |||
{ | |||
while (node != NULL) { | |||
port = (jack_port_t *) node->data; | |||
buf = jack_port_get_buffer (port, nframes); | |||
porttype = jack_port_type (port); | |||
@@ -438,47 +423,45 @@ process (jack_nframes_t nframes, void *arg) | |||
} | |||
} | |||
if (latency != 0) { | |||
/* reset packet_bufX... */ | |||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||
/* ---------- Send ---------- */ | |||
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, | |||
packet_bufX, net_period, dont_htonl_floats); | |||
/* fill in packet hdr */ | |||
pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); | |||
pkthdr_tx->transport_frame = local_trans_pos.frame; | |||
pkthdr_tx->framecnt = framecnt; | |||
pkthdr_tx->latency = latency; | |||
pkthdr_tx->reply_port = reply_port; | |||
pkthdr_tx->sample_rate = jack_get_sample_rate (client); | |||
pkthdr_tx->period_size = nframes; | |||
/* playback for us is capture on the other side */ | |||
pkthdr_tx->capture_channels_audio = playback_channels_audio; | |||
pkthdr_tx->playback_channels_audio = capture_channels_audio; | |||
pkthdr_tx->capture_channels_midi = playback_channels_midi; | |||
pkthdr_tx->playback_channels_midi = capture_channels_midi; | |||
pkthdr_tx->mtu = mtu; | |||
if( freewheeling!= 0 ) | |||
pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; | |||
else | |||
pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; | |||
//printf("goodness=%d\n", deadline_goodness ); | |||
packet_header_hton (pkthdr_tx); | |||
if (cont_miss < 3*latency+5) { | |||
int r; | |||
for( r=0; r<redundancy; r++ ) | |||
netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||
} | |||
else if (cont_miss > 50+5*latency) | |||
{ | |||
state_connected = 0; | |||
packet_cache_reset_master_address( packcache ); | |||
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||
cont_miss = 0; | |||
} | |||
/* reset packet_bufX... */ | |||
packet_bufX = packet_buf_tx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t); | |||
/* ---------- Send ---------- */ | |||
render_jack_ports_to_payload (bitdepth, playback_ports, playback_srcs, nframes, | |||
packet_bufX, net_period, dont_htonl_floats); | |||
/* fill in packet hdr */ | |||
pkthdr_tx->transport_state = jack_transport_query (client, &local_trans_pos); | |||
pkthdr_tx->transport_frame = local_trans_pos.frame; | |||
pkthdr_tx->framecnt = framecnt; | |||
pkthdr_tx->latency = latency; | |||
pkthdr_tx->reply_port = reply_port; | |||
pkthdr_tx->sample_rate = jack_get_sample_rate (client); | |||
pkthdr_tx->period_size = nframes; | |||
/* playback for us is capture on the other side */ | |||
pkthdr_tx->capture_channels_audio = playback_channels_audio; | |||
pkthdr_tx->playback_channels_audio = capture_channels_audio; | |||
pkthdr_tx->capture_channels_midi = playback_channels_midi; | |||
pkthdr_tx->playback_channels_midi = capture_channels_midi; | |||
pkthdr_tx->mtu = mtu; | |||
if( freewheeling != 0 ) | |||
pkthdr_tx->sync_state = (jack_nframes_t)MASTER_FREEWHEELS; | |||
else | |||
pkthdr_tx->sync_state = (jack_nframes_t)deadline_goodness; | |||
//printf("goodness=%d\n", deadline_goodness ); | |||
packet_header_hton (pkthdr_tx); | |||
if (cont_miss < 3 * latency + 5) { | |||
int r; | |||
for( r = 0; r < redundancy; r++ ) | |||
netjack_sendto (outsockfd, (char *) packet_buf_tx, tx_bufsize, 0, &destaddr, sizeof (destaddr), mtu); | |||
} else if (cont_miss > 50 + 5 * latency) { | |||
state_connected = 0; | |||
packet_cache_reset_master_address( packcache ); | |||
//printf ("Frame %d \tRealy too many packets missed (%d). Let's reset the counter\n", framecnt, cont_miss); | |||
cont_miss = 0; | |||
} | |||
} | |||
framecnt++; | |||
@@ -502,20 +485,18 @@ init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t por | |||
{ | |||
name->sin_family = AF_INET ; | |||
name->sin_port = htons (port); | |||
if (hostname) | |||
{ | |||
if (hostname) { | |||
struct hostent *hostinfo = gethostbyname (hostname); | |||
if (hostinfo == NULL) { | |||
fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname); | |||
fflush( stderr ); | |||
} | |||
fflush( stderr ); | |||
} | |||
#ifdef WIN32 | |||
name->sin_addr.s_addr = inet_addr( hostname ); | |||
#else | |||
name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; | |||
#endif | |||
} | |||
else | |||
} else | |||
name->sin_addr.s_addr = htonl (INADDR_ANY) ; | |||
} | |||
@@ -523,32 +504,32 @@ init_sockaddr_in (struct sockaddr_in *name , const char *hostname , uint16_t por | |||
void | |||
printUsage () | |||
{ | |||
fprintf (stderr, "usage: jack_netsource [options]\n" | |||
"\n" | |||
" -h this help text\n" | |||
" -H <slave host> - Host name of the slave JACK\n" | |||
" -o <num channels> - Number of audio playback channels\n" | |||
" -i <num channels> - Number of audio capture channels\n" | |||
" -O <num channels> - Number of midi playback channels\n" | |||
" -I <num channels> - Number of midi capture channels\n" | |||
" -n <periods> - Network latency in JACK periods\n" | |||
" -p <port> - UDP port that the slave is listening on\n" | |||
" -r <reply port> - UDP port that we are listening on\n" | |||
" -B <bind port> - reply port, for use in NAT environments\n" | |||
" -b <bitdepth> - Set transport to use 16bit or 8bit\n" | |||
" -c <kbits> - Use CELT encoding with <kbits> kbits per channel\n" | |||
" -m <mtu> - Assume this mtu for the link\n" | |||
" -R <N> - Redundancy: send out packets N times.\n" | |||
" -e - skip host-to-network endianness conversion\n" | |||
" -N <jack name> - Reports a different name to jack\n" | |||
" -s <server name> - The name of the local jack server\n" | |||
"\n"); | |||
fprintf (stderr, "usage: jack_netsource [options]\n" | |||
"\n" | |||
" -h this help text\n" | |||
" -H <slave host> - Host name of the slave JACK\n" | |||
" -o <num channels> - Number of audio playback channels\n" | |||
" -i <num channels> - Number of audio capture channels\n" | |||
" -O <num channels> - Number of midi playback channels\n" | |||
" -I <num channels> - Number of midi capture channels\n" | |||
" -n <periods> - Network latency in JACK periods\n" | |||
" -p <port> - UDP port that the slave is listening on\n" | |||
" -r <reply port> - UDP port that we are listening on\n" | |||
" -B <bind port> - reply port, for use in NAT environments\n" | |||
" -b <bitdepth> - Set transport to use 16bit or 8bit\n" | |||
" -c <kbits> - Use CELT encoding with <kbits> kbits per channel\n" | |||
" -m <mtu> - Assume this mtu for the link\n" | |||
" -R <N> - Redundancy: send out packets N times.\n" | |||
" -e - skip host-to-network endianness conversion\n" | |||
" -N <jack name> - Reports a different name to jack\n" | |||
" -s <server name> - The name of the local jack server\n" | |||
"\n"); | |||
} | |||
void | |||
sigterm_handler( int signal ) | |||
{ | |||
quit = 1; | |||
quit = 1; | |||
} | |||
int | |||
@@ -561,7 +542,7 @@ main (int argc, char *argv[]) | |||
jack_status_t status; | |||
#ifdef WIN32 | |||
WSADATA wsa; | |||
int rc = WSAStartup(MAKEWORD(2,0),&wsa); | |||
int rc = WSAStartup(MAKEWORD(2, 0), &wsa); | |||
#endif | |||
/* Torben's famous state variables, aka "the reporting API" ! */ | |||
/* heh ? these are only the copies of them ;) */ | |||
@@ -570,10 +551,9 @@ main (int argc, char *argv[]) | |||
/* Argument parsing stuff */ | |||
extern char *optarg; | |||
extern int optind, optopt; | |||
int errflg=0, c; | |||
int errflg = 0, c; | |||
if (argc < 3) | |||
{ | |||
if (argc < 3) { | |||
printUsage (); | |||
return 1; | |||
} | |||
@@ -583,17 +563,15 @@ main (int argc, char *argv[]) | |||
sprintf(client_name, "netjack"); | |||
sprintf(peer_ip, "localhost"); | |||
while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:")) != -1) | |||
{ | |||
switch (c) | |||
{ | |||
while ((c = getopt (argc, argv, ":h:H:o:i:O:I:n:p:r:B:b:c:m:R:e:N:s:")) != -1) { | |||
switch (c) { | |||
case 'h': | |||
printUsage(); | |||
exit (0); | |||
break; | |||
case 'H': | |||
free(peer_ip); | |||
peer_ip = (char *) malloc (sizeof (char) * strlen (optarg)+1); | |||
peer_ip = (char *) malloc (sizeof (char) * strlen (optarg) + 1); | |||
strcpy (peer_ip, optarg); | |||
break; | |||
case 'o': | |||
@@ -647,11 +625,11 @@ main (int argc, char *argv[]) | |||
break; | |||
case 'N': | |||
free(client_name); | |||
client_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); | |||
client_name = (char *) malloc (sizeof (char) * strlen (optarg) + 1); | |||
strcpy (client_name, optarg); | |||
break; | |||
case 's': | |||
server_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); | |||
server_name = (char *) malloc (sizeof (char) * strlen (optarg) + 1); | |||
strcpy (server_name, optarg); | |||
options |= JackServerName; | |||
break; | |||
@@ -664,8 +642,7 @@ main (int argc, char *argv[]) | |||
errflg++; | |||
} | |||
} | |||
if (errflg) | |||
{ | |||
if (errflg) { | |||
printUsage (); | |||
exit (2); | |||
} | |||
@@ -688,8 +665,7 @@ main (int argc, char *argv[]) | |||
fprintf (stderr, "bind failure\n" ); | |||
} | |||
} | |||
if (reply_port) | |||
{ | |||
if (reply_port) { | |||
init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); | |||
if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { | |||
fprintf (stderr, "bind failure\n" ); | |||
@@ -698,10 +674,9 @@ main (int argc, char *argv[]) | |||
/* try to become a client of the JACK server */ | |||
client = jack_client_open (client_name, options, &status, server_name); | |||
if (client == NULL) | |||
{ | |||
if (client == NULL) { | |||
fprintf (stderr, "jack_client_open() failed, status = 0x%2.0x\n" | |||
"Is the JACK server running ?\n", status); | |||
"Is the JACK server running ?\n", status); | |||
return 1; | |||
} | |||
@@ -714,7 +689,7 @@ main (int argc, char *argv[]) | |||
alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); | |||
if( bitdepth == 1000 ) | |||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8)&(~1) ; | |||
net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ; | |||
else | |||
net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); | |||
@@ -722,8 +697,7 @@ main (int argc, char *argv[]) | |||
packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); | |||
/* tell the JACK server that we are ready to roll */ | |||
if (jack_activate (client)) | |||
{ | |||
if (jack_activate (client)) { | |||
fprintf (stderr, "Cannot activate client"); | |||
return 1; | |||
} | |||
@@ -737,49 +711,41 @@ main (int argc, char *argv[]) | |||
statecopy_latency = state_latency; | |||
statecopy_netxruns = state_netxruns; | |||
while ( !quit ) | |||
{ | |||
while ( !quit ) { | |||
#ifdef WIN32 | |||
Sleep (1000); | |||
#else | |||
sleep(1); | |||
#endif | |||
if (statecopy_connected != state_connected) | |||
{ | |||
if (statecopy_connected != state_connected) { | |||
statecopy_connected = state_connected; | |||
if (statecopy_connected) | |||
{ | |||
if (statecopy_connected) { | |||
state_netxruns = 1; // We want to reset the netxrun count on each new connection | |||
printf ("Connected :-)\n"); | |||
} | |||
else | |||
} else | |||
printf ("Not Connected\n"); | |||
fflush(stdout); | |||
fflush(stdout); | |||
} | |||
if (statecopy_connected) | |||
{ | |||
if (statecopy_netxruns != state_netxruns) { | |||
statecopy_netxruns = state_netxruns; | |||
printf ("%s: at frame %06d -> total netxruns %d (%d%%) queue time= %d\n", | |||
client_name, | |||
state_currentframe, | |||
statecopy_netxruns, | |||
100*statecopy_netxruns/state_currentframe, | |||
state_recv_packet_queue_time); | |||
fflush(stdout); | |||
if (statecopy_connected) { | |||
if (statecopy_netxruns != state_netxruns) { | |||
statecopy_netxruns = state_netxruns; | |||
printf ("%s: at frame %06d -> total netxruns %d (%d%%) queue time= %d\n", | |||
client_name, | |||
state_currentframe, | |||
statecopy_netxruns, | |||
100 * statecopy_netxruns / state_currentframe, | |||
state_recv_packet_queue_time); | |||
fflush(stdout); | |||
} | |||
} | |||
else | |||
{ | |||
if (statecopy_latency != state_latency) | |||
{ | |||
statecopy_latency = state_latency; | |||
if (statecopy_latency > 1) | |||
printf ("current latency %d\n", statecopy_latency); | |||
fflush(stdout); | |||
} else { | |||
if (statecopy_latency != state_latency) { | |||
statecopy_latency = state_latency; | |||
if (statecopy_latency > 1) | |||
printf ("current latency %d\n", statecopy_latency); | |||
fflush(stdout); | |||
} | |||
} | |||
} | |||
@@ -0,0 +1,80 @@ | |||
/* | |||
Copyright (C) 2004-2008 Grame | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#include "JackMMCSS.h" | |||
#include "JackError.h" | |||
#include <assert.h> | |||
#include <stdio.h> | |||
namespace Jack | |||
{ | |||
avSetMmThreadCharacteristics JackMMCSS::ffMMCSSFun1 = NULL; | |||
avSetMmThreadPriority JackMMCSS::ffMMCSSFun2 = NULL; | |||
avRevertMmThreadCharacteristics JackMMCSS::ffMMCSSFun3 = NULL; | |||
JACK_HANDLE JackMMCSS::fAvrtDll; | |||
std::map<jack_native_thread_t, HANDLE> JackMMCSS::fHandleTable; | |||
JackMMCSS::JackMMCSS() | |||
{ | |||
fAvrtDll = LoadJackModule("avrt.dll"); | |||
if (fAvrtDll != NULL) { | |||
ffMMCSSFun1 = (avSetMmThreadCharacteristics)GetJackProc(fAvrtDll, "AvSetMmThreadCharacteristicsA"); | |||
ffMMCSSFun2 = (avSetMmThreadPriority)GetJackProc(fAvrtDll, "AvSetMmThreadPriority"); | |||
ffMMCSSFun3 = (avRevertMmThreadCharacteristics)GetJackProc(fAvrtDll, "AvRevertMmThreadCharacteristics"); | |||
} | |||
} | |||
JackMMCSS::~JackMMCSS() | |||
{} | |||
int JackMMCSS::MMCSSAcquireRealTime(jack_native_thread_t thread) | |||
{ | |||
if (fHandleTable.find(thread) != fHandleTable.end()) { | |||
return 0; | |||
} | |||
if (ffMMCSSFun1) { | |||
DWORD dummy = 0; | |||
HANDLE task = ffMMCSSFun1("Pro Audio", &dummy); | |||
if (task == NULL) { | |||
jack_error("Cannot use MMCSS %d", GetLastError()); | |||
} else if (ffMMCSSFun2(task, AVRT_PRIORITY_CRITICAL)) { | |||
fHandleTable[thread] = task; | |||
return 0; | |||
} | |||
} | |||
return -1; | |||
} | |||
int JackMMCSS::MMCSSDropRealTime(jack_native_thread_t thread) | |||
{ | |||
if (fHandleTable.find(thread) != fHandleTable.end()) { | |||
HANDLE task = fHandleTable[thread]; | |||
ffMMCSSFun3(task); | |||
return 0; | |||
} else { | |||
return -1; | |||
} | |||
} | |||
} |
@@ -0,0 +1,72 @@ | |||
/* | |||
Copyright (C) 2004-2008 Grame | |||
This program is free software; you can redistribute it and/or modify | |||
it under the terms of the GNU Lesser General Public License as published by | |||
the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. | |||
You should have received a copy of the GNU Lesser General Public License | |||
along with this program; if not, write to the Free Software | |||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |||
*/ | |||
#ifndef __JackMMCSS__ | |||
#define __JackMMCSS__ | |||
#include "JackSystemDeps.h" | |||
#include "JackCompilerDeps.h" | |||
#include <windows.h> | |||
#include <map> | |||
namespace Jack | |||
{ | |||
typedef enum _AVRT_PRIORITY { | |||
AVRT_PRIORITY_LOW = -1, | |||
AVRT_PRIORITY_NORMAL, /* 0 */ | |||
AVRT_PRIORITY_HIGH, /* 1 */ | |||
AVRT_PRIORITY_CRITICAL /* 2 */ | |||
} AVRT_PRIORITY, *PAVRT_PRIORITY; | |||
typedef HANDLE (WINAPI *avSetMmThreadCharacteristics)(LPCTSTR, LPDWORD); | |||
typedef BOOL (WINAPI *avRevertMmThreadCharacteristics)(HANDLE); | |||
typedef BOOL (WINAPI *avSetMmThreadPriority)(HANDLE, AVRT_PRIORITY); | |||
/*! | |||
\brief MMCSS services. | |||
*/ | |||
class SERVER_EXPORT JackMMCSS | |||
{ | |||
private: | |||
static JACK_HANDLE fAvrtDll; | |||
static avSetMmThreadCharacteristics ffMMCSSFun1; | |||
static avSetMmThreadPriority ffMMCSSFun2; | |||
static avRevertMmThreadCharacteristics ffMMCSSFun3; | |||
static std::map<jack_native_thread_t, HANDLE> fHandleTable; | |||
public: | |||
JackMMCSS(); | |||
~JackMMCSS(); | |||
static int MMCSSAcquireRealTime(jack_native_thread_t thread); | |||
static int MMCSSDropRealTime(jack_native_thread_t thread); | |||
}; | |||
} // end of namespace | |||
#endif | |||
@@ -17,11 +17,11 @@ | |||
*/ | |||
#include "JackWinThread.h" | |||
#include "JackError.h" | |||
#include "JackTime.h" | |||
#include <assert.h> | |||
#include <stdio.h> | |||
namespace Jack | |||
{ | |||
@@ -55,7 +55,7 @@ DWORD WINAPI JackWinThread::ThreadHandler(void* arg) | |||
} | |||
JackWinThread::JackWinThread(JackRunnableInterface* runnable) | |||
: JackThreadInterface(runnable, 0, false, 0) | |||
: JackMMCSS(), JackThreadInterface(runnable, 0, false, 0) | |||
{ | |||
fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | |||
fThread = (HANDLE)NULL; | |||
@@ -202,11 +202,17 @@ int JackWinThread::AcquireRealTimeImp(jack_native_thread_t thread, int priority) | |||
{ | |||
jack_log("JackWinThread::AcquireRealTimeImp priority = %d", THREAD_PRIORITY_TIME_CRITICAL); | |||
if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
if (priority >= 90 && MMCSSAcquireRealTime(thread) == 0) { | |||
jack_info("MMCSS API used to acquire RT for thread: %x", thread); | |||
return 0; | |||
} else { | |||
jack_error("Cannot set thread priority = %d", GetLastError()); | |||
return -1; | |||
jack_info("MMCSS API not used..."); | |||
if (SetThreadPriority(thread, THREAD_PRIORITY_TIME_CRITICAL)) { | |||
return 0; | |||
} else { | |||
jack_error("Cannot set thread priority = %d", GetLastError()); | |||
return -1; | |||
} | |||
} | |||
} | |||
@@ -222,7 +228,10 @@ int JackWinThread::DropSelfRealTime() | |||
int JackWinThread::DropRealTimeImp(jack_native_thread_t thread) | |||
{ | |||
if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) { | |||
if (MMCSSDropRealTime(thread) == 0 ) { | |||
jack_info("MMCSS API used to drop RT for thread: %x", thread); | |||
return 0; | |||
} else if (SetThreadPriority(thread, THREAD_PRIORITY_NORMAL)) { | |||
return 0; | |||
} else { | |||
jack_error("Cannot set thread priority = %d", GetLastError()); | |||
@@ -17,12 +17,11 @@ | |||
*/ | |||
#ifndef __JackWinThread__ | |||
#define __JackWinThread__ | |||
#include "JackThread.h" | |||
#include "JackMMCSS.h" | |||
#include "JackCompilerDeps.h" | |||
#include "JackSystemDeps.h" | |||
#include <windows.h> | |||
@@ -36,7 +35,7 @@ typedef DWORD (WINAPI *ThreadCallback)(void *arg); | |||
\brief Windows threads. | |||
*/ | |||
class SERVER_EXPORT JackWinThread : public detail::JackThreadInterface | |||
class SERVER_EXPORT JackWinThread : public JackMMCSS, public detail::JackThreadInterface | |||
{ | |||
private: | |||
@@ -1,7 +1,7 @@ | |||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | |||
<CodeBlocks_workspace_file> | |||
<Workspace title="jack"> | |||
<Project filename="libjackserver.cbp" /> | |||
<Project filename="libjackserver.cbp" active="1" /> | |||
<Project filename="jack_portaudio.cbp" /> | |||
<Project filename="jack_netdriver.cbp" /> | |||
<Project filename="jack_netonedriver.cbp" /> | |||
@@ -18,7 +18,7 @@ | |||
<Project filename="jack_disconnect.cbp" /> | |||
<Project filename="jack_test.cbp" /> | |||
<Project filename="multiple_metro.cbp" /> | |||
<Project filename="jack_winmme.cbp" active="1" /> | |||
<Project filename="jack_winmme.cbp" /> | |||
<Project filename="jack_loopback.cbp" /> | |||
<Project filename="jackd.cbp" /> | |||
<Project filename="jack_midi_latency_test.cbp" /> | |||
@@ -133,7 +133,7 @@ | |||
<Add library="odbccp32" /> | |||
</Linker> | |||
</Target> | |||
<Target title="Win32 Release 32bits"> | |||
<Target title="Win32 Release 32bits"> | |||
<Option output="Release\bin\libjack" prefix_auto="1" extension_auto="1" /> | |||
<Option object_output="Release" /> | |||
<Option type="3" /> | |||
@@ -143,7 +143,7 @@ | |||
<Compiler> | |||
<Add option="-O2" /> | |||
<Add option="-Wall" /> | |||
<Add option="-m32" /> | |||
<Add option="-m32" /> | |||
<Add option="-DWIN32" /> | |||
<Add option="-DNDEBUG" /> | |||
<Add option="-D_WINDOWS" /> | |||
@@ -162,7 +162,7 @@ | |||
<Add directory="tre-0.8.0\lib" /> | |||
</Compiler> | |||
<Linker> | |||
<Add option="-m32" /> | |||
<Add option="-m32" /> | |||
<Add library="kernel32" /> | |||
<Add library="user32" /> | |||
<Add library="gdi32" /> | |||
@@ -176,7 +176,7 @@ | |||
<Add library="odbc32" /> | |||
<Add library="odbccp32" /> | |||
</Linker> | |||
<ExtraCommands> | |||
<ExtraCommands> | |||
<Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" /> | |||
</ExtraCommands> | |||
</Target> | |||
@@ -190,7 +190,7 @@ | |||
<Compiler> | |||
<Add option="-Wall" /> | |||
<Add option="-g" /> | |||
<Add option="-m32" /> | |||
<Add option="-m32" /> | |||
<Add option="-DWIN32" /> | |||
<Add option="-D_DEBUG" /> | |||
<Add option="-D_WINDOWS" /> | |||
@@ -209,7 +209,7 @@ | |||
<Add directory="tre-0.8.0\lib" /> | |||
</Compiler> | |||
<Linker> | |||
<Add option="-m32" /> | |||
<Add option="-m32" /> | |||
<Add library="kernel32" /> | |||
<Add library="user32" /> | |||
<Add library="gdi32" /> | |||
@@ -223,7 +223,7 @@ | |||
<Add library="odbc32" /> | |||
<Add library="odbccp32" /> | |||
</Linker> | |||
<ExtraCommands> | |||
<ExtraCommands> | |||
<Add before="windres -F pe-i386 -O coff -o Debug/libjack.res libjack.rc" /> | |||
</ExtraCommands> | |||
</Target> | |||
@@ -237,7 +237,7 @@ | |||
<Compiler> | |||
<Add option="-O2" /> | |||
<Add option="-Wall" /> | |||
<Add option="-m32" /> | |||
<Add option="-m32" /> | |||
<Add option="-DWIN32" /> | |||
<Add option="-DNDEBUG" /> | |||
<Add option="-D_WINDOWS" /> | |||
@@ -257,7 +257,7 @@ | |||
<Add directory="tre-0.8.0\lib" /> | |||
</Compiler> | |||
<Linker> | |||
<Add option="-m32" /> | |||
<Add option="-m32" /> | |||
<Add library="kernel32" /> | |||
<Add library="user32" /> | |||
<Add library="gdi32" /> | |||
@@ -271,7 +271,7 @@ | |||
<Add library="odbc32" /> | |||
<Add library="odbccp32" /> | |||
</Linker> | |||
<ExtraCommands> | |||
<ExtraCommands> | |||
<Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" /> | |||
</ExtraCommands> | |||
</Target> | |||
@@ -322,6 +322,7 @@ | |||
<Unit filename="..\common\shm.c"> | |||
<Option compilerVar="CC" /> | |||
</Unit> | |||
<Unit filename="JackMMCSS.cpp" /> | |||
<Unit filename="JackWinNamedPipe.cpp" /> | |||
<Unit filename="JackWinNamedPipeClientChannel.cpp" /> | |||
<Unit filename="JackWinProcessSync.cpp" /> | |||
@@ -32,8 +32,8 @@ | |||
<Add directory="..\common" /> | |||
</Compiler> | |||
<Linker> | |||
<Add directory="Release64\bin" /> | |||
<Add library="libsamplerate_x86_64" /> | |||
<Add directory="Release64\bin" /> | |||
</Linker> | |||
</Target> | |||
<Target title="Win32 Debug 64bits"> | |||
@@ -62,8 +62,8 @@ | |||
<Add directory="..\common" /> | |||
</Compiler> | |||
<Linker> | |||
<Add directory="Debug64\bin" /> | |||
<Add library="libsamplerate_x86_64" /> | |||
<Add directory="Debug64\bin" /> | |||
</Linker> | |||
</Target> | |||
<Target title="Win32 Profiling 64bits"> | |||
@@ -93,8 +93,8 @@ | |||
<Add directory="..\common" /> | |||
</Compiler> | |||
<Linker> | |||
<Add directory="Release64\bin" /> | |||
<Add library="libsamplerate_x86_64" /> | |||
<Add directory="Release64\bin" /> | |||
</Linker> | |||
</Target> | |||
<Target title="Win32 Release 32bits"> | |||
@@ -125,8 +125,8 @@ | |||
</Compiler> | |||
<Linker> | |||
<Add option="-m32" /> | |||
<Add directory="Release\bin" /> | |||
<Add library="libsamplerate_x86" /> | |||
<Add directory="Release\bin" /> | |||
</Linker> | |||
<ExtraCommands> | |||
<Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" /> | |||
@@ -160,8 +160,8 @@ | |||
</Compiler> | |||
<Linker> | |||
<Add option="-m32" /> | |||
<Add directory="Debug\bin" /> | |||
<Add library="libsamplerate_x86" /> | |||
<Add directory="Debug\bin" /> | |||
</Linker> | |||
<ExtraCommands> | |||
<Add before="windres -F pe-i386 -O coff -o Debug/libjacknet.res libjacknet.rc" /> | |||
@@ -196,8 +196,8 @@ | |||
</Compiler> | |||
<Linker> | |||
<Add option="-m32" /> | |||
<Add directory="Release\bin" /> | |||
<Add library="libsamplerate_x86" /> | |||
<Add directory="Release\bin" /> | |||
</Linker> | |||
<ExtraCommands> | |||
<Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" /> | |||
@@ -235,6 +235,7 @@ | |||
<Unit filename="..\common\ringbuffer.c"> | |||
<Option compilerVar="CC" /> | |||
</Unit> | |||
<Unit filename="JackMMCSS.cpp" /> | |||
<Unit filename="JackNetWinSocket.cpp" /> | |||
<Unit filename="JackWinThread.cpp" /> | |||
<Unit filename="JackWinTime.c"> | |||
@@ -289,6 +289,7 @@ | |||
<Unit filename="..\common\shm.c"> | |||
<Option compilerVar="CC" /> | |||
</Unit> | |||
<Unit filename="JackMMCSS.cpp" /> | |||
<Unit filename="JackNetWinSocket.cpp" /> | |||
<Unit filename="JackWinNamedPipe.cpp" /> | |||
<Unit filename="JackWinNamedPipeClientChannel.cpp" /> | |||
@@ -41,6 +41,8 @@ namespace Jack | |||
driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer; | |||
driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer; | |||
MMCSSAcquireRealTime(GetCurrentThread()); | |||
if (statusFlags) { | |||
if (statusFlags & paOutputUnderflow) | |||
jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | |||
@@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackAudioDriver.h" | |||
#include "JackPortAudioDevices.h" | |||
#include "JackMMCSS.h" | |||
namespace Jack | |||
{ | |||
@@ -30,7 +31,7 @@ namespace Jack | |||
\brief The PortAudio driver. | |||
*/ | |||
class JackPortAudioDriver : public JackAudioDriver | |||
class JackPortAudioDriver : public JackMMCSS, public JackAudioDriver | |||
{ | |||
private: | |||
@@ -54,7 +55,7 @@ class JackPortAudioDriver : public JackAudioDriver | |||
public: | |||
JackPortAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, PortAudioDevices* pa_devices) | |||
: JackAudioDriver(name, alias, engine, table), fStream(NULL), fInputBuffer(NULL), fOutputBuffer(NULL), | |||
: JackMMCSS(), JackAudioDriver(name, alias, engine, table), fStream(NULL), fInputBuffer(NULL), fOutputBuffer(NULL), | |||
fInputDevice(paNoDevice), fOutputDevice(paNoDevice) | |||
{ | |||
fPaDevices = pa_devices; | |||
@@ -60,7 +60,7 @@ JackWinMMEDriver::Attach() | |||
// Inputs | |||
for (int i = 0; i < fCaptureChannels; i++) { | |||
JackWinMMEInputPort *input_port = input_ports[i]; | |||
name = input_port->GetName(); | |||
name = input_port->GetName(); | |||
if (fEngine->PortRegister(fClientControl.fRefNum, name, | |||
JACK_DEFAULT_MIDI_TYPE, | |||
CaptureDriverFlags, buffer_size, &index) < 0) { | |||
@@ -22,7 +22,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||
#include "JackMidiUtil.h" | |||
#include "JackTime.h" | |||
#include "JackWinMMEOutputPort.h" | |||
#include "JackWinMMEOutputPort.h" | |||
#include "JackGlobals.h" | |||
#include "JackEngineControl.h" | |||
using Jack::JackWinMMEOutputPort; | |||
@@ -44,7 +46,8 @@ JackWinMMEOutputPort::HandleMessageEvent(HMIDIOUT handle, UINT message, | |||
JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name, | |||
const char *client_name, | |||
const char *driver_name, UINT index, | |||
const char *driver_name, | |||
UINT index, | |||
size_t max_bytes, | |||
size_t max_messages) | |||
{ | |||
@@ -86,7 +89,7 @@ JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name, | |||
snprintf(name, sizeof(name) - 1, "%s:playback_%d", client_name, index + 1); | |||
read_queue_ptr.release(); | |||
thread_queue_ptr.release(); | |||
thread_ptr.release(); | |||
thread_ptr.release(); | |||
return; | |||
destroy_thread_queue_semaphore: | |||
@@ -132,7 +135,7 @@ JackWinMMEOutputPort::Execute() | |||
for (;;) { | |||
if (! Wait(thread_queue_semaphore)) { | |||
jack_log("JackWinMMEOutputPort::Execute BREAK"); | |||
break; | |||
} | |||
jack_midi_event_t *event = thread_queue->DequeueEvent(); | |||
@@ -274,7 +277,7 @@ JackWinMMEOutputPort::Init() | |||
set_threaded_log_function(); | |||
// XX: Can more be done? Ideally, this thread should have the JACK server | |||
// thread priority + 1. | |||
if (thread->AcquireSelfRealTime()) { | |||
if (thread->AcquireSelfRealTime(GetEngineControl()->fServerPriority)) { | |||
jack_error("JackWinMMEOutputPort::Init - could not acquire realtime " | |||
"scheduling. Continuing anyway."); | |||
} | |||