Merge commit 'flameeyes/master'
[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_get_state((p)->context) != PA_CONTEXT_READY || \
74             !(p)->stream || pa_stream_get_state((p)->stream) != PA_STREAM_READY) { \
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_xnew(pa_simple, 1);
161     p->context = NULL;
162     p->stream = NULL;
163     p->direction = dir;
164     p->read_data = NULL;
165     p->read_index = p->read_length = 0;
166
167     if (!(p->mainloop = pa_threaded_mainloop_new()))
168         goto fail;
169
170     if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
171         goto fail;
172
173     pa_context_set_state_callback(p->context, context_state_cb, p);
174
175     if (pa_context_connect(p->context, server, 0, NULL) < 0) {
176         error = pa_context_errno(p->context);
177         goto fail;
178     }
179
180     pa_threaded_mainloop_lock(p->mainloop);
181
182     if (pa_threaded_mainloop_start(p->mainloop) < 0)
183         goto unlock_and_fail;
184
185     /* Wait until the context is ready */
186     pa_threaded_mainloop_wait(p->mainloop);
187
188     if (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
189         error = pa_context_errno(p->context);
190         goto unlock_and_fail;
191     }
192
193     if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
194         error = pa_context_errno(p->context);
195         goto unlock_and_fail;
196     }
197
198     pa_stream_set_state_callback(p->stream, stream_state_cb, p);
199     pa_stream_set_read_callback(p->stream, stream_request_cb, p);
200     pa_stream_set_write_callback(p->stream, stream_request_cb, p);
201     pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
202
203     if (dir == PA_STREAM_PLAYBACK)
204         r = pa_stream_connect_playback(p->stream, dev, attr,
205                                        PA_STREAM_INTERPOLATE_TIMING
206                                        |PA_STREAM_ADJUST_LATENCY
207                                        |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
208     else
209         r = pa_stream_connect_record(p->stream, dev, attr,
210                                      PA_STREAM_INTERPOLATE_TIMING
211                                      |PA_STREAM_ADJUST_LATENCY
212                                      |PA_STREAM_AUTO_TIMING_UPDATE);
213
214     if (r < 0) {
215         error = pa_context_errno(p->context);
216         goto unlock_and_fail;
217     }
218
219     /* Wait until the stream is ready */
220     pa_threaded_mainloop_wait(p->mainloop);
221
222     /* Wait until the stream is ready */
223     if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
224         error = pa_context_errno(p->context);
225         goto unlock_and_fail;
226     }
227
228     pa_threaded_mainloop_unlock(p->mainloop);
229
230     return p;
231
232 unlock_and_fail:
233     pa_threaded_mainloop_unlock(p->mainloop);
234
235 fail:
236     if (rerror)
237         *rerror = error;
238     pa_simple_free(p);
239     return NULL;
240 }
241
242 void pa_simple_free(pa_simple *s) {
243     pa_assert(s);
244
245     if (s->mainloop)
246         pa_threaded_mainloop_stop(s->mainloop);
247
248     if (s->stream)
249         pa_stream_unref(s->stream);
250
251     if (s->context)
252         pa_context_unref(s->context);
253
254     if (s->mainloop)
255         pa_threaded_mainloop_free(s->mainloop);
256
257     pa_xfree(s);
258 }
259
260 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
261     pa_assert(p);
262
263     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
264     CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
265
266     pa_threaded_mainloop_lock(p->mainloop);
267
268     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
269
270     while (length > 0) {
271         size_t l;
272         int r;
273
274         while (!(l = pa_stream_writable_size(p->stream))) {
275             pa_threaded_mainloop_wait(p->mainloop);
276             CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
277         }
278
279         CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
280
281         if (l > length)
282             l = length;
283
284         r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
285         CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
286
287         data = (const uint8_t*) data + l;
288         length -= l;
289     }
290
291     pa_threaded_mainloop_unlock(p->mainloop);
292     return 0;
293
294 unlock_and_fail:
295     pa_threaded_mainloop_unlock(p->mainloop);
296     return -1;
297 }
298
299 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
300     pa_assert(p);
301
302     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
303     CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
304
305     pa_threaded_mainloop_lock(p->mainloop);
306
307     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
308
309     while (length > 0) {
310         size_t l;
311
312         while (!p->read_data) {
313             int r;
314
315             r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
316             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
317
318             if (!p->read_data) {
319                 pa_threaded_mainloop_wait(p->mainloop);
320                 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
321             } else
322                 p->read_index = 0;
323         }
324
325         l = p->read_length < length ? p->read_length : length;
326         memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
327
328         data = (uint8_t*) data + l;
329         length -= l;
330
331         p->read_index += l;
332         p->read_length -= l;
333
334         if (!p->read_length) {
335             int r;
336
337             r = pa_stream_drop(p->stream);
338             p->read_data = NULL;
339             p->read_length = 0;
340             p->read_index = 0;
341
342             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
343         }
344     }
345
346     pa_threaded_mainloop_unlock(p->mainloop);
347     return 0;
348
349 unlock_and_fail:
350     pa_threaded_mainloop_unlock(p->mainloop);
351     return -1;
352 }
353
354 static void success_cb(pa_stream *s, int success, void *userdata) {
355     pa_simple *p = userdata;
356
357     pa_assert(s);
358     pa_assert(p);
359
360     p->operation_success = success;
361     pa_threaded_mainloop_signal(p->mainloop, 0);
362 }
363
364 int pa_simple_drain(pa_simple *p, int *rerror) {
365     pa_operation *o = NULL;
366
367     pa_assert(p);
368
369     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
370
371     pa_threaded_mainloop_lock(p->mainloop);
372     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
373
374     o = pa_stream_drain(p->stream, success_cb, p);
375     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
376
377     p->operation_success = 0;
378     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
379         pa_threaded_mainloop_wait(p->mainloop);
380         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
381     }
382     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
383
384     pa_operation_unref(o);
385     pa_threaded_mainloop_unlock(p->mainloop);
386
387     return 0;
388
389 unlock_and_fail:
390
391     if (o) {
392         pa_operation_cancel(o);
393         pa_operation_unref(o);
394     }
395
396     pa_threaded_mainloop_unlock(p->mainloop);
397     return -1;
398 }
399
400 int pa_simple_flush(pa_simple *p, int *rerror) {
401     pa_operation *o = NULL;
402
403     pa_assert(p);
404
405     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
406
407     pa_threaded_mainloop_lock(p->mainloop);
408     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
409
410     o = pa_stream_flush(p->stream, success_cb, p);
411     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
412
413     p->operation_success = 0;
414     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
415         pa_threaded_mainloop_wait(p->mainloop);
416         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
417     }
418     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
419
420     pa_operation_unref(o);
421     pa_threaded_mainloop_unlock(p->mainloop);
422
423     return 0;
424
425 unlock_and_fail:
426
427     if (o) {
428         pa_operation_cancel(o);
429         pa_operation_unref(o);
430     }
431
432     pa_threaded_mainloop_unlock(p->mainloop);
433     return -1;
434 }
435
436 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
437     pa_usec_t t;
438     int negative;
439
440     pa_assert(p);
441
442     pa_threaded_mainloop_lock(p->mainloop);
443
444     for (;;) {
445         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
446
447         if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
448             break;
449
450         CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
451
452         /* Wait until latency data is available again */
453         pa_threaded_mainloop_wait(p->mainloop);
454     }
455
456     pa_threaded_mainloop_unlock(p->mainloop);
457
458     return negative ? 0 : t;
459
460 unlock_and_fail:
461
462     pa_threaded_mainloop_unlock(p->mainloop);
463     return (pa_usec_t) -1;
464 }