Merge branch 'master' of git://0pointer.de/pulseaudio
[profile/ivi/pulseaudio.git] / 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 }