simple: always loop around pa_threaded_mainloop_wait() to handle spurious wakeups...
[pulseaudio-mirror.git] / src / pulse / simple.c
blobc2014c5c95b2569928541310a6d2f059f0ea831c
2 /***
3 This file is part of PulseAudio.
5 Copyright 2004-2006 Lennart Poettering
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
31 #include <pulse/pulseaudio.h>
32 #include <pulse/thread-mainloop.h>
33 #include <pulse/xmalloc.h>
35 #include <pulsecore/native-common.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/macro.h>
39 #include "simple.h"
41 struct pa_simple {
42 pa_threaded_mainloop *mainloop;
43 pa_context *context;
44 pa_stream *stream;
45 pa_stream_direction_t direction;
47 const void *read_data;
48 size_t read_index, read_length;
50 int operation_success;
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);
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);
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);
86 static void context_state_cb(pa_context *c, void *userdata) {
87 pa_simple *p = userdata;
88 pa_assert(c);
89 pa_assert(p);
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;
98 case PA_CONTEXT_UNCONNECTED:
99 case PA_CONTEXT_CONNECTING:
100 case PA_CONTEXT_AUTHORIZING:
101 case PA_CONTEXT_SETTING_NAME:
102 break;
106 static void stream_state_cb(pa_stream *s, void * userdata) {
107 pa_simple *p = userdata;
108 pa_assert(s);
109 pa_assert(p);
111 switch (pa_stream_get_state(s)) {
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;
119 case PA_STREAM_UNCONNECTED:
120 case PA_STREAM_CREATING:
121 break;
125 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
126 pa_simple *p = userdata;
127 pa_assert(p);
129 pa_threaded_mainloop_signal(p->mainloop, 0);
132 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
133 pa_simple *p = userdata;
135 pa_assert(p);
137 pa_threaded_mainloop_signal(p->mainloop, 0);
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) {
151 pa_simple *p;
152 int error = PA_ERR_INTERNAL, r;
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)
160 p = pa_xnew0(pa_simple, 1);
161 p->direction = dir;
163 if (!(p->mainloop = pa_threaded_mainloop_new()))
164 goto fail;
166 if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
167 goto fail;
169 pa_context_set_state_callback(p->context, context_state_cb, p);
171 if (pa_context_connect(p->context, server, 0, NULL) < 0) {
172 error = pa_context_errno(p->context);
173 goto fail;
176 pa_threaded_mainloop_lock(p->mainloop);
178 if (pa_threaded_mainloop_start(p->mainloop) < 0)
179 goto unlock_and_fail;
181 for (;;) {
182 pa_context_state_t state;
184 state = pa_context_get_state(p->context);
186 if (state == PA_CONTEXT_READY)
187 break;
189 if (!PA_CONTEXT_IS_GOOD(state)) {
190 error = pa_context_errno(p->context);
191 goto unlock_and_fail;
194 /* Wait until the context is ready */
195 pa_threaded_mainloop_wait(p->mainloop);
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;
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);
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);
219 if (r < 0) {
220 error = pa_context_errno(p->context);
221 goto unlock_and_fail;
224 for (;;) {
225 pa_stream_state_t state;
227 state = pa_stream_get_state(p->stream);
229 if (state == PA_STREAM_READY)
230 break;
232 if (!PA_STREAM_IS_GOOD(state)) {
233 error = pa_context_errno(p->context);
234 goto unlock_and_fail;
237 /* Wait until the stream is ready */
238 pa_threaded_mainloop_wait(p->mainloop);
241 pa_threaded_mainloop_unlock(p->mainloop);
243 return p;
245 unlock_and_fail:
246 pa_threaded_mainloop_unlock(p->mainloop);
248 fail:
249 if (rerror)
250 *rerror = error;
251 pa_simple_free(p);
252 return NULL;
255 void pa_simple_free(pa_simple *s) {
256 pa_assert(s);
258 if (s->mainloop)
259 pa_threaded_mainloop_stop(s->mainloop);
261 if (s->stream)
262 pa_stream_unref(s->stream);
264 if (s->context)
265 pa_context_unref(s->context);
267 if (s->mainloop)
268 pa_threaded_mainloop_free(s->mainloop);
270 pa_xfree(s);
273 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
274 pa_assert(p);
276 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
277 CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
279 pa_threaded_mainloop_lock(p->mainloop);
281 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
283 while (length > 0) {
284 size_t l;
285 int r;
287 while (!(l = pa_stream_writable_size(p->stream))) {
288 pa_threaded_mainloop_wait(p->mainloop);
289 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
292 CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
294 if (l > length)
295 l = length;
297 r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
298 CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
300 data = (const uint8_t*) data + l;
301 length -= l;
304 pa_threaded_mainloop_unlock(p->mainloop);
305 return 0;
307 unlock_and_fail:
308 pa_threaded_mainloop_unlock(p->mainloop);
309 return -1;
312 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
313 pa_assert(p);
315 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
316 CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
318 pa_threaded_mainloop_lock(p->mainloop);
320 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
322 while (length > 0) {
323 size_t l;
325 while (!p->read_data) {
326 int r;
328 r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
329 CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
331 if (!p->read_data) {
332 pa_threaded_mainloop_wait(p->mainloop);
333 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
334 } else
335 p->read_index = 0;
338 l = p->read_length < length ? p->read_length : length;
339 memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
341 data = (uint8_t*) data + l;
342 length -= l;
344 p->read_index += l;
345 p->read_length -= l;
347 if (!p->read_length) {
348 int r;
350 r = pa_stream_drop(p->stream);
351 p->read_data = NULL;
352 p->read_length = 0;
353 p->read_index = 0;
355 CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
359 pa_threaded_mainloop_unlock(p->mainloop);
360 return 0;
362 unlock_and_fail:
363 pa_threaded_mainloop_unlock(p->mainloop);
364 return -1;
367 static void success_cb(pa_stream *s, int success, void *userdata) {
368 pa_simple *p = userdata;
370 pa_assert(s);
371 pa_assert(p);
373 p->operation_success = success;
374 pa_threaded_mainloop_signal(p->mainloop, 0);
377 int pa_simple_drain(pa_simple *p, int *rerror) {
378 pa_operation *o = NULL;
380 pa_assert(p);
382 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
384 pa_threaded_mainloop_lock(p->mainloop);
385 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
387 o = pa_stream_drain(p->stream, success_cb, p);
388 CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
390 p->operation_success = 0;
391 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
392 pa_threaded_mainloop_wait(p->mainloop);
393 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
395 CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
397 pa_operation_unref(o);
398 pa_threaded_mainloop_unlock(p->mainloop);
400 return 0;
402 unlock_and_fail:
404 if (o) {
405 pa_operation_cancel(o);
406 pa_operation_unref(o);
409 pa_threaded_mainloop_unlock(p->mainloop);
410 return -1;
413 int pa_simple_flush(pa_simple *p, int *rerror) {
414 pa_operation *o = NULL;
416 pa_assert(p);
418 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
420 pa_threaded_mainloop_lock(p->mainloop);
421 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
423 o = pa_stream_flush(p->stream, success_cb, p);
424 CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
426 p->operation_success = 0;
427 while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
428 pa_threaded_mainloop_wait(p->mainloop);
429 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
431 CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
433 pa_operation_unref(o);
434 pa_threaded_mainloop_unlock(p->mainloop);
436 return 0;
438 unlock_and_fail:
440 if (o) {
441 pa_operation_cancel(o);
442 pa_operation_unref(o);
445 pa_threaded_mainloop_unlock(p->mainloop);
446 return -1;
449 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
450 pa_usec_t t;
451 int negative;
453 pa_assert(p);
455 pa_threaded_mainloop_lock(p->mainloop);
457 for (;;) {
458 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
460 if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
461 break;
463 CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
465 /* Wait until latency data is available again */
466 pa_threaded_mainloop_wait(p->mainloop);
469 pa_threaded_mainloop_unlock(p->mainloop);
471 return negative ? 0 : t;
473 unlock_and_fail:
475 pa_threaded_mainloop_unlock(p->mainloop);
476 return (pa_usec_t) -1;