4 * \brief PCM Shared Memory Plugin Interface
5 * \author Abramo Bagnara <abramo@alsa-project.org>
9 * PCM - Shared Memory Client
10 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
13 * This library is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU Lesser General Public License as
15 * published by the Free Software Foundation; either version 2.1 of
16 * the License, or (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License for more details.
23 * You should have received a copy of the GNU Lesser General Public
24 * License along with this library; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include <sys/ioctl.h>
38 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
49 /* entry for static linking */
50 const char *_snd_module_pcm_shm = "";
56 volatile snd_pcm_shm_ctrl_t *ctrl;
61 int snd_receive_fd(int sock, void *data, size_t len, int *fd)
64 size_t cmsg_len = CMSG_LEN(sizeof(int));
65 struct cmsghdr *cmsg = alloca(cmsg_len);
66 int *fds = (int *) CMSG_DATA(cmsg);
70 vec.iov_base = (void *)&data;
73 cmsg->cmsg_len = cmsg_len;
74 cmsg->cmsg_level = SOL_SOCKET;
75 cmsg->cmsg_type = SCM_RIGHTS;
78 msghdr.msg_name = NULL;
79 msghdr.msg_namelen = 0;
80 msghdr.msg_iov = &vec;
81 msghdr.msg_iovlen = 1;
82 msghdr.msg_control = cmsg;
83 msghdr.msg_controllen = cmsg_len;
86 ret = recvmsg(sock, &msghdr, 0);
88 SYSERR("recvmsg failed");
96 static long snd_pcm_shm_action_fd0(snd_pcm_t *pcm, int *fd)
98 snd_pcm_shm_t *shm = pcm->private_data;
101 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
103 err = write(shm->socket, buf, 1);
106 err = snd_receive_fd(shm->socket, buf, 1, fd);
110 SNDERR("Server has not done the cmd");
116 static int snd_pcm_shm_new_rbptr(snd_pcm_t *pcm, snd_pcm_shm_t *shm,
117 snd_pcm_rbptr_t *rbptr, volatile snd_pcm_shm_rbptr_t *shm_rbptr)
119 if (!shm_rbptr->use_mmap) {
120 if (&pcm->hw == rbptr)
121 snd_pcm_set_hw_ptr(pcm, &shm_rbptr->ptr, -1, 0);
123 snd_pcm_set_appl_ptr(pcm, &shm_rbptr->ptr, -1, 0);
126 size_t mmap_size, mmap_offset, offset;
130 shm->ctrl->cmd = &pcm->hw == rbptr ? SND_PCM_IOCTL_HW_PTR_FD : SND_PCM_IOCTL_APPL_PTR_FD;
131 result = snd_pcm_shm_action_fd0(pcm, &fd);
134 mmap_size = page_ptr(shm_rbptr->offset, sizeof(snd_pcm_uframes_t), &offset, &mmap_offset);
135 ptr = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, mmap_offset);
136 if (ptr == MAP_FAILED || ptr == NULL) {
137 SYSERR("shm rbptr mmap failed");
140 if (&pcm->hw == rbptr)
141 snd_pcm_set_hw_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset);
143 snd_pcm_set_appl_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset);
148 static long snd_pcm_shm_action(snd_pcm_t *pcm)
150 snd_pcm_shm_t *shm = pcm->private_data;
153 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
155 if (ctrl->hw.changed || ctrl->appl.changed)
157 err = write(shm->socket, buf, 1);
160 err = read(shm->socket, buf, 1);
164 SNDERR("Server has not done the cmd");
167 result = ctrl->result;
168 if (ctrl->hw.changed) {
169 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw);
172 ctrl->hw.changed = 0;
174 if (ctrl->appl.changed) {
175 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl);
178 ctrl->appl.changed = 0;
183 static long snd_pcm_shm_action_fd(snd_pcm_t *pcm, int *fd)
185 snd_pcm_shm_t *shm = pcm->private_data;
188 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
190 if (ctrl->hw.changed || ctrl->appl.changed)
192 err = write(shm->socket, buf, 1);
195 err = snd_receive_fd(shm->socket, buf, 1, fd);
199 SNDERR("Server has not done the cmd");
202 if (ctrl->hw.changed) {
203 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw);
206 ctrl->hw.changed = 0;
208 if (ctrl->appl.changed) {
209 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl);
212 ctrl->appl.changed = 0;
217 static int snd_pcm_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
222 static int snd_pcm_shm_async(snd_pcm_t *pcm, int sig, pid_t pid)
224 snd_pcm_shm_t *shm = pcm->private_data;
225 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
226 ctrl->cmd = SND_PCM_IOCTL_ASYNC;
227 ctrl->u.async.sig = sig;
228 ctrl->u.async.pid = pid;
229 return snd_pcm_shm_action(pcm);
232 static int snd_pcm_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
234 snd_pcm_shm_t *shm = pcm->private_data;
235 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
237 // ctrl->u.info = *info;
238 ctrl->cmd = SNDRV_PCM_IOCTL_INFO;
239 err = snd_pcm_shm_action(pcm);
242 *info = ctrl->u.info;
246 static int snd_pcm_shm_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
251 static int snd_pcm_shm_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
253 snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
254 _snd_pcm_hw_params_any(sparams);
255 _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
260 static int snd_pcm_shm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
261 snd_pcm_hw_params_t *sparams)
264 unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
265 const snd_pcm_access_mask_t *access_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
266 if (!snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
267 !snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) {
268 err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
273 err = _snd_pcm_hw_params_refine(sparams, links, params);
279 static int snd_pcm_shm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
280 snd_pcm_hw_params_t *sparams)
283 unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
284 snd_pcm_access_mask_t access_mask;
285 snd_mask_copy(&access_mask, snd_pcm_hw_param_get_mask(sparams, SND_PCM_HW_PARAM_ACCESS));
286 snd_pcm_access_mask_set(&access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
287 snd_pcm_access_mask_set(&access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
288 err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
292 err = _snd_pcm_hw_params_refine(params, links, sparams);
298 static int snd_pcm_shm_hw_refine_slave(snd_pcm_t *pcm,
299 snd_pcm_hw_params_t *params)
301 snd_pcm_shm_t *shm = pcm->private_data;
302 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
304 ctrl->u.hw_refine = *params;
305 ctrl->cmd = SNDRV_PCM_IOCTL_HW_REFINE;
306 err = snd_pcm_shm_action(pcm);
307 *params = ctrl->u.hw_refine;
311 static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
313 return snd_pcm_hw_refine_slave(pcm, params,
314 snd_pcm_shm_hw_refine_cprepare,
315 snd_pcm_shm_hw_refine_cchange,
316 snd_pcm_shm_hw_refine_sprepare,
317 snd_pcm_shm_hw_refine_schange,
318 snd_pcm_shm_hw_refine_slave);
321 static int snd_pcm_shm_hw_params_slave(snd_pcm_t *pcm,
322 snd_pcm_hw_params_t *params)
324 snd_pcm_shm_t *shm = pcm->private_data;
325 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
327 ctrl->cmd = SNDRV_PCM_IOCTL_HW_PARAMS;
328 ctrl->u.hw_params = *params;
329 err = snd_pcm_shm_action(pcm);
330 *params = ctrl->u.hw_params;
334 static int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
336 return snd_pcm_hw_params_slave(pcm, params,
337 snd_pcm_shm_hw_refine_cchange,
338 snd_pcm_shm_hw_refine_sprepare,
339 snd_pcm_shm_hw_refine_schange,
340 snd_pcm_shm_hw_params_slave);
343 static int snd_pcm_shm_hw_free(snd_pcm_t *pcm)
345 snd_pcm_shm_t *shm = pcm->private_data;
346 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
347 ctrl->cmd = SNDRV_PCM_IOCTL_HW_FREE;
348 return snd_pcm_shm_action(pcm);
351 static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
353 snd_pcm_shm_t *shm = pcm->private_data;
354 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
356 ctrl->cmd = SNDRV_PCM_IOCTL_SW_PARAMS;
357 ctrl->u.sw_params = *params;
358 err = snd_pcm_shm_action(pcm);
359 *params = ctrl->u.sw_params;
365 static int snd_pcm_shm_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
370 static int snd_pcm_shm_munmap(snd_pcm_t *pcm)
373 for (c = 0; c < pcm->channels; ++c) {
374 snd_pcm_channel_info_t *i = &pcm->mmap_channels[c];
377 if (i->type != SND_PCM_AREA_MMAP)
379 if (i->u.mmap.fd < 0)
381 for (c1 = c + 1; c1 < pcm->channels; ++c1) {
382 snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1];
383 if (i1->type != SND_PCM_AREA_MMAP)
385 if (i1->u.mmap.fd != i->u.mmap.fd)
389 err = close(i->u.mmap.fd);
391 SYSERR("close failed");
398 static int snd_pcm_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
400 snd_pcm_shm_t *shm = pcm->private_data;
401 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
404 ctrl->cmd = SNDRV_PCM_IOCTL_CHANNEL_INFO;
405 ctrl->u.channel_info = *info;
406 err = snd_pcm_shm_action_fd(pcm, &fd);
409 *info = ctrl->u.channel_info;
411 switch (info->type) {
412 case SND_PCM_AREA_MMAP:
413 info->u.mmap.fd = fd;
415 case SND_PCM_AREA_SHM:
424 static int snd_pcm_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
426 snd_pcm_shm_t *shm = pcm->private_data;
427 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
429 ctrl->cmd = SNDRV_PCM_IOCTL_STATUS;
430 // ctrl->u.status = *status;
431 err = snd_pcm_shm_action(pcm);
434 *status = ctrl->u.status;
438 static snd_pcm_state_t snd_pcm_shm_state(snd_pcm_t *pcm)
440 snd_pcm_shm_t *shm = pcm->private_data;
441 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
442 ctrl->cmd = SND_PCM_IOCTL_STATE;
443 return snd_pcm_shm_action(pcm);
446 static int snd_pcm_shm_hwsync(snd_pcm_t *pcm)
448 snd_pcm_shm_t *shm = pcm->private_data;
449 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
450 ctrl->cmd = SND_PCM_IOCTL_HWSYNC;
451 return snd_pcm_shm_action(pcm);
454 static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
456 snd_pcm_shm_t *shm = pcm->private_data;
457 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
459 ctrl->cmd = SNDRV_PCM_IOCTL_DELAY;
460 err = snd_pcm_shm_action(pcm);
463 *delayp = ctrl->u.delay.frames;
467 static snd_pcm_sframes_t snd_pcm_shm_avail_update(snd_pcm_t *pcm)
469 snd_pcm_shm_t *shm = pcm->private_data;
470 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
472 ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE;
473 err = snd_pcm_shm_action(pcm);
479 static int snd_pcm_shm_prepare(snd_pcm_t *pcm)
481 snd_pcm_shm_t *shm = pcm->private_data;
482 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
483 ctrl->cmd = SNDRV_PCM_IOCTL_PREPARE;
484 return snd_pcm_shm_action(pcm);
487 static int snd_pcm_shm_reset(snd_pcm_t *pcm)
489 snd_pcm_shm_t *shm = pcm->private_data;
490 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
491 ctrl->cmd = SNDRV_PCM_IOCTL_RESET;
492 return snd_pcm_shm_action(pcm);
495 static int snd_pcm_shm_start(snd_pcm_t *pcm)
497 snd_pcm_shm_t *shm = pcm->private_data;
498 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
499 ctrl->cmd = SNDRV_PCM_IOCTL_START;
500 return snd_pcm_shm_action(pcm);
503 static int snd_pcm_shm_drop(snd_pcm_t *pcm)
505 snd_pcm_shm_t *shm = pcm->private_data;
506 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
507 ctrl->cmd = SNDRV_PCM_IOCTL_DROP;
508 return snd_pcm_shm_action(pcm);
511 static int snd_pcm_shm_drain(snd_pcm_t *pcm)
513 snd_pcm_shm_t *shm = pcm->private_data;
514 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
517 ctrl->cmd = SNDRV_PCM_IOCTL_DRAIN;
518 err = snd_pcm_shm_action(pcm);
525 if (!(pcm->mode & SND_PCM_NONBLOCK))
526 snd_pcm_wait(pcm, -1);
530 static int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable)
532 snd_pcm_shm_t *shm = pcm->private_data;
533 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
534 ctrl->cmd = SNDRV_PCM_IOCTL_PAUSE;
535 ctrl->u.pause.enable = enable;
536 return snd_pcm_shm_action(pcm);
539 static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
541 snd_pcm_shm_t *shm = pcm->private_data;
542 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
543 ctrl->cmd = SNDRV_PCM_IOCTL_REWIND;
544 ctrl->u.rewind.frames = frames;
545 return snd_pcm_shm_action(pcm);
548 static int snd_pcm_shm_resume(snd_pcm_t *pcm)
550 snd_pcm_shm_t *shm = pcm->private_data;
551 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
552 ctrl->cmd = SNDRV_PCM_IOCTL_RESUME;
553 return snd_pcm_shm_action(pcm);
556 static snd_pcm_sframes_t snd_pcm_shm_mmap_commit(snd_pcm_t *pcm,
557 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
558 snd_pcm_uframes_t size)
560 snd_pcm_shm_t *shm = pcm->private_data;
561 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
562 ctrl->cmd = SND_PCM_IOCTL_MMAP_COMMIT;
563 ctrl->u.mmap_commit.offset = offset;
564 ctrl->u.mmap_commit.frames = size;
565 return snd_pcm_shm_action(pcm);
568 static int snd_pcm_shm_poll_descriptor(snd_pcm_t *pcm)
570 snd_pcm_shm_t *shm = pcm->private_data;
571 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
573 ctrl->cmd = SND_PCM_IOCTL_POLL_DESCRIPTOR;
574 err = snd_pcm_shm_action_fd(pcm, &fd);
580 static int snd_pcm_shm_close(snd_pcm_t *pcm)
582 snd_pcm_shm_t *shm = pcm->private_data;
583 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
585 ctrl->cmd = SND_PCM_IOCTL_CLOSE;
586 result = snd_pcm_shm_action(pcm);
594 static void snd_pcm_shm_dump(snd_pcm_t *pcm, snd_output_t *out)
596 snd_output_printf(out, "Shm PCM\n");
598 snd_output_printf(out, "\nIts setup is:\n");
599 snd_pcm_dump_setup(pcm, out);
603 static snd_pcm_ops_t snd_pcm_shm_ops = {
604 close: snd_pcm_shm_close,
605 info: snd_pcm_shm_info,
606 hw_refine: snd_pcm_shm_hw_refine,
607 hw_params: snd_pcm_shm_hw_params,
608 hw_free: snd_pcm_shm_hw_free,
609 sw_params: snd_pcm_shm_sw_params,
610 channel_info: snd_pcm_shm_channel_info,
611 dump: snd_pcm_shm_dump,
612 nonblock: snd_pcm_shm_nonblock,
613 async: snd_pcm_shm_async,
614 mmap: snd_pcm_shm_mmap,
615 munmap: snd_pcm_shm_munmap,
618 static snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
619 status: snd_pcm_shm_status,
620 state: snd_pcm_shm_state,
621 hwsync: snd_pcm_shm_hwsync,
622 delay: snd_pcm_shm_delay,
623 prepare: snd_pcm_shm_prepare,
624 reset: snd_pcm_shm_reset,
625 start: snd_pcm_shm_start,
626 drop: snd_pcm_shm_drop,
627 drain: snd_pcm_shm_drain,
628 pause: snd_pcm_shm_pause,
629 rewind: snd_pcm_shm_rewind,
630 resume: snd_pcm_shm_resume,
631 writei: snd_pcm_mmap_writei,
632 writen: snd_pcm_mmap_writen,
633 readi: snd_pcm_mmap_readi,
634 readn: snd_pcm_mmap_readn,
635 avail_update: snd_pcm_shm_avail_update,
636 mmap_commit: snd_pcm_shm_mmap_commit,
639 static int make_local_socket(const char *filename)
641 size_t l = strlen(filename);
642 size_t size = offsetof(struct sockaddr_un, sun_path) + l;
643 struct sockaddr_un *addr = alloca(size);
646 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
648 SYSERR("socket failed");
652 addr->sun_family = AF_LOCAL;
653 memcpy(addr->sun_path, filename, l);
655 if (connect(sock, (struct sockaddr *) addr, size) < 0) {
656 SYSERR("connect failed");
663 static int make_inet_socket(const char *host, int port)
665 struct sockaddr_in addr;
667 struct hostent *h = gethostbyname(host);
671 sock = socket(PF_INET, SOCK_STREAM, 0);
673 SYSERR("socket failed");
677 addr.sin_family = AF_INET;
678 addr.sin_port = htons(port);
679 memcpy(&addr.sin_addr, h->h_addr_list[0], sizeof(struct in_addr));
681 if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
682 SYSERR("connect failed");
690 * \brief Creates a new shared memory PCM
691 * \param pcmp Returns created PCM handle
692 * \param name Name of PCM
693 * \param sockname Unix socket name
694 * \param sname Server name
695 * \param stream PCM Stream
696 * \param mode PCM Mode
697 * \retval zero on success otherwise a negative error code
698 * \warning Using of this function might be dangerous in the sense
699 * of compatibility reasons. The prototype might be freely
702 int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
703 const char *sockname, const char *sname,
704 snd_pcm_stream_t stream, int mode)
707 snd_pcm_shm_t *shm = NULL;
708 snd_client_open_request_t *req;
709 snd_client_open_answer_t ans;
710 size_t snamelen, reqlen;
713 snd_pcm_shm_ctrl_t *ctrl = NULL;
715 snamelen = strlen(sname);
719 result = make_local_socket(sockname);
721 SNDERR("server for socket %s is not running", sockname);
726 reqlen = sizeof(*req) + snamelen;
727 req = alloca(reqlen);
728 memcpy(req->name, sname, snamelen);
729 req->dev_type = SND_DEV_TYPE_PCM;
730 req->transport_type = SND_TRANSPORT_TYPE_SHM;
731 req->stream = stream;
733 req->namelen = snamelen;
734 err = write(sock, req, reqlen);
736 SYSERR("write error");
740 if ((size_t) err != reqlen) {
741 SNDERR("write size error");
745 err = read(sock, &ans, sizeof(ans));
747 SYSERR("read error");
751 if (err != sizeof(ans)) {
752 SNDERR("read size error");
760 ctrl = shmat(ans.cookie, 0, 0);
762 SYSERR("shmat error");
767 shm = calloc(1, sizeof(snd_pcm_shm_t));
776 err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHM, name, stream, mode);
782 pcm->ops = &snd_pcm_shm_ops;
783 pcm->fast_ops = &snd_pcm_shm_fast_ops;
784 pcm->private_data = shm;
785 err = snd_pcm_shm_poll_descriptor(pcm);
791 snd_pcm_set_hw_ptr(pcm, &ctrl->hw.ptr, -1, 0);
792 snd_pcm_set_appl_ptr(pcm, &ctrl->appl.ptr, -1, 0);
806 int snd_is_local(struct hostent *hent)
813 struct in_addr *haddr = (struct in_addr*) hent->h_addr_list[0];
815 s = socket(PF_INET, SOCK_STREAM, 0);
817 SYSERR("socket failed");
821 conf.ifc_len = numreqs * sizeof(struct ifreq);
822 conf.ifc_buf = malloc((unsigned int) conf.ifc_len);
824 err = ioctl(s, SIOCGIFCONF, &conf);
826 SYSERR("SIOCGIFCONF failed");
829 if ((size_t)conf.ifc_len < numreqs * sizeof(struct ifreq))
832 conf.ifc_len = numreqs * sizeof(struct ifreq);
833 conf.ifc_buf = realloc(conf.ifc_buf, (unsigned int) conf.ifc_len);
835 numreqs = conf.ifc_len / sizeof(struct ifreq);
836 for (i = 0; i < numreqs; ++i) {
837 struct ifreq *req = &conf.ifc_req[i];
838 struct sockaddr_in *s_in = (struct sockaddr_in *)&req->ifr_addr;
839 s_in->sin_family = AF_INET;
840 err = ioctl(s, SIOCGIFADDR, req);
843 if (haddr->s_addr == s_in->sin_addr.s_addr)
852 /*! \page pcm_plugins
854 \section pcm_plugins_shm Plugin: shm
856 This plugin communicates with aserver via shared memory. It is a raw
857 communication without any conversions, but it can be expected worse
862 type shm # Shared memory PCM
863 server STR # Server name
868 \subsection pcm_plugins_shm_funcref Function reference
871 <LI>snd_pcm_shm_open()
872 <LI>_snd_pcm_shm_open()
878 * \brief Creates a new shm PCM
879 * \param pcmp Returns created PCM handle
880 * \param name Name of PCM
881 * \param root Root configuration node
882 * \param conf Configuration node with hw PCM description
883 * \param stream PCM Stream
884 * \param mode PCM Mode
885 * \warning Using of this function might be dangerous in the sense
886 * of compatibility reasons. The prototype might be freely
889 int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
890 snd_config_t *root, snd_config_t *conf,
891 snd_pcm_stream_t stream, int mode)
893 snd_config_iterator_t i, next;
894 const char *server = NULL;
895 const char *pcm_name = NULL;
896 snd_config_t *sconfig;
897 const char *host = NULL;
898 const char *sockname = NULL;
903 snd_config_for_each(i, next, conf) {
904 snd_config_t *n = snd_config_iterator_entry(i);
906 if (snd_config_get_id(n, &id) < 0)
908 if (snd_pcm_conf_generic_id(id))
910 if (strcmp(id, "server") == 0) {
911 err = snd_config_get_string(n, &server);
913 SNDERR("Invalid type for %s", id);
918 if (strcmp(id, "pcm") == 0) {
919 err = snd_config_get_string(n, &pcm_name);
921 SNDERR("Invalid type for %s", id);
926 SNDERR("Unknown field %s", id);
930 SNDERR("pcm is not defined");
934 SNDERR("server is not defined");
937 err = snd_config_search_definition(root, "server", server, &sconfig);
939 SNDERR("Unknown server %s", server);
942 if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
943 SNDERR("Invalid type for server %s definition", server);
946 snd_config_for_each(i, next, sconfig) {
947 snd_config_t *n = snd_config_iterator_entry(i);
949 if (snd_config_get_id(n, &id) < 0)
951 if (strcmp(id, "comment") == 0)
953 if (strcmp(id, "host") == 0) {
954 err = snd_config_get_string(n, &host);
956 SNDERR("Invalid type for %s", id);
961 if (strcmp(id, "socket") == 0) {
962 err = snd_config_get_string(n, &sockname);
964 SNDERR("Invalid type for %s", id);
969 if (strcmp(id, "port") == 0) {
970 err = snd_config_get_integer(n, &port);
972 SNDERR("Invalid type for %s", id);
977 SNDERR("Unknown field %s", id);
984 SNDERR("host is not defined");
988 SNDERR("socket is not defined");
991 h = gethostbyname(host);
993 SNDERR("Cannot resolve %s", host);
996 local = snd_is_local(h);
998 SNDERR("%s is not the local host", host);
1001 err = snd_pcm_shm_open(pcmp, name, sockname, pcm_name, stream, mode);
1003 snd_config_delete(sconfig);
1007 SND_DLSYM_BUILD_VERSION(_snd_pcm_shm_open, SND_PCM_DLSYM_VERSION);