3 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Library General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 #include <sys/socket.h>
32 #include "pcm_local.h"
35 static LIST_HEAD(slaves);
36 static pthread_mutex_t slaves_mutex = PTHREAD_MUTEX_INITIALIZER;
39 struct list_head clients;
40 struct list_head list;
42 size_t channels_count;
46 size_t prepared_count;
48 size_t safety_threshold;
50 pthread_mutex_t mutex;
51 } snd_pcm_share_slave_t;
54 struct list_head list;
56 snd_pcm_share_slave_t *slave;
57 size_t channels_count;
63 struct timeval trigger_time;
64 size_t draining_silence;
75 static void snd_pcm_share_interrupt(snd_pcm_share_slave_t *slave)
78 pthread_mutex_lock(&slave->mutex);
79 /* Update poll status */
80 for (i = slave->clients.next; i != &slave->clients; i = i->next) {
81 snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
82 snd_pcm_t *pcm = share->pcm;
84 switch (share->state) {
85 case SND_PCM_STATE_DRAINING:
86 if (pcm->stream == SND_PCM_STREAM_CAPTURE)
89 if (pcm->mode & SND_PCM_ASYNC)
90 kill(share->async_pid, share->async_sig);
94 case SND_PCM_STATE_RUNNING:
95 if (pcm->mode & SND_PCM_ASYNC)
96 kill(share->async_pid, share->async_sig);
97 ready = (snd_pcm_mmap_avail(pcm) >= pcm->setup.avail_min);
102 if (ready != share->ready) {
104 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
106 read(share->slave_socket, buf, 1);
108 write(share->client_socket, buf, 1);
111 write(share->slave_socket, buf, 1);
113 read(share->client_socket, buf, 1);
115 share->ready = ready;
118 pthread_mutex_unlock(&slave->mutex);
122 void sigio_handler(int sig ATTRIBUTE_UNUSED)
126 void *snd_pcm_share_slave_thread(void *data)
128 snd_pcm_share_slave_t *slave = data;
130 struct sigaction act;
131 err = snd_pcm_async(slave->pcm, SIGIO, 0);
133 act.sa_handler = sigio_handler;
134 sigemptyset(&act.sa_mask);
135 sigaddset(&act.sa_mask, SIGIO);
137 err = sigaction(SIGIO, &act, NULL);
141 snd_pcm_share_interrupt(slave);
146 /* Warning: take the mutex before to call this */
147 static void snd_pcm_share_stop(snd_pcm_t *pcm, int state)
149 snd_pcm_share_t *share = pcm->private;
150 snd_pcm_share_slave_t *slave = share->slave;
151 share->state = state;
152 gettimeofday(&share->trigger_time, 0);
153 slave->prepared_count--;
154 slave->running_count--;
155 if (slave->running_count == 0) {
156 int err = snd_pcm_drop(slave->pcm);
159 if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
160 snd_pcm_areas_copy(pcm->running_areas, 0,
161 pcm->stopped_areas, 0,
162 pcm->setup.format.channels, pcm->setup.buffer_size,
163 pcm->setup.format.sfmt);
165 share->hw_ptr = *slave->pcm->hw_ptr;
166 pcm->hw_ptr = &share->hw_ptr;
169 /* Warning: take the mutex before to call this */
170 static void snd_pcm_share_slave_forward(snd_pcm_share_slave_t *slave)
173 size_t buffer_size, boundary;
174 size_t slave_appl_ptr;
175 ssize_t frames, safety_frames;
176 size_t min_frames, max_frames;
179 avail = snd_pcm_avail_update(slave->pcm);
183 boundary = slave->pcm->setup.boundary;
184 buffer_size = slave->pcm->setup.buffer_size;
185 min_frames = buffer_size;
187 slave_appl_ptr = *slave->pcm->appl_ptr;
188 for (i = slave->clients.next; i != &slave->clients; i = i->next) {
189 snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
190 snd_pcm_t *pcm = share->pcm;
191 switch (share->state) {
192 case SND_PCM_STATE_RUNNING:
194 case SND_PCM_STATE_DRAINING:
197 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
199 a = snd_pcm_mmap_avail(pcm);
200 frames = a - share->draining_silence;
201 offset = snd_pcm_mmap_offset(pcm);
202 offset += share->draining_silence;
203 if (offset >= buffer_size)
204 offset -= buffer_size;
206 size_t f = buffer_size - offset;
207 if (f > (size_t) frames)
209 snd_pcm_areas_silence(pcm->running_areas, offset,
210 pcm->setup.format.channels,
211 f, pcm->setup.format.sfmt);
213 if (offset == buffer_size)
217 share->draining_silence = a;
218 if (a == buffer_size)
219 snd_pcm_share_stop(pcm, SND_PCM_STATE_SETUP);
225 frames = share->appl_ptr - slave_appl_ptr;
226 if (frames > (ssize_t)buffer_size)
227 frames -= pcm->setup.boundary;
228 else if (frames < -(ssize_t)pcm->setup.buffer_size)
229 frames += pcm->setup.boundary;
231 if (snd_pcm_mmap_hw_avail(pcm) <= 0 &&
232 pcm->setup.xrun_mode != SND_PCM_XRUN_NONE)
233 snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
236 if ((size_t)frames < min_frames)
238 if ((size_t)frames > max_frames)
246 /* Slave xrun prevention */
247 safety_frames = slave->safety_threshold - snd_pcm_mmap_hw_avail(slave->pcm);
248 if (safety_frames > 0 &&
249 frames < (ssize_t)safety_frames) {
250 /* Avoid to pass over the last */
251 if (max_frames < (size_t)safety_frames)
254 frames = safety_frames;
257 err = snd_pcm_mmap_forward(slave->pcm, frames);
258 assert(err == frames);
262 static int snd_pcm_share_close(snd_pcm_t *pcm)
264 snd_pcm_share_t *share = pcm->private;
265 snd_pcm_share_slave_t *slave = share->slave;
267 if (share->state == SND_PCM_STATE_RUNNING) {
268 if (pcm->mode & SND_PCM_NONBLOCK)
273 pthread_mutex_lock(&slave->mutex);
274 if (pcm->valid_setup)
275 slave->setup_count--;
277 if (slave->open_count == 0) {
278 pthread_kill(slave->thread, SIGTERM);
279 err = snd_pcm_close(slave->pcm);
280 list_del(&slave->list);
281 pthread_mutex_unlock(&slave->mutex);
282 pthread_mutex_destroy(&slave->mutex);
284 list_del(&share->list);
286 list_del(&share->list);
287 pthread_mutex_unlock(&slave->mutex);
289 close(share->client_socket);
290 close(share->slave_socket);
291 free(share->slave_channels);
296 static int snd_pcm_share_nonblock(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int nonblock ATTRIBUTE_UNUSED)
301 static int snd_pcm_share_async(snd_pcm_t *pcm, int sig, pid_t pid)
303 snd_pcm_share_t *share = pcm->private;
305 share->async_sig = sig;
307 share->async_sig = SIGIO;
309 share->async_pid = pid;
311 share->async_pid = getpid();
315 static int snd_pcm_share_info(snd_pcm_t *pcm, snd_pcm_info_t *info)
317 snd_pcm_share_t *share = pcm->private;
318 return snd_pcm_info(share->slave->pcm, info);
321 static int snd_pcm_share_params_info(snd_pcm_t *pcm, snd_pcm_params_info_t *info)
323 snd_pcm_share_t *share = pcm->private;
324 snd_pcm_share_slave_t *slave = share->slave;
326 unsigned int req_mask = info->req_mask;
327 unsigned int channels = info->req.format.channels;
328 if ((req_mask & SND_PCM_PARAMS_CHANNELS) &&
329 channels != share->channels_count) {
330 info->req.fail_mask |= SND_PCM_PARAMS_CHANNELS;
331 info->req.fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
334 info->req_mask |= SND_PCM_PARAMS_CHANNELS;
335 info->req.format.channels = slave->channels_count;
336 err = snd_pcm_params_info(slave->pcm, info);
337 info->req.format.channels = channels;
338 info->req_mask = req_mask;
339 if (slave->setup_count > 1 ||
340 (slave->setup_count == 1 && !pcm->valid_setup)) {
341 snd_pcm_setup_t *s = &slave->pcm->setup;
342 if ((req_mask & SND_PCM_PARAMS_SFMT) &&
343 info->req.format.sfmt != s->format.sfmt) {
344 info->req.fail_mask |= SND_PCM_PARAMS_SFMT;
345 info->req.fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
348 info->formats = 1 << s->format.sfmt;
349 info->rates = SND_PCM_RATE_CONTINUOUS;
350 info->min_rate = info->max_rate = s->format.rate;
351 info->buffer_size = s->buffer_size;
352 info->min_fragment_size = info->max_fragment_size = s->frag_size;
353 info->min_fragments = info->max_fragments = s->frags;
354 info->fragment_align = s->frag_size;
355 info->req.fail_mask = 0;
358 info->min_channels = info->max_channels = share->channels_count;
359 if (info->flags & SND_PCM_INFO_INTERLEAVED) {
360 info->flags &= ~SND_PCM_INFO_INTERLEAVED;
361 info->flags |= SND_PCM_INFO_COMPLEX;
366 static int snd_pcm_share_mmap(snd_pcm_t *pcm)
368 snd_pcm_share_t *share = pcm->private;
369 snd_pcm_share_slave_t *slave = share->slave;
370 snd_pcm_mmap_info_t *i;
372 pthread_mutex_lock(&slave->mutex);
373 if (slave->mmap_count == 0) {
374 err = snd_pcm_mmap(slave->pcm);
376 pthread_mutex_unlock(&slave->mutex);
379 if (slave->pcm->stream == SND_PCM_STREAM_PLAYBACK)
380 snd_pcm_areas_silence(slave->pcm->running_areas, 0, slave->pcm->setup.format.channels, slave->pcm->setup.buffer_size, slave->pcm->setup.format.sfmt);
383 pthread_mutex_unlock(&slave->mutex);
384 pcm->mmap_info_count = slave->pcm->mmap_info_count + 1;
385 pcm->mmap_info = malloc(pcm->mmap_info_count * sizeof(*pcm->mmap_info));
388 memcpy(pcm->mmap_info, slave->pcm->mmap_info, slave->pcm->mmap_info_count * sizeof(*pcm->mmap_info));
389 i = &pcm->mmap_info[slave->pcm->mmap_info_count];
390 i->type = SND_PCM_MMAP_USER;
391 i->size = snd_pcm_frames_to_bytes(pcm, pcm->setup.buffer_size);
392 share->stopped_data = malloc(i->size);
393 if (share->stopped_data == 0) {
394 free(pcm->mmap_info);
398 i->addr = share->stopped_data;
402 static int snd_pcm_share_munmap(snd_pcm_t *pcm ATTRIBUTE_UNUSED)
404 snd_pcm_share_t *share = pcm->private;
405 snd_pcm_share_slave_t *slave = share->slave;
407 pthread_mutex_lock(&slave->mutex);
409 if (slave->mmap_count == 0) {
410 err = snd_pcm_munmap(slave->pcm);
412 pthread_mutex_unlock(&slave->mutex);
416 pthread_mutex_unlock(&slave->mutex);
417 free(pcm->mmap_info);
418 pcm->mmap_info_count = 0;
420 free(share->stopped_data);
424 static int snd_pcm_share_params(snd_pcm_t *pcm, snd_pcm_params_t *params)
426 snd_pcm_share_t *share = pcm->private;
427 snd_pcm_share_slave_t *slave = share->slave;
428 unsigned int channels = params->format.channels;
430 if (channels != share->channels_count) {
431 params->fail_mask = SND_PCM_PARAMS_CHANNELS;
432 params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
433 ERR("channels requested (%d) differs from configuration (%ld)", channels, (long)share->channels_count);
436 share->xfer_mode = params->xfer_mode;
437 share->xrun_mode = params->xrun_mode;
438 pthread_mutex_lock(&slave->mutex);
439 if (slave->setup_count > 1 ||
440 (slave->setup_count == 1 && !pcm->valid_setup)) {
441 snd_pcm_setup_t *s = &slave->pcm->setup;
442 if (params->format.sfmt != s->format.sfmt) {
443 ERR("slave is already running with different format");
444 params->fail_mask |= SND_PCM_PARAMS_SFMT;
446 if (params->fail_mask) {
447 params->fail_reason = SND_PCM_PARAMS_FAIL_INVAL;
452 snd_pcm_params_t sp = *params;
453 sp.xfer_mode = SND_PCM_XFER_UNSPECIFIED;
454 sp.xrun_mode = SND_PCM_XRUN_NONE;
455 sp.format.channels = slave->channels_count;
456 err = snd_pcm_params(slave->pcm, &sp);
460 share->state = SND_PCM_STATE_SETUP;
461 slave->setup_count++;
463 pthread_mutex_unlock(&slave->mutex);
467 static int snd_pcm_share_setup(snd_pcm_t *pcm, snd_pcm_setup_t *setup)
469 snd_pcm_share_t *share = pcm->private;
470 snd_pcm_share_slave_t *slave = share->slave;
472 err = snd_pcm_setup(slave->pcm, setup);
475 setup->xrun_mode = share->xrun_mode;
476 setup->format.channels = share->channels_count;
477 if (share->xfer_mode == SND_PCM_XFER_UNSPECIFIED)
478 setup->xfer_mode = SND_PCM_XFER_NONINTERLEAVED;
480 setup->xfer_mode = share->xfer_mode;
481 if (setup->mmap_shape != SND_PCM_MMAP_INTERLEAVED)
482 setup->mmap_shape = SND_PCM_MMAP_COMPLEX;
486 static int snd_pcm_share_status(snd_pcm_t *pcm, snd_pcm_status_t *status)
488 snd_pcm_share_t *share = pcm->private;
489 snd_pcm_share_slave_t *slave = share->slave;
491 ssize_t sd = 0, d = 0;
492 pthread_mutex_lock(&slave->mutex);
493 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
494 status->avail = snd_pcm_mmap_playback_avail(pcm);
495 if (share->state != SND_PCM_STATE_RUNNING &&
496 share->state != SND_PCM_STATE_DRAINING)
498 d = pcm->setup.buffer_size - status->avail;
500 status->avail = snd_pcm_mmap_capture_avail(pcm);
501 if (share->state != SND_PCM_STATE_RUNNING)
505 err = snd_pcm_delay(slave->pcm, &sd);
509 status->delay = sd + d;
510 status->state = share->state;
511 status->trigger_time = share->trigger_time;
513 pthread_mutex_unlock(&slave->mutex);
517 static int snd_pcm_share_state(snd_pcm_t *pcm)
519 snd_pcm_share_t *share = pcm->private;
523 static int snd_pcm_share_delay(snd_pcm_t *pcm, ssize_t *delayp)
525 snd_pcm_share_t *share = pcm->private;
526 snd_pcm_share_slave_t *slave = share->slave;
529 pthread_mutex_lock(&slave->mutex);
530 switch (share->state) {
531 case SND_PCM_STATE_XRUN:
534 case SND_PCM_STATE_RUNNING:
536 case SND_PCM_STATE_DRAINING:
537 if (pcm->stream == SND_PCM_STREAM_PLAYBACK)
544 err = snd_pcm_delay(slave->pcm, &sd);
547 *delayp = sd + snd_pcm_mmap_delay(pcm);
549 pthread_mutex_unlock(&slave->mutex);
553 static ssize_t snd_pcm_share_avail_update(snd_pcm_t *pcm)
555 snd_pcm_share_t *share = pcm->private;
556 snd_pcm_share_slave_t *slave = share->slave;
558 pthread_mutex_lock(&slave->mutex);
559 ret = snd_pcm_avail_update(slave->pcm);
562 for (i = slave->clients.next; i != &slave->clients; i = i->next) {
563 snd_pcm_share_t *share = list_entry(i, snd_pcm_share_t, list);
564 snd_pcm_t *pcm = share->pcm;
565 if (share->state == SND_PCM_STATE_RUNNING &&
566 pcm->setup.xrun_mode != SND_PCM_XRUN_NONE)
567 snd_pcm_share_stop(pcm, SND_PCM_STATE_XRUN);
570 pthread_mutex_unlock(&slave->mutex);
572 ret = snd_pcm_mmap_avail(pcm);
573 if ((size_t)ret > pcm->setup.buffer_size)
579 /* Call it with mutex held */
580 static ssize_t _snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size)
582 snd_pcm_share_t *share = pcm->private;
583 snd_pcm_share_slave_t *slave = share->slave;
586 if (pcm->stream == SND_PCM_STREAM_PLAYBACK &&
587 share->state == SND_PCM_STATE_RUNNING) {
588 frames = *slave->pcm->appl_ptr - share->appl_ptr;
589 if (frames > (ssize_t)pcm->setup.buffer_size)
590 frames -= pcm->setup.boundary;
591 else if (frames < -(ssize_t)pcm->setup.buffer_size)
592 frames += pcm->setup.boundary;
595 ret = snd_pcm_rewind(slave->pcm, frames);
601 snd_pcm_mmap_appl_forward(pcm, size);
602 snd_pcm_share_slave_forward(share->slave);
606 static ssize_t snd_pcm_share_mmap_forward(snd_pcm_t *pcm, size_t size)
608 snd_pcm_share_t *share = pcm->private;
609 snd_pcm_share_slave_t *slave = share->slave;
611 pthread_mutex_lock(&slave->mutex);
612 ret = _snd_pcm_share_mmap_forward(pcm, size);
613 pthread_mutex_unlock(&slave->mutex);
617 static int snd_pcm_share_prepare(snd_pcm_t *pcm)
619 snd_pcm_share_t *share = pcm->private;
620 snd_pcm_share_slave_t *slave = share->slave;
622 pthread_mutex_lock(&slave->mutex);
623 if (slave->prepared_count == 0) {
624 err = snd_pcm_prepare(slave->pcm);
628 slave->prepared_count++;
631 share->state = SND_PCM_STATE_PREPARED;
633 pthread_mutex_unlock(&slave->mutex);
637 static int snd_pcm_share_start(snd_pcm_t *pcm)
639 snd_pcm_share_t *share = pcm->private;
640 snd_pcm_share_slave_t *slave = share->slave;
642 if (share->state != SND_PCM_STATE_PREPARED)
644 pthread_mutex_lock(&slave->mutex);
645 share->state = SND_PCM_STATE_RUNNING;
646 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
647 size_t hw_avail = snd_pcm_mmap_playback_hw_avail(pcm);
652 if (slave->running_count) {
654 err = snd_pcm_delay(slave->pcm, &sd);
657 err = snd_pcm_rewind(slave->pcm, sd);
661 assert(share->hw_ptr == 0);
662 /* Share the same hw_ptr of slave */
663 pcm->hw_ptr = slave->pcm->hw_ptr;
664 share->appl_ptr = *slave->pcm->appl_ptr;
665 snd_pcm_areas_copy(pcm->stopped_areas, 0,
666 pcm->running_areas, snd_pcm_mmap_offset(pcm),
667 pcm->setup.format.channels, hw_avail,
668 pcm->setup.format.sfmt);
669 _snd_pcm_share_mmap_forward(pcm, pcm->setup.buffer_size);
671 if (slave->running_count == 0) {
672 err = snd_pcm_start(slave->pcm);
676 slave->running_count++;
677 gettimeofday(&share->trigger_time, 0);
679 pthread_mutex_unlock(&slave->mutex);
683 static int snd_pcm_share_drop(snd_pcm_t *pcm)
685 snd_pcm_share_t *share = pcm->private;
686 snd_pcm_share_slave_t *slave = share->slave;
688 pthread_mutex_lock(&slave->mutex);
689 switch (share->state) {
690 case SND_PCM_STATE_OPEN:
693 case SND_PCM_STATE_SETUP:
695 case SND_PCM_STATE_DRAINING:
696 if (pcm->stream == SND_PCM_STREAM_CAPTURE) {
697 share->state = SND_PCM_STATE_SETUP;
701 case SND_PCM_STATE_RUNNING:
702 snd_pcm_share_stop(pcm, SND_PCM_STATE_SETUP);
704 case SND_PCM_STATE_PREPARED:
705 case SND_PCM_STATE_XRUN:
706 share->state = SND_PCM_STATE_SETUP;
710 if (slave->running_count > 0 &&
711 pcm->stream == SND_PCM_STREAM_PLAYBACK) {
713 err = snd_pcm_delay(pcm, &delay);
717 err = snd_pcm_rewind(pcm, delay);
721 snd_pcm_areas_silence(pcm->running_areas, 0, pcm->setup.format.channels,
722 pcm->setup.buffer_size, pcm->setup.format.sfmt);
723 snd_pcm_mmap_forward(pcm, pcm->setup.buffer_size);
725 share->appl_ptr = share->hw_ptr = 0;
727 pthread_mutex_unlock(&slave->mutex);
731 static int snd_pcm_share_drain(snd_pcm_t *pcm)
733 snd_pcm_share_t *share = pcm->private;
734 snd_pcm_share_slave_t *slave = share->slave;
736 pthread_mutex_lock(&slave->mutex);
737 switch (share->state) {
738 case SND_PCM_STATE_OPEN:
741 case SND_PCM_STATE_PREPARED:
742 share->state = SND_PCM_STATE_SETUP;
744 case SND_PCM_STATE_SETUP:
745 case SND_PCM_STATE_DRAINING:
747 case SND_PCM_STATE_XRUN:
748 if (pcm->stream == SND_PCM_STREAM_PLAYBACK) {
749 share->state = SND_PCM_STATE_SETUP;
753 case SND_PCM_STATE_RUNNING:
754 if (snd_pcm_mmap_avail(pcm) <= 0) {
755 share->state = SND_PCM_STATE_SETUP;
758 share->draining_silence = 0;
759 share->state = SND_PCM_STATE_DRAINING;
763 pthread_mutex_unlock(&slave->mutex);
767 static int snd_pcm_share_pause(snd_pcm_t *pcm ATTRIBUTE_UNUSED, int enable ATTRIBUTE_UNUSED)
772 static int snd_pcm_share_channel_info(snd_pcm_t *pcm, snd_pcm_channel_info_t *info)
774 snd_pcm_share_t *share = pcm->private;
775 snd_pcm_share_slave_t *slave = share->slave;
776 unsigned int channel = info->channel;
777 int c = share->slave_channels[channel];
780 err = snd_pcm_channel_info(slave->pcm, info);
781 info->channel = channel;
785 static int snd_pcm_share_channel_params(snd_pcm_t *pcm, snd_pcm_channel_params_t *params)
787 snd_pcm_share_t *share = pcm->private;
788 snd_pcm_share_slave_t *slave = share->slave;
789 unsigned int channel = params->channel;
790 int c = share->slave_channels[channel];
793 err = snd_pcm_channel_params(slave->pcm, params);
794 params->channel = channel;
798 static int snd_pcm_share_channel_setup(snd_pcm_t *pcm, snd_pcm_channel_setup_t *setup)
800 snd_pcm_share_t *share = pcm->private;
801 snd_pcm_share_slave_t *slave = share->slave;
802 unsigned int channel = setup->channel;
803 int c = share->slave_channels[channel];
806 err = snd_pcm_channel_setup(slave->pcm, setup);
807 setup->channel = channel;
812 switch (pcm->setup.mmap_shape) {
813 case SND_PCM_MMAP_INTERLEAVED:
814 case SND_PCM_MMAP_COMPLEX:
815 setup->stopped_area.addr = share->stopped_data;
816 setup->stopped_area.first = channel * pcm->bits_per_sample;
817 setup->stopped_area.step = pcm->bits_per_frame;
819 case SND_PCM_MMAP_NONINTERLEAVED:
820 setup->stopped_area.addr = share->stopped_data + c * pcm->setup.buffer_size * pcm->bits_per_sample / 8;
821 setup->stopped_area.first = 0;
822 setup->stopped_area.step = pcm->bits_per_sample;
830 static ssize_t snd_pcm_share_rewind(snd_pcm_t *pcm, size_t frames)
832 snd_pcm_share_t *share = pcm->private;
833 snd_pcm_share_slave_t *slave = share->slave;
836 switch (share->state) {
837 case SND_PCM_STATE_RUNNING:
839 case SND_PCM_STATE_PREPARED:
840 if (pcm->stream != SND_PCM_STREAM_PLAYBACK)
843 case SND_PCM_STATE_DRAINING:
844 if (pcm->stream != SND_PCM_STREAM_CAPTURE)
847 case SND_PCM_STATE_XRUN:
852 n = snd_pcm_mmap_hw_avail(pcm);
855 if ((size_t)n > frames)
859 if (share->state == SND_PCM_STATE_RUNNING &&
861 pthread_mutex_lock(&slave->mutex);
862 ret = snd_pcm_rewind(slave->pcm, frames);
863 pthread_mutex_unlock(&slave->mutex);
872 snd_pcm_mmap_appl_backward(pcm, n);
878 static int snd_pcm_share_channels_mask(snd_pcm_t *pcm, bitset_t *cmask)
880 snd_pcm_share_t *share = pcm->private;
881 snd_pcm_share_slave_t *slave = share->slave;
883 bitset_t m[bitset_size(slave->channels_count)];
884 int err = snd_pcm_channels_mask(slave->pcm, m);
887 for (i = 0; i < share->channels_count; ++i) {
888 if (!bitset_get(m, share->slave_channels[i]))
889 bitset_reset(cmask, i);
894 int snd_pcm_share_poll_descriptor(snd_pcm_t *pcm)
896 snd_pcm_share_t *share = pcm->private;
897 return share->client_socket;
900 static void snd_pcm_share_dump(snd_pcm_t *pcm, FILE *fp)
902 snd_pcm_share_t *share = pcm->private;
903 snd_pcm_share_slave_t *slave = share->slave;
905 fprintf(fp, "Share PCM\n");
906 fprintf(fp, "\nChannel bindings:\n");
907 for (k = 0; k < share->channels_count; ++k)
908 fprintf(fp, "%d: %d\n", k, share->slave_channels[k]);
909 if (pcm->valid_setup) {
910 fprintf(fp, "\nIts setup is:\n");
911 snd_pcm_dump_setup(pcm, fp);
913 fprintf(fp, "Slave: ");
914 snd_pcm_dump(slave->pcm, fp);
917 snd_pcm_ops_t snd_pcm_share_ops = {
918 close: snd_pcm_share_close,
919 info: snd_pcm_share_info,
920 params_info: snd_pcm_share_params_info,
921 params: snd_pcm_share_params,
922 setup: snd_pcm_share_setup,
923 channel_info: snd_pcm_share_channel_info,
924 channel_params: snd_pcm_share_channel_params,
925 channel_setup: snd_pcm_share_channel_setup,
926 dump: snd_pcm_share_dump,
927 nonblock: snd_pcm_share_nonblock,
928 async: snd_pcm_share_async,
929 mmap: snd_pcm_share_mmap,
930 munmap: snd_pcm_share_munmap,
933 snd_pcm_fast_ops_t snd_pcm_share_fast_ops = {
934 status: snd_pcm_share_status,
935 state: snd_pcm_share_state,
936 delay: snd_pcm_share_delay,
937 prepare: snd_pcm_share_prepare,
938 start: snd_pcm_share_start,
939 drop: snd_pcm_share_drop,
940 drain: snd_pcm_share_drain,
941 pause: snd_pcm_share_pause,
942 writei: snd_pcm_mmap_writei,
943 writen: snd_pcm_mmap_writen,
944 readi: snd_pcm_mmap_readi,
945 readn: snd_pcm_mmap_readn,
946 rewind: snd_pcm_share_rewind,
947 channels_mask: snd_pcm_share_channels_mask,
948 avail_update: snd_pcm_share_avail_update,
949 mmap_forward: snd_pcm_share_mmap_forward,
952 int snd_pcm_share_open(snd_pcm_t **pcmp, char *name, char *sname,
953 size_t schannels_count,
954 size_t channels_count, int *channels_map,
955 int stream, int mode)
958 snd_pcm_share_t *share;
961 char slave_map[32] = { 0 };
963 snd_pcm_share_slave_t *slave = NULL;
967 assert(channels_count > 0 && sname && channels_map);
969 for (k = 0; k < channels_count; ++k) {
970 if (channels_map[k] < 0 || channels_map[k] > 31) {
971 ERR("Invalid slave channel (%d) in binding", channels_map[k]);
974 if (slave_map[channels_map[k]]) {
975 ERR("Repeated slave channel (%d) in binding", channels_map[k]);
978 slave_map[channels_map[k]] = 1;
979 assert((unsigned)channels_map[k] < schannels_count);
982 share = calloc(1, sizeof(snd_pcm_share_t));
986 share->channels_count = channels_count;
987 share->slave_channels = calloc(channels_count, sizeof(*share->slave_channels));
988 if (!share->slave_channels) {
992 memcpy(share->slave_channels, channels_map, channels_count * sizeof(*share->slave_channels));
994 pcm = calloc(1, sizeof(snd_pcm_t));
996 free(share->slave_channels);
1000 err = socketpair(AF_LOCAL, SOCK_STREAM, 0, sd);
1001 if (err >= 0 && stream == SND_PCM_STREAM_PLAYBACK) {
1003 err = setsockopt(sd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(bufsize));
1007 pfd.events = POLLOUT;
1008 while ((err = poll(&pfd, 1, 0)) == 1) {
1010 err = write(sd[0], buf, 1);
1020 free(share->slave_channels);
1025 pthread_mutex_lock(&slaves_mutex);
1026 for (i = slaves.next; i != &slaves; i = i->next) {
1027 snd_pcm_share_slave_t *s = list_entry(i, snd_pcm_share_slave_t, list);
1028 if (s->pcm->name && strcmp(s->pcm->name, sname)) {
1035 err = snd_pcm_open(&spcm, sname, stream, mode);
1037 pthread_mutex_unlock(&slaves_mutex);
1041 free(share->slave_channels);
1045 slave = calloc(1, sizeof(*slave));
1047 pthread_mutex_unlock(&slaves_mutex);
1048 snd_pcm_close(spcm);
1052 free(share->slave_channels);
1056 INIT_LIST_HEAD(&slave->clients);
1058 slave->channels_count = schannels_count;
1059 pthread_mutex_init(&slave->mutex, NULL);
1060 list_add_tail(&slave->list, &slaves);
1062 pthread_mutex_unlock(&slaves_mutex);
1064 pthread_mutex_lock(&slave->mutex);
1065 if (slave->open_count == 0) {
1066 err = pthread_create(&slave->thread, NULL, snd_pcm_share_slave_thread, slave);
1069 slave->open_count++;
1070 list_add_tail(&share->list, &slave->clients);
1071 pthread_mutex_unlock(&slave->mutex);
1073 share->slave = slave;
1075 share->client_socket = sd[0];
1076 share->slave_socket = sd[1];
1077 share->async_sig = SIGIO;
1078 share->async_pid = getpid();
1081 pcm->name = strdup(name);
1082 pcm->type = SND_PCM_TYPE_SHARE;
1083 pcm->stream = stream;
1086 pcm->ops = &snd_pcm_share_ops;
1088 pcm->fast_ops = &snd_pcm_share_fast_ops;
1089 pcm->fast_op_arg = pcm;
1090 pcm->private = share;
1091 pcm->poll_fd = share->client_socket;
1092 pcm->hw_ptr = &share->hw_ptr;
1093 pcm->appl_ptr = &share->appl_ptr;
1098 int _snd_pcm_share_open(snd_pcm_t **pcmp, char *name, snd_config_t *conf,
1099 int stream, int mode)
1101 snd_config_iterator_t i;
1103 snd_config_t *binding = NULL;
1107 size_t channels_count = 0;
1108 long schannels_count = -1;
1109 size_t schannel_max = 0;
1110 snd_config_foreach(i, conf) {
1111 snd_config_t *n = snd_config_entry(i);
1112 if (strcmp(n->id, "comment") == 0)
1114 if (strcmp(n->id, "type") == 0)
1116 if (strcmp(n->id, "stream") == 0)
1118 if (strcmp(n->id, "sname") == 0) {
1119 err = snd_config_string_get(n, &sname);
1121 ERR("Invalid type for sname");
1126 if (strcmp(n->id, "schannels") == 0) {
1127 err = snd_config_integer_get(n, &schannels_count);
1129 ERR("Invalid type for schannels");
1134 if (strcmp(n->id, "binding") == 0) {
1135 if (snd_config_type(n) != SND_CONFIG_TYPE_COMPOUND) {
1136 ERR("Invalid type for binding");
1142 ERR("Unknown field: %s", n->id);
1146 ERR("sname is not defined");
1150 ERR("binding is not defined");
1153 snd_config_foreach(i, binding) {
1156 snd_config_t *n = snd_config_entry(i);
1158 cchannel = strtol(n->id, &p, 10);
1159 if (errno || *p || cchannel < 0) {
1160 ERR("Invalid client channel in binding: %s", n->id);
1163 if ((unsigned)cchannel > channels_count)
1164 channels_count = cchannel + 1;
1166 if (channels_count == 0) {
1167 ERR("No bindings defined");
1170 channels_map = calloc(channels_count, sizeof(*channels_map));
1171 for (idx = 0; idx < channels_count; ++idx)
1172 channels_map[idx] = -1;
1174 snd_config_foreach(i, binding) {
1175 snd_config_t *n = snd_config_entry(i);
1178 cchannel = strtol(n->id, 0, 10);
1179 err = snd_config_integer_get(n, &schannel);
1182 assert(schannels_count <= 0 || schannel < schannels_count);
1183 channels_map[cchannel] = schannel;
1184 if ((unsigned)schannel > schannel_max)
1185 schannel_max = schannel;
1187 if (schannels_count <= 0)
1188 schannels_count = schannel_max + 1;
1189 err = snd_pcm_share_open(pcmp, name, sname, schannels_count,
1190 channels_count, channels_map, stream, mode);