source: roaraudio/libroarpulse/context.c @ 3396:15a6bfb3ae4a

Last change on this file since 3396:15a6bfb3ae4a was 3396:15a6bfb3ae4a, checked in by phi, 10 years ago

corrected pa_context_new_with_proplist()

File size: 7.8 KB
Line 
1//context.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2010
5 *  The code (may) include prototypes and comments (and maybe
6 *  other code fragements) from libpulse*. They are mostly copyrighted by:
7 *  Lennart Poettering <poettering@users.sourceforge.net> and
8 *  Pierre Ossman <drzeus@drzeus.cx>
9 *
10 *  This file is part of libroarpulse a part of RoarAudio,
11 *  a cross-platform sound system for both, home and professional use.
12 *  See README for details.
13 *
14 *  This file is free software; you can redistribute it and/or modify
15 *  it under the terms of the GNU General Public License version 3
16 *  as published by the Free Software Foundation.
17 *
18 *  RoarAudio is distributed in the hope that it will be useful,
19 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 *  GNU General Public License for more details.
22 *
23 *  You should have received a copy of the GNU General Public License
24 *  along with this software; see the file COPYING.  If not, write to
25 *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
26 *
27 *  NOTE for everyone want's to change something and send patches:
28 *  read README and HACKING! There a addition information on
29 *  the license of this document you need to read before you send
30 *  any patches.
31 *
32 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
33 *  or libpulse*:
34 *  The libs libroaresd, libroararts and libroarpulse link this libroar
35 *  and are therefore GPL. Because of this it may be illigal to use
36 *  them with any software that uses libesd, libartsc or libpulse*.
37 */
38
39#include <libroarpulse/libroarpulse.h>
40
41struct _roar_pa_cb_st {
42 union {
43  pa_context_success_cb_t scb;
44  pa_context_notify_cb_t  ncb;
45 } cb;
46 void * userdata;
47};
48
49#define _call_cbs(x,c,s) ((x).cb.scb == NULL ? (void)0 : (x).cb.scb((c), (s), (x).userdata))
50#define _call_cbn(x,c)   ((x).cb.ncb == NULL ? (void)0 : (x).cb.ncb((c), (x).userdata))
51
52struct pa_context {
53 size_t refc;
54 struct roar_connection con;
55 char * server;
56 char * name;
57 int state;
58 int errnum;
59 struct {
60  struct _roar_pa_cb_st set_name;
61  struct _roar_pa_cb_st state_change;
62 } cb;
63 pa_mainloop_api * mainloop;
64};
65
66// older versions:
67typedef void pa_proplist;
68pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
69
70void pa_context_set_state(pa_context *c, pa_context_state_t st);
71
72pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
73 return pa_context_new_with_proplist(mainloop, name, NULL);
74}
75
76pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist) {
77 pa_context * c;
78
79 if ( proplist != NULL )
80  return NULL;
81
82 if ( (c = roar_mm_malloc(sizeof(pa_context))) == NULL )
83  return NULL;
84
85 memset(c, 0, sizeof(pa_context));
86
87 c->refc  = 1;
88
89 c->state = PA_CONTEXT_UNCONNECTED;
90
91 c->errnum = PA_OK;
92
93 if ( name != NULL ) {
94  c->name = roar_mm_strdup(name);
95 }
96
97 c->mainloop = mainloop;
98
99 return c;
100}
101
102static void _context_free(pa_context *c) {
103 pa_context_disconnect(c);
104
105 if ( c->server != NULL )
106  roar_mm_free(c->server);
107
108 if ( c->name != NULL )
109  roar_mm_free(c->name);
110
111 roar_mm_free(c);
112}
113
114pa_context* pa_context_ref(pa_context *c) {
115 c->refc++;
116 return c;
117}
118
119void pa_context_unref(pa_context *c) {
120 c->refc--;
121
122 if ( c->refc < 1 )
123  _context_free(c);
124}
125
126int pa_context_connect(
127        pa_context *c,
128        const char *server,
129        pa_context_flags_t flags,
130        const pa_spawn_api *api) {
131
132 if ( c == NULL )
133  return -1;
134
135 if ( c->state != PA_CONTEXT_UNCONNECTED ) {
136  c->errnum = PA_ERR_BADSTATE;
137  pa_context_set_state(c, PA_CONTEXT_FAILED);
138  return -1;
139 }
140
141 // we do currently not support to spawn a daemon, so we ignore flags and api.
142
143 server = roar_pa_find_server((char*)server);
144
145 if ( roar_simple_connect(&(c->con), (char*)server,
146                          c->name != NULL ? c->name : "libroarpulse [pa_context_connect()]") == -1 ) {
147  c->errnum = PA_ERR_CONNECTIONREFUSED;
148  pa_context_set_state(c, PA_CONTEXT_FAILED);
149  return -1;
150 }
151
152 c->server = roar_mm_strdup(server);
153 pa_context_set_state(c, PA_CONTEXT_READY);
154
155 _call_cbs(c->cb.set_name, c, 1);
156
157 return 0;
158}
159
160void pa_context_disconnect(pa_context *c) {
161 if ( c == NULL )
162  return;
163
164 if ( c->state != PA_CONTEXT_READY )
165  return;
166
167 roar_disconnect(&(c->con));
168
169 pa_context_set_state(c, PA_CONTEXT_TERMINATED);
170}
171
172
173
174/** Set a callback function that is called whenever the context status changes */
175void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
176 if ( c == NULL )
177  return;
178
179 c->cb.state_change.cb.ncb   = cb;
180 c->cb.state_change.userdata = userdata;
181}
182
183void pa_context_set_state(pa_context *c, pa_context_state_t st) {
184 if ( c == NULL )
185  return;
186
187 c->state = st;
188
189 _call_cbn(c->cb.state_change, c);
190}
191
192/** Return the error number of the last failed operation */
193int pa_context_errno(pa_context *c) {
194 if ( c == NULL )
195  return PA_ERR_INVALID;
196
197 return c->errnum;
198}
199
200/** Return non-zero if some data is pending to be written to the connection */
201int pa_context_is_pending(pa_context *c) {
202 return 0;
203}
204
205/** Return the current context status */
206pa_context_state_t pa_context_get_state(pa_context *c) {
207 if ( c == NULL )
208  return PA_CONTEXT_FAILED;
209
210 return c->state;
211}
212
213/** Drain the context. If there is nothing to drain, the function returns NULL */
214pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
215
216 if ( cb != NULL )
217  cb(c, userdata);
218
219 return NULL;
220}
221
222/** Tell the daemon to exit. The returned operation is unlikely to
223 * complete succesfully, since the daemon probably died before
224 * returning a success notification */
225pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata) {
226 int s = 1;
227
228 if ( c == NULL )
229  return NULL;
230
231 if ( c->state == PA_CONTEXT_READY ) {
232  if ( roar_exit(&(c->con)) == -1 ) {
233   c->errnum = PA_ERR_INTERNAL;
234   s = 0;
235  }
236 } else {
237  c->errnum = PA_ERR_BADSTATE;
238  s = 0;
239 }
240
241 if ( cb != NULL )
242  cb(c, s, userdata);
243
244 return NULL;
245}
246
247/** Set the name of the default sink. \since 0.4 */
248pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
249 if ( c != NULL )
250  c->errnum = PA_ERR_NOTSUPPORTED;
251
252 if ( cb != NULL )
253  cb(c, 0, userdata);
254
255 return NULL;
256}
257
258/** Set the name of the default source. \since 0.4 */
259pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
260 if ( c != NULL )
261  c->errnum = PA_ERR_NOTSUPPORTED;
262
263 if ( cb != NULL )
264  cb(c, 0, userdata);
265
266 return NULL;
267}
268
269/** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. \since 0.5 */
270int pa_context_is_local(pa_context *c) {
271 if ( c == NULL )
272  return -1;
273
274 if ( c->state != PA_CONTEXT_READY )
275  return -1;
276
277 // how is /local/ defined?
278 return 0;
279}
280
281/** Set a different application name for context on the server. \since 0.5 */
282pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
283 if ( c == NULL )
284  return NULL;
285
286 if ( c->state != PA_CONTEXT_UNCONNECTED ) {
287  c->errnum = PA_ERR_BADSTATE;
288
289  if ( cb != NULL )
290   cb(c, 0, userdata);
291
292  return NULL;
293 }
294
295 if ( c->name != NULL )
296  roar_mm_free(c->name);
297
298 c->name = roar_mm_strdup(name);
299 c->cb.set_name.cb.scb   = cb;
300 c->cb.set_name.userdata = userdata;
301
302 return NULL;
303}
304
305/** Return the server name this context is connected to. \since 0.7 */
306const char* pa_context_get_server(pa_context *c) {
307 if ( c == NULL )
308  return NULL;
309
310 return c->server;
311}
312
313/** Return the protocol version of the library. \since 0.8 */
314uint32_t pa_context_get_protocol_version(pa_context *c) {
315 return 0;
316}
317
318/** Return the protocol version of the connected server. \since 0.8 */
319uint32_t pa_context_get_server_protocol_version(pa_context *c) {
320 return 0;
321}
322
323
324//ll
Note: See TracBrowser for help on using the repository browser.