cf31ac52d838f6352ab2139b26e2b57b39f760e4
[platform/upstream/pulseaudio.git] / src / simple.c
1 #include <assert.h>
2 #include <stdlib.h>
3
4 #include "simple.h"
5 #include "polyp.h"
6 #include "mainloop.h"
7 #include "polyp-error.h"
8
9 struct pa_simple {
10     struct pa_mainloop *mainloop;
11     struct pa_context *context;
12     struct pa_stream *stream;
13
14     int dead;
15 };
16
17 static int iterate(struct pa_simple *p, int block, int *perror) {
18     assert(p && p->context && p->mainloop && perror);
19
20     if (!block && !pa_context_is_pending(p->context))
21         return 0;
22     
23     do {
24         if (pa_context_is_dead(p->context) || (p->stream && pa_stream_is_dead(p->stream))) {
25             *perror = pa_context_errno(p->context);
26             return -1;
27         }
28         
29         if (pa_mainloop_iterate(p->mainloop, 1, NULL) < 0) {
30             *perror = PA_ERROR_INTERNAL;
31             return -1;
32         }
33     } while (pa_context_is_pending(p->context));
34
35     return 0;
36 }
37
38 struct pa_simple* pa_simple_new(
39     const char *server,
40     const char *name,
41     enum pa_stream_direction dir,
42     const char *dev,
43     const char *stream_name,
44     const struct pa_sample_spec *ss,
45     const struct pa_buffer_attr *attr,
46     int *perror) {
47     
48     struct pa_simple *p;
49     int error = PA_ERROR_INTERNAL;
50     assert(ss);
51
52     p = malloc(sizeof(struct pa_simple));
53     assert(p);
54     p->context = NULL;
55     p->stream = NULL;
56     p->mainloop = pa_mainloop_new();
57     assert(p->mainloop);
58     p->dead = 0;
59
60     if (!(p->context = pa_context_new(pa_mainloop_get_api(p->mainloop), name)))
61         goto fail;
62
63     if (pa_context_connect(p->context, server, NULL, NULL) < 0) {
64         error = pa_context_errno(p->context);
65         goto fail;
66     }
67
68     /* Wait until the context is ready */
69     while (!pa_context_is_ready(p->context)) {
70         if (iterate(p, 1, &error) < 0)
71             goto fail;
72     }
73
74     if (!(p->stream = pa_stream_new(p->context, dir, dev, stream_name, ss, attr, NULL, NULL)))
75         goto fail;
76
77     /* Wait until the stream is ready */
78     while (!pa_stream_is_ready(p->stream)) {
79         if (iterate(p, 1, &error) < 0)
80             goto fail;
81     }
82
83     return p;
84     
85 fail:
86     *perror = error;
87     pa_simple_free(p);
88     return NULL;
89 }
90
91 void pa_simple_free(struct pa_simple *s) {
92     assert(s);
93
94     if (s->stream)
95         pa_stream_free(s->stream);
96     
97     if (s->context)
98         pa_context_free(s->context);
99
100     if (s->mainloop)
101         pa_mainloop_free(s->mainloop);
102
103     free(s);
104 }
105
106 int pa_simple_write(struct pa_simple *p, const void*data, size_t length, int *perror) {
107     assert(p && data);
108
109     while (length > 0) {
110         size_t l;
111         
112         while (!(l = pa_stream_writable_size(p->stream)))
113             if (iterate(p, 1, perror) < 0)
114                 return -1;
115
116         if (l > length)
117             l = length;
118
119         pa_stream_write(p->stream, data, l);
120         data += l;
121         length -= l;
122     }
123
124     /* Make sure that no data is pending for write */
125     if (iterate(p, 0, perror) < 0)
126         return -1;
127
128     return 0;
129 }
130
131 int pa_simple_read(struct pa_simple *s, void*data, size_t length, int *perror) {
132     assert(0);
133 }
134