2
* OSS mixer service daemon (used by libossmix)
7
#include <sys/socket.h>
8
#include <netinet/in.h>
14
#ifdef __SCO_VERSION__
20
#include <soundcard.h>
23
#include "libossmix.h"
27
static int verbose = 0;
28
static int polling_started = 0;
29
static int num_mixers=0;
31
static unsigned char mixer_open_mask[MAX_TMP_MIXER/8] = {0};
34
send_response (int cmd, int p1, int p2, int p3, int p4, int p5, int unsol)
36
ossmix_commad_packet_t msg;
38
memset (&msg, 0, sizeof (msg));
41
printf ("Send %02d, p=0x%08x, %d, %d, %d, %d, unsol=%d\n",
42
cmd, p1, p2, p3, p4, p5, unsol);
45
msg.unsolicited = unsol;
52
if (write (connfd, &msg, sizeof (msg)) != sizeof (msg))
54
fprintf (stderr, "Write to socket failed\n");
59
send_response_long (int cmd, int p1, int p2, int p3, int p4, int p5,
60
const char *payload, int plsize, int unsol)
62
ossmix_commad_packet_t msg;
65
printf ("Send %02d, p=0x%08x, %d, %d, %d, %d, unsol=%d, pl=%d\n",
66
cmd, p1, p2, p3, p4, p5, unsol, plsize);
68
memset (&msg, 0, sizeof (msg));
71
msg.unsolicited = unsol;
77
msg.payload_size = plsize;
79
if (write (connfd, &msg, sizeof (msg)) != sizeof (msg))
81
fprintf (stderr, "Write to socket failed\n");
84
if (write (connfd, payload, msg.payload_size) != msg.payload_size)
86
fprintf (stderr, "Write to socket failed\n");
91
send_error (const char *msg)
93
int l = strlen (msg) + 1;
95
send_response_long (OSSMIX_CMD_ERROR, 0, 0, 0, 0, 0, msg, l, 0);
101
if (listen (listenfd, 1) == -1)
107
if ((connfd = accept (listenfd, NULL, NULL)) == -1)
119
send_response (OSSMIX_CMD_OK, 0, 0, 0, 0, 0, 0);
123
return_value (int val)
125
send_response (val, 0, 0, 0, 0, 0, 0);
129
send_multiple_nodes (ossmix_commad_packet_t * pack)
132
oss_mixext nodes[MAX_NODES];
135
for (i = pack->p2; i <= pack->p3; i++)
137
if (ossmix_get_nodeinfo (pack->p1, i, &nodes[n]) < 0)
139
send_error ("Cannot get mixer node info\n");
143
mixc_add_node (pack->p1, i, &nodes[n]);
145
if (++n >= MAX_NODES)
147
send_response_long (OSSMIX_CMD_GET_NODEINFO, n, i, 0, 0, 0,
148
(void *) &nodes, n * sizeof (oss_mixext), 0);
154
send_response_long (OSSMIX_CMD_GET_NODEINFO, n, pack->p3, 0, 0, 0,
155
(void *) &nodes, n * sizeof (oss_mixext), 0);
159
update_values (int mixernum)
164
int value, prev_value;
166
nrext = ossmix_get_nrext (mixernum);
168
for (i = 0; i < nrext; i++)
170
if ((ext = mixc_get_node (mixernum, i)) == NULL)
173
if (ext->type == MIXT_DEVROOT || ext->type == MIXT_GROUP
174
|| ext->type == MIXT_MARKER)
177
prev_value = mixc_get_value (mixernum, i);
179
if ((value = ossmix_get_value (mixernum, i, ext->timestamp)) < 0)
181
// TODO check for EIDRM
183
mixc_set_value (mixernum, i, value);
188
serve_command (ossmix_commad_packet_t * pack)
192
case OSSMIX_CMD_INIT:
198
case OSSMIX_CMD_EXIT:
199
//fprintf(stderr, "Exit\n");
201
memset(mixer_open_mask, 0, sizeof(mixer_open_mask));
206
case OSSMIX_CMD_START_EVENTS:
210
case OSSMIX_CMD_GET_NMIXERS:
211
return_value (num_mixers=ossmix_get_nmixers ());
214
case OSSMIX_CMD_GET_MIXERINFO:
218
if (ossmix_get_mixerinfo (pack->p1, &mi) < 0)
219
send_error ("Cannot get mixer info\n");
221
send_response_long (OSSMIX_CMD_OK, 0, 0, 0, 0, 0, (void *) &mi,
226
case OSSMIX_CMD_OPEN_MIXER:
227
mixer_open_mask[pack->p1 / 8] |= (1<<(pack->p1 % 8)); // Open
228
return_value (ossmix_open_mixer (pack->p1));
231
case OSSMIX_CMD_CLOSE_MIXER:
232
mixer_open_mask[pack->p1 / 8] &= ~(1<<(pack->p1 % 8)); // Closed
233
ossmix_close_mixer (pack->p1);
236
case OSSMIX_CMD_GET_NREXT:
237
return_value (ossmix_get_nrext (pack->p1));
240
case OSSMIX_CMD_GET_NODEINFO:
244
if (pack->p3 > pack->p2)
246
send_multiple_nodes (pack);
250
if (ossmix_get_nodeinfo (pack->p1, pack->p2, &ext) < 0)
251
send_error ("Cannot get mixer node info\n");
254
mixc_add_node (pack->p1, pack->p2, &ext);
255
send_response_long (OSSMIX_CMD_OK, 0, 0, 0, 0, 0, (void *) &ext,
261
case OSSMIX_CMD_GET_ENUMINFO:
263
oss_mixer_enuminfo desc;
265
if (ossmix_get_enuminfo (pack->p1, pack->p2, &desc) < 0)
266
send_error ("Cannot get mixer enum strings\n");
268
send_response_long (OSSMIX_CMD_OK, 0, 0, 0, 0, 0, (void *) &desc,
273
case OSSMIX_CMD_GET_DESCRIPTION:
275
oss_mixer_enuminfo desc;
277
if (ossmix_get_description (pack->p1, pack->p2, &desc) < 0)
278
send_error ("Cannot get mixer description\n");
280
send_response_long (OSSMIX_CMD_OK, 0, 0, 0, 0, 0, (void *) &desc,
285
case OSSMIX_CMD_GET_VALUE:
286
return_value (ossmix_get_value (pack->p1, pack->p2, pack->p3));
289
case OSSMIX_CMD_GET_ALL_VALUES:
292
value_packet_t value_packet;
294
update_values (pack->p1);
295
n = mixc_get_all_values (pack->p1, value_packet, 0);
297
send_response_long (OSSMIX_CMD_GET_ALL_VALUES, n, pack->p1, 0, 0, 0,
298
(void *) &value_packet,
299
n * sizeof (value_record_t), 0);
300
mixc_clear_changeflags (pack->p1);
304
case OSSMIX_CMD_SET_VALUE:
305
ossmix_set_value (pack->p1, pack->p2, pack->p3, pack->p4);
311
send_error ("Unrecognized request");
320
value_packet_t value_packet;
322
for (mixernum=0;mixernum<num_mixers;mixernum++)
323
if (mixer_open_mask[mixernum / 8] & 1<<(mixernum % 8))
325
update_values (mixernum);
326
n = mixc_get_all_values (mixernum, value_packet, 1);
328
if (n==0) /* Nothing changed */
331
send_response_long (OSSMIX_EVENT_VALUE, n, mixernum, 0, 0, 0,
332
(void *) &value_packet,
333
n * sizeof (value_record_t), 1);
334
mixc_clear_changeflags (mixernum);
337
n=ossmix_get_nmixers();
341
send_response (OSSMIX_EVENT_NEWMIXER, n, 0, 0, 0, 0, 1);
346
handle_connection (int connfd)
348
ossmix_commad_packet_t pack;
349
struct timeval tmout;
351
send_response (OSSMIX_CMD_HALOO, OSSMIX_P1_MAGIC, 0, 0, 0, 0, 0);
359
fd_set readfds, exfds;
363
FD_SET (connfd, &readfds);
364
FD_SET (connfd, &exfds);
366
if ((ndevs = select (connfd + 1, &readfds, NULL, &exfds, &tmout)) == -1)
378
tmout.tv_usec = 100000;
387
if (FD_ISSET (connfd, &readfds) || FD_ISSET (connfd, &exfds))
389
if (read (connfd, &pack, sizeof (pack)) == sizeof (pack))
391
serve_command (&pack);
402
main (int argc, char *argv[])
404
struct sockaddr_in servaddr;
409
if ((err = ossmix_init ()) < 0)
411
fprintf (stderr, "ossmix_init() failed, err=%d\n", err);
415
if ((err = ossmix_connect (NULL, 0)) < 0) /* Force local connection */
417
fprintf (stderr, "ossmix_connect() failed, err=%d\n", err);
421
while ((c = getopt (argc, argv, "vp:")) != EOF)
425
case 'p': /* TCP/IP port */
426
port = atoi (optarg);
431
case 'v': /* Verbose */
437
printf ("Listening socket %d\n", port);
439
if ((listenfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
445
memset (&servaddr, 0, sizeof (servaddr));
446
servaddr.sin_family = AF_INET;
447
servaddr.sin_addr.s_addr = htonl (INADDR_ANY);
448
servaddr.sin_port = htons (port);
450
if (bind (listenfd, (struct sockaddr *) &servaddr, sizeof (servaddr)) == -1)
459
if (!wait_connect ())
462
handle_connection (connfd);
466
// close (listenfd); /* Not reached */