Use LGPL 2.1 on all files previously using LGPL 2
[pulseaudio-mirror.git] / src / pulse / simple.c
blobe70b7b1fdb352b6e3cbe924ea225dd936b724e36
2 /***
3 This file is part of PulseAudio.
5 Copyright 2004-2006 Lennart Poettering
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.
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.
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 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
31 #include <pulse/pulseaudio.h>
32 #include <pulse/thread-mainloop.h>
33 #include <pulse/xmalloc.h>
35 #include <pulsecore/native-common.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/macro.h>
39 #include "simple.h"
41 struct pa_simple {
42 pa_threaded_mainloop *mainloop;
43 pa_context *context;
44 pa_stream *stream;
45 pa_stream_direction_t direction;
47 const void *read_data;
48 size_t read_index, read_length;
50 int operation_success;
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);
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);
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);
83 static void context_state_cb(pa_context *c, void *userdata) {
84 pa_simple *p = userdata;
85 pa_assert(c);
86 pa_assert(p);
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;
95 case PA_CONTEXT_UNCONNECTED:
96 case PA_CONTEXT_CONNECTING:
97 case PA_CONTEXT_AUTHORIZING:
98 case PA_CONTEXT_SETTING_NAME:
99 break;
103 static void stream_state_cb(pa_stream *s, void * userdata) {
104 pa_simple *p = userdata;
105 pa_assert(s);
106 pa_assert(p);
108 switch (pa_stream_get_state(s)) {
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;
116 case PA_STREAM_UNCONNECTED:
117 case PA_STREAM_CREATING:
118 break;
122 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
123 pa_simple *p = userdata;
124 pa_assert(p);
126 pa_threaded_mainloop_signal(p->mainloop, 0);
129 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
130 pa_simple *p = userdata;
132 pa_assert(p);
134 pa_threaded_mainloop_signal(p->mainloop, 0);
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) {
148 pa_simple *p;
149 int error = PA_ERR_INTERNAL, r;
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)
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;
164 if (!(p->mainloop = pa_threaded_mainloop_new()))
165 goto fail;
167 if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
168 goto fail;
170 pa_context_set_state_callback(p->context, context_state_cb, p);
172 if (pa_context_connect(p->context, server, 0, NULL) < 0) {
173 error = pa_context_errno(p->context);
174 goto fail;
177 pa_threaded_mainloop_lock(p->mainloop);
179 if (pa_threaded_mainloop_start(p->mainloop) < 0)
180 goto unlock_and_fail;
182 /* Wait until the context is ready */
183 pa_threaded_mainloop_wait(p->mainloop);
185 if (pa_context_get_state(p->context) != PA_CONTEXT_READY) {
186 error = pa_context_errno(p->context);
187 goto unlock_and_fail;
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;
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);
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);
205 if (r < 0) {
206 error = pa_context_errno(p->context);
207 goto unlock_and_fail;
210 /* Wait until the stream is ready */
211 pa_threaded_mainloop_wait(p->mainloop);
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;
219 pa_threaded_mainloop_unlock(p->mainloop);
221 return p;
223 unlock_and_fail:
224 pa_threaded_mainloop_unlock(p->mainloop);
226 fail:
227 if (rerror)
228 *rerror = error;
229 pa_simple_free(p);
230 return NULL;
233 void pa_simple_free(pa_simple *s) {
234 pa_assert(s);
236 if (s->mainloop)
237 pa_threaded_mainloop_stop(s->mainloop);
239 if (s->stream)
240 pa_stream_unref(s->stream);
242 if (s->context)
243 pa_context_unref(s->context);
245 if (s->mainloop)
246 pa_threaded_mainloop_free(s->mainloop);
248 pa_xfree(s);
251 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
252 pa_assert(p);
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);
257 pa_threaded_mainloop_lock(p->mainloop);
259 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
261 while (length > 0) {
262 size_t l;
263 int r;
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);
270 CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
272 if (l > length)
273 l = length;
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);
278 data = (const uint8_t*) data + l;
279 length -= l;
282 pa_threaded_mainloop_unlock(p->mainloop);
283 return 0;
285 unlock_and_fail:
286 pa_threaded_mainloop_unlock(p->mainloop);
287 return -1;
290 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
291 pa_assert(p);
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);
296 pa_threaded_mainloop_lock(p->mainloop);
298 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
300 while (length > 0) {
301 size_t l;
303 while (!p->read_data) {
304 int r;
306 r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
307 CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
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;
316 l = p->read_length < length ? p->read_length : length;
317 memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
319 data = (uint8_t*) data + l;
320 length -= l;
322 p->read_index += l;
323 p->read_length -= l;
325 if (!p->read_length) {
326 int r;
328 r = pa_stream_drop(p->stream);
329 p->read_data = NULL;
330 p->read_length = 0;
331 p->read_index = 0;
333 CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
337 pa_threaded_mainloop_unlock(p->mainloop);
338 return 0;
340 unlock_and_fail:
341 pa_threaded_mainloop_unlock(p->mainloop);
342 return -1;
345 static void success_cb(pa_stream *s, int success, void *userdata) {
346 pa_simple *p = userdata;
348 pa_assert(s);
349 pa_assert(p);
351 p->operation_success = success;
352 pa_threaded_mainloop_signal(p->mainloop, 0);
355 int pa_simple_drain(pa_simple *p, int *rerror) {
356 pa_operation *o = NULL;
358 pa_assert(p);
360 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
362 pa_threaded_mainloop_lock(p->mainloop);
363 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
365 o = pa_stream_drain(p->stream, success_cb, p);
366 CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
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);
373 CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
375 pa_operation_unref(o);
376 pa_threaded_mainloop_unlock(p->mainloop);
378 return 0;
380 unlock_and_fail:
382 if (o) {
383 pa_operation_cancel(o);
384 pa_operation_unref(o);
387 pa_threaded_mainloop_unlock(p->mainloop);
388 return -1;
391 int pa_simple_flush(pa_simple *p, int *rerror) {
392 pa_operation *o = NULL;
394 pa_assert(p);
396 CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
398 pa_threaded_mainloop_lock(p->mainloop);
399 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
401 o = pa_stream_flush(p->stream, success_cb, p);
402 CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
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);
409 CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
411 pa_operation_unref(o);
412 pa_threaded_mainloop_unlock(p->mainloop);
414 return 0;
416 unlock_and_fail:
418 if (o) {
419 pa_operation_cancel(o);
420 pa_operation_unref(o);
423 pa_threaded_mainloop_unlock(p->mainloop);
424 return -1;
427 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
428 pa_usec_t t;
429 int negative;
431 pa_assert(p);
433 pa_threaded_mainloop_lock(p->mainloop);
435 for (;;) {
436 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
438 if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
439 break;
441 CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
443 /* Wait until latency data is available again */
444 pa_threaded_mainloop_wait(p->mainloop);
447 pa_threaded_mainloop_unlock(p->mainloop);
449 return negative ? 0 : t;
451 unlock_and_fail:
453 pa_threaded_mainloop_unlock(p->mainloop);
454 return (pa_usec_t) -1;