1d5ac70f0Sopenharmony_ci/*
2d5ac70f0Sopenharmony_ci *  Sequencer Interface - middle-level routines
3d5ac70f0Sopenharmony_ci *
4d5ac70f0Sopenharmony_ci *  Copyright (c) 1999 by Takashi Iwai <tiwai@suse.de>
5d5ac70f0Sopenharmony_ci *
6d5ac70f0Sopenharmony_ci *
7d5ac70f0Sopenharmony_ci *   This library is free software; you can redistribute it and/or modify
8d5ac70f0Sopenharmony_ci *   it under the terms of the GNU Lesser General Public License as
9d5ac70f0Sopenharmony_ci *   published by the Free Software Foundation; either version 2.1 of
10d5ac70f0Sopenharmony_ci *   the License, or (at your option) any later version.
11d5ac70f0Sopenharmony_ci *
12d5ac70f0Sopenharmony_ci *   This program is distributed in the hope that it will be useful,
13d5ac70f0Sopenharmony_ci *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14d5ac70f0Sopenharmony_ci *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15d5ac70f0Sopenharmony_ci *   GNU Lesser General Public License for more details.
16d5ac70f0Sopenharmony_ci *
17d5ac70f0Sopenharmony_ci *   You should have received a copy of the GNU Lesser General Public
18d5ac70f0Sopenharmony_ci *   License along with this library; if not, write to the Free Software
19d5ac70f0Sopenharmony_ci *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
20d5ac70f0Sopenharmony_ci *
21d5ac70f0Sopenharmony_ci */
22d5ac70f0Sopenharmony_ci
23d5ac70f0Sopenharmony_ci#include "seq_local.h"
24d5ac70f0Sopenharmony_ci#include <unistd.h>
25d5ac70f0Sopenharmony_ci#include <string.h>
26d5ac70f0Sopenharmony_ci#include <fcntl.h>
27d5ac70f0Sopenharmony_ci#include <ctype.h>
28d5ac70f0Sopenharmony_ci#include <sys/ioctl.h>
29d5ac70f0Sopenharmony_ci
30d5ac70f0Sopenharmony_ci/**
31d5ac70f0Sopenharmony_ci * \brief queue controls - start/stop/continue
32d5ac70f0Sopenharmony_ci * \param seq sequencer handle
33d5ac70f0Sopenharmony_ci * \param q queue id to control
34d5ac70f0Sopenharmony_ci * \param type event type
35d5ac70f0Sopenharmony_ci * \param value event value
36d5ac70f0Sopenharmony_ci * \param ev event instance
37d5ac70f0Sopenharmony_ci *
38d5ac70f0Sopenharmony_ci * This function sets up general queue control event and sends it.
39d5ac70f0Sopenharmony_ci * To send at scheduled time, set the schedule in \a ev.
40d5ac70f0Sopenharmony_ci * If \a ev is NULL, the event is composed locally and sent immediately
41d5ac70f0Sopenharmony_ci * to the specified queue.  In any cases, you need to call #snd_seq_drain_output()
42d5ac70f0Sopenharmony_ci * appropriately to feed the event.
43d5ac70f0Sopenharmony_ci *
44d5ac70f0Sopenharmony_ci * \sa snd_seq_alloc_queue()
45d5ac70f0Sopenharmony_ci */
46d5ac70f0Sopenharmony_ciint snd_seq_control_queue(snd_seq_t *seq, int q, int type, int value, snd_seq_event_t *ev)
47d5ac70f0Sopenharmony_ci{
48d5ac70f0Sopenharmony_ci	snd_seq_event_t tmpev;
49d5ac70f0Sopenharmony_ci	if (ev == NULL) {
50d5ac70f0Sopenharmony_ci		snd_seq_ev_clear(&tmpev);
51d5ac70f0Sopenharmony_ci		ev = &tmpev;
52d5ac70f0Sopenharmony_ci		snd_seq_ev_set_direct(ev);
53d5ac70f0Sopenharmony_ci	}
54d5ac70f0Sopenharmony_ci	snd_seq_ev_set_queue_control(ev, type, q, value);
55d5ac70f0Sopenharmony_ci	return snd_seq_event_output(seq, ev);
56d5ac70f0Sopenharmony_ci}
57d5ac70f0Sopenharmony_ci
58d5ac70f0Sopenharmony_ci
59d5ac70f0Sopenharmony_ci/**
60d5ac70f0Sopenharmony_ci * \brief create a port - simple version
61d5ac70f0Sopenharmony_ci * \param seq sequencer handle
62d5ac70f0Sopenharmony_ci * \param name the name of the port
63d5ac70f0Sopenharmony_ci * \param caps capability bits
64d5ac70f0Sopenharmony_ci * \param type type bits
65d5ac70f0Sopenharmony_ci * \return the created port number or negative error code
66d5ac70f0Sopenharmony_ci *
67d5ac70f0Sopenharmony_ci * Creates a port with the given capability and type bits.
68d5ac70f0Sopenharmony_ci *
69d5ac70f0Sopenharmony_ci * \sa snd_seq_create_port(), snd_seq_delete_simple_port()
70d5ac70f0Sopenharmony_ci */
71d5ac70f0Sopenharmony_ciint snd_seq_create_simple_port(snd_seq_t *seq, const char *name,
72d5ac70f0Sopenharmony_ci			       unsigned int caps, unsigned int type)
73d5ac70f0Sopenharmony_ci{
74d5ac70f0Sopenharmony_ci	snd_seq_port_info_t pinfo;
75d5ac70f0Sopenharmony_ci	int result;
76d5ac70f0Sopenharmony_ci
77d5ac70f0Sopenharmony_ci	memset(&pinfo, 0, sizeof(pinfo));
78d5ac70f0Sopenharmony_ci	if (name)
79d5ac70f0Sopenharmony_ci		strncpy(pinfo.name, name, sizeof(pinfo.name) - 1);
80d5ac70f0Sopenharmony_ci	pinfo.capability = caps;
81d5ac70f0Sopenharmony_ci	pinfo.type = type;
82d5ac70f0Sopenharmony_ci	pinfo.midi_channels = 16;
83d5ac70f0Sopenharmony_ci	pinfo.midi_voices = 64; /* XXX */
84d5ac70f0Sopenharmony_ci	pinfo.synth_voices = 0; /* XXX */
85d5ac70f0Sopenharmony_ci
86d5ac70f0Sopenharmony_ci	result = snd_seq_create_port(seq, &pinfo);
87d5ac70f0Sopenharmony_ci	if (result < 0)
88d5ac70f0Sopenharmony_ci		return result;
89d5ac70f0Sopenharmony_ci	else
90d5ac70f0Sopenharmony_ci		return pinfo.addr.port;
91d5ac70f0Sopenharmony_ci}
92d5ac70f0Sopenharmony_ci
93d5ac70f0Sopenharmony_ci/**
94d5ac70f0Sopenharmony_ci * \brief delete the port
95d5ac70f0Sopenharmony_ci * \param seq sequencer handle
96d5ac70f0Sopenharmony_ci * \param port port id
97d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
98d5ac70f0Sopenharmony_ci *
99d5ac70f0Sopenharmony_ci * \sa snd_seq_delete_port(), snd_seq_create_simple_port()
100d5ac70f0Sopenharmony_ci */
101d5ac70f0Sopenharmony_ciint snd_seq_delete_simple_port(snd_seq_t *seq, int port)
102d5ac70f0Sopenharmony_ci{
103d5ac70f0Sopenharmony_ci	return snd_seq_delete_port(seq, port);
104d5ac70f0Sopenharmony_ci}
105d5ac70f0Sopenharmony_ci
106d5ac70f0Sopenharmony_ci/**
107d5ac70f0Sopenharmony_ci * \brief simple subscription (w/o exclusive & time conversion)
108d5ac70f0Sopenharmony_ci * \param seq sequencer handle
109d5ac70f0Sopenharmony_ci * \param myport the port id as receiver
110d5ac70f0Sopenharmony_ci * \param src_client sender client id
111d5ac70f0Sopenharmony_ci * \param src_port sender port id
112d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
113d5ac70f0Sopenharmony_ci *
114d5ac70f0Sopenharmony_ci * Connect from the given sender client:port to the given destination port in the
115d5ac70f0Sopenharmony_ci * current client.
116d5ac70f0Sopenharmony_ci *
117d5ac70f0Sopenharmony_ci * \sa snd_seq_subscribe_port(), snd_seq_disconnect_from()
118d5ac70f0Sopenharmony_ci */
119d5ac70f0Sopenharmony_ciint snd_seq_connect_from(snd_seq_t *seq, int myport, int src_client, int src_port)
120d5ac70f0Sopenharmony_ci{
121d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_t subs;
122d5ac70f0Sopenharmony_ci
123d5ac70f0Sopenharmony_ci	memset(&subs, 0, sizeof(subs));
124d5ac70f0Sopenharmony_ci	subs.sender.client = src_client;
125d5ac70f0Sopenharmony_ci	subs.sender.port = src_port;
126d5ac70f0Sopenharmony_ci	/*subs.dest.client = seq->client;*/
127d5ac70f0Sopenharmony_ci	subs.dest.client = snd_seq_client_id(seq);
128d5ac70f0Sopenharmony_ci	subs.dest.port = myport;
129d5ac70f0Sopenharmony_ci
130d5ac70f0Sopenharmony_ci	return snd_seq_subscribe_port(seq, &subs);
131d5ac70f0Sopenharmony_ci}
132d5ac70f0Sopenharmony_ci
133d5ac70f0Sopenharmony_ci/**
134d5ac70f0Sopenharmony_ci * \brief simple subscription (w/o exclusive & time conversion)
135d5ac70f0Sopenharmony_ci * \param seq sequencer handle
136d5ac70f0Sopenharmony_ci * \param myport the port id as sender
137d5ac70f0Sopenharmony_ci * \param dest_client destination client id
138d5ac70f0Sopenharmony_ci * \param dest_port destination port id
139d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
140d5ac70f0Sopenharmony_ci *
141d5ac70f0Sopenharmony_ci * Connect from the given receiver port in the current client
142d5ac70f0Sopenharmony_ci * to the given destination client:port.
143d5ac70f0Sopenharmony_ci *
144d5ac70f0Sopenharmony_ci * \sa snd_seq_subscribe_port(), snd_seq_disconnect_to()
145d5ac70f0Sopenharmony_ci */
146d5ac70f0Sopenharmony_ciint snd_seq_connect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port)
147d5ac70f0Sopenharmony_ci{
148d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_t subs;
149d5ac70f0Sopenharmony_ci
150d5ac70f0Sopenharmony_ci	memset(&subs, 0, sizeof(subs));
151d5ac70f0Sopenharmony_ci	/*subs.sender.client = seq->client;*/
152d5ac70f0Sopenharmony_ci	subs.sender.client = snd_seq_client_id(seq);
153d5ac70f0Sopenharmony_ci	subs.sender.port = myport;
154d5ac70f0Sopenharmony_ci	subs.dest.client = dest_client;
155d5ac70f0Sopenharmony_ci	subs.dest.port = dest_port;
156d5ac70f0Sopenharmony_ci
157d5ac70f0Sopenharmony_ci	return snd_seq_subscribe_port(seq, &subs);
158d5ac70f0Sopenharmony_ci}
159d5ac70f0Sopenharmony_ci
160d5ac70f0Sopenharmony_ci/**
161d5ac70f0Sopenharmony_ci * \brief simple disconnection
162d5ac70f0Sopenharmony_ci * \param seq sequencer handle
163d5ac70f0Sopenharmony_ci * \param myport the port id as receiver
164d5ac70f0Sopenharmony_ci * \param src_client sender client id
165d5ac70f0Sopenharmony_ci * \param src_port sender port id
166d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
167d5ac70f0Sopenharmony_ci *
168d5ac70f0Sopenharmony_ci * Remove connection from the given sender client:port
169d5ac70f0Sopenharmony_ci * to the given destination port in the current client.
170d5ac70f0Sopenharmony_ci *
171d5ac70f0Sopenharmony_ci * \sa snd_seq_unsubscribe_port(), snd_seq_connect_from()
172d5ac70f0Sopenharmony_ci */
173d5ac70f0Sopenharmony_ciint snd_seq_disconnect_from(snd_seq_t *seq, int myport, int src_client, int src_port)
174d5ac70f0Sopenharmony_ci{
175d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_t subs;
176d5ac70f0Sopenharmony_ci
177d5ac70f0Sopenharmony_ci	memset(&subs, 0, sizeof(subs));
178d5ac70f0Sopenharmony_ci	subs.sender.client = src_client;
179d5ac70f0Sopenharmony_ci	subs.sender.port = src_port;
180d5ac70f0Sopenharmony_ci	/*subs.dest.client = seq->client;*/
181d5ac70f0Sopenharmony_ci	subs.dest.client = snd_seq_client_id(seq);
182d5ac70f0Sopenharmony_ci	subs.dest.port = myport;
183d5ac70f0Sopenharmony_ci
184d5ac70f0Sopenharmony_ci	return snd_seq_unsubscribe_port(seq, &subs);
185d5ac70f0Sopenharmony_ci}
186d5ac70f0Sopenharmony_ci
187d5ac70f0Sopenharmony_ci/**
188d5ac70f0Sopenharmony_ci * \brief simple disconnection
189d5ac70f0Sopenharmony_ci * \param seq sequencer handle
190d5ac70f0Sopenharmony_ci * \param myport the port id as sender
191d5ac70f0Sopenharmony_ci * \param dest_client destination client id
192d5ac70f0Sopenharmony_ci * \param dest_port destination port id
193d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
194d5ac70f0Sopenharmony_ci *
195d5ac70f0Sopenharmony_ci * Remove connection from the given sender client:port
196d5ac70f0Sopenharmony_ci * to the given destination port in the current client.
197d5ac70f0Sopenharmony_ci *
198d5ac70f0Sopenharmony_ci * \sa snd_seq_unsubscribe_port(), snd_seq_connect_to()
199d5ac70f0Sopenharmony_ci */
200d5ac70f0Sopenharmony_ciint snd_seq_disconnect_to(snd_seq_t *seq, int myport, int dest_client, int dest_port)
201d5ac70f0Sopenharmony_ci{
202d5ac70f0Sopenharmony_ci	snd_seq_port_subscribe_t subs;
203d5ac70f0Sopenharmony_ci
204d5ac70f0Sopenharmony_ci	memset(&subs, 0, sizeof(subs));
205d5ac70f0Sopenharmony_ci	/*subs.sender.client = seq->client;*/
206d5ac70f0Sopenharmony_ci	subs.sender.client = snd_seq_client_id(seq);
207d5ac70f0Sopenharmony_ci	subs.sender.port = myport;
208d5ac70f0Sopenharmony_ci	subs.dest.client = dest_client;
209d5ac70f0Sopenharmony_ci	subs.dest.port = dest_port;
210d5ac70f0Sopenharmony_ci
211d5ac70f0Sopenharmony_ci	return snd_seq_unsubscribe_port(seq, &subs);
212d5ac70f0Sopenharmony_ci}
213d5ac70f0Sopenharmony_ci
214d5ac70f0Sopenharmony_ci/*
215d5ac70f0Sopenharmony_ci * set client information
216d5ac70f0Sopenharmony_ci */
217d5ac70f0Sopenharmony_ci
218d5ac70f0Sopenharmony_ci/**
219d5ac70f0Sopenharmony_ci * \brief set client name
220d5ac70f0Sopenharmony_ci * \param seq sequencer handle
221d5ac70f0Sopenharmony_ci * \param name name string
222d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
223d5ac70f0Sopenharmony_ci *
224d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_info()
225d5ac70f0Sopenharmony_ci */
226d5ac70f0Sopenharmony_ciint snd_seq_set_client_name(snd_seq_t *seq, const char *name)
227d5ac70f0Sopenharmony_ci{
228d5ac70f0Sopenharmony_ci	snd_seq_client_info_t info;
229d5ac70f0Sopenharmony_ci	int err;
230d5ac70f0Sopenharmony_ci
231d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_info(seq, &info)) < 0)
232d5ac70f0Sopenharmony_ci		return err;
233d5ac70f0Sopenharmony_ci	strncpy(info.name, name, sizeof(info.name) - 1);
234d5ac70f0Sopenharmony_ci	return snd_seq_set_client_info(seq, &info);
235d5ac70f0Sopenharmony_ci}
236d5ac70f0Sopenharmony_ci
237d5ac70f0Sopenharmony_ci/**
238d5ac70f0Sopenharmony_ci * \brief add client event filter
239d5ac70f0Sopenharmony_ci * \param seq sequencer handle
240d5ac70f0Sopenharmony_ci * \param event_type event type to be added
241d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
242d5ac70f0Sopenharmony_ci *
243d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_info()
244d5ac70f0Sopenharmony_ci */
245d5ac70f0Sopenharmony_ciint snd_seq_set_client_event_filter(snd_seq_t *seq, int event_type)
246d5ac70f0Sopenharmony_ci{
247d5ac70f0Sopenharmony_ci	snd_seq_client_info_t info;
248d5ac70f0Sopenharmony_ci	int err;
249d5ac70f0Sopenharmony_ci
250d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_info(seq, &info)) < 0)
251d5ac70f0Sopenharmony_ci		return err;
252d5ac70f0Sopenharmony_ci	snd_seq_client_info_event_filter_add(&info, event_type);
253d5ac70f0Sopenharmony_ci	return snd_seq_set_client_info(seq, &info);
254d5ac70f0Sopenharmony_ci}
255d5ac70f0Sopenharmony_ci
256d5ac70f0Sopenharmony_ci/**
257d5ac70f0Sopenharmony_ci * \brief set client MIDI protocol version
258d5ac70f0Sopenharmony_ci * \param seq sequencer handle
259d5ac70f0Sopenharmony_ci * \param midi_version MIDI protocol version to set
260d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
261d5ac70f0Sopenharmony_ci *
262d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_info()
263d5ac70f0Sopenharmony_ci */
264d5ac70f0Sopenharmony_ciint snd_seq_set_client_midi_version(snd_seq_t *seq, int midi_version)
265d5ac70f0Sopenharmony_ci{
266d5ac70f0Sopenharmony_ci	snd_seq_client_info_t info;
267d5ac70f0Sopenharmony_ci	int err;
268d5ac70f0Sopenharmony_ci
269d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_info(seq, &info)) < 0)
270d5ac70f0Sopenharmony_ci		return err;
271d5ac70f0Sopenharmony_ci	snd_seq_client_info_set_midi_version(&info, midi_version);
272d5ac70f0Sopenharmony_ci	return snd_seq_set_client_info(seq, &info);
273d5ac70f0Sopenharmony_ci}
274d5ac70f0Sopenharmony_ci
275d5ac70f0Sopenharmony_ci/**
276d5ac70f0Sopenharmony_ci * \brief enable/disable client's automatic conversion of UMP/legacy events
277d5ac70f0Sopenharmony_ci * \param seq sequencer handle
278d5ac70f0Sopenharmony_ci * \param enable 0 or 1 to disable/enable the conversion
279d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
280d5ac70f0Sopenharmony_ci *
281d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_info()
282d5ac70f0Sopenharmony_ci */
283d5ac70f0Sopenharmony_ciint snd_seq_set_client_ump_conversion(snd_seq_t *seq, int enable)
284d5ac70f0Sopenharmony_ci{
285d5ac70f0Sopenharmony_ci	snd_seq_client_info_t info;
286d5ac70f0Sopenharmony_ci	int err;
287d5ac70f0Sopenharmony_ci
288d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_info(seq, &info)) < 0)
289d5ac70f0Sopenharmony_ci		return err;
290d5ac70f0Sopenharmony_ci	snd_seq_client_info_set_ump_conversion(&info, enable);
291d5ac70f0Sopenharmony_ci	return snd_seq_set_client_info(seq, &info);
292d5ac70f0Sopenharmony_ci}
293d5ac70f0Sopenharmony_ci
294d5ac70f0Sopenharmony_ci/**
295d5ac70f0Sopenharmony_ci * \brief change the output pool size of the given client
296d5ac70f0Sopenharmony_ci * \param seq sequencer handle
297d5ac70f0Sopenharmony_ci * \param size output pool size
298d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
299d5ac70f0Sopenharmony_ci *
300d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_pool()
301d5ac70f0Sopenharmony_ci */
302d5ac70f0Sopenharmony_ciint snd_seq_set_client_pool_output(snd_seq_t *seq, size_t size)
303d5ac70f0Sopenharmony_ci{
304d5ac70f0Sopenharmony_ci	snd_seq_client_pool_t info;
305d5ac70f0Sopenharmony_ci	int err;
306d5ac70f0Sopenharmony_ci
307d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
308d5ac70f0Sopenharmony_ci		return err;
309d5ac70f0Sopenharmony_ci	info.output_pool = size;
310d5ac70f0Sopenharmony_ci	return snd_seq_set_client_pool(seq, &info);
311d5ac70f0Sopenharmony_ci}
312d5ac70f0Sopenharmony_ci
313d5ac70f0Sopenharmony_ci/**
314d5ac70f0Sopenharmony_ci * \brief change the output room size of the given client
315d5ac70f0Sopenharmony_ci * \param seq sequencer handle
316d5ac70f0Sopenharmony_ci * \param size output room size
317d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
318d5ac70f0Sopenharmony_ci *
319d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_pool()
320d5ac70f0Sopenharmony_ci */
321d5ac70f0Sopenharmony_ciint snd_seq_set_client_pool_output_room(snd_seq_t *seq, size_t size)
322d5ac70f0Sopenharmony_ci{
323d5ac70f0Sopenharmony_ci	snd_seq_client_pool_t info;
324d5ac70f0Sopenharmony_ci	int err;
325d5ac70f0Sopenharmony_ci
326d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
327d5ac70f0Sopenharmony_ci		return err;
328d5ac70f0Sopenharmony_ci	info.output_room = size;
329d5ac70f0Sopenharmony_ci	return snd_seq_set_client_pool(seq, &info);
330d5ac70f0Sopenharmony_ci}
331d5ac70f0Sopenharmony_ci
332d5ac70f0Sopenharmony_ci/**
333d5ac70f0Sopenharmony_ci * \brief change the input pool size of the given client
334d5ac70f0Sopenharmony_ci * \param seq sequencer handle
335d5ac70f0Sopenharmony_ci * \param size input pool size
336d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
337d5ac70f0Sopenharmony_ci *
338d5ac70f0Sopenharmony_ci * \sa snd_seq_set_client_pool()
339d5ac70f0Sopenharmony_ci */
340d5ac70f0Sopenharmony_ciint snd_seq_set_client_pool_input(snd_seq_t *seq, size_t size)
341d5ac70f0Sopenharmony_ci{
342d5ac70f0Sopenharmony_ci	snd_seq_client_pool_t info;
343d5ac70f0Sopenharmony_ci	int err;
344d5ac70f0Sopenharmony_ci
345d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
346d5ac70f0Sopenharmony_ci		return err;
347d5ac70f0Sopenharmony_ci	info.input_pool = size;
348d5ac70f0Sopenharmony_ci	return snd_seq_set_client_pool(seq, &info);
349d5ac70f0Sopenharmony_ci}
350d5ac70f0Sopenharmony_ci
351d5ac70f0Sopenharmony_ci/**
352d5ac70f0Sopenharmony_ci * \brief reset client output pool
353d5ac70f0Sopenharmony_ci * \param seq sequencer handle
354d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
355d5ac70f0Sopenharmony_ci *
356d5ac70f0Sopenharmony_ci * So far, this works identically like #snd_seq_drop_output().
357d5ac70f0Sopenharmony_ci */
358d5ac70f0Sopenharmony_ciint snd_seq_reset_pool_output(snd_seq_t *seq)
359d5ac70f0Sopenharmony_ci{
360d5ac70f0Sopenharmony_ci	return snd_seq_drop_output(seq);
361d5ac70f0Sopenharmony_ci}
362d5ac70f0Sopenharmony_ci
363d5ac70f0Sopenharmony_ci/**
364d5ac70f0Sopenharmony_ci * \brief reset client input pool
365d5ac70f0Sopenharmony_ci * \param seq sequencer handle
366d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
367d5ac70f0Sopenharmony_ci *
368d5ac70f0Sopenharmony_ci * So far, this works identically like #snd_seq_drop_input().
369d5ac70f0Sopenharmony_ci */
370d5ac70f0Sopenharmony_ciint snd_seq_reset_pool_input(snd_seq_t *seq)
371d5ac70f0Sopenharmony_ci{
372d5ac70f0Sopenharmony_ci	return snd_seq_drop_input(seq);
373d5ac70f0Sopenharmony_ci}
374d5ac70f0Sopenharmony_ci
375d5ac70f0Sopenharmony_ci/**
376d5ac70f0Sopenharmony_ci * \brief wait until all events are processed
377d5ac70f0Sopenharmony_ci * \param seq sequencer handle
378d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
379d5ac70f0Sopenharmony_ci *
380d5ac70f0Sopenharmony_ci * This function waits until all events of this client are processed.
381d5ac70f0Sopenharmony_ci *
382d5ac70f0Sopenharmony_ci * \sa snd_seq_drain_output()
383d5ac70f0Sopenharmony_ci */
384d5ac70f0Sopenharmony_ciint snd_seq_sync_output_queue(snd_seq_t *seq)
385d5ac70f0Sopenharmony_ci{
386d5ac70f0Sopenharmony_ci	int err;
387d5ac70f0Sopenharmony_ci	snd_seq_client_pool_t info;
388d5ac70f0Sopenharmony_ci	int saved_room;
389d5ac70f0Sopenharmony_ci	struct pollfd pfd;
390d5ac70f0Sopenharmony_ci
391d5ac70f0Sopenharmony_ci	assert(seq);
392d5ac70f0Sopenharmony_ci	/* reprogram the room size to full */
393d5ac70f0Sopenharmony_ci	if ((err = snd_seq_get_client_pool(seq, &info)) < 0)
394d5ac70f0Sopenharmony_ci		return err;
395d5ac70f0Sopenharmony_ci	saved_room = info.output_room;
396d5ac70f0Sopenharmony_ci	info.output_room = info.output_pool; /* wait until all gone */
397d5ac70f0Sopenharmony_ci	if ((err = snd_seq_set_client_pool(seq, &info)) < 0)
398d5ac70f0Sopenharmony_ci		return err;
399d5ac70f0Sopenharmony_ci	/* wait until all events are purged */
400d5ac70f0Sopenharmony_ci	pfd.fd = seq->poll_fd;
401d5ac70f0Sopenharmony_ci	pfd.events = POLLOUT;
402d5ac70f0Sopenharmony_ci	err = poll(&pfd, 1, -1);
403d5ac70f0Sopenharmony_ci	/* restore the room size */
404d5ac70f0Sopenharmony_ci	info.output_room = saved_room;
405d5ac70f0Sopenharmony_ci	snd_seq_set_client_pool(seq, &info);
406d5ac70f0Sopenharmony_ci	return err;
407d5ac70f0Sopenharmony_ci}
408d5ac70f0Sopenharmony_ci
409d5ac70f0Sopenharmony_ci/**
410d5ac70f0Sopenharmony_ci * \brief parse the given string and get the sequencer address
411d5ac70f0Sopenharmony_ci * \param seq sequencer handle
412d5ac70f0Sopenharmony_ci * \param addr the address pointer to be returned
413d5ac70f0Sopenharmony_ci * \param arg the string to be parsed
414d5ac70f0Sopenharmony_ci * \return 0 on success or negative error code
415d5ac70f0Sopenharmony_ci *
416d5ac70f0Sopenharmony_ci * This function parses the sequencer client and port numbers from the given string.
417d5ac70f0Sopenharmony_ci * The client and port tokens are separated by either colon or period, e.g. 128:1.
418d5ac70f0Sopenharmony_ci * When \a seq is not NULL, the function accepts also a client name not only
419d5ac70f0Sopenharmony_ci * digit numbers.
420d5ac70f0Sopenharmony_ci * Actually \a arg need to be only a prefix of the wanted client.
421d5ac70f0Sopenharmony_ci * That is, if a client named "Foobar XXL Master 2012" with number 128 is available,
422d5ac70f0Sopenharmony_ci * then parsing "Foobar" will return the address 128:0 if no other client is
423d5ac70f0Sopenharmony_ci * an exact match.
424d5ac70f0Sopenharmony_ci */
425d5ac70f0Sopenharmony_ciint snd_seq_parse_address(snd_seq_t *seq, snd_seq_addr_t *addr, const char *arg)
426d5ac70f0Sopenharmony_ci{
427d5ac70f0Sopenharmony_ci	char *p, *buf;
428d5ac70f0Sopenharmony_ci	const char *s;
429d5ac70f0Sopenharmony_ci	char c;
430d5ac70f0Sopenharmony_ci	long client, port = 0;
431d5ac70f0Sopenharmony_ci	int len;
432d5ac70f0Sopenharmony_ci
433d5ac70f0Sopenharmony_ci	assert(addr && arg);
434d5ac70f0Sopenharmony_ci
435d5ac70f0Sopenharmony_ci	c = *arg;
436d5ac70f0Sopenharmony_ci	if (c == '"' || c == '\'') {
437d5ac70f0Sopenharmony_ci		s = ++arg;
438d5ac70f0Sopenharmony_ci		while (*s && *s != c) s++;
439d5ac70f0Sopenharmony_ci		len = s - arg;
440d5ac70f0Sopenharmony_ci		if (*s)
441d5ac70f0Sopenharmony_ci			s++;
442d5ac70f0Sopenharmony_ci		if (*s) {
443d5ac70f0Sopenharmony_ci			if (*s != '.' && *s != ':')
444d5ac70f0Sopenharmony_ci				return -EINVAL;
445d5ac70f0Sopenharmony_ci			if ((port = atoi(s + 1)) < 0)
446d5ac70f0Sopenharmony_ci				return -EINVAL;
447d5ac70f0Sopenharmony_ci		}
448d5ac70f0Sopenharmony_ci	} else {
449d5ac70f0Sopenharmony_ci		if ((p = strpbrk(arg, ":.")) != NULL) {
450d5ac70f0Sopenharmony_ci			if ((port = atoi(p + 1)) < 0)
451d5ac70f0Sopenharmony_ci				return -EINVAL;
452d5ac70f0Sopenharmony_ci			len = (int)(p - arg); /* length of client name */
453d5ac70f0Sopenharmony_ci		} else {
454d5ac70f0Sopenharmony_ci			len = strlen(arg);
455d5ac70f0Sopenharmony_ci		}
456d5ac70f0Sopenharmony_ci	}
457d5ac70f0Sopenharmony_ci	if (len == 0)
458d5ac70f0Sopenharmony_ci		return -EINVAL;
459d5ac70f0Sopenharmony_ci	buf = alloca(len + 1);
460d5ac70f0Sopenharmony_ci	strncpy(buf, arg, len);
461d5ac70f0Sopenharmony_ci	buf[len] = '\0';
462d5ac70f0Sopenharmony_ci	addr->port = port;
463d5ac70f0Sopenharmony_ci	if (safe_strtol(buf, &client) == 0) {
464d5ac70f0Sopenharmony_ci		addr->client = client;
465d5ac70f0Sopenharmony_ci	} else {
466d5ac70f0Sopenharmony_ci		/* convert from the name */
467d5ac70f0Sopenharmony_ci		snd_seq_client_info_t cinfo;
468d5ac70f0Sopenharmony_ci
469d5ac70f0Sopenharmony_ci		if (! seq)
470d5ac70f0Sopenharmony_ci			return -EINVAL;
471d5ac70f0Sopenharmony_ci		if (len <= 0)
472d5ac70f0Sopenharmony_ci			return -EINVAL;
473d5ac70f0Sopenharmony_ci		client = -1;
474d5ac70f0Sopenharmony_ci		cinfo.client = -1;
475d5ac70f0Sopenharmony_ci		while (snd_seq_query_next_client(seq, &cinfo) >= 0) {
476d5ac70f0Sopenharmony_ci			if (!strncmp(arg, cinfo.name, len)) {
477d5ac70f0Sopenharmony_ci				if (strlen(cinfo.name) == (size_t)len) {
478d5ac70f0Sopenharmony_ci					/* exact match */
479d5ac70f0Sopenharmony_ci					addr->client = cinfo.client;
480d5ac70f0Sopenharmony_ci					return 0;
481d5ac70f0Sopenharmony_ci				}
482d5ac70f0Sopenharmony_ci				if (client < 0)
483d5ac70f0Sopenharmony_ci					client = cinfo.client;
484d5ac70f0Sopenharmony_ci			}
485d5ac70f0Sopenharmony_ci		}
486d5ac70f0Sopenharmony_ci		if (client >= 0) {
487d5ac70f0Sopenharmony_ci			/* prefix match */
488d5ac70f0Sopenharmony_ci			addr->client = client;
489d5ac70f0Sopenharmony_ci			return 0;
490d5ac70f0Sopenharmony_ci		}
491d5ac70f0Sopenharmony_ci		return -ENOENT; /* not found */
492d5ac70f0Sopenharmony_ci	}
493d5ac70f0Sopenharmony_ci	return 0;
494d5ac70f0Sopenharmony_ci}
495d5ac70f0Sopenharmony_ci
496