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