Пример #1
0
int
netjack_poll_deadline (int sockfd, jack_time_t deadline)
{
    fd_set fds;
    FD_ZERO( &fds );
    FD_SET( sockfd, &fds );

    struct timeval timeout;
    while( 1 ) {
        jack_time_t now = jack_get_time();
        if( now >= deadline )
                return 0;

        int timeout_usecs = (deadline - now);
    //jack_error( "timeout = %d", timeout_usecs );
        timeout.tv_sec = 0;
        timeout.tv_usec = (timeout_usecs < 500) ? 500 : timeout_usecs;
        timeout.tv_usec = (timeout_usecs > 1000000) ? 500000 : timeout_usecs;

        int poll_err = select (0, &fds, NULL, NULL, &timeout);
        if( poll_err != 0 )
            return poll_err;
    }

    return 0;
}
Пример #2
0
// new poll using nanoseconds resolution and
// not waiting forever.
int
netjack_poll_deadline (int sockfd, jack_time_t deadline)
{
    struct pollfd fds;
    int poll_err = 0;
#if HAVE_PPOLL
    struct timespec timeout_spec = { 0, 0 };
#else
    int timeout;
#endif


    jack_time_t now = jack_get_time();
    if( now >= deadline )
	return 0;

    if( (deadline-now) >= 1000000 ) {
	    jack_error( "deadline more than 1 second in the future, trimming it." );
	    deadline = now+500000;
    }
#if HAVE_PPOLL
    timeout_spec.tv_nsec = (deadline - now) * 1000;
#else
    timeout = lrintf( (float)(deadline - now) / 1000.0 );
#endif


    fds.fd = sockfd;
    fds.events = POLLIN;

#if HAVE_PPOLL
    poll_err = ppoll (&fds, 1, &timeout_spec, NULL);
#else
    poll_err = poll (&fds, 1, timeout);
#endif

    if (poll_err == -1)
    {
        switch (errno)
        {
            case EBADF:
            jack_error ("Error %d: An invalid file descriptor was given in one of the sets", errno);
            break;
            case EFAULT:
            jack_error ("Error %d: The array given as argument was not contained in the calling program's address space", errno);
            break;
            case EINTR:
            jack_error ("Error %d: A signal occurred before any requested event", errno);
            break;
            case EINVAL:
            jack_error ("Error %d: The nfds value exceeds the RLIMIT_NOFILE value", errno);
            break;
            case ENOMEM:
            jack_error ("Error %d: There was no space to allocate file descriptor tables", errno);
            break;
        }
    }
    return poll_err;
}
Пример #3
0
void
packet_cache_drain_socket( packet_cache *pcache, int sockfd )
{
    char *rx_packet = alloca (pcache->mtu);
    jacknet_packet_header *pkthdr = (jacknet_packet_header *) rx_packet;
    int rcv_len;
    jack_nframes_t framecnt;
    cache_packet *cpack;
    struct sockaddr_in sender_address;
#ifdef WIN32
    size_t senderlen = sizeof( struct sockaddr_in );
    u_long parm = 1;
    ioctlsocket( sockfd, FIONBIO, &parm );
#else
    socklen_t senderlen = sizeof( struct sockaddr_in );
#endif
    while (1)
    {
#ifdef WIN32
        rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, 0,
			    (struct sockaddr*) &sender_address, &senderlen);
#else
        rcv_len = recvfrom (sockfd, rx_packet, pcache->mtu, MSG_DONTWAIT,
			    (struct sockaddr*) &sender_address, &senderlen);
#endif
        if (rcv_len < 0)
            return;

	if (pcache->master_address_valid) {
	    // Verify its from our master.
	    if (memcmp (&sender_address, &(pcache->master_address), senderlen) != 0)
		continue;
	} else {
	    // Setup this one as master
	    //printf( "setup master...\n" );
	    memcpy ( &(pcache->master_address), &sender_address, senderlen );
	    pcache->master_address_valid = 1;
	}

        framecnt = ntohl (pkthdr->framecnt);
	if( pcache->last_framecnt_retreived_valid && (framecnt <= pcache->last_framecnt_retreived ))
	    continue;

        cpack = packet_cache_get_packet (pcache, framecnt);
        cache_packet_add_fragment (cpack, rx_packet, rcv_len);
	cpack->recv_timestamp = jack_get_time();
    }
}
Пример #4
0
int jackProcessIn( jack_nframes_t nframes, void *arg )
{
  JackMidiData *jData = ( (Arguments *) arg )->jackData;
  RtMidiIn :: RtMidiInData *rtData = ( (Arguments *) arg )->rtMidiIn;
  jack_midi_event_t event;
  jack_time_t long long time;

  // Is port created?
  if ( jData->port == NULL ) return 0;
  void *buff = jack_port_get_buffer( jData->port, nframes );

  // We have midi events in buffer
  int evCount = jack_midi_get_event_count( buff );
  if ( evCount > 0 ) {
    RtMidiIn::MidiMessage message;
    message.bytes.clear();

    jack_midi_event_get( &event, buff, 0 );

    for (unsigned int i = 0; i < event.size; i++ )
      message.bytes.push_back( event.buffer[i] );

    // Compute the delta time.
    time = jack_get_time();
    if ( rtData->firstMessage == true )
      rtData->firstMessage = false;
    else
      message.timeStamp = ( time - jData->lastTime ) * 0.000001;

    jData->lastTime = time;

    if ( rtData->usingCallback && !rtData->continueSysex ) {
      RtMidiIn::RtMidiCallback callback = (RtMidiIn::RtMidiCallback) rtData->userCallback;
      callback( message.timeStamp, &message.bytes, rtData->userData );
    }
    else {
      // As long as we haven't reached our queue size limit, push the message.
      if ( rtData->queueLimit > rtData->queue.size() )
        rtData->queue.push( message );
      else
        std::cerr << "\nRtMidiIn: message queue limit reached!!\n\n";
    }
  }

  return 0;
}
Пример #5
0
/**
 * The process callback for this JACK application.
 * It is called by JACK at the appropriate times.
 */
int
process (jack_nframes_t nframes, void *arg)
{
    jack_nframes_t net_period;
    int rx_bufsize, tx_bufsize;

    jack_default_audio_sample_t *buf;
    jack_port_t *port;
    JSList *node;
    int chn;
    int size, i;
    const char *porttype;
    int input_fd;

    jack_position_t local_trans_pos;

    uint32_t *packet_buf_tx, *packet_bufX;
    uint32_t *rx_packet_ptr;
    jack_time_t packet_recv_timestamp;

    if( bitdepth == 1000 || bitdepth == 999)
        net_period = (factor * jack_get_buffer_size(client) * 1024 / jack_get_sample_rate(client) / 8) & (~1) ;
    else
        net_period = (float) nframes / (float) factor;

    rx_bufsize =  get_sample_size (bitdepth) * capture_channels * net_period + sizeof (jacknet_packet_header);
    tx_bufsize =  get_sample_size (bitdepth) * playback_channels * net_period + sizeof (jacknet_packet_header);

    /* Allocate a buffer where both In and Out Buffer will fit */
    packet_buf_tx = alloca (tx_bufsize);

    jacknet_packet_header *pkthdr_tx = (jacknet_packet_header *) packet_buf_tx;

    /*
     * for latency==0 we need to send out the packet before we wait on the reply.
     * but this introduces a cycle of latency, when netsource is connected to itself.
     * so we send out before read only in zero latency mode.
     *
     */

    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;
        }
    }

    /*
     * ok... now the RECEIVE code.
     *
     */


    if( reply_port )
        input_fd = insockfd;
    else
        input_fd = outsockfd;

    // for latency == 0 we can poll.
    if( (latency == 0) || (freewheeling != 0)  ) {
        jack_time_t deadline = jack_get_time() + 1000000 * jack_get_buffer_size(client) / jack_get_sample_rate(client);
        // Now loop until we get the right packet.
        while(1) {
            jack_nframes_t got_frame;
            if ( ! netjack_poll_deadline( input_fd, deadline ) )
                break;

            packet_cache_drain_socket(packcache, input_fd);

            if (packet_cache_get_next_available_framecnt( packcache, framecnt - latency, &got_frame ))
                if( got_frame == (framecnt - latency) )
                    break;
        }
    } else {
        // normally:
        // only drain socket.
        packet_cache_drain_socket(packcache, input_fd);
    }

    size = packet_cache_retreive_packet_pointer( packcache, framecnt - latency, (char**)&rx_packet_ptr, rx_bufsize, &packet_recv_timestamp );
    /* First alternative : we received what we expected. Render the data
     * to the JACK ports so it can be played. */
    if (size == rx_bufsize) {
        uint32_t *packet_buf_rx = rx_packet_ptr;
        jacknet_packet_header *pkthdr_rx = (jacknet_packet_header *) packet_buf_rx;
        packet_bufX = packet_buf_rx + sizeof (jacknet_packet_header) / sizeof (jack_default_audio_sample_t);
        // calculate how much time there would have been, if this packet was sent at the deadline.

        int recv_time_offset = (int) (jack_get_time() - packet_recv_timestamp);
        packet_header_ntoh (pkthdr_rx);
        deadline_goodness = recv_time_offset - (int)pkthdr_rx->latency;
        //printf( "deadline goodness = %d ---> off: %d\n", deadline_goodness, recv_time_offset );

        if (cont_miss) {
            //printf("Frame %d  \tRecovered from dropouts\n", framecnt);
            cont_miss = 0;
        }
        render_payload_to_jack_ports (bitdepth, packet_bufX, net_period,
                                      capture_ports, capture_srcs, nframes, dont_htonl_floats);

        state_currentframe = framecnt;
        state_recv_packet_queue_time = recv_time_offset;
        state_connected = 1;
        sync_state = pkthdr_rx->sync_state;
        packet_cache_release_packet( packcache, framecnt - latency );
    }
    /* Second alternative : we've received something that's not
     * as big as expected or we missed a packet. We render silence
     * to the ouput ports */
    else {
        jack_nframes_t latency_estimate;
        if( packet_cache_find_latency( packcache, framecnt, &latency_estimate ) )
            //if( (state_latency == 0) || (latency_estimate < state_latency) )
            state_latency = latency_estimate;

        // Set the counters up.
        state_currentframe = framecnt;
        //state_latency = framecnt - pkthdr->framecnt;
        state_netxruns += 1;

        //printf ("Frame %d  \tPacket missed or incomplete (expected: %d bytes, got: %d bytes)\n", framecnt, rx_bufsize, size);
        //printf ("Frame %d  \tPacket missed or incomplete\n", framecnt);
        cont_miss += 1;
        chn = 0;
        node = capture_ports;
        while (node != NULL) {
            port = (jack_port_t *) node->data;
            buf = jack_port_get_buffer (port, nframes);
            porttype = jack_port_type (port);
            if (strncmp (porttype, JACK_DEFAULT_AUDIO_TYPE, jack_port_type_size ()) == 0)
                for (i = 0; i < nframes; i++)
                    buf[i] = 0.0;
            else if (strncmp (porttype, JACK_DEFAULT_MIDI_TYPE, jack_port_type_size ()) == 0)
                jack_midi_clear_buffer (buf);
            node = jack_slist_next (node);
            chn++;
        }
    }
    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;
        }
    }

    framecnt++;
    return 0;
}
Пример #6
0
int netjack_wait( netjack_driver_state_t *netj )
{
    int we_have_the_expected_frame = 0;
    jack_nframes_t next_frame_avail;
    jack_time_t packet_recv_time_stamp;
    jacknet_packet_header *pkthdr;

    if( !netj->next_deadline_valid ) {
	    netj->next_deadline = jack_get_time() + netj->period_usecs;
	    netj->next_deadline_valid = 1;
    }

    // Increment expected frame here.

    if( netj->expected_framecnt_valid ) {
	netj->expected_framecnt += 1;
    } 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;
	}

    }

    //jack_log( "expect %d", netj->expected_framecnt );
    // Now check if required packet is already in the cache.
    // then poll (have deadline calculated)
    // then drain socket, rinse and repeat.
    while(1) {
	if( packet_cache_get_next_available_framecnt( netj->packcache, netj->expected_framecnt, &next_frame_avail) ) {
	    if( next_frame_avail == netj->expected_framecnt ) {
		we_have_the_expected_frame = 1;
		if( !netj->always_deadline )
			break;
	    }
	}
	if( ! netjack_poll_deadline( netj->sockfd, netj->next_deadline ) ) {
	    break;
	}

	packet_cache_drain_socket( netj->packcache, netj->sockfd );
    }

    // check if we know who to send our packets too.
    if (!netj->srcaddress_valid)
	if( netj->packcache->master_address_valid ) {
	    memcpy (&(netj->syncsource_address), &(netj->packcache->master_address), sizeof( struct sockaddr_in ) );
	    netj->srcaddress_valid = 1;
	}

    // XXX: switching mode unconditionally is stupid.
    //      if we were running free perhaps we like to behave differently
    //      ie. fastforward one packet etc.
    //      well... this is the first packet we see. hmm.... dunno ;S
    //      it works... so...
    netj->running_free = 0;

    //if( !we_have_the_expected_frame )
    //    jack_error( "netxrun... %d", netj->expected_framecnt );

    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 );
		}
	}
//	if( netj->next_deadline < (netj->period_usecs*70/100) ) {
//		jack_error( "master is forcing deadline_offset to below 70%% of period_usecs... increase latency setting on master" );
//		netj->deadline_offset = (netj->period_usecs*90/100);
//	}

	netj->next_deadline += netj->period_usecs;
    } 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 );
		    }
		}
	    }
	}
    }

    int retval = 0;

    if( !netj->packet_data_valid ) {
	netj->num_lost_packets += 1;
	if( netj->num_lost_packets == 1 )
	    retval = netj->period_usecs;
    } else {
	if( (netj->num_lost_packets>1) && !netj->running_free )
	    retval = (netj->num_lost_packets-1) * netj->period_usecs;

	netj->num_lost_packets = 0;
    }

    return retval;
}
Пример #7
0
static int _time(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj* const *objv) {
  _t *dp = (_t *)clientData;
  if (argc != 2) return fw_error_str(interp, "jack-client time");
  Tcl_SetObjResult(interp, Tcl_NewIntObj(jack_get_time()));
  return TCL_OK;
}