annotate libao2/ao_pulse.c @ 35418:cedb0ba2b5c6

Move the code to set guiInfo's Track, Chapter and Angle start values. Set them before checking whether there is any media opened, because with no media opened we clear the counters.
author ib
date Thu, 29 Nov 2012 14:11:03 +0000
parents aa10c22f69f4
children 99708d402208
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
1 /*
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
2 * PulseAudio audio output driver.
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
3 * Copyright (C) 2006 Lennart Poettering
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
4 * Copyright (C) 2007 Reimar Doeffinger
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
5 *
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
6 * This file is part of MPlayer.
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
7 *
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
8 * MPlayer is free software; you can redistribute it and/or modify
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
9 * it under the terms of the GNU General Public License as published by
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
10 * the Free Software Foundation; either version 2 of the License, or
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
11 * (at your option) any later version.
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
12 *
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
13 * MPlayer is distributed in the hope that it will be useful,
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
16 * GNU General Public License for more details.
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
17 *
26743
0f42fb42843c Use standard license headers with standard formatting.
diego
parents: 26649
diff changeset
18 * You should have received a copy of the GNU General Public License along
0f42fb42843c Use standard license headers with standard formatting.
diego
parents: 26649
diff changeset
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
0f42fb42843c Use standard license headers with standard formatting.
diego
parents: 26649
diff changeset
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
21 */
26743
0f42fb42843c Use standard license headers with standard formatting.
diego
parents: 26649
diff changeset
22
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
23 #include <string.h>
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
24
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
25 #include <pulse/pulseaudio.h>
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
26
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
27 #include "config.h"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
28 #include "libaf/af_format.h"
34564
96019b1174b8 Workaround a bug in Pulse Audio (http://pulseaudio.org/ticket/866)
iive
parents: 30020
diff changeset
29 #include "osdep/timer.h"
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
30 #include "mp_msg.h"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
31 #include "audio_out.h"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
32 #include "audio_out_internal.h"
34696
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
33 #include "subopt-helper.h"
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
34
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
35 #define PULSE_CLIENT_NAME "MPlayer"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
36
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
37 /** General driver info */
28823
9a5b8c2ed6de Make ao_info_t structs const.
reimar
parents: 28633
diff changeset
38 static const ao_info_t info = {
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
39 "PulseAudio audio output",
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
40 "pulse",
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
41 "Lennart Poettering",
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
42 ""
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
43 };
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
44
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
45 /** PulseAudio playback stream object */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
46 static struct pa_stream *stream;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
47
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
48 /** PulseAudio connection context */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
49 static struct pa_context *context;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
50
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
51 /** Main event loop object */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
52 static struct pa_threaded_mainloop *mainloop;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
53
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
54 static int broken_pause;
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
55
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
56 LIBAO_EXTERN(pulse)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
57
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
58 #define GENERIC_ERR_MSG(ctx, str) \
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
59 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] "str": %s\n", \
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
60 pa_strerror(pa_context_errno(ctx)))
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
61
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
62 static void context_state_cb(pa_context *c, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
63 switch (pa_context_get_state(c)) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
64 case PA_CONTEXT_READY:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
65 case PA_CONTEXT_TERMINATED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
66 case PA_CONTEXT_FAILED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
67 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
68 break;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
69 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
70 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
71
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
72 static void stream_state_cb(pa_stream *s, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
73 switch (pa_stream_get_state(s)) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
74 case PA_STREAM_READY:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
75 case PA_STREAM_FAILED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
76 case PA_STREAM_TERMINATED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
77 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
78 break;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
79 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
80 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
81
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
82 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
83 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
84 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
85
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
86 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
87 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
88 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
89
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
90 static void success_cb(pa_stream *s, int success, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
91 if (userdata)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
92 *(int *)userdata = success;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
93 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
94 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
95
25383
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
96 /**
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
97 * \brief waits for a pulseaudio operation to finish, frees it and
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
98 * unlocks the mainloop
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
99 * \param op operation to wait for
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
100 * \return 1 if operation has finished normally (DONE state), 0 otherwise
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
101 */
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
102 static int waitop(pa_operation *op) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
103 pa_operation_state_t state;
29117
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
104 if (!op) {
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
105 pa_threaded_mainloop_unlock(mainloop);
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
106 return 0;
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
107 }
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
108 state = pa_operation_get_state(op);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
109 while (state == PA_OPERATION_RUNNING) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
110 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
111 state = pa_operation_get_state(op);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
112 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
113 pa_operation_unref(op);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
114 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
115 return state == PA_OPERATION_DONE;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
116 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
117
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
118 static const struct format_map_s {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
119 int mp_format;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
120 pa_sample_format_t pa_format;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
121 } format_maps[] = {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
122 {AF_FORMAT_S16_LE, PA_SAMPLE_S16LE},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
123 {AF_FORMAT_S16_BE, PA_SAMPLE_S16BE},
26649
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
124 #ifdef PA_SAMPLE_S32NE
26603
c07abb5a5bef Add support for 32 bit format to ao_pulse.
reimar
parents: 26602
diff changeset
125 {AF_FORMAT_S32_LE, PA_SAMPLE_S32LE},
c07abb5a5bef Add support for 32 bit format to ao_pulse.
reimar
parents: 26602
diff changeset
126 {AF_FORMAT_S32_BE, PA_SAMPLE_S32BE},
26649
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
127 #endif
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
128 #ifdef PA_SAMPLE_FLOAT32NE
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
129 {AF_FORMAT_FLOAT_LE, PA_SAMPLE_FLOAT32LE},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
130 {AF_FORMAT_FLOAT_BE, PA_SAMPLE_FLOAT32BE},
26649
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
131 #endif
26602
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
132 {AF_FORMAT_U8, PA_SAMPLE_U8},
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
133 {AF_FORMAT_MU_LAW, PA_SAMPLE_ULAW},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
134 {AF_FORMAT_A_LAW, PA_SAMPLE_ALAW},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
135 {AF_FORMAT_UNKNOWN, 0}
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
136 };
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
137
34696
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
138 static const opt_t subopts[] = {
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
139 {"broken_pause", OPT_ARG_BOOL, &broken_pause, NULL},
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
140 {NULL}
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
141 };
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
142
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
143 static int init(int rate_hz, int channels, int format, int flags) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
144 struct pa_sample_spec ss;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
145 struct pa_channel_map map;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
146 const struct format_map_s *fmt_map;
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
147 char *devarg = NULL;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
148 char *host = NULL;
24919
51372a34bc7d Make sink variable local, it is only used in one place
reimar
parents: 24782
diff changeset
149 char *sink = NULL;
30020
d652e17184f9 Add a missing const, fixes a compiler warning.
reimar
parents: 30019
diff changeset
150 const char *version = pa_get_library_version();
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
151
34696
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
152 broken_pause = -1;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
153 if (ao_subdevice) {
34696
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
154 char *opts;
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
155 devarg = strdup(ao_subdevice);
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
156 sink = strchr(devarg, ':');
24920
12dc34b2e41c Simplify argument "parsing"
reimar
parents: 24919
diff changeset
157 if (sink) *sink++ = 0;
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
158 if (devarg[0]) host = devarg;
35202
aa10c22f69f4 Fix crash when only specifying a host for -ao pulse.
reimar
parents: 34696
diff changeset
159 opts = sink ? strchr(sink, ':') : NULL;
34696
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
160 if (opts) {
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
161 *opts++ = 0;
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
162 if (!sink[0]) sink = NULL;
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
163 if (subopt_parse(opts, subopts))
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
164 goto fail;
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
165 }
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
166 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
167
29120
aa06c29db609 Disable pause-hack from PulseAudio 0.9.15 on, it should be fixed.
reimar
parents: 29119
diff changeset
168 // not sure which versions are affected, assume 0.9.11* to 0.9.14*
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
169 // known bad: 0.9.14, 0.9.13
29120
aa06c29db609 Disable pause-hack from PulseAudio 0.9.15 on, it should be fixed.
reimar
parents: 29119
diff changeset
170 // known good: 0.9.9, 0.9.10, 0.9.15
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
171 // to test: pause, wait ca. 5 seconds framestep and see if MPlayer hangs somewhen
34696
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
172 if (broken_pause == -1)
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
173 broken_pause = strncmp(version, "0.9.1", 5) == 0 && version[5] >= '1' && version[5] <= '4';
f2c90c9dd61c Add suboption parsing support to ao_pulse and add an
reimar
parents: 34638
diff changeset
174 if (broken_pause) {
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
175 mp_msg(MSGT_AO, MSGL_WARN, "[pulse] working around probably broken pause functionality,\n"
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
176 " see http://www.pulseaudio.org/ticket/440\n");
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
177 }
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
178
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
179 ss.channels = channels;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
180 ss.rate = rate_hz;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
181
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
182 ao_data.samplerate = rate_hz;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
183 ao_data.channels = channels;
34638
583c7cfc6653 pulse: set outburst size.
reimar
parents: 34564
diff changeset
184 ao_data.outburst = 8 * channels * (rate_hz / 64);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
185
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
186 fmt_map = format_maps;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
187 while (fmt_map->mp_format != format) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
188 if (fmt_map->mp_format == AF_FORMAT_UNKNOWN) {
26602
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
189 mp_msg(MSGT_AO, MSGL_V, "AO: [pulse] Unsupported format, using default\n");
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
190 fmt_map = format_maps;
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
191 break;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
192 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
193 fmt_map++;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
194 }
26602
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
195 ao_data.format = fmt_map->mp_format;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
196 ss.format = fmt_map->pa_format;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
197
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
198 if (!pa_sample_spec_valid(&ss)) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
199 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Invalid sample spec\n");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
200 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
201 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
202
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
203 pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
204 ao_data.bps = pa_bytes_per_second(&ss);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
205
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
206 if (!(mainloop = pa_threaded_mainloop_new())) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
207 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate main loop\n");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
208 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
209 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
210
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
211 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), PULSE_CLIENT_NAME))) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
212 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate context\n");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
213 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
214 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
215
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
216 pa_context_set_state_callback(context, context_state_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
217
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
218 if (pa_context_connect(context, host, 0, NULL) < 0)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
219 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
220
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
221 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
222
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
223 if (pa_threaded_mainloop_start(mainloop) < 0)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
224 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
225
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
226 /* Wait until the context is ready */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
227 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
228
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
229 if (pa_context_get_state(context) != PA_CONTEXT_READY)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
230 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
231
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
232 if (!(stream = pa_stream_new(context, "audio stream", &ss, &map)))
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
233 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
234
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
235 pa_stream_set_state_callback(stream, stream_state_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
236 pa_stream_set_write_callback(stream, stream_request_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
237 pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
238
30019
2d62e9614c8d Allow pulseaudio to restore the previous volume on init instead of forcing to
reimar
parents: 30018
diff changeset
239 if (pa_stream_connect_playback(stream, sink, NULL, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL) < 0)
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
240 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
241
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
242 /* Wait until the stream is ready */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
243 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
244
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
245 if (pa_stream_get_state(stream) != PA_STREAM_READY)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
246 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
247
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
248 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
249
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
250 free(devarg);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
251 return 1;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
252
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
253 unlock_and_fail:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
254
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
255 if (mainloop)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
256 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
257
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
258 fail:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
259 if (context)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
260 GENERIC_ERR_MSG(context, "Init failed");
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
261 free(devarg);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
262 uninit(1);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
263 return 0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
264 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
265
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
266 /** Destroy libao driver */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
267 static void uninit(int immed) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
268 if (stream && !immed) {
34564
96019b1174b8 Workaround a bug in Pulse Audio (http://pulseaudio.org/ticket/866)
iive
parents: 30020
diff changeset
269 /* Workaround the bug in pa_stream_drain that causes
96019b1174b8 Workaround a bug in Pulse Audio (http://pulseaudio.org/ticket/866)
iive
parents: 30020
diff changeset
270 a delay of 2 second if the buffer is not empty */
96019b1174b8 Workaround a bug in Pulse Audio (http://pulseaudio.org/ticket/866)
iive
parents: 30020
diff changeset
271 usec_sleep(get_delay() * 1000 * 1000);
96019b1174b8 Workaround a bug in Pulse Audio (http://pulseaudio.org/ticket/866)
iive
parents: 30020
diff changeset
272
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
273 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
274 waitop(pa_stream_drain(stream, success_cb, NULL));
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
275 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
276
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
277 if (mainloop)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
278 pa_threaded_mainloop_stop(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
279
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
280 if (stream) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
281 pa_stream_disconnect(stream);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
282 pa_stream_unref(stream);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
283 stream = NULL;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
284 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
285
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
286 if (context) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
287 pa_context_disconnect(context);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
288 pa_context_unref(context);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
289 context = NULL;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
290 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
291
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
292 if (mainloop) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
293 pa_threaded_mainloop_free(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
294 mainloop = NULL;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
295 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
296 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
297
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
298 /** Play the specified data to the pulseaudio server */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
299 static int play(void* data, int len, int flags) {
25386
bd46b759fd35 pa_stream_write reportedly needs locking of the main loop
reimar
parents: 25385
diff changeset
300 pa_threaded_mainloop_lock(mainloop);
25385
52f6c42c43bb Fix indentation
reimar
parents: 25384
diff changeset
301 if (pa_stream_write(stream, data, len, NULL, 0, PA_SEEK_RELATIVE) < 0) {
52f6c42c43bb Fix indentation
reimar
parents: 25384
diff changeset
302 GENERIC_ERR_MSG(context, "pa_stream_write() failed");
25386
bd46b759fd35 pa_stream_write reportedly needs locking of the main loop
reimar
parents: 25385
diff changeset
303 len = -1;
25385
52f6c42c43bb Fix indentation
reimar
parents: 25384
diff changeset
304 }
25386
bd46b759fd35 pa_stream_write reportedly needs locking of the main loop
reimar
parents: 25385
diff changeset
305 pa_threaded_mainloop_unlock(mainloop);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
306 return len;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
307 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
308
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
309 static void cork(int b) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
310 int success = 0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
311 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
312 if (!waitop(pa_stream_cork(stream, b, success_cb, &success)) ||
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
313 !success)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
314 GENERIC_ERR_MSG(context, "pa_stream_cork() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
315 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
316
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
317 /** Pause the audio stream by corking it on the server */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
318 static void audio_pause(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
319 cork(1);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
320 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
321
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
322 /** Resume the audio stream by uncorking it on the server */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
323 static void audio_resume(void) {
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
324 // without this, certain versions will cause an infinite hang because
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
325 // pa_stream_writable_size returns 0 always.
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
326 // Note that this workaround causes A-V desync after pause
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
327 if (broken_pause) reset();
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
328 cork(0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
329 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
330
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
331 /** Reset the audio stream, i.e. flush the playback buffer on the server side */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
332 static void reset(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
333 int success = 0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
334 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
335 if (!waitop(pa_stream_flush(stream, success_cb, &success)) ||
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
336 !success)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
337 GENERIC_ERR_MSG(context, "pa_stream_flush() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
338 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
339
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
340 /** Return number of bytes that may be written to the server without blocking */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
341 static int get_space(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
342 size_t l;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
343 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
344 l = pa_stream_writable_size(stream);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
345 pa_threaded_mainloop_unlock(mainloop);
24923
d0d04fe92bce Remove idiotic check that would always be false
reimar
parents: 24921
diff changeset
346 return l;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
347 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
348
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
349 /** Return the current latency in seconds */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
350 static float get_delay(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
351 pa_usec_t latency = (pa_usec_t) -1;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
352 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
353 while (pa_stream_get_latency(stream, &latency, NULL) < 0) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
354 if (pa_context_errno(context) != PA_ERR_NODATA) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
355 GENERIC_ERR_MSG(context, "pa_stream_get_latency() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
356 break;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
357 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
358 /* Wait until latency data is available again */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
359 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
360 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
361 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
362 return latency == (pa_usec_t) -1 ? 0 : latency / 1000000.0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
363 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
364
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
365 /** A callback function that is called when the
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
366 * pa_context_get_sink_input_info() operation completes. Saves the
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
367 * volume field of the specified structure to the global variable volume. */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
368 static void info_func(struct pa_context *c, const struct pa_sink_input_info *i, int is_last, void *userdata) {
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
369 struct pa_cvolume *volume = userdata;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
370 if (is_last < 0) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
371 GENERIC_ERR_MSG(context, "Failed to get sink input info");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
372 return;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
373 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
374 if (!i)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
375 return;
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
376 *volume = i->volume;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
377 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
378 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
379
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
380 static int control(int cmd, void *arg) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
381 switch (cmd) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
382 case AOCONTROL_GET_VOLUME: {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
383 ao_control_vol_t *vol = arg;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
384 uint32_t devidx = pa_stream_get_index(stream);
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
385 struct pa_cvolume volume;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
386 pa_threaded_mainloop_lock(mainloop);
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
387 if (!waitop(pa_context_get_sink_input_info(context, devidx, info_func, &volume))) {
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
388 GENERIC_ERR_MSG(context, "pa_stream_get_sink_input_info() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
389 return CONTROL_ERROR;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
390 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
391
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
392 if (volume.channels != 2)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
393 vol->left = vol->right = pa_cvolume_avg(&volume)*100/PA_VOLUME_NORM;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
394 else {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
395 vol->left = volume.values[0]*100/PA_VOLUME_NORM;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
396 vol->right = volume.values[1]*100/PA_VOLUME_NORM;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
397 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
398
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
399 return CONTROL_OK;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
400 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
401
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
402 case AOCONTROL_SET_VOLUME: {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
403 const ao_control_vol_t *vol = arg;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
404 pa_operation *o;
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
405 struct pa_cvolume volume;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
406
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
407 pa_cvolume_reset(&volume, ao_data.channels);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
408 if (volume.channels != 2)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
409 pa_cvolume_set(&volume, volume.channels, (pa_volume_t)vol->left*PA_VOLUME_NORM/100);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
410 else {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
411 volume.values[0] = (pa_volume_t)vol->left*PA_VOLUME_NORM/100;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
412 volume.values[1] = (pa_volume_t)vol->right*PA_VOLUME_NORM/100;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
413 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
414
29118
17c6a6c192a7 Also lock the mainloop when doing adjusting the volume for PulseAudio.
reimar
parents: 29117
diff changeset
415 pa_threaded_mainloop_lock(mainloop);
29119
52afd0fe451b Split oversized of "argument" onto a separate line.
reimar
parents: 29118
diff changeset
416 o = pa_context_set_sink_input_volume(context, pa_stream_get_index(stream), &volume, NULL, NULL);
52afd0fe451b Split oversized of "argument" onto a separate line.
reimar
parents: 29118
diff changeset
417 if (!o) {
29118
17c6a6c192a7 Also lock the mainloop when doing adjusting the volume for PulseAudio.
reimar
parents: 29117
diff changeset
418 pa_threaded_mainloop_unlock(mainloop);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
419 GENERIC_ERR_MSG(context, "pa_context_set_sink_input_volume() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
420 return CONTROL_ERROR;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
421 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
422 /* We don't wait for completion here */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
423 pa_operation_unref(o);
29118
17c6a6c192a7 Also lock the mainloop when doing adjusting the volume for PulseAudio.
reimar
parents: 29117
diff changeset
424 pa_threaded_mainloop_unlock(mainloop);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
425 return CONTROL_OK;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
426 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
427
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
428 default:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
429 return CONTROL_UNKNOWN;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
430 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
431 }