diff options
Diffstat (limited to 'testing/portmidi/20-movetest.patch')
-rw-r--r-- | testing/portmidi/20-movetest.patch | 1001 |
1 files changed, 1001 insertions, 0 deletions
diff --git a/testing/portmidi/20-movetest.patch b/testing/portmidi/20-movetest.patch new file mode 100644 index 0000000000..69d65b2615 --- /dev/null +++ b/testing/portmidi/20-movetest.patch @@ -0,0 +1,1001 @@ +--- a/pm_test/CMakeLists.txt ++++ b/pm_test/CMakeLists.txt +@@ -12,11 +12,11 @@ + + macro(make_a_test name) + add_executable(${name} ${name}.c) +- target_link_libraries(${name} portmidi-static ${PM_NEEDED_LIBS}) +- add_dependencies(${name} portmidi-static) ++ target_link_libraries(${name} portmidi-dynamic ${PM_NEEDED_LIBS}) ++ add_dependencies(${name} portmidi-dynamic) + endmacro(make_a_test) + +-make_a_test(test) ++make_a_test(simple_test) + make_a_test(midithread) + make_a_test(midithru) + make_a_test(sysex) +--- /dev/null ++++ b/pm_test/simple_test.c +@@ -0,0 +1,489 @@ ++#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 DRIVER_INFO NULL ++#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 STRING_MAX 80 /* used for console input */ ++ ++int32_t latency = 0; ++ ++/* 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(char *prompt) ++{ ++ char line[STRING_MAX]; ++ int n = 0, i; ++ printf("%s\n", prompt); ++ while (n != 1) { ++ n = scanf("%d", &i); ++ fgets(line, STRING_MAX, stdin); ++ ++ } ++ return i; ++} ++ ++ ++/* ++ * 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, ++ DRIVER_INFO, ++ 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, %2lx %2lx %2lx\n", ++ i, ++ (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() { ++ PmStream * midi; ++ char line[80]; ++ 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, ++ DRIVER_INFO, ++ 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 RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ /* 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 = TIME_PROC(TIME_INFO); ++ /* 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); ++ ++ printf("ready to note-on... (type RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ buffer[0].timestamp = TIME_PROC(TIME_INFO); ++ buffer[0].message = Pm_Message(0x90, 60, 100); ++ Pm_Write(midi, buffer, 1); ++ printf("ready to note-off... (type RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ buffer[0].timestamp = TIME_PROC(TIME_INFO); ++ buffer[0].message = Pm_Message(0x90, 60, 0); ++ Pm_Write(midi, buffer, 1); ++ ++ /* output short note on/off w/latency offset; hold until user prompts */ ++ printf("ready to note-on (short form)... (type RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ Pm_WriteShort(midi, TIME_PROC(TIME_INFO), ++ Pm_Message(0x90, 60, 100)); ++ printf("ready to note-off (short form)... (type RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ Pm_WriteShort(midi, TIME_PROC(TIME_INFO), ++ Pm_Message(0x90, 60, 0)); ++ ++ /* output several note on/offs to test timing. ++ Should be 1s between notes */ ++ printf("chord will arpeggiate if latency > 0\n"); ++ printf("ready to chord-on/chord-off... (type RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ timestamp = TIME_PROC(TIME_INFO); ++ 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 (TIME_PROC(TIME_INFO) < off_time) ++ /* busy 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 RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ ++ 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 = 10; ++ ++ 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, ++ DRIVER_INFO, ++ 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, ++ DRIVER_INFO, ++ 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, %2lx %2lx %2lx\n", ++ i, ++ (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); ++ } ++ } ++ } ++ ++ /* 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; ++ char line[80]; ++ 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, ++ DRIVER_INFO, ++ 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 RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ ++ /* 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 = TIME_PROC(TIME_INFO); ++ 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 = TIME_PROC(TIME_INFO); ++ 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) ++ /* busy wait */; ++ /* 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 RETURN):"); ++ fgets(line, STRING_MAX, stdin); ++ ++ Pm_Close(midi); ++ Pm_Terminate(); ++ printf("done closing and terminating...\n"); ++} ++ ++ ++void show_usage() ++{ ++ printf("Usage: test [-h] [-l latency-in-ms]\n"); ++ exit(0); ++} ++ ++int main(int argc, char *argv[]) ++{ ++ int default_in; ++ int default_out; ++ int i = 0, n = 0; ++ char line[STRING_MAX]; ++ int test_input = 0, test_output = 0, test_both = 0, somethingStupid = 0; ++ int stream_test = 0; ++ int latency_valid = FALSE; ++ ++ 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) { ++ show_usage(); ++ } 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 { ++ show_usage(); ++ } ++ } ++ ++ 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("%s%s%s%s%s", ++ "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\n"); ++ while (n != 1) { ++ n = scanf("%d", &i); ++ fgets(line, STRING_MAX, stdin); ++ 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; ++ 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(); ++ } else if (test_both) { ++ main_test_both(); ++ } ++ ++ printf("finished portMidi test...type ENTER to quit..."); ++ fgets(line, STRING_MAX, stdin); ++ return 0; ++} +--- a/pm_test/test.c ++++ /dev/null +@@ -1,489 +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 DRIVER_INFO NULL +-#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 STRING_MAX 80 /* used for console input */ +- +-int32_t latency = 0; +- +-/* 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(char *prompt) +-{ +- char line[STRING_MAX]; +- int n = 0, i; +- printf(prompt); +- while (n != 1) { +- n = scanf("%d", &i); +- fgets(line, STRING_MAX, stdin); +- +- } +- return i; +-} +- +- +-/* +- * 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, +- DRIVER_INFO, +- 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, %2lx %2lx %2lx\n", +- i, +- (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() { +- PmStream * midi; +- char line[80]; +- 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, +- DRIVER_INFO, +- 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 RETURN):"); +- fgets(line, STRING_MAX, stdin); +- /* 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 = TIME_PROC(TIME_INFO); +- /* 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); +- +- printf("ready to note-on... (type RETURN):"); +- fgets(line, STRING_MAX, stdin); +- buffer[0].timestamp = TIME_PROC(TIME_INFO); +- buffer[0].message = Pm_Message(0x90, 60, 100); +- Pm_Write(midi, buffer, 1); +- printf("ready to note-off... (type RETURN):"); +- fgets(line, STRING_MAX, stdin); +- buffer[0].timestamp = TIME_PROC(TIME_INFO); +- buffer[0].message = Pm_Message(0x90, 60, 0); +- Pm_Write(midi, buffer, 1); +- +- /* output short note on/off w/latency offset; hold until user prompts */ +- printf("ready to note-on (short form)... (type RETURN):"); +- fgets(line, STRING_MAX, stdin); +- Pm_WriteShort(midi, TIME_PROC(TIME_INFO), +- Pm_Message(0x90, 60, 100)); +- printf("ready to note-off (short form)... (type RETURN):"); +- fgets(line, STRING_MAX, stdin); +- Pm_WriteShort(midi, TIME_PROC(TIME_INFO), +- Pm_Message(0x90, 60, 0)); +- +- /* output several note on/offs to test timing. +- Should be 1s between notes */ +- printf("chord will arpeggiate if latency > 0\n"); +- printf("ready to chord-on/chord-off... (type RETURN):"); +- fgets(line, STRING_MAX, stdin); +- timestamp = TIME_PROC(TIME_INFO); +- 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 (TIME_PROC(TIME_INFO) < off_time) +- /* busy 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 RETURN):"); +- fgets(line, STRING_MAX, stdin); +- +- 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 = 10; +- +- 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, +- DRIVER_INFO, +- 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, +- DRIVER_INFO, +- 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, %2lx %2lx %2lx\n", +- i, +- (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); +- } +- } +- } +- +- /* 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; +- char line[80]; +- 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, +- DRIVER_INFO, +- 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 RETURN):"); +- fgets(line, STRING_MAX, stdin); +- +- /* 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 = TIME_PROC(TIME_INFO); +- 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 = TIME_PROC(TIME_INFO); +- 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) +- /* busy wait */; +- /* 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 RETURN):"); +- fgets(line, STRING_MAX, stdin); +- +- Pm_Close(midi); +- Pm_Terminate(); +- printf("done closing and terminating...\n"); +-} +- +- +-void show_usage() +-{ +- printf("Usage: test [-h] [-l latency-in-ms]\n"); +- exit(0); +-} +- +-int main(int argc, char *argv[]) +-{ +- int default_in; +- int default_out; +- int i = 0, n = 0; +- char line[STRING_MAX]; +- int test_input = 0, test_output = 0, test_both = 0, somethingStupid = 0; +- int stream_test = 0; +- int latency_valid = FALSE; +- +- 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) { +- show_usage(); +- } 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 { +- show_usage(); +- } +- } +- +- 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("%s%s%s%s%s", +- "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\n"); +- while (n != 1) { +- n = scanf("%d", &i); +- fgets(line, STRING_MAX, stdin); +- 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; +- 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(); +- } else if (test_both) { +- main_test_both(); +- } +- +- printf("finished portMidi test...type ENTER to quit..."); +- fgets(line, STRING_MAX, stdin); +- return 0; +-} |