1 /* 2 * Control - SHM Client 3 * Copyright (c) 2000 by Abramo Bagnara <abramo (at) alsa-project.org> 4 * 5 * 6 * This library is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU Lesser General Public License as 8 * published by the Free Software Foundation; either version 2.1 of 9 * the License, or (at your option) any later version. 10 * 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 Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <stddef.h> 25 #include <unistd.h> 26 #include <string.h> 27 #include <fcntl.h> 28 #include <sys/shm.h> 29 #include <sys/socket.h> 30 #include <sys/poll.h> 31 #include <sys/un.h> 32 #include <sys/uio.h> 33 #include <sys/mman.h> 34 #include <netinet/in.h> 35 #include <netdb.h> 36 #include "aserver.h" 37 38 #ifndef PIC 39 /* entry for static linking */ 40 const char *_snd_module_control_shm = ""; 41 #endif 42 43 #ifndef DOC_HIDDEN 44 typedef struct { 45 int socket; 46 volatile snd_ctl_shm_ctrl_t *ctrl; 47 } snd_ctl_shm_t; 48 #endif 49 50 static int snd_ctl_shm_action(snd_ctl_t *ctl) 51 { 52 snd_ctl_shm_t *shm = ctl->private_data; 53 int err; 54 char buf[1]; 55 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 56 err = write(shm->socket, buf, 1); 57 if (err != 1) 58 return -EBADFD; 59 err = read(shm->socket, buf, 1); 60 if (err != 1) 61 return -EBADFD; 62 if (ctrl->cmd) { 63 SNDERR("Server has not done the cmd"); 64 return -EBADFD; 65 } 66 return ctrl->result; 67 } 68 69 static int snd_ctl_shm_action_fd(snd_ctl_t *ctl, int *fd) 70 { 71 snd_ctl_shm_t *shm = ctl->private_data; 72 int err; 73 char buf[1]; 74 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 75 err = write(shm->socket, buf, 1); 76 if (err != 1) 77 return -EBADFD; 78 err = snd_receive_fd(shm->socket, buf, 1, fd); 79 if (err != 1) 80 return -EBADFD; 81 if (ctrl->cmd) { 82 SNDERR("Server has not done the cmd"); 83 return -EBADFD; 84 } 85 return ctrl->result; 86 } 87 88 static int snd_ctl_shm_close(snd_ctl_t *ctl) 89 { 90 snd_ctl_shm_t *shm = ctl->private_data; 91 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 92 int result; 93 ctrl->cmd = SND_CTL_IOCTL_CLOSE; 94 result = snd_ctl_shm_action(ctl); 95 shmdt((void *)ctrl); 96 close(shm->socket); 97 free(shm); 98 return result; 99 } 100 101 static int snd_ctl_shm_nonblock(snd_ctl_t *handle ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED) 102 { 103 return 0; 104 } 105 106 static int snd_ctl_shm_async(snd_ctl_t *ctl, int sig, pid_t pid) 107 { 108 snd_ctl_shm_t *shm = ctl->private_data; 109 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 110 ctrl->cmd = SND_CTL_IOCTL_ASYNC; 111 ctrl->u.async.sig = sig; 112 if (pid == 0) 113 pid = getpid(); 114 ctrl->u.async.pid = pid; 115 return snd_ctl_shm_action(ctl); 116 } 117 118 static int snd_ctl_shm_poll_descriptor(snd_ctl_t *ctl) 119 { 120 snd_ctl_shm_t *shm = ctl->private_data; 121 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 122 int fd, err; 123 ctrl->cmd = SND_CTL_IOCTL_POLL_DESCRIPTOR; 124 err = snd_ctl_shm_action_fd(ctl, &fd); 125 if (err < 0) 126 return err; 127 return fd; 128 } 129 130 static int snd_ctl_shm_subscribe_events(snd_ctl_t *ctl, int subscribe) 131 { 132 snd_ctl_shm_t *shm = ctl->private_data; 133 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 134 ctrl->cmd = SNDRV_CTL_IOCTL_SUBSCRIBE_EVENTS; 135 ctrl->u.subscribe_events = subscribe; 136 return snd_ctl_shm_action(ctl); 137 } 138 139 static int snd_ctl_shm_card_info(snd_ctl_t *ctl, snd_ctl_card_info_t *info) 140 { 141 snd_ctl_shm_t *shm = ctl->private_data; 142 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 143 int err; 144 // ctrl->u.card_info = *info; 145 ctrl->cmd = SNDRV_CTL_IOCTL_CARD_INFO; 146 err = snd_ctl_shm_action(ctl); 147 if (err < 0) 148 return err; 149 *info = ctrl->u.card_info; 150 return err; 151 } 152 153 static int snd_ctl_shm_elem_list(snd_ctl_t *ctl, snd_ctl_elem_list_t *list) 154 { 155 snd_ctl_shm_t *shm = ctl->private_data; 156 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 157 size_t maxsize = CTL_SHM_DATA_MAXLEN; 158 size_t bytes = list->space * sizeof(*list->pids); 159 int err; 160 snd_ctl_elem_id_t *pids = list->pids; 161 if (bytes > maxsize) 162 return -EINVAL; 163 ctrl->u.element_list = *list; 164 ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_LIST; 165 err = snd_ctl_shm_action(ctl); 166 if (err < 0) 167 return err; 168 *list = ctrl->u.element_list; 169 list->pids = pids; 170 bytes = list->used * sizeof(*list->pids); 171 memcpy(pids, (void *)ctrl->data, bytes); 172 return err; 173 } 174 175 static int snd_ctl_shm_elem_info(snd_ctl_t *ctl, snd_ctl_elem_info_t *info) 176 { 177 snd_ctl_shm_t *shm = ctl->private_data; 178 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 179 int err; 180 ctrl->u.element_info = *info; 181 ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_INFO; 182 err = snd_ctl_shm_action(ctl); 183 if (err < 0) 184 return err; 185 *info = ctrl->u.element_info; 186 return err; 187 } 188 189 static int snd_ctl_shm_elem_read(snd_ctl_t *ctl, snd_ctl_elem_value_t *control) 190 { 191 snd_ctl_shm_t *shm = ctl->private_data; 192 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 193 int err; 194 ctrl->u.element_read = *control; 195 ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_READ; 196 err = snd_ctl_shm_action(ctl); 197 if (err < 0) 198 return err; 199 *control = ctrl->u.element_read; 200 return err; 201 } 202 203 static int snd_ctl_shm_elem_write(snd_ctl_t *ctl, snd_ctl_elem_value_t *control) 204 { 205 snd_ctl_shm_t *shm = ctl->private_data; 206 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 207 int err; 208 ctrl->u.element_write = *control; 209 ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_WRITE; 210 err = snd_ctl_shm_action(ctl); 211 if (err < 0) 212 return err; 213 *control = ctrl->u.element_write; 214 return err; 215 } 216 217 static int snd_ctl_shm_elem_lock(snd_ctl_t *ctl, snd_ctl_elem_id_t *id) 218 { 219 snd_ctl_shm_t *shm = ctl->private_data; 220 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 221 int err; 222 ctrl->u.element_lock = *id; 223 ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_LOCK; 224 err = snd_ctl_shm_action(ctl); 225 if (err < 0) 226 return err; 227 *id = ctrl->u.element_lock; 228 return err; 229 } 230 231 static int snd_ctl_shm_elem_unlock(snd_ctl_t *ctl, snd_ctl_elem_id_t *id) 232 { 233 snd_ctl_shm_t *shm = ctl->private_data; 234 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 235 int err; 236 ctrl->u.element_unlock = *id; 237 ctrl->cmd = SNDRV_CTL_IOCTL_ELEM_UNLOCK; 238 err = snd_ctl_shm_action(ctl); 239 if (err < 0) 240 return err; 241 *id = ctrl->u.element_unlock; 242 return err; 243 } 244 245 static int snd_ctl_shm_hwdep_next_device(snd_ctl_t *ctl, int * device) 246 { 247 snd_ctl_shm_t *shm = ctl->private_data; 248 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 249 int err; 250 ctrl->u.device = *device; 251 ctrl->cmd = SNDRV_CTL_IOCTL_HWDEP_NEXT_DEVICE; 252 err = snd_ctl_shm_action(ctl); 253 if (err < 0) 254 return err; 255 *device = ctrl->u.device; 256 return err; 257 } 258 259 static int snd_ctl_shm_hwdep_info(snd_ctl_t *ctl, snd_hwdep_info_t * info) 260 { 261 snd_ctl_shm_t *shm = ctl->private_data; 262 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 263 int err; 264 ctrl->u.hwdep_info = *info; 265 ctrl->cmd = SNDRV_CTL_IOCTL_HWDEP_INFO; 266 err = snd_ctl_shm_action(ctl); 267 if (err < 0) 268 return err; 269 *info = ctrl->u.hwdep_info; 270 return err; 271 } 272 273 static int snd_ctl_shm_pcm_next_device(snd_ctl_t *ctl, int * device) 274 { 275 snd_ctl_shm_t *shm = ctl->private_data; 276 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 277 int err; 278 ctrl->u.device = *device; 279 ctrl->cmd = SNDRV_CTL_IOCTL_PCM_NEXT_DEVICE; 280 err = snd_ctl_shm_action(ctl); 281 if (err < 0) 282 return err; 283 *device = ctrl->u.device; 284 return err; 285 } 286 287 static int snd_ctl_shm_pcm_info(snd_ctl_t *ctl, snd_pcm_info_t * info) 288 { 289 snd_ctl_shm_t *shm = ctl->private_data; 290 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 291 int err; 292 ctrl->u.pcm_info = *info; 293 ctrl->cmd = SNDRV_CTL_IOCTL_PCM_INFO; 294 err = snd_ctl_shm_action(ctl); 295 if (err < 0) 296 return err; 297 *info = ctrl->u.pcm_info; 298 return err; 299 } 300 301 static int snd_ctl_shm_pcm_prefer_subdevice(snd_ctl_t *ctl, int subdev) 302 { 303 snd_ctl_shm_t *shm = ctl->private_data; 304 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 305 int err; 306 ctrl->u.pcm_prefer_subdevice = subdev; 307 ctrl->cmd = SNDRV_CTL_IOCTL_PCM_PREFER_SUBDEVICE; 308 err = snd_ctl_shm_action(ctl); 309 if (err < 0) 310 return err; 311 return err; 312 } 313 314 static int snd_ctl_shm_rawmidi_next_device(snd_ctl_t *ctl, int * device) 315 { 316 snd_ctl_shm_t *shm = ctl->private_data; 317 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 318 int err; 319 ctrl->u.device = *device; 320 ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_NEXT_DEVICE; 321 err = snd_ctl_shm_action(ctl); 322 if (err < 0) 323 return err; 324 *device = ctrl->u.device; 325 return err; 326 } 327 328 static int snd_ctl_shm_rawmidi_info(snd_ctl_t *ctl, snd_rawmidi_info_t * info) 329 { 330 snd_ctl_shm_t *shm = ctl->private_data; 331 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 332 int err; 333 ctrl->u.rawmidi_info = *info; 334 ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_INFO; 335 err = snd_ctl_shm_action(ctl); 336 if (err < 0) 337 return err; 338 *info = ctrl->u.rawmidi_info; 339 return err; 340 } 341 342 static int snd_ctl_shm_rawmidi_prefer_subdevice(snd_ctl_t *ctl, int subdev) 343 { 344 snd_ctl_shm_t *shm = ctl->private_data; 345 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 346 int err; 347 ctrl->u.rawmidi_prefer_subdevice = subdev; 348 ctrl->cmd = SNDRV_CTL_IOCTL_RAWMIDI_PREFER_SUBDEVICE; 349 err = snd_ctl_shm_action(ctl); 350 if (err < 0) 351 return err; 352 return err; 353 } 354 355 static int snd_ctl_shm_set_power_state(snd_ctl_t *ctl, unsigned int state) 356 { 357 snd_ctl_shm_t *shm = ctl->private_data; 358 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 359 int err; 360 ctrl->u.power_state = state; 361 ctrl->cmd = SNDRV_CTL_IOCTL_POWER; 362 err = snd_ctl_shm_action(ctl); 363 if (err < 0) 364 return err; 365 return err; 366 } 367 368 static int snd_ctl_shm_get_power_state(snd_ctl_t *ctl, unsigned int *state) 369 { 370 snd_ctl_shm_t *shm = ctl->private_data; 371 volatile snd_ctl_shm_ctrl_t *ctrl = shm->ctrl; 372 int err; 373 ctrl->cmd = SNDRV_CTL_IOCTL_POWER_STATE; 374 err = snd_ctl_shm_action(ctl); 375 if (err < 0) 376 return err; 377 *state = ctrl->u.power_state; 378 return err; 379 } 380 381 static int snd_ctl_shm_read(snd_ctl_t *ctl, snd_ctl_event_t *event) 382 { 383 snd_ctl_shm_t *shm; 384 volatile snd_ctl_shm_ctrl_t *ctrl; 385 int err; 386 err = snd_ctl_wait(ctl, -1); 387 if (err < 0) 388 return 0; 389 shm = ctl->private_data; 390 ctrl = shm->ctrl; 391 ctrl->u.read = *event; 392 ctrl->cmd = SND_CTL_IOCTL_READ; 393 err = snd_ctl_shm_action(ctl); 394 if (err < 0) 395 return err; 396 *event = ctrl->u.read; 397 return err; 398 } 399 400 static const snd_ctl_ops_t snd_ctl_shm_ops = { 401 .close = snd_ctl_shm_close, 402 .nonblock = snd_ctl_shm_nonblock, 403 .async = snd_ctl_shm_async, 404 .subscribe_events = snd_ctl_shm_subscribe_events, 405 .card_info = snd_ctl_shm_card_info, 406 .element_list = snd_ctl_shm_elem_list, 407 .element_info = snd_ctl_shm_elem_info, 408 .element_read = snd_ctl_shm_elem_read, 409 .element_write = snd_ctl_shm_elem_write, 410 .element_lock = snd_ctl_shm_elem_lock, 411 .element_unlock = snd_ctl_shm_elem_unlock, 412 .hwdep_next_device = snd_ctl_shm_hwdep_next_device, 413 .hwdep_info = snd_ctl_shm_hwdep_info, 414 .pcm_next_device = snd_ctl_shm_pcm_next_device, 415 .pcm_info = snd_ctl_shm_pcm_info, 416 .pcm_prefer_subdevice = snd_ctl_shm_pcm_prefer_subdevice, 417 .rawmidi_next_device = snd_ctl_shm_rawmidi_next_device, 418 .rawmidi_info = snd_ctl_shm_rawmidi_info, 419 .rawmidi_prefer_subdevice = snd_ctl_shm_rawmidi_prefer_subdevice, 420 .set_power_state = snd_ctl_shm_set_power_state, 421 .get_power_state = snd_ctl_shm_get_power_state, 422 .read = snd_ctl_shm_read, 423 }; 424 425 static int make_local_socket(const char *filename) 426 { 427 size_t l = strlen(filename); 428 size_t size = offsetof(struct sockaddr_un, sun_path) + l; 429 struct sockaddr_un *addr = alloca(size); 430 int sock; 431 432 sock = socket(PF_LOCAL, SOCK_STREAM, 0); 433 if (sock < 0) 434 return -errno; 435 436 addr->sun_family = AF_LOCAL; 437 memcpy(addr->sun_path, filename, l); 438 439 if (connect(sock, (struct sockaddr *) addr, size) < 0) 440 return -errno; 441 return sock; 442 } 443 444 #if 0 445 static int make_inet_socket(const char *host, int port) 446 { 447 struct sockaddr_in addr; 448 int sock; 449 struct hostent *h = gethostbyname(host); 450 if (!h) 451 return -ENOENT; 452 453 sock = socket(PF_INET, SOCK_STREAM, 0); 454 if (sock < 0) 455 return -errno; 456 457 addr.sin_family = AF_INET; 458 addr.sin_port = htons(port); 459 memcpy(&addr.sin_addr, h->h_addr_list[0], sizeof(struct in_addr)); 460 461 if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) 462 return -errno; 463 return sock; 464 } 465 #endif 466 467 int snd_ctl_shm_open(snd_ctl_t **handlep, const char *name, const char *sockname, const char *sname, int mode) 468 { 469 snd_ctl_t *ctl; 470 snd_ctl_shm_t *shm = NULL; 471 snd_client_open_request_t *req; 472 snd_client_open_answer_t ans; 473 size_t snamelen, reqlen; 474 int err; 475 int result; 476 int sock = -1; 477 snd_ctl_shm_ctrl_t *ctrl = NULL; 478 snamelen = strlen(sname); 479 if (snamelen > 255) 480 return -EINVAL; 481 482 result = make_local_socket(sockname); 483 if (result < 0) { 484 SNDERR("server for socket %s is not running", sockname); 485 goto _err; 486 } 487 sock = result; 488 489 reqlen = sizeof(*req) + snamelen; 490 req = alloca(reqlen); 491 memcpy(req->name, sname, snamelen); 492 req->dev_type = SND_DEV_TYPE_CONTROL; 493 req->transport_type = SND_TRANSPORT_TYPE_SHM; 494 req->stream = 0; 495 req->mode = mode; 496 req->namelen = snamelen; 497 err = write(sock, req, reqlen); 498 if (err < 0) { 499 SNDERR("write error"); 500 result = -errno; 501 goto _err; 502 } 503 if ((size_t) err != reqlen) { 504 SNDERR("write size error"); 505 result = -EINVAL; 506 goto _err; 507 } 508 err = read(sock, &ans, sizeof(ans)); 509 if (err < 0) { 510 SNDERR("read error"); 511 result = -errno; 512 goto _err; 513 } 514 if (err != sizeof(ans)) { 515 SNDERR("read size error"); 516 result = -EINVAL; 517 goto _err; 518 } 519 result = ans.result; 520 if (result < 0) 521 goto _err; 522 523 ctrl = shmat(ans.cookie, 0, 0); 524 if (!ctrl) { 525 result = -errno; 526 goto _err; 527 } 528 529 shm = calloc(1, sizeof(snd_ctl_shm_t)); 530 if (!shm) { 531 result = -ENOMEM; 532 goto _err; 533 } 534 535 shm->socket = sock; 536 shm->ctrl = ctrl; 537 538 err = snd_ctl_new(&ctl, SND_CTL_TYPE_SHM, name); 539 if (err < 0) { 540 result = err; 541 goto _err; 542 } 543 ctl->ops = &snd_ctl_shm_ops; 544 ctl->private_data = shm; 545 err = snd_ctl_shm_poll_descriptor(ctl); 546 if (err < 0) { 547 snd_ctl_close(ctl); 548 return err; 549 } 550 ctl->poll_fd = err; 551 *handlep = ctl; 552 return 0; 553 554 _err: 555 close(sock); 556 if (ctrl) 557 shmdt(ctrl); 558 free(shm); 559 return result; 560 } 561 562 int _snd_ctl_shm_open(snd_ctl_t **handlep, char *name, snd_config_t *root, snd_config_t *conf, int mode) 563 { 564 snd_config_iterator_t i, next; 565 const char *server = NULL; 566 const char *ctl_name = NULL; 567 snd_config_t *sconfig; 568 const char *host = NULL; 569 const char *sockname = NULL; 570 long port = -1; 571 int err; 572 int local; 573 struct hostent *h; 574 snd_config_for_each(i, next, conf) { 575 snd_config_t *n = snd_config_iterator_entry(i); 576 const char *id; 577 if (snd_config_get_id(n, &id) < 0) 578 continue; 579 if (strcmp(id, "comment") == 0) 580 continue; 581 if (strcmp(id, "type") == 0) 582 continue; 583 if (strcmp(id, "server") == 0) { 584 err = snd_config_get_string(n, &server); 585 if (err < 0) { 586 SNDERR("Invalid type for %s", id); 587 return -EINVAL; 588 } 589 continue; 590 } 591 if (strcmp(id, "ctl") == 0) { 592 err = snd_config_get_string(n, &ctl_name); 593 if (err < 0) { 594 SNDERR("Invalid type for %s", id); 595 return -EINVAL; 596 } 597 continue; 598 } 599 SNDERR("Unknown field %s", id); 600 return -EINVAL; 601 } 602 if (!ctl_name) { 603 SNDERR("ctl is not defined"); 604 return -EINVAL; 605 } 606 if (!server) { 607 SNDERR("server is not defined"); 608 return -EINVAL; 609 } 610 err = snd_config_search_definition(root, "server", server, &sconfig); 611 if (err < 0) { 612 SNDERR("Unknown server %s", server); 613 return -EINVAL; 614 } 615 if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) { 616 SNDERR("Invalid type for server %s definition", server); 617 err = -EINVAL; 618 goto _err; 619 } 620 snd_config_for_each(i, next, sconfig) { 621 snd_config_t *n = snd_config_iterator_entry(i); 622 const char *id; 623 if (snd_config_get_id(n, &id) < 0) 624 continue; 625 if (strcmp(id, "comment") == 0) 626 continue; 627 if (strcmp(id, "host") == 0) { 628 err = snd_config_get_string(n, &host); 629 if (err < 0) { 630 SNDERR("Invalid type for %s", id); 631 goto _err; 632 } 633 continue; 634 } 635 if (strcmp(id, "socket") == 0) { 636 err = snd_config_get_string(n, &sockname); 637 if (err < 0) { 638 SNDERR("Invalid type for %s", id); 639 goto _err; 640 } 641 continue; 642 } 643 if (strcmp(id, "port") == 0) { 644 err = snd_config_get_integer(n, &port); 645 if (err < 0) { 646 SNDERR("Invalid type for %s", id); 647 goto _err; 648 } 649 continue; 650 } 651 SNDERR("Unknown field %s", id); 652 err = -EINVAL; 653 goto _err; 654 } 655 656 if (!host) { 657 SNDERR("host is not defined"); 658 goto _err; 659 } 660 if (!sockname) { 661 SNDERR("socket is not defined"); 662 goto _err; 663 } 664 h = gethostbyname(host); 665 if (!h) { 666 SNDERR("Cannot resolve %s", host); 667 goto _err; 668 } 669 local = snd_is_local(h); 670 if (!local) { 671 SNDERR("%s is not the local host", host); 672 goto _err; 673 } 674 err = snd_ctl_shm_open(handlep, name, sockname, ctl_name, mode); 675 _err: 676 snd_config_delete(sconfig); 677 return err; 678 } 679 SND_DLSYM_BUILD_VERSION(_snd_ctl_shm_open, SND_CONTROL_DLSYM_VERSION); 680