3c188e02b3dd5b97f259c3baf3006013996c6f45
[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/log.h>
36 #include <pulsecore/macro.h>
37
38 #include "simple.h"
39
40 #include "internal.h"
41
42 struct pa_simple {
43     pa_threaded_mainloop *mainloop;
44     pa_context *context;
45     pa_stream *stream;
46     pa_stream_direction_t direction;
47
48     const void *read_data;
49     size_t read_index, read_length;
50
51     int operation_success;
52 };
53
54 #define CHECK_VALIDITY_RETURN_ANY(rerror, expression, error, ret)       \
55     do {                                                                \
56         if (!(expression)) {                                            \
57             if (rerror)                                                 \
58                 *(rerror) = error;                                      \
59             return (ret);                                               \
60         }                                                               \
61     } while(FALSE);
62
63 #define CHECK_SUCCESS_GOTO(p, rerror, expression, label)        \
64     do {                                                        \
65         if (!(expression)) {                                    \
66             if (rerror)                                         \
67                 *(rerror) = pa_context_errno((p)->context);     \
68             goto label;                                         \
69         }                                                       \
70     } while(FALSE);
71
72 #define CHECK_DEAD_GOTO(p, rerror, label)                               \
73     do {                                                                \
74         if (!(p)->context || !PA_CONTEXT_IS_GOOD(pa_context_get_state((p)->context)) || \
75             !(p)->stream || !PA_STREAM_IS_GOOD(pa_stream_get_state((p)->stream))) { \
76             if (((p)->context && pa_context_get_state((p)->context) == PA_CONTEXT_FAILED) || \
77                 ((p)->stream && pa_stream_get_state((p)->stream) == PA_STREAM_FAILED)) { \
78                 if (rerror)                                             \
79                     *(rerror) = pa_context_errno((p)->context);         \
80             } else                                                      \
81                 if (rerror)                                             \
82                     *(rerror) = PA_ERR_BADSTATE;                        \
83             goto label;                                                 \
84         }                                                               \
85     } while(FALSE);
86
87 static void context_state_cb(pa_context *c, void *userdata) {
88     pa_simple *p = userdata;
89     pa_assert(c);
90     pa_assert(p);
91
92     switch (pa_context_get_state(c)) {
93         case PA_CONTEXT_READY:
94         case PA_CONTEXT_TERMINATED:
95         case PA_CONTEXT_FAILED:
96             pa_threaded_mainloop_signal(p->mainloop, 0);
97             break;
98
99         case PA_CONTEXT_UNCONNECTED:
100         case PA_CONTEXT_CONNECTING:
101         case PA_CONTEXT_AUTHORIZING:
102         case PA_CONTEXT_SETTING_NAME:
103             break;
104     }
105 }
106
107 static void success_context_cb(pa_context *c, int success, void *userdata) {
108     pa_simple *p = userdata;
109     pa_assert(c);
110     pa_assert(p);
111
112     p->operation_success = success;
113     pa_threaded_mainloop_signal(p->mainloop, 0);
114 }
115
116 static void stream_state_cb(pa_stream *s, void * userdata) {
117     pa_simple *p = userdata;
118     pa_assert(s);
119     pa_assert(p);
120
121     switch (pa_stream_get_state(s)) {
122
123         case PA_STREAM_READY:
124         case PA_STREAM_FAILED:
125         case PA_STREAM_TERMINATED:
126             pa_threaded_mainloop_signal(p->mainloop, 0);
127             break;
128
129         case PA_STREAM_UNCONNECTED:
130         case PA_STREAM_CREATING:
131             break;
132     }
133 }
134
135 static void stream_request_cb(pa_stream *s, size_t length, void *userdata) {
136     pa_simple *p = userdata;
137     pa_assert(p);
138
139     pa_threaded_mainloop_signal(p->mainloop, 0);
140 }
141
142 static void stream_latency_update_cb(pa_stream *s, void *userdata) {
143     pa_simple *p = userdata;
144
145     pa_assert(p);
146
147     pa_threaded_mainloop_signal(p->mainloop, 0);
148 }
149
150 pa_simple* pa_simple_new(
151         const char *server,
152         const char *name,
153         pa_stream_direction_t dir,
154         const char *dev,
155         const char *stream_name,
156         const pa_sample_spec *ss,
157         const pa_channel_map *map,
158         const pa_buffer_attr *attr,
159         int *rerror) {
160
161     pa_simple *p;
162     int error = PA_ERR_INTERNAL, r;
163
164     CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
165     CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
166     CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
167     CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
168     CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL)
169
170     p = pa_xnew0(pa_simple, 1);
171     p->direction = dir;
172
173     if (!(p->mainloop = pa_threaded_mainloop_new()))
174         goto fail;
175
176     if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
177         goto fail;
178
179     pa_context_set_state_callback(p->context, context_state_cb, p);
180
181     if (pa_context_connect(p->context, server, 0, NULL) < 0) {
182         error = pa_context_errno(p->context);
183         goto fail;
184     }
185
186     pa_threaded_mainloop_lock(p->mainloop);
187
188     if (pa_threaded_mainloop_start(p->mainloop) < 0)
189         goto unlock_and_fail;
190
191     for (;;) {
192         pa_context_state_t state;
193
194         state = pa_context_get_state(p->context);
195
196         if (state == PA_CONTEXT_READY)
197             break;
198
199         if (!PA_CONTEXT_IS_GOOD(state)) {
200             error = pa_context_errno(p->context);
201             goto unlock_and_fail;
202         }
203
204         /* Wait until the context is ready */
205         pa_threaded_mainloop_wait(p->mainloop);
206     }
207
208     if (!(p->stream = pa_stream_new(p->context, stream_name, ss, map))) {
209         error = pa_context_errno(p->context);
210         goto unlock_and_fail;
211     }
212
213     pa_stream_set_state_callback(p->stream, stream_state_cb, p);
214     pa_stream_set_read_callback(p->stream, stream_request_cb, p);
215     pa_stream_set_write_callback(p->stream, stream_request_cb, p);
216     pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
217
218     if (dir == PA_STREAM_PLAYBACK)
219         r = pa_stream_connect_playback(p->stream, dev, attr,
220                                        PA_STREAM_INTERPOLATE_TIMING
221                                        |PA_STREAM_ADJUST_LATENCY
222                                        |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
223     else
224         r = pa_stream_connect_record(p->stream, dev, attr,
225                                      PA_STREAM_INTERPOLATE_TIMING
226                                      |PA_STREAM_ADJUST_LATENCY
227                                      |PA_STREAM_AUTO_TIMING_UPDATE);
228
229     if (r < 0) {
230         error = pa_context_errno(p->context);
231         goto unlock_and_fail;
232     }
233
234     for (;;) {
235         pa_stream_state_t state;
236
237         state = pa_stream_get_state(p->stream);
238
239         if (state == PA_STREAM_READY)
240             break;
241
242         if (!PA_STREAM_IS_GOOD(state)) {
243             error = pa_context_errno(p->context);
244             goto unlock_and_fail;
245         }
246
247         /* Wait until the stream is ready */
248         pa_threaded_mainloop_wait(p->mainloop);
249     }
250
251     pa_threaded_mainloop_unlock(p->mainloop);
252
253     return p;
254
255 unlock_and_fail:
256     pa_threaded_mainloop_unlock(p->mainloop);
257
258 fail:
259     if (rerror)
260         *rerror = error;
261     pa_simple_free(p);
262     return NULL;
263 }
264
265 void pa_simple_free(pa_simple *s) {
266     pa_assert(s);
267
268     if (s->mainloop)
269         pa_threaded_mainloop_stop(s->mainloop);
270
271     if (s->stream)
272         pa_stream_unref(s->stream);
273
274     if (s->context) {
275         pa_context_disconnect(s->context);
276         pa_context_unref(s->context);
277     }
278
279     if (s->mainloop)
280         pa_threaded_mainloop_free(s->mainloop);
281
282     pa_xfree(s);
283 }
284
285 int pa_simple_write(pa_simple *p, const void*data, size_t length, int *rerror) {
286     pa_assert(p);
287
288     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
289     CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1);
290     CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1);
291
292     pa_threaded_mainloop_lock(p->mainloop);
293
294     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
295
296     while (length > 0) {
297         size_t l;
298         int r;
299
300         while (!(l = pa_stream_writable_size(p->stream))) {
301             pa_threaded_mainloop_wait(p->mainloop);
302             CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
303         }
304
305         CHECK_SUCCESS_GOTO(p, rerror, l != (size_t) -1, unlock_and_fail);
306
307         if (l > length)
308             l = length;
309
310         r = pa_stream_write(p->stream, data, l, NULL, 0LL, PA_SEEK_RELATIVE);
311         CHECK_SUCCESS_GOTO(p, rerror, r >= 0, unlock_and_fail);
312
313         data = (const uint8_t*) data + l;
314         length -= l;
315     }
316
317     pa_threaded_mainloop_unlock(p->mainloop);
318     return 0;
319
320 unlock_and_fail:
321     pa_threaded_mainloop_unlock(p->mainloop);
322     return -1;
323 }
324
325 int pa_simple_read(pa_simple *p, void*data, size_t length, int *rerror) {
326     pa_assert(p);
327
328     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_RECORD, PA_ERR_BADSTATE, -1);
329     CHECK_VALIDITY_RETURN_ANY(rerror, data, PA_ERR_INVALID, -1);
330     CHECK_VALIDITY_RETURN_ANY(rerror, length > 0, PA_ERR_INVALID, -1);
331
332     pa_threaded_mainloop_lock(p->mainloop);
333
334     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
335
336     while (length > 0) {
337         size_t l;
338
339         while (!p->read_data) {
340             int r;
341
342             r = pa_stream_peek(p->stream, &p->read_data, &p->read_length);
343             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
344
345             if (!p->read_data) {
346                 pa_threaded_mainloop_wait(p->mainloop);
347                 CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
348             } else
349                 p->read_index = 0;
350         }
351
352         l = p->read_length < length ? p->read_length : length;
353         memcpy(data, (const uint8_t*) p->read_data+p->read_index, l);
354
355         data = (uint8_t*) data + l;
356         length -= l;
357
358         p->read_index += l;
359         p->read_length -= l;
360
361         if (!p->read_length) {
362             int r;
363
364             r = pa_stream_drop(p->stream);
365             p->read_data = NULL;
366             p->read_length = 0;
367             p->read_index = 0;
368
369             CHECK_SUCCESS_GOTO(p, rerror, r == 0, unlock_and_fail);
370         }
371     }
372
373     pa_threaded_mainloop_unlock(p->mainloop);
374     return 0;
375
376 unlock_and_fail:
377     pa_threaded_mainloop_unlock(p->mainloop);
378     return -1;
379 }
380
381 static void success_cb(pa_stream *s, int success, void *userdata) {
382     pa_simple *p = userdata;
383
384     pa_assert(s);
385     pa_assert(p);
386
387     p->operation_success = success;
388     pa_threaded_mainloop_signal(p->mainloop, 0);
389 }
390
391 int pa_simple_drain(pa_simple *p, int *rerror) {
392     pa_operation *o = NULL;
393
394     pa_assert(p);
395
396     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
397
398     pa_threaded_mainloop_lock(p->mainloop);
399     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
400
401     o = pa_stream_drain(p->stream, success_cb, p);
402     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
403
404     p->operation_success = 0;
405     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
406         pa_threaded_mainloop_wait(p->mainloop);
407         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
408     }
409     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
410
411     pa_operation_unref(o);
412     pa_threaded_mainloop_unlock(p->mainloop);
413
414     return 0;
415
416 unlock_and_fail:
417
418     if (o) {
419         pa_operation_cancel(o);
420         pa_operation_unref(o);
421     }
422
423     pa_threaded_mainloop_unlock(p->mainloop);
424     return -1;
425 }
426
427 int pa_simple_flush(pa_simple *p, int *rerror) {
428     pa_operation *o = NULL;
429
430     pa_assert(p);
431
432     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
433
434     pa_threaded_mainloop_lock(p->mainloop);
435     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
436
437     o = pa_stream_flush(p->stream, success_cb, p);
438     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
439
440     p->operation_success = 0;
441     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
442         pa_threaded_mainloop_wait(p->mainloop);
443         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
444     }
445     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
446
447     pa_operation_unref(o);
448     pa_threaded_mainloop_unlock(p->mainloop);
449
450     return 0;
451
452 unlock_and_fail:
453
454     if (o) {
455         pa_operation_cancel(o);
456         pa_operation_unref(o);
457     }
458
459     pa_threaded_mainloop_unlock(p->mainloop);
460     return -1;
461 }
462
463 pa_usec_t pa_simple_get_latency(pa_simple *p, int *rerror) {
464     pa_usec_t t;
465     int negative;
466
467     pa_assert(p);
468
469     pa_threaded_mainloop_lock(p->mainloop);
470
471     for (;;) {
472         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
473
474         if (pa_stream_get_latency(p->stream, &t, &negative) >= 0)
475             break;
476
477         CHECK_SUCCESS_GOTO(p, rerror, pa_context_errno(p->context) == PA_ERR_NODATA, unlock_and_fail);
478
479         /* Wait until latency data is available again */
480         pa_threaded_mainloop_wait(p->mainloop);
481     }
482
483     pa_threaded_mainloop_unlock(p->mainloop);
484
485     return negative ? 0 : t;
486
487 unlock_and_fail:
488
489     pa_threaded_mainloop_unlock(p->mainloop);
490     return (pa_usec_t) -1;
491 }
492
493 pa_simple* pa_simple_new_proplist(
494         const char *server,
495         const char *name,
496         pa_stream_direction_t dir,
497         const char *dev,
498         const char *stream_name,
499         const pa_sample_spec *ss,
500         const pa_channel_map *map,
501         const pa_buffer_attr *attr,
502         pa_proplist *proplist,
503         int *rerror) {
504
505     pa_simple *p;
506     int error = PA_ERR_INTERNAL, r;
507
508     CHECK_VALIDITY_RETURN_ANY(rerror, !server || *server, PA_ERR_INVALID, NULL);
509     CHECK_VALIDITY_RETURN_ANY(rerror, dir == PA_STREAM_PLAYBACK || dir == PA_STREAM_RECORD, PA_ERR_INVALID, NULL);
510     CHECK_VALIDITY_RETURN_ANY(rerror, !dev || *dev, PA_ERR_INVALID, NULL);
511     CHECK_VALIDITY_RETURN_ANY(rerror, ss && pa_sample_spec_valid(ss), PA_ERR_INVALID, NULL);
512     CHECK_VALIDITY_RETURN_ANY(rerror, !map || (pa_channel_map_valid(map) && map->channels == ss->channels), PA_ERR_INVALID, NULL);
513
514     p = pa_xnew0(pa_simple, 1);
515     p->direction = dir;
516
517     if (!(p->mainloop = pa_threaded_mainloop_new()))
518         goto fail;
519
520     if (!(p->context = pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), name)))
521         goto fail;
522
523     pa_context_set_state_callback(p->context, context_state_cb, p);
524
525     if (pa_context_connect(p->context, server, 0, NULL) < 0) {
526         error = pa_context_errno(p->context);
527         goto fail;
528     }
529
530     pa_threaded_mainloop_lock(p->mainloop);
531
532     if (pa_threaded_mainloop_start(p->mainloop) < 0)
533         goto unlock_and_fail;
534
535     for (;;) {
536         pa_context_state_t state;
537
538         state = pa_context_get_state(p->context);
539
540         if (state == PA_CONTEXT_READY)
541             break;
542
543         if (!PA_CONTEXT_IS_GOOD(state)) {
544             error = pa_context_errno(p->context);
545             goto unlock_and_fail;
546         }
547
548         /* Wait until the context is ready */
549         pa_threaded_mainloop_wait(p->mainloop);
550     }
551
552     if (!(p->stream = pa_stream_new_with_proplist(p->context, stream_name, ss, map, proplist))) {
553         error = pa_context_errno(p->context);
554         goto unlock_and_fail;
555     }
556
557     pa_stream_set_state_callback(p->stream, stream_state_cb, p);
558     pa_stream_set_read_callback(p->stream, stream_request_cb, p);
559     pa_stream_set_write_callback(p->stream, stream_request_cb, p);
560     pa_stream_set_latency_update_callback(p->stream, stream_latency_update_cb, p);
561
562     if (dir == PA_STREAM_PLAYBACK)
563         r = pa_stream_connect_playback(p->stream, dev, attr,
564                                        PA_STREAM_INTERPOLATE_TIMING
565                                        |PA_STREAM_ADJUST_LATENCY
566                                        |PA_STREAM_AUTO_TIMING_UPDATE, NULL, NULL);
567     else
568         r = pa_stream_connect_record(p->stream, dev, attr,
569                                      PA_STREAM_INTERPOLATE_TIMING
570                                      |PA_STREAM_ADJUST_LATENCY
571                                      |PA_STREAM_AUTO_TIMING_UPDATE
572                                      |PA_STREAM_START_CORKED);
573
574     if (r < 0) {
575         error = pa_context_errno(p->context);
576         goto unlock_and_fail;
577     }
578
579     for (;;) {
580         pa_stream_state_t state;
581
582         state = pa_stream_get_state(p->stream);
583
584         if (state == PA_STREAM_READY)
585             break;
586
587         if (!PA_STREAM_IS_GOOD(state)) {
588             error = pa_context_errno(p->context);
589             goto unlock_and_fail;
590         }
591
592         /* Wait until the stream is ready */
593         pa_threaded_mainloop_wait(p->mainloop);
594     }
595
596     pa_threaded_mainloop_unlock(p->mainloop);
597
598     return p;
599
600  unlock_and_fail:
601     pa_threaded_mainloop_unlock(p->mainloop);
602
603  fail:
604     if (rerror)
605         *rerror = error;
606     pa_simple_free(p);
607     return NULL;
608 }
609
610 int pa_simple_mute(pa_simple *p, int mute, int *rerror) {
611     pa_operation *o = NULL;
612     uint32_t idx;
613
614     pa_assert(p);
615
616     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
617
618     pa_threaded_mainloop_lock(p->mainloop);
619     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
620
621     CHECK_SUCCESS_GOTO(p, rerror, ((idx = pa_stream_get_index (p->stream)) != PA_INVALID_INDEX), unlock_and_fail);
622
623
624     o = pa_context_set_sink_input_mute (p->context, idx, mute, success_context_cb, p);
625     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
626
627     p->operation_success = 0;
628     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
629         pa_threaded_mainloop_wait(p->mainloop);
630         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
631     }
632     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
633
634     pa_operation_unref(o);
635     pa_threaded_mainloop_unlock(p->mainloop);
636
637     return 0;
638
639  unlock_and_fail:
640
641     if (o) {
642         pa_operation_cancel(o);
643         pa_operation_unref(o);
644     }
645
646     pa_threaded_mainloop_unlock(p->mainloop);
647     return -1;
648 }
649
650 int pa_simple_get_stream_index(pa_simple *p, unsigned int *idx, int *rerror) {
651     pa_assert(p);
652     CHECK_VALIDITY_RETURN_ANY(rerror, idx != NULL, PA_ERR_INVALID, -1);
653
654     pa_threaded_mainloop_lock(p->mainloop);
655
656     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
657
658     *idx = pa_stream_get_index(p->stream);
659
660         pa_threaded_mainloop_unlock(p->mainloop);
661     return 0;
662
663  unlock_and_fail:
664     pa_threaded_mainloop_unlock(p->mainloop);
665     return -1;
666 }
667
668 int pa_simple_set_volume(pa_simple *p, int volume, int *rerror) {
669     pa_operation *o = NULL;
670     pa_stream *s = NULL;
671     uint32_t idx;
672     pa_cvolume cv;
673
674     pa_assert(p);
675
676     CHECK_VALIDITY_RETURN_ANY(rerror, p->direction == PA_STREAM_PLAYBACK, PA_ERR_BADSTATE, -1);
677     CHECK_VALIDITY_RETURN_ANY(rerror, volume >= 0, PA_ERR_INVALID, -1);
678     CHECK_VALIDITY_RETURN_ANY(rerror, volume <= 65535, PA_ERR_INVALID, -1);
679
680     pa_threaded_mainloop_lock(p->mainloop);
681     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
682
683     CHECK_SUCCESS_GOTO(p, rerror, ((idx = pa_stream_get_index (p->stream)) != PA_INVALID_INDEX), unlock_and_fail);
684
685     s = p->stream;
686     pa_assert(s);
687     pa_cvolume_set(&cv, s->sample_spec.channels, volume);
688
689     o = pa_context_set_sink_input_volume (p->context, idx, &cv, success_context_cb, p);
690
691     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
692
693     p->operation_success = 0;
694     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
695         pa_threaded_mainloop_wait(p->mainloop);
696         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
697     }
698     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
699
700     pa_operation_unref(o);
701     pa_threaded_mainloop_unlock(p->mainloop);
702
703     return 0;
704
705  unlock_and_fail:
706
707     if (o) {
708         pa_operation_cancel(o);
709         pa_operation_unref(o);
710     }
711
712     pa_threaded_mainloop_unlock(p->mainloop);
713     return -1;
714 }
715
716 int pa_simple_cork(pa_simple *p, int cork, int *rerror) {
717     pa_operation *o = NULL;
718
719     pa_assert(p);
720
721     pa_threaded_mainloop_lock(p->mainloop);
722     CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
723
724     o = pa_stream_cork(p->stream, cork, success_cb, p);
725     CHECK_SUCCESS_GOTO(p, rerror, o, unlock_and_fail);
726
727     p->operation_success = 0;
728     while (pa_operation_get_state(o) == PA_OPERATION_RUNNING) {
729         pa_threaded_mainloop_wait(p->mainloop);
730         CHECK_DEAD_GOTO(p, rerror, unlock_and_fail);
731     }
732     CHECK_SUCCESS_GOTO(p, rerror, p->operation_success, unlock_and_fail);
733
734     pa_operation_unref(o);
735     pa_threaded_mainloop_unlock(p->mainloop);
736
737     return 0;
738
739 unlock_and_fail:
740
741     if (o) {
742         pa_operation_cancel(o);
743         pa_operation_unref(o);
744     }
745
746     pa_threaded_mainloop_unlock(p->mainloop);
747     return -1;
748 }
749
750 int pa_simple_is_corked(pa_simple *p) {
751     int is_cork;
752     pa_assert(p);
753
754     pa_threaded_mainloop_lock(p->mainloop);
755
756     is_cork = pa_stream_is_corked(p->stream);
757
758     pa_threaded_mainloop_unlock(p->mainloop);
759
760     return is_cork;
761 }