Beispiel #1
0
static PyObject* is_realtime(PyObject* self, PyObject* args)
{
    pyjack_client_t * client = self_or_global_client(self);
    if(client->pjc == NULL) {
        PyErr_SetString(JackNotConnectedError, "Jack connection has not yet been established.");
        return NULL;
    }

    int realtime = jack_is_realtime(client->pjc);
    return Py_BuildValue("i", realtime);
}
Beispiel #2
0
static
void *midi_thread(void *arg)
{
    midi_stream_t *str = arg;
    alsa_rawmidi_t *midi = str->owner;
    struct pollfd pfds[MAX_PFDS];
    int npfds;
    jack_time_t wait_nsec = 1000*1000*1000; // 1 sec
    process_midi_t proc;

    proc.midi = midi;
    proc.mode = str->mode;

    pfds[0].fd = str->wake_pipe[0];
    pfds[0].events = POLLIN|POLLERR|POLLNVAL;
    npfds = 1;

    if (jack_is_realtime(midi->client))
        set_threaded_log_function();

    //debug_log("midi_thread(%s): enter", str->name);

    while (midi->keep_walking) {
        int poll_timeout;
        int wait_nanosleep;
        int r=1, w=1; // read,write pos in pfds
        int rp=0, wp=0; // read, write pos in ports

        // sleep
        //if (wait_nsec != 1000*1000*1000) {
        //	debug_log("midi_thread(%s): ", str->name);
        //	assert (wait_nsec == 1000*1000*1000);
        //}
        poll_timeout = wait_nsec / (1000*1000);
        wait_nanosleep = wait_nsec % (1000*1000);
        if (wait_nanosleep > NANOSLEEP_RESOLUTION) {
            struct timespec ts;
            ts.tv_sec = 0;
            ts.tv_nsec = wait_nanosleep;
            clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);
        }
        int res = poll((struct pollfd*)&pfds, npfds, poll_timeout);
        //debug_log("midi_thread(%s): poll exit: %d", str->name, res);
        if (!midi->keep_walking)
            break;
        if (res < 0) {
            if (errno == EINTR)
                continue;
            error_log("midi_thread(%s) poll failed: %s", str->name, strerror(errno));
            break;
        }

        // check wakeup pipe
        if (pfds[0].revents & ~POLLIN)
            break;
        if (pfds[0].revents & POLLIN) {
            char c;
            read(pfds[0].fd, &c, 1);
        }

        // add new ports
        while (jack_ringbuffer_read_space(str->midi.new_ports) >= sizeof(midi_port_t*) && str->midi.nports < MAX_PORTS) {
            midi_port_t *port;
            jack_ringbuffer_read(str->midi.new_ports, (char*)&port, sizeof(port));
            str->midi.ports[str->midi.nports++] = port;
            debug_log("midi_thread(%s): added port %s", str->name, port->name);
        }

//		if (res == 0)
//			continue;

        // process ports
        proc.cur_time = 0; //jack_frame_time(midi->client);
        proc.next_time = NFRAMES_INF;

        for (rp = 0; rp < str->midi.nports; ++rp) {
            midi_port_t *port = str->midi.ports[rp];
            proc.cur_time = jack_frame_time(midi->client);
            proc.port = port;
            proc.rpfds = &pfds[r];
            proc.wpfds = &pfds[w];
            proc.max_pfds = MAX_PFDS - w;
            r += port->npfds;
            if (!(str->process_midi)(&proc)) {
                port->state = PORT_REMOVED_FROM_MIDI; // this signals to jack thread
                continue; // this effectively removes port from array
            }
            w += port->npfds;
            if (rp != wp)
                str->midi.ports[wp] = port;
            ++wp;
        }
        if (str->midi.nports != wp)
            debug_log("midi_%s: nports %d -> %d", str->name, str->midi.nports, wp);
        str->midi.nports = wp;
        if (npfds != w)
            debug_log("midi_%s: npfds %d -> %d", str->name, npfds, w);
        npfds = w;

        /*
         * Input : ports do not set proc.next_time.
         * Output: port sets proc.next_time ONLY if it does not have queued data.
         * So, zero timeout will not cause busy-looping.
         */
        if (proc.next_time < proc.cur_time) {
            debug_log("%s: late: next_time = %d, cur_time = %d", str->name, (int)proc.next_time, (int)proc.cur_time);
            wait_nsec = 0; // we are late
        } else if (proc.next_time != NFRAMES_INF) {
            jack_time_t wait_frames = proc.next_time - proc.cur_time;
            jack_nframes_t rate = jack_get_sample_rate(midi->client);
            wait_nsec = (wait_frames * (1000*1000*1000)) / rate;
            debug_log("midi_%s: timeout = %d", str->name, (int)wait_frames);
        } else
            wait_nsec = 1000*1000*1000;
        //debug_log("midi_thread(%s): wait_nsec = %lld", str->name, wait_nsec);
    }
    return NULL;
}
Beispiel #3
0
static
int alsa_rawmidi_start(alsa_midi_t *m)
{
    alsa_rawmidi_t *midi = (alsa_rawmidi_t*)m;
    int err;
    char c = 'q';
    if (midi->keep_walking == 1)
        return -EALREADY;

    midi->keep_walking = 1;
    if ((err = jack_client_create_thread(midi->client, &midi->in.thread, MIDI_THREAD_PRIO, jack_is_realtime(midi->client), midi_thread, &midi->in))) {
        midi->keep_walking = 0;
        return err;
    }
    if ((err = jack_client_create_thread(midi->client, &midi->out.thread, MIDI_THREAD_PRIO, jack_is_realtime(midi->client), midi_thread, &midi->out))) {
        midi->keep_walking = 0;
        write(midi->in.wake_pipe[1], &c, 1);
        pthread_join(midi->in.thread, NULL);
        return err;
    }
    if ((err = jack_client_create_thread(midi->client, &midi->scan.thread, 0, 0, scan_thread, midi))) {
        midi->keep_walking = 0;
        write(midi->in.wake_pipe[1], &c, 1);
        write(midi->out.wake_pipe[1], &c, 1);
        pthread_join(midi->in.thread, NULL);
        pthread_join(midi->out.thread, NULL);
        return err;
    }
    return 0;
}
Beispiel #4
0
/*****************************************************************************
 *
 * JACK_INIT()
 *
 * Setup the jack client.
 *
 *****************************************************************************/
int
jack_init(void) {
    const char		*server_name = NULL;
    static char		client_name[32];
    jack_options_t	options = JackNoStartServer | JackUseExactName;
    jack_status_t	status = 0;

    if (debug) {
	fprintf (stderr, "Initializing JACK client from thread 0x%lx\n", pthread_self());
    }

    if (client != NULL) {
	if (debug) {
	    fprintf (stderr, "Warning: closing stale JACK client...\n");
	}
	jack_client_close (client);
	client = NULL;
    }

    /* open a client connection to the JACK server */
    for( phasex_instance = 0; phasex_instance != 16; phasex_instance++)
    {
    if(!phasex_instance) {
        snprintf (client_name, 32, "%s", phasex_title);
    }
    else {
        snprintf (client_name, 32, "%s-%02d", phasex_title, phasex_instance);
    }
    printf("Using client name %s\n", client_name);
    if (client = jack_client_open ((const char *)client_name, options, &status, server_name))
        break;
    }
    
    /* deal with non-unique client name */
    if (status & JackNameNotUnique) {
	fprintf (stderr, "Unable to start JACK client '%s'!\n", client_name);
	return 1;
    }

    /* deal with jack server problems */
    if (status & (JackServerFailed | JackServerError)) {
	if (debug) {
	    fprintf (stderr, "Unable to connect to JACK server.  Status = 0x%2.0x\n", status);
	}
	return 1;
    }

    /* deal with missing client */
    if (client == NULL) {
	if (debug) {
	    fprintf (stderr, "Unable to open JACK client.  Status = 0x%2.0x\n", status);
	}
	return 1;
    }

    /* callback for when jack shuts down (needs to be set as early as possible) */
    jack_on_shutdown (client, jack_shutdown_handler, 0);

    if (debug) {
	fprintf (stderr, "Unique JACK client name '%s' assigned.\n", client_name);
    }

    /* notify if we started jack server */
    if (status & JackServerStarted) {
	fprintf (stderr, "JACK server started.\n");
    }

    /* report realtime scheduling in JACK */
    if (debug) {
	if (jack_is_realtime (client)) {
	    fprintf (stderr, "JACK is running with realtime scheduling.\n");
	}
	else {
	    fprintf (stderr, "JACK is running without realtime scheduling.\n");
	}
    }

    /* get sample rate early and notify other threads */
    sample_rate = jack_get_sample_rate (client);

    if (debug) {
	fprintf (stderr, "JACK sample rate:  %d\n", sample_rate);
    }

    /* scale sample rate depending on mode */
    switch (sample_rate_mode) {
    case SAMPLE_RATE_UNDERSAMPLE:
	sample_rate /= 2;
	break;
    case SAMPLE_RATE_OVERSAMPLE:
	sample_rate *= 2;
	break;
    }

    /* set samplerate related vars */
    f_sample_rate = (sample_t)sample_rate;
    nyquist_freq  = (sample_t)(sample_rate / 2);
    wave_period   = (sample_t)(F_WAVEFORM_SIZE / (double)sample_rate);

    if (debug) {
	fprintf (stderr, "Internal sample rate:  %d\n", sample_rate);
    }

    /* callback for setting our sample rate when jack tells us to */
    jack_set_sample_rate_callback (client, jack_samplerate_handler, 0);

    /* now that we have the sample rate, signal anyone else who needs to know */
    pthread_mutex_lock (&sample_rate_mutex);
    pthread_cond_broadcast (&sample_rate_cond);
    pthread_mutex_unlock (&sample_rate_mutex);

    /* get buffer size */
    buffer_size = jack_get_buffer_size (client) * 2;
    if (buffer_size > (PHASEX_MAX_BUFSIZE / 2)) {
    	fprintf (stderr, "JACK requested buffer size:  %d.  Max is:  %d.\n",
		 buffer_size, (PHASEX_MAX_BUFSIZE / 2));
    	fprintf (stderr, "JACK buffer size exceeded.  Closing client...\n");
	jack_client_close (client);
	client = NULL;
	jack_running = 0;
	return 1;
    }
    buffer_full = buffer_size;
    if (debug) {
	fprintf (stderr, "JACK output buffer size:  %d.\n", buffer_size);
    }

    /* callback for setting our buffer size when jack tells us to */
    jack_set_buffer_size_callback (client, jack_bufsize_handler, 0);

    /* callback for dealing with xruns */
    jack_set_xrun_callback (client, jack_xrun_handler, 0);

    /* create ports */
    input_port1 = jack_port_register (client, "in_1",
				      JACK_DEFAULT_AUDIO_TYPE,
				      JackPortIsInput, 0);
    input_port2 = jack_port_register (client, "in_2",
				      JACK_DEFAULT_AUDIO_TYPE,
				      JackPortIsInput, 0);

    output_port1 = jack_port_register (client, "out_1",
				       JACK_DEFAULT_AUDIO_TYPE,
				       JackPortIsOutput, 0);
    output_port2 = jack_port_register (client, "out_2",
				       JACK_DEFAULT_AUDIO_TYPE,
				       JackPortIsOutput, 0);

    if ( (output_port1 == NULL) || (output_port2 == NULL) ||
	 (input_port1 == NULL) || (input_port2 == NULL) )
    {
	fprintf (stderr, "JACK has no output ports available.\n");
	jack_client_close (client);
	client = NULL;
	jack_running = 0;
	return 0;
    }

    /* set callback for jack to grab audio data */
    jack_set_process_callback (client, process_buffer, 0);

    return 0;
}
Beispiel #5
0
static int _is_realtime(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 is-realtime");
  Tcl_SetObjResult(interp, Tcl_NewIntObj(jack_is_realtime(dp->fw.client)));
  return TCL_OK;
}
Beispiel #6
0
int luajack_is_realtime(luajack_t *client)
	{
	cud_t *cud = get_cud(client);	
	if(!cud) return 0;
	return jack_is_realtime(cud->client);
	}