@@ -90,6 +90,7 @@ class JackNetOneDriver : public JackAudioDriver | |||||
} | } | ||||
}; | }; | ||||
} | } | ||||
#endif | #endif |
@@ -86,26 +86,25 @@ int netjack_wait( netjack_driver_state_t *netj ) | |||||
jacknet_packet_header *pkthdr; | jacknet_packet_header *pkthdr; | ||||
if( !netj->next_deadline_valid ) { | 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. | // Increment expected frame here. | ||||
if( netj->expected_framecnt_valid ) { | if( netj->expected_framecnt_valid ) { | ||||
netj->expected_framecnt += 1; | |||||
netj->expected_framecnt += 1; | |||||
} else { | } 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 ); | //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 poll (have deadline calculated) | ||||
// then drain socket, rinse and repeat. | // then drain socket, rinse and repeat. | ||||
while(1) { | 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. | // check if we know who to send our packets too. | ||||
if (!netj->srcaddress_valid) | 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. | // XXX: switching mode unconditionally is stupid. | ||||
// if we were running free perhaps we like to behave differently | // 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 ) { | 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) ) { | // 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" ); | // 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->deadline_offset = (netj->period_usecs*90/100); | ||||
// } | // } | ||||
netj->next_deadline += netj->period_usecs; | |||||
netj->next_deadline += netj->period_usecs; | |||||
} else { | } 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; | int retval = 0; | ||||
if( !netj->packet_data_valid ) { | 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 { | } 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; | return retval; | ||||
@@ -338,19 +336,17 @@ void netjack_send_silence( netjack_driver_state_t *netj, int syncstate ) | |||||
memset(packet_bufX, 0, payload_size); | memset(packet_bufX, 0, payload_size); | ||||
packet_header_hton(tx_pkthdr); | 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 ) | void netjack_attach( netjack_driver_state_t *netj ) | ||||
{ | { | ||||
//puts ("net_driver_attach"); | //puts ("net_driver_attach"); | ||||
@@ -359,19 +355,17 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||||
unsigned int chn; | unsigned int chn; | ||||
int port_flags; | int port_flags; | ||||
if( netj->bitdepth == CELT_MODE ) | |||||
{ | |||||
if( netj->bitdepth == CELT_MODE ) { | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_7 || HAVE_CELT_API_0_8 || HAVE_CELT_API_0_11 | #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 | #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 | #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 | #endif | ||||
} | } | ||||
@@ -394,21 +388,21 @@ void netjack_attach( netjack_driver_state_t *netj ) | |||||
netj->capture_ports = | netj->capture_ports = | ||||
jack_slist_append (netj->capture_ports, port); | jack_slist_append (netj->capture_ports, port); | ||||
if( netj->bitdepth == CELT_MODE ) { | |||||
if( netj->bitdepth == CELT_MODE ) { | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_11 | #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 | #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 | #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 | ||||
#endif | #endif | ||||
} else { | |||||
} else { | |||||
#if HAVE_SAMPLERATE | #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 | #endif | ||||
} | |||||
} | |||||
} | } | ||||
for (chn = netj->capture_channels_audio; chn < netj->capture_channels; chn++) { | 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 = | netj->playback_ports = | ||||
jack_slist_append (netj->playback_ports, port); | jack_slist_append (netj->playback_ports, port); | ||||
if( netj->bitdepth == CELT_MODE ) { | |||||
if( netj->bitdepth == CELT_MODE ) { | |||||
#if HAVE_CELT | #if HAVE_CELT | ||||
#if HAVE_CELT_API_0_11 | #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 | #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 | #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 | ||||
#endif | #endif | ||||
} else { | |||||
} else { | |||||
#if HAVE_SAMPLERATE | #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 | #endif | ||||
} | |||||
} | |||||
} | } | ||||
for (chn = netj->playback_channels_audio; chn < netj->playback_channels; chn++) { | for (chn = netj->playback_channels_audio; chn < netj->playback_channels; chn++) { | ||||
snprintf (buf, sizeof(buf) - 1, "playback_%u", chn + 1); | 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); | jack_slist_free (netj->capture_ports); | ||||
netj->capture_ports = NULL; | 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 HAVE_CELT | ||||
if( netj->bitdepth == CELT_MODE ) | |||||
{ | |||||
if( netj->bitdepth == CELT_MODE ) { | |||||
CELTDecoder * decoder = node->data; | CELTDecoder * decoder = node->data; | ||||
celt_decoder_destroy(decoder); | celt_decoder_destroy(decoder); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #endif | ||||
{ | { | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
@@ -519,15 +510,12 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||||
jack_slist_free (netj->playback_ports); | jack_slist_free (netj->playback_ports); | ||||
netj->playback_ports = NULL; | 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 HAVE_CELT | ||||
if( netj->bitdepth == CELT_MODE ) | |||||
{ | |||||
if( netj->bitdepth == CELT_MODE ) { | |||||
CELTEncoder * encoder = node->data; | CELTEncoder * encoder = node->data; | ||||
celt_encoder_destroy(encoder); | celt_encoder_destroy(encoder); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #endif | ||||
{ | { | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
@@ -540,32 +528,32 @@ void netjack_detach( netjack_driver_state_t *netj ) | |||||
netj->playback_srcs = NULL; | netj->playback_srcs = NULL; | ||||
#if HAVE_CELT | #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 | #endif | ||||
} | } | ||||
netjack_driver_state_t *netjack_init (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 ) | |||||
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. | // Fill in netj values. | ||||
@@ -600,8 +588,7 @@ netjack_driver_state_t *netjack_init (netjack_driver_state_t *netj, | |||||
netj->client = client; | 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); | jack_info ("Invalid bitdepth: %d (8, 16 or 0 for float) !!!", bitdepth); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -647,8 +634,7 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
address.sin_family = AF_INET; | address.sin_family = AF_INET; | ||||
address.sin_port = htons(netj->listen_port); | address.sin_port = htons(netj->listen_port); | ||||
address.sin_addr.s_addr = htonl(INADDR_ANY); | 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"); | jack_info("bind error"); | ||||
return -1; | return -1; | ||||
} | } | ||||
@@ -664,14 +650,13 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
return -1; | return -1; | ||||
} | } | ||||
netj->srcaddress_valid = 0; | netj->srcaddress_valid = 0; | ||||
if (netj->use_autoconfig) | |||||
{ | |||||
if (netj->use_autoconfig) { | |||||
jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header)); | jacknet_packet_header *first_packet = alloca (sizeof (jacknet_packet_header)); | ||||
#ifdef WIN32 | |||||
#ifdef WIN32 | |||||
int address_size = sizeof( struct sockaddr_in ); | int address_size = sizeof( struct sockaddr_in ); | ||||
#else | |||||
#else | |||||
socklen_t address_size = sizeof (struct sockaddr_in); | socklen_t address_size = sizeof (struct sockaddr_in); | ||||
#endif | |||||
#endif | |||||
//jack_info ("Waiting for an incoming packet !!!"); | //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 !!!"); | //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; | return -1; | ||||
} | } | ||||
first_pack_len = recvfrom (netj->sockfd, (char *)first_packet, sizeof (jacknet_packet_header), 0, (struct sockaddr*) & netj->syncsource_address, &address_size); | 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; | 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); | packet_header_ntoh (first_packet); | ||||
jack_info ("AutoConfig Override !!!"); | 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); | jack_info ("AutoConfig Override: Master JACK sample rate = %d", first_packet->sample_rate); | ||||
netj->sample_rate = 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); | jack_info ("AutoConfig Override: Master JACK period size is %d", first_packet->period_size); | ||||
netj->period_size = 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); | jack_info ("AutoConfig Override: capture_channels_audio = %d", first_packet->capture_channels_audio); | ||||
netj->capture_channels_audio = 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); | jack_info ("AutoConfig Override: capture_channels_midi = %d", first_packet->capture_channels_midi); | ||||
netj->capture_channels_midi = 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); | jack_info ("AutoConfig Override: playback_channels_audio = %d", first_packet->playback_channels_audio); | ||||
netj->playback_channels_audio = 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); | jack_info ("AutoConfig Override: playback_channels_midi = %d", first_packet->playback_channels_midi); | ||||
netj->playback_channels_midi = 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; | netj->playback_channels = netj->playback_channels_audio + netj->playback_channels_midi; | ||||
if( (netj->capture_channels * netj->period_size * netj->latency * 4) > 100000000 ) { | 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 ) { | 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 ) { | 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... | // After possible Autoconfig: do all calculations... | ||||
@@ -765,15 +743,15 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
* 1000000.0f); | * 1000000.0f); | ||||
if( netj->latency == 0 ) | if( netj->latency == 0 ) | ||||
netj->deadline_offset = 50*netj->period_usecs; | |||||
netj->deadline_offset = 50 * netj->period_usecs; | |||||
else | 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 ) { | if( netj->bitdepth == CELT_MODE ) { | ||||
// celt mode. | // celt mode. | ||||
// TODO: this is a hack. But i dont want to change the packet header. | // 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_down = netj->resample_factor; | ||||
netj->net_period_up = netj->resample_factor_up; | netj->net_period_up = netj->resample_factor_up; | ||||
@@ -795,7 +773,7 @@ netjack_startup( netjack_driver_state_t *netj ) | |||||
if( netj->latency == 0 ) | if( netj->latency == 0 ) | ||||
netj->resync_threshold = 0; | netj->resync_threshold = 0; | ||||
else | else | ||||
netj->resync_threshold = MIN( 15, netj->latency-1 ); | |||||
netj->resync_threshold = MIN( 15, netj->latency - 1 ); | |||||
netj->running_free = 0; | netj->running_free = 0; | ||||
@@ -37,113 +37,113 @@ extern "C" | |||||
{ | { | ||||
#endif | #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 | #ifdef WIN32 | ||||
SOCKET sockfd; | |||||
SOCKET outsockfd; | |||||
SOCKET sockfd; | |||||
SOCKET outsockfd; | |||||
#else | #else | ||||
int sockfd; | |||||
int outsockfd; | |||||
int sockfd; | |||||
int outsockfd; | |||||
#endif | #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 | #if HAVE_CELT | ||||
CELTMode *celt_mode; | |||||
CELTMode *celt_mode; | |||||
#endif | #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 | #ifdef __cplusplus | ||||
} | } | ||||
@@ -152,13 +152,12 @@ packet_cache | |||||
int i, fragment_number; | int i, fragment_number; | ||||
if( pkt_size == sizeof(jacknet_packet_header) ) | if( pkt_size == sizeof(jacknet_packet_header) ) | ||||
fragment_number = 1; | |||||
fragment_number = 1; | |||||
else | 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)); | packet_cache *pcache = malloc (sizeof (packet_cache)); | ||||
if (pcache == NULL) | |||||
{ | |||||
if (pcache == NULL) { | |||||
jack_error ("could not allocate packet cache (1)"); | jack_error ("could not allocate packet cache (1)"); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -169,14 +168,12 @@ packet_cache | |||||
pcache->last_framecnt_retreived = 0; | pcache->last_framecnt_retreived = 0; | ||||
pcache->last_framecnt_retreived_valid = 0; | pcache->last_framecnt_retreived_valid = 0; | ||||
if (pcache->packets == NULL) | |||||
{ | |||||
if (pcache->packets == NULL) { | |||||
jack_error ("could not allocate packet cache (2)"); | jack_error ("could not allocate packet cache (2)"); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
for (i = 0; i < num_packets; i++) | |||||
{ | |||||
for (i = 0; i < num_packets; i++) { | |||||
pcache->packets[i].valid = 0; | pcache->packets[i].valid = 0; | ||||
pcache->packets[i].num_fragments = fragment_number; | pcache->packets[i].num_fragments = fragment_number; | ||||
pcache->packets[i].packet_size = pkt_size; | pcache->packets[i].packet_size = pkt_size; | ||||
@@ -184,8 +181,7 @@ packet_cache | |||||
pcache->packets[i].framecnt = 0; | pcache->packets[i].framecnt = 0; | ||||
pcache->packets[i].fragment_array = malloc (sizeof (char) * fragment_number); | pcache->packets[i].fragment_array = malloc (sizeof (char) * fragment_number); | ||||
pcache->packets[i].packet_buf = malloc (pkt_size); | 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)"); | jack_error ("could not allocate packet cache (3)"); | ||||
return NULL; | return NULL; | ||||
} | } | ||||
@@ -200,10 +196,9 @@ packet_cache_free (packet_cache *pcache) | |||||
{ | { | ||||
int i; | int i; | ||||
if( pcache == NULL ) | 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].fragment_array); | ||||
free (pcache->packets[i].packet_buf); | free (pcache->packets[i].packet_buf); | ||||
} | } | ||||
@@ -218,8 +213,7 @@ cache_packet | |||||
int i; | int i; | ||||
cache_packet *retval; | 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)) | if (pcache->packets[i].valid && (pcache->packets[i].framecnt == framecnt)) | ||||
return &(pcache->packets[i]); | return &(pcache->packets[i]); | ||||
} | } | ||||
@@ -228,8 +222,7 @@ cache_packet | |||||
// find a free packet. | // find a free packet. | ||||
retval = packet_cache_get_free_packet (pcache); | retval = packet_cache_get_free_packet (pcache); | ||||
if (retval != NULL) | |||||
{ | |||||
if (retval != NULL) { | |||||
cache_packet_set_framecnt (retval, framecnt); | cache_packet_set_framecnt (retval, framecnt); | ||||
return retval; | return retval; | ||||
} | } | ||||
@@ -257,10 +250,8 @@ cache_packet | |||||
cache_packet *retval = &(pcache->packets[0]); | cache_packet *retval = &(pcache->packets[0]); | ||||
int i; | 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; | minimal_frame = pcache->packets[i].framecnt; | ||||
retval = &(pcache->packets[i]); | retval = &(pcache->packets[i]); | ||||
} | } | ||||
@@ -274,8 +265,7 @@ cache_packet | |||||
{ | { | ||||
int i; | int i; | ||||
for (i = 0; i < pcache->size; i++) | |||||
{ | |||||
for (i = 0; i < pcache->size; i++) { | |||||
if (pcache->packets[i].valid == 0) | if (pcache->packets[i].valid == 0) | ||||
return &(pcache->packets[i]); | 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 fragment_nr = ntohl (pkthdr->fragment_nr); | ||||
jack_nframes_t framecnt = ntohl (pkthdr->framecnt); | jack_nframes_t framecnt = ntohl (pkthdr->framecnt); | ||||
if (framecnt != pack->framecnt) | |||||
{ | |||||
if (framecnt != pack->framecnt) { | |||||
jack_error ("errror. framecnts dont match"); | jack_error ("errror. framecnts dont match"); | ||||
return; | return; | ||||
} | } | ||||
if (fragment_nr == 0) | |||||
{ | |||||
if (fragment_nr == 0) { | |||||
memcpy (pack->packet_buf, packet_buf, rcv_len); | memcpy (pack->packet_buf, packet_buf, rcv_len); | ||||
pack->fragment_array[0] = 1; | pack->fragment_array[0] = 1; | ||||
return; | 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)); | memcpy (packet_bufX + fragment_nr * fragment_payload_size, dataX, rcv_len - sizeof (jacknet_packet_header)); | ||||
pack->fragment_array[fragment_nr] = 1; | pack->fragment_array[fragment_nr] = 1; | ||||
} | |||||
else | |||||
} else | |||||
jack_error ("too long packet received..."); | 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(); | jack_time_t now = jack_get_time(); | ||||
if( now >= deadline ) | 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 | #if HAVE_PPOLL | ||||
timeout_spec.tv_nsec = (deadline - now) * 1000; | 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); | poll_err = poll (&fds, 1, timeout); | ||||
#endif | #endif | ||||
if (poll_err == -1) | |||||
{ | |||||
switch (errno) | |||||
{ | |||||
if (poll_err == -1) { | |||||
switch (errno) { | |||||
case EBADF: | 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: | 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: | 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: | 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: | 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; | return poll_err; | ||||
@@ -427,17 +410,17 @@ netjack_poll (int sockfd, int timeout) | |||||
struct sigaction action; | struct sigaction action; | ||||
sigemptyset(&sigmask); | 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++) | for (i = 1; i < NSIG; i++) | ||||
if (sigismember (&sigmask, i)) | if (sigismember (&sigmask, i)) | ||||
@@ -447,31 +430,28 @@ netjack_poll (int sockfd, int timeout) | |||||
fds.events = POLLIN; | fds.events = POLLIN; | ||||
sigprocmask(SIG_UNBLOCK, &sigmask, &rsigmask); | sigprocmask(SIG_UNBLOCK, &sigmask, &rsigmask); | ||||
while (poll_err == 0) | |||||
{ | |||||
while (poll_err == 0) { | |||||
poll_err = poll (&fds, 1, timeout); | poll_err = poll (&fds, 1, timeout); | ||||
} | } | ||||
sigprocmask(SIG_SETMASK, &rsigmask, NULL); | sigprocmask(SIG_SETMASK, &rsigmask, NULL); | ||||
if (poll_err == -1) | |||||
{ | |||||
switch (errno) | |||||
{ | |||||
if (poll_err == -1) { | |||||
switch (errno) { | |||||
case EBADF: | 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: | 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: | 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: | 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: | 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; | return 0; | ||||
} | } | ||||
@@ -496,10 +476,10 @@ netjack_poll_deadline (int sockfd, jack_time_t deadline) | |||||
while( 1 ) { | while( 1 ) { | ||||
jack_time_t now = jack_get_time(); | jack_time_t now = jack_get_time(); | ||||
if( now >= deadline ) | if( now >= deadline ) | ||||
return 0; | |||||
return 0; | |||||
int timeout_usecs = (deadline - now); | int timeout_usecs = (deadline - now); | ||||
//jack_error( "timeout = %d", timeout_usecs ); | |||||
//jack_error( "timeout = %d", timeout_usecs ); | |||||
timeout.tv_sec = 0; | timeout.tv_sec = 0; | ||||
timeout.tv_usec = (timeout_usecs < 500) ? 500 : timeout_usecs; | timeout.tv_usec = (timeout_usecs < 500) ? 500 : timeout_usecs; | ||||
timeout.tv_usec = (timeout_usecs > 1000000) ? 500000 : 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 | #else | ||||
socklen_t senderlen = sizeof( struct sockaddr_in ); | socklen_t senderlen = sizeof( struct sockaddr_in ); | ||||
#endif | #endif | ||||
while (1) | |||||
{ | |||||
while (1) { | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, 0, | rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, 0, | ||||
(struct sockaddr*) &sender_address, &senderlen); | |||||
(struct sockaddr*) &sender_address, &senderlen); | |||||
#else | #else | ||||
rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, MSG_DONTWAIT, | rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, MSG_DONTWAIT, | ||||
(struct sockaddr*) &sender_address, &senderlen); | |||||
(struct sockaddr*) &sender_address, &senderlen); | |||||
#endif | #endif | ||||
if (rcv_len < 0) | if (rcv_len < 0) | ||||
return; | 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); | 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); | cpack = packet_cache_get_packet (pcache, framecnt); | ||||
cache_packet_add_fragment (cpack, rx_packet, rcv_len); | 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; | 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])); | 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 num_packets_before_us = 0; | ||||
int i; | int i; | ||||
for (i = 0; i < pcache->size; i++) | |||||
{ | |||||
for (i = 0; i < pcache->size; i++) { | |||||
cache_packet *cpack = &(pcache->packets[i]); | cache_packet *cpack = &(pcache->packets[i]); | ||||
if (cpack->valid && cache_packet_is_complete( cpack )) | if (cpack->valid && cache_packet_is_complete( cpack )) | ||||
if( cpack->framecnt >= expected_framecnt ) | 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 ) | packet_cache_get_next_available_framecnt( packet_cache *pcache, jack_nframes_t expected_framecnt, jack_nframes_t *framecnt ) | ||||
{ | { | ||||
int i; | 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; | int retval = 0; | ||||
for (i = 0; i < pcache->size; i++) | |||||
{ | |||||
for (i = 0; i < pcache->size; i++) { | |||||
cache_packet *cpack = &(pcache->packets[i]); | cache_packet *cpack = &(pcache->packets[i]); | ||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | //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 ) { | if( (cpack->framecnt - expected_framecnt) > best_offset ) { | ||||
continue; | 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) | if (retval && framecnt) | ||||
*framecnt = expected_framecnt + best_offset; | *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; | jack_nframes_t best_value = 0; | ||||
int retval = 0; | int retval = 0; | ||||
for (i = 0; i < pcache->size; i++) | |||||
{ | |||||
for (i = 0; i < pcache->size; i++) { | |||||
cache_packet *cpack = &(pcache->packets[i]); | cache_packet *cpack = &(pcache->packets[i]); | ||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | ||||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | if (!cpack->valid || !cache_packet_is_complete( cpack )) { | ||||
//printf( "invalid\n" ); | //printf( "invalid\n" ); | ||||
continue; | 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) | 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; | jack_nframes_t best_offset = 0; | ||||
int retval = 0; | int retval = 0; | ||||
for (i = 0; i < pcache->size; i++) | |||||
{ | |||||
for (i = 0; i < pcache->size; i++) { | |||||
cache_packet *cpack = &(pcache->packets[i]); | cache_packet *cpack = &(pcache->packets[i]); | ||||
//printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | //printf( "p%d: valid=%d, frame %d\n", i, cpack->valid, cpack->framecnt ); | ||||
if (!cpack->valid || !cache_packet_is_complete( cpack )) { | if (!cpack->valid || !cache_packet_is_complete( cpack )) { | ||||
//printf( "invalid\n" ); | //printf( "invalid\n" ); | ||||
continue; | 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) | if (retval && framecnt) | ||||
*framecnt = JACK_MAX_FRAMES - best_offset; | *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 = (jacknet_packet_header *) packet_buf; | ||||
pkthdr->fragment_nr = htonl (0); | pkthdr->fragment_nr = htonl (0); | ||||
err = sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size); | err = sendto(sockfd, packet_buf, pkt_size, flags, addr, addr_size); | ||||
if( err<0 ) { | |||||
if( err < 0 ) { | |||||
//printf( "error in send\n" ); | //printf( "error in send\n" ); | ||||
perror( "send" ); | perror( "send" ); | ||||
} | } | ||||
} | |||||
else | |||||
{ | |||||
} else { | |||||
int err; | int err; | ||||
// Copy the packet header to the tx pack first. | // Copy the packet header to the tx pack first. | ||||
memcpy(tx_packet, packet_buf, sizeof (jacknet_packet_header)); | 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 | // Now loop and send all | ||||
char *packet_bufX = packet_buf + sizeof (jacknet_packet_header); | 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++); | pkthdr->fragment_nr = htonl (frag_cnt++); | ||||
memcpy (dataX, packet_bufX, fragment_payload_size); | memcpy (dataX, packet_bufX, fragment_payload_size); | ||||
sendto (sockfd, tx_packet, mtu, flags, addr, addr_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); | // sendto(last_pack_size); | ||||
err = sendto(sockfd, tx_packet, last_payload_size + sizeof(jacknet_packet_header), flags, addr, addr_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" ); | //printf( "error in send\n" ); | ||||
perror( "send" ); | perror( "send" ); | ||||
} | } | ||||
@@ -826,24 +796,21 @@ decode_midi_buffer (uint32_t *buffer_uint32, unsigned int buffer_size_uint32, ja | |||||
{ | { | ||||
int i; | int i; | ||||
jack_midi_clear_buffer (buf); | 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; | uint32_t payload_size; | ||||
payload_size = buffer_uint32[i]; | payload_size = buffer_uint32[i]; | ||||
payload_size = ntohl (payload_size); | payload_size = ntohl (payload_size); | ||||
if (payload_size) | |||||
{ | |||||
if (payload_size) { | |||||
jack_midi_event_t event; | 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); | jack_midi_event_write (buf, event.time, event.buffer, event.size); | ||||
// skip to the next event | // 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 | 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; | unsigned int written = 0; | ||||
// midi port, encode midi events | // midi port, encode midi events | ||||
unsigned int nevents = jack_midi_get_event_count (buf); | 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_t event; | ||||
jack_midi_event_get (&event, buf, i); | jack_midi_event_get (&event, buf, i); | ||||
unsigned int nb_data_quads = (((event.size - 1) & ~0x3) >> 2) + 1; | unsigned int nb_data_quads = (((event.size - 1) & ~0x3) >> 2) + 1; | ||||
unsigned int payload_size = 3 + nb_data_quads; | unsigned int payload_size = 3 + nb_data_quads; | ||||
// only write if we have sufficient space for the event | // only write if we have sufficient space for the event | ||||
// otherwise drop it | // otherwise drop it | ||||
if (written + payload_size < buffer_size_uint32 - 1) | |||||
{ | |||||
if (written + payload_size < buffer_size_uint32 - 1) { | |||||
// write header | // write header | ||||
buffer_uint32[written]=htonl (payload_size); | |||||
buffer_uint32[written] = htonl (payload_size); | |||||
written++; | written++; | ||||
buffer_uint32[written]=htonl (event.time); | |||||
buffer_uint32[written] = htonl (event.time); | |||||
written++; | written++; | ||||
buffer_uint32[written]=htonl (event.size); | |||||
buffer_uint32[written] = htonl (event.size); | |||||
written++; | written++; | ||||
// write data | // write data | ||||
jack_midi_data_t* tmpbuff = (jack_midi_data_t*)(&(buffer_uint32[written])); | jack_midi_data_t* tmpbuff = (jack_midi_data_t*)(&(buffer_uint32[written])); | ||||
memcpy (tmpbuff, event.buffer, event.size); | memcpy (tmpbuff, event.buffer, event.size); | ||||
written += nb_data_quads; | written += nb_data_quads; | ||||
} | |||||
else | |||||
{ | |||||
} else { | |||||
// buffer overflow | // buffer overflow | ||||
jack_error ("midi buffer overflow"); | jack_error ("midi buffer overflow"); | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
// now put a netjack_midi 'no-payload' event, signaling EOF | // now put a netjack_midi 'no-payload' event, signaling EOF | ||||
buffer_uint32[written]=0; | |||||
buffer_uint32[written] = 0; | |||||
} | } | ||||
// render functions for float | // 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) | if (!packet_payload) | ||||
return; | return; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
int i; | int i; | ||||
int_float_t val; | int_float_t val; | ||||
#if HAVE_SAMPLERATE | #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); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
// audio port, resample if necessary | // audio port, resample if necessary | ||||
if (net_period_down != nframes) | |||||
{ | |||||
if (net_period_down != nframes) { | |||||
SRC_STATE *src_state = src_node->data; | 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]); | 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_set_ratio (src_state, src.src_ratio); | ||||
src_process (src_state, &src); | src_process (src_state, &src); | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #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 | // midi port, decode midi events | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_down; | 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; | uint32_t *packet_bufX = (uint32_t *) packet_payload; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
SRC_DATA src; | SRC_DATA src; | ||||
#endif | #endif | ||||
@@ -997,8 +948,7 @@ render_jack_ports_to_payload_float (JSList *playback_ports, JSList *playback_src | |||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
// audio port, resample if necessary | // audio port, resample if necessary | ||||
#if HAVE_SAMPLERATE | #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_set_ratio (src_state, src.src_ratio); | ||||
src_process (src_state, &src); | 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]); | packet_bufX[i] = htonl (packet_bufX[i]); | ||||
} | } | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #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 | // encode midi events from port to packet | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_up; | 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; | uint16_t *packet_bufX = (uint16_t *)packet_payload; | ||||
if( !packet_payload ) | if( !packet_payload ) | ||||
return; | |||||
return; | |||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
int i; | int i; | ||||
//uint32_t val; | //uint32_t val; | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
@@ -1085,16 +1026,13 @@ render_payload_to_jack_ports_16bit (void *packet_payload, jack_nframes_t net_per | |||||
#endif | #endif | ||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
// audio port, resample if necessary | // audio port, resample if necessary | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
if (net_period_down != nframes) | |||||
{ | |||||
if (net_period_down != nframes) { | |||||
SRC_STATE *src_state = src_node->data; | 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; | 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_set_ratio (src_state, src.src_ratio); | ||||
src_process (src_state, &src); | src_process (src_state, &src); | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #endif | ||||
for (i = 0; i < net_period_down; i++) | for (i = 0; i < net_period_down; i++) | ||||
buf[i] = ((float) ntohs (packet_bufX[i])) / 32768.0 - 1.0; | 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 | // midi port, decode midi events | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_down / 2; | 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; | uint16_t *packet_bufX = (uint16_t *)packet_payload; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
SRC_DATA src; | SRC_DATA src; | ||||
#endif | #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); | jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | ||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
// audio port, resample if necessary | // audio port, resample if necessary | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
if (net_period_up != nframes) | |||||
{ | |||||
if (net_period_up != nframes) { | |||||
SRC_STATE *src_state = src_node->data; | SRC_STATE *src_state = src_node->data; | ||||
float *floatbuf = alloca (sizeof(float) * net_period_up); | 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_set_ratio (src_state, src.src_ratio); | ||||
src_process (src_state, &src); | 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))); | packet_bufX[i] = htons (((uint16_t)((floatbuf[i] + 1.0) * 32767.0))); | ||||
} | } | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #endif | ||||
for (i = 0; i < net_period_up; i++) | for (i = 0; i < net_period_up; i++) | ||||
packet_bufX[i] = htons(((uint16_t)((buf[i] + 1.0) * 32767.0))); | 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 | // encode midi events from port to packet | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_up / 2; | 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) | if (!packet_payload) | ||||
return; | return; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
int i; | int i; | ||||
//uint32_t val; | //uint32_t val; | ||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
@@ -1231,12 +1158,10 @@ render_payload_to_jack_ports_8bit (void *packet_payload, jack_nframes_t net_peri | |||||
#endif | #endif | ||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio(porttype)) | |||||
{ | |||||
if (jack_port_is_audio(porttype)) { | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
// audio port, resample if necessary | // audio port, resample if necessary | ||||
if (net_period_down != nframes) | |||||
{ | |||||
if (net_period_down != nframes) { | |||||
SRC_STATE *src_state = src_node->data; | 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) packet_bufX[i]) / 127.0; | 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_set_ratio (src_state, src.src_ratio); | ||||
src_process (src_state, &src); | src_process (src_state, &src); | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #endif | ||||
for (i = 0; i < net_period_down; i++) | for (i = 0; i < net_period_down; i++) | ||||
buf[i] = ((float) packet_bufX[i]) / 127.0; | 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 | // midi port, decode midi events | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_down / 2; | 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; | int8_t *packet_bufX = (int8_t *)packet_payload; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
SRC_DATA src; | SRC_DATA src; | ||||
#endif | #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); | jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | ||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
#if HAVE_SAMPLERATE | #if HAVE_SAMPLERATE | ||||
// audio port, resample if necessary | // audio port, resample if necessary | ||||
if (net_period_up != nframes) | |||||
{ | |||||
if (net_period_up != nframes) { | |||||
SRC_STATE *src_state = src_node->data; | 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++) | for (i = 0; i < net_period_up; i++) | ||||
packet_bufX[i] = floatbuf[i] * 127.0; | packet_bufX[i] = floatbuf[i] * 127.0; | ||||
src_node = jack_slist_next (src_node); | src_node = jack_slist_next (src_node); | ||||
} | |||||
else | |||||
} else | |||||
#endif | #endif | ||||
for (i = 0; i < net_period_up; i++) | for (i = 0; i < net_period_up; i++) | ||||
packet_bufX[i] = buf[i] * 127.0; | 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 | // encode midi events from port to packet | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_up / 4; | 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; | unsigned char *packet_bufX = (unsigned char *)packet_payload; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
jack_port_t *port = (jack_port_t *) node->data; | jack_port_t *port = (jack_port_t *) node->data; | ||||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | ||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
// audio port, decode celt data. | // audio port, decode celt data. | ||||
CELTDecoder *decoder = src_node->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 ) | if( !packet_payload ) | ||||
celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); | celt_decode_float( decoder, NULL, net_period_down, buf, nframes ); | ||||
else | else | ||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); | celt_decode_float( decoder, packet_bufX, net_period_down, buf, nframes ); | ||||
#else | |||||
#else | |||||
if( !packet_payload ) | if( !packet_payload ) | ||||
celt_decode_float( decoder, NULL, net_period_down, buf ); | celt_decode_float( decoder, NULL, net_period_down, buf ); | ||||
else | else | ||||
celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | celt_decode_float( decoder, packet_bufX, net_period_down, buf ); | ||||
#endif | |||||
#endif | |||||
src_node = jack_slist_next (src_node); | 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 | // midi port, decode midi events | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_down / 2; | 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; | unsigned char *packet_bufX = (unsigned char *)packet_payload; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
jack_port_t *port = (jack_port_t *) node->data; | jack_port_t *port = (jack_port_t *) node->data; | ||||
jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | jack_default_audio_sample_t* buf = jack_port_get_buffer (port, nframes); | ||||
const char *porttype = jack_port_type (port); | const char *porttype = jack_port_type (port); | ||||
if (jack_port_is_audio (porttype)) | |||||
{ | |||||
if (jack_port_is_audio (porttype)) { | |||||
// audio port, encode celt data. | // 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 | #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 | #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 | #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 | // encode midi events from port to packet | ||||
// convert the data buffer to a standard format (uint32_t based) | // convert the data buffer to a standard format (uint32_t based) | ||||
unsigned int buffer_size_uint32 = net_period_up / 2; | unsigned int buffer_size_uint32 = net_period_up / 2; | ||||
@@ -28,8 +28,8 @@ | |||||
#define __JACK_NET_PACKET_H__ | #define __JACK_NET_PACKET_H__ | ||||
#ifdef __cplusplus | #ifdef __cplusplus | ||||
extern "C" | |||||
{ | |||||
extern "C" | |||||
{ | |||||
#endif | #endif | ||||
#include <jack/jack.h> | #include <jack/jack.h> | ||||
@@ -42,115 +42,106 @@ | |||||
#define CELT_MODE 1000 // Magic bitdepth value that indicates CELT compression | #define CELT_MODE 1000 // Magic bitdepth value that indicates CELT compression | ||||
#define MASTER_FREEWHEELS 0x80000000 | #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 | #ifdef __cplusplus | ||||
} | |||||
} | |||||
#endif | #endif | ||||
#endif | #endif | ||||
@@ -92,7 +92,7 @@ int state_netxruns = 0; | |||||
int state_currentframe = 0; | int state_currentframe = 0; | ||||
int state_recv_packet_queue_time = 0; | int state_recv_packet_queue_time = 0; | ||||
int quit=0; | |||||
int quit = 0; | |||||
int outsockfd; | int outsockfd; | ||||
@@ -128,43 +128,39 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||||
capture_ports = NULL; | capture_ports = NULL; | ||||
/* Allocate audio capture channels */ | /* 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); | snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); | ||||
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | 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); | printf( "jack_netsource: cannot register %s port\n", buf); | ||||
break; | 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 ); | 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 ) ); | 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 ); | 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 ) ); | 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 ); | 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 ) ); | capture_srcs = jack_slist_append(capture_srcs, celt_decoder_create( celt_mode ) ); | ||||
#endif | |||||
#endif | |||||
#endif | |||||
#endif | |||||
} else { | } 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); | capture_ports = jack_slist_append (capture_ports, port); | ||||
} | } | ||||
/* Allocate midi capture channels */ | /* 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); | snprintf (buf, sizeof (buf) - 1, "capture_%u", chn + 1); | ||||
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); | 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); | printf ("jack_netsource: cannot register %s port\n", buf); | ||||
break; | break; | ||||
} | } | ||||
@@ -174,43 +170,39 @@ alloc_ports (int n_capture_audio, int n_playback_audio, int n_capture_midi, int | |||||
/* Allocate audio playback channels */ | /* Allocate audio playback channels */ | ||||
port_flags = JackPortIsInput; | port_flags = JackPortIsInput; | ||||
playback_ports = NULL; | 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); | snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); | ||||
port = jack_port_register (client, buf, JACK_DEFAULT_AUDIO_TYPE, port_flags, 0); | 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); | printf ("jack_netsource: cannot register %s port\n", buf); | ||||
break; | break; | ||||
} | } | ||||
if( bitdepth == 1000 ) { | 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 ); | 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 ) ); | 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 ); | 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 ) ); | 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 ); | 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 ) ); | playback_srcs = jack_slist_append(playback_srcs, celt_encoder_create( celt_mode ) ); | ||||
#endif | |||||
#endif | |||||
#endif | |||||
#endif | |||||
} else { | } else { | ||||
#if HAVE_SAMPLERATE | |||||
#if HAVE_SAMPLERATE | |||||
playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); | playback_srcs = jack_slist_append (playback_srcs, src_new (SRC_LINEAR, 1, NULL)); | ||||
#endif | |||||
#endif | |||||
} | } | ||||
playback_ports = jack_slist_append (playback_ports, port); | playback_ports = jack_slist_append (playback_ports, port); | ||||
} | } | ||||
/* Allocate midi playback channels */ | /* 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); | snprintf (buf, sizeof (buf) - 1, "playback_%u", chn + 1); | ||||
port = jack_port_register (client, buf, JACK_DEFAULT_MIDI_TYPE, port_flags, 0); | 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); | printf ("jack_netsource: cannot register %s port\n", buf); | ||||
break; | break; | ||||
} | } | ||||
@@ -237,8 +229,7 @@ sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) | |||||
retval = 0; | retval = 0; | ||||
} | } | ||||
else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) | |||||
{ | |||||
else if (state == JackTransportStarting && last_transport_state != JackTransportStarting) { | |||||
retval = 0; | retval = 0; | ||||
latency_count = latency - 1; | latency_count = latency - 1; | ||||
} | } | ||||
@@ -250,10 +241,10 @@ sync_cb (jack_transport_state_t state, jack_position_t *pos, void *arg) | |||||
void | void | ||||
freewheel_cb (int starting, void *arg) | 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. | * The process callback for this JACK application. | ||||
* It is called by JACK at the appropriate times. | * 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; | jack_time_t packet_recv_timestamp; | ||||
if( bitdepth == 1000 ) | 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 | else | ||||
net_period = (float) nframes / (float) factor; | net_period = (float) nframes / (float) factor; | ||||
@@ -299,47 +290,45 @@ process (jack_nframes_t nframes, void *arg) | |||||
*/ | */ | ||||
if( latency == 0 ) { | 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; | input_fd = outsockfd; | ||||
// for latency == 0 we can poll. | // 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. | // Now loop until we get the right packet. | ||||
while(1) { | while(1) { | ||||
jack_nframes_t got_frame; | jack_nframes_t got_frame; | ||||
if ( ! netjack_poll_deadline( input_fd, deadline ) ) | if ( ! netjack_poll_deadline( input_fd, deadline ) ) | ||||
break; | |||||
break; | |||||
packet_cache_drain_socket(packcache, input_fd); | packet_cache_drain_socket(packcache, input_fd); | ||||
if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame )) | 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 { | } else { | ||||
// normally: | // 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 ); | 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 | /* First alternative : we received what we expected. Render the data | ||||
* to the JACK ports so it can be played. */ | * 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; | uint32_t *packet_buf_rx = rx_packet_ptr; | ||||
jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx; | 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); | 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; | deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency; | ||||
//printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset ); | //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); | //printf("Frame %d \tRecovered from dropouts\n", framecnt); | ||||
cont_miss = 0; | cont_miss = 0; | ||||
} | } | ||||
render_payload_to_jack_ports (bitdepth, packet_bufX, net_period, | 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_currentframe = framecnt; | ||||
state_recv_packet_queue_time = recv_time_offset; | 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 | /* Second alternative : we've received something that's not | ||||
* as big as expected or we missed a packet. We render silence | * as big as expected or we missed a packet. We render silence | ||||
* to the ouput ports */ | * to the ouput ports */ | ||||
else | |||||
{ | |||||
else { | |||||
jack_nframes_t latency_estimate; | jack_nframes_t latency_estimate; | ||||
if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) | if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) ) | ||||
//if( (state_latency == 0) || (latency_estimate < state_latency) ) | //if( (state_latency == 0) || (latency_estimate < state_latency) ) | ||||
@@ -423,8 +409,7 @@ process (jack_nframes_t nframes, void *arg) | |||||
cont_miss += 1; | cont_miss += 1; | ||||
chn = 0; | chn = 0; | ||||
node = capture_ports; | node = capture_ports; | ||||
while (node != NULL) | |||||
{ | |||||
while (node != NULL) { | |||||
port = (jack_port_t *) node->data; | port = (jack_port_t *) node->data; | ||||
buf = jack_port_get_buffer (port, nframes); | buf = jack_port_get_buffer (port, nframes); | ||||
porttype = jack_port_type (port); | porttype = jack_port_type (port); | ||||
@@ -438,47 +423,45 @@ process (jack_nframes_t nframes, void *arg) | |||||
} | } | ||||
} | } | ||||
if (latency != 0) { | 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++; | 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_family = AF_INET ; | ||||
name->sin_port = htons (port); | name->sin_port = htons (port); | ||||
if (hostname) | |||||
{ | |||||
if (hostname) { | |||||
struct hostent *hostinfo = gethostbyname (hostname); | struct hostent *hostinfo = gethostbyname (hostname); | ||||
if (hostinfo == NULL) { | if (hostinfo == NULL) { | ||||
fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname); | fprintf (stderr, "init_sockaddr_in: unknown host: %s.\n", hostname); | ||||
fflush( stderr ); | |||||
} | |||||
fflush( stderr ); | |||||
} | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
name->sin_addr.s_addr = inet_addr( hostname ); | name->sin_addr.s_addr = inet_addr( hostname ); | ||||
#else | #else | ||||
name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; | name->sin_addr = *(struct in_addr *) hostinfo->h_addr ; | ||||
#endif | #endif | ||||
} | |||||
else | |||||
} else | |||||
name->sin_addr.s_addr = htonl (INADDR_ANY) ; | 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 | void | ||||
printUsage () | 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 | void | ||||
sigterm_handler( int signal ) | sigterm_handler( int signal ) | ||||
{ | { | ||||
quit = 1; | |||||
quit = 1; | |||||
} | } | ||||
int | int | ||||
@@ -561,7 +542,7 @@ main (int argc, char *argv[]) | |||||
jack_status_t status; | jack_status_t status; | ||||
#ifdef WIN32 | #ifdef WIN32 | ||||
WSADATA wsa; | WSADATA wsa; | ||||
int rc = WSAStartup(MAKEWORD(2,0),&wsa); | |||||
int rc = WSAStartup(MAKEWORD(2, 0), &wsa); | |||||
#endif | #endif | ||||
/* Torben's famous state variables, aka "the reporting API" ! */ | /* Torben's famous state variables, aka "the reporting API" ! */ | ||||
/* heh ? these are only the copies of them ;) */ | /* heh ? these are only the copies of them ;) */ | ||||
@@ -570,10 +551,9 @@ main (int argc, char *argv[]) | |||||
/* Argument parsing stuff */ | /* Argument parsing stuff */ | ||||
extern char *optarg; | extern char *optarg; | ||||
extern int optind, optopt; | extern int optind, optopt; | ||||
int errflg=0, c; | |||||
int errflg = 0, c; | |||||
if (argc < 3) | |||||
{ | |||||
if (argc < 3) { | |||||
printUsage (); | printUsage (); | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -583,17 +563,15 @@ main (int argc, char *argv[]) | |||||
sprintf(client_name, "netjack"); | sprintf(client_name, "netjack"); | ||||
sprintf(peer_ip, "localhost"); | 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': | case 'h': | ||||
printUsage(); | printUsage(); | ||||
exit (0); | exit (0); | ||||
break; | break; | ||||
case 'H': | case 'H': | ||||
free(peer_ip); | 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); | strcpy (peer_ip, optarg); | ||||
break; | break; | ||||
case 'o': | case 'o': | ||||
@@ -647,11 +625,11 @@ main (int argc, char *argv[]) | |||||
break; | break; | ||||
case 'N': | case 'N': | ||||
free(client_name); | 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); | strcpy (client_name, optarg); | ||||
break; | break; | ||||
case 's': | case 's': | ||||
server_name = (char *) malloc (sizeof (char) * strlen (optarg)+1); | |||||
server_name = (char *) malloc (sizeof (char) * strlen (optarg) + 1); | |||||
strcpy (server_name, optarg); | strcpy (server_name, optarg); | ||||
options |= JackServerName; | options |= JackServerName; | ||||
break; | break; | ||||
@@ -664,8 +642,7 @@ main (int argc, char *argv[]) | |||||
errflg++; | errflg++; | ||||
} | } | ||||
} | } | ||||
if (errflg) | |||||
{ | |||||
if (errflg) { | |||||
printUsage (); | printUsage (); | ||||
exit (2); | exit (2); | ||||
} | } | ||||
@@ -688,8 +665,7 @@ main (int argc, char *argv[]) | |||||
fprintf (stderr, "bind failure\n" ); | fprintf (stderr, "bind failure\n" ); | ||||
} | } | ||||
} | } | ||||
if (reply_port) | |||||
{ | |||||
if (reply_port) { | |||||
init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); | init_sockaddr_in ((struct sockaddr_in *) &bindaddr, NULL, reply_port); | ||||
if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { | if( bind (insockfd, &bindaddr, sizeof (bindaddr)) ) { | ||||
fprintf (stderr, "bind failure\n" ); | fprintf (stderr, "bind failure\n" ); | ||||
@@ -698,10 +674,9 @@ main (int argc, char *argv[]) | |||||
/* try to become a client of the JACK server */ | /* try to become a client of the JACK server */ | ||||
client = jack_client_open (client_name, options, &status, server_name); | 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" | 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; | 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); | alloc_ports (capture_channels_audio, playback_channels_audio, capture_channels_midi, playback_channels_midi); | ||||
if( bitdepth == 1000 ) | 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 | else | ||||
net_period = ceilf((float) jack_get_buffer_size (client) / (float) factor); | 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); | packcache = packet_cache_new (latency + 50, rx_bufsize, mtu); | ||||
/* tell the JACK server that we are ready to roll */ | /* tell the JACK server that we are ready to roll */ | ||||
if (jack_activate (client)) | |||||
{ | |||||
if (jack_activate (client)) { | |||||
fprintf (stderr, "Cannot activate client"); | fprintf (stderr, "Cannot activate client"); | ||||
return 1; | return 1; | ||||
} | } | ||||
@@ -737,49 +711,41 @@ main (int argc, char *argv[]) | |||||
statecopy_latency = state_latency; | statecopy_latency = state_latency; | ||||
statecopy_netxruns = state_netxruns; | statecopy_netxruns = state_netxruns; | ||||
while ( !quit ) | |||||
{ | |||||
while ( !quit ) { | |||||
#ifdef WIN32 | #ifdef WIN32 | ||||
Sleep (1000); | Sleep (1000); | ||||
#else | #else | ||||
sleep(1); | sleep(1); | ||||
#endif | #endif | ||||
if (statecopy_connected != state_connected) | |||||
{ | |||||
if (statecopy_connected != state_connected) { | |||||
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 | state_netxruns = 1; // We want to reset the netxrun count on each new connection | ||||
printf ("Connected :-)\n"); | printf ("Connected :-)\n"); | ||||
} | |||||
else | |||||
} else | |||||
printf ("Not Connected\n"); | 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 "JackWinThread.h" | ||||
#include "JackError.h" | #include "JackError.h" | ||||
#include "JackTime.h" | #include "JackTime.h" | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <stdio.h> | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -55,7 +55,7 @@ DWORD WINAPI JackWinThread::ThreadHandler(void* arg) | |||||
} | } | ||||
JackWinThread::JackWinThread(JackRunnableInterface* runnable) | JackWinThread::JackWinThread(JackRunnableInterface* runnable) | ||||
: JackThreadInterface(runnable, 0, false, 0) | |||||
: JackMMCSS(), JackThreadInterface(runnable, 0, false, 0) | |||||
{ | { | ||||
fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | fEvent = CreateEvent(NULL, FALSE, FALSE, NULL); | ||||
fThread = (HANDLE)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); | 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; | return 0; | ||||
} else { | } 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) | 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; | return 0; | ||||
} else { | } else { | ||||
jack_error("Cannot set thread priority = %d", GetLastError()); | jack_error("Cannot set thread priority = %d", GetLastError()); | ||||
@@ -17,12 +17,11 @@ | |||||
*/ | */ | ||||
#ifndef __JackWinThread__ | #ifndef __JackWinThread__ | ||||
#define __JackWinThread__ | #define __JackWinThread__ | ||||
#include "JackThread.h" | #include "JackThread.h" | ||||
#include "JackMMCSS.h" | |||||
#include "JackCompilerDeps.h" | #include "JackCompilerDeps.h" | ||||
#include "JackSystemDeps.h" | #include "JackSystemDeps.h" | ||||
#include <windows.h> | #include <windows.h> | ||||
@@ -36,7 +35,7 @@ typedef DWORD (WINAPI *ThreadCallback)(void *arg); | |||||
\brief Windows threads. | \brief Windows threads. | ||||
*/ | */ | ||||
class SERVER_EXPORT JackWinThread : public detail::JackThreadInterface | |||||
class SERVER_EXPORT JackWinThread : public JackMMCSS, public detail::JackThreadInterface | |||||
{ | { | ||||
private: | private: | ||||
@@ -1,7 +1,7 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | <?xml version="1.0" encoding="UTF-8" standalone="yes" ?> | ||||
<CodeBlocks_workspace_file> | <CodeBlocks_workspace_file> | ||||
<Workspace title="jack"> | <Workspace title="jack"> | ||||
<Project filename="libjackserver.cbp" /> | |||||
<Project filename="libjackserver.cbp" active="1" /> | |||||
<Project filename="jack_portaudio.cbp" /> | <Project filename="jack_portaudio.cbp" /> | ||||
<Project filename="jack_netdriver.cbp" /> | <Project filename="jack_netdriver.cbp" /> | ||||
<Project filename="jack_netonedriver.cbp" /> | <Project filename="jack_netonedriver.cbp" /> | ||||
@@ -18,7 +18,7 @@ | |||||
<Project filename="jack_disconnect.cbp" /> | <Project filename="jack_disconnect.cbp" /> | ||||
<Project filename="jack_test.cbp" /> | <Project filename="jack_test.cbp" /> | ||||
<Project filename="multiple_metro.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="jack_loopback.cbp" /> | ||||
<Project filename="jackd.cbp" /> | <Project filename="jackd.cbp" /> | ||||
<Project filename="jack_midi_latency_test.cbp" /> | <Project filename="jack_midi_latency_test.cbp" /> | ||||
@@ -133,7 +133,7 @@ | |||||
<Add library="odbccp32" /> | <Add library="odbccp32" /> | ||||
</Linker> | </Linker> | ||||
</Target> | </Target> | ||||
<Target title="Win32 Release 32bits"> | |||||
<Target title="Win32 Release 32bits"> | |||||
<Option output="Release\bin\libjack" prefix_auto="1" extension_auto="1" /> | <Option output="Release\bin\libjack" prefix_auto="1" extension_auto="1" /> | ||||
<Option object_output="Release" /> | <Option object_output="Release" /> | ||||
<Option type="3" /> | <Option type="3" /> | ||||
@@ -143,7 +143,7 @@ | |||||
<Compiler> | <Compiler> | ||||
<Add option="-O2" /> | <Add option="-O2" /> | ||||
<Add option="-Wall" /> | <Add option="-Wall" /> | ||||
<Add option="-m32" /> | |||||
<Add option="-m32" /> | |||||
<Add option="-DWIN32" /> | <Add option="-DWIN32" /> | ||||
<Add option="-DNDEBUG" /> | <Add option="-DNDEBUG" /> | ||||
<Add option="-D_WINDOWS" /> | <Add option="-D_WINDOWS" /> | ||||
@@ -162,7 +162,7 @@ | |||||
<Add directory="tre-0.8.0\lib" /> | <Add directory="tre-0.8.0\lib" /> | ||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add option="-m32" /> | |||||
<Add option="-m32" /> | |||||
<Add library="kernel32" /> | <Add library="kernel32" /> | ||||
<Add library="user32" /> | <Add library="user32" /> | ||||
<Add library="gdi32" /> | <Add library="gdi32" /> | ||||
@@ -176,7 +176,7 @@ | |||||
<Add library="odbc32" /> | <Add library="odbc32" /> | ||||
<Add library="odbccp32" /> | <Add library="odbccp32" /> | ||||
</Linker> | </Linker> | ||||
<ExtraCommands> | |||||
<ExtraCommands> | |||||
<Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" /> | <Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" /> | ||||
</ExtraCommands> | </ExtraCommands> | ||||
</Target> | </Target> | ||||
@@ -190,7 +190,7 @@ | |||||
<Compiler> | <Compiler> | ||||
<Add option="-Wall" /> | <Add option="-Wall" /> | ||||
<Add option="-g" /> | <Add option="-g" /> | ||||
<Add option="-m32" /> | |||||
<Add option="-m32" /> | |||||
<Add option="-DWIN32" /> | <Add option="-DWIN32" /> | ||||
<Add option="-D_DEBUG" /> | <Add option="-D_DEBUG" /> | ||||
<Add option="-D_WINDOWS" /> | <Add option="-D_WINDOWS" /> | ||||
@@ -209,7 +209,7 @@ | |||||
<Add directory="tre-0.8.0\lib" /> | <Add directory="tre-0.8.0\lib" /> | ||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add option="-m32" /> | |||||
<Add option="-m32" /> | |||||
<Add library="kernel32" /> | <Add library="kernel32" /> | ||||
<Add library="user32" /> | <Add library="user32" /> | ||||
<Add library="gdi32" /> | <Add library="gdi32" /> | ||||
@@ -223,7 +223,7 @@ | |||||
<Add library="odbc32" /> | <Add library="odbc32" /> | ||||
<Add library="odbccp32" /> | <Add library="odbccp32" /> | ||||
</Linker> | </Linker> | ||||
<ExtraCommands> | |||||
<ExtraCommands> | |||||
<Add before="windres -F pe-i386 -O coff -o Debug/libjack.res libjack.rc" /> | <Add before="windres -F pe-i386 -O coff -o Debug/libjack.res libjack.rc" /> | ||||
</ExtraCommands> | </ExtraCommands> | ||||
</Target> | </Target> | ||||
@@ -237,7 +237,7 @@ | |||||
<Compiler> | <Compiler> | ||||
<Add option="-O2" /> | <Add option="-O2" /> | ||||
<Add option="-Wall" /> | <Add option="-Wall" /> | ||||
<Add option="-m32" /> | |||||
<Add option="-m32" /> | |||||
<Add option="-DWIN32" /> | <Add option="-DWIN32" /> | ||||
<Add option="-DNDEBUG" /> | <Add option="-DNDEBUG" /> | ||||
<Add option="-D_WINDOWS" /> | <Add option="-D_WINDOWS" /> | ||||
@@ -257,7 +257,7 @@ | |||||
<Add directory="tre-0.8.0\lib" /> | <Add directory="tre-0.8.0\lib" /> | ||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add option="-m32" /> | |||||
<Add option="-m32" /> | |||||
<Add library="kernel32" /> | <Add library="kernel32" /> | ||||
<Add library="user32" /> | <Add library="user32" /> | ||||
<Add library="gdi32" /> | <Add library="gdi32" /> | ||||
@@ -271,7 +271,7 @@ | |||||
<Add library="odbc32" /> | <Add library="odbc32" /> | ||||
<Add library="odbccp32" /> | <Add library="odbccp32" /> | ||||
</Linker> | </Linker> | ||||
<ExtraCommands> | |||||
<ExtraCommands> | |||||
<Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" /> | <Add before="windres -F pe-i386 -O coff -o Release/libjack.res libjack.rc" /> | ||||
</ExtraCommands> | </ExtraCommands> | ||||
</Target> | </Target> | ||||
@@ -322,6 +322,7 @@ | |||||
<Unit filename="..\common\shm.c"> | <Unit filename="..\common\shm.c"> | ||||
<Option compilerVar="CC" /> | <Option compilerVar="CC" /> | ||||
</Unit> | </Unit> | ||||
<Unit filename="JackMMCSS.cpp" /> | |||||
<Unit filename="JackWinNamedPipe.cpp" /> | <Unit filename="JackWinNamedPipe.cpp" /> | ||||
<Unit filename="JackWinNamedPipeClientChannel.cpp" /> | <Unit filename="JackWinNamedPipeClientChannel.cpp" /> | ||||
<Unit filename="JackWinProcessSync.cpp" /> | <Unit filename="JackWinProcessSync.cpp" /> | ||||
@@ -32,8 +32,8 @@ | |||||
<Add directory="..\common" /> | <Add directory="..\common" /> | ||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add directory="Release64\bin" /> | |||||
<Add library="libsamplerate_x86_64" /> | <Add library="libsamplerate_x86_64" /> | ||||
<Add directory="Release64\bin" /> | |||||
</Linker> | </Linker> | ||||
</Target> | </Target> | ||||
<Target title="Win32 Debug 64bits"> | <Target title="Win32 Debug 64bits"> | ||||
@@ -62,8 +62,8 @@ | |||||
<Add directory="..\common" /> | <Add directory="..\common" /> | ||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add directory="Debug64\bin" /> | |||||
<Add library="libsamplerate_x86_64" /> | <Add library="libsamplerate_x86_64" /> | ||||
<Add directory="Debug64\bin" /> | |||||
</Linker> | </Linker> | ||||
</Target> | </Target> | ||||
<Target title="Win32 Profiling 64bits"> | <Target title="Win32 Profiling 64bits"> | ||||
@@ -93,8 +93,8 @@ | |||||
<Add directory="..\common" /> | <Add directory="..\common" /> | ||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add directory="Release64\bin" /> | |||||
<Add library="libsamplerate_x86_64" /> | <Add library="libsamplerate_x86_64" /> | ||||
<Add directory="Release64\bin" /> | |||||
</Linker> | </Linker> | ||||
</Target> | </Target> | ||||
<Target title="Win32 Release 32bits"> | <Target title="Win32 Release 32bits"> | ||||
@@ -125,8 +125,8 @@ | |||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add option="-m32" /> | <Add option="-m32" /> | ||||
<Add directory="Release\bin" /> | |||||
<Add library="libsamplerate_x86" /> | <Add library="libsamplerate_x86" /> | ||||
<Add directory="Release\bin" /> | |||||
</Linker> | </Linker> | ||||
<ExtraCommands> | <ExtraCommands> | ||||
<Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" /> | <Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" /> | ||||
@@ -160,8 +160,8 @@ | |||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add option="-m32" /> | <Add option="-m32" /> | ||||
<Add directory="Debug\bin" /> | |||||
<Add library="libsamplerate_x86" /> | <Add library="libsamplerate_x86" /> | ||||
<Add directory="Debug\bin" /> | |||||
</Linker> | </Linker> | ||||
<ExtraCommands> | <ExtraCommands> | ||||
<Add before="windres -F pe-i386 -O coff -o Debug/libjacknet.res libjacknet.rc" /> | <Add before="windres -F pe-i386 -O coff -o Debug/libjacknet.res libjacknet.rc" /> | ||||
@@ -196,8 +196,8 @@ | |||||
</Compiler> | </Compiler> | ||||
<Linker> | <Linker> | ||||
<Add option="-m32" /> | <Add option="-m32" /> | ||||
<Add directory="Release\bin" /> | |||||
<Add library="libsamplerate_x86" /> | <Add library="libsamplerate_x86" /> | ||||
<Add directory="Release\bin" /> | |||||
</Linker> | </Linker> | ||||
<ExtraCommands> | <ExtraCommands> | ||||
<Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" /> | <Add before="windres -F pe-i386 -O coff -o Release/libjacknet.res libjacknet.rc" /> | ||||
@@ -235,6 +235,7 @@ | |||||
<Unit filename="..\common\ringbuffer.c"> | <Unit filename="..\common\ringbuffer.c"> | ||||
<Option compilerVar="CC" /> | <Option compilerVar="CC" /> | ||||
</Unit> | </Unit> | ||||
<Unit filename="JackMMCSS.cpp" /> | |||||
<Unit filename="JackNetWinSocket.cpp" /> | <Unit filename="JackNetWinSocket.cpp" /> | ||||
<Unit filename="JackWinThread.cpp" /> | <Unit filename="JackWinThread.cpp" /> | ||||
<Unit filename="JackWinTime.c"> | <Unit filename="JackWinTime.c"> | ||||
@@ -289,6 +289,7 @@ | |||||
<Unit filename="..\common\shm.c"> | <Unit filename="..\common\shm.c"> | ||||
<Option compilerVar="CC" /> | <Option compilerVar="CC" /> | ||||
</Unit> | </Unit> | ||||
<Unit filename="JackMMCSS.cpp" /> | |||||
<Unit filename="JackNetWinSocket.cpp" /> | <Unit filename="JackNetWinSocket.cpp" /> | ||||
<Unit filename="JackWinNamedPipe.cpp" /> | <Unit filename="JackWinNamedPipe.cpp" /> | ||||
<Unit filename="JackWinNamedPipeClientChannel.cpp" /> | <Unit filename="JackWinNamedPipeClientChannel.cpp" /> | ||||
@@ -41,6 +41,8 @@ namespace Jack | |||||
driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer; | driver->fInputBuffer = (jack_default_audio_sample_t**)inputBuffer; | ||||
driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer; | driver->fOutputBuffer = (jack_default_audio_sample_t**)outputBuffer; | ||||
MMCSSAcquireRealTime(GetCurrentThread()); | |||||
if (statusFlags) { | if (statusFlags) { | ||||
if (statusFlags & paOutputUnderflow) | if (statusFlags & paOutputUnderflow) | ||||
jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | jack_error("JackPortAudioDriver::Render paOutputUnderflow"); | ||||
@@ -22,6 +22,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackAudioDriver.h" | #include "JackAudioDriver.h" | ||||
#include "JackPortAudioDevices.h" | #include "JackPortAudioDevices.h" | ||||
#include "JackMMCSS.h" | |||||
namespace Jack | namespace Jack | ||||
{ | { | ||||
@@ -30,7 +31,7 @@ namespace Jack | |||||
\brief The PortAudio driver. | \brief The PortAudio driver. | ||||
*/ | */ | ||||
class JackPortAudioDriver : public JackAudioDriver | |||||
class JackPortAudioDriver : public JackMMCSS, public JackAudioDriver | |||||
{ | { | ||||
private: | private: | ||||
@@ -54,7 +55,7 @@ class JackPortAudioDriver : public JackAudioDriver | |||||
public: | public: | ||||
JackPortAudioDriver(const char* name, const char* alias, JackLockedEngine* engine, JackSynchro* table, PortAudioDevices* pa_devices) | 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) | fInputDevice(paNoDevice), fOutputDevice(paNoDevice) | ||||
{ | { | ||||
fPaDevices = pa_devices; | fPaDevices = pa_devices; | ||||
@@ -60,7 +60,7 @@ JackWinMMEDriver::Attach() | |||||
// Inputs | // Inputs | ||||
for (int i = 0; i < fCaptureChannels; i++) { | for (int i = 0; i < fCaptureChannels; i++) { | ||||
JackWinMMEInputPort *input_port = input_ports[i]; | JackWinMMEInputPort *input_port = input_ports[i]; | ||||
name = input_port->GetName(); | |||||
name = input_port->GetName(); | |||||
if (fEngine->PortRegister(fClientControl.fRefNum, name, | if (fEngine->PortRegister(fClientControl.fRefNum, name, | ||||
JACK_DEFAULT_MIDI_TYPE, | JACK_DEFAULT_MIDI_TYPE, | ||||
CaptureDriverFlags, buffer_size, &index) < 0) { | CaptureDriverFlags, buffer_size, &index) < 0) { | ||||
@@ -22,7 +22,9 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |||||
#include "JackMidiUtil.h" | #include "JackMidiUtil.h" | ||||
#include "JackTime.h" | #include "JackTime.h" | ||||
#include "JackWinMMEOutputPort.h" | |||||
#include "JackWinMMEOutputPort.h" | |||||
#include "JackGlobals.h" | |||||
#include "JackEngineControl.h" | |||||
using Jack::JackWinMMEOutputPort; | using Jack::JackWinMMEOutputPort; | ||||
@@ -44,7 +46,8 @@ JackWinMMEOutputPort::HandleMessageEvent(HMIDIOUT handle, UINT message, | |||||
JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name, | JackWinMMEOutputPort::JackWinMMEOutputPort(const char *alias_name, | ||||
const char *client_name, | const char *client_name, | ||||
const char *driver_name, UINT index, | |||||
const char *driver_name, | |||||
UINT index, | |||||
size_t max_bytes, | size_t max_bytes, | ||||
size_t max_messages) | 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); | snprintf(name, sizeof(name) - 1, "%s:playback_%d", client_name, index + 1); | ||||
read_queue_ptr.release(); | read_queue_ptr.release(); | ||||
thread_queue_ptr.release(); | thread_queue_ptr.release(); | ||||
thread_ptr.release(); | |||||
thread_ptr.release(); | |||||
return; | return; | ||||
destroy_thread_queue_semaphore: | destroy_thread_queue_semaphore: | ||||
@@ -132,7 +135,7 @@ JackWinMMEOutputPort::Execute() | |||||
for (;;) { | for (;;) { | ||||
if (! Wait(thread_queue_semaphore)) { | if (! Wait(thread_queue_semaphore)) { | ||||
jack_log("JackWinMMEOutputPort::Execute BREAK"); | jack_log("JackWinMMEOutputPort::Execute BREAK"); | ||||
break; | break; | ||||
} | } | ||||
jack_midi_event_t *event = thread_queue->DequeueEvent(); | jack_midi_event_t *event = thread_queue->DequeueEvent(); | ||||
@@ -274,7 +277,7 @@ JackWinMMEOutputPort::Init() | |||||
set_threaded_log_function(); | set_threaded_log_function(); | ||||
// XX: Can more be done? Ideally, this thread should have the JACK server | // XX: Can more be done? Ideally, this thread should have the JACK server | ||||
// thread priority + 1. | // thread priority + 1. | ||||
if (thread->AcquireSelfRealTime()) { | |||||
if (thread->AcquireSelfRealTime(GetEngineControl()->fServerPriority)) { | |||||
jack_error("JackWinMMEOutputPort::Init - could not acquire realtime " | jack_error("JackWinMMEOutputPort::Init - could not acquire realtime " | ||||
"scheduling. Continuing anyway."); | "scheduling. Continuing anyway."); | ||||
} | } | ||||