source: roaraudio/libroarpulse/context.c @ 3391:b2905b861e43

Last change on this file since 3391:b2905b861e43 was 3391:b2905b861e43, checked in by phi, 14 years ago

we are now mostly done, just a commit inbetween

File size: 7.0 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 struct {
59  struct _roar_pa_cb_st set_name;
60  struct _roar_pa_cb_st state_change;
61 } cb;
62};
63
64// older versions:
65typedef void pa_proplist;
66pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist);
67
68void pa_context_set_state(pa_context *c, pa_context_state_t st);
69
70pa_context *pa_context_new(pa_mainloop_api *mainloop, const char *name) {
71 return pa_context_new_with_proplist(mainloop, name, NULL);
72}
73
74pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, pa_proplist *proplist) {
75 pa_context * c;
76
77 if ( proplist != NULL )
78  return NULL;
79
80 if ( (c = roar_mm_malloc(sizeof(pa_context))) == NULL )
81  return NULL;
82
83 memset(c, 0, sizeof(pa_context));
84
85 c->refc  = 1;
86
87 c->state = PA_CONTEXT_UNCONNECTED;
88
89 return NULL;
90}
91
92static void _context_free(pa_context *c) {
93 pa_context_disconnect(c);
94
95 if ( c->server != NULL )
96  roar_mm_free(c->server);
97
98 if ( c->name != NULL )
99  roar_mm_free(c->name);
100
101 roar_mm_free(c);
102}
103
104pa_context* pa_context_ref(pa_context *c) {
105 c->refc++;
106 return c;
107}
108
109void pa_context_unref(pa_context *c) {
110 c->refc--;
111
112 if ( c->refc < 1 )
113  _context_free(c);
114}
115
116int pa_context_connect(
117        pa_context *c,
118        const char *server,
119        pa_context_flags_t flags,
120        const pa_spawn_api *api) {
121
122 if ( c == NULL )
123  return -1;
124
125 if ( c->state != PA_CONTEXT_UNCONNECTED )
126  return -1;
127
128 // we do currently not support to spawn a daemon, so we ignore flags and api.
129
130 server = roar_pa_find_server((char*)server);
131
132 if ( roar_simple_connect(&(c->con), (char*)server,
133                          c->name != NULL ? c->name : "libroarpulse [pa_context_connect()]") == -1 ) {
134  pa_context_set_state(c, PA_CONTEXT_FAILED);
135  return -1;
136 }
137
138 c->server = roar_mm_strdup(server);
139 pa_context_set_state(c, PA_CONTEXT_READY);
140
141 _call_cbs(c->cb.set_name, c, 1);
142
143 return 0;
144}
145
146void pa_context_disconnect(pa_context *c) {
147 if ( c == NULL )
148  return;
149
150 if ( c->state != PA_CONTEXT_READY )
151  return;
152
153 roar_disconnect(&(c->con));
154
155 pa_context_set_state(c, PA_CONTEXT_TERMINATED);
156}
157
158
159
160/** Set a callback function that is called whenever the context status changes */
161void pa_context_set_state_callback(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
162 if ( c == NULL )
163  return;
164
165 c->cb.state_change.cb.ncb   = cb;
166 c->cb.state_change.userdata = userdata;
167}
168
169void pa_context_set_state(pa_context *c, pa_context_state_t st) {
170 if ( c == NULL )
171  return;
172
173 c->state = st;
174
175 _call_cbn(c->cb.state_change, c);
176}
177
178/** Return the error number of the last failed operation */
179int pa_context_errno(pa_context *c);
180
181/** Return non-zero if some data is pending to be written to the connection */
182int pa_context_is_pending(pa_context *c) {
183 return 0;
184}
185
186/** Return the current context status */
187pa_context_state_t pa_context_get_state(pa_context *c) {
188 if ( c == NULL )
189  return PA_CONTEXT_FAILED;
190
191 return c->state;
192}
193
194/** Drain the context. If there is nothing to drain, the function returns NULL */
195pa_operation* pa_context_drain(pa_context *c, pa_context_notify_cb_t cb, void *userdata) {
196
197 if ( cb != NULL )
198  cb(c, userdata);
199
200 return NULL;
201}
202
203/** Tell the daemon to exit. The returned operation is unlikely to
204 * complete succesfully, since the daemon probably died before
205 * returning a success notification */
206pa_operation* pa_context_exit_daemon(pa_context *c, pa_context_success_cb_t cb, void *userdata);
207
208/** Set the name of the default sink. \since 0.4 */
209pa_operation* pa_context_set_default_sink(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
210 if ( cb != NULL )
211  cb(c, 0, userdata);
212
213 return NULL;
214}
215
216/** Set the name of the default source. \since 0.4 */
217pa_operation* pa_context_set_default_source(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
218 if ( cb != NULL )
219  cb(c, 0, userdata);
220
221 return NULL;
222}
223
224/** Returns 1 when the connection is to a local daemon. Returns negative when no connection has been made yet. \since 0.5 */
225int pa_context_is_local(pa_context *c) {
226 if ( c == NULL )
227  return -1;
228
229 if ( c->state != PA_CONTEXT_READY )
230  return -1;
231
232 // how is /local/ defined?
233 return 0;
234}
235
236/** Set a different application name for context on the server. \since 0.5 */
237pa_operation* pa_context_set_name(pa_context *c, const char *name, pa_context_success_cb_t cb, void *userdata) {
238 if ( c == NULL )
239  return NULL;
240
241 if ( c->state != PA_CONTEXT_UNCONNECTED )
242  return NULL;
243
244 c->name = roar_mm_strdup(name);
245 c->cb.set_name.cb.scb   = cb;
246 c->cb.set_name.userdata = userdata;
247
248 return NULL;
249}
250
251/** Return the server name this context is connected to. \since 0.7 */
252const char* pa_context_get_server(pa_context *c) {
253 if ( c == NULL )
254  return NULL;
255
256 return c->server;
257}
258
259/** Return the protocol version of the library. \since 0.8 */
260uint32_t pa_context_get_protocol_version(pa_context *c) {
261 return 0;
262}
263
264/** Return the protocol version of the connected server. \since 0.8 */
265uint32_t pa_context_get_server_protocol_version(pa_context *c) {
266 return 0;
267}
268
269
270//ll
Note: See TracBrowser for help on using the repository browser.