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;
60 static long snd_pcm_shm_action_fd0(snd_pcm_t *pcm, int *fd)
62 snd_pcm_shm_t *shm = pcm->private_data;
65 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
67 err = write(shm->socket, buf, 1);
70 err = snd_receive_fd(shm->socket, buf, 1, fd);
74 SNDERR("Server has not done the cmd");
80 static int snd_pcm_shm_new_rbptr(snd_pcm_t *pcm, snd_pcm_shm_t *shm,
81 snd_pcm_rbptr_t *rbptr, volatile snd_pcm_shm_rbptr_t *shm_rbptr)
83 if (!shm_rbptr->use_mmap) {
84 if (&pcm->hw == rbptr)
85 snd_pcm_set_hw_ptr(pcm, &shm_rbptr->ptr, -1, 0);
87 snd_pcm_set_appl_ptr(pcm, &shm_rbptr->ptr, -1, 0);
90 size_t mmap_size, mmap_offset, offset;
94 shm->ctrl->cmd = &pcm->hw == rbptr ? SND_PCM_IOCTL_HW_PTR_FD : SND_PCM_IOCTL_APPL_PTR_FD;
95 result = snd_pcm_shm_action_fd0(pcm, &fd);
98 mmap_size = page_ptr(shm_rbptr->offset, sizeof(snd_pcm_uframes_t), &offset, &mmap_offset);
99 ptr = mmap(NULL, mmap_size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED, fd, mmap_offset);
100 if (ptr == MAP_FAILED || ptr == NULL) {
101 SYSERR("shm rbptr mmap failed");
104 if (&pcm->hw == rbptr)
105 snd_pcm_set_hw_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset);
107 snd_pcm_set_appl_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset);
112 static long snd_pcm_shm_action(snd_pcm_t *pcm)
114 snd_pcm_shm_t *shm = pcm->private_data;
117 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
119 if (ctrl->hw.changed || ctrl->appl.changed)
121 err = write(shm->socket, buf, 1);
124 err = read(shm->socket, buf, 1);
128 SNDERR("Server has not done the cmd");
131 result = ctrl->result;
132 if (ctrl->hw.changed) {
133 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw);
136 ctrl->hw.changed = 0;
138 if (ctrl->appl.changed) {
139 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl);
142 ctrl->appl.changed = 0;
147 static long snd_pcm_shm_action_fd(snd_pcm_t *pcm, int *fd)
149 snd_pcm_shm_t *shm = pcm->private_data;
152 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
154 if (ctrl->hw.changed || ctrl->appl.changed)
156 err = write(shm->socket, buf, 1);
159 err = snd_receive_fd(shm->socket, buf, 1, fd);
163 SNDERR("Server has not done the cmd");
166 if (ctrl->hw.changed) {
167 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw);
170 ctrl->hw.changed = 0;
172 if (ctrl->appl.changed) {
173 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl);
176 ctrl->appl.changed = 0;
181 static int snd_pcm_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
186 static int snd_pcm_shm_async(snd_pcm_t *pcm, int sig, pid_t pid)
188 snd_pcm_shm_t *shm = pcm->private_data;
189 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
190 ctrl->cmd = SND_PCM_IOCTL_ASYNC;
191 ctrl->u.async.sig = sig;
192 ctrl->u.async.pid = pid;
193 return snd_pcm_shm_action(pcm);
196 static int snd_pcm_shm_info(snd_pcm_t *pcm, snd_pcm_info_t * info)
198 snd_pcm_shm_t *shm = pcm->private_data;
199 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
201 // ctrl->u.info = *info;
202 ctrl->cmd = SNDRV_PCM_IOCTL_INFO;
203 err = snd_pcm_shm_action(pcm);
206 *info = ctrl->u.info;
210 static int snd_pcm_shm_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
215 static int snd_pcm_shm_hw_refine_sprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *sparams)
217 snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
218 _snd_pcm_hw_params_any(sparams);
219 _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
224 static int snd_pcm_shm_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
225 snd_pcm_hw_params_t *sparams)
228 unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
229 const snd_pcm_access_mask_t *access_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
230 if (!snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
231 !snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED)) {
232 err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
237 err = _snd_pcm_hw_params_refine(sparams, links, params);
243 static int snd_pcm_shm_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
244 snd_pcm_hw_params_t *sparams)
247 unsigned int links = ~SND_PCM_HW_PARBIT_ACCESS;
248 snd_pcm_access_mask_t access_mask;
249 snd_mask_copy(&access_mask, snd_pcm_hw_param_get_mask(sparams, SND_PCM_HW_PARAM_ACCESS));
250 snd_pcm_access_mask_set(&access_mask, SND_PCM_ACCESS_RW_INTERLEAVED);
251 snd_pcm_access_mask_set(&access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED);
252 err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
256 err = _snd_pcm_hw_params_refine(params, links, sparams);
262 static int snd_pcm_shm_hw_refine_slave(snd_pcm_t *pcm,
263 snd_pcm_hw_params_t *params)
265 snd_pcm_shm_t *shm = pcm->private_data;
266 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
268 ctrl->u.hw_refine = *params;
269 ctrl->cmd = SNDRV_PCM_IOCTL_HW_REFINE;
270 err = snd_pcm_shm_action(pcm);
271 *params = ctrl->u.hw_refine;
275 static int snd_pcm_shm_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
277 return snd_pcm_hw_refine_slave(pcm, params,
278 snd_pcm_shm_hw_refine_cprepare,
279 snd_pcm_shm_hw_refine_cchange,
280 snd_pcm_shm_hw_refine_sprepare,
281 snd_pcm_shm_hw_refine_schange,
282 snd_pcm_shm_hw_refine_slave);
285 static int snd_pcm_shm_hw_params_slave(snd_pcm_t *pcm,
286 snd_pcm_hw_params_t *params)
288 snd_pcm_shm_t *shm = pcm->private_data;
289 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
291 params->flags |= SND_PCM_HW_PARAMS_EXPORT_BUFFER;
292 ctrl->cmd = SNDRV_PCM_IOCTL_HW_PARAMS;
293 ctrl->u.hw_params = *params;
294 err = snd_pcm_shm_action(pcm);
295 *params = ctrl->u.hw_params;
299 static int snd_pcm_shm_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t * params)
301 return snd_pcm_hw_params_slave(pcm, params,
302 snd_pcm_shm_hw_refine_cchange,
303 snd_pcm_shm_hw_refine_sprepare,
304 snd_pcm_shm_hw_refine_schange,
305 snd_pcm_shm_hw_params_slave);
308 static int snd_pcm_shm_hw_free(snd_pcm_t *pcm)
310 snd_pcm_shm_t *shm = pcm->private_data;
311 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
312 ctrl->cmd = SNDRV_PCM_IOCTL_HW_FREE;
313 return snd_pcm_shm_action(pcm);
316 static int snd_pcm_shm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t * params)
318 snd_pcm_shm_t *shm = pcm->private_data;
319 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
321 ctrl->cmd = SNDRV_PCM_IOCTL_SW_PARAMS;
322 ctrl->u.sw_params = *params;
323 err = snd_pcm_shm_action(pcm);
324 *params = ctrl->u.sw_params;
330 static int snd_pcm_shm_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
335 static int snd_pcm_shm_munmap(snd_pcm_t *pcm)
338 for (c = 0; c < pcm->channels; ++c) {
339 snd_pcm_channel_info_t *i = &pcm->mmap_channels[c];
342 if (i->type != SND_PCM_AREA_MMAP)
344 if (i->u.mmap.fd < 0)
346 for (c1 = c + 1; c1 < pcm->channels; ++c1) {
347 snd_pcm_channel_info_t *i1 = &pcm->mmap_channels[c1];
348 if (i1->type != SND_PCM_AREA_MMAP)
350 if (i1->u.mmap.fd != i->u.mmap.fd)
354 err = close(i->u.mmap.fd);
356 SYSERR("close failed");
363 static int snd_pcm_shm_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t * info)
365 snd_pcm_shm_t *shm = pcm->private_data;
366 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
369 ctrl->cmd = SNDRV_PCM_IOCTL_CHANNEL_INFO;
370 ctrl->u.channel_info = *info;
371 err = snd_pcm_shm_action_fd(pcm, &fd);
374 *info = ctrl->u.channel_info;
376 switch (info->type) {
377 case SND_PCM_AREA_MMAP:
378 info->u.mmap.fd = fd;
380 case SND_PCM_AREA_SHM:
389 static int snd_pcm_shm_status(snd_pcm_t *pcm, snd_pcm_status_t * status)
391 snd_pcm_shm_t *shm = pcm->private_data;
392 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
394 ctrl->cmd = SNDRV_PCM_IOCTL_STATUS;
395 // ctrl->u.status = *status;
396 err = snd_pcm_shm_action(pcm);
399 *status = ctrl->u.status;
403 static snd_pcm_state_t snd_pcm_shm_state(snd_pcm_t *pcm)
405 snd_pcm_shm_t *shm = pcm->private_data;
406 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
407 ctrl->cmd = SND_PCM_IOCTL_STATE;
408 return snd_pcm_shm_action(pcm);
411 static int snd_pcm_shm_hwsync(snd_pcm_t *pcm)
413 snd_pcm_shm_t *shm = pcm->private_data;
414 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
415 ctrl->cmd = SND_PCM_IOCTL_HWSYNC;
416 return snd_pcm_shm_action(pcm);
419 static int snd_pcm_shm_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
421 snd_pcm_shm_t *shm = pcm->private_data;
422 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
424 ctrl->cmd = SNDRV_PCM_IOCTL_DELAY;
425 err = snd_pcm_shm_action(pcm);
428 *delayp = ctrl->u.delay.frames;
432 static snd_pcm_sframes_t snd_pcm_shm_avail_update(snd_pcm_t *pcm)
434 snd_pcm_shm_t *shm = pcm->private_data;
435 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
437 ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE;
438 err = snd_pcm_shm_action(pcm);
444 static int snd_pcm_shm_htimestamp(snd_pcm_t *pcm ATTRIBUTE_UNUSED,
445 snd_pcm_uframes_t *avail ATTRIBUTE_UNUSED,
446 snd_htimestamp_t *tstamp ATTRIBUTE_UNUSED)
448 return -EIO; /* not implemented yet */
451 static int snd_pcm_shm_prepare(snd_pcm_t *pcm)
453 snd_pcm_shm_t *shm = pcm->private_data;
454 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
455 ctrl->cmd = SNDRV_PCM_IOCTL_PREPARE;
456 return snd_pcm_shm_action(pcm);
459 static int snd_pcm_shm_reset(snd_pcm_t *pcm)
461 snd_pcm_shm_t *shm = pcm->private_data;
462 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
463 ctrl->cmd = SNDRV_PCM_IOCTL_RESET;
464 return snd_pcm_shm_action(pcm);
467 static int snd_pcm_shm_start(snd_pcm_t *pcm)
469 snd_pcm_shm_t *shm = pcm->private_data;
470 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
471 ctrl->cmd = SNDRV_PCM_IOCTL_START;
472 return snd_pcm_shm_action(pcm);
475 static int snd_pcm_shm_drop(snd_pcm_t *pcm)
477 snd_pcm_shm_t *shm = pcm->private_data;
478 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
479 ctrl->cmd = SNDRV_PCM_IOCTL_DROP;
480 return snd_pcm_shm_action(pcm);
483 static int snd_pcm_shm_drain(snd_pcm_t *pcm)
485 snd_pcm_shm_t *shm = pcm->private_data;
486 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
489 ctrl->cmd = SNDRV_PCM_IOCTL_DRAIN;
490 err = snd_pcm_shm_action(pcm);
497 if (!(pcm->mode & SND_PCM_NONBLOCK))
498 snd_pcm_wait(pcm, -1);
502 static int snd_pcm_shm_pause(snd_pcm_t *pcm, int enable)
504 snd_pcm_shm_t *shm = pcm->private_data;
505 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
506 ctrl->cmd = SNDRV_PCM_IOCTL_PAUSE;
507 ctrl->u.pause.enable = enable;
508 return snd_pcm_shm_action(pcm);
511 static snd_pcm_sframes_t snd_pcm_shm_rewindable(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
513 return 0; /* FIX ME */
516 static snd_pcm_sframes_t snd_pcm_shm_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
518 snd_pcm_shm_t *shm = pcm->private_data;
519 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
520 ctrl->cmd = SNDRV_PCM_IOCTL_REWIND;
521 ctrl->u.rewind.frames = frames;
522 return snd_pcm_shm_action(pcm);
525 static snd_pcm_sframes_t snd_pcm_shm_forwardable(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
527 return 0; /* FIX ME */
530 static snd_pcm_sframes_t snd_pcm_shm_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
532 snd_pcm_shm_t *shm = pcm->private_data;
533 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
534 ctrl->cmd = SND_PCM_IOCTL_FORWARD;
535 ctrl->u.forward.frames = frames;
536 return snd_pcm_shm_action(pcm);
539 static int snd_pcm_shm_resume(snd_pcm_t *pcm)
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_RESUME;
544 return snd_pcm_shm_action(pcm);
547 static snd_pcm_sframes_t snd_pcm_shm_mmap_commit(snd_pcm_t *pcm,
548 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
549 snd_pcm_uframes_t size)
551 snd_pcm_shm_t *shm = pcm->private_data;
552 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
553 ctrl->cmd = SND_PCM_IOCTL_MMAP_COMMIT;
554 ctrl->u.mmap_commit.offset = offset;
555 ctrl->u.mmap_commit.frames = size;
556 return snd_pcm_shm_action(pcm);
559 static int snd_pcm_shm_poll_descriptor(snd_pcm_t *pcm)
561 snd_pcm_shm_t *shm = pcm->private_data;
562 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
564 ctrl->cmd = SND_PCM_IOCTL_POLL_DESCRIPTOR;
565 err = snd_pcm_shm_action_fd(pcm, &fd);
571 static int snd_pcm_shm_close(snd_pcm_t *pcm)
573 snd_pcm_shm_t *shm = pcm->private_data;
574 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
576 ctrl->cmd = SND_PCM_IOCTL_CLOSE;
577 result = snd_pcm_shm_action(pcm);
585 static void snd_pcm_shm_dump(snd_pcm_t *pcm, snd_output_t *out)
587 snd_output_printf(out, "Shm PCM\n");
589 snd_output_printf(out, "Its setup is:\n");
590 snd_pcm_dump_setup(pcm, out);
594 static const snd_pcm_ops_t snd_pcm_shm_ops = {
595 .close = snd_pcm_shm_close,
596 .info = snd_pcm_shm_info,
597 .hw_refine = snd_pcm_shm_hw_refine,
598 .hw_params = snd_pcm_shm_hw_params,
599 .hw_free = snd_pcm_shm_hw_free,
600 .sw_params = snd_pcm_shm_sw_params,
601 .channel_info = snd_pcm_shm_channel_info,
602 .dump = snd_pcm_shm_dump,
603 .nonblock = snd_pcm_shm_nonblock,
604 .async = snd_pcm_shm_async,
605 .mmap = snd_pcm_shm_mmap,
606 .munmap = snd_pcm_shm_munmap,
609 static const snd_pcm_fast_ops_t snd_pcm_shm_fast_ops = {
610 .status = snd_pcm_shm_status,
611 .state = snd_pcm_shm_state,
612 .hwsync = snd_pcm_shm_hwsync,
613 .delay = snd_pcm_shm_delay,
614 .prepare = snd_pcm_shm_prepare,
615 .reset = snd_pcm_shm_reset,
616 .start = snd_pcm_shm_start,
617 .drop = snd_pcm_shm_drop,
618 .drain = snd_pcm_shm_drain,
619 .pause = snd_pcm_shm_pause,
620 .rewindable = snd_pcm_shm_rewindable,
621 .rewind = snd_pcm_shm_rewind,
622 .forwardable = snd_pcm_shm_forwardable,
623 .forward = snd_pcm_shm_forward,
624 .resume = snd_pcm_shm_resume,
625 .writei = snd_pcm_mmap_writei,
626 .writen = snd_pcm_mmap_writen,
627 .readi = snd_pcm_mmap_readi,
628 .readn = snd_pcm_mmap_readn,
629 .avail_update = snd_pcm_shm_avail_update,
630 .mmap_commit = snd_pcm_shm_mmap_commit,
631 .htimestamp = snd_pcm_shm_htimestamp,
634 static int make_local_socket(const char *filename)
636 size_t l = strlen(filename);
637 size_t size = offsetof(struct sockaddr_un, sun_path) + l;
638 struct sockaddr_un *addr = alloca(size);
641 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
643 SYSERR("socket failed");
647 addr->sun_family = AF_LOCAL;
648 memcpy(addr->sun_path, filename, l);
650 if (connect(sock, (struct sockaddr *) addr, size) < 0) {
651 SYSERR("connect failed");
658 static int make_inet_socket(const char *host, int port)
660 struct sockaddr_in addr;
662 struct hostent *h = gethostbyname(host);
666 sock = socket(PF_INET, SOCK_STREAM, 0);
668 SYSERR("socket failed");
672 addr.sin_family = AF_INET;
673 addr.sin_port = htons(port);
674 memcpy(&addr.sin_addr, h->h_addr_list[0], sizeof(struct in_addr));
676 if (connect(sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
677 SYSERR("connect failed");
685 * \brief Creates a new shared memory PCM
686 * \param pcmp Returns created PCM handle
687 * \param name Name of PCM
688 * \param sockname Unix socket name
689 * \param sname Server name
690 * \param stream PCM Stream
691 * \param mode PCM Mode
692 * \retval zero on success otherwise a negative error code
693 * \warning Using of this function might be dangerous in the sense
694 * of compatibility reasons. The prototype might be freely
697 int snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
698 const char *sockname, const char *sname,
699 snd_pcm_stream_t stream, int mode)
702 snd_pcm_shm_t *shm = NULL;
703 snd_client_open_request_t *req;
704 snd_client_open_answer_t ans;
705 size_t snamelen, reqlen;
708 snd_pcm_shm_ctrl_t *ctrl = NULL;
710 snamelen = strlen(sname);
714 result = make_local_socket(sockname);
716 SNDERR("server for socket %s is not running", sockname);
721 reqlen = sizeof(*req) + snamelen;
722 req = alloca(reqlen);
723 memcpy(req->name, sname, snamelen);
724 req->dev_type = SND_DEV_TYPE_PCM;
725 req->transport_type = SND_TRANSPORT_TYPE_SHM;
726 req->stream = stream;
728 req->namelen = snamelen;
729 err = write(sock, req, reqlen);
731 SYSERR("write error");
735 if ((size_t) err != reqlen) {
736 SNDERR("write size error");
740 err = read(sock, &ans, sizeof(ans));
742 SYSERR("read error");
746 if (err != sizeof(ans)) {
747 SNDERR("read size error");
755 ctrl = shmat(ans.cookie, 0, 0);
757 SYSERR("shmat error");
762 shm = calloc(1, sizeof(snd_pcm_shm_t));
771 err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHM, name, stream, mode);
777 pcm->ops = &snd_pcm_shm_ops;
778 pcm->fast_ops = &snd_pcm_shm_fast_ops;
779 pcm->private_data = shm;
780 err = snd_pcm_shm_poll_descriptor(pcm);
786 pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
787 snd_pcm_set_hw_ptr(pcm, &ctrl->hw.ptr, -1, 0);
788 snd_pcm_set_appl_ptr(pcm, &ctrl->appl.ptr, -1, 0);
800 /*! \page pcm_plugins
802 \section pcm_plugins_shm Plugin: shm
804 This plugin communicates with aserver via shared memory. It is a raw
805 communication without any conversions, but it can be expected worse
810 type shm # Shared memory PCM
811 server STR # Server name
816 \subsection pcm_plugins_shm_funcref Function reference
819 <LI>snd_pcm_shm_open()
820 <LI>_snd_pcm_shm_open()
826 * \brief Creates a new shm PCM
827 * \param pcmp Returns created PCM handle
828 * \param name Name of PCM
829 * \param root Root configuration node
830 * \param conf Configuration node with hw PCM description
831 * \param stream PCM Stream
832 * \param mode PCM Mode
833 * \warning Using of this function might be dangerous in the sense
834 * of compatibility reasons. The prototype might be freely
837 int _snd_pcm_shm_open(snd_pcm_t **pcmp, const char *name,
838 snd_config_t *root, snd_config_t *conf,
839 snd_pcm_stream_t stream, int mode)
841 snd_config_iterator_t i, next;
842 const char *server = NULL;
843 const char *pcm_name = NULL;
844 snd_config_t *sconfig;
845 const char *host = NULL;
846 const char *sockname = NULL;
851 snd_config_for_each(i, next, conf) {
852 snd_config_t *n = snd_config_iterator_entry(i);
854 if (snd_config_get_id(n, &id) < 0)
856 if (snd_pcm_conf_generic_id(id))
858 if (strcmp(id, "server") == 0) {
859 err = snd_config_get_string(n, &server);
861 SNDERR("Invalid type for %s", id);
866 if (strcmp(id, "pcm") == 0) {
867 err = snd_config_get_string(n, &pcm_name);
869 SNDERR("Invalid type for %s", id);
874 SNDERR("Unknown field %s", id);
878 SNDERR("pcm is not defined");
882 SNDERR("server is not defined");
885 err = snd_config_search_definition(root, "server", server, &sconfig);
887 SNDERR("Unknown server %s", server);
890 if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
891 SNDERR("Invalid type for server %s definition", server);
894 snd_config_for_each(i, next, sconfig) {
895 snd_config_t *n = snd_config_iterator_entry(i);
897 if (snd_config_get_id(n, &id) < 0)
899 if (strcmp(id, "comment") == 0)
901 if (strcmp(id, "host") == 0) {
902 err = snd_config_get_string(n, &host);
904 SNDERR("Invalid type for %s", id);
909 if (strcmp(id, "socket") == 0) {
910 err = snd_config_get_string(n, &sockname);
912 SNDERR("Invalid type for %s", id);
917 if (strcmp(id, "port") == 0) {
918 err = snd_config_get_integer(n, &port);
920 SNDERR("Invalid type for %s", id);
925 SNDERR("Unknown field %s", id);
932 SNDERR("host is not defined");
936 SNDERR("socket is not defined");
939 h = gethostbyname(host);
941 SNDERR("Cannot resolve %s", host);
944 local = snd_is_local(h);
946 SNDERR("%s is not the local host", host);
949 err = snd_pcm_shm_open(pcmp, name, sockname, pcm_name, stream, mode);
951 snd_config_delete(sconfig);
955 SND_DLSYM_BUILD_VERSION(_snd_pcm_shm_open, SND_PCM_DLSYM_VERSION);