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