summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/portmidi/pm_test/virttest.c
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/portmidi/pm_test/virttest.c')
-rw-r--r--3rdparty/portmidi/pm_test/virttest.c339
1 files changed, 339 insertions, 0 deletions
diff --git a/3rdparty/portmidi/pm_test/virttest.c b/3rdparty/portmidi/pm_test/virttest.c
new file mode 100644
index 00000000000..1aeb09b8c54
--- /dev/null
+++ b/3rdparty/portmidi/pm_test/virttest.c
@@ -0,0 +1,339 @@
+/* virttest.c -- test for creating/deleting virtual ports */
+/*
+ * Roger B. Dannenberg
+ * Oct 2021
+
+This test is performed by running 2 instances of the program. The
+first instance makes input and output ports named portmidi and waits
+for a message. The second tries to do the same, but will fail because
+portmidi already exists. It then opens portmidi (both input and
+output). In greater detail:
+
+FIRST INSTANCE SECOND INSTANCE
+-------------- ---------------
+
+initialize PortMidi initialize PortMidi
+create portmidi in
+create portmidi out
+wait for input
+ create portmidi in -> fails
+ open portmidi in/out
+ send to portmidi
+recv from portmidi
+send to portmidi
+wait 1s recv from portmidi
+ close portmidi in and out
+ terminate PortMidi
+list all devices:
+ - check for correct number
+ - check for good description of portmidi in port (open)
+ - check for good description of portmidi out port (open)
+close portmidi in
+list all devices:
+ - check for correct number
+ - check for good description of portmidi in port (closed)
+ - check for good description of portmidi out port (open)
+close portmidi out
+list all devices:
+ - check for correct number
+ - check for good description of portmidi in port (closed)
+ - check for good description of portmidi out port (closed)
+delete portmidi in
+ - check for correct number
+ - check for NULL description of portmidi in port
+ - check for good description of portmidi out port (closed)
+delete portmidi out
+ - check for correct number
+ - check for NULL description of portmidi in port
+ - check for NULL description of portmidi out port
+terminate portmidi
+REPEAT 3 TIMES wait 2 seconds to give head start to other instance
+ REPEAT 3 TIMES
+ */
+
+#include "portmidi.h"
+#include "porttime.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include "string.h"
+#include "assert.h"
+
+#define OUTPUT_BUFFER_SIZE 0
+#define INPUT_BUFFER_SIZE 10
+#define DEVICE_INFO NULL
+#define DRIVER_INFO NULL
+#define TIME_PROC ((PmTimeProcPtr) Pt_Time)
+#define TIME_INFO NULL
+#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */
+
+
+static void prompt_and_exit(void)
+{
+ printf("type ENTER...");
+ while (getchar() != '\n') ;
+ /* this will clean up open ports: */
+ exit(-1);
+}
+
+
+static PmError printerror(PmError err, const char *msg)
+{
+ if (err == pmHostError) {
+ /* it seems pointless to allocate memory and copy the string,
+ * so I will do the work of Pm_GetHostErrorText directly
+ */
+ char errmsg[80];
+ Pm_GetHostErrorText(errmsg, 80);
+ printf("%s\n %s\n", msg, errmsg);
+ } else if (err < 0) {
+ printf("%s\n %s\n", msg, Pm_GetErrorText(err));
+ }
+ return err;
+}
+
+
+static PmError checkerror(PmError err)
+{
+ if (err < 0) {
+ printerror(err, "PortMidi call failed...");
+ prompt_and_exit();
+ }
+ return err;
+}
+
+
+void wait_until(PmTimestamp when)
+{
+ PtTimestamp now = Pt_Time();
+ if (when > now) {
+ Pt_Sleep(when - now);
+ }
+}
+
+
+void show_usage()
+{
+ printf("Usage: virttest\n"
+ " run two instances to test virtual port create/delete\n");
+}
+
+
+void check_info(int id, char stat, int input, int virtual)
+{
+ const PmDeviceInfo *info = Pm_GetDeviceInfo(id);
+ if (stat == 'd') {
+ if (info) {
+ printf("Expected device %d to be deleted.\n", id);
+ prompt_and_exit();
+ }
+ return;
+ }
+ if (!info) {
+ printf("Expected device %d to not be deleted.\n", id);
+ prompt_and_exit();
+ }
+ if (strcmp("portmidi", info->name) != 0) {
+ printf("Device %d name is %s, not \"portmidi\".\n", id, info->name);
+ prompt_and_exit();
+ }
+ if (info->input != input || (!info->output) != input) {
+ printf("Device %d input/output fields are wrong.\n", id);
+ prompt_and_exit();
+ }
+ if ((!info->opened && stat == 'o') || (info->opened && stat == 'c')) {
+ printf("Device %d opened==%d, status should be %c.\n", id,
+ info->opened, stat);
+ prompt_and_exit();
+ }
+ if (info->is_virtual != virtual) {
+ printf("Expected device %d to be virtual.\n", id);
+ prompt_and_exit();
+ }
+}
+
+
+/* stat is 'o' for open, 'c' for closed, 'd' for deleted device */
+void check_ports(int cnt, int in_id, char in_stat,
+ int out_id, char out_stat, int virtual)
+{
+ if (cnt != Pm_CountDevices()) {
+ printf("Device count changed from %d to %d.\n", cnt, Pm_CountDevices());
+ prompt_and_exit();
+ }
+ check_info(in_id, in_stat, TRUE, virtual);
+ check_info(out_id, out_stat, FALSE, virtual);
+}
+
+
+void devices_list()
+{
+ int i;
+ for (i = 0; i < Pm_CountDevices(); i++) {
+ const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+ if (info) {
+ printf("%d: %s %s %s %s\n", i, info->name,
+ (info->input ? "input" : "output"),
+ (info->is_virtual ? "virtual" : "real_device"),
+ (info->opened ? "opened" : "closed"));
+ }
+ }
+}
+
+
+void test2()
+{
+ PmStream *out = NULL;
+ PmStream *in = NULL;
+ int out_id;
+ int in_id;
+ PmEvent buffer[1];
+ PmTimestamp timestamp;
+ int pitch = 60;
+ int device_count = 0;
+ int i;
+
+ printf("This must be virttest instance #2\n");
+
+ /* find and open portmidi in and out */
+ device_count = Pm_CountDevices();
+ for (i = 0; i < device_count; i++) {
+ const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+ if (info && strcmp(info->name, "portmidi") == 0) {
+ if (info->input) {
+ checkerror(Pm_OpenInput(&in, i, DRIVER_INFO,
+ INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO));
+ in_id = i;
+ } else {
+ checkerror(Pm_OpenOutput(&out, i, DRIVER_INFO,
+ OUTPUT_BUFFER_SIZE, NULL, NULL, 0));
+ out_id = i;
+ }
+ }
+ }
+ if (!in) {
+ printf("Did not open portmidi as input (virtual output).\n");
+ prompt_and_exit();
+ }
+ if (!out) {
+ printf("Did not open portmidi as output (virtual input).\n");
+ prompt_and_exit();
+ }
+ printf("Input device %d and output device %d are open.\n", in_id, out_id);
+
+ /* send a message */
+ buffer[0].timestamp = 0;
+ buffer[0].message = Pm_Message(0x90, pitch, 100);
+ checkerror(Pm_Write(out, buffer, 1));
+
+ /* wait for reply */
+ printf("Sent message, waiting for reply...\n");
+ while (Pm_Read(in, buffer, 1) < 1) Pt_Sleep(10);
+
+ printf("********** GOT THE MESSAGE, SHUTTING DOWN ************\n");
+
+ /* close in */
+ checkerror(Pm_Close(in));
+ check_ports(device_count, in_id, 'c', out_id, 'o', FALSE);
+ printf("Closed input %d\n", in_id);
+
+ /* close out */
+ checkerror(Pm_Close(out));
+ check_ports(device_count, in_id, 'c', out_id, 'c', FALSE);
+ printf("Closed output %d\n", out_id);
+
+ Pt_Sleep(1000);
+ /* wrap it up */
+ Pm_Terminate();
+ printf("Got reply and terminated...\n");
+ Pt_Sleep(2000); /* 2 seconds because other is waiting 1s. */
+ /* 1 more second to make sure other shuts down before test repeats. */
+}
+
+extern int pm_check_errors;
+
+void test()
+{
+ PmStream *out;
+ PmStream *in;
+ int out_id;
+ int in_id;
+ PmEvent buffer[1];
+ PmTimestamp timestamp;
+ int device_count = 0;
+
+ TIME_START;
+
+ printf("******** INITIALIZING PORTMIDI ***********\n");
+ timestamp = Pt_Time();
+ Pm_Initialize();
+ printf("Pm_Initialize took %dms\n", Pt_Time() - timestamp);
+ devices_list();
+
+ pm_check_errors = FALSE; /* otherwise, PM_CHECK_ERRORS, if defined, */
+ /* can cause this program to report an error and exit on pmNameConflict. */
+ in_id = Pm_CreateVirtualInput("portmidi", NULL, DEVICE_INFO);
+ pm_check_errors = TRUE; /* there should be no other errors */
+ if (in_id < 0) {
+ printerror(in_id, "Pm_CreateVirtualInput failed...");
+ test2();
+ return;
+ }
+ printf("Created portmidi virtual input; this is virttest instance #1\n");
+ out_id = checkerror(Pm_CreateVirtualOutput("portmidi", NULL, DRIVER_INFO));
+ device_count = Pm_CountDevices();
+
+ checkerror(Pm_OpenInput(&in, in_id, NULL, 0, NULL, NULL));
+ checkerror(Pm_OpenOutput(&out, out_id, DRIVER_INFO, OUTPUT_BUFFER_SIZE,
+ TIME_PROC, TIME_INFO, 0));
+ printf("Created/Opened input %d and output %d\n", in_id, out_id);
+ Pm_SetFilter(in, PM_FILT_ACTIVE | PM_FILT_CLOCK | PM_FILT_SYSEX);
+ /* empty the buffer after setting filter, just in case anything
+ got through */
+ while (Pm_Read(in, buffer, 1)) ;
+
+ /* wait for input */
+ printf("Waiting for input...\n");
+ while (Pm_Read(in, buffer, 1) < 1) Pt_Sleep(10);
+
+ /* send two replies (only one would be fine) */
+ checkerror(Pm_Write(out, buffer, 1));
+ printf("Received input, writing output...\n");
+
+ /* wait 1s so receiver can get the message before we shut down */
+ Pt_Sleep(1000);
+ printf("****** Closing everything and shutting down...\n");
+
+ /* expect 2 open ports */
+ check_ports(device_count, in_id, 'o', out_id, 'o', TRUE);
+ /* close in */
+ checkerror(Pm_Close(in));
+ check_ports(device_count, in_id, 'c', out_id, 'o', TRUE);
+
+ /* close out */
+ checkerror(Pm_Close(out));
+ check_ports(device_count, in_id, 'c', out_id, 'c', TRUE);
+
+ /* delete in */
+ checkerror(Pm_DeleteVirtualDevice(in_id));
+ check_ports(device_count, in_id, 'd', out_id, 'c', TRUE);
+
+ /* delete out */
+ checkerror(Pm_DeleteVirtualDevice(out_id));
+ check_ports(device_count, in_id, 'd', out_id, 'd', TRUE);
+
+ /* we are done */
+ Pm_Terminate();
+}
+
+
+int main(int argc, char *argv[])
+{
+ int i;
+ show_usage();
+ for (i = 0; i < 3; i++) {
+ test();
+ }
+ printf("finished virttest (SUCCESS). Type ENTER to quit...");
+ while (getchar() != '\n') ;
+ return 0;
+}