--- /dev/null
+/*
+ * Simple event decoder
+ */
+
+static char *event_names[256] = {
+ /* 0 */ "System",
+ /* 1 */ "Note",
+ /* 2 */ "Note On",
+ /* 3 */ "Note Off",
+ /* 4 */ "Reserved 4",
+ /* 5 */ "Reserved 5",
+ /* 6 */ "Reserved 6",
+ /* 7 */ "Reserved 7",
+ /* 8 */ "Reserved 8",
+ /* 9 */ "Reserved 9",
+ /* 10 */ "KeyPress",
+ /* 11 */ "Controller",
+ /* 12 */ "Program Change",
+ /* 13 */ "Channel Pressure",
+ /* 14 */ "Pitchbend",
+ /* 15 */ "Control14",
+ /* 16 */ "Nonregparam",
+ /* 17 */ "Regparam",
+ /* 18 */ "Reserved 18",
+ /* 19 */ "Reserved 19",
+ /* 20 */ "Song Position",
+ /* 21 */ "Song Select",
+ /* 22 */ "Clock",
+ /* 23 */ "Start",
+ /* 24 */ "Continue",
+ /* 25 */ "Stop",
+ /* 26 */ "Qframe",
+ /* 27 */ "Reserved 27",
+ /* 28 */ "Reserved 28",
+ /* 29 */ "Reserved 29",
+ /* 30 */ "Tempo",
+ /* 31 */ "SMF Time Signature",
+ /* 32 */ "SMF Key Signature",
+ /* 33 */ "Reserved 33",
+ /* 34 */ "Reserved 34",
+ /* 35 */ "Reserved 35",
+ /* 36 */ "Reserved 36",
+ /* 37 */ "Reserved 37",
+ /* 38 */ "Reserved 38",
+ /* 39 */ "Reserved 39",
+ /* 40 */ "System Exclusive",
+ /* 41 */ "Heart Beat",
+ /* 42 */ "Reserved 42",
+ /* 43 */ "Reserved 43",
+ /* 44 */ "Reserved 44",
+ /* 45 */ "Reserved 45",
+ /* 46 */ "Reserved 46",
+ /* 47 */ "Reserved 47",
+ /* 48 */ "Reserved 48",
+ /* 49 */ "Reserved 49",
+ /* 50 */ "Heart Beat (Active sensing)",
+ /* 51 */ "Echo",
+ /* 52 */ "Reserved 52",
+ /* 53 */ "Reserved 53",
+ /* 54 */ "Reserved 54",
+ /* 55 */ "Reserved 55",
+ /* 56 */ "Reserved 56",
+ /* 57 */ "Reserved 57",
+ /* 58 */ "Reserved 58",
+ /* 59 */ "Reserved 59",
+ /* 60 */ "Client Start",
+ /* 61 */ "Client Exit",
+ /* 62 */ "Client Change",
+ /* 63 */ "Port Start",
+ /* 64 */ "Port Exit",
+ /* 65 */ "Port Change",
+ /* 66 */ "Reserved 66",
+ /* 67 */ "Reserved 67",
+ /* 68 */ "Reserved 68",
+ /* 69 */ "Reserved 69",
+ /* 70 */ "Reserved 70",
+ /* 71 */ "Reserved 71",
+ /* 72 */ "Reserved 72",
+ /* 73 */ "Reserved 73",
+ /* 74 */ "Reserved 74",
+ /* 75 */ "Reserved 75",
+ /* 76 */ "Reserved 76",
+ /* 77 */ "Reserved 77",
+ /* 78 */ "Reserved 78",
+ /* 79 */ "Reserved 79",
+ /* 80 */ "Sample Select",
+ /* 81 */ "Sample Start",
+ /* 82 */ "Sample Stop",
+ /* 83 */ "Sample Frequency",
+ /* 84 */ "Sample Volume",
+ /* 85 */ "Sample Loop",
+ /* 86 */ "Sample Position",
+ /* 87 */ "Reseved 87",
+ /* 88 */ "Reseved 88",
+ /* 89 */ "Reseved 89",
+ /* 90 */ "Reseved 90",
+ /* 91 */ "Reseved 91",
+ /* 92 */ "Reseved 92",
+ /* 93 */ "Reseved 93",
+ /* 94 */ "Reseved 94",
+ /* 95 */ "Reseved 95",
+ /* 96 */ "Reseved 96",
+ /* 97 */ "Reseved 97",
+ /* 98 */ "Reseved 98",
+ /* 99 */ "Reseved 99",
+ /* 100 */ "Reseved 100",
+ /* 101 */ "Reseved 101",
+ /* 102 */ "Reseved 102",
+ /* 103 */ "Reseved 103",
+ /* 104 */ "Reseved 104",
+ /* 105 */ "Reseved 105",
+ /* 106 */ "Reseved 106",
+ /* 107 */ "Reseved 107",
+ /* 108 */ "Reseved 108",
+ /* 109 */ "Reseved 109",
+ /* 100 */ "Reserved 100"
+ /* 101 */ "Reserved 101"
+ /* 102 */ "Reserved 102"
+ /* 103 */ "Reserved 103"
+ /* 104 */ "Reserved 104"
+ /* 105 */ "Reserved 105"
+ /* 106 */ "Reserved 106"
+ /* 107 */ "Reserved 107"
+ /* 108 */ "Reserved 108"
+ /* 109 */ "Reserved 109"
+ /* 110 */ "Reserved 110"
+ /* 111 */ "Reserved 111"
+ /* 112 */ "Reserved 112"
+ /* 113 */ "Reserved 113"
+ /* 114 */ "Reserved 114"
+ /* 115 */ "Reserved 115"
+ /* 116 */ "Reserved 116"
+ /* 117 */ "Reserved 117"
+ /* 118 */ "Reserved 118"
+ /* 119 */ "Reserved 119"
+ /* 120 */ "Reserved 120"
+ /* 121 */ "Reserved 121"
+ /* 122 */ "Reserved 122"
+ /* 123 */ "Reserved 123"
+ /* 124 */ "Reserved 124"
+ /* 125 */ "Reserved 125"
+ /* 126 */ "Reserved 126"
+ /* 127 */ "Reserved 127"
+ /* 128 */ "Reserved 128"
+ /* 129 */ "Reserved 129"
+ /* 130 */ "Reserved 130"
+ /* 131 */ "Reserved 131"
+ /* 132 */ "Reserved 132"
+ /* 133 */ "Reserved 133"
+ /* 134 */ "Reserved 134"
+ /* 135 */ "Reserved 135"
+ /* 136 */ "Reserved 136"
+ /* 137 */ "Reserved 137"
+ /* 138 */ "Reserved 138"
+ /* 139 */ "Reserved 139"
+ /* 140 */ "Reserved 140"
+ /* 141 */ "Reserved 141"
+ /* 142 */ "Reserved 142"
+ /* 143 */ "Reserved 143"
+ /* 144 */ "Reserved 144"
+ /* 145 */ "Reserved 145"
+ /* 146 */ "Reserved 146"
+ /* 147 */ "Reserved 147"
+ /* 148 */ "Reserved 148"
+ /* 149 */ "Reserved 149"
+ /* 150 */ "Reserved 150"
+ /* 151 */ "Reserved 151"
+ /* 152 */ "Reserved 152"
+ /* 153 */ "Reserved 153"
+ /* 154 */ "Reserved 154"
+ /* 155 */ "Reserved 155"
+ /* 156 */ "Reserved 156"
+ /* 157 */ "Reserved 157"
+ /* 158 */ "Reserved 158"
+ /* 159 */ "Reserved 159"
+ /* 160 */ "Reserved 160"
+ /* 161 */ "Reserved 161"
+ /* 162 */ "Reserved 162"
+ /* 163 */ "Reserved 163"
+ /* 164 */ "Reserved 164"
+ /* 165 */ "Reserved 165"
+ /* 166 */ "Reserved 166"
+ /* 167 */ "Reserved 167"
+ /* 168 */ "Reserved 168"
+ /* 169 */ "Reserved 169"
+ /* 170 */ "Reserved 170"
+ /* 171 */ "Reserved 171"
+ /* 172 */ "Reserved 172"
+ /* 173 */ "Reserved 173"
+ /* 174 */ "Reserved 174"
+ /* 175 */ "Reserved 175"
+ /* 176 */ "Reserved 176"
+ /* 177 */ "Reserved 177"
+ /* 178 */ "Reserved 178"
+ /* 179 */ "Reserved 179"
+ /* 180 */ "Reserved 180"
+ /* 181 */ "Reserved 181"
+ /* 182 */ "Reserved 182"
+ /* 183 */ "Reserved 183"
+ /* 184 */ "Reserved 184"
+ /* 185 */ "Reserved 185"
+ /* 186 */ "Reserved 186"
+ /* 187 */ "Reserved 187"
+ /* 188 */ "Reserved 188"
+ /* 189 */ "Reserved 189"
+ /* 190 */ "Reserved 190"
+ /* 191 */ "Reserved 191"
+ /* 192 */ "Reserved 192"
+ /* 193 */ "Reserved 193"
+ /* 194 */ "Reserved 194"
+ /* 195 */ "Reserved 195"
+ /* 196 */ "Reserved 196"
+ /* 197 */ "Reserved 197"
+ /* 198 */ "Reserved 198"
+ /* 199 */ "Reserved 199"
+ /* 200 */ "Reserved 200"
+ /* 201 */ "Reserved 201"
+ /* 202 */ "Reserved 202"
+ /* 203 */ "Reserved 203"
+ /* 204 */ "Reserved 204"
+ /* 205 */ "Reserved 205"
+ /* 206 */ "Reserved 206"
+ /* 207 */ "Reserved 207"
+ /* 208 */ "Reserved 208"
+ /* 209 */ "Reserved 209"
+ /* 210 */ "Reserved 210"
+ /* 211 */ "Reserved 211"
+ /* 212 */ "Reserved 212"
+ /* 213 */ "Reserved 213"
+ /* 214 */ "Reserved 214"
+ /* 215 */ "Reserved 215"
+ /* 216 */ "Reserved 216"
+ /* 217 */ "Reserved 217"
+ /* 218 */ "Reserved 218"
+ /* 219 */ "Reserved 219"
+ /* 220 */ "Reserved 220"
+ /* 221 */ "Reserved 221"
+ /* 222 */ "Reserved 222"
+ /* 223 */ "Reserved 223"
+ /* 224 */ "Reserved 224"
+ /* 225 */ "Reserved 225"
+ /* 226 */ "Reserved 226"
+ /* 227 */ "Reserved 227"
+ /* 228 */ "Reserved 228"
+ /* 229 */ "Reserved 229"
+ /* 230 */ "Reserved 230"
+ /* 231 */ "Reserved 231"
+ /* 232 */ "Reserved 232"
+ /* 233 */ "Reserved 233"
+ /* 234 */ "Reserved 234"
+ /* 235 */ "Reserved 235"
+ /* 236 */ "Reserved 236"
+ /* 237 */ "Reserved 237"
+ /* 238 */ "Reserved 238"
+ /* 239 */ "Reserved 239"
+ /* 240 */ "Reserved 240"
+ /* 241 */ "Reserved 241"
+ /* 242 */ "Reserved 242"
+ /* 243 */ "Reserved 243"
+ /* 244 */ "Reserved 244"
+ /* 245 */ "Reserved 245"
+ /* 246 */ "Reserved 246"
+ /* 247 */ "Reserved 247"
+ /* 248 */ "Reserved 248"
+ /* 249 */ "Reserved 249"
+ /* 250 */ "Reserved 250"
+ /* 251 */ "Reserved 251"
+ /* 252 */ "Reserved 252"
+ /* 253 */ "Reserved 253"
+ /* 254 */ "Reserved 254"
+ /* 255 */ "Reserved 255"
+};
+
+int decode_event(snd_seq_event_t * ev)
+{
+ char *space = " ";
+
+ printf("EVENT>>> Type = %d, flags = 0x%x", ev->type, ev->flags);
+ switch (ev->flags & SND_SEQ_TIME_STAMP_MASK) {
+ case SND_SEQ_TIME_STAMP_TICK:
+ printf(", time = %d ticks",
+ ev->time.tick);
+ break;
+ case SND_SEQ_TIME_STAMP_REAL:
+ printf(", time = %d.%09d",
+ (int)ev->time.real.tv_sec,
+ (int)ev->time.real.tv_nsec);
+ break;
+ }
+ printf("\n%sSource = %d.%d.%d.%d, dest = %d.%d.%d.%d\n",
+ space,
+ ev->source.queue,
+ ev->source.client,
+ ev->source.port,
+ ev->source.channel,
+ ev->dest.queue,
+ ev->dest.client,
+ ev->dest.port,
+ ev->dest.channel);
+
+ printf("%sEvent = %s", space, event_names[ev->type]);
+ /* decode actual event data... */
+ switch (ev->type) {
+ case SND_SEQ_EVENT_NOTE:
+ printf("; note=%d, velocity=%d, duration=%d\n",
+ ev->data.note.note,
+ ev->data.note.velocity,
+ ev->data.note.duration);
+ break;
+
+ case SND_SEQ_EVENT_NOTEON:
+ case SND_SEQ_EVENT_NOTEOFF:
+ printf("; note=%d, velocity=%d\n",
+ ev->data.note.note,
+ ev->data.note.velocity);
+ break;
+
+ case SND_SEQ_EVENT_KEYPRESS:
+ case SND_SEQ_EVENT_CONTROLLER:
+ printf("; param=%i, value=%i\n",
+ ev->data.control.param,
+ ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_PGMCHANGE:
+ printf("; program=%i\n", ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_CHANPRESS:
+ case SND_SEQ_EVENT_PITCHBEND:
+ printf("; value=%i\n", ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_SYSEX:
+ {
+ unsigned char *sysex = (unsigned char *) ev + sizeof(snd_seq_event_t);
+ int c;
+
+ printf("; len=%d [", ev->data.ext.len);
+
+ for (c = 0; c < ev->data.ext.len; c++) {
+ printf("%02x%s", sysex[c], c < ev->data.ext.len - 1 ? ":" : "");
+ }
+ printf("]\n");
+ }
+ break;
+
+ case SND_SEQ_EVENT_QFRAME:
+ printf("; frame=%i\n", ev->data.control.value);
+ break;
+
+ case SND_SEQ_EVENT_CLOCK:
+ case SND_SEQ_EVENT_START:
+ case SND_SEQ_EVENT_CONTINUE:
+ case SND_SEQ_EVENT_STOP:
+ printf("; queue = %i, client = %i\n", ev->data.addr.queue, ev->data.addr.client);
+ break;
+
+ case SND_SEQ_EVENT_HEARTBEAT:
+ printf("\n");
+ break;
+
+ case SND_SEQ_EVENT_ECHO:
+ {
+ int i;
+
+ printf("; ");
+ for (i = 0; i < 8; i++) {
+ printf("%02i%s", ev->data.raw8.d[i], i < 7 ? ":" : "\n");
+ }
+ }
+ break;
+
+ case SND_SEQ_EVENT_CLIENT_START:
+ case SND_SEQ_EVENT_CLIENT_EXIT:
+ case SND_SEQ_EVENT_CLIENT_CHANGE:
+ printf("; client=%i\n", ev->data.addr.client);
+ break;
+
+ case SND_SEQ_EVENT_PORT_START:
+ case SND_SEQ_EVENT_PORT_EXIT:
+ case SND_SEQ_EVENT_PORT_CHANGE:
+ printf("; client=%i, port = %i\n", ev->data.addr.client, ev->data.addr.port);
+ break;
+
+ default:
+ printf("; not implemented\n");
+ }
+
+
+ switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
+ case SND_SEQ_EVENT_LENGTH_FIXED:
+ return sizeof(snd_seq_event_t);
+
+ case SND_SEQ_EVENT_LENGTH_VARIABLE:
+ return sizeof(snd_seq_event_t) + ev->data.ext.len;
+ }
+
+ return 0;
+}
+
+void event_decoder_start_timer(void *handle, int queue, int client, int port)
+{
+ int err;
+ snd_seq_event_t ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.source.queue = queue;
+ ev.source.client = client;
+ ev.source.port = 0;
+ ev.dest.queue = queue;
+ ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+ ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+ ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL;
+ ev.type = SND_SEQ_EVENT_START;
+ if ((err = snd_seq_event_output(handle, &ev))<0)
+ fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
+ while (snd_seq_flush_output(handle)>0)
+ sleep(1);
+}
+
+void event_decoder(void *handle, int argc, char *argv[])
+{
+ snd_seq_event_t *ev;
+ snd_seq_port_info_t port;
+ snd_seq_port_subscribe_t sub;
+ fd_set in;
+ int client, queue, max, err, v1, v2;
+ char *ptr;
+
+ if ((client = snd_seq_client_id(handle))<0) {
+ fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
+ return;
+ }
+ printf("Client ID = %i\n", client);
+ if ((queue = snd_seq_alloc_queue(handle, NULL))<0) {
+ fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
+ return;
+ }
+ printf("Queue ID = %i\n", queue);
+ if ((err = snd_seq_block_mode(handle, 0))<0)
+ fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
+ bzero(&port, sizeof(port));
+ strcpy(port.name, "Input");
+ if ((err = snd_seq_create_port(handle, &port)) < 0) {
+ fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
+ return;
+ }
+ event_decoder_start_timer(handle, queue, client, port.port);
+
+ bzero(&sub, sizeof(sub));
+ sub.sender.queue = queue;
+ sub.sender.client = SND_SEQ_CLIENT_SYSTEM;
+ sub.sender.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
+ sub.dest.queue = queue;
+ sub.dest.client = client;
+ sub.dest.port = port.port;
+ sub.exclusive = 0;
+ sub.realtime = 1;
+ if ((err = snd_seq_subscribe_port(handle, &sub))<0) {
+ fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err));
+ return;
+ }
+ sub.sender.port = SND_SEQ_PORT_SYSTEM_TIMER;
+ if ((err = snd_seq_subscribe_port(handle, &sub))<0) {
+ fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err));
+ return;
+ }
+
+ for (max = 0; max < argc; max++) {
+ ptr = argv[max];
+ if (!ptr)
+ continue;
+ sub.realtime = 0;
+ if (tolower(*ptr) == 'r') {
+ sub.realtime = 1;
+ ptr++;
+ }
+ if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
+ fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
+ return;
+ }
+ sub.sender.client = v1;
+ sub.sender.port = v2;
+ if ((err = snd_seq_subscribe_port(handle, &sub))<0) {
+ fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
+ return;
+ }
+ }
+
+ while (1) {
+ FD_ZERO(&in);
+ FD_SET(max = snd_seq_file_descriptor(handle), &in);
+ if (select(max + 1, &in, NULL, NULL, NULL) < 0)
+ break;
+ do {
+ if ((err = snd_seq_event_input(handle, &ev))<0)
+ break;
+ if (!ev)
+ continue;
+ decode_event(ev);
+ snd_seq_free_event(ev);
+ } while (err > 0);
+ }
+}
--- /dev/null
+/*
+ * Simple event sender
+ */
+
+void event_sender_start_timer(void *handle, int client, int queue)
+{
+ int err;
+ snd_seq_event_t ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.source.queue = queue;
+ ev.source.client = client;
+ ev.source.port = 0;
+ ev.dest.queue = queue;
+ ev.dest.client = SND_SEQ_CLIENT_SYSTEM;
+ ev.dest.port = SND_SEQ_PORT_SYSTEM_TIMER;
+ ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_REL;
+ ev.type = SND_SEQ_EVENT_START;
+ if ((err = snd_seq_event_output(handle, &ev))<0)
+ fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
+ while (snd_seq_flush_output(handle)>0)
+ sleep(1);
+}
+
+void event_sender_filter(void *handle)
+{
+ int err;
+ snd_seq_client_info_t info;
+
+ if ((err = snd_seq_get_client_info(handle, &info)) < 0) {
+ fprintf(stderr, "Unable to get client info: %s\n", snd_strerror(err));
+ return;
+ }
+ info.filter = SND_SEQ_FILTER_USE_EVENT;
+ memset(&info.event_filter, 0, sizeof(info.event_filter));
+ snd_seq_set_bit(SND_SEQ_EVENT_ECHO, info.event_filter);
+ if ((err = snd_seq_set_client_info(handle, &info)) < 0) {
+ fprintf(stderr, "Unable to set client info: %s\n", snd_strerror(err));
+ return;
+ }
+}
+
+void send_event(void *handle, int queue, int client, int port,
+ snd_seq_port_subscribe_t *sub, int *time)
+{
+ int err;
+ snd_seq_event_t ev;
+
+ bzero(&ev, sizeof(ev));
+ ev.source.queue = ev.dest.queue = queue;
+ ev.source.client = ev.dest.client = client;
+ ev.source.port = ev.dest.port = port;
+ ev.flags = SND_SEQ_TIME_STAMP_REAL | SND_SEQ_TIME_MODE_ABS;
+ ev.time.real.tv_sec = *time; (*time)++;
+ ev.type = SND_SEQ_EVENT_ECHO;
+ if ((err = snd_seq_event_output(handle, &ev))<0)
+ fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
+ ev.dest.client = sub->dest.client;
+ ev.dest.port = sub->dest.port;
+ ev.dest.channel = 0;
+ ev.type = SND_SEQ_EVENT_NOTE;
+ ev.data.note.note = 64 + (queue*2);
+ ev.data.note.velocity = 127;
+ ev.data.note.duration = 500; /* 0.5sec */
+ if ((err = snd_seq_event_output(handle, &ev))<0)
+ fprintf(stderr, "Event output error: %s\n", snd_strerror(err));
+ if ((err = snd_seq_flush_output(handle))<0)
+ fprintf(stderr, "Event flush error: %s\n", snd_strerror(err));
+}
+
+void event_sender(void *handle, int argc, char *argv[])
+{
+ snd_seq_event_t *ev;
+ snd_seq_port_info_t port;
+ snd_seq_port_subscribe_t sub;
+ fd_set out, in;
+ int client, queue, max, err, v1, v2, time = 0;
+ char *ptr;
+
+ if (argc != 1) {
+ fprintf(stderr, "Invalid destonation...\n");
+ return;
+ }
+
+ if ((client = snd_seq_client_id(handle))<0) {
+ fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
+ return;
+ }
+ printf("Client ID = %i\n", client);
+ if ((queue = snd_seq_alloc_queue(handle, NULL))<0) {
+ fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
+ return;
+ }
+ printf("Queue ID = %i\n", queue);
+ event_sender_filter(handle);
+ if ((err = snd_seq_block_mode(handle, 0))<0)
+ fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
+ event_sender_start_timer(handle, client, queue);
+ bzero(&port, sizeof(port));
+ strcpy(port.name, "Output");
+ if ((err = snd_seq_create_port(handle, &port)) < 0) {
+ fprintf(stderr, "Cannot create output port: %s\n", snd_strerror(err));
+ return;
+ }
+
+ bzero(&sub, sizeof(sub));
+ sub.sender.queue = queue;
+ sub.sender.client = client;
+ sub.sender.port = port.port;
+ sub.dest.queue = queue;
+ sub.exclusive = 0;
+
+ for (max = 0; max < argc; max++) {
+ ptr = argv[max];
+ if (!ptr)
+ continue;
+ if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
+ fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
+ return;
+ }
+ sub.dest.client = v1;
+ sub.dest.port = v2;
+ if ((err = snd_seq_subscribe_port(handle, &sub))<0) {
+ fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
+ return;
+ }
+ }
+
+ printf("Destonation client = %i, port = %i\n", sub.dest.client, sub.dest.port);
+
+ while (1) {
+ FD_ZERO(&out);
+ FD_ZERO(&in);
+ FD_SET(max = snd_seq_file_descriptor(handle), &out);
+ FD_SET(max = snd_seq_file_descriptor(handle), &in);
+ if (select(max + 1, &in, &out, NULL, NULL) < 0)
+ break;
+ if (FD_ISSET(max, &out)) {
+ send_event(handle, queue, client, port.port, &sub, &time);
+ }
+ if (FD_ISSET(max, &in)) {
+ do {
+ if ((err = snd_seq_event_input(handle, &ev))<0)
+ break;
+ if (!ev)
+ continue;
+ decode_event(ev);
+ snd_seq_free_event(ev);
+ } while (err > 0);
+ }
+ }
+}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#include <getopt.h>
+#include "../include/asoundlib.h"
+
+#include "seq-decoder.c"
+#include "seq-sender.c"
+
+#define SEQ_VERSION "0.0.1"
+
+#define HELPID_HELP 1000
+#define HELPID_DEBUG 1001
+#define HELPID_VERBOSE 1002
+#define HELPID_VERSION 1003
+
+snd_seq_system_info_t sysinfo;
+int debug = 0;
+int verbose = 0;
+
+void set_name(void *handle)
+{
+ int err;
+ snd_seq_client_info_t info;
+
+ bzero(&info, sizeof(info));
+ snprintf(info.name, sizeof(info.name), "SeqUtil - %i", getpid());
+ if ((err = snd_seq_set_client_info(handle, &info)) < 0) {
+ fprintf(stderr, "Set client info error: %s\n", snd_strerror(err));
+ exit(0);
+ }
+}
+
+void system_info(void *handle)
+{
+ int err;
+
+ if ((err = snd_seq_system_info(handle, &sysinfo))<0) {
+ fprintf(stderr, "System info error: %s\n", snd_strerror(err));
+ exit(0);
+ }
+}
+
+void show_system_info(void *handle)
+{
+ printf("System info\n");
+ printf(" Max queues : %i\n", sysinfo.queues);
+ printf(" Max clients : %i\n", sysinfo.clients);
+ printf(" Max ports : %i\n", sysinfo.ports);
+}
+
+void show_queue_info(void *handle, int queue)
+{
+ int err, idx, min, max;
+ snd_seq_queue_info_t info;
+
+ min = queue < 0 ? 0 : queue;
+ max = queue < 0 ? sysinfo.queues : queue + 1;
+ for (idx = min; idx < max; idx++) {
+ if ((err = snd_seq_get_queue_info(handle, idx, &info))<0) {
+ if (err == -ENOENT)
+ continue;
+ fprintf(stderr, "Client %i info error: %s\n", idx, snd_strerror(err));
+ exit(0);
+ }
+ printf("Queue %i info\n", info.queue);
+ printf(" Tick : %u\n", info.tick);
+ printf(" Realtime : %i.%i\n", info.time.tv_sec, info.time.tv_nsec);
+ printf(" Running : %i\n", info.running);
+ printf(" Tempo : %i\n", info.tempo);
+ printf(" PPQ : %i\n", info.ppq);
+ printf(" Flags : 0x%x\n", info.flags);
+ printf(" Owner : %i\n", info.owner);
+ printf(" Locked : %i\n", info.locked);
+ }
+}
+
+void show_port_info(void *handle, int client, int port)
+{
+ int err, idx, min, max;
+ snd_seq_port_info_t info;
+
+ min = port < 0 ? 0 : port;
+ max = port < 0 ? sysinfo.ports : port + 1;
+ for (idx = min; idx < max; idx++) {
+ if ((err = snd_seq_get_any_port_info(handle, client, idx, &info))<0) {
+ if (err == -ENOENT)
+ continue;
+ fprintf(stderr, "Port %i/%i info error: %s\n", client, idx, snd_strerror(err));
+ exit(0);
+ }
+ printf(" Port %i info\n", idx);
+ printf(" Client : %i\n", info.client);
+ printf(" Port : %i\n", info.port);
+ printf(" Name : %s\n", info.name);
+ printf(" Capability : 0x%x\n", info.capability);
+ printf(" Type : 0x%x\n", info.type);
+ printf(" Midi channels : %i\n", info.midi_channels);
+ printf(" Synth voices : %i\n", info.synth_voices);
+ printf(" Subscribers : %i\n", info.subscribers);
+ printf(" Use : %i\n", info.use);
+ }
+}
+
+void show_client_info(void *handle, int client)
+{
+ int err, idx, min, max;
+ snd_seq_client_info_t info;
+
+ min = client < 0 ? 0 : client;
+ max = client < 0 ? sysinfo.clients : client + 1;
+ for (idx = min; idx < max; idx++) {
+ if ((err = snd_seq_get_any_client_info(handle, idx, &info))<0) {
+ if (err == -ENOENT)
+ continue;
+ fprintf(stderr, "Client %i info error: %s\n", idx, snd_strerror(err));
+ exit(0);
+ }
+ printf("Client %i info\n", idx);
+ if (verbose)
+ printf(" Client : %i\n", info.client);
+ printf(" Type : %s\n", info.type == KERNEL_CLIENT ? "kernel" : "user");
+ printf(" Name : %s\n", info.name);
+ }
+}
+
+static void help(void)
+{
+ printf("Usage: seq <options> command\n");
+ printf("\nAvailable options:\n");
+ printf(" -h,--help this help\n");
+ printf(" -d,--debug debug mode\n");
+ printf(" -v,--verbose verbose mode\n");
+ printf(" -V,--version print version of this program\n");
+ printf("\nAvailable commands:\n");
+ printf(" system show basic sequencer info\n");
+ printf(" queue [#] show all queues or specified queue\n");
+ printf(" client [#] show all clients or specified client\n");
+ printf(" port <client> [#] show all ports or specified port for specified client\n");
+ printf(" decoder event decoder\n");
+}
+
+int main(int argc, char *argv[])
+{
+ int morehelp, err, arg, arg1;
+ void *handle;
+ static struct option long_option[] =
+ {
+ {"help", 0, NULL, HELPID_HELP},
+ {"debug", 0, NULL, HELPID_DEBUG},
+ {"verbose", 0, NULL, HELPID_VERBOSE},
+ {"version", 0, NULL, HELPID_VERSION},
+ {NULL, 0, NULL, 0},
+ };
+
+ while (1) {
+ int c;
+
+ if ((c = getopt_long(argc, argv, "hdvV", long_option, NULL)) < 0)
+ break;
+ switch (c) {
+ case 'h':
+ case HELPID_HELP:
+ morehelp++;
+ break;
+ case 'd':
+ case HELPID_DEBUG:
+ debug = 1;
+ break;
+ case 'v':
+ case HELPID_VERBOSE:
+ verbose = 1;
+ break;
+ case 'V':
+ case HELPID_VERSION:
+ printf("alsactl version " SEQ_VERSION "\n");
+ return 1;
+ default:
+ fprintf(stderr, "\07Invalid switch or option needs an argument.\n");
+ morehelp++;
+ }
+ }
+ if (morehelp) {
+ help();
+ return 1;
+ }
+ if (argc - optind <= 0) {
+ fprintf(stderr, "seq: Specify command...\n");
+ return 0;
+ }
+ if ((err = snd_seq_open(&handle, SND_SEQ_OPEN))<0) {
+ fprintf(stderr, "Open error: %s\n", snd_strerror(err));
+ exit(0);
+ }
+ set_name(handle);
+ system_info(handle);
+ if (!strcmp(argv[optind], "system")) {
+ show_system_info(handle);
+ } else if (!strcmp(argv[optind], "queue")) {
+ arg = argc - optind > 1 ? atoi(argv[optind + 1]) : -1;
+ show_queue_info(handle, arg);
+ } else if (!strcmp(argv[optind], "client")) {
+ arg = argc - optind > 1 ? atoi(argv[optind + 1]) : -1;
+ show_client_info(handle, arg);
+ } else if (!strcmp(argv[optind], "port")) {
+ arg = argc - optind > 1 ? atoi(argv[optind + 1]) : -1;
+ if (arg < 0) {
+ fprintf(stderr, "Specify port...\n");
+ exit(0);
+ }
+ arg1 = argc - optind > 2 ? atoi(argv[optind + 2]) : -1;
+ show_port_info(handle, arg, arg1);
+ } else if (!strcmp(argv[optind], "decoder")) {
+ event_decoder(handle, argc - optind - 1, argv + optind + 1);
+ } else if (!strcmp(argv[optind], "sender")) {
+ event_sender(handle, argc - optind - 1, argv + optind + 1);
+ } else {
+ help();
+ }
+ exit(1);
+}