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