source: roaraudio/roarclients/roarpluginrunner.c @ 5714:d9d16e63c248

Last change on this file since 5714:d9d16e63c248 was 5712:1548b8b21bd4, checked in by phi, 12 years ago

moved to scheduler API

File size: 15.0 KB
RevLine 
[5336]1//roarpluginrunner.c:
2
3/*
[5381]4 *      Copyright (C) Philipp 'ph3-der-loewe' Schafft - 2011-2012
[5336]5 *
6 *  This file is part of roarclients 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 *  RoarAudio 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 */
25
26int g_verbose = 0;
27#define ROAR_DBG_INFOVAR g_verbose
28
29#include <roaraudio.h>
30
31enum action {
32 RUN,
[5484]33 RUN_AS_APPLICATION,
[5336]34 EXPLAIN
35};
36
[5712]37static struct roar_dl_librarypara * g_para  = NULL;
38static struct roar_scheduler      * g_sched = NULL;
39static struct roar_scheduler_source g_s_service   = {.type = ROAR_SCHEDULER_CPI_SERVICE};
[5336]40
[5354]41static void usage (const char * progname) {
[5336]42 fprintf(stderr, "Usage: %s [OPTIONS]... PLUGIN\n", progname);
43
44 fprintf(stderr, "\nOptions:\n\n");
45
[5484]46 fprintf(stderr, " -h --help               - This help.\n"
47                 " -v --verbose            - Be verbose. Can be used multiple times.\n"
48                 "    --server SERVER      - Set default server to SERVER.\n"
49                 "    --run                - Run plugin.\n"
50                 "    --run-as-application - Same as --run except all tailing arguments are\n"
51                 "                           passed to the plugin.\n"
52                 "    --explain            - Explain plugin.\n"
53                 "    --appname NAME       - Sets the appname.\n"
54                 "    --abiversion ABI     - Set the ABI version.\n"
55                 "    --args ARGS          - Set plugin arguments.\n"
[5353]56        );
[5336]57}
58
59static int do_run(const char * name) {
[5712]60 struct roar_scheduler_source s_container;
[5442]61 struct roar_plugincontainer * cont = roar_plugincontainer_new(g_para);
62 int err;
[5336]63
[5442]64 if ( cont == NULL )
[5336]65  return -1;
66
[5712]67 memset(&s_container, 0, sizeof(s_container));
68 s_container.type = ROAR_SCHEDULER_PLUGINCONTAINER;
69 s_container.handle.container = cont;
70 roar_scheduler_source_add(g_sched, &s_container);
71
[5442]72 if ( roar_plugincontainer_load(cont, name, NULL) == -1 ) {
73  err = roar_error;
74  roar_plugincontainer_unref(cont);
75  roar_error = err;
76  return -1;
77 }
[5336]78
[5442]79 roar_plugincontainer_appsched_trigger(cont, ROAR_DL_APPSCHED_INIT);
80
[5712]81/*
[5442]82 while (roar_plugincontainer_appsched_trigger(cont, ROAR_DL_APPSCHED_WAIT) == 0)
83  roar_plugincontainer_appsched_trigger(cont, ROAR_DL_APPSCHED_UPDATE);
[5712]84*/
85 roar_scheduler_run(g_sched);
[5336]86
[5442]87 roar_plugincontainer_appsched_trigger(cont, ROAR_DL_APPSCHED_UPDATE);
88 roar_plugincontainer_appsched_trigger(cont, ROAR_DL_APPSCHED_FREE);
89
[5712]90 roar_scheduler_source_del(g_sched, &s_container);
[5442]91 roar_plugincontainer_unref(cont);
[5336]92 return 0;
93}
94
95static const char * _ptr2str(const void * p) {
[5517]96#if defined(ROAR_HAVE_H_DLFCN) && defined(ROAR_HAVE_DLADDR)
[5353]97 static char buf[80];
98 Dl_info info;
99#else
[5336]100 static char buf[24];
[5353]101#endif
[5336]102
103 if ( p == NULL )
104  return "<not set>";
105
[5517]106#if defined(ROAR_HAVE_H_DLFCN) && defined(ROAR_HAVE_DLADDR)
[5353]107 if ( dladdr(p, &info) != 0 ) {
108  if ( p == info.dli_saddr ) {
109   snprintf(buf, sizeof(buf), "%p <%s in \"%s\">", p, info.dli_sname, info.dli_fname);
110   return buf;
111  }
112 }
113#endif
114
[5336]115 snprintf(buf, sizeof(buf), "%p", p);
116
117 return buf;
118}
119
120static const char * _ptrrange2str(const void * p, size_t len) {
[5353]121 static char buf[80];
[5336]122
123 if ( p == NULL )
124  return "<not set>";
125
126 if ( len == 0 )
127  return _ptr2str(p);
128
129 snprintf(buf, sizeof(buf), "%p-%p", p, p + len);
130
131 return buf;
132}
133
134static int do_explain(const char * name) {
[5427]135 struct roar_dl_lhandle * lhandle = roar_dl_open(name, ROAR_DL_FLAG_LAZY|ROAR_DL_FLAG_PLUGINPATH, 0, g_para);
[5336]136 struct roar_dl_libraryinst * (*func)(struct roar_dl_librarypara * para);
137 struct roar_dl_libraryinst * lib;
[5347]138 int libok = 0, libnameok = 0, libdepok = 0;
[5336]139 int tmp;
140 int i;
[5347]141 size_t iter;
142 char c;
[5336]143
144 if ( lhandle == NULL )
145  return -1;
146
147 func = roar_dl_getsym(lhandle, "_roaraudio_library_init", -1);
148 if ( func == NULL ) {
149  fprintf(stderr, "Warning: Not a RA lib: %s\n", name);
150  roar_dl_unref(lhandle);
151  return 0;
152 }
153
154 lib = func(g_para);
155 if ( lib == NULL ) {
[5353]156  fprintf(stderr, "Warning: Can not RA init: %s: %s\n", name, roar_error2str(roar_error));
[5336]157  roar_dl_unref(lhandle);
158  return 0;
159 }
160
161 if ( lib->version == ROAR_DL_LIBINST_VERSION && lib->len == sizeof(*lib) ) {
162  libok = 1;
163 }
164
165 printf("lib                     = %s\n", _ptr2str(lib));
[5353]166 if ( g_verbose || !libok ) {
167  printf("|-> version             = %i (%smatch)\n", lib->version, lib->version == ROAR_DL_LIBINST_VERSION ? "" : "no ");
168  printf("%c-> len                 = %zu (%smatch)\n", libok ? '|' : '\\', lib->len, lib->len == sizeof(*lib) ? "" : "no ");
169 }
[5336]170
171 if ( libok ) {
[5353]172  if ( g_verbose || lib->unload != NULL )
173   printf("|-> unload              = %s\n", _ptr2str(lib->unload));
[5336]174  printf("|-> func                = {");
[5346]175  i = 0;
176  while (i < ROAR_DL_FN_MAX) {
177   for (tmp = 0; i < ROAR_DL_FN_MAX; i++) {
178    if ( lib->func[i] != NULL ) {
179     break;
180    }
181    tmp++;
182   }
183   if (tmp)
184    printf("%i x <not set>%s", tmp, i < (ROAR_DL_FN_MAX-1) ? ", " : "");
185
186   if ( i < ROAR_DL_FN_MAX ) {
187    printf("[%i] = %s%s", i, _ptr2str(lib->func[i]), i < (ROAR_DL_FN_MAX-1) ? ", " : "");
188    i++;
[5336]189   }
190  }
[5346]191
[5336]192  printf("}\n");
193  printf("|-> libname             = %s\n", _ptr2str(lib->libname));
194  if ( lib->libname != NULL ) {
195   if ( lib->libname->version == ROAR_DL_LIBNAME_VERSION && lib->libname->len == sizeof(*(lib->libname)) ) {
196    libnameok = 1;
197   }
[5353]198   if ( g_verbose || !libnameok ) {
199    printf("|   |-> version         = %i (%smatch)\n", lib->libname->version,
200                                                       lib->libname->version == ROAR_DL_LIBNAME_VERSION ? "" : "no ");
201    printf("|   %c-> len             = %zu (%smatch)\n", libnameok ? '|' : '\\', lib->libname->len,
202                                                         lib->libname->len == sizeof(*(lib->libname)) ? "" : "no ");
203   }
204
[5336]205   if ( libnameok ) {
[5347]206#define _ps(k,name) \
[5336]207    tmp = (lib->libname->name) != NULL; \
[5353]208    if ( tmp || g_verbose || (k) == '\\' ) \
[5347]209    printf("|   %c-> %-15s = %s%s%s\n", (k), #name, tmp ? "\"" : "", \
[5336]210                                    tmp ? (lib->libname->name) : "<not set>", tmp ? "\"" : "");
211
212    _ps('|', name);
213    _ps('|', libname);
214    _ps('|', libversion);
215    _ps('|', abiversion);
216    _ps('|', description);
217    _ps('|', contact);
218    _ps('|', authors);
219    _ps('\\', license);
220#undef _ps
221   }
222  }
[5353]223  if ( g_verbose || lib->global_data_pointer != NULL )
224   printf("|-> global_data_len     = %zu\n", lib->global_data_len);
225  if ( g_verbose || lib->global_data_init != NULL )
226   printf("|-> global_data_init    = %s\n", _ptrrange2str(lib->global_data_init, lib->global_data_len));
227  if ( g_verbose || lib->global_data_pointer != NULL )
228   printf("|-> global_data_pointer = %s\n", _ptr2str(lib->global_data_pointer));
229
[5347]230  if ( lib->libdep != NULL && lib->libdep_len ) {
231   printf("|-> libdep              = %s\n", _ptr2str(lib->libdep));
232   for (iter = 0; iter < lib->libdep_len; iter++) {
233    printf("|   %c-> Table entry %zu   = %p\n", iter == (lib->libdep_len-1) ? '\\' : '|', iter, &(lib->libdep[iter]));
234    c = iter == (lib->libdep_len-1) ? ' ' : '|';
235    if ( lib->libdep[iter].version == ROAR_DL_LIBDEP_VERSION &&
236         lib->libdep[iter].len     == sizeof(struct roar_dl_librarydep) ) {
237     libdepok = 1;
238    } else {
239     libdepok = 0;
240    }
[5353]241    if ( g_verbose || !libdepok ) {
242     printf("|   %c   |-> version     = %i (%smatch)\n", c, lib->libdep[iter].version,
243                                                         lib->libdep[iter].version == ROAR_DL_LIBDEP_VERSION ? "" : "no ");
244     printf("|   %c   %c-> len         = %zu (%smatch)\n", c, libdepok ? '|' : '\\',
245                                                        lib->libdep[iter].len,
246                                                        lib->libdep[iter].len == sizeof(struct roar_dl_librarydep) ?
247                                                        "" : "no ");
248    }
249
[5347]250    if ( libdepok ) {
251     printf("|   %c   |-> flags       = 0x%.8lX\n", c, (unsigned long int)lib->libdep[iter].flags);
252#define _ps(k,name) \
253    tmp = (lib->libdep[iter].name) != NULL; \
[5353]254    if ( tmp || g_verbose || (k) == '\\' ) \
[5347]255    printf("|   %c   %c-> %-11s = %s%s%s\n", c, (k), #name, tmp ? "\"" : "", \
256                                    tmp ? (lib->libdep[iter].name) : "<not set>", tmp ? "\"" : "");
257     _ps('|', name);
258     _ps('|', libname);
259     _ps('\\', abiversion);
260#undef _ps
261    }
262   }
263   printf("|-> libdep_len          = %zu\n", lib->libdep_len);
264  } else if ( (lib->libdep == NULL && lib->libdep_len) || (lib->libdep != NULL && !lib->libdep_len) ) {
265   printf("|-> libdep              = %s (invalid)\n", _ptr2str(lib->libdep));
266   printf("|-> libdep_len          = %zu (invalid)\n", lib->libdep_len);
267  }
[5353]268  if ( g_verbose || lib->appsched != NULL ) {
269   printf("|-> appsched            = %s\n", _ptr2str(lib->appsched));
270   if ( lib->appsched != NULL ) {
[5355]271    if ( g_verbose || lib->appsched->init != NULL )
[5353]272     printf("|   |-> init            = %s\n", _ptr2str(lib->appsched->init));
[5355]273    if ( g_verbose || lib->appsched->free != NULL )
[5353]274     printf("|   |-> free            = %s\n", _ptr2str(lib->appsched->free));
[5355]275    if ( g_verbose || lib->appsched->update != NULL )
[5353]276     printf("|   |-> update          = %s\n", _ptr2str(lib->appsched->update));
[5355]277    if ( g_verbose || lib->appsched->tick != NULL )
[5353]278     printf("|   |-> tick            = %s\n", _ptr2str(lib->appsched->tick));
279    printf("|   \\-> wait            = %s\n", _ptr2str(lib->appsched->wait));
280   }
[5336]281  }
[5353]282#define _ps(k,name) \
283    tmp = (lib->name) != NULL; \
284    if ( tmp || g_verbose || (k) == '\\' ) \
285    printf("%c-> %-19s = %s%s%s\n", (k), #name, tmp ? "\"" : "", \
286                                    tmp ? (lib->name) : "<not set>", tmp ? "\"" : "");
287  _ps('|', host_appname);
288  _ps('\\', host_abiversion);
289#undef _ps
[5336]290 }
291
292 roar_dl_unref(lhandle);
293 return 0;
294}
295
296static int do_plugin(enum action action, const char * name) {
297 switch (action) {
298  case EXPLAIN:
299    return do_explain(name);
300   break;
301  case RUN:
[5484]302  case RUN_AS_APPLICATION:
[5336]303    return do_run(name);
304   break;
305  default:
306    roar_err_set(ROAR_ERROR_BADRQC);
307    return -1;
308   break;
309 }
310}
311
312static inline void _clear_para(void) {
[5341]313 if ( g_para == NULL )
314  return;
315
316 roar_dl_para_unref(g_para);
[5336]317 g_para = NULL;
318}
319
[5484]320static inline int _add_para(struct roar_dl_librarypara * para, const char * pluginargs, size_t argc, char * argv[]) {
321 struct roar_keyval * kv;
322 ssize_t argslen, argvlen;
323 ssize_t arglen;
324 ssize_t pluginargc;
325 size_t argv_phys = argc;
326 size_t i;
327 int error;
328 char * sp, * c;
329 int after_parser_end;
330
331 if ( pluginargs == NULL )
332  pluginargs = "";
333
334 argslen = roar_mm_strlen(pluginargs) + 1 /* tailing '\0' */;
335
336 after_parser_end = 0;
337 argvlen = 0;
338 for (i = 0; i < argv_phys; i++) {
339  arglen   = roar_mm_strlen(argv[i]);
340  argvlen += arglen;
341  if ( !after_parser_end ) {
342   if ( !strcmp(argv[i], "--") ) {
343    after_parser_end = 1;
344    argc--;
345   } else if ( arglen > 1 && argv[i][0] == '-' && !(arglen > 2 && argv[i][1] == '-') ) {
346    argc += arglen - 2;
347   }
348  }
349 }
350 argvlen += argc; // the '\0's.
351
352 para->args_store = roar_mm_malloc(argslen+argvlen);
353 if ( para == NULL )
354  return -1;
355
356 memcpy(para->args_store, pluginargs, argslen);
357
358 pluginargc = roar_keyval_split(&kv, para->args_store, NULL, NULL, 1);
359 if ( pluginargc == -1 ) {
360  error = roar_error;
361  roar_mm_free(para->args_store);
362  para->args_store = NULL;
363  roar_error = error;
364  return -1;
365 }
366
367 para->argv = roar_mm_malloc((pluginargc+argc)*sizeof(struct roar_keyval));
368 if ( para->argv == NULL ) {
369  error = roar_error;
370  roar_mm_free(kv);
371  roar_mm_free(para->args_store);
372  para->args_store = NULL;
373  roar_error = error;
374  return -1;
375 }
376
377 para->argc = pluginargc + argc;
378
379 memcpy(para->argv, kv, pluginargc*sizeof(struct roar_keyval));
380 roar_mm_free(kv);
381
382 sp = para->args_store + argslen;
383 kv = para->argv + pluginargc;
384
385 after_parser_end = 0;
386 for (i = 0; i < argv_phys; i++) {
387  arglen = roar_mm_strlen(argv[i]) + 1;
388  if ( after_parser_end || !(arglen > 2 && argv[i][0] == '-' && !(arglen > 3 && argv[i][1] == '-')) )
389   memcpy(sp, argv[i], arglen);
390
391  if ( !after_parser_end && !strcmp(argv[i], "--") ) {
392   after_parser_end = 1;
393   continue;
394  } else if ( !after_parser_end && arglen > 3 && sp[0] == '-' && sp[1] == '-' ) {
395   kv->key = sp + 2;
396   kv->value = NULL;
397   for (c = sp + 2; *c; c++) {
398    if (*c == '=') {
399     *c = 0;
400     c++;
401     kv->value = c;
402     break;
403    }
404   }
405  } else if ( !after_parser_end && arglen > 2 && argv[i][0] == '-' ) {
406   for (c = argv[i] + 1; *c; c++) {
407    sp[0] = *c;
408    sp[1] = 0;
409    kv->key = sp;
410    kv->value = NULL;
411    sp += 2;
412    kv++;
413   }
414   continue;
415  } else {
416   kv->key = NULL;
417   kv->value = sp;
418  }
419
420  sp += arglen;
421  kv++;
422 }
423
424 return 0;
425}
426
[5336]427int main (int argc, char * argv[]) {
[5353]428 const char * appname    = "roarpluginrunner " ROAR_VSTR_ROARAUDIO;
429 const char * abiversion = "1.0beta0";
[5341]430 const char * pluginargs = NULL;
[5336]431 enum action action = RUN;
432 int ret = 0;
433 int i;
[5534]434 const char * k;
[5336]435
[5712]436 g_sched = roar_scheduler_new(ROAR_SCHEDULER_FLAG_NONE, ROAR_SCHEDULER_STRATEGY_DEFAULT);
437 if ( g_sched == NULL ) {
438  fprintf(stderr, "Error creating scheduler object: %s\n", roar_error2str(roar_error));
439  return 1;
440 }
441
442 roar_scheduler_source_add(g_sched, &g_s_service);
443
[5336]444 for (i = 1; i < argc; i++) {
445  k = argv[i];
446
447  if ( !strcmp(k, "-h") || !strcmp(k, "--help") ) {
448   usage(argv[0]);
[5712]449   roar_scheduler_unref(g_sched);
[5336]450   return 0;
451  } else if ( !strcmp(k, "--run") ) {
452   action = RUN;
[5484]453  } else if ( !strcmp(k, "--run-as-application") ) {
454   action = RUN_AS_APPLICATION;
[5336]455  } else if ( !strcmp(k, "--explain") ) {
456   action = EXPLAIN;
[5355]457  } else if ( !strcmp(k, "-v") || !strcmp(k, "--verbose") ) {
[5336]458   g_verbose++;
[5353]459  } else if ( !strcmp(k, "--server") ) {
460   roar_libroar_set_server(argv[++i]);
[5341]461  } else if ( !strcmp(k, "--appname") ) {
462   appname = argv[++i];
463   _clear_para();
464  } else if ( !strcmp(k, "--abiversion") ) {
465   abiversion = argv[++i];
466   _clear_para();
467  } else if ( !strcmp(k, "--args") ) {
468   pluginargs = argv[++i];
469   _clear_para();
[5336]470  } else {
471   if ( g_para == NULL )
[5484]472    g_para = roar_dl_para_new(action == RUN_AS_APPLICATION ? NULL : pluginargs, NULL, appname, abiversion);
473   if ( action == RUN_AS_APPLICATION && _add_para(g_para, pluginargs, argc - i - 1, &(argv[i+1])) == -1 ) {
474    fprintf(stderr, "Error parsing plugin arguments: %s\n", roar_error2str(roar_error));
475   } else {
476    roar_err_set(ROAR_ERROR_NONE);
477    if ( do_plugin(action, k) == -1 ) {
478     fprintf(stderr, "Error loading plugin: %s\n",
479                     roar_error != ROAR_ERROR_NONE ? roar_error2str(roar_error) : roar_dl_errstr(NULL));
480     ret = 1;
481    }
[5341]482   }
[5484]483   if ( action == RUN_AS_APPLICATION )
484    break; // end looping over arguments
[5336]485  }
486 }
487
488 _clear_para();
489
[5712]490 roar_scheduler_unref(g_sched);
[5336]491 return ret;
492}
493
494//ll
Note: See TracBrowser for help on using the repository browser.