1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  Simple event decoder
3d5ac70f0Sopenharmony_ci */
4d5ac70f0Sopenharmony_ci
5d5ac70f0Sopenharmony_cistatic char *event_names[256] = {
6d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SYSTEM]=	"System",
7d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_RESULT]=	"Result",
8d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_NOTE]=	"Note",
9d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_NOTEON]=	"Note On",
10d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_NOTEOFF]=	"Note Off",
11d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_KEYPRESS]=	"Key Pressure",
12d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CONTROLLER]=	"Controller",
13d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PGMCHANGE]=	"Program Change",
14d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CHANPRESS]=	"Channel Pressure",
15d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PITCHBEND]=	"Pitchbend",
16d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CONTROL14]=	"Control14",
17d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_NONREGPARAM]=	"Nonregparam",
18d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_REGPARAM]=		"Regparam",
19d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SONGPOS]=	"Song Position",
20d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SONGSEL]=	"Song Select",
21d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_QFRAME]=	"Qframe",
22d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_TIMESIGN]=	"SMF Time Signature",
23d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_KEYSIGN]=	"SMF Key Signature",
24d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_START]=	"Start",
25d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CONTINUE]=	"Continue",
26d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_STOP]=	"Stop",
27d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SETPOS_TICK]=	"Set Position Tick",
28d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SETPOS_TIME]=	"Set Position Time",
29d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_TEMPO]=	"Tempo",
30d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CLOCK]=	"Clock",
31d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_TICK]=	"Tick",
32d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_TUNE_REQUEST]=	"Tune Request",
33d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_RESET]=	"Reset",
34d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SENSING]=	"Active Sensing",
35d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_ECHO]=	"Echo",
36d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_OSS]=	"OSS",
37d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CLIENT_START]=	"Client Start",
38d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CLIENT_EXIT]=	"Client Exit",
39d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_CLIENT_CHANGE]=	"Client Change",
40d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PORT_START]=	"Port Start",
41d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PORT_EXIT]=	"Port Exit",
42d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PORT_CHANGE]=	"Port Change",
43d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PORT_SUBSCRIBED]=	"Port Subscribed",
44d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_PORT_UNSUBSCRIBED]=	"Port Unsubscribed",
45d5ac70f0Sopenharmony_ci#if 0
46d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE]=	"Sample",
47d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_CLUSTER]=	"Sample Cluster",
48d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_START]=	"Sample Start",
49d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_STOP]=	"Sample Stop",
50d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_FREQ]=	"Sample Freq",
51d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_VOLUME]=	"Sample Volume",
52d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_LOOP]=	"Sample Loop",
53d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_POSITION]=	"Sample Position",
54d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SAMPLE_PRIVATE1]=	"Sample Private1",
55d5ac70f0Sopenharmony_ci#endif
56d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR0]=	"User 0",
57d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR1]=	"User 1",
58d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR2]=	"User 2",
59d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR3]=	"User 3",
60d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR4]=	"User 4",
61d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR5]=	"User 5",
62d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR6]=	"User 6",
63d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR7]=	"User 7",
64d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR8]=	"User 8",
65d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR9]=	"User 9",
66d5ac70f0Sopenharmony_ci#if 0
67d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_BEGIN]=	"Instr Begin",
68d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_END]=	"Instr End",
69d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_INFO]=	"Instr Info",
70d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_INFO_RESULT]=	"Instr Info Result",
71d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_FINFO]=	"Instr Font Info",
72d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_FINFO_RESULT]=	"Instr Font Info Result",
73d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_RESET]=	"Instr Reset",
74d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_STATUS]=	"Instr Status",
75d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_STATUS_RESULT]=	"Instr Status Result",
76d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_PUT]=	"Instr Put",
77d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_GET]=	"Instr Get",
78d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_GET_RESULT]=	"Instr Get Result",
79d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_FREE]=	"Instr Free",
80d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_LIST]=	"Instr List",
81d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_LIST_RESULT]=	"Instr List Result",
82d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_CLUSTER]=	"Instr Cluster",
83d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_CLUSTER_GET]=	"Instr Cluster Get",
84d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_CLUSTER_RESULT]=	"Instr Cluster Result",
85d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_INSTR_CHANGE]=	"Instr Change",
86d5ac70f0Sopenharmony_ci#endif
87d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_SYSEX]=	"Sysex",
88d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_BOUNCE]=	"Bounce",
89d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VAR0]=	"User Var0",
90d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VAR1]=	"User Var1",
91d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VAR2]=	"User Var2",
92d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VAR3]=	"User Var3",
93d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VAR4]=	"User Var4",
94d5ac70f0Sopenharmony_ci#if 0
95d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_IPCSHM]=	"IPC Shm",
96d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VARIPC0]=	"User IPC0",
97d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VARIPC1]=	"User IPC1",
98d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VARIPC2]=	"User IPC2",
99d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VARIPC3]=	"User IPC3",
100d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_USR_VARIPC4]=	"User IPC4",
101d5ac70f0Sopenharmony_ci#endif
102d5ac70f0Sopenharmony_ci	[SND_SEQ_EVENT_NONE]=	"None",
103d5ac70f0Sopenharmony_ci};
104d5ac70f0Sopenharmony_ci
105d5ac70f0Sopenharmony_ciint decode_event(snd_seq_event_t * ev)
106d5ac70f0Sopenharmony_ci{
107d5ac70f0Sopenharmony_ci	char *space = "         ";
108d5ac70f0Sopenharmony_ci
109d5ac70f0Sopenharmony_ci	printf("EVENT>>> Type = %d, flags = 0x%x", ev->type, ev->flags);
110d5ac70f0Sopenharmony_ci	switch (ev->flags & SND_SEQ_TIME_STAMP_MASK) {
111d5ac70f0Sopenharmony_ci	case SND_SEQ_TIME_STAMP_TICK:
112d5ac70f0Sopenharmony_ci		printf(", time = %d ticks",
113d5ac70f0Sopenharmony_ci		       ev->time.tick);
114d5ac70f0Sopenharmony_ci		break;
115d5ac70f0Sopenharmony_ci	case SND_SEQ_TIME_STAMP_REAL:
116d5ac70f0Sopenharmony_ci		printf(", time = %d.%09d",
117d5ac70f0Sopenharmony_ci		       (int)ev->time.time.tv_sec,
118d5ac70f0Sopenharmony_ci		       (int)ev->time.time.tv_nsec);
119d5ac70f0Sopenharmony_ci		break;
120d5ac70f0Sopenharmony_ci	}
121d5ac70f0Sopenharmony_ci	printf("\n%sSource = %d.%d, dest = %d.%d, queue = %d\n",
122d5ac70f0Sopenharmony_ci	       space,
123d5ac70f0Sopenharmony_ci	       ev->source.client,
124d5ac70f0Sopenharmony_ci	       ev->source.port,
125d5ac70f0Sopenharmony_ci	       ev->dest.client,
126d5ac70f0Sopenharmony_ci	       ev->dest.port,
127d5ac70f0Sopenharmony_ci	       ev->queue);
128d5ac70f0Sopenharmony_ci
129d5ac70f0Sopenharmony_ci	if (event_names[ev->type])
130d5ac70f0Sopenharmony_ci		printf("%sEvent = %s", space, event_names[ev->type]);
131d5ac70f0Sopenharmony_ci	else
132d5ac70f0Sopenharmony_ci		printf("%sEvent = Reserved %d\n", space, ev->type);
133d5ac70f0Sopenharmony_ci	/* decode the actual event data... */
134d5ac70f0Sopenharmony_ci	switch (ev->type) {
135d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_NOTE:
136d5ac70f0Sopenharmony_ci		printf("; ch=%d, note=%d, velocity=%d, off_velocity=%d, duration=%d\n",
137d5ac70f0Sopenharmony_ci		       ev->data.note.channel,
138d5ac70f0Sopenharmony_ci		       ev->data.note.note,
139d5ac70f0Sopenharmony_ci		       ev->data.note.velocity,
140d5ac70f0Sopenharmony_ci		       ev->data.note.off_velocity,
141d5ac70f0Sopenharmony_ci		       ev->data.note.duration);
142d5ac70f0Sopenharmony_ci		break;
143d5ac70f0Sopenharmony_ci
144d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_NOTEON:
145d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_NOTEOFF:
146d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_KEYPRESS:
147d5ac70f0Sopenharmony_ci		printf("; ch=%d, note=%d, velocity=%d\n",
148d5ac70f0Sopenharmony_ci		       ev->data.note.channel,
149d5ac70f0Sopenharmony_ci		       ev->data.note.note,
150d5ac70f0Sopenharmony_ci		       ev->data.note.velocity);
151d5ac70f0Sopenharmony_ci		break;
152d5ac70f0Sopenharmony_ci
153d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CONTROLLER:
154d5ac70f0Sopenharmony_ci		printf("; ch=%d, param=%i, value=%i\n",
155d5ac70f0Sopenharmony_ci		       ev->data.control.channel,
156d5ac70f0Sopenharmony_ci		       ev->data.control.param,
157d5ac70f0Sopenharmony_ci		       ev->data.control.value);
158d5ac70f0Sopenharmony_ci		break;
159d5ac70f0Sopenharmony_ci
160d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PGMCHANGE:
161d5ac70f0Sopenharmony_ci		printf("; ch=%d, program=%i\n",
162d5ac70f0Sopenharmony_ci		       ev->data.control.channel,
163d5ac70f0Sopenharmony_ci		       ev->data.control.value);
164d5ac70f0Sopenharmony_ci		break;
165d5ac70f0Sopenharmony_ci
166d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CHANPRESS:
167d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PITCHBEND:
168d5ac70f0Sopenharmony_ci		printf("; ch=%d, value=%i\n",
169d5ac70f0Sopenharmony_ci		       ev->data.control.channel,
170d5ac70f0Sopenharmony_ci		       ev->data.control.value);
171d5ac70f0Sopenharmony_ci		break;
172d5ac70f0Sopenharmony_ci
173d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_SYSEX:
174d5ac70f0Sopenharmony_ci		{
175d5ac70f0Sopenharmony_ci			unsigned char *sysex = (unsigned char *) ev + sizeof(snd_seq_event_t);
176d5ac70f0Sopenharmony_ci			unsigned int c;
177d5ac70f0Sopenharmony_ci
178d5ac70f0Sopenharmony_ci			printf("; len=%d [", ev->data.ext.len);
179d5ac70f0Sopenharmony_ci
180d5ac70f0Sopenharmony_ci			for (c = 0; c < ev->data.ext.len; c++) {
181d5ac70f0Sopenharmony_ci				printf("%02x%s", sysex[c], c < ev->data.ext.len - 1 ? ":" : "");
182d5ac70f0Sopenharmony_ci			}
183d5ac70f0Sopenharmony_ci			printf("]\n");
184d5ac70f0Sopenharmony_ci		}
185d5ac70f0Sopenharmony_ci		break;
186d5ac70f0Sopenharmony_ci
187d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_QFRAME:
188d5ac70f0Sopenharmony_ci		printf("; frame=0x%02x\n", ev->data.control.value);
189d5ac70f0Sopenharmony_ci		break;
190d5ac70f0Sopenharmony_ci
191d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CLOCK:
192d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_START:
193d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CONTINUE:
194d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_STOP:
195d5ac70f0Sopenharmony_ci		printf("; queue = %i\n", ev->data.queue.queue);
196d5ac70f0Sopenharmony_ci		break;
197d5ac70f0Sopenharmony_ci
198d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_SENSING:
199d5ac70f0Sopenharmony_ci		printf("\n");
200d5ac70f0Sopenharmony_ci		break;
201d5ac70f0Sopenharmony_ci
202d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_ECHO:
203d5ac70f0Sopenharmony_ci		{
204d5ac70f0Sopenharmony_ci			int i;
205d5ac70f0Sopenharmony_ci
206d5ac70f0Sopenharmony_ci			printf("; ");
207d5ac70f0Sopenharmony_ci			for (i = 0; i < 8; i++) {
208d5ac70f0Sopenharmony_ci				printf("%02i%s", ev->data.raw8.d[i], i < 7 ? ":" : "\n");
209d5ac70f0Sopenharmony_ci			}
210d5ac70f0Sopenharmony_ci		}
211d5ac70f0Sopenharmony_ci		break;
212d5ac70f0Sopenharmony_ci
213d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CLIENT_START:
214d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CLIENT_EXIT:
215d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_CLIENT_CHANGE:
216d5ac70f0Sopenharmony_ci		printf("; client=%i\n", ev->data.addr.client);
217d5ac70f0Sopenharmony_ci		break;
218d5ac70f0Sopenharmony_ci
219d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PORT_START:
220d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PORT_EXIT:
221d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PORT_CHANGE:
222d5ac70f0Sopenharmony_ci		printf("; client=%i, port = %i\n", ev->data.addr.client, ev->data.addr.port);
223d5ac70f0Sopenharmony_ci		break;
224d5ac70f0Sopenharmony_ci
225d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PORT_SUBSCRIBED:
226d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_PORT_UNSUBSCRIBED:
227d5ac70f0Sopenharmony_ci		printf("; %i:%i -> %i:%i\n",
228d5ac70f0Sopenharmony_ci		       ev->data.connect.sender.client, ev->data.connect.sender.port,
229d5ac70f0Sopenharmony_ci		       ev->data.connect.dest.client, ev->data.connect.dest.port);
230d5ac70f0Sopenharmony_ci		break;
231d5ac70f0Sopenharmony_ci
232d5ac70f0Sopenharmony_ci	default:
233d5ac70f0Sopenharmony_ci		printf("; not implemented\n");
234d5ac70f0Sopenharmony_ci	}
235d5ac70f0Sopenharmony_ci
236d5ac70f0Sopenharmony_ci
237d5ac70f0Sopenharmony_ci	switch (ev->flags & SND_SEQ_EVENT_LENGTH_MASK) {
238d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_LENGTH_FIXED:
239d5ac70f0Sopenharmony_ci		return sizeof(snd_seq_event_t);
240d5ac70f0Sopenharmony_ci
241d5ac70f0Sopenharmony_ci	case SND_SEQ_EVENT_LENGTH_VARIABLE:
242d5ac70f0Sopenharmony_ci		return sizeof(snd_seq_event_t) + ev->data.ext.len;
243d5ac70f0Sopenharmony_ci	}
244d5ac70f0Sopenharmony_ci
245d5ac70f0Sopenharmony_ci	return 0;
246d5ac70f0Sopenharmony_ci}
247d5ac70f0Sopenharmony_ci
248d5ac70f0Sopenharmony_civoid event_decoder_start_timer(snd_seq_t *handle, int queue,
249d5ac70f0Sopenharmony_ci			       int client ATTRIBUTE_UNUSED,
250d5ac70f0Sopenharmony_ci			       int port ATTRIBUTE_UNUSED)
251d5ac70f0Sopenharmony_ci{
252d5ac70f0Sopenharmony_ci	int err;
253d5ac70f0Sopenharmony_ci
254d5ac70f0Sopenharmony_ci	if ((err = snd_seq_start_queue(handle, queue, NULL))<0)
255d5ac70f0Sopenharmony_ci		fprintf(stderr, "Timer event output error: %s\n", snd_strerror(err));
256d5ac70f0Sopenharmony_ci	while (snd_seq_drain_output(handle)>0)
257d5ac70f0Sopenharmony_ci		sleep(1);
258d5ac70f0Sopenharmony_ci}
259d5ac70f0Sopenharmony_ci
260d5ac70f0Sopenharmony_civoid event_decoder(snd_seq_t *handle, int argc, char *argv[])
261d5ac70f0Sopenharmony_ci{
262d5ac70f0Sopenharmony_ci	snd_seq_event_t *ev;
263d5ac70f0Sopenharmony_ci	snd_seq_port_info_t *pinfo;
264d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_t *sub;
265d5ac70f0Sopenharmony_ci	snd_seq_addr_t addr;
266d5ac70f0Sopenharmony_ci	int client, port, queue, max, err, v1, v2;
267d5ac70f0Sopenharmony_ci	char *ptr;
268d5ac70f0Sopenharmony_ci	struct pollfd *pfds;
269d5ac70f0Sopenharmony_ci
270d5ac70f0Sopenharmony_ci	if ((client = snd_seq_client_id(handle))<0) {
271d5ac70f0Sopenharmony_ci		fprintf(stderr, "Cannot determine client number: %s\n", snd_strerror(client));
272d5ac70f0Sopenharmony_ci		return;
273d5ac70f0Sopenharmony_ci	}
274d5ac70f0Sopenharmony_ci	printf("Client ID = %i\n", client);
275d5ac70f0Sopenharmony_ci	if ((queue = snd_seq_alloc_queue(handle))<0) {
276d5ac70f0Sopenharmony_ci		fprintf(stderr, "Cannot allocate queue: %s\n", snd_strerror(queue));
277d5ac70f0Sopenharmony_ci		return;
278d5ac70f0Sopenharmony_ci	}
279d5ac70f0Sopenharmony_ci	printf("Queue ID = %i\n", queue);
280d5ac70f0Sopenharmony_ci	if ((err = snd_seq_nonblock(handle, 1))<0)
281d5ac70f0Sopenharmony_ci		fprintf(stderr, "Cannot set nonblock mode: %s\n", snd_strerror(err));
282d5ac70f0Sopenharmony_ci	snd_seq_port_info_alloca(&pinfo);
283d5ac70f0Sopenharmony_ci	snd_seq_port_info_set_name(pinfo, "Input");
284d5ac70f0Sopenharmony_ci	snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC);
285d5ac70f0Sopenharmony_ci	snd_seq_port_info_set_capability(pinfo, SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_READ | SND_SEQ_PORT_CAP_SUBS_WRITE);
286d5ac70f0Sopenharmony_ci
287d5ac70f0Sopenharmony_ci	/* Enable timestamping for events sent by external subscribers. */
288d5ac70f0Sopenharmony_ci	snd_seq_port_info_set_timestamping(pinfo, 1);
289d5ac70f0Sopenharmony_ci	snd_seq_port_info_set_timestamp_real(pinfo, 1);
290d5ac70f0Sopenharmony_ci	snd_seq_port_info_set_timestamp_queue(pinfo, queue);
291d5ac70f0Sopenharmony_ci
292d5ac70f0Sopenharmony_ci	if ((err = snd_seq_create_port(handle, pinfo)) < 0) {
293d5ac70f0Sopenharmony_ci		fprintf(stderr, "Cannot create input port: %s\n", snd_strerror(err));
294d5ac70f0Sopenharmony_ci		return;
295d5ac70f0Sopenharmony_ci	}
296d5ac70f0Sopenharmony_ci	port = snd_seq_port_info_get_port(pinfo);
297d5ac70f0Sopenharmony_ci	event_decoder_start_timer(handle, queue, client, port);
298d5ac70f0Sopenharmony_ci
299d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_alloca(&sub);
300d5ac70f0Sopenharmony_ci	addr.client = SND_SEQ_CLIENT_SYSTEM;
301d5ac70f0Sopenharmony_ci	addr.port = SND_SEQ_PORT_SYSTEM_ANNOUNCE;
302d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_set_sender(sub, &addr);
303d5ac70f0Sopenharmony_ci	addr.client = client;
304d5ac70f0Sopenharmony_ci	addr.port = port;
305d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_set_dest(sub, &addr);
306d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_set_queue(sub, queue);
307d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_set_time_update(sub, 1);
308d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_set_time_real(sub, 1);
309d5ac70f0Sopenharmony_ci	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
310d5ac70f0Sopenharmony_ci		fprintf(stderr, "Cannot subscribe announce port: %s\n", snd_strerror(err));
311d5ac70f0Sopenharmony_ci		return;
312d5ac70f0Sopenharmony_ci	}
313d5ac70f0Sopenharmony_ci
314d5ac70f0Sopenharmony_ci	addr.client = SND_SEQ_CLIENT_SYSTEM;
315d5ac70f0Sopenharmony_ci	addr.port = SND_SEQ_PORT_SYSTEM_TIMER;
316d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_set_sender(sub, &addr);
317d5ac70f0Sopenharmony_ci	if ((err = snd_seq_subscribe_port(handle, sub))<0) {
318d5ac70f0Sopenharmony_ci		fprintf(stderr, "Cannot subscribe timer port: %s\n", snd_strerror(err));
319d5ac70f0Sopenharmony_ci		return;
320d5ac70f0Sopenharmony_ci	}
321d5ac70f0Sopenharmony_ci
322d5ac70f0Sopenharmony_ci	for (max = 0; max < argc; max++) {
323d5ac70f0Sopenharmony_ci		ptr = argv[max];
324d5ac70f0Sopenharmony_ci		if (!ptr)
325d5ac70f0Sopenharmony_ci			continue;
326d5ac70f0Sopenharmony_ci		snd_seq_port_subscribe_set_time_real(sub, 0);
327d5ac70f0Sopenharmony_ci		if (tolower(*ptr) == 'r') {
328d5ac70f0Sopenharmony_ci			snd_seq_port_subscribe_set_time_real(sub, 1);
329d5ac70f0Sopenharmony_ci			ptr++;
330d5ac70f0Sopenharmony_ci		}
331d5ac70f0Sopenharmony_ci		if (sscanf(ptr, "%i.%i", &v1, &v2) != 2) {
332d5ac70f0Sopenharmony_ci			fprintf(stderr, "Wrong argument '%s'...\n", argv[max]);
333d5ac70f0Sopenharmony_ci			return;
334d5ac70f0Sopenharmony_ci		}
335d5ac70f0Sopenharmony_ci		addr.client = v1;
336d5ac70f0Sopenharmony_ci		addr.port = v2;
337d5ac70f0Sopenharmony_ci		snd_seq_port_subscribe_set_sender(sub, &addr);
338d5ac70f0Sopenharmony_ci		if ((err = snd_seq_subscribe_port(handle, sub))<0) {
339d5ac70f0Sopenharmony_ci			fprintf(stderr, "Cannot subscribe port %i from client %i: %s\n", v2, v1, snd_strerror(err));
340d5ac70f0Sopenharmony_ci			return;
341d5ac70f0Sopenharmony_ci		}
342d5ac70f0Sopenharmony_ci	}
343d5ac70f0Sopenharmony_ci
344d5ac70f0Sopenharmony_ci	max = snd_seq_poll_descriptors_count(handle, POLLIN);
345d5ac70f0Sopenharmony_ci	pfds = alloca(sizeof(*pfds) * max);
346d5ac70f0Sopenharmony_ci	while (1) {
347d5ac70f0Sopenharmony_ci		snd_seq_poll_descriptors(handle, pfds, max, POLLIN);
348d5ac70f0Sopenharmony_ci		if (poll(pfds, max, -1) < 0)
349d5ac70f0Sopenharmony_ci			break;
350d5ac70f0Sopenharmony_ci		do {
351d5ac70f0Sopenharmony_ci			if ((err = snd_seq_event_input(handle, &ev))<0)
352d5ac70f0Sopenharmony_ci				break;
353d5ac70f0Sopenharmony_ci			if (!ev)
354d5ac70f0Sopenharmony_ci				continue;
355d5ac70f0Sopenharmony_ci			decode_event(ev);
356d5ac70f0Sopenharmony_ci			snd_seq_free_event(ev);
357d5ac70f0Sopenharmony_ci		} while (err > 0);
358d5ac70f0Sopenharmony_ci	}
359d5ac70f0Sopenharmony_ci}
360