]> code.delx.au - pulseaudio/blob - src/pulse/simple.c
9ed7a6535802180e9f4f68e83e3636ea635df069
[pulseaudio] / src / pulse / simple.c
1
2 /***
3 This file is part of PulseAudio.
4
5 Copyright 2004-2006 Lennart Poettering
6
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
11
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30
31 #include <pulse/pulseaudio.h>
32 #include <pulse/thread-mainloop.h>
33 #include <pulse/xmalloc.h>
34
35 #include <pulsecore/native-common.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/macro.h>
38
39 #include "simple.h"
40
41 struct pa_simple {
42 pa_threaded_mainloop *mainloop;
43 pa_context *context;
44 pa_stream *stream;
45 pa_stream_direction_t direction;
46
47 const void *read_data;
48 size_t read_index, read_length;
49
50 int operation_success;
51 };
52
53 #define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret) \
54 do { \
55 if (!(expression)) { \
56 if (rerror) \
57 *(rerror) = error; \
58 return (ret); \
59 } \
60 } while(FALSE);
61
62 #define CHECK_SUCCESS_GOTO(p, rerror, expression, label) \
63 do { \
64 if (!(expression)) { \
65 if (rerror) \
66 *(rerror) = pa_context_errno((p)->context); \
67 goto label; \
68 } \
69 } while(FALSE);
70
71 #define CHECK_DEAD_GOTO(p, rerror, label) \
72 do { \
73 if (!(p)->context || !PA_CONTEXT_IS_GOOD(pa_context_get_state((p)->context)) || \
74 !(p)->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state((p)->stream))) { \
75 if (((p)->context && pa_context_get_state((p)->context) == PA_CONTEXT_FAILED) || \
76 ((p)->stream && pa_stream_get_state((p)->stream) == PA_STREAM_FAILED)) { \
77 if (rerror) \
78 *(rerror) = pa_context_errno((p)->context); \
79 } else \
80 if (rerror) \
81 *(rerror) = PA_ERR_BADSTATE; \
82 goto label; \
83 } \
84 } while(FALSE);
85
86 static void context_state_cb(pa_context *c, void *userdata) {
87 pa_simple *p = userdata;
88 pa_assert(c);
89 pa_assert(p);
90
91 switch (pa_context_get_state(c)) {
92 case PA_CONTEXT_READY:
93 case PA_CONTEXT_TERMINATED:
94 case PA_CONTEXT_FAILED:
95 pa_threaded_mainloop_signal(p->mainloop, 0);
96 break;
97
98 case PA_CONTEXT_UNCONNECTED:
99 case PA_CONTEXT_CONNECTING:
100 case PA_CONTEXT_AUTHORIZING:
101 case PA_CONTEXT_SETTING_NAME:
102 break;
103 }
104 }
105
106 static void stream_state_cb(pa_stream *s, void * userdata) {
107 pa_simple *p = userdata;
108 pa_assert(s);
109 pa_assert(p);
110
111 switch (pa_stream_get_state(s)) {
112
113 case PA_STREAM_READY:
114 case PA_STREAM_FAILED:
115 case PA_STREAM_TERMINATED:
116 pa_threaded_mainloop_signal(p->mainloop, 0);
117 break;
118
119 case PA_STREAM_UNCONNECTED:
120 case PA_STREAM_CREATING:
121 break;
122 }
123 }
124
125 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
126 pa_simple *p = userdata;
127 pa_assert(p);
128
129 pa_threaded_mainloop_signal(p->mainloop, 0);
130 }
131
132 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
133 pa_simple *p = userdata;
134
135 pa_assert(p);
136
137 pa_threaded_mainloop_signal(p->mainloop, 0);
138 }
139
140 pa_simple* pa_simple_new(
141 const char *server,
142 const char *name,
143 pa_stream_direction_t dir,
144 const char *dev,
145 const char *stream_name,
146 const pa_sample_spec *ss,
147 const pa_channel_map *map,
148 const pa_buffer_attr *attr,
149 int *rerror) {
150
151 pa_simple *p;
152 int error = PA_ERR_INTERNAL, r;
153
154 CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
155 CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
156 CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
157 CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
158 CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL)
159
160 p = pa_xnew0(pa_simple, 1);
161 p->direction = dir;
162
163 if (!(p->mainloop = pa_threaded_mainloop_new()))
164 goto fail;
165
166 if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
167 goto fail;
168
169 pa_context_set_state_callback(p->context, context_state_cb, p);
170
171 if (pa_context_connect(p->context, server, 0, NULL) < 0) {
172 error = pa_context_errno(p->context);
173 goto fail;
174 }
175
176 pa_threaded_mainloop_lock(p->mainloop);
177
178 if (pa_threaded_mainloop_start(p->mainloop) < 0)
179 goto unlock_and_fail;
180
181 for (;;) {
182 pa_context_state_t state;
183
184 state = pa_context_get_state(p->context);
185
186 if (state == PA_CONTEXT_READY)
187 break;
188
189 if (!PA_CONTEXT_IS_GOOD(state)) {
190 error = pa_context_errno(p->context);
191 goto unlock_and_fail;
192 }
193
194 /* Wait until the context is ready */
195 pa_threaded_mainloop_wait(p->mainloop);
196 }
197
198 if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
199 error = pa_context_errno(p->context);
200 goto unlock_and_fail;
201 }
202
203 pa_stream_set_state_callback(p->stream, stream_state_cb, p);
204 pa_stream_set_read_callback(p->stream, stream_request_cb, p);
205 pa_stream_set_write_callback(p->stream, stream_request_cb, p);
206 pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
207
208 if (dir == PA_STREAM_PLAYBACK)
209 r = pa_stream_connect_playback(p->stream, dev, attr,
210 PA_STREAM_INTERPOLATE_TIMING
211 |PA_STREAM_ADJUST_LATENCY
212 |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
213 else
214 r = pa_stream_connect_record(p->stream, dev, attr,
215 PA_STREAM_INTERPOLATE_TIMING
216 |PA_STREAM_ADJUST_LATENCY
217 |PA_STREAM_AUTO_TIMING_UPDATE);
218
219 if (r < 0) {
220 error = pa_context_errno(p->context);
221 goto unlock_and_fail;
222 }
223
224 for (;;) {
225 pa_stream_state_t state;
226
227 state = pa_stream_get_state(p->stream);
228
229 if (state == PA_STREAM_READY)
230 break;
231
232 if (!PA_STREAM_IS_GOOD(state)) {
233 error = pa_context_errno(p->context);
234 goto unlock_and_fail;
235 }
236
237 /* Wait until the stream is ready */
238 pa_threaded_mainloop_wait(p->mainloop);
239 }
240
241 pa_threaded_mainloop_unlock(p->mainloop);
242
243 return p;
244
245 unlock_and_fail:
246 pa_threaded_mainloop_unlock(p->mainloop);
247
248 fail:
249 if (rerror)
250 *rerror = error;
251 pa_simple_free(p);
252 return NULL;
253 }
254
255 void pa_simple_free(pa_simple *s) {
256 pa_assert(s);
257
258 if (s->mainloop)
259 pa_threaded_mainloop_stop(s->mainloop);
260
261 if (s->stream)
262 pa_stream_unref(s->stream);
263
264 if (s->context) {
265 pa_context_disconnect(s->context);
266 pa_context_unref(s->context);
267 }
268
269 if (s->mainloop)
270 pa_threaded_mainloop_free(s->mainloop);
271
272 pa_xfree(s);
273 }
274
275 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
276 pa_assert(p);
277
278 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
279 CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1);
280 CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1);
281
282 pa_threaded_mainloop_lock(p->mainloop);
283
284 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
285
286 while (length > 0) {
287 size_t l;
288 int r;
289
290 while (!(l = pa_stream_writable_size(p->stream))) {
291 pa_threaded_mainloop_wait(p->mainloop);
292 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
293 }
294
295 CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
296
297 if (l > length)
298 l = length;
299
300 r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
301 CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
302
303 data = (const uint8_t*) data + l;
304 length -= l;
305 }
306
307 pa_threaded_mainloop_unlock(p->mainloop);
308 return 0;
309
310 unlock_and_fail:
311 pa_threaded_mainloop_unlock(p->mainloop);
312 return -1;
313 }
314
315 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
316 pa_assert(p);
317
318 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
319 CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1);
320 CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1);
321
322 pa_threaded_mainloop_lock(p->mainloop);
323
324 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
325
326 while (length > 0) {
327 size_t l;
328
329 while (!p->read_data) {
330 int r;
331
332 r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
333 CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
334
335 if (!p->read_data) {
336 pa_threaded_mainloop_wait(p->mainloop);
337 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
338 } else
339 p->read_index = 0;
340 }
341
342 l = p->read_length < length ? p->read_length : length;
343 memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
344
345 data = (uint8_t*) data + l;
346 length -= l;
347
348 p->read_index += l;
349 p->read_length -= l;
350
351 if (!p->read_length) {
352 int r;
353
354 r = pa_stream_drop(p->stream);
355 p->read_data = NULL;
356 p->read_length = 0;
357 p->read_index = 0;
358
359 CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
360 }
361 }
362
363 pa_threaded_mainloop_unlock(p->mainloop);
364 return 0;
365
366 unlock_and_fail:
367 pa_threaded_mainloop_unlock(p->mainloop);
368 return -1;
369 }
370
371 static void success_cb(pa_stream *s, int success, void *userdata) {
372 pa_simple *p = userdata;
373
374 pa_assert(s);
375 pa_assert(p);
376
377 p->operation_success = success;
378 pa_threaded_mainloop_signal(p->mainloop, 0);
379 }
380
381 int pa_simple_drain(pa_simple *p, int *rerror) {
382 pa_operation *o = NULL;
383
384 pa_assert(p);
385
386 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
387
388 pa_threaded_mainloop_lock(p->mainloop);
389 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
390
391 o = pa_stream_drain(p->stream, success_cb, p);
392 CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
393
394 p->operation_success = 0;
395 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
396 pa_threaded_mainloop_wait(p->mainloop);
397 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
398 }
399 CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
400
401 pa_operation_unref(o);
402 pa_threaded_mainloop_unlock(p->mainloop);
403
404 return 0;
405
406 unlock_and_fail:
407
408 if (o) {
409 pa_operation_cancel(o);
410 pa_operation_unref(o);
411 }
412
413 pa_threaded_mainloop_unlock(p->mainloop);
414 return -1;
415 }
416
417 int pa_simple_flush(pa_simple *p, int *rerror) {
418 pa_operation *o = NULL;
419
420 pa_assert(p);
421
422 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
423
424 pa_threaded_mainloop_lock(p->mainloop);
425 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
426
427 o = pa_stream_flush(p->stream, success_cb, p);
428 CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
429
430 p->operation_success = 0;
431 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
432 pa_threaded_mainloop_wait(p->mainloop);
433 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
434 }
435 CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
436
437 pa_operation_unref(o);
438 pa_threaded_mainloop_unlock(p->mainloop);
439
440 return 0;
441
442 unlock_and_fail:
443
444 if (o) {
445 pa_operation_cancel(o);
446 pa_operation_unref(o);
447 }
448
449 pa_threaded_mainloop_unlock(p->mainloop);
450 return -1;
451 }
452
453 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
454 pa_usec_t t;
455 int negative;
456
457 pa_assert(p);
458
459 pa_threaded_mainloop_lock(p->mainloop);
460
461 for (;;) {
462 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
463
464 if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
465 break;
466
467 CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
468
469 /* Wait until latency data is available again */
470 pa_threaded_mainloop_wait(p->mainloop);
471 }
472
473 pa_threaded_mainloop_unlock(p->mainloop);
474
475 return negative ? 0 : t;
476
477 unlock_and_fail:
478
479 pa_threaded_mainloop_unlock(p->mainloop);
480 return (pa_usec_t) -1;
481 }