mirror of
				https://github.com/cookiengineer/audacity
				synced 2025-11-03 23:53:55 +01:00 
			
		
		
		
	
		
			
				
	
	
		
			490 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			490 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#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;
 | 
						|
}
 |