3 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Library General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <sys/socket.h>
35 #include <netinet/in.h>
37 #include "control_local.h"
45 extern int receive_fd(int socket, void *data, size_t len, int *fd);
47 static int snd_ctl_shm_action(snd_ctl_t *ctl)
49 snd_ctl_shm_t *shm = ctl->private;
52 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
53 err = write(shm->socket, buf, 1);
56 err = read(shm->socket, buf, 1);
60 fprintf(stderr, "Server has not done the cmd\n");
66 static int snd_ctl_shm_action_fd(snd_ctl_t *ctl, int *fd)
68 snd_ctl_shm_t *shm = ctl->private;
71 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
72 err = write(shm->socket, buf, 1);
75 err = receive_fd(shm->socket, buf, 1, fd);
79 fprintf(stderr, "Server has not done the cmd\n");
85 static int snd_ctl_shm_close(snd_ctl_t *ctl)
87 snd_ctl_shm_t *shm = ctl->private;
88 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
90 ctrl->cmd = SND_CTL_IOCTL_CLOSE;
91 result = snd_ctl_shm_action(ctl);
98 static int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl)
100 snd_ctl_shm_t *shm = ctl->private;
101 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
103 ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR;
104 err = snd_ctl_shm_action_fd(ctl, &fd);
110 static int snd_ctl_shm_hw_info(snd_ctl_t *ctl, snd_ctl_hw_info_t *info)
112 snd_ctl_shm_t *shm = ctl->private;
113 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
115 // ctrl->u.hw_info = *info;
116 ctrl->cmd = SND_CTL_IOCTL_HW_INFO;
117 err = snd_ctl_shm_action(ctl);
120 *info = ctrl->u.hw_info;
124 static int snd_ctl_shm_clist(snd_ctl_t *ctl, snd_control_list_t *list)
126 snd_ctl_shm_t *shm = ctl->private;
127 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
128 size_t maxsize = CTL_SHM_DATA_MAXLEN;
129 size_t bytes = list->controls_request * sizeof(*list->pids);
131 snd_control_id_t *pids = list->pids;
134 ctrl->u.clist = *list;
135 ctrl->cmd = SND_CTL_IOCTL_CONTROL_LIST;
136 err = snd_ctl_shm_action(ctl);
139 *list = ctrl->u.clist;
141 memcpy(pids, ctrl->data, bytes);
145 static int snd_ctl_shm_cinfo(snd_ctl_t *ctl, snd_control_info_t *info)
147 snd_ctl_shm_t *shm = ctl->private;
148 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
150 ctrl->u.cinfo = *info;
151 ctrl->cmd = SND_CTL_IOCTL_CONTROL_INFO;
152 err = snd_ctl_shm_action(ctl);
155 *info = ctrl->u.cinfo;
159 static int snd_ctl_shm_cread(snd_ctl_t *ctl, snd_control_t *control)
161 snd_ctl_shm_t *shm = ctl->private;
162 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
164 ctrl->u.cread = *control;
165 ctrl->cmd = SND_CTL_IOCTL_CONTROL_READ;
166 err = snd_ctl_shm_action(ctl);
169 *control = ctrl->u.cread;
173 static int snd_ctl_shm_cwrite(snd_ctl_t *ctl, snd_control_t *control)
175 snd_ctl_shm_t *shm = ctl->private;
176 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
178 ctrl->u.cwrite = *control;
179 ctrl->cmd = SND_CTL_IOCTL_CONTROL_WRITE;
180 err = snd_ctl_shm_action(ctl);
183 *control = ctrl->u.cwrite;
187 static int snd_ctl_shm_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info)
189 snd_ctl_shm_t *shm = ctl->private;
190 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
192 ctrl->u.hwdep_info = *info;
193 ctrl->cmd = SND_CTL_IOCTL_HWDEP_INFO;
194 err = snd_ctl_shm_action(ctl);
197 *info = ctrl->u.hwdep_info;
201 static int snd_ctl_shm_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info)
203 snd_ctl_shm_t *shm = ctl->private;
204 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
206 ctrl->u.pcm_info = *info;
207 ctrl->cmd = SND_CTL_IOCTL_PCM_INFO;
208 err = snd_ctl_shm_action(ctl);
211 *info = ctrl->u.pcm_info;
215 static int snd_ctl_shm_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev)
217 snd_ctl_shm_t *shm = ctl->private;
218 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
220 ctrl->u.pcm_prefer_subdevice = subdev;
221 ctrl->cmd = SND_CTL_IOCTL_PCM_PREFER_SUBDEVICE;
222 err = snd_ctl_shm_action(ctl);
228 static int snd_ctl_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info)
230 snd_ctl_shm_t *shm = ctl->private;
231 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
233 ctrl->u.rawmidi_info = *info;
234 ctrl->cmd = SND_CTL_IOCTL_RAWMIDI_INFO;
235 err = snd_ctl_shm_action(ctl);
238 *info = ctrl->u.rawmidi_info;
242 static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event)
244 snd_ctl_shm_t *shm = ctl->private;
245 snd_ctl_shm_ctrl_t *ctrl = shm->ctrl;
247 ctrl->u.read = *event;
248 ctrl->cmd = SND_CTL_IOCTL_READ;
249 err = snd_ctl_shm_action(ctl);
252 *event = ctrl->u.read;
256 struct snd_ctl_ops snd_ctl_shm_ops = {
257 close: snd_ctl_shm_close,
258 poll_descriptor: snd_ctl_shm_poll_descriptor,
259 hw_info: snd_ctl_shm_hw_info,
260 clist: snd_ctl_shm_clist,
261 cinfo: snd_ctl_shm_cinfo,
262 cread: snd_ctl_shm_cread,
263 cwrite: snd_ctl_shm_cwrite,
264 hwdep_info: snd_ctl_shm_hwdep_info,
265 pcm_info: snd_ctl_shm_pcm_info,
266 pcm_prefer_subdevice: snd_ctl_shm_pcm_prefer_subdevice,
267 rawmidi_info: snd_ctl_shm_rawmidi_info,
268 read: snd_ctl_shm_read,
271 static int make_local_socket(const char *filename)
273 size_t l = strlen(filename);
274 size_t size = offsetof(struct sockaddr_un, sun_path) + l;
275 struct sockaddr_un *addr = alloca(size);
278 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
282 addr->sun_family = AF_LOCAL;
283 memcpy(addr->sun_path, filename, l);
285 if (connect(sock, (struct sockaddr *) addr, size) < 0)
291 static int make_inet_socket(const char *host, int port)
293 struct sockaddr_in addr;
295 struct hostent *h = gethostbyname(host);
299 sock = socket(PF_INET, SOCK_STREAM, 0);
303 addr.sin_family = AF_INET;
304 addr.sin_port = htons(port);
305 memcpy(&addr.sin_addr, h->h_addr_list[0], sizeof(struct in_addr));
307 if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0)
313 int snd_ctl_shm_open(snd_ctl_t **handlep, char *name, char *socket, char *sname)
316 snd_ctl_shm_t *shm = NULL;
317 snd_client_open_request_t *req;
318 snd_client_open_answer_t ans;
319 size_t snamelen, reqlen;
323 snd_ctl_shm_ctrl_t *ctrl = NULL;
324 snamelen = strlen(sname);
328 result = make_local_socket(socket);
330 ERR("server for socket %s is not running", socket);
335 reqlen = sizeof(*req) + snamelen;
336 req = alloca(reqlen);
337 memcpy(req->name, sname, snamelen);
338 req->dev_type = SND_DEV_TYPE_CONTROL;
339 req->transport_type = SND_TRANSPORT_TYPE_SHM;
342 req->namelen = snamelen;
343 err = write(sock, req, reqlen);
349 if ((size_t) err != reqlen) {
350 ERR("write size error");
354 err = read(sock, &ans, sizeof(ans));
360 if (err != sizeof(ans)) {
361 ERR("read size error");
369 ctrl = shmat(ans.cookie, 0, 0);
375 ctl = calloc(1, sizeof(snd_ctl_t));
380 shm = calloc(1, sizeof(snd_ctl_shm_t));
391 ctl->name = strdup(name);
392 ctl->type = SND_CTL_TYPE_SHM;
393 ctl->ops = &snd_ctl_shm_ops;
395 INIT_LIST_HEAD(&ctl->hlist);
408 extern int is_local(struct hostent *hent);
410 int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *conf)
412 snd_config_iterator_t i;
415 snd_config_t *sconfig;
422 snd_config_foreach(i, conf) {
423 snd_config_t *n = snd_config_entry(i);
424 if (strcmp(n->id, "comment") == 0)
426 if (strcmp(n->id, "type") == 0)
428 if (strcmp(n->id, "server") == 0) {
429 err = snd_config_string_get(n, &server);
431 ERR("Invalid type for server");
436 if (strcmp(n->id, "sname") == 0) {
437 err = snd_config_string_get(n, &sname);
439 ERR("Invalid type for sname");
444 ERR("Unknown field: %s", n->id);
448 ERR("sname is not defined");
452 ERR("server is not defined");
455 err = snd_config_searchv(snd_config, &sconfig, "server", server, 0);
457 ERR("Unknown server %s", server);
460 snd_config_foreach(i, conf) {
461 snd_config_t *n = snd_config_entry(i);
462 if (strcmp(n->id, "comment") == 0)
464 if (strcmp(n->id, "host") == 0) {
465 err = snd_config_string_get(n, &host);
467 ERR("Invalid type for host");
472 if (strcmp(n->id, "socket") == 0) {
473 err = snd_config_string_get(n, &socket);
475 ERR("Invalid type for socket");
480 if (strcmp(n->id, "port") == 0) {
481 err = snd_config_integer_get(n, &port);
483 ERR("Invalid type for port");
488 ERR("Unknown field: %s", n->id);
493 ERR("host is not defined");
497 ERR("socket is not defined");
500 h = gethostbyname(host);
502 ERR("Cannot resolve %s", host);
507 ERR("%s is not the local host", host);
510 return snd_ctl_shm_open(handlep, name, socket, sname);