annotate libao2/ao_pulse.c @ 34175:a345e7162d0a

Move TranslateFilename() to util/string.c. Now that the Win32 GUI uses symbolic constants for its messages, the code of TranslateFilename() both GUIs use is almost identical. So, share the code.
author ib
date Wed, 26 Oct 2011 15:14:06 +0000
parents d652e17184f9
children 96019b1174b8
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"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
29 #include "mp_msg.h"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
30 #include "audio_out.h"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
31 #include "audio_out_internal.h"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
32
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
33 #define PULSE_CLIENT_NAME "MPlayer"
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
34
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
35 /** General driver info */
28823
9a5b8c2ed6de Make ao_info_t structs const.
reimar
parents: 28633
diff changeset
36 static const ao_info_t info = {
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
37 "PulseAudio audio output",
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
38 "pulse",
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
39 "Lennart Poettering",
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
40 ""
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
41 };
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
42
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
43 /** PulseAudio playback stream object */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
44 static struct pa_stream *stream;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
45
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
46 /** PulseAudio connection context */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
47 static struct pa_context *context;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
48
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
49 /** Main event loop object */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
50 static struct pa_threaded_mainloop *mainloop;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
51
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
52 static int broken_pause;
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
53
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
54 LIBAO_EXTERN(pulse)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
55
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
56 #define GENERIC_ERR_MSG(ctx, str) \
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
57 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] "str": %s\n", \
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
58 pa_strerror(pa_context_errno(ctx)))
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
59
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
60 static void context_state_cb(pa_context *c, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
61 switch (pa_context_get_state(c)) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
62 case PA_CONTEXT_READY:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
63 case PA_CONTEXT_TERMINATED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
64 case PA_CONTEXT_FAILED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
65 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
66 break;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
67 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
68 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
69
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
70 static void stream_state_cb(pa_stream *s, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
71 switch (pa_stream_get_state(s)) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
72 case PA_STREAM_READY:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
73 case PA_STREAM_FAILED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
74 case PA_STREAM_TERMINATED:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
75 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
76 break;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
77 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
78 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
79
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
80 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
81 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
82 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
83
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
84 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
85 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
86 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
87
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
88 static void success_cb(pa_stream *s, int success, void *userdata) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
89 if (userdata)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
90 *(int *)userdata = success;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
91 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
92 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
93
25383
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
94 /**
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
95 * \brief waits for a pulseaudio operation to finish, frees it and
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
96 * unlocks the mainloop
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
97 * \param op operation to wait for
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
98 * \return 1 if operation has finished normally (DONE state), 0 otherwise
9ca05492f9f3 Documentation for waitop function
reimar
parents: 24923
diff changeset
99 */
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
100 static int waitop(pa_operation *op) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
101 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
102 if (!op) {
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
103 pa_threaded_mainloop_unlock(mainloop);
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
104 return 0;
010781e92294 Make sure waitop always unlocks the mainloop even if the operation could not
reimar
parents: 28823
diff changeset
105 }
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
106 state = pa_operation_get_state(op);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
107 while (state == PA_OPERATION_RUNNING) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
108 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
109 state = pa_operation_get_state(op);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
110 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
111 pa_operation_unref(op);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
112 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
113 return state == PA_OPERATION_DONE;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
114 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
115
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
116 static const struct format_map_s {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
117 int mp_format;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
118 pa_sample_format_t pa_format;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
119 } format_maps[] = {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
120 {AF_FORMAT_S16_LE, PA_SAMPLE_S16LE},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
121 {AF_FORMAT_S16_BE, PA_SAMPLE_S16BE},
26649
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
122 #ifdef PA_SAMPLE_S32NE
26603
c07abb5a5bef Add support for 32 bit format to ao_pulse.
reimar
parents: 26602
diff changeset
123 {AF_FORMAT_S32_LE, PA_SAMPLE_S32LE},
c07abb5a5bef Add support for 32 bit format to ao_pulse.
reimar
parents: 26602
diff changeset
124 {AF_FORMAT_S32_BE, PA_SAMPLE_S32BE},
26649
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
125 #endif
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
126 #ifdef PA_SAMPLE_FLOAT32NE
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
127 {AF_FORMAT_FLOAT_LE, PA_SAMPLE_FLOAT32LE},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
128 {AF_FORMAT_FLOAT_BE, PA_SAMPLE_FLOAT32BE},
26649
07d106323e5c Avoid dependency on newer pulseaudio version.
reimar
parents: 26603
diff changeset
129 #endif
26602
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
130 {AF_FORMAT_U8, PA_SAMPLE_U8},
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
131 {AF_FORMAT_MU_LAW, PA_SAMPLE_ULAW},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
132 {AF_FORMAT_A_LAW, PA_SAMPLE_ALAW},
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
133 {AF_FORMAT_UNKNOWN, 0}
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
134 };
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
135
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
136 static int init(int rate_hz, int channels, int format, int flags) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
137 struct pa_sample_spec ss;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
138 struct pa_channel_map map;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
139 const struct format_map_s *fmt_map;
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
140 char *devarg = NULL;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
141 char *host = NULL;
24919
51372a34bc7d Make sink variable local, it is only used in one place
reimar
parents: 24782
diff changeset
142 char *sink = NULL;
30020
d652e17184f9 Add a missing const, fixes a compiler warning.
reimar
parents: 30019
diff changeset
143 const char *version = pa_get_library_version();
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
144
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
145 if (ao_subdevice) {
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
146 devarg = strdup(ao_subdevice);
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
147 sink = strchr(devarg, ':');
24920
12dc34b2e41c Simplify argument "parsing"
reimar
parents: 24919
diff changeset
148 if (sink) *sink++ = 0;
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
149 if (devarg[0]) host = devarg;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
150 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
151
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
152 broken_pause = 0;
29120
aa06c29db609 Disable pause-hack from PulseAudio 0.9.15 on, it should be fixed.
reimar
parents: 29119
diff changeset
153 // 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
154 // 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
155 // 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
156 // to test: pause, wait ca. 5 seconds framestep and see if MPlayer hangs somewhen
29120
aa06c29db609 Disable pause-hack from PulseAudio 0.9.15 on, it should be fixed.
reimar
parents: 29119
diff changeset
157 if (strncmp(version, "0.9.1", 5) == 0 && version[5] >= '1' && version[5] <= '4') {
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
158 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
159 " 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
160 broken_pause = 1;
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
161 }
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
162
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
163 ss.channels = channels;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
164 ss.rate = rate_hz;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
165
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
166 ao_data.samplerate = rate_hz;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
167 ao_data.channels = channels;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
168
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
169 fmt_map = format_maps;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
170 while (fmt_map->mp_format != format) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
171 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
172 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
173 fmt_map = format_maps;
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
174 break;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
175 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
176 fmt_map++;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
177 }
26602
d48e2d7191df Make ao_pulse fall back to s16le format instead of just failing.
reimar
parents: 25386
diff changeset
178 ao_data.format = fmt_map->mp_format;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
179 ss.format = fmt_map->pa_format;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
180
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
181 if (!pa_sample_spec_valid(&ss)) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
182 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Invalid sample spec\n");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
183 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
184 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
185
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
186 pa_channel_map_init_auto(&map, ss.channels, PA_CHANNEL_MAP_ALSA);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
187 ao_data.bps = pa_bytes_per_second(&ss);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
188
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
189 if (!(mainloop = pa_threaded_mainloop_new())) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
190 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate main loop\n");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
191 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
192 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
193
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
194 if (!(context = pa_context_new(pa_threaded_mainloop_get_api(mainloop), PULSE_CLIENT_NAME))) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
195 mp_msg(MSGT_AO, MSGL_ERR, "AO: [pulse] Failed to allocate context\n");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
196 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
197 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
198
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
199 pa_context_set_state_callback(context, context_state_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
200
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
201 if (pa_context_connect(context, host, 0, NULL) < 0)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
202 goto fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
203
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
204 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
205
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
206 if (pa_threaded_mainloop_start(mainloop) < 0)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
207 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
208
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
209 /* Wait until the context is ready */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
210 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
211
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
212 if (pa_context_get_state(context) != PA_CONTEXT_READY)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
213 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
214
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
215 if (!(stream = pa_stream_new(context, "audio stream", &ss, &map)))
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
216 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
217
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
218 pa_stream_set_state_callback(stream, stream_state_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
219 pa_stream_set_write_callback(stream, stream_request_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
220 pa_stream_set_latency_update_callback(stream, stream_latency_update_cb, NULL);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
221
30019
2d62e9614c8d Allow pulseaudio to restore the previous volume on init instead of forcing to
reimar
parents: 30018
diff changeset
222 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
223 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
224
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
225 /* Wait until the stream is ready */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
226 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
227
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
228 if (pa_stream_get_state(stream) != PA_STREAM_READY)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
229 goto unlock_and_fail;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
230
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
231 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
232
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
233 free(devarg);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
234 return 1;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
235
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
236 unlock_and_fail:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
237
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
238 if (mainloop)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
239 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
240
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
241 fail:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
242 if (context)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
243 GENERIC_ERR_MSG(context, "Init failed");
24921
148ca265fcb6 Change parsing to allow host == NULL and sink != NULL
reimar
parents: 24920
diff changeset
244 free(devarg);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
245 uninit(1);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
246 return 0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
247 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
248
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
249 /** Destroy libao driver */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
250 static void uninit(int immed) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
251 if (stream && !immed) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
252 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
253 waitop(pa_stream_drain(stream, success_cb, NULL));
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
254 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
255
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
256 if (mainloop)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
257 pa_threaded_mainloop_stop(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
258
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
259 if (stream) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
260 pa_stream_disconnect(stream);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
261 pa_stream_unref(stream);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
262 stream = NULL;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
263 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
264
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
265 if (context) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
266 pa_context_disconnect(context);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
267 pa_context_unref(context);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
268 context = NULL;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
269 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
270
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
271 if (mainloop) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
272 pa_threaded_mainloop_free(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
273 mainloop = NULL;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
274 }
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 /** Play the specified data to the pulseaudio server */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
278 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
279 pa_threaded_mainloop_lock(mainloop);
25385
52f6c42c43bb Fix indentation
reimar
parents: 25384
diff changeset
280 if (pa_stream_write(stream, data, len, NULL, 0, PA_SEEK_RELATIVE) < 0) {
52f6c42c43bb Fix indentation
reimar
parents: 25384
diff changeset
281 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
282 len = -1;
25385
52f6c42c43bb Fix indentation
reimar
parents: 25384
diff changeset
283 }
25386
bd46b759fd35 pa_stream_write reportedly needs locking of the main loop
reimar
parents: 25385
diff changeset
284 pa_threaded_mainloop_unlock(mainloop);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
285 return len;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
286 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
287
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
288 static void cork(int b) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
289 int success = 0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
290 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
291 if (!waitop(pa_stream_cork(stream, b, success_cb, &success)) ||
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
292 !success)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
293 GENERIC_ERR_MSG(context, "pa_stream_cork() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
294 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
295
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
296 /** Pause the audio stream by corking it on the server */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
297 static void audio_pause(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
298 cork(1);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
299 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
300
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
301 /** Resume the audio stream by uncorking it on the server */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
302 static void audio_resume(void) {
28633
28fe0787a67c Work around a PulseAudio bug that causes MPlayer to hang after unpausing.
reimar
parents: 26743
diff changeset
303 // 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
304 // 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
305 // 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
306 if (broken_pause) reset();
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
307 cork(0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
308 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
309
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
310 /** Reset the audio stream, i.e. flush the playback buffer on the server side */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
311 static void reset(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
312 int success = 0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
313 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
314 if (!waitop(pa_stream_flush(stream, success_cb, &success)) ||
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
315 !success)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
316 GENERIC_ERR_MSG(context, "pa_stream_flush() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
317 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
318
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
319 /** Return number of bytes that may be written to the server without blocking */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
320 static int get_space(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
321 size_t l;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
322 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
323 l = pa_stream_writable_size(stream);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
324 pa_threaded_mainloop_unlock(mainloop);
24923
d0d04fe92bce Remove idiotic check that would always be false
reimar
parents: 24921
diff changeset
325 return l;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
326 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
327
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
328 /** Return the current latency in seconds */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
329 static float get_delay(void) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
330 pa_usec_t latency = (pa_usec_t) -1;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
331 pa_threaded_mainloop_lock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
332 while (pa_stream_get_latency(stream, &latency, NULL) < 0) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
333 if (pa_context_errno(context) != PA_ERR_NODATA) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
334 GENERIC_ERR_MSG(context, "pa_stream_get_latency() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
335 break;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
336 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
337 /* Wait until latency data is available again */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
338 pa_threaded_mainloop_wait(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
339 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
340 pa_threaded_mainloop_unlock(mainloop);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
341 return latency == (pa_usec_t) -1 ? 0 : latency / 1000000.0;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
342 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
343
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
344 /** A callback function that is called when the
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
345 * pa_context_get_sink_input_info() operation completes. Saves the
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
346 * volume field of the specified structure to the global variable volume. */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
347 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
348 struct pa_cvolume *volume = userdata;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
349 if (is_last < 0) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
350 GENERIC_ERR_MSG(context, "Failed to get sink input info");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
351 return;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
352 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
353 if (!i)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
354 return;
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
355 *volume = i->volume;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
356 pa_threaded_mainloop_signal(mainloop, 0);
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
357 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
358
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
359 static int control(int cmd, void *arg) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
360 switch (cmd) {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
361 case AOCONTROL_GET_VOLUME: {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
362 ao_control_vol_t *vol = arg;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
363 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
364 struct pa_cvolume volume;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
365 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
366 if (!waitop(pa_context_get_sink_input_info(context, devidx, info_func, &volume))) {
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
367 GENERIC_ERR_MSG(context, "pa_stream_get_sink_input_info() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
368 return CONTROL_ERROR;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
369 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
370
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
371 if (volume.channels != 2)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
372 vol->left = vol->right = pa_cvolume_avg(&volume)*100/PA_VOLUME_NORM;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
373 else {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
374 vol->left = volume.values[0]*100/PA_VOLUME_NORM;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
375 vol->right = volume.values[1]*100/PA_VOLUME_NORM;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
376 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
377
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
378 return CONTROL_OK;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
379 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
380
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
381 case AOCONTROL_SET_VOLUME: {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
382 const ao_control_vol_t *vol = arg;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
383 pa_operation *o;
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
384 struct pa_cvolume volume;
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
385
30018
ae5d67d8ee95 Get rid of global volume variable, it is only used for temporary values.
reimar
parents: 29120
diff changeset
386 pa_cvolume_reset(&volume, ao_data.channels);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
387 if (volume.channels != 2)
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
388 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
389 else {
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
390 volume.values[0] = (pa_volume_t)vol->left*PA_VOLUME_NORM/100;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
391 volume.values[1] = (pa_volume_t)vol->right*PA_VOLUME_NORM/100;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
392 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
393
29118
17c6a6c192a7 Also lock the mainloop when doing adjusting the volume for PulseAudio.
reimar
parents: 29117
diff changeset
394 pa_threaded_mainloop_lock(mainloop);
29119
52afd0fe451b Split oversized of "argument" onto a separate line.
reimar
parents: 29118
diff changeset
395 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
396 if (!o) {
29118
17c6a6c192a7 Also lock the mainloop when doing adjusting the volume for PulseAudio.
reimar
parents: 29117
diff changeset
397 pa_threaded_mainloop_unlock(mainloop);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
398 GENERIC_ERR_MSG(context, "pa_context_set_sink_input_volume() failed");
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
399 return CONTROL_ERROR;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
400 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
401 /* We don't wait for completion here */
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
402 pa_operation_unref(o);
29118
17c6a6c192a7 Also lock the mainloop when doing adjusting the volume for PulseAudio.
reimar
parents: 29117
diff changeset
403 pa_threaded_mainloop_unlock(mainloop);
24782
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
404 return CONTROL_OK;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
405 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
406
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
407 default:
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
408 return CONTROL_UNKNOWN;
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
409 }
6479c850fcfd Add missing ao_pulse.c
reimar
parents:
diff changeset
410 }