aboutsummaryrefslogtreecommitdiffstats
path: root/testing/portmidi
diff options
context:
space:
mode:
authorTaner Tas <taner76@gmail.com>2018-02-21 16:33:34 +0000
committerLeonardo Arena <rnalrd@alpinelinux.org>2018-02-28 12:53:05 +0000
commit24cdbb59afb3e0141401a09cc98c918283ccdc49 (patch)
treec18c934ec904845e8c95d4f52137960751faeec0 /testing/portmidi
parent478a4a468ecf31c263b6c76dfab0f2332bc3365f (diff)
downloadaports-24cdbb59afb3e0141401a09cc98c918283ccdc49.tar.bz2
aports-24cdbb59afb3e0141401a09cc98c918283ccdc49.tar.xz
testing/portmidi: new aport
http://portmedia.sourceforge.net/ PortMidi is a platform independent library for MIDI input/output.
Diffstat (limited to 'testing/portmidi')
-rw-r--r--testing/portmidi/00_cmake.patch33
-rw-r--r--testing/portmidi/01_pmlinux.patch17
-rw-r--r--testing/portmidi/02_pmlinuxalsa.patch33
-rw-r--r--testing/portmidi/03_pm_test_Makefile.patch39
-rw-r--r--testing/portmidi/11-pmlinuxalsa.patch70
-rw-r--r--testing/portmidi/13-disablejni.patch86
-rw-r--r--testing/portmidi/20-movetest.patch1001
-rw-r--r--testing/portmidi/21-hardentests.patch93
-rw-r--r--testing/portmidi/30-porttime_cmake.patch32
-rw-r--r--testing/portmidi/40-test_sysex.patch19
-rw-r--r--testing/portmidi/41-pm_linux.patch77
-rw-r--r--testing/portmidi/50-change_assert.patch41
-rw-r--r--testing/portmidi/51-remove_assert.patch13
-rw-r--r--testing/portmidi/APKBUILD63
14 files changed, 1617 insertions, 0 deletions
diff --git a/testing/portmidi/00_cmake.patch b/testing/portmidi/00_cmake.patch
new file mode 100644
index 0000000000..af8062c0ef
--- /dev/null
+++ b/testing/portmidi/00_cmake.patch
@@ -0,0 +1,33 @@
+--- a/pm_dylib/CMakeLists.txt
++++ b/pm_dylib/CMakeLists.txt
+@@ -115,13 +115,14 @@
+
+ add_library(portmidi-dynamic SHARED ${LIBSRC})
+ set_target_properties(portmidi-dynamic PROPERTIES OUTPUT_NAME "portmidi")
++set_target_properties(portmidi-dynamic PROPERTIES VERSION "0.0.0" SOVERSION "0")
+ target_link_libraries(portmidi-dynamic ${PM_NEEDED_LIBS})
+
+ # install the libraries (Linux and Mac OS X command line)
+ if(UNIX)
+ INSTALL(TARGETS portmidi-dynamic
+- LIBRARY DESTINATION /usr/local/lib
+- ARCHIVE DESTINATION /usr/local/lib)
++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ INSTALL(FILES ../pm_common/portmidi.h ../porttime/porttime.h
+- DESTINATION /usr/local/include)
++ DESTINATION include)
+ endif(UNIX)
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 4919b78..4067a5a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -4,6 +4,8 @@
+
+ cmake_minimum_required(VERSION 2.6)
+
++include(GNUInstallDirs)
++
+ if(UNIX)
+ # allow user to set Release or Debug
+ set(CMAKE_BUILD_TYPE Release CACHE STRING
diff --git a/testing/portmidi/01_pmlinux.patch b/testing/portmidi/01_pmlinux.patch
new file mode 100644
index 0000000000..e37be1af94
--- /dev/null
+++ b/testing/portmidi/01_pmlinux.patch
@@ -0,0 +1,17 @@
+Index: portmidi-200/pm_linux/pmlinux.c
+===================================================================
+--- portmidi-200.orig/pm_linux/pmlinux.c 2010-02-14 17:35:40.000000000 -0500
++++ portmidi-200/pm_linux/pmlinux.c 2010-02-14 17:36:17.000000000 -0500
+@@ -34,10 +34,10 @@
+ * devices.
+ */
+ #ifdef PMALSA
+- pm_linuxalsa_init();
++ return pm_linuxalsa_init();
+ #endif
+ #ifdef PMNULL
+- pm_linuxnull_init();
++ return pm_linuxnull_init();
+ #endif
+ // this is set when we return to Pm_Initialize, but we need it
+ // now in order to (successfully) call Pm_CountDevices()
diff --git a/testing/portmidi/02_pmlinuxalsa.patch b/testing/portmidi/02_pmlinuxalsa.patch
new file mode 100644
index 0000000000..2464475180
--- /dev/null
+++ b/testing/portmidi/02_pmlinuxalsa.patch
@@ -0,0 +1,33 @@
+--- portmidi~/pm_linux/pmlinuxalsa.c 2009-09-16 05:41:04.000000000 +0200
++++ portmidi/pm_linux/pmlinuxalsa.c 2009-09-16 05:45:29.000000000 +0200
+@@ -242,8 +242,8 @@
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
+ if (!desc) return pmBadPtr;
+
+- if (pm_hosterror = snd_seq_disconnect_to(seq, desc->this_port,
+- desc->client, desc->port)) {
++ if ((pm_hosterror = snd_seq_disconnect_to(seq, desc->this_port,
++ desc->client, desc->port))) {
+ // if there's an error, try to delete the port anyway, but don't
+ // change the pm_hosterror value so we retain the first error
+ snd_seq_delete_port(seq, desc->this_port);
+@@ -332,8 +332,8 @@
+ {
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
+ if (!desc) return pmBadPtr;
+- if (pm_hosterror = snd_seq_disconnect_from(seq, desc->this_port,
+- desc->client, desc->port)) {
++ if ((pm_hosterror = snd_seq_disconnect_from(seq, desc->this_port,
++ desc->client, desc->port))) {
+ snd_seq_delete_port(seq, desc->this_port); /* try to close port */
+ } else {
+ pm_hosterror = snd_seq_delete_port(seq, desc->this_port);
+@@ -606,7 +606,7 @@
+ 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);
++ pm_read_bytes(midi, (unsigned char*)ptr, ev->data.ext.len, timestamp);
+ break;
+ }
+ }
diff --git a/testing/portmidi/03_pm_test_Makefile.patch b/testing/portmidi/03_pm_test_Makefile.patch
new file mode 100644
index 0000000000..b1a2c380ba
--- /dev/null
+++ b/testing/portmidi/03_pm_test_Makefile.patch
@@ -0,0 +1,39 @@
+--- portmidi-20041117.orig/pm_test/debian/Makefile
++++ portmidi-20041117/pm_test/debian/Makefile
+@@ -0,0 +1,36 @@
++# For debugging, define PM_CHECK_ERRORS
++PMFLAGS = -DPM_CHECK_ERRORS
++# Use this for linux alsa (0.9x) version
++ALSALIB = -lasound
++pmlib = -lportmidi
++ptlib = -lporttime
++VFLAGS = -DPMALSA
++
++CC = gcc $(CFLAGS) $(VFLAGS) $(PMFLAGS) -g
++
++all: simple_test sysex midithread latency midithru mm
++
++simple_test: simple_test.o
++ $(CC) simple_test.c -o simple_test $(pmlib) $(ptlib) $(ALSALIB)
++
++sysex: sysex.o
++ $(CC) sysex.c -o sysex $(pmlib) $(ptlib) $(ALSALIB)
++
++midithread: midithread.o
++ $(CC) midithread.c -o midithread \
++ $(pmlib) $(ptlib) $(ALSALIB)
++
++latency: latency.o
++ $(CC) latency.c -o latency $(pmlib) $(ptlib) \
++ $(ALSALIB) -lpthread -lm
++
++midithru: midithru.o
++ $(CC) midithru.c -o midithru $(pmlib) $(ptlib) \
++ $(ALSALIB) -lpthread -lm
++
++mm: mm.o
++ $(CC) mm.c -o mm $(pmlib) $(ptlib) \
++ $(ALSALIB) -lpthread -lm
++
++clean:
++ rm -f *.o mm midithru latency midithread sysex simple_test
diff --git a/testing/portmidi/11-pmlinuxalsa.patch b/testing/portmidi/11-pmlinuxalsa.patch
new file mode 100644
index 0000000000..eb98a79df0
--- /dev/null
+++ b/testing/portmidi/11-pmlinuxalsa.patch
@@ -0,0 +1,70 @@
+Subject: Prevent SIGSEGV on handling events for already closed devices.
+Bug: http://sourceforge.net/apps/trac/portmedia/ticket/3
+Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=695842
+Bug-Ubuntu: https://launchpad.net/bugs/1073484
+Applied-Upstream: yes
+---
+ pm_linux/pmlinuxalsa.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- portmidi-200.orig/pm_linux/pmlinuxalsa.c
++++ portmidi-200/pm_linux/pmlinuxalsa.c
+@@ -193,6 +193,7 @@ static PmError alsa_write_byte(PmInterna
+ snd_seq_event_t ev;
+ int err;
+
++ if (!desc) return pmBadPtr;
+ snd_seq_ev_clear(&ev);
+ if (snd_midi_event_encode_byte(desc->parser, byte, &ev) == 1) {
+ snd_seq_ev_set_dest(&ev, desc->client, desc->port);
+@@ -339,6 +340,7 @@ static PmError alsa_in_close(PmInternal
+ pm_hosterror = snd_seq_delete_port(seq, desc->this_port);
+ }
+ alsa_unuse_queue();
++ midi->descriptor = NULL;
+ pm_free(desc);
+ if (pm_hosterror) {
+ get_alsa_error_text(pm_hosterror_text, PM_HOST_ERROR_MSG_LEN,
+@@ -433,6 +435,7 @@ static PmError alsa_write(PmInternal *mi
+ static PmError alsa_write_flush(PmInternal *midi, PmTimestamp timestamp)
+ {
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
++ if (!desc) return pmBadPtr;
+ 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;
+@@ -448,6 +451,7 @@ static PmError alsa_write_short(PmIntern
+ PmMessage msg = event->message;
+ int i;
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
++ if (!desc) return pmBadPtr;
+ for (i = 0; i < bytes; i++) {
+ unsigned char byte = msg;
+ VERBOSE printf("sending 0x%x\n", byte);
+@@ -481,6 +485,10 @@ static void handle_event(snd_seq_event_t
+ {
+ int device_id = ev->dest.port;
+ PmInternal *midi = descriptors[device_id].internalDescriptor;
++ /* The device we received events for might have been closed before we
++ processed them. */
++ if (!midi)
++ return;
+ PmEvent pm_ev;
+ PmTimeProcPtr time_proc = midi->time_proc;
+ PmTimestamp timestamp;
+@@ -650,6 +658,7 @@ static PmError alsa_poll(PmInternal *mid
+ static unsigned int alsa_has_host_error(PmInternal *midi)
+ {
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
++ if (!desc) return 0;
+ return desc->error;
+ }
+
+@@ -657,6 +666,7 @@ static unsigned int alsa_has_host_error(
+ static void alsa_get_host_error(PmInternal *midi, char *msg, unsigned int len)
+ {
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
++ if (!desc) return;
+ int err = (pm_hosterror || desc->error);
+ get_alsa_error_text(msg, len, err);
+ }
diff --git a/testing/portmidi/13-disablejni.patch b/testing/portmidi/13-disablejni.patch
new file mode 100644
index 0000000000..cddabe14e0
--- /dev/null
+++ b/testing/portmidi/13-disablejni.patch
@@ -0,0 +1,86 @@
+diff --git a/pm_java/CMakeLists.txt b/pm_java/CMakeLists.txt
+index a350620..b491bbd 100644
+--- a/pm_java/CMakeLists.txt
++++ b/pm_java/CMakeLists.txt
+@@ -1,6 +1,7 @@
+ # pm_java
+
+ if(UNIX)
++else (UNIX)
+ if(APPLE)
+ # java not dealt with in CMake -- see pm_mac/pm_mac.xcodeproj
+ else(APPLE)
+diff --git a/pm_common/CMakeLists.txt b/pm_common/CMakeLists.txt
+index e171047..68ac212 100644
+--- a/pm_common/CMakeLists.txt
++++ b/pm_common/CMakeLists.txt
+@@ -66,19 +66,19 @@ if(UNIX)
+ set(JAVA_INCLUDE_PATHS ${JAVAVM_LIB}/Headers)
+ message(STATUS "SYSROOT: " ${CMAKE_OSX_SYSROOT})
+ else(APPLE)
+- # LINUX settings...
+- include(FindJNI)
+- message(STATUS "JAVA_JVM_LIB_PATH is " ${JAVA_JVM_LIB_PATH})
+- message(STATUS "JAVA_INCLUDE_PATH is " ${JAVA_INCLUDE_PATH})
+- message(STATUS "JAVA_INCLUDE_PATH2 is " ${JAVA_INCLUDE_PATH2})
+- message(STATUS "JAVA_JVM_LIBRARY is " ${JAVA_JVM_LIBRARY})
+- set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
+- # libjvm.so is found relative to JAVA_INCLUDE_PATH:
+- set(JAVAVM_LIB ${JAVA_JVM_LIBRARY}/libjvm.so)
++# # LINUX settings...
++# include(FindJNI)
++# message(STATUS "JAVA_JVM_LIB_PATH is " ${JAVA_JVM_LIB_PATH})
++# message(STATUS "JAVA_INCLUDE_PATH is " ${JAVA_INCLUDE_PATH})
++# message(STATUS "JAVA_INCLUDE_PATH2 is " ${JAVA_INCLUDE_PATH2})
++# message(STATUS "JAVA_JVM_LIBRARY is " ${JAVA_JVM_LIBRARY})
++# set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
++# # libjvm.so is found relative to JAVA_INCLUDE_PATH:
++# set(JAVAVM_LIB ${JAVA_JVM_LIBRARY}/libjvm.so)
+
+ set(LINUXSRC pmlinuxalsa pmlinux finddefault)
+ prepend_path(LIBSRC ../pm_linux/ ${LINUXSRC})
+- list(APPEND LIBSRC ../porttime/ptlinux)
++ #list(APPEND LIBSRC ../porttime/ptlinux)
+
+ set(PM_NEEDED_LIBS pthread asound)
+ endif(APPLE)
+@@ -104,24 +104,24 @@ set(JNI_EXTRA_LIBS ${PM_NEEDED_LIBS} ${JAVA_JVM_LIBRARY})
+ # this completes the list of library sources by adding shared code
+ list(APPEND LIBSRC pmutil portmidi)
+
+-# now add the shared files to make the complete list of library sources
+-add_library(portmidi-static ${LIBSRC})
+-set_target_properties(portmidi-static PROPERTIES OUTPUT_NAME "portmidi_s")
++## now add the shared files to make the complete list of library sources
++add_library(portmidi-static STATIC ${LIBSRC})
++set_target_properties(portmidi-static PROPERTIES OUTPUT_NAME "portmidi")
+ target_link_libraries(portmidi-static ${PM_NEEDED_LIBS})
+-
+-# define the jni library
+-include_directories(${JAVA_INCLUDE_PATHS})
+-
+-set(JNISRC ${LIBSRC} ../pm_java/pmjni/pmjni.c)
+-add_library(pmjni SHARED ${JNISRC})
+-target_link_libraries(pmjni ${JNI_EXTRA_LIBS})
+-set_target_properties(pmjni PROPERTIES EXECUTABLE_EXTENSION "jnilib")
+-
++#
++## define the jni library
++#include_directories(${JAVA_INCLUDE_PATHS})
++#
++#set(JNISRC ${LIBSRC} ../pm_java/pmjni/pmjni.c)
++#add_library(pmjni SHARED ${JNISRC})
++#target_link_libraries(pmjni ${JNI_EXTRA_LIBS})
++#set_target_properties(pmjni PROPERTIES EXECUTABLE_EXTENSION "jnilib")
++#
+ # install the libraries (Linux and Mac OS X command line)
+ if(UNIX)
+- INSTALL(TARGETS portmidi-static pmjni
+- LIBRARY DESTINATION /usr/local/lib
+- ARCHIVE DESTINATION /usr/local/lib)
++ INSTALL(TARGETS portmidi-static
++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
++ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+ # .h files installed by pm_dylib/CMakeLists.txt, so don't need them here
+ # INSTALL(FILES portmidi.h ../porttime/porttime.h
+ # DESTINATION /usr/local/include)
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;
+-}
diff --git a/testing/portmidi/21-hardentests.patch b/testing/portmidi/21-hardentests.patch
new file mode 100644
index 0000000000..9097003fd8
--- /dev/null
+++ b/testing/portmidi/21-hardentests.patch
@@ -0,0 +1,93 @@
+diff --git a/pm_test/latency.c b/pm_test/latency.c
+old mode 100755
+new mode 100644
+index bfcdc0c..87f6a5e
+--- a/pm_test/latency.c
++++ b/pm_test/latency.c
+@@ -280,7 +280,7 @@ int get_number(char *prompt)
+ {
+ char line[STRING_MAX];
+ int n = 0, i;
+- printf(prompt);
++ printf("%s\n", prompt);
+ while (n != 1) {
+ n = scanf("%d", &i);
+ fgets(line, STRING_MAX, stdin);
+diff --git a/pm_test/mm.c b/pm_test/mm.c
+old mode 100755
+new mode 100644
+index 0f2a52e..3f04a30
+--- a/pm_test/mm.c
++++ b/pm_test/mm.c
+@@ -119,7 +119,7 @@ int get_number(char *prompt)
+ {
+ char line[STRING_MAX];
+ int n = 0, i;
+- printf(prompt);
++ printf("%s", prompt);
+ while (n != 1) {
+ n = scanf("%d", &i);
+ fgets(line, STRING_MAX, stdin);
+@@ -136,7 +136,7 @@ void receive_poll(PtTimestamp timestamp, void *userData)
+ if (!active) return;
+ while ((count = Pm_Read(midi_in, &event, 1))) {
+ if (count == 1) output(event.message);
+- else printf(Pm_GetErrorText(count));
++ else printf("%s", Pm_GetErrorText(count));
+ }
+ }
+
+@@ -168,7 +168,7 @@ int main(int argc, char **argv)
+ inp = get_number("Type input device number: ");
+ err = Pm_OpenInput(&midi_in, inp, NULL, 512, NULL, NULL);
+ if (err) {
+- printf(Pm_GetErrorText(err));
++ printf("%s", Pm_GetErrorText(err));
+ Pt_Stop();
+ mmexit(1);
+ }
+@@ -484,7 +484,7 @@ private int put_pitch(int p)
+ "gs", "a", "bf", "b" };
+ /* note octave correction below */
+ sprintf(result, "%s%d", ptos[p % 12], (p / 12) - 1);
+- printf(result);
++ printf("%s\n", result);
+ return strlen(result);
+ }
+
+diff --git a/pm_test/midiclock.c b/pm_test/midiclock.c
+index 60fcf7a..def511a 100644
+--- a/pm_test/midiclock.c
++++ b/pm_test/midiclock.c
+@@ -167,7 +167,7 @@ int get_number(char *prompt)
+ {
+ char line[STRING_MAX];
+ int n = 0, i;
+- printf(prompt);
++ printf("%s", prompt);
+ while (n != 1) {
+ n = scanf("%d", &i);
+ fgets(line, STRING_MAX, stdin);
+@@ -256,7 +256,7 @@ int main(int argc, char **argv)
+ err = Pm_OpenOutput(&midi, outp, DRIVER_INFO, OUTPUT_BUFFER_SIZE,
+ TIME_PROC, TIME_INFO, LATENCY);
+ if (err) {
+- printf(Pm_GetErrorText(err));
++ printf("%s", Pm_GetErrorText(err));
+ goto error_exit_no_device;
+ }
+ active = true;
+diff --git a/pm_test/sysex.c b/pm_test/sysex.c
+index 7bbcf0e..812d979 100755
+--- a/pm_test/sysex.c
++++ b/pm_test/sysex.c
+@@ -39,7 +39,7 @@ int get_number(char *prompt)
+ {
+ char line[STRING_MAX];
+ int n = 0, i;
+- printf(prompt);
++ printf("%s", prompt);
+ while (n != 1) {
+ n = scanf("%d", &i);
+ fgets(line, STRING_MAX, stdin);
+
diff --git a/testing/portmidi/30-porttime_cmake.patch b/testing/portmidi/30-porttime_cmake.patch
new file mode 100644
index 0000000000..f03e33fcae
--- /dev/null
+++ b/testing/portmidi/30-porttime_cmake.patch
@@ -0,0 +1,32 @@
+diff --git a/porttime/CMakeLists.txt b/porttime/CMakeLists.txt
+new file mode 100644
+index 0000000..7c4da89
+--- /dev/null
++++ b/porttime/CMakeLists.txt
+@@ -0,0 +1,13 @@
++if(UNIX)
++ list(APPEND LIBSRC ptlinux)
++ set(PM_NEEDED_LIBS pthread asound)
++ add_library(porttime SHARED ${LIBSRC})
++ set_target_properties(porttime PROPERTIES VERSION "0.0.0" SOVERSION "0")
++ target_link_libraries(porttime ${PM_NEEDED_LIBS})
++ add_library(porttime-static ${LIBSRC})
++ set_target_properties(porttime-static PROPERTIES OUTPUT_NAME "porttime")
++ target_link_libraries(porttime-static ${PM_NEEDED_LIBS})
++ INSTALL(TARGETS porttime porttime-static
++ LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
++ ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}")
++endif(UNIX)
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 4919b78..08301a0 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -74,6 +74,8 @@
+
+ add_subdirectory(pm_dylib)
+
++add_subdirectory(porttime)
++
+ # Cannot figure out how to make an xcode Java application with CMake
+ add_subdirectory(pm_java)
+
diff --git a/testing/portmidi/40-test_sysex.patch b/testing/portmidi/40-test_sysex.patch
new file mode 100644
index 0000000000..66ca01d1f2
--- /dev/null
+++ b/testing/portmidi/40-test_sysex.patch
@@ -0,0 +1,19 @@
+--- a/pm_test/sysex.c
++++ b/pm_test/sysex.c
+@@ -171,7 +171,7 @@
+ if (seconds == 0) seconds = 1;
+ printf("Correctly received %d byte sysex message.\n", i);
+ total_bytes += i;
+- printf("Cummulative bytes/sec: %d\n", total_bytes / seconds);
++ printf("Cummulative bytes/sec: %ld\n", total_bytes / seconds);
+ }
+ }
+ cleanup:
+@@ -231,6 +231,7 @@
+ Pm_WriteSysEx(midi_out, 0, msg);
+ }
+ stop_time = Pt_Time();
++ printf("Delay was: %x\n", start_time - stop_time);
+ Pm_Close(midi_out);
+ return;
+ }
diff --git a/testing/portmidi/41-pm_linux.patch b/testing/portmidi/41-pm_linux.patch
new file mode 100644
index 0000000000..5404bddc67
--- /dev/null
+++ b/testing/portmidi/41-pm_linux.patch
@@ -0,0 +1,77 @@
+--- a/pm_linux/finddefault.c
++++ b/pm_linux/finddefault.c
+@@ -5,10 +5,13 @@
+ #include <stdlib.h>
+ #include <stdio.h>
+ #include <string.h>
++#include <ctype.h>
+ #include "portmidi.h"
+
+ #define STRING_MAX 256
+
++extern int pm_find_default_device(char *pattern, int is_input);
++
+ /* skip over spaces, return first non-space */
+ void skip_spaces(FILE *inf)
+ {
+@@ -26,7 +29,6 @@
+ }
+
+
+-/*
+ /* Parse preference files, find default device, search devices --
+ */
+ PmDeviceID find_default_device(char *path, int input, PmDeviceID id)
+@@ -80,7 +82,7 @@
+ pref_str[i] = c;
+ }
+ if (i == STRING_MAX) continue; // value too long, ignore
+- pref_str[i] == 0;
++ //pref_str[i] == 0;
+ i = pm_find_default_device(pref_str, input);
+ if (i != pmNoDevice) {
+ id = i;
+--- a/pm_linux/pmlinux.c
++++ b/pm_linux/pmlinux.c
+@@ -26,6 +26,8 @@
+ PmDeviceID pm_default_input_device_id = -1;
+ PmDeviceID pm_default_output_device_id = -1;
+
++extern int find_default_device(char *path, int input, PmDeviceID id);
++
+ void pm_init()
+ {
+ /* Note: it is not an error for PMALSA to fail to initialize.
+--- a/pm_linux/pmlinuxalsa.c
++++ b/pm_linux/pmlinuxalsa.c
+@@ -32,9 +32,9 @@
+ #endif
+
+ /* to store client/port in the device descriptor */
+-#define MAKE_DESCRIPTOR(client, port) ((void*)(((client) << 8) | (port)))
+-#define GET_DESCRIPTOR_CLIENT(info) ((((int)(info)) >> 8) & 0xff)
+-#define GET_DESCRIPTOR_PORT(info) (((int)(info)) & 0xff)
++#define MAKE_DESCRIPTOR(client, port) ((void*)((((size_t)client) << 8) | (port)))
++#define GET_DESCRIPTOR_CLIENT(info) ((((size_t)(info)) >> 8) & 0xff)
++#define GET_DESCRIPTOR_PORT(info) (((size_t)(info)) & 0xff)
+
+ #define BYTE unsigned char
+
+@@ -422,7 +422,7 @@
+ }
+ if (desc->error < 0) return pmHostError;
+
+- VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int) seq);
++ VERBOSE printf("snd_seq_drain_output: 0x%zx\n", (size_t) seq);
+ desc->error = snd_seq_drain_output(seq);
+ if (desc->error < 0) return pmHostError;
+
+@@ -436,7 +436,7 @@
+ {
+ alsa_descriptor_type desc = (alsa_descriptor_type) midi->descriptor;
+ if (!desc) return pmBadPtr;
+- VERBOSE printf("snd_seq_drain_output: 0x%x\n", (unsigned int) seq);
++ VERBOSE printf("snd_seq_drain_output: 0x%zx\n", (size_t) seq);
+ desc->error = snd_seq_drain_output(seq);
+ if (desc->error < 0) return pmHostError;
+
diff --git a/testing/portmidi/50-change_assert.patch b/testing/portmidi/50-change_assert.patch
new file mode 100644
index 0000000000..05a2bf709c
--- /dev/null
+++ b/testing/portmidi/50-change_assert.patch
@@ -0,0 +1,41 @@
+diff --git a/pm_common/portmidi.c b/pm_common/portmidi.c
+index b716170..9a469b1 100755
+--- a/pm_common/portmidi.c
++++ b/pm_common/portmidi.c
+@@ -9,7 +9,6 @@
+ #include "porttime.h"
+ #include "pmutil.h"
+ #include "pminternal.h"
+-#include <assert.h>
+
+ #define MIDI_CLOCK 0xf8
+ #define MIDI_ACTIVE 0xfe
+@@ -293,8 +292,8 @@ PMEXPORT const char *Pm_GetErrorText( PmError errnum ) {
+ * The error will always be in the global pm_hosterror_text.
+ */
+ PMEXPORT void Pm_GetHostErrorText(char * msg, unsigned int len) {
+- assert(msg);
+- assert(len > 0);
++ if (!msg) return;
++ if (len <= 0) return;
+ if (pm_hosterror) {
+ strncpy(msg, (char *) pm_hosterror_text, len);
+ pm_hosterror = FALSE;
+@@ -1016,7 +1015,7 @@ void pm_read_short(PmInternal *midi, PmEvent *event)
+ {
+ int status;
+ /* arg checking */
+- assert(midi != NULL);
++ if (!midi) return;
+ /* midi filtering is applied here */
+ status = Pm_MessageStatus(event->message);
+ if (!pm_status_filtered(status, midi->filters)
+@@ -1058,7 +1057,7 @@ unsigned int pm_read_bytes(PmInternal *midi, const unsigned char *data,
+ int i = 0; /* index into data, must not be unsigned (!) */
+ PmEvent event;
+ event.timestamp = timestamp;
+- assert(midi);
++ if (!midi) return 0;
+ /* note that since buffers may not have multiples of 4 bytes,
+ * pm_read_bytes may be called in the middle of an outgoing
+ * 4-byte PortMidi message. sysex_in_progress indicates that
diff --git a/testing/portmidi/51-remove_assert.patch b/testing/portmidi/51-remove_assert.patch
new file mode 100644
index 0000000000..fd29501fdd
--- /dev/null
+++ b/testing/portmidi/51-remove_assert.patch
@@ -0,0 +1,13 @@
+diff --git a/pm_linux/pmlinuxalsa.c b/pm_linux/pmlinuxalsa.c
+index 8e85cfe..1ec3e56 100755
+--- a/pm_linux/pmlinuxalsa.c
++++ b/pm_linux/pmlinuxalsa.c
+@@ -494,7 +494,7 @@ static void handle_event(snd_seq_event_t *ev)
+ PmTimestamp timestamp;
+
+ /* time stamp should be in ticks, using our queue where 1 tick = 1ms */
+- assert((ev->flags & SND_SEQ_TIME_STAMP_MASK) == SND_SEQ_TIME_STAMP_TICK);
++ if ((ev->flags & SND_SEQ_TIME_STAMP_MASK) != SND_SEQ_TIME_STAMP_TICK) return;
+
+ /* if no time_proc, just return "native" ticks (ms) */
+ if (time_proc == NULL) {
diff --git a/testing/portmidi/APKBUILD b/testing/portmidi/APKBUILD
new file mode 100644
index 0000000000..a7b2396b51
--- /dev/null
+++ b/testing/portmidi/APKBUILD
@@ -0,0 +1,63 @@
+# Contributor: Taner Tas <taner76@gmail.com>
+# Maintainer: Taner Tas <taner76@gmail.com>
+pkgname=portmidi
+pkgver=217
+pkgrel=0
+pkgdesc="PortMidi is a platform independent library for MIDI input/output."
+url="http://portmedia.sourceforge.net/"
+arch="all"
+license="MIT"
+makedepends="dos2unix cmake alsa-lib-dev"
+subpackages="$pkgname-dev"
+options="!check" # no testsuite
+source="http://downloads.sourceforge.net/portmedia/$pkgname-src-$pkgver.zip
+ 00_cmake.patch
+ 01_pmlinux.patch
+ 02_pmlinuxalsa.patch
+ 03_pm_test_Makefile.patch
+ 11-pmlinuxalsa.patch
+ 13-disablejni.patch
+ 20-movetest.patch
+ 21-hardentests.patch
+ 30-porttime_cmake.patch
+ 40-test_sysex.patch
+ 41-pm_linux.patch
+ 50-change_assert.patch
+ 51-remove_assert.patch"
+builddir="$srcdir"/$pkgname
+
+prepare() {
+ cd "$builddir"
+ find . -type f -exec dos2unix -s -q {} \;
+ default_prepare
+}
+build() {
+ cd "$builddir"
+ cmake . \
+ -DCMAKE_BUILD_TYPE="Release" \
+ -DCMAKE_INSTALL_PREFIX=/usr \
+ -DCMAKE_INSTALL_LIBDIR=/usr/lib \
+ -DCMAKE_CACHEFILE_DIR="$builddir"/build
+ make
+}
+
+package() {
+ cd "$builddir"
+ make DESTDIR="$pkgdir" install
+ rm -f "$pkgdir"/usr/lib/*.a
+}
+
+sha512sums="d08d4d57429d26d292b5fe6868b7c7a32f2f1d2428f6695cd403a697e2d91629bd4380242ab2720e8f21c895bb75cb56b709fb663a20e8e623120e50bfc5d90b portmidi-src-217.zip
+39a7c30a58f71be517d57d11c1fedfdd7c56cfdf71593f35027323e64c41dd29065791bcce6ce0f373679c9e26caba390867c93904f5efc47605ac05feaccc45 00_cmake.patch
+39ce54128b3f9712d47064557d6331bb9a44e65c2b13e2dd36bc474dfa073b391b0f3a8b01da54b0f56a14379ced2967f22b8822da46afaec62972b732b17442 01_pmlinux.patch
+032c8777dbda6af1b17fdd7664300c41b6a9ccb06ad2a68595fd8d0216fdbef7452f3c407b2be2eb0445d08243adb8929096df1f3f1ee4d032a2928495acda81 02_pmlinuxalsa.patch
+baf8231d0288079b5734e886e8cfe27d48ac5bf4bf181e956f6f0161235d21f3794ef4fcc77e8d6d3a3cf51461fa0c6f065c3b80d711ddfe736f4e6592d65400 03_pm_test_Makefile.patch
+fcfc350e37940fd9ebb070f1efc727f1903a8cf23e21866c56b09766a31479a98676327a981f50905c11e93e32119ef56fef9d3a0de51182a85f175b1dfd3155 11-pmlinuxalsa.patch
+58c638793f5e4eff7782f9844a7d19cb98e7a763497a03f77dbdc15e60a2d3dcfb2ae94cc3bc7a7ddfd880db8d5dd552dff659f1f300f7635b3a484bec35fb60 13-disablejni.patch
+186358ec42a003b943672820ceb71c421b397bb47bb20cdbe92080755bbba3a5238c06632154c72878a92b10e32364d7f8c059fd8f6c864a87a9b9ebe546d15e 20-movetest.patch
+8fa0944be2a70b4aede2a1967e1b38c863812245db6d725c0c253457f3443864a9cfba582d96ff0cc9d8fd1dd38fbb2e04e9447d2bd1abb5d2a933728135e8e4 21-hardentests.patch
+15e529aa8757c4f74a372bcb43748fb0f88d7fc4c858d00199989ad92d0eb0b2edc72d591ba471ee534b38e5756e1c72255ef93c3eb670a64a7b35a973d8368c 30-porttime_cmake.patch
+e52396df909b9ed1f8d58fad929c551a1124a2e5137f635087ac078bdf133162c618a17a9ecc4159acdfc48a640aaae06a4e392aacb1bc69a2389d9cfa18519d 40-test_sysex.patch
+4c56ebc01ed51acec3fe4a0b9fe54a6f61cdcb9640f24a076d94788174c4ebd1fd958adcedb355dc78d9a11a22d79cb276eaa2f5248d5790142bd5ced178172e 41-pm_linux.patch
+e4ffd1d49569b8279baeec45dd22b58a9724b396b927aa6c10198ab135290fbfb570d373b59317dae1d0a26ce71dcaf568325c728bc9302677d6fd28a74f4749 50-change_assert.patch
+a40e268719f949d519285fbed477b587e47434eb9b8d97de5aa4f0e6209e2a24afb8a373d4f7616c88d141525a812e23105f10a0fd457be80c93989286963c56 51-remove_assert.patch"