source: roaraudio/libroar/basic.c @ 5248:0133acb5ae31

Last change on this file since 5248:0133acb5ae31 was 5240:db409850667a, checked in by phi, 12 years ago

Removed roar_debug_audio_info_print().

File size: 10.8 KB
Line 
1//basic.c:
2
3/*
4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2008-2011
5 *
6 *  This file is part of libroar a part of RoarAudio,
7 *  a cross-platform sound system for both, home and professional use.
8 *  See README for details.
9 *
10 *  This file is free software; you can redistribute it and/or modify
11 *  it under the terms of the GNU General Public License version 3
12 *  as published by the Free Software Foundation.
13 *
14 *  libroar is distributed in the hope that it will be useful,
15 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 *  GNU General Public License for more details.
18 *
19 *  You should have received a copy of the GNU General Public License
20 *  along with this software; see the file COPYING.  If not, write to
21 *  the Free Software Foundation, 51 Franklin Street, Fifth Floor,
22 *  Boston, MA 02110-1301, USA.
23 *
24 *  NOTE for everyone want's to change something and send patches:
25 *  read README and HACKING! There a addition information on
26 *  the license of this document you need to read before you send
27 *  any patches.
28 *
29 *  NOTE for uses of non-GPL (LGPL,...) software using libesd, libartsc
30 *  or libpulse*:
31 *  The libs libroaresd, libroararts and libroarpulse link this lib
32 *  and are therefore GPL. Because of this it may be illigal to use
33 *  them with any software that uses libesd, libartsc or libpulse*.
34 */
35
36#include "libroar.h"
37
38int roar_connect_raw (const char * server, int flags, uint_least32_t timeout) {
39#ifdef ROAR_HAVE_LIBSLP
40 struct roar_libroar_config * config = roar_libroar_get_config();
41#endif
42 char user_sock[128];
43 char * roar_server;
44 int i = 0;
45 int port = 0;
46 int fh = -1;
47 int is_decnet = 0;
48 const char * obj = NULL;
49#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
50 struct passwd * pwd;
51#endif
52#ifdef ROAR_HAVE_LIBDNET
53 struct stat decnet_stat;
54#endif
55#ifdef ROAR_HAVE_LIBX11
56 struct roar_x11_connection * x11con;
57#endif
58#ifdef ROAR_HAVE_LIBSLP
59 struct roar_server * list;
60 int workarounds_store;
61#endif
62
63 roar_err_set(ROAR_ERROR_UNKNOWN);
64
65 if ( timeout != 0 ) {
66  roar_err_set(ROAR_ERROR_INVAL);
67  return -1;
68 }
69
70 if ( flags & ROAR_ENUM_FLAG_HARDNONBLOCK )
71  flags |= ROAR_ENUM_FLAG_NONBLOCK;
72
73
74 if ( server == NULL )
75  server = roar_libroar_get_server();
76
77 if ( server == NULL && (roar_server = getenv("ROAR_SERVER")) != NULL )
78  server = roar_server;
79
80#ifdef ROAR_HAVE_LIBX11
81 if ( server == NULL ) {
82  if ( (x11con = roar_x11_connect(NULL)) != NULL ) {
83   server = roar_x11_get_prop(x11con, "ROAR_SERVER");
84   roar_x11_disconnect(x11con);
85  }
86 }
87#endif
88
89#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
90 if ( server == NULL && (i = readlink("/etc/roarserver", user_sock, sizeof(user_sock)-1)) != -1 ) {
91   user_sock[i] = 0;
92   server = user_sock;
93 }
94#endif
95
96 if ( server != NULL && !strcasecmp(server, "+slp") ) {
97  server = roar_slp_find_roard(0);
98  if ( server == NULL ) {
99   return -1;
100  }
101 }
102
103 if ( server == NULL || *server == 0 ) {
104  /* connect via defaults */
105
106#ifdef ROAR_HAVE_UNIX
107#ifndef ROAR_TARGET_MICROCONTROLLER
108  roar_server = getenv("HOME");
109#else
110  roar_server = NULL;
111#endif
112
113  if ( roar_server == NULL ) {
114#if !defined(ROAR_TARGET_WIN32) && !defined(ROAR_TARGET_MICROCONTROLLER)
115   if ( (pwd = getpwuid(getuid())) == NULL ) {
116    roar_server = "/NX-HOME-DIR";
117   } else {
118    roar_server = pwd->pw_dir;
119   }
120#else
121   roar_server = "/WIN32-SUCKS";
122#endif
123  }
124
125  snprintf(user_sock, sizeof(user_sock)-1, "%s/%s", roar_server, ROAR_DEFAULT_SOCK_USER);
126  user_sock[sizeof(user_sock)-1] = 0;
127
128  if ( (fh = roar_socket_connect(user_sock, 0)) != -1 )
129   return fh;
130
131  if ( (fh = roar_socket_connect(ROAR_DEFAULT_SOCK_GLOBAL, 0)) != -1 )
132   return fh;
133#endif
134
135  if ( (fh = roar_socket_connect(ROAR_DEFAULT_HOST, ROAR_DEFAULT_PORT)) != -1 )
136   return fh;
137
138#ifdef ROAR_HAVE_LIBDNET
139  if ( stat(ROAR_PROC_NET_DECNET, &decnet_stat) == 0 ) {
140   if ( roar_socket_get_local_nodename() ) {
141    snprintf(user_sock, 79, "%s::%s", roar_socket_get_local_nodename(), ROAR_DEFAULT_OBJECT);
142    if ( (fh = roar_socket_connect(user_sock, ROAR_DEFAULT_NUM)) != -1 )
143     return fh;
144   }
145  }
146#endif
147
148  if ( (fh = roar_socket_connect("+abstract", 0)) != -1 )
149   return fh;
150
151#ifdef ROAR_HAVE_LIBSLP
152 if ( !(config->workaround.workarounds & ROAR_LIBROAR_CONFIG_WAS_NO_SLP) &&
153      !(flags & ROAR_ENUM_FLAG_NONBLOCK)
154    ) {
155  if ( (server = roar_slp_find_roard(0)) != NULL ) {
156   if ( (fh = roar_connect_raw(server, 0, 0)) != -1 )
157    return fh;
158
159   /* in case we can not connect to the server given this may be a cache problem,
160      we do a new lookup with the cache disabled in this case                     */
161   ROAR_WARN("roar_connect_raw(*): Can not connect to SLP located server, disabling cache");
162   if ( (server = roar_slp_find_roard(1)) != NULL )
163    if ( (fh = roar_connect_raw(server, 0, 0)) != -1 )
164     return fh;
165  }
166 }
167
168 workarounds_store = config->workaround.workarounds;
169 config->workaround.workarounds |= ROAR_LIBROAR_CONFIG_WAS_NO_SLP;
170 list = roar_enum_servers(flags, -1, -1);
171 config->workaround.workarounds = workarounds_store;
172 if ( list != NULL ) {
173  for (i = 0; list[i].server != NULL; i++) {
174   if ( (fh = roar_connect_raw((char*)list[i].server, 0, 0)) != -1 ) {
175    roar_enum_servers_free(list);
176    return fh;
177   }
178  }
179  roar_enum_servers_free(list);
180 }
181#endif
182
183 return -1;
184
185 } else {
186  /* connect via (char*)server */
187  // find a port:
188
189  if ( !strcmp(server, "+invalid") ) {
190   roar_err_set(ROAR_ERROR_CANCELED);
191   return -1;
192  }
193
194  strncpy(user_sock, server, sizeof(user_sock)-1);
195  user_sock[sizeof(user_sock)-1] = 0;
196
197  if ( *user_sock != '/' ) { // don't test AF_UNIX sockets for ports
198   for (i = 0; user_sock[i] != 0; i++) {
199    if ( user_sock[i] == ':' ) {
200     if ( user_sock[i+1] == ':' ) { // DECnet, leave unchanged
201      is_decnet = 1;
202      obj = &user_sock[i+2];
203      break;
204     }
205
206     port = atoi(&(user_sock[i+1]));
207     user_sock[i] = 0;
208     break;
209    }
210   }
211  }
212
213  if ( is_decnet ) {
214   if ( *user_sock == ':' ) {
215    if ( roar_socket_get_local_nodename() != NULL ) {
216     strncpy(user_sock, roar_socket_get_local_nodename(), sizeof(user_sock)-1);
217     user_sock[sizeof(user_sock)-1] = 0;
218     roar_mm_strlcat(user_sock, server, sizeof(user_sock)-1);
219     user_sock[sizeof(user_sock)-1] = 0;
220     obj  = strstr(user_sock, "::");
221     obj += 2;
222    }
223   }
224
225   if ( *obj == 0 ) {
226#ifdef DN_MAXOBJL
227    roar_mm_strlcat(user_sock, ROAR_DEFAULT_OBJECT, sizeof(user_sock)-1);
228    user_sock[sizeof(user_sock)-1] = 0;
229#else
230    ROAR_ERR("roar_connect_raw(*): size of DECnet object unknown.");
231#endif
232   }
233    ROAR_DBG("roar_connect_raw(*): user_sock='%s'", user_sock);
234  }
235
236  if ( port || is_decnet ) {
237   fh = roar_socket_connect(user_sock, port);
238   // restore the original string
239   user_sock[i] = ':';
240  } else {
241   fh = roar_socket_connect(user_sock, ROAR_DEFAULT_PORT);
242  }
243 }
244
245 ROAR_DBG("roar_connect_raw(*) = %i", fh);
246
247 return fh;
248}
249
250int roar_connect     (struct roar_connection * con, const char * server, int flags, uint_least32_t timeout) {
251 int fh;
252
253 if ( con == NULL ) {
254  roar_err_set(ROAR_ERROR_FAULT);
255  return -1;
256 }
257
258 roar_err_set(ROAR_ERROR_UNKNOWN);
259 fh = roar_connect_raw(server, flags, timeout);
260
261 if ( fh == -1 )
262  return -1;
263
264 return roar_connect_fh(con, fh);
265}
266
267int roar_connect_fh (struct roar_connection * con, int fh) {
268
269 if ( con == NULL || fh == -1 ) {
270  roar_err_set(ROAR_ERROR_INVAL);
271  return -1;
272 }
273
274 // specal hack to set an ilegal value used internaly in libroar:
275 if ( fh == -2 )
276  fh = -1;
277
278 memset(con, 0, sizeof(struct roar_connection));
279 con->refc        = 0;
280 con->flags       = ROAR_CON_FLAGS_NONE;
281 con->version     = 0;
282 con->cb_userdata = NULL;
283 con->cb          = NULL;
284
285 roar_err_init(&(con->errorframe));
286
287 if ( roar_vio_open_fh_socket(&(con->viocon), fh) != -1 ) {
288  con->flags |= ROAR_CON_FLAGS_VIO;
289 }
290
291 roar_err_set(ROAR_ERROR_NONE);
292 return 0;
293}
294
295int roar_get_connection_fh (struct roar_connection * con) {
296 int fh;
297
298 ROAR_DBG("roar_get_connection_fh(con=%p) = ?", con);
299
300 roar_debug_warn_sysio("roar_get_connection_fh", "roar_get_connection_vio2", NULL);
301
302 if ( con == NULL )
303  return -1;
304
305 ROAR_DBG("roar_get_connection_fh(con=%p) = ?", con);
306
307 if ( roar_vio_ctl(&(con->viocon), ROAR_VIO_CTL_GET_FH, &fh) == -1 )
308  return -1;
309
310 ROAR_DBG("roar_get_connection_fh(con=%p) = %i", con, fh);
311
312 return fh;
313}
314
315struct roar_vio_calls * roar_get_connection_vio2 (struct roar_connection * con) {
316 if ( con == NULL )
317  return NULL;
318
319 if ( con->flags & ROAR_CON_FLAGS_VIO )
320  return &(con->viocon);
321
322// TODO: try to open the VIO.
323
324 return NULL;
325}
326
327int roar_disconnect (struct roar_connection * con) {
328 struct roar_vio_calls * vio;
329 struct roar_message m;
330
331 memset(&m, 0, sizeof(m));
332
333 m.datalen =  0;
334 m.stream  = -1;
335 m.pos     =  0;
336 m.cmd     = ROAR_CMD_QUIT;
337
338 roar_req(con, &m, NULL);
339
340 if ( (vio = roar_get_connection_vio2(con)) != NULL ) {
341  roar_vio_close(vio);
342 }
343
344 roar_connect_fh(con, -2);
345
346 roar_err_set(ROAR_ERROR_NONE);
347
348 return 0;
349}
350
351int roar_set_connection_callback(struct roar_connection * con,
352                                 void (*cb)(struct roar_connection * con,
353                                            struct roar_message    * mes,
354                                            void                   * data,
355                                            void                   * userdata),
356                                 void * userdata) {
357 if ( con == NULL )
358  return -1;
359
360 con->cb       = cb;
361 con->cb_userdata = userdata;
362
363 return 0;
364}
365
366int roar_sync         (struct roar_connection * con) {
367 // wait for any non-client reqs
368 return roar_wait_msg(con, 0x0000, 0x8000);
369}
370
371int roar_wait_msg     (struct roar_connection * con, int16_t seq, int16_t seqmask) {
372 roar_err_set(ROAR_ERROR_NOSYS);
373 return -1;
374}
375
376int roar_noop         (struct roar_connection * con) {
377 struct roar_message mes;
378
379 if ( con == NULL ) {
380  roar_err_set(ROAR_ERROR_FAULT);
381  return -1;
382 }
383
384 memset(&mes, 0, sizeof(mes));
385
386 mes.cmd = ROAR_CMD_NOOP;
387 mes.stream = -1;
388
389 return roar_req3(con, &mes, NULL);
390}
391
392int roar_identify   (struct roar_connection * con, const char * name) {
393 struct roar_message mes;
394 uint32_t pid;
395 int max_len;
396
397 roar_err_set(ROAR_ERROR_UNKNOWN);
398
399 ROAR_DBG("roar_identify(*): try to identify myself...");
400
401 memset(&mes, 0, sizeof(mes));
402
403 mes.cmd    = ROAR_CMD_IDENTIFY;
404 mes.stream = -1;
405 mes.pos    =  0;
406
407 ROAR_DBG("roar_identify(*): name=%p", name);
408
409 if ( name == NULL )
410  name = "libroar client";
411
412 ROAR_DBG("roar_identify(*): name=%p", name);
413
414 max_len = roar_mm_strlen(name);
415 ROAR_DBG("roar_identify(*): strlen(name) = %i", max_len);
416
417 if ( max_len > (LIBROAR_BUFFER_MSGDATA - 5) )
418  max_len = LIBROAR_BUFFER_MSGDATA - 5;
419
420 mes.datalen = 5 + max_len;
421 mes.data[0] = 1;
422
423 pid = getpid();
424 mes.data[1] = (pid & 0xFF000000UL) >> 24;
425 mes.data[2] = (pid & 0x00FF0000UL) >> 16;
426 mes.data[3] = (pid & 0x0000FF00UL) >>  8;
427 mes.data[4] = (pid & 0x000000FFUL) >>  0;
428 ROAR_DBG("roar_identify(*): pid = %i", (int)pid);
429
430 strncpy(mes.data+5, name, max_len);
431
432 return roar_req3(con, &mes, NULL);
433}
434
435//ll
Note: See TracBrowser for help on using the repository browser.