Update of /cvsroot/pure-data/pd/portmidi/pm_linux In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv5166/pd/portmidi/pm_linux
Modified Files: README_LINUX.txt pmlinux.c pmlinuxalsa.c Log Message: 0.41-0 test 11
Index: pmlinux.c =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_linux/pmlinux.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pmlinux.c 15 Dec 2005 00:56:57 -0000 1.1 --- pmlinux.c 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 6,9 **** --- 6,12 ---- dependent, and it is separate from, pmlinuxalsa.c, because it might need to register non-alsa devices as well. + + NOTE: if you add non-ALSA support, you need to fix :alsa_poll() + in pmlinuxalsa.c, which assumes all input devices are ALSA. */
*************** *** 20,23 **** --- 23,31 ---- PmError pm_init() { + /* Note: it is not an error for PMALSA to fail to initialize. + * It may be a design error that the client cannot query what subsystems + * are working properly other than by looking at the list of available + * devices. + */ #ifdef PMALSA pm_linuxalsa_init(); *************** *** 26,29 **** --- 34,38 ---- pm_linuxnull_init(); #endif + return pmNoError; }
Index: README_LINUX.txt =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_linux/README_LINUX.txt,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** README_LINUX.txt 15 Dec 2005 00:56:57 -0000 1.1 --- README_LINUX.txt 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 1,8 **** README_LINUX.txt for PortMidi Roger Dannenberg ! 8 June 2004
To make PortMidi and PortTime, go back up to the portmidi ! directory and type make.
The Makefile will build all test programs and the portmidi --- 1,13 ---- README_LINUX.txt for PortMidi Roger Dannenberg ! 29 Aug 2006
To make PortMidi and PortTime, go back up to the portmidi ! directory and type ! ! make -f pm_linux/Makefile ! ! (You can also copy pm_linux/Makefile to the portmidi ! directory and just type "make".)
The Makefile will build all test programs and the portmidi *************** *** 22,25 **** --- 27,36 ---- CHANGELOG
+ 29-aug-2006 Roger B. Dannenberg + Fixed PortTime to join with time thread for clean exit. + + 28-aug-2006 Roger B. Dannenberg + Updated this documentation. + 08-Jun-2004 Roger B. Dannenberg Updated code to use new system abstraction.
Index: pmlinuxalsa.c =================================================================== RCS file: /cvsroot/pure-data/pd/portmidi/pm_linux/pmlinuxalsa.c,v retrieving revision 1.1 retrieving revision 1.2 diff -C2 -d -r1.1 -r1.2 *** pmlinuxalsa.c 15 Dec 2005 00:56:57 -0000 1.1 --- pmlinuxalsa.c 16 Jan 2008 21:54:10 -0000 1.2 *************** *** 10,13 **** --- 10,16 ---- #include "stdlib.h" #include "portmidi.h" + #ifdef NEWBUFFER + #include "pmutil.h" + #endif #include "pminternal.h" #include "pmlinuxalsa.h" *************** *** 42,46 **** extern pm_fns_node pm_linuxalsa_out_dictionary;
! static snd_seq_t *seq; // all input comes here, output queue allocated on seq static int queue, queue_used; /* one for all ports, reference counted */
--- 45,50 ---- extern pm_fns_node pm_linuxalsa_out_dictionary;
! static snd_seq_t *seq = NULL; // all input comes here, ! // output queue allocated on seq static int queue, queue_used; /* one for all ports, reference counted */
*************** *** 209,213 **** if (when < 0) when = 0; VERBOSE printf("timestamp %d now %d latency %d, ", ! timestamp, now, midi->latency); VERBOSE printf("scheduling event after %d\n", when); /* message is sent in relative ticks, where 1 tick = 1 ms */ --- 213,217 ---- if (when < 0) when = 0; VERBOSE printf("timestamp %d now %d latency %d, ", ! (int) timestamp, (int) now, midi->latency); VERBOSE printf("scheduling event after %d\n", when); /* message is sent in relative ticks, where 1 tick = 1 ms */ *************** *** 239,243 **** static PmError alsa_out_close(PmInternal *midi) { - int err; alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; if (!desc) return pmBadPtr; --- 243,246 ---- *************** *** 253,256 **** --- 256,260 ---- if (midi->latency > 0) alsa_unuse_queue(); snd_midi_event_free(desc->parser); + midi->descriptor = NULL; /* destroy the pointer to signify "closed" */ pm_free(desc); if (pm_hosterror) { *************** *** 330,334 **** static PmError alsa_in_close(PmInternal *midi) { - int err; alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; if (!desc) return pmBadPtr; --- 334,337 ---- *************** *** 352,357 **** static PmError alsa_abort(PmInternal *midi) { alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; ! /* This is supposed to flush any pending output. */ printf("WARNING: alsa_abort not implemented\n"); return pmNoError; --- 355,382 ---- static PmError alsa_abort(PmInternal *midi) { + /* NOTE: ALSA documentation is vague. This is supposed to + * remove any pending output messages. If you can test and + * confirm this code is correct, please update this comment. -RBD + */ + /* Unfortunately, I can't even compile it -- my ALSA version + * does not implement snd_seq_remove_events_t, so this does + * not compile. I'll try again, but it looks like I'll need to + * upgrade my entire Linux OS -RBD + */ + /* alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; ! snd_seq_remove_events_t info; ! snd_seq_addr_t addr; ! addr.client = desc->client; ! addr.port = desc->port; ! snd_seq_remove_events_set_dest(&info, &addr); ! snd_seq_remove_events_set_condition(&info, SND_SEQ_REMOVE_DEST); ! pm_hosterror = snd_seq_remove_events(seq, &info); ! if (pm_hosterror) { ! get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN, ! pm_hosterror); ! return pmHostError; ! } ! */ printf("WARNING: alsa_abort not implemented\n"); return pmNoError; *************** *** 409,416 ****
! static PmError alsa_write_flush(PmInternal *midi) { alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; ! VERBOSE printf("snd_seq_drain_output: 0x%x\n", seq); desc->error = snd_seq_drain_output(seq); if (desc->error < 0) return pmHostError; --- 434,441 ----
! static PmError alsa_write_flush(PmInternal *midi, PmTimestamp timestamp) { alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor; ! VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int) seq); desc->error = snd_seq_drain_output(seq); if (desc->error < 0) return pmHostError; *************** *** 584,595 **** case SND_SEQ_EVENT_SYSEX: { const BYTE *ptr = (const BYTE *) ev->data.ext.ptr; ! int i; ! long msg = 0; ! int shift = 0; ! if (!(midi->filters & PM_FILT_SYSEX)) { ! for (i = 0; i < ev->data.ext.len; i++) { ! pm_read_byte(midi, *ptr++, timestamp); ! } ! } break; } --- 609,614 ---- case SND_SEQ_EVENT_SYSEX: { const BYTE *ptr = (const BYTE *) ev->data.ext.ptr; ! /* assume there is one sysex byte to process */ ! pm_read_bytes(midi, ptr, ev->data.ext.len, timestamp); break; } *************** *** 597,606 **** }
static PmError alsa_poll(PmInternal *midi) { snd_seq_event_t *ev; ! while (snd_seq_event_input(seq, &ev) >= 0) { ! if (ev) { ! handle_event(ev); } } --- 616,648 ---- }
+ static PmError alsa_poll(PmInternal *midi) { snd_seq_event_t *ev; ! /* expensive check for input data, gets data from device: */ ! while (snd_seq_event_input_pending(seq, TRUE) > 0) { ! /* cheap check on local input buffer */ ! while (snd_seq_event_input_pending(seq, FALSE) > 0) { ! /* check for and ignore errors, e.g. input overflow */ ! /* note: if there's overflow, this should be reported ! * all the way through to client. Since input from all ! * devices is merged, we need to find all input devices ! * and set all to the overflow state. ! * NOTE: this assumes every input is ALSA based. ! */ ! int rslt = snd_seq_event_input(seq, &ev); ! if (rslt >= 0) { ! handle_event(ev); ! } else if (rslt == -ENOSPC) { ! int i; ! for (i = 0; i < pm_descriptor_index; i++) { ! if (descriptors[i].pub.input) { ! PmInternal *midi = (PmInternal *) ! descriptors[i].internalDescriptor; ! /* careful, device may not be open! */ ! if (midi) Pm_SetOverflow(midi->queue); ! } ! } ! } } } *************** *** 678,683 **** unsigned int caps;
! err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, SND_SEQ_NONBLOCK); ! if (err < 0) return;
snd_seq_client_info_alloca(&cinfo); --- 720,734 ---- unsigned int caps;
! /* Previously, the last parameter was SND_SEQ_NONBLOCK, but this ! * would cause messages to be dropped if the ALSA buffer fills up. ! * The correct behavior is for writes to block until there is ! * room to send all the data. The client should normally allocate ! * a large enough buffer to avoid blocking on output. ! * Now that blocking is enabled, the seq_event_input() will block ! * if there is no input data. This is not what we want, so must ! * call seq_event_input_pending() to avoid blocking. ! */ ! err = snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0); ! if (err < 0) return err;
snd_seq_client_info_alloca(&cinfo); *************** *** 716,719 **** --- 767,771 ---- } } + return pmNoError; }
*************** *** 721,724 **** void pm_linuxalsa_term(void) { ! snd_seq_close(seq); } --- 773,782 ---- void pm_linuxalsa_term(void) { ! if (seq) { ! snd_seq_close(seq); ! pm_free(descriptors); ! descriptors = NULL; ! pm_descriptor_index = 0; ! pm_descriptor_max = 0; ! } }