2 * \file pcm/pcm_share.c
4 * \brief PCM Share Plugin Interface
5 * \author Abramo Bagnara <abramo@alsa-project.org>
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/socket.h>
40 #include "pcm_local.h"
43 /* entry for static linking */
44 const char *_snd_module_pcm_share = "";
49 static LIST_HEAD(snd_pcm_share_slaves);
50 static pthread_mutex_t snd_pcm_share_slaves_mutex = PTHREAD_MUTEX_INITIALIZER;
53 #define Pthread_mutex_lock(mutex) \
54 char *snd_pcm_share_slaves_mutex_holder;
56 int err = pthread_mutex_trylock(mutex); \
58 fprintf(stderr, "lock " #mutex " is busy (%s): waiting in " __FUNCTION__ "\n", *(mutex##_holder)); \
59 pthread_mutex_lock(mutex); \
60 fprintf(stderr, "... got\n"); \
62 *(mutex##_holder) = __FUNCTION__; \
65 #define Pthread_mutex_unlock(mutex) \
67 *(mutex##_holder) = 0; \
68 pthread_mutex_unlock(mutex); \
71 #define Pthread_mutex_lock(mutex) pthread_mutex_lock(mutex)
72 #define Pthread_mutex_unlock(mutex) pthread_mutex_unlock(mutex)
76 struct list_head clients;
77 struct list_head list;
79 snd_pcm_format_t format;
81 unsigned int channels;
82 snd_pcm_sframes_t period_time;
83 snd_pcm_sframes_t buffer_time;
84 unsigned int open_count;
85 unsigned int setup_count;
86 unsigned int prepared_count;
87 unsigned int running_count;
88 snd_pcm_uframes_t safety_threshold;
89 snd_pcm_uframes_t silence_frames;
90 snd_pcm_sw_params_t sw_params;
91 snd_pcm_uframes_t hw_ptr;
95 pthread_mutex_t mutex;
99 pthread_cond_t poll_cond;
100 } snd_pcm_share_slave_t;
103 struct list_head list;
105 snd_pcm_share_slave_t *slave;
106 unsigned int channels;
107 unsigned int *slave_channels;
109 snd_htimestamp_t trigger_tstamp;
110 snd_pcm_state_t state;
111 snd_pcm_uframes_t hw_ptr;
112 snd_pcm_uframes_t appl_ptr;
118 #endif /* DOC_HIDDEN */
120 static void _snd_pcm_share_stop(snd_pcm_t *pcm, snd_pcm_state_t state);
122 static snd_pcm_uframes_t snd_pcm_share_slave_avail(snd_pcm_share_slave_t *slave)
124 snd_pcm_sframes_t avail;
125 snd_pcm_t *pcm = slave->pcm;
126 avail = slave->hw_ptr - *pcm->appl.ptr;
127 if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
128 avail += pcm->buffer_size;
130 avail += pcm->boundary;
134 /* Warning: take the mutex before to call this */
135 /* Return number of frames to mmap_commit the slave */
136 static snd_pcm_uframes_t _snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
139 snd_pcm_uframes_t buffer_size, boundary;
140 snd_pcm_uframes_t slave_appl_ptr;
141 snd_pcm_sframes_t frames, safety_frames;
142 snd_pcm_sframes_t min_frames, max_frames;
143 snd_pcm_uframes_t avail, slave_avail;
144 snd_pcm_uframes_t slave_hw_avail;
145 slave_avail = snd_pcm_share_slave_avail(slave);
146 boundary = slave->pcm->boundary;
147 buffer_size = slave->pcm->buffer_size;
148 min_frames = slave_avail;
150 slave_appl_ptr = *slave->pcm->appl.ptr;
151 list_for_each(i, &slave->clients) {
152 snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
153 snd_pcm_t *pcm = share->pcm;
154 switch (share->state) {
155 case SND_PCM_STATE_RUNNING:
157 case SND_PCM_STATE_DRAINING:
158 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
164 avail = snd_pcm_mmap_avail(pcm);
165 frames = slave_avail - avail;
166 if (frames > max_frames)
168 if (share->state != SND_PCM_STATE_RUNNING)
170 if (frames < min_frames)
176 /* Slave xrun prevention */
177 slave_hw_avail = buffer_size - slave_avail;
178 safety_frames = slave->safety_threshold - slave_hw_avail;
179 if (safety_frames > 0 &&
180 frames < safety_frames) {
181 /* Avoid to pass over the last */
182 if (max_frames < safety_frames)
185 frames = safety_frames;
197 - return distance in frames to next event
199 static snd_pcm_uframes_t _snd_pcm_share_missing(snd_pcm_t *pcm)
201 snd_pcm_share_t *share = pcm->private_data;
202 snd_pcm_share_slave_t *slave = share->slave;
203 snd_pcm_t *spcm = slave->pcm;
204 snd_pcm_uframes_t buffer_size = spcm->buffer_size;
205 int ready = 1, running = 0;
206 snd_pcm_uframes_t avail = 0, slave_avail;
207 snd_pcm_sframes_t hw_avail;
208 snd_pcm_uframes_t missing = INT_MAX;
209 snd_pcm_sframes_t ready_missing;
210 // printf("state=%s hw_ptr=%ld appl_ptr=%ld slave appl_ptr=%ld safety=%ld silence=%ld\n", snd_pcm_state_name(share->state), slave->hw_ptr, share->appl_ptr, *slave->pcm->appl_ptr, slave->safety_threshold, slave->silence_frames);
211 switch (share->state) {
212 case SND_PCM_STATE_RUNNING:
214 case SND_PCM_STATE_DRAINING:
215 if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
221 share->hw_ptr = slave->hw_ptr;
222 avail = snd_pcm_mmap_avail(pcm);
223 if (avail >= pcm->stop_threshold) {
224 _snd_pcm_share_stop(pcm, share->state == SND_PCM_STATE_DRAINING ? SND_PCM_STATE_SETUP : SND_PCM_STATE_XRUN);
227 hw_avail = buffer_size - avail;
228 slave_avail = snd_pcm_share_slave_avail(slave);
229 if (avail < slave_avail) {
230 /* Some frames need still to be transferred */
231 snd_pcm_sframes_t slave_hw_avail = buffer_size - slave_avail;
232 snd_pcm_sframes_t safety_missing = slave_hw_avail - slave->safety_threshold;
233 if (safety_missing < 0) {
234 snd_pcm_sframes_t err;
235 snd_pcm_sframes_t frames = slave_avail - avail;
236 if (-safety_missing <= frames) {
237 frames = -safety_missing;
240 err = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), frames);
242 SYSMSG("snd_pcm_mmap_commit error");
246 SYSMSG("commit returns %ld for size %ld", err, frames);
249 if (safety_missing == 0)
252 missing = safety_missing;
255 switch (share->state) {
256 case SND_PCM_STATE_DRAINING:
257 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
259 _snd_pcm_share_stop(pcm, SND_PCM_STATE_SETUP);
262 if ((snd_pcm_uframes_t)hw_avail < missing)
268 case SND_PCM_STATE_RUNNING:
269 if (avail >= pcm->stop_threshold) {
270 _snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
273 snd_pcm_uframes_t xrun_missing = pcm->stop_threshold - avail;
274 if (missing > xrun_missing)
275 missing = xrun_missing;
277 ready_missing = pcm->avail_min - avail;
278 if (ready_missing > 0) {
280 if (missing > (snd_pcm_uframes_t)ready_missing)
281 missing = ready_missing;
286 SNDERR("invalid shared PCM state %d", share->state);
291 if (ready != share->ready) {
293 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
295 read(share->slave_socket, buf, 1);
297 write(share->client_socket, buf, 1);
300 write(share->slave_socket, buf, 1);
302 read(share->client_socket, buf, 1);
304 share->ready = ready;
308 if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
309 share->state == SND_PCM_STATE_DRAINING &&
310 !share->drain_silenced) {
311 /* drain silencing */
312 if (avail >= slave->silence_frames) {
313 snd_pcm_uframes_t offset = share->appl_ptr % buffer_size;
314 snd_pcm_uframes_t xfer = 0;
315 snd_pcm_uframes_t size = slave->silence_frames;
316 while (xfer < size) {
317 snd_pcm_uframes_t frames = size - xfer;
318 snd_pcm_uframes_t cont = buffer_size - offset;
321 snd_pcm_areas_silence(pcm->running_areas, offset, pcm->channels, frames, pcm->format);
323 if (offset >= buffer_size)
327 share->drain_silenced = 1;
329 snd_pcm_uframes_t silence_missing;
330 silence_missing = slave->silence_frames - avail;
331 if (silence_missing < missing)
332 missing = silence_missing;
335 // printf("missing=%d\n", missing);
339 static snd_pcm_uframes_t _snd_pcm_share_slave_missing(snd_pcm_share_slave_t *slave)
341 snd_pcm_uframes_t missing = INT_MAX;
343 /* snd_pcm_sframes_t avail = */ snd_pcm_avail_update(slave->pcm);
344 slave->hw_ptr = *slave->pcm->hw.ptr;
345 list_for_each(i, &slave->clients) {
346 snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
347 snd_pcm_t *pcm = share->pcm;
348 snd_pcm_uframes_t m = _snd_pcm_share_missing(pcm);
355 static void *snd_pcm_share_thread(void *data)
357 snd_pcm_share_slave_t *slave = data;
358 snd_pcm_t *spcm = slave->pcm;
359 struct pollfd pfd[2];
362 pfd[0].fd = slave->poll[0];
363 pfd[0].events = POLLIN;
364 err = snd_pcm_poll_descriptors(spcm, &pfd[1], 1);
366 SNDERR("invalid poll descriptors %d", err);
369 Pthread_mutex_lock(&slave->mutex);
370 err = pipe(slave->poll);
372 SYSERR("can't create a pipe");
375 while (slave->open_count > 0) {
376 snd_pcm_uframes_t missing;
377 // printf("begin min_missing\n");
378 missing = _snd_pcm_share_slave_missing(slave);
379 // printf("min_missing=%ld\n", missing);
380 if (missing < INT_MAX) {
381 snd_pcm_uframes_t hw_ptr;
382 snd_pcm_sframes_t avail_min;
383 hw_ptr = slave->hw_ptr + missing;
384 hw_ptr += spcm->period_size - 1;
385 if (hw_ptr >= spcm->boundary)
386 hw_ptr -= spcm->boundary;
387 hw_ptr -= hw_ptr % spcm->period_size;
388 avail_min = hw_ptr - *spcm->appl.ptr;
389 if (spcm->stream == SND_PCM_STREAM_PLAYBACK)
390 avail_min += spcm->buffer_size;
392 avail_min += spcm->boundary;
393 // printf("avail_min=%d\n", avail_min);
394 if ((snd_pcm_uframes_t)avail_min != spcm->avail_min) {
395 snd_pcm_sw_params_set_avail_min(spcm, &slave->sw_params, avail_min);
396 err = snd_pcm_sw_params(spcm, &slave->sw_params);
398 SYSERR("snd_pcm_sw_params error");
403 Pthread_mutex_unlock(&slave->mutex);
404 err = poll(pfd, 2, -1);
405 Pthread_mutex_lock(&slave->mutex);
406 if (pfd[0].revents & POLLIN) {
408 read(pfd[0].fd, buf, 1);
412 pthread_cond_wait(&slave->poll_cond, &slave->mutex);
415 Pthread_mutex_unlock(&slave->mutex);
419 static void _snd_pcm_share_update(snd_pcm_t *pcm)
421 snd_pcm_share_t *share = pcm->private_data;
422 snd_pcm_share_slave_t *slave = share->slave;
423 snd_pcm_t *spcm = slave->pcm;
424 snd_pcm_uframes_t missing;
425 /* snd_pcm_sframes_t avail = */ snd_pcm_avail_update(spcm);
426 slave->hw_ptr = *slave->pcm->hw.ptr;
427 missing = _snd_pcm_share_missing(pcm);
428 // printf("missing %ld\n", missing);
429 if (!slave->polling) {
430 pthread_cond_signal(&slave->poll_cond);
433 if (missing < INT_MAX) {
434 snd_pcm_uframes_t hw_ptr;
435 snd_pcm_sframes_t avail_min;
436 hw_ptr = slave->hw_ptr + missing;
437 hw_ptr += spcm->period_size - 1;
438 if (hw_ptr >= spcm->boundary)
439 hw_ptr -= spcm->boundary;
440 hw_ptr -= hw_ptr % spcm->period_size;
441 avail_min = hw_ptr - *spcm->appl.ptr;
442 if (spcm->stream == SND_PCM_STREAM_PLAYBACK)
443 avail_min += spcm->buffer_size;
445 avail_min += spcm->boundary;
446 if ((snd_pcm_uframes_t)avail_min < spcm->avail_min) {
448 snd_pcm_sw_params_set_avail_min(spcm, &slave->sw_params, avail_min);
449 err = snd_pcm_sw_params(spcm, &slave->sw_params);
451 SYSERR("snd_pcm_sw_params error");
458 static int snd_pcm_share_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
463 static int snd_pcm_share_async(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int sig ATTRIBUTE_UNUSED, pid_t pid ATTRIBUTE_UNUSED)
468 static int snd_pcm_share_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
470 snd_pcm_share_t *share = pcm->private_data;
471 return snd_pcm_info(share->slave->pcm, info);
474 static int snd_pcm_share_hw_refine_cprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
476 snd_pcm_share_t *share = pcm->private_data;
477 snd_pcm_share_slave_t *slave = share->slave;
478 snd_pcm_access_mask_t access_mask;
480 snd_pcm_access_mask_any(&access_mask);
481 snd_pcm_access_mask_reset(&access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
482 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
486 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_CHANNELS,
490 if (slave->format != SND_PCM_FORMAT_UNKNOWN) {
491 err = _snd_pcm_hw_params_set_format(params, slave->format);
496 if (slave->rate >= 0) {
497 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_RATE,
502 if (slave->period_time >= 0) {
503 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_PERIOD_TIME,
504 slave->period_time, 0);
508 if (slave->buffer_time >= 0) {
509 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_BUFFER_TIME,
510 slave->buffer_time, 0);
514 params->info |= SND_PCM_INFO_DOUBLE;
518 static int snd_pcm_share_hw_refine_sprepare(snd_pcm_t *pcm, snd_pcm_hw_params_t *sparams)
520 snd_pcm_share_t *share = pcm->private_data;
521 snd_pcm_share_slave_t *slave = share->slave;
522 snd_pcm_access_mask_t saccess_mask = { SND_PCM_ACCBIT_MMAP };
523 _snd_pcm_hw_params_any(sparams);
524 _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
526 _snd_pcm_hw_param_set(sparams, SND_PCM_HW_PARAM_CHANNELS,
531 static int snd_pcm_share_hw_refine_schange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
532 snd_pcm_hw_params_t *sparams)
535 unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
536 SND_PCM_HW_PARBIT_SUBFORMAT |
537 SND_PCM_HW_PARBIT_RATE |
538 SND_PCM_HW_PARBIT_PERIOD_SIZE |
539 SND_PCM_HW_PARBIT_PERIOD_TIME |
540 SND_PCM_HW_PARBIT_BUFFER_SIZE |
541 SND_PCM_HW_PARBIT_BUFFER_TIME |
542 SND_PCM_HW_PARBIT_PERIODS);
543 const snd_pcm_access_mask_t *access_mask = snd_pcm_hw_param_get_mask(params, SND_PCM_HW_PARAM_ACCESS);
544 if (!snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_INTERLEAVED) &&
545 !snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_RW_NONINTERLEAVED) &&
546 !snd_pcm_access_mask_test(access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED)) {
547 snd_pcm_access_mask_t saccess_mask;
548 snd_pcm_access_mask_any(&saccess_mask);
549 snd_pcm_access_mask_reset(&saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
550 err = _snd_pcm_hw_param_set_mask(sparams, SND_PCM_HW_PARAM_ACCESS,
555 err = _snd_pcm_hw_params_refine(sparams, links, params);
561 static int snd_pcm_share_hw_refine_cchange(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_hw_params_t *params,
562 snd_pcm_hw_params_t *sparams)
565 unsigned int links = (SND_PCM_HW_PARBIT_FORMAT |
566 SND_PCM_HW_PARBIT_SUBFORMAT |
567 SND_PCM_HW_PARBIT_RATE |
568 SND_PCM_HW_PARBIT_PERIOD_SIZE |
569 SND_PCM_HW_PARBIT_PERIOD_TIME |
570 SND_PCM_HW_PARBIT_BUFFER_SIZE |
571 SND_PCM_HW_PARBIT_BUFFER_TIME |
572 SND_PCM_HW_PARBIT_PERIODS);
573 snd_pcm_access_mask_t access_mask;
574 const snd_pcm_access_mask_t *saccess_mask = snd_pcm_hw_param_get_mask(sparams, SND_PCM_HW_PARAM_ACCESS);
575 snd_pcm_access_mask_any(&access_mask);
576 snd_pcm_access_mask_reset(&access_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
577 if (!snd_pcm_access_mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED))
578 snd_pcm_access_mask_reset(&access_mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
579 if (!snd_pcm_access_mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_COMPLEX) &&
580 !snd_pcm_access_mask_test(saccess_mask, SND_PCM_ACCESS_MMAP_INTERLEAVED))
581 snd_pcm_access_mask_reset(&access_mask, SND_PCM_ACCESS_MMAP_COMPLEX);
582 err = _snd_pcm_hw_param_set_mask(params, SND_PCM_HW_PARAM_ACCESS,
586 err = _snd_pcm_hw_params_refine(params, links, sparams);
592 static int snd_pcm_share_hw_refine_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
594 snd_pcm_share_t *share = pcm->private_data;
595 return snd_pcm_hw_refine(share->slave->pcm, params);
598 static int snd_pcm_share_hw_params_slave(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
600 snd_pcm_share_t *share = pcm->private_data;
601 return _snd_pcm_hw_params(share->slave->pcm, params);
604 static int snd_pcm_share_hw_refine(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
606 return snd_pcm_hw_refine_slave(pcm, params,
607 snd_pcm_share_hw_refine_cprepare,
608 snd_pcm_share_hw_refine_cchange,
609 snd_pcm_share_hw_refine_sprepare,
610 snd_pcm_share_hw_refine_schange,
611 snd_pcm_share_hw_refine_slave);
614 static int snd_pcm_share_hw_params(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
616 snd_pcm_share_t *share = pcm->private_data;
617 snd_pcm_share_slave_t *slave = share->slave;
618 snd_pcm_t *spcm = slave->pcm;
620 Pthread_mutex_lock(&slave->mutex);
621 if (slave->setup_count) {
622 err = _snd_pcm_hw_params_set_format(params, spcm->format);
625 err = _snd_pcm_hw_params_set_subformat(params, spcm->subformat);
628 err = _snd_pcm_hw_param_set_minmax(params, SND_PCM_HW_PARAM_RATE,
633 err = _snd_pcm_hw_param_set_minmax(params, SND_PCM_HW_PARAM_PERIOD_TIME,
634 spcm->period_time, 0,
635 spcm->period_time, 1);
638 err = _snd_pcm_hw_param_set(params, SND_PCM_HW_PARAM_BUFFER_SIZE,
639 spcm->buffer_size, 0);
642 SNDERR("slave is already running with incompatible setup");
647 err = snd_pcm_hw_params_slave(pcm, params,
648 snd_pcm_share_hw_refine_cchange,
649 snd_pcm_share_hw_refine_sprepare,
650 snd_pcm_share_hw_refine_schange,
651 snd_pcm_share_hw_params_slave);
654 snd_pcm_sw_params_current(slave->pcm, &slave->sw_params);
656 slave->safety_threshold = slave->pcm->rate * 30 / 1000;
657 slave->safety_threshold += slave->pcm->period_size - 1;
658 slave->safety_threshold -= slave->safety_threshold % slave->pcm->period_size;
659 slave->silence_frames = slave->safety_threshold;
660 if (slave->pcm->stream == SND_PCM_STREAM_PLAYBACK)
661 snd_pcm_areas_silence(slave->pcm->running_areas, 0, slave->pcm->channels, slave->pcm->buffer_size, slave->pcm->format);
663 share->state = SND_PCM_STATE_SETUP;
664 slave->setup_count++;
666 Pthread_mutex_unlock(&slave->mutex);
670 static int snd_pcm_share_hw_free(snd_pcm_t *pcm)
672 snd_pcm_share_t *share = pcm->private_data;
673 snd_pcm_share_slave_t *slave = share->slave;
675 Pthread_mutex_lock(&slave->mutex);
676 slave->setup_count--;
677 if (slave->setup_count == 0)
678 err = snd_pcm_hw_free(slave->pcm);
679 share->state = SND_PCM_STATE_OPEN;
680 Pthread_mutex_unlock(&slave->mutex);
684 static int snd_pcm_share_sw_params(snd_pcm_t *pcm ATTRIBUTE_UNUSED, snd_pcm_sw_params_t *params ATTRIBUTE_UNUSED)
689 static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
691 snd_pcm_share_t *share = pcm->private_data;
692 snd_pcm_share_slave_t *slave = share->slave;
694 snd_pcm_sframes_t sd = 0, d = 0;
695 Pthread_mutex_lock(&slave->mutex);
696 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
697 status->avail = snd_pcm_mmap_playback_avail(pcm);
698 if (share->state != SND_PCM_STATE_RUNNING &&
699 share->state != SND_PCM_STATE_DRAINING)
701 d = pcm->buffer_size - status->avail;
703 status->avail = snd_pcm_mmap_capture_avail(pcm);
704 if (share->state != SND_PCM_STATE_RUNNING)
708 err = snd_pcm_delay(slave->pcm, &sd);
712 status->delay = sd + d;
713 status->state = share->state;
714 status->trigger_tstamp = share->trigger_tstamp;
716 Pthread_mutex_unlock(&slave->mutex);
720 static snd_pcm_state_t snd_pcm_share_state(snd_pcm_t *pcm)
722 snd_pcm_share_t *share = pcm->private_data;
726 static int _snd_pcm_share_hwsync(snd_pcm_t *pcm)
728 snd_pcm_share_t *share = pcm->private_data;
729 snd_pcm_share_slave_t *slave = share->slave;
730 switch (share->state) {
731 case SND_PCM_STATE_XRUN:
736 return snd_pcm_hwsync(slave->pcm);
739 static int snd_pcm_share_hwsync(snd_pcm_t *pcm)
741 snd_pcm_share_t *share = pcm->private_data;
742 snd_pcm_share_slave_t *slave = share->slave;
744 Pthread_mutex_lock(&slave->mutex);
745 err = _snd_pcm_share_hwsync(pcm);
746 Pthread_mutex_unlock(&slave->mutex);
750 static int _snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
752 snd_pcm_share_t *share = pcm->private_data;
753 snd_pcm_share_slave_t *slave = share->slave;
754 switch (share->state) {
755 case SND_PCM_STATE_XRUN:
757 case SND_PCM_STATE_RUNNING:
759 case SND_PCM_STATE_DRAINING:
760 if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
766 return snd_pcm_delay(slave->pcm, delayp);
769 static int snd_pcm_share_delay(snd_pcm_t *pcm, snd_pcm_sframes_t *delayp)
771 snd_pcm_share_t *share = pcm->private_data;
772 snd_pcm_share_slave_t *slave = share->slave;
774 Pthread_mutex_lock(&slave->mutex);
775 err = _snd_pcm_share_delay(pcm, delayp);
776 Pthread_mutex_unlock(&slave->mutex);
780 static snd_pcm_sframes_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
782 snd_pcm_share_t *share = pcm->private_data;
783 snd_pcm_share_slave_t *slave = share->slave;
784 snd_pcm_sframes_t avail;
785 Pthread_mutex_lock(&slave->mutex);
786 if (share->state == SND_PCM_STATE_RUNNING) {
787 avail = snd_pcm_avail_update(slave->pcm);
789 Pthread_mutex_unlock(&slave->mutex);
792 share->hw_ptr = *slave->pcm->hw.ptr;
794 Pthread_mutex_unlock(&slave->mutex);
795 avail = snd_pcm_mmap_avail(pcm);
796 if ((snd_pcm_uframes_t)avail > pcm->buffer_size)
801 static int snd_pcm_share_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
802 snd_htimestamp_t *tstamp)
804 snd_pcm_share_t *share = pcm->private_data;
805 snd_pcm_share_slave_t *slave = share->slave;
807 Pthread_mutex_lock(&slave->mutex);
808 err = snd_pcm_htimestamp(slave->pcm, avail, tstamp);
809 Pthread_mutex_unlock(&slave->mutex);
813 /* Call it with mutex held */
814 static snd_pcm_sframes_t _snd_pcm_share_mmap_commit(snd_pcm_t *pcm,
815 snd_pcm_uframes_t offset ATTRIBUTE_UNUSED,
816 snd_pcm_uframes_t size)
818 snd_pcm_share_t *share = pcm->private_data;
819 snd_pcm_share_slave_t *slave = share->slave;
820 snd_pcm_t *spcm = slave->pcm;
821 snd_pcm_sframes_t ret;
822 snd_pcm_sframes_t frames;
823 if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
824 share->state == SND_PCM_STATE_RUNNING) {
825 frames = *spcm->appl.ptr - share->appl_ptr;
826 if (frames > (snd_pcm_sframes_t)pcm->buffer_size)
827 frames -= pcm->boundary;
828 else if (frames < -(snd_pcm_sframes_t)pcm->buffer_size)
829 frames += pcm->boundary;
832 ret = snd_pcm_rewind(spcm, frames);
837 snd_pcm_mmap_appl_forward(pcm, size);
838 if (share->state == SND_PCM_STATE_RUNNING) {
839 frames = _snd_pcm_share_slave_forward(slave);
841 snd_pcm_sframes_t err;
842 err = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), frames);
844 SYSMSG("snd_pcm_mmap_commit error");
848 SYSMSG("commit returns %ld for size %ld", err, frames);
852 _snd_pcm_share_update(pcm);
857 static snd_pcm_sframes_t snd_pcm_share_mmap_commit(snd_pcm_t *pcm,
858 snd_pcm_uframes_t offset,
859 snd_pcm_uframes_t size)
861 snd_pcm_share_t *share = pcm->private_data;
862 snd_pcm_share_slave_t *slave = share->slave;
863 snd_pcm_sframes_t ret;
864 Pthread_mutex_lock(&slave->mutex);
865 ret = _snd_pcm_share_mmap_commit(pcm, offset, size);
866 Pthread_mutex_unlock(&slave->mutex);
870 static int snd_pcm_share_prepare(snd_pcm_t *pcm)
872 snd_pcm_share_t *share = pcm->private_data;
873 snd_pcm_share_slave_t *slave = share->slave;
875 Pthread_mutex_lock(&slave->mutex);
876 switch (share->state) {
877 case SND_PCM_STATE_OPEN:
880 case SND_PCM_STATE_RUNNING:
883 case SND_PCM_STATE_PREPARED:
886 default: /* nothing todo */
889 if (slave->prepared_count == 0) {
890 err = snd_pcm_prepare(slave->pcm);
894 slave->prepared_count++;
897 share->state = SND_PCM_STATE_PREPARED;
899 Pthread_mutex_unlock(&slave->mutex);
903 static int snd_pcm_share_reset(snd_pcm_t *pcm)
905 snd_pcm_share_t *share = pcm->private_data;
906 snd_pcm_share_slave_t *slave = share->slave;
909 Pthread_mutex_lock(&slave->mutex);
910 snd_pcm_areas_silence(pcm->running_areas, 0, pcm->channels, pcm->buffer_size, pcm->format);
911 share->hw_ptr = *slave->pcm->hw.ptr;
912 share->appl_ptr = share->hw_ptr;
913 Pthread_mutex_unlock(&slave->mutex);
917 static int snd_pcm_share_start(snd_pcm_t *pcm)
919 snd_pcm_share_t *share = pcm->private_data;
920 snd_pcm_share_slave_t *slave = share->slave;
921 snd_pcm_t *spcm = slave->pcm;
923 if (share->state != SND_PCM_STATE_PREPARED)
925 Pthread_mutex_lock(&slave->mutex);
926 share->state = SND_PCM_STATE_RUNNING;
927 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
928 snd_pcm_uframes_t hw_avail = snd_pcm_mmap_playback_hw_avail(pcm);
929 snd_pcm_uframes_t xfer = 0;
934 if (slave->running_count) {
935 snd_pcm_sframes_t sd;
936 err = snd_pcm_delay(spcm, &sd);
939 err = snd_pcm_rewind(spcm, sd);
943 assert(share->hw_ptr == 0);
944 share->hw_ptr = *spcm->hw.ptr;
945 share->appl_ptr = *spcm->appl.ptr;
946 while (xfer < hw_avail) {
947 snd_pcm_uframes_t frames = hw_avail - xfer;
948 snd_pcm_uframes_t offset = snd_pcm_mmap_offset(pcm);
949 snd_pcm_uframes_t cont = pcm->buffer_size - offset;
952 if (pcm->stopped_areas != NULL)
953 snd_pcm_areas_copy(pcm->running_areas, offset,
954 pcm->stopped_areas, xfer,
955 pcm->channels, frames,
959 snd_pcm_mmap_appl_forward(pcm, hw_avail);
960 if (slave->running_count == 0) {
961 snd_pcm_sframes_t res;
962 res = snd_pcm_mmap_commit(spcm, snd_pcm_mmap_offset(spcm), hw_avail);
967 assert((snd_pcm_uframes_t)res == hw_avail);
970 if (slave->running_count == 0) {
971 err = snd_pcm_start(spcm);
975 slave->running_count++;
976 _snd_pcm_share_update(pcm);
977 gettimestamp(&share->trigger_tstamp, pcm->monotonic);
979 Pthread_mutex_unlock(&slave->mutex);
983 static int snd_pcm_share_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
988 static int snd_pcm_share_resume(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
993 static int snd_pcm_share_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
995 snd_pcm_share_t *share = pcm->private_data;
996 snd_pcm_share_slave_t *slave = share->slave;
997 unsigned int channel = info->channel;
998 int c = share->slave_channels[channel];
1001 err = snd_pcm_channel_info(slave->pcm, info);
1002 info->channel = channel;
1006 static snd_pcm_sframes_t _snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1008 snd_pcm_share_t *share = pcm->private_data;
1009 snd_pcm_share_slave_t *slave = share->slave;
1010 snd_pcm_sframes_t n;
1011 switch (share->state) {
1012 case SND_PCM_STATE_RUNNING:
1014 case SND_PCM_STATE_PREPARED:
1015 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
1018 case SND_PCM_STATE_DRAINING:
1019 if (pcm->stream != SND_PCM_STREAM_CAPTURE)
1022 case SND_PCM_STATE_XRUN:
1027 n = snd_pcm_mmap_hw_avail(pcm);
1029 if ((snd_pcm_uframes_t)n > frames)
1031 if (share->state == SND_PCM_STATE_RUNNING && frames > 0) {
1032 snd_pcm_sframes_t ret = snd_pcm_rewind(slave->pcm, frames);
1037 snd_pcm_mmap_appl_backward(pcm, frames);
1038 _snd_pcm_share_update(pcm);
1042 static snd_pcm_sframes_t snd_pcm_share_rewindable(snd_pcm_t *pcm)
1044 snd_pcm_share_t *share = pcm->private_data;
1045 snd_pcm_share_slave_t *slave = share->slave;
1046 snd_pcm_sframes_t ret;
1047 Pthread_mutex_lock(&slave->mutex);
1048 ret = snd_pcm_rewindable(slave->pcm);
1049 Pthread_mutex_unlock(&slave->mutex);
1053 static snd_pcm_sframes_t snd_pcm_share_rewind(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1055 snd_pcm_share_t *share = pcm->private_data;
1056 snd_pcm_share_slave_t *slave = share->slave;
1057 snd_pcm_sframes_t ret;
1058 Pthread_mutex_lock(&slave->mutex);
1059 ret = _snd_pcm_share_rewind(pcm, frames);
1060 Pthread_mutex_unlock(&slave->mutex);
1064 static snd_pcm_sframes_t _snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1066 snd_pcm_share_t *share = pcm->private_data;
1067 snd_pcm_share_slave_t *slave = share->slave;
1068 snd_pcm_sframes_t n;
1069 switch (share->state) {
1070 case SND_PCM_STATE_RUNNING:
1072 case SND_PCM_STATE_PREPARED:
1073 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
1076 case SND_PCM_STATE_DRAINING:
1077 if (pcm->stream != SND_PCM_STREAM_CAPTURE)
1080 case SND_PCM_STATE_XRUN:
1085 n = snd_pcm_mmap_avail(pcm);
1086 if ((snd_pcm_uframes_t)n > frames)
1088 if (share->state == SND_PCM_STATE_RUNNING && frames > 0) {
1089 snd_pcm_sframes_t ret = INTERNAL(snd_pcm_forward)(slave->pcm, frames);
1094 snd_pcm_mmap_appl_forward(pcm, frames);
1095 _snd_pcm_share_update(pcm);
1099 static snd_pcm_sframes_t snd_pcm_share_forwardable(snd_pcm_t *pcm)
1101 snd_pcm_share_t *share = pcm->private_data;
1102 snd_pcm_share_slave_t *slave = share->slave;
1103 snd_pcm_sframes_t ret;
1104 Pthread_mutex_lock(&slave->mutex);
1105 ret = snd_pcm_forwardable(slave->pcm);
1106 Pthread_mutex_unlock(&slave->mutex);
1110 static snd_pcm_sframes_t snd_pcm_share_forward(snd_pcm_t *pcm, snd_pcm_uframes_t frames)
1112 snd_pcm_share_t *share = pcm->private_data;
1113 snd_pcm_share_slave_t *slave = share->slave;
1114 snd_pcm_sframes_t ret;
1115 Pthread_mutex_lock(&slave->mutex);
1116 ret = _snd_pcm_share_forward(pcm, frames);
1117 Pthread_mutex_unlock(&slave->mutex);
1121 /* Warning: take the mutex before to call this */
1122 static void _snd_pcm_share_stop(snd_pcm_t *pcm, snd_pcm_state_t state)
1124 snd_pcm_share_t *share = pcm->private_data;
1125 snd_pcm_share_slave_t *slave = share->slave;
1127 if (!pcm->mmap_channels) {
1128 /* PCM closing already begun in the main thread */
1132 gettimestamp(&share->trigger_tstamp, pcm->monotonic);
1133 if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
1134 snd_pcm_areas_copy(pcm->stopped_areas, 0,
1135 pcm->running_areas, 0,
1136 pcm->channels, pcm->buffer_size,
1138 } else if (slave->running_count > 1) {
1140 snd_pcm_sframes_t delay;
1141 snd_pcm_areas_silence(pcm->running_areas, 0, pcm->channels,
1142 pcm->buffer_size, pcm->format);
1143 err = snd_pcm_delay(slave->pcm, &delay);
1144 if (err >= 0 && delay > 0)
1145 snd_pcm_rewind(slave->pcm, delay);
1146 share->drain_silenced = 0;
1148 share->state = state;
1149 slave->prepared_count--;
1150 slave->running_count--;
1151 if (slave->running_count == 0) {
1152 int err = snd_pcm_drop(slave->pcm);
1157 static int snd_pcm_share_drain(snd_pcm_t *pcm)
1159 snd_pcm_share_t *share = pcm->private_data;
1160 snd_pcm_share_slave_t *slave = share->slave;
1162 Pthread_mutex_lock(&slave->mutex);
1163 switch (share->state) {
1164 case SND_PCM_STATE_OPEN:
1167 case SND_PCM_STATE_PREPARED:
1168 share->state = SND_PCM_STATE_SETUP;
1170 case SND_PCM_STATE_SETUP:
1175 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
1176 switch (share->state) {
1177 case SND_PCM_STATE_XRUN:
1178 share->state = SND_PCM_STATE_SETUP;
1180 case SND_PCM_STATE_DRAINING:
1181 case SND_PCM_STATE_RUNNING:
1182 share->state = SND_PCM_STATE_DRAINING;
1183 _snd_pcm_share_update(pcm);
1184 Pthread_mutex_unlock(&slave->mutex);
1185 if (!(pcm->mode & SND_PCM_NONBLOCK))
1186 snd_pcm_wait(pcm, -1);
1193 switch (share->state) {
1194 case SND_PCM_STATE_RUNNING:
1195 _snd_pcm_share_stop(pcm, SND_PCM_STATE_DRAINING);
1196 _snd_pcm_share_update(pcm);
1198 case SND_PCM_STATE_XRUN:
1199 case SND_PCM_STATE_DRAINING:
1200 if (snd_pcm_mmap_capture_avail(pcm) <= 0)
1201 share->state = SND_PCM_STATE_SETUP;
1203 share->state = SND_PCM_STATE_DRAINING;
1211 Pthread_mutex_unlock(&slave->mutex);
1215 static int snd_pcm_share_drop(snd_pcm_t *pcm)
1217 snd_pcm_share_t *share = pcm->private_data;
1218 snd_pcm_share_slave_t *slave = share->slave;
1220 Pthread_mutex_lock(&slave->mutex);
1221 switch (share->state) {
1222 case SND_PCM_STATE_OPEN:
1225 case SND_PCM_STATE_SETUP:
1227 case SND_PCM_STATE_DRAINING:
1228 if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
1229 share->state = SND_PCM_STATE_SETUP;
1233 case SND_PCM_STATE_RUNNING:
1234 _snd_pcm_share_stop(pcm, SND_PCM_STATE_SETUP);
1235 _snd_pcm_share_update(pcm);
1237 case SND_PCM_STATE_PREPARED:
1238 case SND_PCM_STATE_XRUN:
1239 share->state = SND_PCM_STATE_SETUP;
1246 share->appl_ptr = share->hw_ptr = 0;
1248 Pthread_mutex_unlock(&slave->mutex);
1252 static int snd_pcm_share_close(snd_pcm_t *pcm)
1254 snd_pcm_share_t *share = pcm->private_data;
1255 snd_pcm_share_slave_t *slave = share->slave;
1258 Pthread_mutex_lock(&snd_pcm_share_slaves_mutex);
1259 Pthread_mutex_lock(&slave->mutex);
1260 slave->open_count--;
1261 if (slave->open_count == 0) {
1262 pthread_cond_signal(&slave->poll_cond);
1263 Pthread_mutex_unlock(&slave->mutex);
1264 err = pthread_join(slave->thread, 0);
1266 err = snd_pcm_close(slave->pcm);
1267 pthread_mutex_destroy(&slave->mutex);
1268 pthread_cond_destroy(&slave->poll_cond);
1269 list_del(&slave->list);
1271 list_del(&share->list);
1273 list_del(&share->list);
1274 Pthread_mutex_unlock(&slave->mutex);
1276 Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
1277 close(share->client_socket);
1278 close(share->slave_socket);
1279 free(share->slave_channels);
1284 static int snd_pcm_share_mmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1289 static int snd_pcm_share_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
1294 static void snd_pcm_share_dump(snd_pcm_t *pcm, snd_output_t *out)
1296 snd_pcm_share_t *share = pcm->private_data;
1297 snd_pcm_share_slave_t *slave = share->slave;
1299 snd_output_printf(out, "Share PCM\n");
1300 snd_output_printf(out, " Channel bindings:\n");
1301 for (k = 0; k < share->channels; ++k)
1302 snd_output_printf(out, " %d: %d\n", k, share->slave_channels[k]);
1304 snd_output_printf(out, "Its setup is:\n");
1305 snd_pcm_dump_setup(pcm, out);
1307 snd_output_printf(out, "Slave: ");
1308 snd_pcm_dump(slave->pcm, out);
1311 static const snd_pcm_ops_t snd_pcm_share_ops = {
1312 .close = snd_pcm_share_close,
1313 .info = snd_pcm_share_info,
1314 .hw_refine = snd_pcm_share_hw_refine,
1315 .hw_params = snd_pcm_share_hw_params,
1316 .hw_free = snd_pcm_share_hw_free,
1317 .sw_params = snd_pcm_share_sw_params,
1318 .channel_info = snd_pcm_share_channel_info,
1319 .dump = snd_pcm_share_dump,
1320 .nonblock = snd_pcm_share_nonblock,
1321 .async = snd_pcm_share_async,
1322 .mmap = snd_pcm_share_mmap,
1323 .munmap = snd_pcm_share_munmap,
1326 static const snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
1327 .status = snd_pcm_share_status,
1328 .state = snd_pcm_share_state,
1329 .hwsync = snd_pcm_share_hwsync,
1330 .delay = snd_pcm_share_delay,
1331 .prepare = snd_pcm_share_prepare,
1332 .reset = snd_pcm_share_reset,
1333 .start = snd_pcm_share_start,
1334 .drop = snd_pcm_share_drop,
1335 .drain = snd_pcm_share_drain,
1336 .pause = snd_pcm_share_pause,
1337 .writei = snd_pcm_mmap_writei,
1338 .writen = snd_pcm_mmap_writen,
1339 .readi = snd_pcm_mmap_readi,
1340 .readn = snd_pcm_mmap_readn,
1341 .rewindable = snd_pcm_share_rewindable,
1342 .rewind = snd_pcm_share_rewind,
1343 .forwardable = snd_pcm_share_forwardable,
1344 .forward = snd_pcm_share_forward,
1345 .resume = snd_pcm_share_resume,
1346 .avail_update = snd_pcm_share_avail_update,
1347 .htimestamp = snd_pcm_share_htimestamp,
1348 .mmap_commit = snd_pcm_share_mmap_commit,
1352 * \brief Creates a new Share PCM
1353 * \param pcmp Returns created PCM handle
1354 * \param name Name of PCM
1355 * \param sname Slave name
1356 * \param sformat Slave format
1357 * \param srate Slave rate
1358 * \param schannels Slave channels
1359 * \param speriod_time Slave period time
1360 * \param sbuffer_time Slave buffer time
1361 * \param channels Count of channels
1362 * \param channels_map Map of channels
1363 * \param stream Direction
1364 * \param mode PCM mode
1365 * \retval zero on success otherwise a negative error code
1366 * \warning Using of this function might be dangerous in the sense
1367 * of compatibility reasons. The prototype might be freely
1368 * changed in future.
1370 int snd_pcm_share_open(snd_pcm_t **pcmp, const char *name, const char *sname,
1371 snd_pcm_format_t sformat, int srate,
1372 unsigned int schannels,
1373 int speriod_time, int sbuffer_time,
1374 unsigned int channels, unsigned int *channels_map,
1375 snd_pcm_stream_t stream, int mode)
1378 snd_pcm_share_t *share;
1380 struct list_head *i;
1381 char slave_map[32] = { 0 };
1383 snd_pcm_share_slave_t *slave = NULL;
1387 assert(channels > 0 && sname && channels_map);
1389 for (k = 0; k < channels; ++k) {
1390 if (channels_map[k] >= sizeof(slave_map) / sizeof(slave_map[0])) {
1391 SNDERR("Invalid slave channel (%d) in binding", channels_map[k]);
1394 if (slave_map[channels_map[k]]) {
1395 SNDERR("Repeated slave channel (%d) in binding", channels_map[k]);
1398 slave_map[channels_map[k]] = 1;
1399 assert((unsigned)channels_map[k] < schannels);
1402 share = calloc(1, sizeof(snd_pcm_share_t));
1406 share->channels = channels;
1407 share->slave_channels = calloc(channels, sizeof(*share->slave_channels));
1408 if (!share->slave_channels) {
1412 memcpy(share->slave_channels, channels_map, channels * sizeof(*share->slave_channels));
1414 err = snd_pcm_new(&pcm, SND_PCM_TYPE_SHARE, name, stream, mode);
1416 free(share->slave_channels);
1420 err = socketpair(AF_LOCAL, SOCK_STREAM, 0, sd);
1423 free(share->slave_channels);
1428 if (stream == SND_PCM_STREAM_PLAYBACK) {
1430 err = setsockopt(sd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
1434 pfd.events = POLLOUT;
1435 while ((err = poll(&pfd, 1, 0)) == 1) {
1437 err = write(sd[0], buf, 1);
1449 free(share->slave_channels);
1454 Pthread_mutex_lock(&snd_pcm_share_slaves_mutex);
1455 list_for_each(i, &snd_pcm_share_slaves) {
1456 snd_pcm_share_slave_t *s = list_entry(i, snd_pcm_share_slave_t, list);
1457 if (s->pcm->name && strcmp(s->pcm->name, sname) == 0) {
1464 err = snd_pcm_open(&spcm, sname, stream, mode);
1466 Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
1470 free(share->slave_channels);
1474 /* FIXME: bellow is a real ugly hack to get things working */
1475 /* there is a memory leak somewhere, but I'm unable to trace it --jk */
1476 slave = calloc(1, sizeof(snd_pcm_share_slave_t) * 8);
1478 Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
1479 snd_pcm_close(spcm);
1483 free(share->slave_channels);
1487 INIT_LIST_HEAD(&slave->clients);
1489 slave->channels = schannels;
1490 slave->format = sformat;
1491 slave->rate = srate;
1492 slave->period_time = speriod_time;
1493 slave->buffer_time = sbuffer_time;
1494 pthread_mutex_init(&slave->mutex, NULL);
1495 pthread_cond_init(&slave->poll_cond, NULL);
1496 list_add_tail(&slave->list, &snd_pcm_share_slaves);
1497 Pthread_mutex_lock(&slave->mutex);
1498 err = pthread_create(&slave->thread, NULL, snd_pcm_share_thread, slave);
1500 Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
1502 Pthread_mutex_lock(&slave->mutex);
1503 Pthread_mutex_unlock(&snd_pcm_share_slaves_mutex);
1504 list_for_each(i, &slave->clients) {
1505 snd_pcm_share_t *sh = list_entry(i, snd_pcm_share_t, list);
1506 for (k = 0; k < sh->channels; ++k) {
1507 if (slave_map[sh->slave_channels[k]]) {
1508 SNDERR("Slave channel %d is already in use", sh->slave_channels[k]);
1509 Pthread_mutex_unlock(&slave->mutex);
1513 free(share->slave_channels);
1521 share->slave = slave;
1523 share->client_socket = sd[0];
1524 share->slave_socket = sd[1];
1527 pcm->ops = &snd_pcm_share_ops;
1528 pcm->fast_ops = &snd_pcm_share_fast_ops;
1529 pcm->private_data = share;
1530 pcm->poll_fd = share->client_socket;
1531 pcm->poll_events = stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
1532 pcm->monotonic = slave->pcm->monotonic;
1533 snd_pcm_set_hw_ptr(pcm, &share->hw_ptr, -1, 0);
1534 snd_pcm_set_appl_ptr(pcm, &share->appl_ptr, -1, 0);
1536 slave->open_count++;
1537 list_add_tail(&share->list, &slave->clients);
1539 Pthread_mutex_unlock(&slave->mutex);
1545 /*! \page pcm_plugins
1547 \section pcm_plugins_share Plugin: Share
1549 This plugin allows sharing of multiple channels with more clients. The access
1550 to each channel is exlusive (samples are not mixed together). It means, if
1551 the channel zero is used with first client, the channel cannot be used with
1552 second one. If you are looking for a mixing plugin, use the
1553 \ref pcm_plugins_dmix "dmix plugin".
1555 The difference from \ref pcm_plugins_dshare "dshare plugin" is that
1556 share plugin requires the server program "aserver", while dshare plugin
1557 doesn't need the explicit server but access to the shared buffer.
1561 type share # Share PCM
1562 slave STR # Slave name
1564 slave { # Slave definition
1565 pcm STR # Slave PCM name
1566 [format STR] # Slave format
1567 [channels INT] # Slave channels
1568 [rate INT] # Slave rate
1569 [period_time INT] # Slave period time in us
1570 [buffer_time INT] # Slave buffer time in us
1573 N INT # Slave channel INT for client channel N
1578 \subsection pcm_plugins_share_funcref Function reference
1581 <LI>snd_pcm_share_open()
1582 <LI>_snd_pcm_share_open()
1588 * \brief Creates a new Share PCM
1589 * \param pcmp Returns created PCM handle
1590 * \param name Name of PCM
1591 * \param root Root configuration node
1592 * \param conf Configuration node with Share PCM description
1593 * \param stream Stream type
1594 * \param mode Stream mode
1595 * \retval zero on success otherwise a negative error code
1596 * \warning Using of this function might be dangerous in the sense
1597 * of compatibility reasons. The prototype might be freely
1598 * changed in future.
1600 int _snd_pcm_share_open(snd_pcm_t **pcmp, const char *name,
1601 snd_config_t *root, snd_config_t *conf,
1602 snd_pcm_stream_t stream, int mode)
1604 snd_config_iterator_t i, next;
1605 const char *sname = NULL;
1606 snd_config_t *bindings = NULL;
1608 snd_config_t *slave = NULL, *sconf;
1609 unsigned int *channels_map = NULL;
1610 unsigned int channels = 0;
1611 snd_pcm_format_t sformat = SND_PCM_FORMAT_UNKNOWN;
1614 int speriod_time= -1, sbuffer_time = -1;
1615 unsigned int schannel_max = 0;
1617 snd_config_for_each(i, next, conf) {
1618 snd_config_t *n = snd_config_iterator_entry(i);
1620 if (snd_config_get_id(n, &id) < 0)
1622 if (snd_pcm_conf_generic_id(id))
1624 if (strcmp(id, "slave") == 0) {
1628 if (strcmp(id, "bindings") == 0) {
1629 if (snd_config_get_type(n) != SND_CONFIG_TYPE_COMPOUND) {
1630 SNDERR("Invalid type for %s", id);
1636 SNDERR("Unknown field %s", id);
1640 SNDERR("slave is not defined");
1643 err = snd_pcm_slave_conf(root, slave, &sconf, 5,
1644 SND_PCM_HW_PARAM_FORMAT, 0, &sformat,
1645 SND_PCM_HW_PARAM_CHANNELS, 0, &schannels,
1646 SND_PCM_HW_PARAM_RATE, 0, &srate,
1647 SND_PCM_HW_PARAM_PERIOD_TIME, 0, &speriod_time,
1648 SND_PCM_HW_PARAM_BUFFER_TIME, 0, &sbuffer_time);
1652 /* FIXME: nothing strictly forces to have named definition */
1653 err = snd_config_get_string(sconf, &sname);
1654 sname = err >= 0 && sname ? strdup(sname) : NULL;
1655 snd_config_delete(sconf);
1656 if (sname == NULL) {
1657 SNDERR("slave.pcm is not a string");
1662 SNDERR("bindings is not defined");
1666 snd_config_for_each(i, next, bindings) {
1668 snd_config_t *n = snd_config_iterator_entry(i);
1670 if (snd_config_get_id(n, &id) < 0)
1672 err = safe_strtol(id, &cchannel);
1673 if (err < 0 || cchannel < 0) {
1674 SNDERR("Invalid client channel in binding: %s", id);
1678 if ((unsigned)cchannel >= channels)
1679 channels = cchannel + 1;
1681 if (channels == 0) {
1682 SNDERR("No bindings defined");
1686 channels_map = calloc(channels, sizeof(*channels_map));
1687 if (! channels_map) {
1692 snd_config_for_each(i, next, bindings) {
1693 snd_config_t *n = snd_config_iterator_entry(i);
1697 if (snd_config_get_id(n, &id) < 0)
1699 cchannel = atoi(id);
1700 err = snd_config_get_integer(n, &schannel);
1704 assert(schannel >= 0);
1705 assert(schannels <= 0 || schannel < schannels);
1706 channels_map[cchannel] = schannel;
1707 if ((unsigned)schannel > schannel_max)
1708 schannel_max = schannel;
1711 schannels = schannel_max + 1;
1712 err = snd_pcm_share_open(pcmp, name, sname, sformat, srate,
1713 (unsigned int) schannels,
1714 speriod_time, sbuffer_time,
1715 channels, channels_map, stream, mode);
1718 free((char *)sname);
1722 SND_DLSYM_BUILD_VERSION(_snd_pcm_share_open, SND_PCM_DLSYM_VERSION);