Merge commit 'origin/master-tx'
[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) do { \
54 if (!(expression)) { \
55     if (rerror) \
56         *(rerror) = error; \
57     return (ret); \
58     }  \
59 } while(0);
60
61 #define CHECK_SUCCESS_GOTO(p, rerror, expression, label) do { \
62 if (!(expression)) { \
63     if (rerror) \
64         *(rerror) = pa_context_errno((p)->context); \
65     goto label; \
66     }  \
67 } while(0);
68
69 #define CHECK_DEAD_GOTO(p, rerror, label) do { \
70 if (!(p)->context || pa_context_get_state((p)->context) != PA_CONTEXT_READY || \
71     !(p)->stream || pa_stream_get_state((p)->stream) != PA_STREAM_READY) { \
72         if (((p)->context && pa_context_get_state((p)->context) == PA_CONTEXT_FAILED) || \
73             ((p)->stream && pa_stream_get_state((p)->stream) == PA_STREAM_FAILED)) { \
74             if (rerror) \
75                 *(rerror) = pa_context_errno((p)->context); \
76         } else \
77             if (rerror) \
78                 *(rerror) = PA_ERR_BADSTATE; \
79         goto label; \
80     } \
81 } while(0);
82
83 static void context_state_cb(pa_context *c, void *userdata) {
84     pa_simple *p = userdata;
85     pa_assert(c);
86     pa_assert(p);
87
88     switch (pa_context_get_state(c)) {
89         case PA_CONTEXT_READY:
90         case PA_CONTEXT_TERMINATED:
91         case PA_CONTEXT_FAILED:
92             pa_threaded_mainloop_signal(p->mainloop, 0);
93             break;
94
95         case PA_CONTEXT_UNCONNECTED:
96         case PA_CONTEXT_CONNECTING:
97         case PA_CONTEXT_AUTHORIZING:
98         case PA_CONTEXT_SETTING_NAME:
99             break;
100     }
101 }
102
103 static void stream_state_cb(pa_stream *s, void * userdata) {
104     pa_simple *p = userdata;
105     pa_assert(s);
106     pa_assert(p);
107
108     switch (pa_stream_get_state(s)) {
109
110         case PA_STREAM_READY:
111         case PA_STREAM_FAILED:
112         case PA_STREAM_TERMINATED:
113             pa_threaded_mainloop_signal(p->mainloop, 0);
114             break;
115
116         case PA_STREAM_UNCONNECTED:
117         case PA_STREAM_CREATING:
118             break;
119     }
120 }
121
122 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
123     pa_simple *p = userdata;
124     pa_assert(p);
125
126     pa_threaded_mainloop_signal(p->mainloop, 0);
127 }
128
129 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
130     pa_simple *p = userdata;
131
132     pa_assert(p);
133
134     pa_threaded_mainloop_signal(p->mainloop, 0);
135 }
136
137 pa_simple* pa_simple_new(
138         const char *server,
139         const char *name,
140         pa_stream_direction_t dir,
141         const char *dev,
142         const char *stream_name,
143         const pa_sample_spec *ss,
144         const pa_channel_map *map,
145         const pa_buffer_attr *attr,
146         int *rerror) {
147
148     pa_simple *p;
149     int error = PA_ERR_INTERNAL, r;
150
151     CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
152     CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
153     CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
154     CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
155     CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL)
156
157     p = pa_xnew(pa_simple, 1);
158     p->context = NULL;
159     p->stream = NULL;
160     p->direction = dir;
161     p->read_data = NULL;
162     p->read_index = p->read_length = 0;
163
164     if (!(p->mainloop = pa_threaded_mainloop_new()))
165         goto fail;
166
167     if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
168         goto fail;
169
170     pa_context_set_state_callback(p->context, context_state_cb, p);
171
172     if (pa_context_connect(p->context, server, 0, NULL) < 0) {
173         error = pa_context_errno(p->context);
174         goto fail;
175     }
176
177     pa_threaded_mainloop_lock(p->mainloop);
178
179     if (pa_threaded_mainloop_start(p->mainloop) < 0)
180         goto unlock_and_fail;
181
182     /* Wait until the context is ready */
183     pa_threaded_mainloop_wait(p->mainloop);
184
185     if (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
186         error = pa_context_errno(p->context);
187         goto unlock_and_fail;
188     }
189
190     if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
191         error = pa_context_errno(p->context);
192         goto unlock_and_fail;
193     }
194
195     pa_stream_set_state_callback(p->stream, stream_state_cb, p);
196     pa_stream_set_read_callback(p->stream, stream_request_cb, p);
197     pa_stream_set_write_callback(p->stream, stream_request_cb, p);
198     pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
199
200     if (dir == PA_STREAM_PLAYBACK)
201         r = pa_stream_connect_playback(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
202     else
203         r = pa_stream_connect_record(p->stream, dev, attr, PA_STREAM_INTERPOLATE_TIMING|PA_STREAM_AUTO_TIMING_UPDATE);
204
205     if (r < 0) {
206         error = pa_context_errno(p->context);
207         goto unlock_and_fail;
208     }
209
210     /* Wait until the stream is ready */
211     pa_threaded_mainloop_wait(p->mainloop);
212
213     /* Wait until the stream is ready */
214     if (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
215         error = pa_context_errno(p->context);
216         goto unlock_and_fail;
217     }
218
219     pa_threaded_mainloop_unlock(p->mainloop);
220
221     return p;
222
223 unlock_and_fail:
224     pa_threaded_mainloop_unlock(p->mainloop);
225
226 fail:
227     if (rerror)
228         *rerror = error;
229     pa_simple_free(p);
230     return NULL;
231 }
232
233 void pa_simple_free(pa_simple *s) {
234     pa_assert(s);
235
236     if (s->mainloop)
237         pa_threaded_mainloop_stop(s->mainloop);
238
239     if (s->stream)
240         pa_stream_unref(s->stream);
241
242     if (s->context)
243         pa_context_unref(s->context);
244
245     if (s->mainloop)
246         pa_threaded_mainloop_free(s->mainloop);
247
248     pa_xfree(s);
249 }
250
251 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
252     pa_assert(p);
253
254     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
255     CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
256
257     pa_threaded_mainloop_lock(p->mainloop);
258
259     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
260
261     while (length > 0) {
262         size_t l;
263         int r;
264
265         while (!(l = pa_stream_writable_size(p->stream))) {
266             pa_threaded_mainloop_wait(p->mainloop);
267             CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
268         }
269
270         CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
271
272         if (l > length)
273             l = length;
274
275         r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
276         CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
277
278         data = (const uint8_t*) data + l;
279         length -= l;
280     }
281
282     pa_threaded_mainloop_unlock(p->mainloop);
283     return 0;
284
285 unlock_and_fail:
286     pa_threaded_mainloop_unlock(p->mainloop);
287     return -1;
288 }
289
290 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
291     pa_assert(p);
292
293     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
294     CHECK_VALIDITY_RETURN_ANY(rerror, data && length, PA_ERR_INVALID, -1);
295
296     pa_threaded_mainloop_lock(p->mainloop);
297
298     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
299
300     while (length > 0) {
301         size_t l;
302
303         while (!p->read_data) {
304             int r;
305
306             r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
307             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
308
309             if (!p->read_data) {
310                 pa_threaded_mainloop_wait(p->mainloop);
311                 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
312             } else
313                 p->read_index = 0;
314         }
315
316         l = p->read_length < length ? p->read_length : length;
317         memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
318
319         data = (uint8_t*) data + l;
320         length -= l;
321
322         p->read_index += l;
323         p->read_length -= l;
324
325         if (!p->read_length) {
326             int r;
327
328             r = pa_stream_drop(p->stream);
329             p->read_data = NULL;
330             p->read_length = 0;
331             p->read_index = 0;
332
333             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
334         }
335     }
336
337     pa_threaded_mainloop_unlock(p->mainloop);
338     return 0;
339
340 unlock_and_fail:
341     pa_threaded_mainloop_unlock(p->mainloop);
342     return -1;
343 }
344
345 static void success_cb(pa_stream *s, int success, void *userdata) {
346     pa_simple *p = userdata;
347
348     pa_assert(s);
349     pa_assert(p);
350
351     p->operation_success = success;
352     pa_threaded_mainloop_signal(p->mainloop, 0);
353 }
354
355 int pa_simple_drain(pa_simple *p, int *rerror) {
356     pa_operation *o = NULL;
357
358     pa_assert(p);
359
360     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
361
362     pa_threaded_mainloop_lock(p->mainloop);
363     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
364
365     o = pa_stream_drain(p->stream, success_cb, p);
366     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
367
368     p->operation_success = 0;
369     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
370         pa_threaded_mainloop_wait(p->mainloop);
371         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
372     }
373     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
374
375     pa_operation_unref(o);
376     pa_threaded_mainloop_unlock(p->mainloop);
377
378     return 0;
379
380 unlock_and_fail:
381
382     if (o) {
383         pa_operation_cancel(o);
384         pa_operation_unref(o);
385     }
386
387     pa_threaded_mainloop_unlock(p->mainloop);
388     return -1;
389 }
390
391 int pa_simple_flush(pa_simple *p, int *rerror) {
392     pa_operation *o = NULL;
393
394     pa_assert(p);
395
396     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
397
398     pa_threaded_mainloop_lock(p->mainloop);
399     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
400
401     o = pa_stream_flush(p->stream, success_cb, p);
402     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
403
404     p->operation_success = 0;
405     while (pa_operation_get_state(o) != PA_OPERATION_DONE) {
406         pa_threaded_mainloop_wait(p->mainloop);
407         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
408     }
409     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
410
411     pa_operation_unref(o);
412     pa_threaded_mainloop_unlock(p->mainloop);
413
414     return 0;
415
416 unlock_and_fail:
417
418     if (o) {
419         pa_operation_cancel(o);
420         pa_operation_unref(o);
421     }
422
423     pa_threaded_mainloop_unlock(p->mainloop);
424     return -1;
425 }
426
427 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
428     pa_usec_t t;
429     int negative;
430
431     pa_assert(p);
432
433     pa_threaded_mainloop_lock(p->mainloop);
434
435     for (;;) {
436         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
437
438         if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
439             break;
440
441         CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
442
443         /* Wait until latency data is available again */
444         pa_threaded_mainloop_wait(p->mainloop);
445     }
446
447     pa_threaded_mainloop_unlock(p->mainloop);
448
449     return negative ? 0 : t;
450
451 unlock_and_fail:
452
453     pa_threaded_mainloop_unlock(p->mainloop);
454     return (pa_usec_t) -1;
455 }