diff options
Diffstat (limited to 'portmidi/pm_test/testio.c')
| -rwxr-xr-x | portmidi/pm_test/testio.c | 594 |
1 files changed, 0 insertions, 594 deletions
diff --git a/portmidi/pm_test/testio.c b/portmidi/pm_test/testio.c deleted file mode 100755 index 2711286..0000000 --- a/portmidi/pm_test/testio.c +++ /dev/null @@ -1,594 +0,0 @@ -#include "portmidi.h" -#include "porttime.h" -#include "stdlib.h" -#include "stdio.h" -#include "string.h" -#include "assert.h" - -#define INPUT_BUFFER_SIZE 100 -#define OUTPUT_BUFFER_SIZE 0 -#define TIME_PROC ((int32_t (*)(void *)) Pt_Time) -#define TIME_INFO NULL -#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ - -#define WAIT_FOR_ENTER while (getchar() != '\n') ; - -int32_t latency = 0; -int verbose = FALSE; -PmSysDepInfo *sysdepinfo = NULL; - -/* crash the program to test whether midi ports are closed */ -/**/ -void doSomethingReallyStupid() { - int * tmp = NULL; - *tmp = 5; -} - - -/* exit the program without any explicit cleanup */ -/**/ -void doSomethingStupid() { - assert(0); -} - - -/* read a number from console */ -/**/ -int get_number(const char *prompt) -{ - int n = 0, i; - fputs(prompt, stdout); - while (n != 1) { - n = scanf("%d", &i); - WAIT_FOR_ENTER - } - return i; -} - - -static void set_sysdepinfo(char m_or_p, const char *name) -{ - if (!sysdepinfo) { - // allocate some space we will alias with open-ended PmDriverInfo: - // there is space for 4 parameters: - static char dimem[sizeof(PmSysDepInfo) + sizeof(void *) * 8]; - sysdepinfo = (PmSysDepInfo *) dimem; - // build the driver info structure: - sysdepinfo->structVersion = PM_SYSDEPINFO_VERS; - sysdepinfo->length = 0; - } - if (sysdepinfo->length > 1) { - printf("Error: sysdepinfo was allocated to hold 2 parameters\n"); - exit(1); - } - int i = sysdepinfo->length++; - enum PmSysDepPropertyKey k = pmKeyNone; - if (m_or_p == 'm') k = pmKeyCoreMidiManufacturer; - else if (m_or_p == 'p') k = pmKeyAlsaPortName; - else if (m_or_p == 'c') k = pmKeyAlsaClientName; - sysdepinfo->properties[i].key = k; - sysdepinfo->properties[i].value = name; -} - - -/* - * the somethingStupid parameter can be set to simulate a program crash. - * We want PortMidi to close Midi ports automatically in the event of a - * crash because Windows does not (and this may cause an OS crash) - */ -void main_test_input(unsigned int somethingStupid) { - PmStream * midi; - PmError status, length; - PmEvent buffer[1]; - int num = 10; - int i = get_number("Type input number: "); - /* It is recommended to start timer before Midi; otherwise, PortMidi may - start the timer with its (default) parameters - */ - TIME_START; - - /* open input device */ - Pm_OpenInput(&midi, - i, - sysdepinfo, - INPUT_BUFFER_SIZE, - TIME_PROC, - TIME_INFO); - - printf("Midi Input opened. Reading %d Midi messages...\n", num); - Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX); - /* empty the buffer after setting filter, just in case anything - got through */ - while (Pm_Poll(midi)) { - Pm_Read(midi, buffer, 1); - } - /* now start paying attention to messages */ - i = 0; /* count messages as they arrive */ - while (i < num) { - status = Pm_Poll(midi); - if (status == TRUE) { - length = Pm_Read(midi, buffer, 1); - if (length > 0) { - printf("Got message %d @ time %ld: timestamp %ld, " - "%2lx %2lx %2lx\n", i, (long) Pt_Time(), - (long) buffer[0].timestamp, - (long) Pm_MessageStatus(buffer[0].message), - (long) Pm_MessageData1(buffer[0].message), - (long) Pm_MessageData2(buffer[0].message)); - i++; - } else { - assert(0); - } - } - /* simulate crash if somethingStupid is 1 or 2 */ - if ((i > (num/2)) && (somethingStupid == 1)) { - doSomethingStupid(); - } else if ((i > (num/2)) && (somethingStupid == 2)) { - doSomethingReallyStupid(); - } - } - - /* close device (this not explicitly needed in most implementations) */ - printf("ready to close..."); - - Pm_Close(midi); - printf("done closing..."); -} - - - -void main_test_output(int isochronous_test) -{ - PmStream * midi; - int32_t off_time; - int chord[] = { 60, 67, 76, 83, 90 }; - #define chord_size 5 - PmEvent buffer[chord_size]; - PmTimestamp timestamp; - - /* determine which output device to use */ - int i = get_number("Type output number: "); - - /* It is recommended to start timer before PortMidi */ - TIME_START; - - /* open output device -- since PortMidi avoids opening a timer - when latency is zero, we will pass in a NULL timer pointer - for that case. If PortMidi tries to access the time_proc, - we will crash, so this test will tell us something. */ - Pm_OpenOutput(&midi, - i, - sysdepinfo, - OUTPUT_BUFFER_SIZE, - (latency == 0 ? NULL : TIME_PROC), - (latency == 0 ? NULL : TIME_INFO), - latency); - printf("Midi Output opened with %ld ms latency.\n", (long) latency); - - /* output note on/off w/latency offset; hold until user prompts */ - printf("ready to send program 1 change... (type ENTER):"); - WAIT_FOR_ENTER - /* if we were writing midi for immediate output, we could always use - timestamps of zero, but since we may be writing with latency, we - will explicitly set the timestamp to "now" by getting the time. - The source of timestamps should always correspond to the TIME_PROC - and TIME_INFO parameters used in Pm_OpenOutput(). */ - buffer[0].timestamp = Pt_Time(); - /* Send a program change to increase the chances we will hear notes */ - /* Program 0 is usually a piano, but you can change it here: */ -#define PROGRAM 0 - buffer[0].message = Pm_Message(0xC0, PROGRAM, 0); - Pm_Write(midi, buffer, 1); - - if (isochronous_test) { // play 4 notes per sec for 20s - int count; - PmTimestamp start; - if (latency < 100) { - printf("Warning: latency < 100, but this test sends messages" - " at times that are jittered by up to 100ms, so you" - " may hear uneven timing\n"); - } - printf("Starting in 1s..."); fflush(stdout); - Pt_Sleep(1000); - start = Pt_Time(); - for (count = 0; count < 80; count++) { - PmTimestamp next_time; - buffer[0].timestamp = start + count * 250; - buffer[0].message = Pm_Message(0x90, 69, 100); - buffer[1].timestamp = start + count * 250 + 200; - buffer[1].message = Pm_Message(0x90, 69, 0); - Pm_Write(midi, buffer, 2); - next_time = start + (count + 1) * 250; - // sleep for a random time up to 100ms to add jitter to - // the times at which we send messages. PortMidi timing - // should remove the jitter if latency > 100 - while (Pt_Time() < next_time) { - Pt_Sleep(rand() % 100); - } - } - printf("Done sending 80 notes at 4 notes per second.\n"); - } else { - PmError err = 0; - printf("ready to note-on... (type ENTER):"); - WAIT_FOR_ENTER - buffer[0].timestamp = Pt_Time(); - buffer[0].message = Pm_Message(0x90, 60, 100); - if ((err = Pm_Write(midi, buffer, 1))) { - printf("Pm_Write returns error: %d (%s)\n", - err, Pm_GetErrorText(err)); - if (err == pmHostError) { - char errmsg[128]; - Pm_GetHostErrorText(errmsg, 127); - printf(" Host error: %s\n", errmsg); - } - } - printf("ready to note-off... (type ENTER):"); - WAIT_FOR_ENTER - buffer[0].timestamp = Pt_Time(); - buffer[0].message = Pm_Message(0x90, 60, 0); - if ((err = Pm_Write(midi, buffer, 1))) { - printf("Pm_Write returns error: %d (%s)\n", - err, Pm_GetErrorText(err)); - if (err == pmHostError) { - char errmsg[128]; - Pm_GetHostErrorText(errmsg, 127); - printf(" Host error: %s\n", errmsg); - } - } - - /* output short note on/off w/latency offset; hold until user prompts */ - printf("ready to note-on (short form)... (type ENTER):"); - WAIT_FOR_ENTER - Pm_WriteShort(midi, Pt_Time(), - Pm_Message(0x90, 60, 100)); - printf("ready to note-off (short form)... (type ENTER):"); - WAIT_FOR_ENTER - Pm_WriteShort(midi, Pt_Time(), - Pm_Message(0x90, 60, 0)); - - /* output several note on/offs to test timing. - Should be 1s between notes */ - if (latency == 0) { - printf("chord should not arpeggiate, latency == 0\n"); - } else { - printf("chord should arpeggiate (latency = %ld > 0\n", - (long) latency); - } - printf("ready to chord-on/chord-off... (type ENTER):"); - WAIT_FOR_ENTER - timestamp = Pt_Time(); - printf("starting timestamp %ld\n", (long) timestamp); - for (i = 0; i < chord_size; i++) { - buffer[i].timestamp = timestamp + 1000 * i; - buffer[i].message = Pm_Message(0x90, chord[i], 100); - } - Pm_Write(midi, buffer, chord_size); - - off_time = timestamp + 1000 + chord_size * 1000; - while (Pt_Time() < off_time) - /* There was a report that Pm_Write with zero length sent last - * message again, so call Pm_Write here to see if note repeats - */ - Pm_Write(midi, buffer, 0); - Pt_Sleep(20); /* wait */ - - for (i = 0; i < chord_size; i++) { - buffer[i].timestamp = timestamp + 1000 * i; - buffer[i].message = Pm_Message(0x90, chord[i], 0); - } - Pm_Write(midi, buffer, chord_size); - } - - /* close device (this not explicitly needed in most implementations) */ - printf("ready to close and terminate... (type ENTER):"); - WAIT_FOR_ENTER - - Pm_Close(midi); - Pm_Terminate(); - printf("done closing and terminating...\n"); -} - - -void main_test_both() -{ - int i = 0; - int in, out; - PmStream * midi, * midiOut; - PmEvent buffer[1]; - PmError status, length; - int num = 11; - - in = get_number("Type input number: "); - out = get_number("Type output number: "); - - /* In is recommended to start timer before PortMidi */ - TIME_START; - - Pm_OpenOutput(&midiOut, - out, - sysdepinfo, - OUTPUT_BUFFER_SIZE, - TIME_PROC, - TIME_INFO, - latency); - printf("Midi Output opened with %ld ms latency.\n", (long) latency); - /* open input device */ - Pm_OpenInput(&midi, - in, - sysdepinfo, - INPUT_BUFFER_SIZE, - TIME_PROC, - TIME_INFO); - printf("Midi Input opened. Reading %d Midi messages...\n", num); - Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK); - /* empty the buffer after setting filter, just in case anything - got through */ - while (Pm_Poll(midi)) { - Pm_Read(midi, buffer, 1); - } - i = 0; - while (i < num) { - status = Pm_Poll(midi); - if (status == TRUE) { - length = Pm_Read(midi,buffer,1); - if (length > 0) { - Pm_Write(midiOut, buffer, 1); - printf("Got message %d @ time %ld: timestamp %ld, " - "%2lx %2lx %2lx\n", i, (long) Pt_Time(), - (long) buffer[0].timestamp, - (long) Pm_MessageStatus(buffer[0].message), - (long) Pm_MessageData1(buffer[0].message), - (long) Pm_MessageData2(buffer[0].message)); - i++; - } else { - assert(0); - } - } - } - /* allow time for last message to go out */ - Pt_Sleep(100 + latency); - - /* close midi devices */ - Pm_Close(midi); - Pm_Close(midiOut); - Pm_Terminate(); -} - - -/* main_test_stream exercises windows winmm API's stream mode */ -/* The winmm stream mode is used for latency>0, and sends - timestamped messages. The timestamps are relative (delta) - times, whereas PortMidi times are absolute. Since peculiar - things happen when messages are not always sent in advance, - this function allows us to exercise the system and test it. - */ -void main_test_stream() { - PmStream * midi; - PmEvent buffer[16]; - - /* determine which output device to use */ - int i = get_number("Type output number: "); - - latency = 500; /* ignore LATENCY for this test and - fix the latency at 500ms */ - - /* It is recommended to start timer before PortMidi */ - TIME_START; - - /* open output device */ - Pm_OpenOutput(&midi, - i, - sysdepinfo, - OUTPUT_BUFFER_SIZE, - TIME_PROC, - TIME_INFO, - latency); - printf("Midi Output opened with %ld ms latency.\n", (long) latency); - - /* output note on/off w/latency offset; hold until user prompts */ - printf("ready to send output... (type ENTER):"); - WAIT_FOR_ENTER - - /* if we were writing midi for immediate output, we could always use - timestamps of zero, but since we may be writing with latency, we - will explicitly set the timestamp to "now" by getting the time. - The source of timestamps should always correspond to the TIME_PROC - and TIME_INFO parameters used in Pm_OpenOutput(). */ - buffer[0].timestamp = Pt_Time(); - buffer[0].message = Pm_Message(0xC0, 0, 0); - buffer[1].timestamp = buffer[0].timestamp; - buffer[1].message = Pm_Message(0x90, 60, 100); - buffer[2].timestamp = buffer[0].timestamp + 1000; - buffer[2].message = Pm_Message(0x90, 62, 100); - buffer[3].timestamp = buffer[0].timestamp + 2000; - buffer[3].message = Pm_Message(0x90, 64, 100); - buffer[4].timestamp = buffer[0].timestamp + 3000; - buffer[4].message = Pm_Message(0x90, 66, 100); - buffer[5].timestamp = buffer[0].timestamp + 4000; - buffer[5].message = Pm_Message(0x90, 60, 0); - buffer[6].timestamp = buffer[0].timestamp + 4000; - buffer[6].message = Pm_Message(0x90, 62, 0); - buffer[7].timestamp = buffer[0].timestamp + 4000; - buffer[7].message = Pm_Message(0x90, 64, 0); - buffer[8].timestamp = buffer[0].timestamp + 4000; - buffer[8].message = Pm_Message(0x90, 66, 0); - - Pm_Write(midi, buffer, 9); -#ifdef SEND8 - /* Now, we're ready for the real test. - Play 4 notes at now, now+500, now+1000, and now+1500 - Then wait until now+2000. - Play 4 more notes as before. - We should hear 8 evenly spaced notes. */ - now = Pt_Time(); - for (i = 0; i < 4; i++) { - buffer[i * 2].timestamp = now + (i * 500); - buffer[i * 2].message = Pm_Message(0x90, 60, 100); - buffer[i * 2 + 1].timestamp = now + 250 + (i * 500); - buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0); - } - Pm_Write(midi, buffer, 8); - - while (Pt_Time() < now + 2500) - Pt_Sleep(10); - /* now we are 500 ms behind schedule, but since the latency - is 500, the delay should not be audible */ - now += 2000; - for (i = 0; i < 4; i++) { - buffer[i * 2].timestamp = now + (i * 500); - buffer[i * 2].message = Pm_Message(0x90, 60, 100); - buffer[i * 2 + 1].timestamp = now + 250 + (i * 500); - buffer[i * 2 + 1].message = Pm_Message(0x90, 60, 0); - } - Pm_Write(midi, buffer, 8); -#endif - /* close device (this not explicitly needed in most implementations) */ - printf("ready to close and terminate... (type ENTER):"); - WAIT_FOR_ENTER - - Pm_Close(midi); - Pm_Terminate(); - printf("done closing and terminating...\n"); -} - - -void show_usage() -{ - printf("Usage: test [-h] [-l latency-in-ms] [-c clientname] " - "[-p portname] [-v]\n" - " -h for this help message (only)\n" - " -l for latency\n" - " -c name designates a client name (linux only),\n" - " -p name designates a port name (linux only),\n" - " -v for verbose (enables more output)\n"); -} - -int main(int argc, char *argv[]) -{ - int default_in; - int default_out; - int i = 0, n = 0; - int test_input = 0, test_output = 0, test_both = 0, somethingStupid = 0; - int isochronous_test = 0; - int stream_test = 0; - int latency_valid = FALSE; - - show_usage(); - if (sizeof(void *) == 8) - printf("Apparently this is a 64-bit machine.\n"); - else if (sizeof(void *) == 4) - printf ("Apparently this is a 32-bit machine.\n"); - - for (i = 1; i < argc; i++) { - if (strcmp(argv[i], "-h") == 0) { - exit(0); - } else if (strcmp(argv[i], "-p") == 0 && (i + 1 < argc)) { - i = i + 1; - const char *port_name = argv[i]; - set_sysdepinfo('p', port_name); - printf("Port name will be %s\n", port_name); - } else if (strcmp(argv[i], "-c") == 0 && (i + 1 < argc)) { - i = i + 1; - set_sysdepinfo('c', argv[i]); - printf("Client name will be %s\n", argv[i]); - } else if (strcmp(argv[i], "-l") == 0 && (i + 1 < argc)) { - i = i + 1; - latency = atoi(argv[i]); - printf("Latency will be %ld\n", (long) latency); - latency_valid = TRUE; - } else if (strcmp(argv[i], "-v") == 0) { - printf("Verbose is now TRUE\n"); - verbose = TRUE; /* not currently used for anything */ - } else { - show_usage(); - exit(0); - } - } - - while (!latency_valid) { - int lat; // declared int to match "%d" - printf("Latency in ms: "); - if (scanf("%d", &lat) == 1) { - latency = (int32_t) lat; // coerce from "%d" to known size - latency_valid = TRUE; - } - } - - /* determine what type of test to run */ - printf("begin portMidi test...\n"); - printf("enter your choice...\n 1: test input\n" - " 2: test input (fail w/assert)\n" - " 3: test input (fail w/NULL assign)\n" - " 4: test output\n 5: test both\n" - " 6: stream test (for WinMM)\n" - " 7. isochronous out\n"); - while (n != 1) { - n = scanf("%d", &i); - WAIT_FOR_ENTER - switch(i) { - case 1: - test_input = 1; - break; - case 2: - test_input = 1; - somethingStupid = 1; - break; - case 3: - test_input = 1; - somethingStupid = 2; - break; - case 4: - test_output = 1; - break; - case 5: - test_both = 1; - break; - case 6: - stream_test = 1; - break; - case 7: - test_output = 1; - isochronous_test = 1; - break; - default: - printf("got %d (invalid input)\n", n); - break; - } - } - - /* list device information */ - default_in = Pm_GetDefaultInputDeviceID(); - default_out = Pm_GetDefaultOutputDeviceID(); - for (i = 0; i < Pm_CountDevices(); i++) { - char *deflt; - const PmDeviceInfo *info = Pm_GetDeviceInfo(i); - if (((test_input | test_both) & info->input) | - ((test_output | test_both | stream_test) & info->output)) { - printf("%d: %s, %s", i, info->interf, info->name); - if (info->input) { - deflt = (i == default_in ? "default " : ""); - printf(" (%sinput)", deflt); - } - if (info->output) { - deflt = (i == default_out ? "default " : ""); - printf(" (%soutput)", deflt); - } - printf("\n"); - } - } - - /* run test */ - if (stream_test) { - main_test_stream(); - } else if (test_input) { - main_test_input(somethingStupid); - } else if (test_output) { - main_test_output(isochronous_test); - } else if (test_both) { - main_test_both(); - } - - printf("finished portMidi test...type ENTER to quit..."); - WAIT_FOR_ENTER - return 0; -} |
