static PyObject * alsaseq_client(PyObject *self /* Not used */, PyObject *args) { const char * client_name; if (!PyArg_ParseTuple(args, "siii", &client_name, &ninputports, &noutputports, &createqueue ) ) return NULL; if ( ninputports > maximum_nports || noutputports > maximum_nports ) { printf( "Only %d ports of each are allowed.\n", maximum_nports ); exit( 1 ); } int portid, n; if (snd_seq_open(&seq_handle, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) { fprintf(stderr, "Error creating ALSA client.\n"); exit(1); } snd_seq_set_client_name(seq_handle, client_name ); if ( createqueue ) queue_id = snd_seq_alloc_queue(seq_handle); else queue_id = SND_SEQ_QUEUE_DIRECT; for ( n=0; n < ninputports; n++ ) { if (( portid = snd_seq_create_simple_port(seq_handle, "Input port", SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating input port %d.\n", n ); exit(1); } if( createqueue ) { /* set timestamp info of port */ snd_seq_port_info_t *pinfo; snd_seq_port_info_alloca(&pinfo); snd_seq_get_port_info( seq_handle, portid, pinfo ); snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, queue_id ); snd_seq_port_info_set_timestamp_real( pinfo, 1 ); snd_seq_set_port_info( seq_handle, portid, pinfo ); } } for ( n=0; n < noutputports; n++ ) { if (( portid = snd_seq_create_simple_port(seq_handle, "Output port", SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, SND_SEQ_PORT_TYPE_APPLICATION)) < 0) { fprintf(stderr, "Error creating output port %d.\n", n ); exit(1); } } firstoutputport = ninputports; lastoutputport = noutputports + ninputports - 1; Py_INCREF(Py_None); return Py_None; }
/** call-seq: timestamping = bool Switch auto-timestamping on or off. Note that the port needs a timestamp-queue as well to actually activate it. This is not verified though. It will simply not work. See RRTS::Driver::AlsaPortInfo_i#timestamp_queue= */ static VALUE wrap_snd_seq_port_info_set_timestamping(VALUE v_port_info, VALUE v_bool) { snd_seq_port_info_t *port_info; Data_Get_Struct(v_port_info, snd_seq_port_info_t, port_info); snd_seq_port_info_set_timestamping(port_info, BOOL2INT(v_bool)); return Qnil; }
void event_decoder(snd_seq_t *handle, int argc, char *argv[]) { snd_seq_event_t *ev; snd_seq_port_info_t *pinfo; snd_seq_port_subscribe_t *sub; snd_seq_addr_t addr; int client, port, queue, max, err, v1, v2; char *ptr; struct pollfd *pfds; if ((client = snd_seq_client_id(handle))<0) { fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client)); return; } printf("Client ID = %i\n", client); if ((queue = snd_seq_alloc_queue(handle))<0) { fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue)); return; } printf("Queue ID = %i\n", queue); if ((err = snd_seq_nonblock(handle, 1))<0) fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err)); snd_seq_port_info_alloca(&pinfo); snd_seq_port_info_set_name(pinfo, "Input"); snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC); snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE); /* Enable timestamping for events sent by external subscribers. */ snd_seq_port_info_set_timestamping(pinfo, 1); snd_seq_port_info_set_timestamp_real(pinfo, 1); snd_seq_port_info_set_timestamp_queue(pinfo, queue); if ((err = snd_seq_create_port(handle, pinfo)) < 0) { fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err)); return; } port = snd_seq_port_info_get_port(pinfo); event_decoder_start_timer(handle, queue, client, port); snd_seq_port_subscribe_alloca(&sub); addr.client = SND_SEQ_CLIENT_SYSTEM; addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE; snd_seq_port_subscribe_set_sender(sub, &addr); addr.client = client; addr.port = port; snd_seq_port_subscribe_set_dest(sub, &addr); snd_seq_port_subscribe_set_queue(sub, queue); snd_seq_port_subscribe_set_time_update(sub, 1); snd_seq_port_subscribe_set_time_real(sub, 1); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err)); return; } addr.client = SND_SEQ_CLIENT_SYSTEM; addr.port = SND_SEQ_PORT_SYSTEM_TIMER; snd_seq_port_subscribe_set_sender(sub, &addr); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err)); return; } for (max = 0; max < argc; max++) { ptr = argv[max]; if (!ptr) continue; snd_seq_port_subscribe_set_time_real(sub, 0); if (tolower(*ptr) == 'r') { snd_seq_port_subscribe_set_time_real(sub, 1); ptr++; } if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) { fprintf(stderr, "Wrong argument '%s'...\n", argv[max]); return; } addr.client = v1; addr.port = v2; snd_seq_port_subscribe_set_sender(sub, &addr); if ((err = snd_seq_subscribe_port(handle, sub))<0) { fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err)); return; } } max = snd_seq_poll_descriptors_count(handle, POLLIN); pfds = alloca(sizeof(*pfds) * max); while (1) { snd_seq_poll_descriptors(handle, pfds, max, POLLIN); if (poll(pfds, max, -1) < 0) break; do { if ((err = snd_seq_event_input(handle, &ev))<0) break; if (!ev) continue; decode_event(ev); snd_seq_free_event(ev); } while (err > 0); } }