1d5ac70f0Sopenharmony_ci#include "config.h"
2d5ac70f0Sopenharmony_ci
3d5ac70f0Sopenharmony_ci#include <stdio.h>
4d5ac70f0Sopenharmony_ci#include <stdlib.h>
5d5ac70f0Sopenharmony_ci#include <string.h>
6d5ac70f0Sopenharmony_ci#include <errno.h>
7d5ac70f0Sopenharmony_ci#include <ctype.h>
8d5ac70f0Sopenharmony_ci#include <getopt.h>
9d5ac70f0Sopenharmony_ci#include "../include/asoundlib.h"
10d5ac70f0Sopenharmony_ci
11d5ac70f0Sopenharmony_ci#include "seq-decoder.c"
12d5ac70f0Sopenharmony_ci#include "seq-sender.c"
13d5ac70f0Sopenharmony_ci
14d5ac70f0Sopenharmony_ci#define SEQ_VERSION "0.0.1"
15d5ac70f0Sopenharmony_ci
16d5ac70f0Sopenharmony_ci#define HELPID_HELP             1000
17d5ac70f0Sopenharmony_ci#define HELPID_DEBUG            1001
18d5ac70f0Sopenharmony_ci#define HELPID_VERBOSE		1002
19d5ac70f0Sopenharmony_ci#define HELPID_VERSION          1003
20d5ac70f0Sopenharmony_ci
21d5ac70f0Sopenharmony_ciint max_clients;
22d5ac70f0Sopenharmony_ciint max_ports;
23d5ac70f0Sopenharmony_ciint max_queues;
24d5ac70f0Sopenharmony_ciint debug = 0;
25d5ac70f0Sopenharmony_ciint verbose = 0;
26d5ac70f0Sopenharmony_ci
27d5ac70f0Sopenharmony_civoid set_name(snd_seq_t *handle)
28d5ac70f0Sopenharmony_ci{
29d5ac70f0Sopenharmony_ci	int err;
30d5ac70f0Sopenharmony_ci	char name[64];
31d5ac70f0Sopenharmony_ci
32d5ac70f0Sopenharmony_ci	sprintf(name, "SeqUtil - %i", getpid());
33d5ac70f0Sopenharmony_ci	if ((err = snd_seq_set_client_name(handle, name)) < 0) {
34d5ac70f0Sopenharmony_ci		fprintf(stderr, "Set client info error: %s\n", snd_strerror(err));
35d5ac70f0Sopenharmony_ci		exit(0);
36d5ac70f0Sopenharmony_ci	}
37d5ac70f0Sopenharmony_ci}
38d5ac70f0Sopenharmony_ci
39d5ac70f0Sopenharmony_civoid system_info(snd_seq_t *handle)
40d5ac70f0Sopenharmony_ci{
41d5ac70f0Sopenharmony_ci	int err;
42d5ac70f0Sopenharmony_ci	snd_seq_system_info_t *sysinfo;
43d5ac70f0Sopenharmony_ci
44d5ac70f0Sopenharmony_ci	snd_seq_system_info_alloca(&sysinfo);
45d5ac70f0Sopenharmony_ci	if ((err = snd_seq_system_info(handle, sysinfo))<0) {
46d5ac70f0Sopenharmony_ci		fprintf(stderr, "System info error: %s\n", snd_strerror(err));
47d5ac70f0Sopenharmony_ci		exit(0);
48d5ac70f0Sopenharmony_ci	}
49d5ac70f0Sopenharmony_ci	max_clients = snd_seq_system_info_get_clients(sysinfo);
50d5ac70f0Sopenharmony_ci	max_ports = snd_seq_system_info_get_ports(sysinfo);
51d5ac70f0Sopenharmony_ci	max_queues = snd_seq_system_info_get_ports(sysinfo);
52d5ac70f0Sopenharmony_ci}
53d5ac70f0Sopenharmony_ci
54d5ac70f0Sopenharmony_civoid show_system_info(snd_seq_t *handle ATTRIBUTE_UNUSED)
55d5ac70f0Sopenharmony_ci{
56d5ac70f0Sopenharmony_ci	printf("System info\n");
57d5ac70f0Sopenharmony_ci	printf("  Max queues    : %i\n", max_queues);
58d5ac70f0Sopenharmony_ci	printf("  Max clients   : %i\n", max_clients);
59d5ac70f0Sopenharmony_ci	printf("  Max ports     : %i\n", max_ports);
60d5ac70f0Sopenharmony_ci}
61d5ac70f0Sopenharmony_ci
62d5ac70f0Sopenharmony_civoid show_queue_status(snd_seq_t *handle, int queue)
63d5ac70f0Sopenharmony_ci{
64d5ac70f0Sopenharmony_ci	int err, idx, min, max;
65d5ac70f0Sopenharmony_ci	snd_seq_queue_status_t *status;
66d5ac70f0Sopenharmony_ci
67d5ac70f0Sopenharmony_ci	snd_seq_queue_status_alloca(&status);
68d5ac70f0Sopenharmony_ci	min = queue < 0 ? 0 : queue;
69d5ac70f0Sopenharmony_ci	max = queue < 0 ? max_queues : queue + 1;
70d5ac70f0Sopenharmony_ci	for (idx = min; idx < max; idx++) {
71d5ac70f0Sopenharmony_ci		if ((err = snd_seq_get_queue_status(handle, idx, status))<0) {
72d5ac70f0Sopenharmony_ci			if (err == -ENOENT)
73d5ac70f0Sopenharmony_ci				continue;
74d5ac70f0Sopenharmony_ci			fprintf(stderr, "Client %i info error: %s\n", idx, snd_strerror(err));
75d5ac70f0Sopenharmony_ci			exit(0);
76d5ac70f0Sopenharmony_ci		}
77d5ac70f0Sopenharmony_ci		printf("Queue %i info\n", snd_seq_queue_status_get_queue(status));
78d5ac70f0Sopenharmony_ci		printf("  Tick          : %u\n", snd_seq_queue_status_get_tick_time(status));
79d5ac70f0Sopenharmony_ci		printf("  Realtime      : %i.%i\n",
80d5ac70f0Sopenharmony_ci		       snd_seq_queue_status_get_real_time(status)->tv_sec,
81d5ac70f0Sopenharmony_ci		       snd_seq_queue_status_get_real_time(status)->tv_nsec);
82d5ac70f0Sopenharmony_ci		printf("  Flags         : 0x%x\n", snd_seq_queue_status_get_status(status));
83d5ac70f0Sopenharmony_ci	}
84d5ac70f0Sopenharmony_ci}
85d5ac70f0Sopenharmony_ci
86d5ac70f0Sopenharmony_civoid show_port_info(snd_seq_t *handle, int client, int port)
87d5ac70f0Sopenharmony_ci{
88d5ac70f0Sopenharmony_ci	int err, idx, min, max;
89d5ac70f0Sopenharmony_ci	snd_seq_port_info_t *info;
90d5ac70f0Sopenharmony_ci
91d5ac70f0Sopenharmony_ci	snd_seq_port_info_alloca(&info);
92d5ac70f0Sopenharmony_ci	min = port < 0 ? 0 : port;
93d5ac70f0Sopenharmony_ci	max = port < 0 ? max_ports : port + 1;
94d5ac70f0Sopenharmony_ci	for (idx = min; idx < max; idx++) {
95d5ac70f0Sopenharmony_ci		if ((err = snd_seq_get_any_port_info(handle, client, idx, info))<0) {
96d5ac70f0Sopenharmony_ci			if (err == -ENOENT)
97d5ac70f0Sopenharmony_ci				continue;
98d5ac70f0Sopenharmony_ci			fprintf(stderr, "Port %i/%i info error: %s\n", client, idx, snd_strerror(err));
99d5ac70f0Sopenharmony_ci			exit(0);
100d5ac70f0Sopenharmony_ci		}
101d5ac70f0Sopenharmony_ci		printf("  Port %i info\n", idx);
102d5ac70f0Sopenharmony_ci		printf("    Client        : %i\n", snd_seq_port_info_get_client(info));
103d5ac70f0Sopenharmony_ci		printf("    Port          : %i\n", snd_seq_port_info_get_port(info));
104d5ac70f0Sopenharmony_ci		printf("    Name          : %s\n", snd_seq_port_info_get_name(info));
105d5ac70f0Sopenharmony_ci		printf("    Capability    : 0x%x\n", snd_seq_port_info_get_capability(info));
106d5ac70f0Sopenharmony_ci		printf("    Type          : 0x%x\n", snd_seq_port_info_get_type(info));
107d5ac70f0Sopenharmony_ci		//printf("    Midi channels : %i\n", info.midi_channels);
108d5ac70f0Sopenharmony_ci		//printf("    Synth voices  : %i\n", info.synth_voices);
109d5ac70f0Sopenharmony_ci		printf("    Output subs   : %i\n", snd_seq_port_info_get_write_use(info));
110d5ac70f0Sopenharmony_ci		printf("    Input subs    : %i\n", snd_seq_port_info_get_read_use(info));
111d5ac70f0Sopenharmony_ci	}
112d5ac70f0Sopenharmony_ci}
113d5ac70f0Sopenharmony_ci
114d5ac70f0Sopenharmony_civoid show_client_info(snd_seq_t *handle, int client)
115d5ac70f0Sopenharmony_ci{
116d5ac70f0Sopenharmony_ci	int err, idx, min, max;
117d5ac70f0Sopenharmony_ci	snd_seq_client_info_t *info;
118d5ac70f0Sopenharmony_ci
119d5ac70f0Sopenharmony_ci	snd_seq_client_info_alloca(&info);
120d5ac70f0Sopenharmony_ci	min = client < 0 ? 0 : client;
121d5ac70f0Sopenharmony_ci	max = client < 0 ? max_clients : client + 1;
122d5ac70f0Sopenharmony_ci	for (idx = min; idx < max; idx++) {
123d5ac70f0Sopenharmony_ci		if ((err = snd_seq_get_any_client_info(handle, idx, info))<0) {
124d5ac70f0Sopenharmony_ci			if (err == -ENOENT)
125d5ac70f0Sopenharmony_ci				continue;
126d5ac70f0Sopenharmony_ci			fprintf(stderr, "Client %i info error: %s\n", idx, snd_strerror(err));
127d5ac70f0Sopenharmony_ci			exit(0);
128d5ac70f0Sopenharmony_ci		}
129d5ac70f0Sopenharmony_ci		printf("Client %i info\n", idx);
130d5ac70f0Sopenharmony_ci		if (verbose)
131d5ac70f0Sopenharmony_ci			printf("  Client        : %i\n", snd_seq_client_info_get_client(info));
132d5ac70f0Sopenharmony_ci		printf("  Type          : %s\n", snd_seq_client_info_get_type(info) == SND_SEQ_KERNEL_CLIENT ? "kernel" : "user");
133d5ac70f0Sopenharmony_ci		printf("  Name          : %s\n", snd_seq_client_info_get_name(info));
134d5ac70f0Sopenharmony_ci	}
135d5ac70f0Sopenharmony_ci}
136d5ac70f0Sopenharmony_ci
137d5ac70f0Sopenharmony_cistatic void help(void)
138d5ac70f0Sopenharmony_ci{
139d5ac70f0Sopenharmony_ci	printf("Usage: seq <options> command\n");
140d5ac70f0Sopenharmony_ci	printf("\nAvailable options:\n");
141d5ac70f0Sopenharmony_ci	printf("  -h,--help       this help\n");
142d5ac70f0Sopenharmony_ci	printf("  -d,--debug      debug mode\n");
143d5ac70f0Sopenharmony_ci	printf("  -v,--verbose    verbose mode\n");
144d5ac70f0Sopenharmony_ci	printf("  -V,--version    print version of this program\n");
145d5ac70f0Sopenharmony_ci	printf("\nAvailable commands:\n");
146d5ac70f0Sopenharmony_ci	printf("  system          show basic sequencer info\n");
147d5ac70f0Sopenharmony_ci	printf("  queue [#]       show all queues or specified queue\n");
148d5ac70f0Sopenharmony_ci	printf("  client [#]      show all clients or specified client\n");
149d5ac70f0Sopenharmony_ci	printf("  port <client> [#]  show all ports or specified port for specified client\n");
150d5ac70f0Sopenharmony_ci	printf("  decoder         event decoder\n");
151d5ac70f0Sopenharmony_ci	printf("  sender <client.port> [<client.port>] ...   event sender\n");
152d5ac70f0Sopenharmony_ci}
153d5ac70f0Sopenharmony_ci
154d5ac70f0Sopenharmony_ciint main(int argc, char *argv[])
155d5ac70f0Sopenharmony_ci{
156d5ac70f0Sopenharmony_ci	int morehelp, err, arg, arg1;
157d5ac70f0Sopenharmony_ci	snd_seq_t *handle;
158d5ac70f0Sopenharmony_ci	static struct option long_option[] =
159d5ac70f0Sopenharmony_ci	{
160d5ac70f0Sopenharmony_ci		{"help", 0, NULL, HELPID_HELP},
161d5ac70f0Sopenharmony_ci		{"debug", 0, NULL, HELPID_DEBUG},
162d5ac70f0Sopenharmony_ci		{"verbose", 0, NULL, HELPID_VERBOSE},
163d5ac70f0Sopenharmony_ci		{"version", 0, NULL, HELPID_VERSION},
164d5ac70f0Sopenharmony_ci		{NULL, 0, NULL, 0},
165d5ac70f0Sopenharmony_ci        };
166d5ac70f0Sopenharmony_ci
167d5ac70f0Sopenharmony_ci        morehelp = 0;
168d5ac70f0Sopenharmony_ci
169d5ac70f0Sopenharmony_ci	while (1) {
170d5ac70f0Sopenharmony_ci		int c;
171d5ac70f0Sopenharmony_ci
172d5ac70f0Sopenharmony_ci		if ((c = getopt_long(argc, argv, "hdvV", long_option, NULL)) < 0)
173d5ac70f0Sopenharmony_ci			break;
174d5ac70f0Sopenharmony_ci		switch (c) {
175d5ac70f0Sopenharmony_ci		case 'h':
176d5ac70f0Sopenharmony_ci		case HELPID_HELP:
177d5ac70f0Sopenharmony_ci			morehelp++;
178d5ac70f0Sopenharmony_ci			break;
179d5ac70f0Sopenharmony_ci		case 'd':
180d5ac70f0Sopenharmony_ci		case HELPID_DEBUG:
181d5ac70f0Sopenharmony_ci			debug = 1;
182d5ac70f0Sopenharmony_ci			break;
183d5ac70f0Sopenharmony_ci		case 'v':
184d5ac70f0Sopenharmony_ci		case HELPID_VERBOSE:
185d5ac70f0Sopenharmony_ci			verbose = 1;
186d5ac70f0Sopenharmony_ci			break;
187d5ac70f0Sopenharmony_ci		case 'V':
188d5ac70f0Sopenharmony_ci		case HELPID_VERSION:
189d5ac70f0Sopenharmony_ci			printf("alsactl version " SEQ_VERSION "\n");
190d5ac70f0Sopenharmony_ci			return 1;
191d5ac70f0Sopenharmony_ci		default:
192d5ac70f0Sopenharmony_ci			fprintf(stderr, "\07Invalid switch or option needs an argument.\n");
193d5ac70f0Sopenharmony_ci			morehelp++;
194d5ac70f0Sopenharmony_ci		}
195d5ac70f0Sopenharmony_ci	}
196d5ac70f0Sopenharmony_ci        if (morehelp) {
197d5ac70f0Sopenharmony_ci                help();
198d5ac70f0Sopenharmony_ci                return 1;
199d5ac70f0Sopenharmony_ci        }
200d5ac70f0Sopenharmony_ci	if (argc - optind <= 0) {
201d5ac70f0Sopenharmony_ci		fprintf(stderr, "seq: Specify command...\n");
202d5ac70f0Sopenharmony_ci		return 0;
203d5ac70f0Sopenharmony_ci	}
204d5ac70f0Sopenharmony_ci	if ((err = snd_seq_open(&handle, "hw", SND_SEQ_OPEN_DUPLEX, 0))<0) {
205d5ac70f0Sopenharmony_ci		fprintf(stderr, "Open error: %s\n", snd_strerror(err));
206d5ac70f0Sopenharmony_ci		exit(0);
207d5ac70f0Sopenharmony_ci	}
208d5ac70f0Sopenharmony_ci	set_name(handle);
209d5ac70f0Sopenharmony_ci	system_info(handle);
210d5ac70f0Sopenharmony_ci
211d5ac70f0Sopenharmony_ci        if (!strcmp(argv[optind], "system")) {
212d5ac70f0Sopenharmony_ci		show_system_info(handle);
213d5ac70f0Sopenharmony_ci	} else if (!strcmp(argv[optind], "queue")) {
214d5ac70f0Sopenharmony_ci		arg = argc - optind > 1 ? atoi(argv[optind + 1]) : -1;
215d5ac70f0Sopenharmony_ci		show_queue_status(handle, arg);
216d5ac70f0Sopenharmony_ci	} else if (!strcmp(argv[optind], "client")) {
217d5ac70f0Sopenharmony_ci		arg = argc - optind > 1 ? atoi(argv[optind + 1]) : -1;
218d5ac70f0Sopenharmony_ci		show_client_info(handle, arg);
219d5ac70f0Sopenharmony_ci	} else if (!strcmp(argv[optind], "port")) {
220d5ac70f0Sopenharmony_ci		arg = argc - optind > 1 ? atoi(argv[optind + 1]) : -1;
221d5ac70f0Sopenharmony_ci		if (arg < 0) {
222d5ac70f0Sopenharmony_ci			fprintf(stderr, "Specify port...\n");
223d5ac70f0Sopenharmony_ci			exit(0);
224d5ac70f0Sopenharmony_ci		}
225d5ac70f0Sopenharmony_ci		arg1 = argc - optind > 2 ? atoi(argv[optind + 2]) : -1;
226d5ac70f0Sopenharmony_ci		show_port_info(handle, arg, arg1);
227d5ac70f0Sopenharmony_ci	} else if (!strcmp(argv[optind], "decoder")) {
228d5ac70f0Sopenharmony_ci		event_decoder(handle, argc - optind - 1, argv + optind + 1);
229d5ac70f0Sopenharmony_ci	} else if (!strcmp(argv[optind], "sender")) {
230d5ac70f0Sopenharmony_ci		event_sender(handle, argc - optind - 1, argv + optind + 1);
231d5ac70f0Sopenharmony_ci	} else {
232d5ac70f0Sopenharmony_ci		help();
233d5ac70f0Sopenharmony_ci	}
234d5ac70f0Sopenharmony_ci	exit(1);
235d5ac70f0Sopenharmony_ci}
236