• Home
  • History
  • Annotate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/iserver/alsa-lib-1.0.26/src/pcm/

Lines Matching defs:*

2  * \file pcm/pcm_shm.c
3 * \ingroup PCM_Plugins
4 * \brief PCM Shared Memory Plugin Interface
5 * \author Abramo Bagnara <abramo@alsa-project.org>
6 * \date 2000-2001
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
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <stddef.h>
32 #include <limits.h>
33 #include <unistd.h>
34 #include <string.h>
35 #include <fcntl.h>
36 #include <sys/ioctl.h>
37 #include <sys/shm.h>
38 #include <sys/socket.h>
39 #include <sys/poll.h>
40 #include <sys/un.h>
41 #include <sys/mman.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44 #include <net/if.h>
45 #include <netdb.h>
46 #include "aserver.h"
48 #ifndef PIC
49 /* entry for static linking */
50 const char *_snd_module_pcm_shm = "";
51 #endif
53 #ifndef DOC_HIDDEN
54 typedef struct {
55 int socket;
56 volatile snd_pcm_shm_ctrl_t *ctrl;
57 } snd_pcm_shm_t;
58 #endif
60 static long snd_pcm_shm_action_fd0(snd_pcm_t *pcm, int *fd)
62 snd_pcm_shm_t *shm = pcm->private_data;
63 int err;
64 char buf[1];
65 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
67 err = write(shm->socket, buf, 1);
68 if (err != 1)
69 return -EBADFD;
70 err = snd_receive_fd(shm->socket, buf, 1, fd);
71 if (err != 1)
72 return -EBADFD;
73 if (ctrl->cmd) {
74 SNDERR("Server has not done the cmd");
75 return -EBADFD;
77 return ctrl->result;
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);
86 else
87 snd_pcm_set_appl_ptr(pcm, &shm_rbptr->ptr, -1, 0);
88 } else {
89 void *ptr;
90 size_t mmap_size, mmap_offset, offset;
91 int fd;
92 long result;
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);
96 if (result < 0)
97 return result;
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");
102 return -errno;
104 if (&pcm->hw == rbptr)
105 snd_pcm_set_hw_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset);
106 else
107 snd_pcm_set_appl_ptr(pcm, (snd_pcm_uframes_t *)((char *)ptr + offset), fd, shm_rbptr->offset);
109 return 0;
112 static long snd_pcm_shm_action(snd_pcm_t *pcm)
114 snd_pcm_shm_t *shm = pcm->private_data;
115 int err, result;
116 char buf[1];
117 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
119 if (ctrl->hw.changed || ctrl->appl.changed)
120 return -EBADFD;
121 err = write(shm->socket, buf, 1);
122 if (err != 1)
123 return -EBADFD;
124 err = read(shm->socket, buf, 1);
125 if (err != 1)
126 return -EBADFD;
127 if (ctrl->cmd) {
128 SNDERR("Server has not done the cmd");
129 return -EBADFD;
131 result = ctrl->result;
132 if (ctrl->hw.changed) {
133 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw);
134 if (err < 0)
135 return err;
136 ctrl->hw.changed = 0;
138 if (ctrl->appl.changed) {
139 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl);
140 if (err < 0)
141 return err;
142 ctrl->appl.changed = 0;
144 return result;
147 static long snd_pcm_shm_action_fd(snd_pcm_t *pcm, int *fd)
149 snd_pcm_shm_t *shm = pcm->private_data;
150 int err;
151 char buf[1];
152 volatile snd_pcm_shm_ctrl_t *ctrl = shm->ctrl;
154 if (ctrl->hw.changed || ctrl->appl.changed)
155 return -EBADFD;
156 err = write(shm->socket, buf, 1);
157 if (err != 1)
158 return -EBADFD;
159 err = snd_receive_fd(shm->socket, buf, 1, fd);
160 if (err != 1)
161 return -EBADFD;
162 if (ctrl->cmd) {
163 SNDERR("Server has not done the cmd");
164 return -EBADFD;
166 if (ctrl->hw.changed) {
167 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->hw, &ctrl->hw);
168 if (err < 0)
169 return err;
170 ctrl->hw.changed = 0;
172 if (ctrl->appl.changed) {
173 err = snd_pcm_shm_new_rbptr(pcm, shm, &pcm->appl, &ctrl->appl);
174 if (err < 0)
175 return err;
176 ctrl->appl.changed = 0;
178 return ctrl->result;
181 static int snd_pcm_shm_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
183 return 0;
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;
200 int err;
201 // ctrl->u.info = *info;
202 ctrl->cmd = SNDRV_PCM_IOCTL_INFO;
203 err = snd_pcm_shm_action(pcm);
204 if (err < 0)
205 return err;
206 *info = ctrl->u.info;
207 return err;
210 static int snd_pcm_shm_hw_refine_cprepare(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params ATTRIBUTE_UNUSED)
212 return 0;
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,
220 &saccess_mask);
221 return 0;
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)
227 int err;
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,
233 access_mask);
234 if (err < 0)
235 return err;
237 err = _snd_pcm_hw_params_refine(sparams, links, params);
238 if (err < 0)
239 return err;
240 return 0;
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)
246 int err;
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,
253 &access_mask);
254 if (err < 0)
255 return err;
256 err = _snd_pcm_hw_params_refine(params, links, sparams);
257 if (err < 0)
258 return err;
259 return 0;
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;
267 int err;
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;
272 return err;
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;
290 int err;
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;
296 return err;
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;
320 int err;
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;
325 if (err < 0)
326 return err;
327 return err;
330 static int snd_pcm_shm_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
332 return 0;
335 static int snd_pcm_shm_munmap(snd_pcm_t *pcm)
337 unsigned int c;
338 for (c = 0; c < pcm->channels; ++c) {
339 snd_pcm_channel_info_t *i = &pcm->mmap_channels[c];
340 unsigned int c1;
341 int err;
342 if (i->type != SND_PCM_AREA_MMAP)
343 continue;
344 if (i->u.mmap.fd < 0)
345 continue;
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)
349 continue;
350 if (i1->u.mmap.fd != i->u.mmap.fd)
351 continue;
352 i1->u.mmap.fd = -1;
354 err = close(i->u.mmap.fd);
355 if (err < 0) {
356 SYSERR("close failed");
357 return -errno;
360 return 0;
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;
367 int err;
368 int fd;
369 ctrl->cmd = SNDRV_PCM_IOCTL_CHANNEL_INFO;
370 ctrl->u.channel_info = *info;
371 err = snd_pcm_shm_action_fd(pcm, &fd);
372 if (err < 0)
373 return err;
374 *info = ctrl->u.channel_info;
375 info->addr = 0;
376 switch (info->type) {
377 case SND_PCM_AREA_MMAP:
378 info->u.mmap.fd = fd;
379 break;
380 case SND_PCM_AREA_SHM:
381 break;
382 default:
383 assert(0);
384 break;
386 return err;
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;
393 int err;
394 ctrl->cmd = SNDRV_PCM_IOCTL_STATUS;
395 // ctrl->u.status = *status;
396 err = snd_pcm_shm_action(pcm);
397 if (err < 0)
398 return err;
399 *status = ctrl->u.status;
400 return err;
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;
423 int err;
424 ctrl->cmd = SNDRV_PCM_IOCTL_DELAY;
425 err = snd_pcm_shm_action(pcm);
426 if (err < 0)
427 return err;
428 *delayp = ctrl->u.delay.frames;
429 return err;
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;
436 int err;
437 ctrl->cmd = SND_PCM_IOCTL_AVAIL_UPDATE;
438 err = snd_pcm_shm_action(pcm);
439 if (err < 0)
440 return err;
441 return err;
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;
487 int err;
488 do {
489 ctrl->cmd = SNDRV_PCM_IOCTL_DRAIN;
490 err = snd_pcm_shm_action(pcm);
491 if (err != -EAGAIN)
492 break;
493 usleep(10000);
494 } while (1);
495 if (err < 0)
496 return err;
497 if (!(pcm->mode & SND_PCM_NONBLOCK))
498 snd_pcm_wait(pcm, -1);
499 return err;
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;
563 int fd, err;
564 ctrl->cmd = SND_PCM_IOCTL_POLL_DESCRIPTOR;
565 err = snd_pcm_shm_action_fd(pcm, &fd);
566 if (err < 0)
567 return err;
568 return 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;
575 int result;
576 ctrl->cmd = SND_PCM_IOCTL_CLOSE;
577 result = snd_pcm_shm_action(pcm);
578 shmdt((void *)ctrl);
579 close(shm->socket);
580 close(pcm->poll_fd);
581 free(shm);
582 return result;
585 static void snd_pcm_shm_dump(snd_pcm_t *pcm, snd_output_t *out)
587 snd_output_printf(out, "Shm PCM\n");
588 if (pcm->setup) {
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);
639 int sock;
641 sock = socket(PF_LOCAL, SOCK_STREAM, 0);
642 if (sock < 0) {
643 SYSERR("socket failed");
644 return -errno;
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");
652 return -errno;
654 return sock;
657 #if 0
658 static int make_inet_socket(const char *host, int port)
660 struct sockaddr_in addr;
661 int sock;
662 struct hostent *h = gethostbyname(host);
663 if (!h)
664 return -ENOENT;
666 sock = socket(PF_INET, SOCK_STREAM, 0);
667 if (sock < 0) {
668 SYSERR("socket failed");
669 return -errno;
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");
678 return -errno;
680 return sock;
682 #endif
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
695 * changed in future.
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)
701 snd_pcm_t *pcm;
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;
706 int err;
707 int result;
708 snd_pcm_shm_ctrl_t *ctrl = NULL;
709 int sock = -1;
710 snamelen = strlen(sname);
711 if (snamelen > 255)
712 return -EINVAL;
714 result = make_local_socket(sockname);
715 if (result < 0) {
716 SNDERR("server for socket %s is not running", sockname);
717 goto _err;
719 sock = result;
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;
727 req->mode = mode;
728 req->namelen = snamelen;
729 err = write(sock, req, reqlen);
730 if (err < 0) {
731 SYSERR("write error");
732 result = -errno;
733 goto _err;
735 if ((size_t) err != reqlen) {
736 SNDERR("write size error");
737 result = -EINVAL;
738 goto _err;
740 err = read(sock, &ans, sizeof(ans));
741 if (err < 0) {
742 SYSERR("read error");
743 result = -errno;
744 goto _err;
746 if (err != sizeof(ans)) {
747 SNDERR("read size error");
748 result = -EINVAL;
749 goto _err;
751 result = ans.result;
752 if (result < 0)
753 goto _err;
755 ctrl = shmat(ans.cookie, 0, 0);
756 if (!ctrl) {
757 SYSERR("shmat error");
758 result = -errno;
759 goto _err;
762 shm = calloc(1, sizeof(snd_pcm_shm_t));
763 if (!shm) {
764 result = -ENOMEM;
765 goto _err;
768 shm->socket = sock;
769 shm->ctrl = ctrl;
771 err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHM, name, stream, mode);
772 if (err < 0) {
773 result = err;
774 goto _err;
776 pcm->mmap_rw = 1;
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);
781 if (err < 0) {
782 snd_pcm_close(pcm);
783 return err;
785 pcm->poll_fd = err;
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);
789 *pcmp = pcm;
790 return 0;
792 _err:
793 close(sock);
794 if (ctrl)
795 shmdt(ctrl);
796 free(shm);
797 return result;
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
806 performance.
808 \code
809 pcm.name {
810 type shm # Shared memory PCM
811 server STR # Server name
812 pcm STR # PCM name
814 \endcode
816 \subsection pcm_plugins_shm_funcref Function reference
818 <UL>
819 <LI>snd_pcm_shm_open()
820 <LI>_snd_pcm_shm_open()
821 </UL>
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
835 * changed in future.
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;
847 long port = -1;
848 int err;
849 int local;
850 struct hostent *h;
851 snd_config_for_each(i, next, conf) {
852 snd_config_t *n = snd_config_iterator_entry(i);
853 const char *id;
854 if (snd_config_get_id(n, &id) < 0)
855 continue;
856 if (snd_pcm_conf_generic_id(id))
857 continue;
858 if (strcmp(id, "server") == 0) {
859 err = snd_config_get_string(n, &server);
860 if (err < 0) {
861 SNDERR("Invalid type for %s", id);
862 return -EINVAL;
864 continue;
866 if (strcmp(id, "pcm") == 0) {
867 err = snd_config_get_string(n, &pcm_name);
868 if (err < 0) {
869 SNDERR("Invalid type for %s", id);
870 return -EINVAL;
872 continue;
874 SNDERR("Unknown field %s", id);
875 return -EINVAL;
877 if (!pcm_name) {
878 SNDERR("pcm is not defined");
879 return -EINVAL;
881 if (!server) {
882 SNDERR("server is not defined");
883 return -EINVAL;
885 err = snd_config_search_definition(root, "server", server, &sconfig);
886 if (err < 0) {
887 SNDERR("Unknown server %s", server);
888 return -EINVAL;
890 if (snd_config_get_type(sconfig) != SND_CONFIG_TYPE_COMPOUND) {
891 SNDERR("Invalid type for server %s definition", server);
892 goto _err;
894 snd_config_for_each(i, next, sconfig) {
895 snd_config_t *n = snd_config_iterator_entry(i);
896 const char *id;
897 if (snd_config_get_id(n, &id) < 0)
898 continue;
899 if (strcmp(id, "comment") == 0)
900 continue;
901 if (strcmp(id, "host") == 0) {
902 err = snd_config_get_string(n, &host);
903 if (err < 0) {
904 SNDERR("Invalid type for %s", id);
905 goto _err;
907 continue;
909 if (strcmp(id, "socket") == 0) {
910 err = snd_config_get_string(n, &sockname);
911 if (err < 0) {
912 SNDERR("Invalid type for %s", id);
913 goto _err;
915 continue;
917 if (strcmp(id, "port") == 0) {
918 err = snd_config_get_integer(n, &port);
919 if (err < 0) {
920 SNDERR("Invalid type for %s", id);
921 goto _err;
923 continue;
925 SNDERR("Unknown field %s", id);
926 _err:
927 err = -EINVAL;
928 goto __error;
931 if (!host) {
932 SNDERR("host is not defined");
933 goto _err;
935 if (!sockname) {
936 SNDERR("socket is not defined");
937 goto _err;
939 h = gethostbyname(host);
940 if (!h) {
941 SNDERR("Cannot resolve %s", host);
942 goto _err;
944 local = snd_is_local(h);
945 if (!local) {
946 SNDERR("%s is not the local host", host);
947 goto _err;
949 err = snd_pcm_shm_open(pcmp, name, sockname, pcm_name, stream, mode);
950 __error:
951 snd_config_delete(sconfig);
952 return err;
954 #ifndef DOC_HIDDEN
955 SND_DLSYM_BUILD_VERSION(_snd_pcm_shm_open, SND_PCM_DLSYM_VERSION);
956 #endif