c2014c5c95b2569928541310a6d2f059f0ea831c
[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_unref(s->context);
266
267     if (s->mainloop)
268         pa_threaded_mainloop_free(s->mainloop);
269
270     pa_xfree(s);
271 }
272
273 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
274     pa_assert(p);
275
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);
278
279     pa_threaded_mainloop_lock(p->mainloop);
280
281     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
282
283     while (length > 0) {
284         size_t l;
285         int r;
286
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);
290         }
291
292         CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
293
294         if (l > length)
295             l = length;
296
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);
299
300         data = (const uint8_t*) data + l;
301         length -= l;
302     }
303
304     pa_threaded_mainloop_unlock(p->mainloop);
305     return 0;
306
307 unlock_and_fail:
308     pa_threaded_mainloop_unlock(p->mainloop);
309     return -1;
310 }
311
312 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
313     pa_assert(p);
314
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);
317
318     pa_threaded_mainloop_lock(p->mainloop);
319
320     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
321
322     while (length > 0) {
323         size_t l;
324
325         while (!p->read_data) {
326             int r;
327
328             r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
329             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
330
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;
336         }
337
338         l = p->read_length < length ? p->read_length : length;
339         memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
340
341         data = (uint8_t*) data + l;
342         length -= l;
343
344         p->read_index += l;
345         p->read_length -= l;
346
347         if (!p->read_length) {
348             int r;
349
350             r = pa_stream_drop(p->stream);
351             p->read_data = NULL;
352             p->read_length = 0;
353             p->read_index = 0;
354
355             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
356         }
357     }
358
359     pa_threaded_mainloop_unlock(p->mainloop);
360     return 0;
361
362 unlock_and_fail:
363     pa_threaded_mainloop_unlock(p->mainloop);
364     return -1;
365 }
366
367 static void success_cb(pa_stream *s, int success, void *userdata) {
368     pa_simple *p = userdata;
369
370     pa_assert(s);
371     pa_assert(p);
372
373     p->operation_success = success;
374     pa_threaded_mainloop_signal(p->mainloop, 0);
375 }
376
377 int pa_simple_drain(pa_simple *p, int *rerror) {
378     pa_operation *o = NULL;
379
380     pa_assert(p);
381
382     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
383
384     pa_threaded_mainloop_lock(p->mainloop);
385     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
386
387     o = pa_stream_drain(p->stream, success_cb, p);
388     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
389
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);
394     }
395     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
396
397     pa_operation_unref(o);
398     pa_threaded_mainloop_unlock(p->mainloop);
399
400     return 0;
401
402 unlock_and_fail:
403
404     if (o) {
405         pa_operation_cancel(o);
406         pa_operation_unref(o);
407     }
408
409     pa_threaded_mainloop_unlock(p->mainloop);
410     return -1;
411 }
412
413 int pa_simple_flush(pa_simple *p, int *rerror) {
414     pa_operation *o = NULL;
415
416     pa_assert(p);
417
418     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
419
420     pa_threaded_mainloop_lock(p->mainloop);
421     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
422
423     o = pa_stream_flush(p->stream, success_cb, p);
424     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
425
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);
430     }
431     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
432
433     pa_operation_unref(o);
434     pa_threaded_mainloop_unlock(p->mainloop);
435
436     return 0;
437
438 unlock_and_fail:
439
440     if (o) {
441         pa_operation_cancel(o);
442         pa_operation_unref(o);
443     }
444
445     pa_threaded_mainloop_unlock(p->mainloop);
446     return -1;
447 }
448
449 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
450     pa_usec_t t;
451     int negative;
452
453     pa_assert(p);
454
455     pa_threaded_mainloop_lock(p->mainloop);
456
457     for (;;) {
458         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
459
460         if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
461             break;
462
463         CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
464
465         /* Wait until latency data is available again */
466         pa_threaded_mainloop_wait(p->mainloop);
467     }
468
469     pa_threaded_mainloop_unlock(p->mainloop);
470
471     return negative ? 0 : t;
472
473 unlock_and_fail:
474
475     pa_threaded_mainloop_unlock(p->mainloop);
476     return (pa_usec_t) -1;
477 }