4 * ALSA <-> PulseAudio PCM I/O plugin
6 * Copyright (c) 2006 by Pierre Ossman <ossman@cendio.se>
8 * This library is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License as
10 * published by the Free Software Foundation; either version 2.1 of
11 * the License, or (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include <alsa/asoundlib.h>
27 #include <alsa/pcm_external.h>
31 typedef struct snd_pcm_pulse {
38 /* Since ALSA expects a ring buffer we must do some voodoo. */
51 pa_buffer_attr buffer_attr;
54 static int check_stream(snd_pcm_pulse_t *pcm)
57 pa_stream_state_t state;
64 err = pulse_check_connection(pcm->p);
71 state = pa_stream_get_state(pcm->stream);
72 if (!PA_STREAM_IS_GOOD(state))
80 static int update_ptr(snd_pcm_pulse_t *pcm)
84 if (pcm->io.stream == SND_PCM_STREAM_PLAYBACK)
85 size = pa_stream_writable_size(pcm->stream);
87 size = pa_stream_readable_size(pcm->stream);
89 if (size == (size_t) -1)
92 if (pcm->io.stream == SND_PCM_STREAM_CAPTURE)
95 /* Prevent accidental overrun of the fake ringbuffer */
96 if (size > pcm->buffer_attr.tlength - pcm->frame_size)
97 size = pcm->buffer_attr.tlength - pcm->frame_size;
99 if (size > pcm->last_size) {
100 pcm->ptr += size - pcm->last_size;
101 pcm->ptr %= pcm->buffer_attr.tlength;
104 pcm->last_size = size;
108 static int check_active(snd_pcm_pulse_t *pcm) {
112 * ALSA thinks in periods, not bytes, samples or frames.
115 if (pcm->io.stream == SND_PCM_STREAM_PLAYBACK) {
118 wsize = pa_stream_writable_size(pcm->stream);
120 if (wsize == (size_t) -1)
123 return wsize >= pcm->buffer_attr.minreq;
127 rsize = pa_stream_readable_size(pcm->stream);
129 if (rsize == (size_t) -1)
132 return rsize >= pcm->buffer_attr.fragsize;
136 static int update_active(snd_pcm_pulse_t *pcm) {
144 ret = check_stream(pcm);
148 ret = check_active(pcm);
152 if (ret != 0) /* On error signal the caller, too */
153 pulse_poll_activate(pcm->p);
155 pulse_poll_deactivate(pcm->p);
160 static int wait_stream_state(snd_pcm_pulse_t *pcm, pa_stream_state_t target)
162 pa_stream_state_t state;
172 err = pulse_check_connection(pcm->p);
179 state = pa_stream_get_state(pcm->stream);
183 if (!PA_STREAM_IS_GOOD(state))
186 pa_threaded_mainloop_wait(pcm->p->mainloop);
192 static void stream_success_cb(pa_stream * p, int success, void *userdata)
194 snd_pcm_pulse_t *pcm = userdata;
201 pa_threaded_mainloop_signal(pcm->p->mainloop, 0);
204 static int pulse_start(snd_pcm_ioplug_t * io)
206 snd_pcm_pulse_t *pcm = io->private_data;
208 int err = 0, err_o = 0, err_u = 0;
212 if (!pcm->p || !pcm->p->mainloop)
215 pa_threaded_mainloop_lock(pcm->p->mainloop);
217 err = check_stream(pcm);
221 o = pa_stream_cork(pcm->stream, 0, stream_success_cb, pcm);
227 u = pa_stream_trigger(pcm->stream, stream_success_cb, pcm);
230 err_o = pulse_wait_operation(pcm->p, o);
232 err_u = pulse_wait_operation(pcm->p, u);
234 pa_operation_unref(o);
236 pa_operation_unref(u);
238 if (err_o < 0 || err_u < 0) {
244 pa_threaded_mainloop_unlock(pcm->p->mainloop);
249 static int pulse_stop(snd_pcm_ioplug_t * io)
251 snd_pcm_pulse_t *pcm = io->private_data;
253 int err = 0, err_o = 0, err_u = 0;
257 if (!pcm->p || !pcm->p->mainloop)
260 pa_threaded_mainloop_lock(pcm->p->mainloop);
262 err = check_stream(pcm);
266 o = pa_stream_cork(pcm->stream, 1, stream_success_cb, pcm);
272 u = pa_stream_flush(pcm->stream, stream_success_cb, pcm);
274 pa_operation_unref(o);
279 err_o = pulse_wait_operation(pcm->p, o);
280 err_u = pulse_wait_operation(pcm->p, u);
282 pa_operation_unref(o);
283 pa_operation_unref(u);
285 if (err_o < 0 || err_u < 0) {
291 pa_threaded_mainloop_unlock(pcm->p->mainloop);
296 static int pulse_drain(snd_pcm_ioplug_t * io)
298 snd_pcm_pulse_t *pcm = io->private_data;
304 if (!pcm->p || !pcm->p->mainloop)
307 pa_threaded_mainloop_lock(pcm->p->mainloop);
309 err = check_stream(pcm);
313 o = pa_stream_drain(pcm->stream, stream_success_cb, pcm);
319 err = pulse_wait_operation(pcm->p, o);
321 pa_operation_unref(o);
329 pa_threaded_mainloop_unlock(pcm->p->mainloop);
334 static snd_pcm_sframes_t pulse_pointer(snd_pcm_ioplug_t * io)
336 snd_pcm_pulse_t *pcm = io->private_data;
337 snd_pcm_sframes_t ret = 0;
341 if (!pcm->p || !pcm->p->mainloop)
344 if (io->state == SND_PCM_STATE_XRUN)
347 if (io->state != SND_PCM_STATE_RUNNING)
350 pa_threaded_mainloop_lock(pcm->p->mainloop);
352 ret = check_stream(pcm);
361 ret = update_ptr(pcm);
370 ret = snd_pcm_bytes_to_frames(io->pcm, pcm->ptr);
374 pa_threaded_mainloop_unlock(pcm->p->mainloop);
379 static int pulse_delay(snd_pcm_ioplug_t * io, snd_pcm_sframes_t * delayp)
381 snd_pcm_pulse_t *pcm = io->private_data;
387 if (!pcm->p || !pcm->p->mainloop)
390 pa_threaded_mainloop_lock(pcm->p->mainloop);
393 err = check_stream(pcm);
397 err = pa_stream_get_latency(pcm->stream, &lat, NULL);
399 if (err != PA_ERR_NODATA) {
406 pa_threaded_mainloop_wait(pcm->p->mainloop);
410 snd_pcm_bytes_to_frames(io->pcm,
411 pa_usec_to_bytes(lat, &pcm->ss));
417 if (pcm->underrun && pcm->io.state == SND_PCM_STATE_RUNNING)
418 snd_pcm_ioplug_set_state(io, SND_PCM_STATE_XRUN);
420 pa_threaded_mainloop_unlock(pcm->p->mainloop);
425 static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io,
426 const snd_pcm_channel_area_t * areas,
427 snd_pcm_uframes_t offset,
428 snd_pcm_uframes_t size)
430 snd_pcm_pulse_t *pcm = io->private_data;
432 snd_pcm_sframes_t ret = 0;
437 if (!pcm->p || !pcm->p->mainloop)
440 pa_threaded_mainloop_lock(pcm->p->mainloop);
442 ret = check_stream(pcm);
446 /* Make sure the buffer pointer is in sync */
447 ret = update_ptr(pcm);
452 (char *) areas->addr + (areas->first +
453 areas->step * offset) / 8;
455 writebytes = size * pcm->frame_size;
456 ret = pa_stream_write(pcm->stream, buf, writebytes, NULL, 0, 0);
462 /* Make sure the buffer pointer is in sync */
463 pcm->last_size -= writebytes;
464 pcm->written += writebytes;
465 ret = update_ptr(pcm);
470 ret = update_active(pcm);
478 pa_threaded_mainloop_unlock(pcm->p->mainloop);
483 static snd_pcm_sframes_t pulse_read(snd_pcm_ioplug_t * io,
484 const snd_pcm_channel_area_t * areas,
485 snd_pcm_uframes_t offset,
486 snd_pcm_uframes_t size)
488 snd_pcm_pulse_t *pcm = io->private_data;
490 size_t remain_size, frag_length;
491 snd_pcm_sframes_t ret = 0;
495 if (!pcm->p || !pcm->p->mainloop)
498 pa_threaded_mainloop_lock(pcm->p->mainloop);
500 ret = check_stream(pcm);
504 /* Make sure the buffer pointer is in sync */
505 ret = update_ptr(pcm);
509 remain_size = size * pcm->frame_size;
512 (char *) areas->addr + (areas->first +
513 areas->step * offset) / 8;
514 while (remain_size > 0) {
517 if (pa_stream_peek(pcm->stream, &src_buf, &frag_length) < 0) {
522 if (frag_length == 0)
526 src_buf = (char *) src_buf + pcm->offset;
527 frag_length -= pcm->offset;
529 if (frag_length > remain_size) {
530 pcm->offset += remain_size;
531 frag_length = remain_size;
535 memcpy(dst_buf, src_buf, frag_length);
537 /* If there is a hole in the stream, generate silence. */
538 int sample_size = snd_pcm_format_physical_width(io->format) / 8;
539 snd_pcm_format_set_silence(io->format, dst_buf, frag_length / sample_size);
542 if (pcm->offset == 0)
543 pa_stream_drop(pcm->stream);
545 dst_buf = (char *) dst_buf + frag_length;
546 remain_size -= frag_length;
547 pcm->last_size -= frag_length;
550 /* Make sure the buffer pointer is in sync */
551 ret = update_ptr(pcm);
555 ret = update_active(pcm);
559 ret = size - (remain_size / pcm->frame_size);
562 pa_threaded_mainloop_unlock(pcm->p->mainloop);
567 static void stream_state_cb(pa_stream * p, void *userdata)
569 snd_pcm_pulse_t *pcm = userdata;
570 pa_stream_state_t state;
577 state = pa_stream_get_state(p);
578 if (!PA_STREAM_IS_GOOD(state))
579 pulse_poll_activate(pcm->p);
581 pa_threaded_mainloop_signal(pcm->p->mainloop, 0);
584 static void stream_request_cb(pa_stream * p, size_t length, void *userdata)
586 snd_pcm_pulse_t *pcm = userdata;
596 #ifndef PA_CHECK_VERSION
597 #define PA_CHECK_VERSION(x, y, z) 0
600 #if PA_CHECK_VERSION(0,99,0)
601 #define DEFAULT_HANDLE_UNDERRUN 1
602 #define do_underrun_detect(pcm, p) \
603 ((pcm)->written <= pa_stream_get_underflow_index(p))
605 #define DEFAULT_HANDLE_UNDERRUN 0
606 #define do_underrun_detect(pcm, p) 1 /* always true */
609 static void stream_underrun_cb(pa_stream * p, void *userdata)
611 snd_pcm_pulse_t *pcm = userdata;
618 if (do_underrun_detect(pcm, p))
622 static void stream_latency_cb(pa_stream *p, void *userdata) {
623 snd_pcm_pulse_t *pcm = userdata;
630 pa_threaded_mainloop_signal(pcm->p->mainloop, 0);
633 static int pulse_pcm_poll_revents(snd_pcm_ioplug_t * io,
634 struct pollfd *pfd, unsigned int nfds,
635 unsigned short *revents)
638 snd_pcm_pulse_t *pcm = io->private_data;
642 if (!pcm->p || !pcm->p->mainloop)
645 pa_threaded_mainloop_lock(pcm->p->mainloop);
647 err = check_stream(pcm);
651 err = check_active(pcm);
656 *revents = io->stream == SND_PCM_STREAM_PLAYBACK ? POLLOUT : POLLIN;
664 pa_threaded_mainloop_unlock(pcm->p->mainloop);
669 static int pulse_prepare(snd_pcm_ioplug_t * io)
672 snd_pcm_pulse_t *pcm = io->private_data;
678 if (!pcm->p || !pcm->p->mainloop)
681 pa_threaded_mainloop_lock(pcm->p->mainloop);
684 pa_stream_disconnect(pcm->stream);
685 wait_stream_state(pcm, PA_STREAM_TERMINATED);
686 pa_stream_unref(pcm->stream);
690 err = pulse_check_connection(pcm->p);
694 assert(pcm->stream == NULL);
696 for (c = pcm->ss.channels; c > 0; c--)
697 if (pa_channel_map_init_auto(&map, c, PA_CHANNEL_MAP_ALSA))
700 /* Extend if nessary */
701 for (d = c; d < pcm->ss.channels; d++)
702 map.map[d] = PA_CHANNEL_POSITION_AUX0+(d-c);
704 map.channels = pcm->ss.channels;
706 if (io->stream == SND_PCM_STREAM_PLAYBACK)
708 pa_stream_new(pcm->p->context, "ALSA Playback", &pcm->ss, &map);
711 pa_stream_new(pcm->p->context, "ALSA Capture", &pcm->ss, &map);
718 pa_stream_set_state_callback(pcm->stream, stream_state_cb, pcm);
719 pa_stream_set_latency_update_callback(pcm->stream, stream_latency_cb, pcm);
721 if (io->stream == SND_PCM_STREAM_PLAYBACK) {
722 pa_stream_set_write_callback(pcm->stream,
723 stream_request_cb, pcm);
724 if (pcm->handle_underrun)
725 pa_stream_set_underflow_callback(pcm->stream,
726 stream_underrun_cb, pcm);
727 r = pa_stream_connect_playback(pcm->stream, pcm->device,
729 PA_STREAM_AUTO_TIMING_UPDATE |
730 PA_STREAM_INTERPOLATE_TIMING
731 #ifdef PA_STREAM_EARLY_REQUESTS
732 | PA_STREAM_EARLY_REQUESTS
736 pa_stream_set_read_callback(pcm->stream, stream_request_cb,
738 r = pa_stream_connect_record(pcm->stream, pcm->device,
740 PA_STREAM_AUTO_TIMING_UPDATE |
741 PA_STREAM_INTERPOLATE_TIMING
742 #ifdef PA_STREAM_EARLY_REQUESTS
743 | PA_STREAM_EARLY_REQUESTS
749 SNDERR("PulseAudio: Unable to create stream: %s\n", pa_strerror(pa_context_errno(pcm->p->context)));
750 pa_stream_unref(pcm->stream);
756 err = wait_stream_state(pcm, PA_STREAM_READY);
758 SNDERR("PulseAudio: Unable to create stream: %s\n", pa_strerror(pa_context_errno(pcm->p->context)));
759 pa_stream_unref(pcm->stream);
768 /* Reset fake ringbuffer */
774 pa_threaded_mainloop_unlock(pcm->p->mainloop);
779 static int pulse_hw_params(snd_pcm_ioplug_t * io,
780 snd_pcm_hw_params_t * params)
782 snd_pcm_pulse_t *pcm = io->private_data;
787 if (!pcm->p || !pcm->p->mainloop)
790 pa_threaded_mainloop_lock(pcm->p->mainloop);
793 (snd_pcm_format_physical_width(io->format) * io->channels) / 8;
795 switch (io->format) {
796 case SND_PCM_FORMAT_U8:
797 pcm->ss.format = PA_SAMPLE_U8;
799 case SND_PCM_FORMAT_A_LAW:
800 pcm->ss.format = PA_SAMPLE_ALAW;
802 case SND_PCM_FORMAT_MU_LAW:
803 pcm->ss.format = PA_SAMPLE_ULAW;
805 case SND_PCM_FORMAT_S16_LE:
806 pcm->ss.format = PA_SAMPLE_S16LE;
808 case SND_PCM_FORMAT_S16_BE:
809 pcm->ss.format = PA_SAMPLE_S16BE;
811 #ifdef PA_SAMPLE_FLOAT32LE
812 case SND_PCM_FORMAT_FLOAT_LE:
813 pcm->ss.format = PA_SAMPLE_FLOAT32LE;
816 #ifdef PA_SAMPLE_FLOAT32BE
817 case SND_PCM_FORMAT_FLOAT_BE:
818 pcm->ss.format = PA_SAMPLE_FLOAT32BE;
821 #ifdef PA_SAMPLE_S32LE
822 case SND_PCM_FORMAT_S32_LE:
823 pcm->ss.format = PA_SAMPLE_S32LE;
826 #ifdef PA_SAMPLE_S32BE
827 case SND_PCM_FORMAT_S32_BE:
828 pcm->ss.format = PA_SAMPLE_S32BE;
831 #ifdef PA_SAMPLE_S24LE
832 case SND_PCM_FORMAT_S24_3LE:
833 pcm->ss.format = PA_SAMPLE_S24LE;
836 #ifdef PA_SAMPLE_S24BE
837 case SND_PCM_FORMAT_S24_3BE:
838 pcm->ss.format = PA_SAMPLE_S24BE;
841 #ifdef PA_SAMPLE_S24_32LE
842 case SND_PCM_FORMAT_S24_LE:
843 pcm->ss.format = PA_SAMPLE_S24_32LE;
846 #ifdef PA_SAMPLE_S24_32BE
847 case SND_PCM_FORMAT_S24_BE:
848 pcm->ss.format = PA_SAMPLE_S24_32BE;
852 SNDERR("PulseAudio: Unsupported format %s\n",
853 snd_pcm_format_name(io->format));
858 pcm->ss.rate = io->rate;
859 pcm->ss.channels = io->channels;
861 pcm->buffer_attr.maxlength =
863 pcm->buffer_attr.tlength =
864 io->buffer_size * pcm->frame_size;
865 if (pcm->buffer_attr.prebuf == (uint32_t)-1)
866 pcm->buffer_attr.prebuf =
867 (io->buffer_size - io->period_size) * pcm->frame_size;
868 pcm->buffer_attr.minreq = io->period_size * pcm->frame_size;
869 pcm->buffer_attr.fragsize = io->period_size * pcm->frame_size;
872 pa_threaded_mainloop_unlock(pcm->p->mainloop);
877 static int pulse_sw_params(snd_pcm_ioplug_t *io, snd_pcm_sw_params_t *params)
879 snd_pcm_pulse_t *pcm = io->private_data;
880 snd_pcm_uframes_t start_threshold;
884 if (!pcm->p || !pcm->p->mainloop)
887 pa_threaded_mainloop_lock(pcm->p->mainloop);
889 snd_pcm_sw_params_get_start_threshold(params, &start_threshold);
891 /* At least one period to keep PulseAudio happy */
892 if (start_threshold < io->period_size)
893 start_threshold = io->period_size;
895 pcm->buffer_attr.prebuf = start_threshold * pcm->frame_size;
897 pa_threaded_mainloop_unlock(pcm->p->mainloop);
902 static int pulse_close(snd_pcm_ioplug_t * io)
904 snd_pcm_pulse_t *pcm = io->private_data;
908 if (pcm->p && pcm->p->mainloop) {
910 pa_threaded_mainloop_lock(pcm->p->mainloop);
913 pa_stream_disconnect(pcm->stream);
914 pa_stream_unref(pcm->stream);
917 pa_threaded_mainloop_unlock(pcm->p->mainloop);
929 static int pulse_pause(snd_pcm_ioplug_t * io, int enable)
931 snd_pcm_pulse_t *pcm = io->private_data;
937 if (!pcm->p || !pcm->p->mainloop)
940 pa_threaded_mainloop_lock(pcm->p->mainloop);
942 err = check_stream(pcm);
946 o = pa_stream_cork(pcm->stream, enable, NULL, NULL);
948 pa_operation_unref(o);
953 pa_threaded_mainloop_unlock(pcm->p->mainloop);
958 static const snd_pcm_ioplug_callback_t pulse_playback_callback = {
959 .start = pulse_start,
961 .drain = pulse_drain,
962 .pointer = pulse_pointer,
963 .transfer = pulse_write,
964 .delay = pulse_delay,
965 .poll_revents = pulse_pcm_poll_revents,
966 .prepare = pulse_prepare,
967 .hw_params = pulse_hw_params,
968 .sw_params = pulse_sw_params,
969 .close = pulse_close,
974 static const snd_pcm_ioplug_callback_t pulse_capture_callback = {
975 .start = pulse_start,
977 .pointer = pulse_pointer,
978 .transfer = pulse_read,
979 .delay = pulse_delay,
980 .poll_revents = pulse_pcm_poll_revents,
981 .prepare = pulse_prepare,
982 .hw_params = pulse_hw_params,
983 .close = pulse_close,
987 static int pulse_hw_constraint(snd_pcm_pulse_t * pcm)
989 snd_pcm_ioplug_t *io = &pcm->io;
991 static const snd_pcm_access_t access_list[] = {
992 SND_PCM_ACCESS_RW_INTERLEAVED
994 static const unsigned int formats[] = {
996 SND_PCM_FORMAT_A_LAW,
997 SND_PCM_FORMAT_MU_LAW,
998 SND_PCM_FORMAT_S16_LE,
999 SND_PCM_FORMAT_S16_BE,
1000 SND_PCM_FORMAT_FLOAT_LE,
1001 SND_PCM_FORMAT_FLOAT_BE,
1002 SND_PCM_FORMAT_S32_LE,
1003 SND_PCM_FORMAT_S32_BE,
1004 SND_PCM_FORMAT_S24_3LE,
1005 SND_PCM_FORMAT_S24_3BE,
1006 SND_PCM_FORMAT_S24_LE,
1007 SND_PCM_FORMAT_S24_BE
1012 err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_ACCESS,
1013 ARRAY_SIZE(access_list),
1018 err = snd_pcm_ioplug_set_param_list(io, SND_PCM_IOPLUG_HW_FORMAT,
1019 ARRAY_SIZE(formats), formats);
1024 snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_CHANNELS,
1025 1, PA_CHANNELS_MAX);
1029 err = snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_RATE,
1035 snd_pcm_ioplug_set_param_minmax(io,
1036 SND_PCM_IOPLUG_HW_BUFFER_BYTES,
1037 1, 4 * 1024 * 1024);
1042 snd_pcm_ioplug_set_param_minmax(io,
1043 SND_PCM_IOPLUG_HW_PERIOD_BYTES,
1044 128, 2 * 1024 * 1024);
1049 snd_pcm_ioplug_set_param_minmax(io, SND_PCM_IOPLUG_HW_PERIODS,
1056 SND_PCM_PLUGIN_DEFINE_FUNC(pulse)
1058 snd_config_iterator_t i, next;
1059 const char *server = NULL;
1060 const char *device = NULL;
1061 const char *fallback_name = NULL;
1062 int handle_underrun = DEFAULT_HANDLE_UNDERRUN;
1064 snd_pcm_pulse_t *pcm;
1066 snd_config_for_each(i, next, conf) {
1067 snd_config_t *n = snd_config_iterator_entry(i);
1069 if (snd_config_get_id(n, &id) < 0)
1071 if (strcmp(id, "comment") == 0 || strcmp(id, "type") == 0
1072 || strcmp(id, "hint") == 0)
1074 if (strcmp(id, "server") == 0) {
1075 if (snd_config_get_string(n, &server) < 0) {
1076 SNDERR("Invalid type for %s", id);
1078 } else if (!*server) {
1083 if (strcmp(id, "device") == 0) {
1084 if (snd_config_get_string(n, &device) < 0) {
1085 SNDERR("Invalid type for %s", id);
1087 } else if (!*device) {
1092 if (strcmp(id, "handle_underrun") == 0) {
1093 if ((err = snd_config_get_bool(n)) < 0) {
1094 SNDERR("Invalid value for %s", id);
1097 handle_underrun = err;
1100 if (strcmp(id, "fallback") == 0) {
1101 if (snd_config_get_string(n, &fallback_name) < 0) {
1102 SNDERR("Invalid value for %s", id);
1104 } else if (!*fallback_name) {
1105 fallback_name = NULL;
1109 SNDERR("Unknown field %s", id);
1113 if (fallback_name && name && !strcmp(name, fallback_name))
1114 fallback_name = NULL; /* no fallback for the same name */
1116 pcm = calloc(1, sizeof(*pcm));
1121 pcm->device = strdup(device);
1129 pcm->p = pulse_new();
1135 pcm->handle_underrun = handle_underrun;
1136 pcm->buffer_attr.prebuf = -1;
1138 err = pulse_connect(pcm->p, server, fallback_name != NULL);
1142 pcm->io.version = SND_PCM_IOPLUG_VERSION;
1143 pcm->io.name = "ALSA <-> PulseAudio PCM I/O Plugin";
1144 pcm->io.poll_fd = pcm->p->main_fd;
1145 pcm->io.poll_events = POLLIN;
1146 pcm->io.mmap_rw = 0;
1147 pcm->io.callback = stream == SND_PCM_STREAM_PLAYBACK ?
1148 &pulse_playback_callback : &pulse_capture_callback;
1149 pcm->io.private_data = pcm;
1151 err = snd_pcm_ioplug_create(&pcm->io, name, stream, mode);
1155 err = pulse_hw_constraint(pcm);
1157 snd_pcm_ioplug_delete(&pcm->io);
1161 *pcmp = pcm->io.pcm;
1173 return snd_pcm_open_fallback(pcmp, root, fallback_name, name,
1179 SND_PCM_PLUGIN_SYMBOL(pulse);