]> code.delx.au - pulseaudio/blob - src/polyp/simple.c
Clarify behaviour of deferred events.
[pulseaudio] / src / polyp / simple.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <stdlib.h>
30
31 #include <polyp/polypaudio.h>
32 #include <polyp/mainloop.h>
33
34 #include <polypcore/native-common.h>
35 #include <polypcore/xmalloc.h>
36 #include <polypcore/log.h>
37
38 #include "simple.h"
39
40 #define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret) do { \
41 if (!(expression)) { \
42 if (rerror) \
43 *(rerror) = error; \
44 return ret; \
45 } \
46 } while(0);
47
48 struct pa_simple {
49 pa_mainloop *mainloop;
50 pa_context *context;
51 pa_stream *stream;
52 pa_stream_direction_t direction;
53
54 int dead;
55
56 const void *read_data;
57 size_t read_index, read_length;
58 pa_usec_t latency;
59 };
60
61 static int check_error(pa_simple *p, int *rerror) {
62 pa_context_state_t cst;
63 pa_stream_state_t sst;
64 assert(p);
65
66 if ((cst = pa_context_get_state(p->context)) == PA_CONTEXT_FAILED)
67 goto fail;
68
69 assert(cst != PA_CONTEXT_TERMINATED);
70
71 if (p->stream) {
72 if ((sst = pa_stream_get_state(p->stream)) == PA_STREAM_FAILED)
73 goto fail;
74
75 assert(sst != PA_STREAM_TERMINATED);
76 }
77
78 return 0;
79
80 fail:
81 if (rerror)
82 *rerror = pa_context_errno(p->context);
83
84 p->dead = 1;
85
86 return -1;
87 }
88
89 static int iterate(pa_simple *p, int block, int *rerror) {
90 assert(p && p->context && p->mainloop);
91
92 if (check_error(p, rerror) < 0)
93 return -1;
94
95 if (block || pa_context_is_pending(p->context)) {
96 do {
97 if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) {
98 if (rerror)
99 *rerror = PA_ERR_INTERNAL;
100 return -1;
101 }
102
103 if (check_error(p, rerror) < 0)
104 return -1;
105 } while (pa_context_is_pending(p->context));
106 }
107
108 for (;;) {
109 int r;
110
111 if ((r = pa_mainloop_iterate(p->mainloop, 0, NULL)) < 0) {
112 if (rerror)
113 *rerror = PA_ERR_INTERNAL;
114 return -1;
115 }
116
117 if (r == 0)
118 break;
119
120 if (check_error(p, rerror) < 0)
121 return -1;
122 }
123
124 return 0;
125 }
126
127 pa_simple* pa_simple_new(
128 const char *server,
129 const char *name,
130 pa_stream_direction_t dir,
131 const char *dev,
132 const char *stream_name,
133 const pa_sample_spec *ss,
134 const pa_buffer_attr *attr,
135 int *rerror) {
136
137 pa_simple *p;
138 int error = PA_ERR_INTERNAL, r;
139
140 CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
141 CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
142 CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
143 CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
144
145 p = pa_xnew(pa_simple, 1);
146 p->context = NULL;
147 p->stream = NULL;
148 p->mainloop = pa_mainloop_new();
149 assert(p->mainloop);
150 p->dead = 0;
151 p->direction = dir;
152 p->read_data = NULL;
153 p->read_index = p->read_length = 0;
154 p->latency = 0;
155
156 if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name)))
157 goto fail;
158
159 if (pa_context_connect(p->context, server, 0, NULL) < 0) {
160 error = pa_context_errno(p->context);
161 goto fail;
162 }
163
164 /* Wait until the context is ready */
165 while (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
166 if (iterate(p, 1, &error) < 0)
167 goto fail;
168 }
169
170 if (!(p->stream = pa_stream_new(p->context, stream_name, ss, NULL))) {
171 error = pa_context_errno(p->context);
172 goto fail;
173 }
174
175 if (dir == PA_STREAM_PLAYBACK)
176 r = pa_stream_connect_playback(p->stream, dev, attr, 0, NULL, NULL);
177 else
178 r = pa_stream_connect_record(p->stream, dev, attr, 0);
179
180 if (r < 0) {
181 error = pa_context_errno(p->context);
182 goto fail;
183 }
184
185 /* Wait until the stream is ready */
186 while (pa_stream_get_state(p->stream) != PA_STREAM_READY) {
187 if (iterate(p, 1, &error) < 0)
188 goto fail;
189 }
190
191 return p;
192
193 fail:
194 if (rerror)
195 *rerror = error;
196 pa_simple_free(p);
197 return NULL;
198 }
199
200 void pa_simple_free(pa_simple *s) {
201 assert(s);
202
203 if (s->stream)
204 pa_stream_unref(s->stream);
205
206 if (s->context)
207 pa_context_unref(s->context);
208
209 if (s->mainloop)
210 pa_mainloop_free(s->mainloop);
211
212 pa_xfree(s);
213 }
214
215 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
216 assert(p);
217 assert(data);
218
219 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
220
221 if (p->dead) {
222 if (rerror)
223 *rerror = pa_context_errno(p->context);
224
225 return -1;
226 }
227
228 while (length > 0) {
229 size_t l;
230
231 while (!(l = pa_stream_writable_size(p->stream)))
232 if (iterate(p, 1, rerror) < 0)
233 return -1;
234
235 if (l > length)
236 l = length;
237
238 pa_stream_write(p->stream, data, l, NULL, 0, PA_SEEK_RELATIVE);
239 data = (const uint8_t*) data + l;
240 length -= l;
241 }
242
243 /* Make sure that no data is pending for write */
244 if (iterate(p, 0, rerror) < 0)
245 return -1;
246
247 return 0;
248 }
249
250 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
251 assert(p);
252 assert(data);
253
254 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
255
256 if (p->dead) {
257 if (rerror)
258 *rerror = pa_context_errno(p->context);
259
260 return -1;
261 }
262
263 while (length > 0) {
264
265 if (!p->read_data)
266 if (pa_stream_peek(p->stream, &p->read_data, &p->read_length) >= 0)
267 p->read_index = 0;
268
269 if (p->read_data) {
270 size_t l = length;
271
272 if (p->read_length <= l)
273 l = p->read_length;
274
275 memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
276
277 data = (uint8_t*) data + l;
278 length -= l;
279
280 p->read_index += l;
281 p->read_length -= l;
282
283 if (!p->read_length) {
284 pa_stream_drop(p->stream);
285 p->read_data = NULL;
286 p->read_length = 0;
287 p->read_index = 0;
288 }
289
290 if (!length)
291 return 0;
292
293 assert(!p->read_data);
294 }
295
296 if (iterate(p, 1, rerror) < 0)
297 return -1;
298 }
299
300 return 0;
301 }
302
303 static void drain_or_flush_complete(pa_stream *s, int success, void *userdata) {
304 pa_simple *p = userdata;
305
306 assert(s);
307 assert(p);
308
309 if (!success)
310 p->dead = 1;
311 }
312
313 int pa_simple_drain(pa_simple *p, int *rerror) {
314 pa_operation *o;
315
316 assert(p);
317
318 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
319
320 if (p->dead) {
321 if (rerror)
322 *rerror = pa_context_errno(p->context);
323
324 return -1;
325 }
326
327 if (!(o = pa_stream_drain(p->stream, drain_or_flush_complete, p))) {
328 if (rerror)
329 *rerror = pa_context_errno(p->context);
330 return -1;
331 }
332
333 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
334 if (iterate(p, 1, rerror) < 0) {
335 pa_operation_cancel(o);
336 pa_operation_unref(o);
337 return -1;
338 }
339 }
340
341 pa_operation_unref(o);
342
343 if (p->dead && rerror)
344 *rerror = pa_context_errno(p->context);
345
346 return p->dead ? -1 : 0;
347 }
348
349 static void timing_complete(pa_stream *s, int success, void *userdata) {
350 pa_simple *p = userdata;
351
352 assert(s);
353 assert(p);
354
355 if (!success)
356 p->dead = 1;
357 else {
358 int negative = 0;
359 if (pa_stream_get_latency(s, &p->latency, &negative) < 0)
360 p->dead = 1;
361 else if (negative)
362 p->latency = 0;
363 }
364 }
365
366 pa_usec_t pa_simple_get_playback_latency(pa_simple *p, int *rerror) {
367 pa_operation *o;
368
369 assert(p);
370
371 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
372
373 if (p->dead) {
374 if (rerror)
375 *rerror = pa_context_errno(p->context);
376
377 return (pa_usec_t) -1;
378 }
379
380 p->latency = 0;
381 if (!(o = pa_stream_update_timing_info(p->stream, timing_complete, p))) {
382 if (rerror)
383 *rerror = pa_context_errno(p->context);
384 return (pa_usec_t) -1;
385 }
386
387 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
388
389 if (iterate(p, 1, rerror) < 0) {
390 pa_operation_cancel(o);
391 pa_operation_unref(o);
392 return -1;
393 }
394 }
395
396 pa_operation_unref(o);
397
398 if (p->dead && rerror)
399 *rerror = pa_context_errno(p->context);
400
401 return p->dead ? (pa_usec_t) -1 : p->latency;
402 }
403
404 int pa_simple_flush(pa_simple *p, int *rerror) {
405 pa_operation *o;
406
407 assert(p);
408
409 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
410
411 if (p->dead) {
412 if (rerror)
413 *rerror = pa_context_errno(p->context);
414
415 return -1;
416 }
417
418 if (!(o = pa_stream_flush(p->stream, drain_or_flush_complete, p))) {
419 if (rerror)
420 *rerror = pa_context_errno(p->context);
421 return -1;
422 }
423
424 while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
425 if (iterate(p, 1, rerror) < 0) {
426 pa_operation_cancel(o);
427 pa_operation_unref(o);
428 return -1;
429 }
430 }
431
432 pa_operation_unref(o);
433
434 if (p->dead && rerror)
435 *rerror = pa_context_errno(p->context);
436
437 return p->dead ? -1 : 0;
438 }