From c25ccbb4bac26f43d117d44f0a3bf1bb446d1e56 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 14 Nov 2016 12:42:00 +0100 Subject: [PATCH] WIP change object model --- pinos/client/array.h | 3 + pinos/client/meson.build | 2 + pinos/client/object.h | 5 +- pinos/client/pinos.h | 1 + pinos/client/signal.h | 46 +- pinos/client/utils.c | 83 ++++ .../spa/spa-alsa-monitor.h => client/utils.h} | 39 +- pinos/daemon/daemon-config.c | 137 +++--- pinos/daemon/daemon-config.h | 41 +- pinos/daemon/main.c | 13 +- pinos/modules/spa/meson.build | 12 +- pinos/modules/spa/module.c | 28 +- pinos/modules/spa/spa-alsa-monitor.c | 251 ---------- pinos/modules/spa/spa-audiotestsrc.c | 207 --------- pinos/modules/spa/spa-audiotestsrc.h | 36 -- .../spa/{spa-v4l2-monitor.c => spa-monitor.c} | 180 ++++--- .../spa/{spa-v4l2-monitor.h => spa-monitor.h} | 24 +- pinos/modules/spa/spa-node.c | 138 ++++++ pinos/modules/spa/spa-node.h | 52 +++ pinos/modules/spa/spa-videotestsrc.c | 172 ------- pinos/modules/spa/spa-videotestsrc.h | 43 -- pinos/server/client-node.c | 227 +++++---- pinos/server/client-node.h | 32 +- pinos/server/client.c | 176 +++---- pinos/server/client.h | 39 +- pinos/server/command.c | 177 +++---- pinos/server/command.h | 49 +- pinos/server/core.c | 91 +++- pinos/server/core.h | 72 ++- pinos/server/daemon.c | 439 +++++++----------- pinos/server/daemon.h | 14 +- pinos/server/data-loop.c | 269 +++++------ pinos/server/data-loop.h | 31 +- pinos/server/link.c | 271 ++++------- pinos/server/link.h | 35 +- pinos/server/main-loop.c | 30 +- pinos/server/module.c | 152 +++--- pinos/server/module.h | 44 +- pinos/server/node.c | 309 ++++-------- pinos/server/node.h | 61 ++- pinos/server/registry.c | 9 +- pinos/server/registry.h | 28 +- spa/include/spa/defs.h | 13 +- spa/plugins/v4l2/v4l2-source.c | 1 + 44 files changed, 1557 insertions(+), 2525 deletions(-) create mode 100644 pinos/client/utils.c rename pinos/{modules/spa/spa-alsa-monitor.h => client/utils.h} (50%) delete mode 100644 pinos/modules/spa/spa-alsa-monitor.c delete mode 100644 pinos/modules/spa/spa-audiotestsrc.c delete mode 100644 pinos/modules/spa/spa-audiotestsrc.h rename pinos/modules/spa/{spa-v4l2-monitor.c => spa-monitor.c} (64%) rename pinos/modules/spa/{spa-v4l2-monitor.h => spa-monitor.h} (56%) create mode 100644 pinos/modules/spa/spa-node.c create mode 100644 pinos/modules/spa/spa-node.h delete mode 100644 pinos/modules/spa/spa-videotestsrc.c delete mode 100644 pinos/modules/spa/spa-videotestsrc.h diff --git a/pinos/client/array.h b/pinos/client/array.h index 050002f97..96b8f5177 100644 --- a/pinos/client/array.h +++ b/pinos/client/array.h @@ -112,6 +112,9 @@ pinos_array_add_fixed (PinosArray *arr, return p; } +#define pinos_array_add_ptr(a,p) \ + *((void**) pinos_array_add (a, sizeof (void*))) = (p) + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/pinos/client/meson.build b/pinos/client/meson.build index e41dfaf47..a73eb64c7 100644 --- a/pinos/client/meson.build +++ b/pinos/client/meson.build @@ -14,6 +14,7 @@ pinos_headers = [ 'subscribe.h', 'thread-mainloop.h', 'transport.h', + 'utils.h', ] pinos_sources = [ @@ -33,6 +34,7 @@ pinos_sources = [ 'subscribe.c', 'thread-mainloop.c', 'transport.c', + 'utils.c', gdbus_target, ] diff --git a/pinos/client/object.h b/pinos/client/object.h index 50e82d54d..1a863cc58 100644 --- a/pinos/client/object.h +++ b/pinos/client/object.h @@ -47,7 +47,8 @@ struct _PinosObject { uint32_t id; PinosObjectFlags flags; PinosDestroyFunc destroy; - PinosSignal destroy_signal; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosObject *object)); unsigned int n_interfaces; PinosInterface *interfaces; }; @@ -81,7 +82,7 @@ static inline void pinos_object_destroy (PinosObject *object) { object->flags |= PINOS_OBJECT_FLAG_DESTROYING; - pinos_signal_emit (&object->destroy_signal, object, NULL); + pinos_signal_emit (&object->destroy_signal, object); if (object->destroy) object->destroy (object); } diff --git a/pinos/client/pinos.h b/pinos/client/pinos.h index 440fea0f4..3cbaf82af 100644 --- a/pinos/client/pinos.h +++ b/pinos/client/pinos.h @@ -32,6 +32,7 @@ extern const char g_log_domain_pinos[]; #include #include #include +#include #include diff --git a/pinos/client/signal.h b/pinos/client/signal.h index 913ad1080..ec175658f 100644 --- a/pinos/client/signal.h +++ b/pinos/client/signal.h @@ -31,25 +31,31 @@ typedef struct _PinosListener PinosListener; struct _PinosListener { SpaList link; - void (*notify) (PinosListener *listener, void *object, void *data); + void (*notify) (void *); }; +#if 0 struct _PinosSignal { SpaList listeners; + void (*notify) (PinosListener *listener, void *object, void *data); }; +#endif -static inline void -pinos_signal_init (PinosSignal *signal) -{ - spa_list_init (&signal->listeners); -} +#define PINOS_SIGNAL(name,func) \ + union { \ + SpaList listeners; \ + void (*notify) func; \ + } name; -static inline void -pinos_signal_add (PinosSignal *signal, - PinosListener *listener) -{ - spa_list_insert (signal->listeners.prev, &listener->link); -} +#define pinos_signal_init(signal) \ + spa_list_init (&(signal)->listeners); + +#define pinos_signal_add(signal,listener,func) \ + do { \ + __typeof__((signal)->notify) n = (func); \ + (listener)->notify = (void (*) (void *)) n; \ + spa_list_insert ((signal)->listeners.prev, &(listener)->link); \ + } while (false); static inline void pinos_signal_remove (PinosListener *listener) @@ -57,16 +63,12 @@ pinos_signal_remove (PinosListener *listener) spa_list_remove (&listener->link); } -static inline void -pinos_signal_emit (PinosSignal *signal, - void *object, - void *data) -{ - PinosListener *l, *next; - - spa_list_for_each_safe (l, next, &signal->listeners, link) - l->notify (l, object, data); -} +#define pinos_signal_emit(signal,...) \ + do { \ + PinosListener *l, *next; \ + spa_list_for_each_safe (l, next, &(signal)->listeners, link) \ + ((__typeof__((signal)->notify))l->notify) (l,__VA_ARGS__); \ + } while (false); #ifdef __cplusplus } diff --git a/pinos/client/utils.c b/pinos/client/utils.c new file mode 100644 index 000000000..c4475bed4 --- /dev/null +++ b/pinos/client/utils.c @@ -0,0 +1,83 @@ +/* Simple Plugin API + * Copyright (C) 2016 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include + +#include +#include +#include + +const char * +pinos_split_walk (const char *str, + const char *delimiter, + size_t *len, + const char **state) +{ + const char *s = *state ? *state : str; + + if (*s == '\0') + return NULL; + + *len = strcspn (s, delimiter); + + *state = s + *len; + *state += strspn (*state, delimiter); + + return s; +} + +char ** +pinos_split_strv (const char *str, + const char *delimiter, + int max_tokens, + int *n_tokens) +{ + const char *state = NULL, *s = NULL; + PinosArray arr; + size_t len; + int n = 0; + + pinos_array_init (&arr); + + s = pinos_split_walk (str, delimiter, &len, &state); + while (s && n + 1 < max_tokens) { + pinos_array_add_ptr (&arr, strndup (s, len)); + s = pinos_split_walk (str, delimiter, &len, &state); + n++; + } + if (s) { + pinos_array_add_ptr (&arr, strdup (s)); + n++; + } + pinos_array_add_ptr (&arr, NULL); + + *n_tokens = n; + + return arr.data; +} + + +void +pinos_free_strv (char **str) +{ + int i; + for (i = 0; str[i]; i++) + free (str[i]); + free (str); +} diff --git a/pinos/modules/spa/spa-alsa-monitor.h b/pinos/client/utils.h similarity index 50% rename from pinos/modules/spa/spa-alsa-monitor.h rename to pinos/client/utils.h index 3875b9363..63b452646 100644 --- a/pinos/modules/spa/spa-alsa-monitor.h +++ b/pinos/client/utils.h @@ -1,5 +1,5 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans +/* Simple Plugin API + * Copyright (C) 2016 Wim Taymans * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -17,26 +17,29 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PINOS_SPA_ALSA_MONITOR_H__ -#define __PINOS_SPA_ALSA_MONITOR_H__ +#ifndef __PINOS_UTILS_H__ +#define __PINOS_UTILS_H__ -#include +#ifdef __cplusplus +extern "C" { +#endif +#include -#include -#include +const char * pinos_split_walk (const char *str, + const char *delimiter, + size_t *len, + const char **state); -G_BEGIN_DECLS +char ** pinos_split_strv (const char *str, + const char *delimiter, + int max_tokens, + int *n_tokens); -typedef struct _PinosSpaALSAMonitor PinosSpaALSAMonitor; +void pinos_free_strv (char **str); -struct _PinosSpaALSAMonitor { - SpaMonitor *monitor; -}; +#ifdef __cplusplus +} /* extern "C" */ +#endif -PinosSpaALSAMonitor * pinos_spa_alsa_monitor_new (PinosCore *core); -void pinos_spa_alsa_monitor_destroy (PinosSpaALSAMonitor *monitor); - -G_END_DECLS - -#endif /* __PINOS_SPA_ALSA_MONITOR_H__ */ +#endif /* __PINOS_UTILS_H__ */ diff --git a/pinos/daemon/daemon-config.c b/pinos/daemon/daemon-config.c index c4c766488..d9680c074 100644 --- a/pinos/daemon/daemon-config.c +++ b/pinos/daemon/daemon-config.c @@ -22,7 +22,6 @@ #include "config.h" #endif -#include #include #include @@ -32,29 +31,17 @@ #define DEFAULT_CONFIG_FILE PINOS_CONFIG_DIR G_DIR_SEPARATOR_S "pinos.conf" -GQuark -pinos_daemon_config_error_quark (void) -{ - static GQuark quark = 0; - - if (quark == 0) { - quark = g_quark_from_static_string ("pinos_daemon_config_error"); - } - - return quark; -} - -static gboolean -parse_line (PinosDaemonConfig * config, - const gchar * filename, - gchar * line, - guint lineno, - GError ** err) +static bool +parse_line (PinosDaemonConfig *config, + const char *filename, + char *line, + unsigned int lineno, + char **err) { PinosCommand *command = NULL; - gchar *p; - gboolean ret = TRUE; - GError *local_err = NULL; + char *p; + bool ret = true; + char *local_err = NULL; /* search for comments */ if ((p = strchr (line, '#'))) @@ -64,16 +51,14 @@ parse_line (PinosDaemonConfig * config, g_strstrip (line); if (*line == '\0') /* empty line */ - return TRUE; + return true; - if (!pinos_command_parse (&command, line, &local_err)) { - g_set_error (err, PINOS_DAEMON_CONFIG_ERROR, - PINOS_DAEMON_CONFIG_ERROR_COMMAND, "%s:%u: %s", filename, lineno, - local_err->message); - g_error_free (local_err); - ret = FALSE; + if ((command = pinos_command_parse (line, &local_err)) == NULL) { + asprintf (err, "%s:%u: %s", filename, lineno, local_err); + free (local_err); + ret = false; } else { - config->commands = g_list_append (config->commands, command); + spa_list_insert (config->commands.prev, &command->link); } return ret; @@ -89,9 +74,8 @@ pinos_daemon_config_new (void) { PinosDaemonConfig *config; - config = g_new (PinosDaemonConfig, 1); - - config->commands = NULL; + config = calloc (1, sizeof (PinosDaemonConfig)); + spa_list_init (&config->commands); return config; } @@ -105,52 +89,50 @@ pinos_daemon_config_new (void) void pinos_daemon_config_free (PinosDaemonConfig * config) { - g_return_if_fail (config != NULL); + PinosCommand *cmd, *tmp; - g_list_free_full (config->commands, (GDestroyNotify) pinos_command_free); + spa_list_for_each_safe (cmd, tmp, &config->commands, link) + pinos_command_free (cmd); - g_free (config); + free (config); } /** * pinos_daemon_config_load_file: * @config: A #PinosDaemonConfig * @filename: A filename - * @err: Return location for a #GError, or %NULL + * @err: Return location for an error string * * Loads pinos config from @filename. * - * Returns: %TRUE on success, otherwise %FALSE and @err is set. + * Returns: %true on success, otherwise %false and @err is set. */ -gboolean -pinos_daemon_config_load_file (PinosDaemonConfig * config, - const gchar * filename, - GError ** err) +bool +pinos_daemon_config_load_file (PinosDaemonConfig *config, + const char *filename, + char **err) { - gchar *data; - gchar **lines; - gboolean ret = TRUE; - guint i; - - g_return_val_if_fail (config != NULL, FALSE); - g_return_val_if_fail (filename != NULL && *filename != '\0', FALSE); + char *data; + char **lines; + bool ret = true; + unsigned int i; + int n_lines; pinos_log_debug ("deamon-config %p loading file %s", config, filename); - if (!g_file_get_contents (filename, &data, NULL, err)) { - return FALSE; - } + if (!g_file_get_contents (filename, &data, NULL, NULL)) + return false; - lines = g_strsplit (data, "\n", 0); + lines = pinos_split_strv (data, "\n", 0, &n_lines); for (i = 0; lines[i] != NULL; i++) { if (!parse_line (config, filename, lines[i], i+1, err)) { - ret = FALSE; + ret = false; break; } } - g_strfreev (lines); - g_free (data); + pinos_free_strv (lines); + free (data); return ret; } @@ -163,23 +145,20 @@ pinos_daemon_config_load_file (PinosDaemonConfig * config, * Loads the default config file for pinos. The filename can be overridden with * an evironment variable PINOS_CONFIG_FILE. * - * Return: %TRUE on success, otherwise %FALSE and @err is set. + * Return: %true on success, otherwise %false and @err is set. */ -gboolean -pinos_daemon_config_load (PinosDaemonConfig * config, - GError ** err) +bool +pinos_daemon_config_load (PinosDaemonConfig *config, + char **err) { const gchar *filename; - g_return_val_if_fail (config != NULL, FALSE); - - filename = g_getenv ("PINOS_CONFIG_FILE"); + filename = getenv ("PINOS_CONFIG_FILE"); if (filename != NULL && *filename != '\0') { pinos_log_debug ("PINOS_CONFIG_FILE set to: %s", filename); } else { filename = DEFAULT_CONFIG_FILE; } - return pinos_daemon_config_load_file (config, filename, err); } @@ -191,29 +170,27 @@ pinos_daemon_config_load (PinosDaemonConfig * config, * Run all commands that have been parsed. The list of commands will be cleared * when this function has been called. * - * Returns: %TRUE if all commands where executed with success, otherwise %FALSE. + * Returns: %true if all commands where executed with success, otherwise %false. */ -gboolean -pinos_daemon_config_run_commands (PinosDaemonConfig * config, - PinosDaemon * daemon) +bool +pinos_daemon_config_run_commands (PinosDaemonConfig *config, + PinosDaemon *daemon) { - GList *walk; - GError *err = NULL; - gboolean ret = TRUE; + char *err = NULL; + bool ret = true; + PinosCommand *command, *tmp; - g_return_val_if_fail (config != NULL, FALSE); - - for (walk = config->commands; walk != NULL; walk = walk->next) { - PinosCommand *command = (PinosCommand *)walk->data; + spa_list_for_each (command, &config->commands, link) { if (!pinos_command_run (command, daemon->core, &err)) { - pinos_log_warn ("could not run command %s: %s", - pinos_command_get_name (command), err->message); - g_clear_error (&err); - ret = FALSE; + pinos_log_warn ("could not run command %s: %s", command->name, err); + free (err); + ret = false; } } - g_list_free_full (config->commands, (GDestroyNotify) pinos_command_free); + spa_list_for_each_safe (command, tmp, &config->commands, link) { + pinos_command_free (command); + } return ret; } diff --git a/pinos/daemon/daemon-config.h b/pinos/daemon/daemon-config.h index 30df4c597..f7358c509 100644 --- a/pinos/daemon/daemon-config.h +++ b/pinos/daemon/daemon-config.h @@ -27,47 +27,20 @@ G_BEGIN_DECLS #include -#define PINOS_TYPE_DAEMON_CONFIG (pinos_daemon_config_get_type ()) - typedef struct _PinosDaemonConfig PinosDaemonConfig; struct _PinosDaemonConfig { - GList *commands; + SpaList commands; }; -GQuark pinos_daemon_config_error_quark (void); -/** - * PINOS_DAEMON_CONFIG_ERROR: - * - * Pinos daemon config error. - */ -#define PINOS_DAEMON_CONFIG_ERROR (pinos_daemon_config_error_quark ()) - -/** - * PinosDaemonConfigError: - * @PINOS_DAEMON_CONFIG_ERROR_GENERIC: Generic daemon config error. - * @PINOS_DAEMON_CONFIG_ERROR_ASSIGNMENT: Assignment error. - * @PINOS_DAEMON_CONFIG_ERROR_COMMAND: Command error. - * - * Error codes for Pinos daemon config. - */ -typedef enum -{ - PINOS_DAEMON_CONFIG_ERROR_GENERIC, - PINOS_DAEMON_CONFIG_ERROR_ASSIGNMENT, - PINOS_DAEMON_CONFIG_ERROR_COMMAND, -} PinosDaemonConfigError; - -GType pinos_daemon_config_get_type (void); - PinosDaemonConfig * pinos_daemon_config_new (void); void pinos_daemon_config_free (PinosDaemonConfig *config); -gboolean pinos_daemon_config_load_file (PinosDaemonConfig *config, - const gchar *filename, - GError **err); -gboolean pinos_daemon_config_load (PinosDaemonConfig *config, - GError **err); -gboolean pinos_daemon_config_run_commands (PinosDaemonConfig *config, +bool pinos_daemon_config_load_file (PinosDaemonConfig *config, + const char *filename, + char **err); +bool pinos_daemon_config_load (PinosDaemonConfig *config, + char **err); +bool pinos_daemon_config_run_commands (PinosDaemonConfig *config, PinosDaemon *daemon); G_END_DECLS diff --git a/pinos/daemon/main.c b/pinos/daemon/main.c index 098c3a125..2ba9809b6 100644 --- a/pinos/daemon/main.c +++ b/pinos/daemon/main.c @@ -17,24 +17,21 @@ * Boston, MA 02110-1301, USA. */ -#include -#include - #include #include #include #include "daemon-config.h" -gint -main (gint argc, gchar *argv[]) +int +main (int argc, char *argv[]) { PinosCore *core; PinosDaemon *daemon; PinosMainLoop *loop; PinosDaemonConfig *config; PinosProperties *props; - GError *err = NULL; + char *err = NULL; pinos_init (&argc, &argv); @@ -44,8 +41,8 @@ main (gint argc, gchar *argv[]) /* parse configuration */ config = pinos_daemon_config_new (); if (!pinos_daemon_config_load (config, &err)) { - g_error ("failed to parse config: %s", err->message); - g_clear_error (&err); + g_error ("failed to parse config: %s", err); + free (err); } props = pinos_properties_new ("test", "test", NULL); diff --git a/pinos/modules/spa/meson.build b/pinos/modules/spa/meson.build index da3ccd354..8521dd702 100644 --- a/pinos/modules/spa/meson.build +++ b/pinos/modules/spa/meson.build @@ -1,16 +1,12 @@ pinos_module_spa_headers = [ - 'spa-alsa-monitor.h', - 'spa-audiotestsrc.h', - 'spa-v4l2-monitor.h', - 'spa-videotestsrc.h', + 'spa-node.h', + 'spa-monitor.h', ] pinos_module_spa_sources = [ 'module.c', - 'spa-alsa-monitor.c', - 'spa-audiotestsrc.c', - 'spa-v4l2-monitor.c', - 'spa-videotestsrc.c', + 'spa-node.c', + 'spa-monitor.c', ] pinos_module_spa_c_args = [ diff --git a/pinos/modules/spa/module.c b/pinos/modules/spa/module.c index 974eba625..37717be6a 100644 --- a/pinos/modules/spa/module.c +++ b/pinos/modules/spa/module.c @@ -21,20 +21,26 @@ #include #include -#include "spa-alsa-monitor.h" -#include "spa-v4l2-monitor.h" -#include "spa-audiotestsrc.h" -#include "spa-videotestsrc.h" +#include "spa-monitor.h" +#include "spa-node.h" -gboolean pinos__module_init (PinosModule *module, const gchar * args); +bool pinos__module_init (PinosModule *module, const char * args); -G_MODULE_EXPORT gboolean -pinos__module_init (PinosModule * module, G_GNUC_UNUSED const gchar * args) +G_MODULE_EXPORT bool +pinos__module_init (PinosModule * module, const char * args) { - pinos_spa_alsa_monitor_new (module->core); - pinos_spa_v4l2_monitor_new (module->core); - pinos_spa_audiotestsrc_new (module->core, "audiotestsrc", NULL); - pinos_spa_videotestsrc_new (module->core, "videotestsrc", NULL); + pinos_spa_monitor_load (module->core, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor", args); + pinos_spa_monitor_load (module->core, "build/spa/plugins/v4l2/libspa-v4l2.so", "v4l2-monitor", args); + pinos_spa_node_load (module->core, + "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so", + "audiotestsrc", + "audiotestsrc", + NULL, args); + pinos_spa_node_load (module->core, + "build/spa/plugins/videotestsrc/libspa-videotestsrc.so", + "videotestsrc", + "videotestsrc", + NULL, args); return TRUE; } diff --git a/pinos/modules/spa/spa-alsa-monitor.c b/pinos/modules/spa/spa-alsa-monitor.c deleted file mode 100644 index 8169ddab7..000000000 --- a/pinos/modules/spa/spa-alsa-monitor.c +++ /dev/null @@ -1,251 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "spa-alsa-monitor.h" - -typedef struct -{ - PinosSpaALSAMonitor this; - - PinosObject object; - - PinosCore *core; - - SpaHandle *handle; - - GHashTable *nodes; -} PinosSpaALSAMonitorImpl; - -static SpaResult -make_handle (PinosCore *core, SpaHandle **handle, const char *lib, const char *name, const SpaDict *info) -{ - SpaResult res; - void *hnd, *state = NULL; - SpaEnumHandleFactoryFunc enum_func; - - if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { - g_error ("can't load %s: %s", lib, dlerror()); - return SPA_RESULT_ERROR; - } - if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { - g_error ("can't find enum function"); - return SPA_RESULT_ERROR; - } - - while (true) { - const SpaHandleFactory *factory; - - if ((res = enum_func (&factory, &state)) < 0) { - if (res != SPA_RESULT_ENUM_END) - g_error ("can't enumerate factories: %d", res); - break; - } - if (strcmp (factory->name, name)) - continue; - - *handle = g_malloc0 (factory->size); - if ((res = spa_handle_factory_init (factory, *handle, info, core->support, core->n_support)) < 0) { - g_error ("can't make factory instance: %d", res); - return res; - } - return SPA_RESULT_OK; - } - return SPA_RESULT_ERROR; -} - -static void -add_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) -{ - PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaALSAMonitorImpl, this); - SpaResult res; - SpaHandle *handle; - PinosNode *node; - void *node_iface, *clock_iface; - PinosProperties *props = NULL; - - pinos_log_debug ("alsa-monitor %p: add: \"%s\" (%s)", this, item->name, item->id); - - handle = calloc (1, item->factory->size); - if ((res = spa_handle_factory_init (item->factory, - handle, - item->info, - impl->core->support, - impl->core->n_support)) < 0) { - g_error ("can't make factory instance: %d", res); - return; - } - if ((res = spa_handle_get_interface (handle, impl->core->registry.uri.spa_node, &node_iface)) < 0) { - g_error ("can't get NODE interface: %d", res); - return; - } - if ((res = spa_handle_get_interface (handle, impl->core->registry.uri.spa_clock, &clock_iface)) < 0) { - pinos_log_debug ("can't get CLOCK interface: %d", res); - clock_iface = NULL; - } - - if (item->info) { - unsigned int i; - - props = pinos_properties_new (NULL, NULL); - - for (i = 0; i < item->info->n_items; i++) - pinos_properties_set (props, - item->info->items[i].key, - item->info->items[i].value); - } - - node = pinos_node_new (impl->core, - item->factory->name, - node_iface, - clock_iface, - props); - - g_hash_table_insert (impl->nodes, strdup (item->id), node); -} - -static void -remove_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) -{ - PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaALSAMonitorImpl, this); - PinosNode *node; - - pinos_log_debug ("alsa-monitor %p: remove: \"%s\" (%s)", this, item->name, item->id); - - node = g_hash_table_lookup (impl->nodes, item->id); - if (node) { - pinos_node_destroy (node); - g_hash_table_remove (impl->nodes, item->id); - } -} - -static void -on_monitor_event (SpaMonitor *monitor, - SpaMonitorEvent *event, - void *user_data) -{ - PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (monitor, PinosSpaALSAMonitorImpl, this); - PinosSpaALSAMonitor *this = &impl->this; - - switch (event->type) { - case SPA_MONITOR_EVENT_TYPE_ADDED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - add_item (this, item); - break; - } - case SPA_MONITOR_EVENT_TYPE_REMOVED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - remove_item (this, item); - } - case SPA_MONITOR_EVENT_TYPE_CHANGED: - { - SpaMonitorItem *item = (SpaMonitorItem *) event; - pinos_log_debug ("alsa-monitor %p: changed: \"%s\"", this, item->name); - break; - } - default: - break; - } -} - -static void -monitor_destroy (PinosObject * object) -{ - PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (object, PinosSpaALSAMonitorImpl, object); - PinosSpaALSAMonitor *this = &impl->this; - - pinos_log_debug ("spa-monitor %p: destroy", this); - - spa_handle_clear (impl->handle); - free (impl->handle); - - g_hash_table_unref (impl->nodes); - free (impl); -} - -PinosSpaALSAMonitor * -pinos_spa_alsa_monitor_new (PinosCore *core) -{ - PinosSpaALSAMonitorImpl *impl; - PinosSpaALSAMonitor *this; - SpaHandle *handle; - SpaResult res; - void *iface; - void *state = NULL; - - if ((res = make_handle (core, &handle, - "build/spa/plugins/alsa/libspa-alsa.so", - "alsa-monitor", - NULL)) < 0) { - g_error ("can't create alsa-monitor: %d", res); - return NULL; - } - - - if ((res = spa_handle_get_interface (handle, - core->registry.uri.spa_monitor, - &iface)) < 0) { - free (handle); - pinos_log_error ("can't get MONITOR interface: %d", res); - return NULL; - } - impl = calloc (1, sizeof (PinosSpaALSAMonitorImpl)); - impl->core = core; - this = &impl->this; - this->monitor = iface; - - pinos_object_init (&impl->object, - impl->core->registry.uri.monitor, - this, - monitor_destroy); - - impl->nodes = g_hash_table_new_full (g_str_hash, - g_str_equal, - free, - NULL); - - while (true) { - SpaMonitorItem *item; - - if ((res = spa_monitor_enum_items (this->monitor, &item, &state)) < 0) { - if (res != SPA_RESULT_ENUM_END) - pinos_log_debug ("spa_monitor_enum_items: got error %d\n", res); - break; - } - add_item (this, item); - } - spa_monitor_set_event_callback (this->monitor, on_monitor_event, impl); - - return this; -} diff --git a/pinos/modules/spa/spa-audiotestsrc.c b/pinos/modules/spa/spa-audiotestsrc.c deleted file mode 100644 index 66aabe092..000000000 --- a/pinos/modules/spa/spa-audiotestsrc.c +++ /dev/null @@ -1,207 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include - -#include - -#include "spa-audiotestsrc.h" - -#define PINOS_SPA_AUDIOTESTSRC_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrcPrivate)) - -struct _PinosSpaAudioTestSrcPrivate -{ - PinosRingbuffer *ringbuffer; - - SpaHandle *handle; -}; - -enum { - PROP_0, -}; - -G_DEFINE_TYPE (PinosSpaAudioTestSrc, pinos_spa_audiotestsrc, PINOS_TYPE_NODE); - -static SpaResult -make_node (PinosDaemon *daemon, SpaHandle **handle, SpaNode **node, const char *lib, const char *name) -{ - SpaResult res; - void *hnd, *state = NULL; - SpaEnumHandleFactoryFunc enum_func; - - if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { - g_error ("can't load %s: %s", lib, dlerror()); - return SPA_RESULT_ERROR; - } - if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { - g_error ("can't find enum function"); - return SPA_RESULT_ERROR; - } - - while (true) { - const SpaHandleFactory *factory; - void *iface; - - if ((res = enum_func (&factory, &state)) < 0) { - if (res != SPA_RESULT_ENUM_END) - g_error ("can't enumerate factories: %d", res); - break; - } - if (strcmp (factory->name, name)) - continue; - - *handle = calloc (1, factory->size); - if ((res = spa_handle_factory_init (factory, - *handle, - NULL, - daemon->support, - daemon->n_support)) < 0) { - g_error ("can't make factory instance: %d", res); - return res; - } - if ((res = spa_handle_get_interface (*handle, - daemon->registry.uri.spa_node, - &iface)) < 0) { - g_error ("can't get interface %d", res); - return res; - } - *node = iface; - return SPA_RESULT_OK; - } - return SPA_RESULT_ERROR; -} - -static void -setup_node (PinosSpaAudioTestSrc *this) -{ -#if 0 - PinosNode *node = PINOS_NODE (this); - SpaResult res; - SpaProps *props; - SpaPropValue value; - - if ((res = spa_node_get_props (node->node, &props)) < 0) - pinos_log_debug ("got get_props error %d", res); - - if ((res = spa_node_set_props (node->node, props)) < 0) - pinos_log_debug ("got set_props error %d", res); -#endif -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -src_constructed (GObject * object) -{ - PinosSpaAudioTestSrc *src = PINOS_SPA_AUDIOTESTSRC (object); - - setup_node (src); - - G_OBJECT_CLASS (pinos_spa_audiotestsrc_parent_class)->constructed (object); -} - -static void -src_finalize (GObject * object) -{ - PinosSpaAudioTestSrc *src = PINOS_SPA_AUDIOTESTSRC (object); - PinosSpaAudioTestSrcPrivate *priv = src->priv; - - pinos_log_debug ("audiotestsrc %p: dispose", src); - spa_handle_clear (priv->handle); - g_free (priv->handle); - - G_OBJECT_CLASS (pinos_spa_audiotestsrc_parent_class)->finalize (object); -} - -static void -pinos_spa_audiotestsrc_class_init (PinosSpaAudioTestSrcClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosSpaAudioTestSrcPrivate)); - - gobject_class->constructed = src_constructed; - gobject_class->finalize = src_finalize; - gobject_class->get_property = get_property; - gobject_class->set_property = set_property; -} - -static void -pinos_spa_audiotestsrc_init (PinosSpaAudioTestSrc * this) -{ - this->priv = PINOS_SPA_AUDIOTESTSRC_GET_PRIVATE (this); -} - -PinosNode * -pinos_spa_audiotestsrc_new (PinosDaemon *daemon, - const gchar *name, - PinosProperties *properties) -{ - PinosNode *node; - SpaNode *n; - SpaResult res; - SpaHandle *handle; - - if ((res = make_node (daemon, - &handle, - &n, - "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so", - "audiotestsrc")) < 0) { - g_error ("can't create audiotestsrc: %d", res); - return NULL; - } - - node = g_object_new (PINOS_TYPE_SPA_AUDIOTESTSRC, - "daemon", daemon, - "name", name, - "properties", properties, - "node", n, - NULL); - - PINOS_SPA_AUDIOTESTSRC (node)->priv->handle = handle; - - return node; -} diff --git a/pinos/modules/spa/spa-audiotestsrc.h b/pinos/modules/spa/spa-audiotestsrc.h deleted file mode 100644 index d05c1e67f..000000000 --- a/pinos/modules/spa/spa-audiotestsrc.h +++ /dev/null @@ -1,36 +0,0 @@ -/* Pinos - * Copyright (C) 2015 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PINOS_SPA_AUDIOTESTSRC_H__ -#define __PINOS_SPA_AUDIOTESTSRC_H__ - -#include - -#include -#include - -G_BEGIN_DECLS - -PinosNode * pinos_spa_audiotestsrc_new (PinosCore *core, - const gchar *name, - PinosProperties *properties); - -G_END_DECLS - -#endif /* __PINOS_SPA_AUDIOTESTSRC_H__ */ diff --git a/pinos/modules/spa/spa-v4l2-monitor.c b/pinos/modules/spa/spa-monitor.c similarity index 64% rename from pinos/modules/spa/spa-v4l2-monitor.c rename to pinos/modules/spa/spa-monitor.c index 5b4d1fcc4..63e0297d1 100644 --- a/pinos/modules/spa/spa-v4l2-monitor.c +++ b/pinos/modules/spa/spa-monitor.c @@ -31,70 +31,23 @@ #include #include -#include "spa-v4l2-monitor.h" +#include "spa-monitor.h" typedef struct { - PinosSpaV4l2Monitor this; - - PinosObject object; + PinosSpaMonitor this; PinosCore *core; - SpaHandle *handle; + void *hnd; GHashTable *nodes; -} PinosSpaV4l2MonitorImpl; - -static SpaResult -make_handle (PinosCore *core, - SpaHandle **handle, - const char *lib, - const char *name, - const SpaDict *info) -{ - SpaResult res; - void *hnd, *state = NULL; - SpaEnumHandleFactoryFunc enum_func; - - if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { - pinos_log_error ("can't load %s: %s", lib, dlerror()); - return SPA_RESULT_ERROR; - } - if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { - pinos_log_error ("can't find enum function"); - return SPA_RESULT_ERROR; - } - - while (true) { - const SpaHandleFactory *factory; - - if ((res = enum_func (&factory, &state)) < 0) { - if (res != SPA_RESULT_ENUM_END) - pinos_log_error ("can't enumerate factories: %d", res); - break; - } - if (strcmp (factory->name, name)) - continue; - - *handle = calloc (1, factory->size); - if ((res = spa_handle_factory_init (factory, - *handle, - info, - core->support, - core->n_support)) < 0) { - pinos_log_error ("can't make factory instance: %d", res); - return res; - } - return SPA_RESULT_OK; - } - return SPA_RESULT_ERROR; -} +} PinosSpaMonitorImpl; static void -add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) +add_item (PinosSpaMonitor *this, SpaMonitorItem *item) { - PinosSpaV4l2MonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaV4l2MonitorImpl, this); + PinosSpaMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaMonitorImpl, this); SpaResult res; SpaHandle *handle; PinosNode *node; @@ -102,7 +55,7 @@ add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) void *clock_iface; PinosProperties *props = NULL; - pinos_log_debug ("v4l2-monitor %p: add: \"%s\" (%s)", this, item->name, item->id); + pinos_log_debug ("monitor %p: add: \"%s\" (%s)", this, item->name, item->id); handle = calloc (1, item->factory->size); if ((res = spa_handle_factory_init (item->factory, @@ -143,12 +96,12 @@ add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) } static void -remove_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) +remove_item (PinosSpaMonitor *this, SpaMonitorItem *item) { - PinosSpaV4l2MonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaV4l2MonitorImpl, this); + PinosSpaMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaMonitorImpl, this); PinosNode *node; - pinos_log_debug ("v4l2-monitor %p: remove: \"%s\" (%s)", this, item->name, item->id); + pinos_log_debug ("monitor %p: remove: \"%s\" (%s)", this, item->name, item->id); node = g_hash_table_lookup (impl->nodes, item->id); if (node) { @@ -162,7 +115,7 @@ on_monitor_event (SpaMonitor *monitor, SpaMonitorEvent *event, void *user_data) { - PinosSpaV4l2Monitor *this = user_data; + PinosSpaMonitor *this = user_data; switch (event->type) { case SPA_MONITOR_EVENT_TYPE_ADDED: @@ -179,7 +132,7 @@ on_monitor_event (SpaMonitor *monitor, case SPA_MONITOR_EVENT_TYPE_CHANGED: { SpaMonitorItem *item = (SpaMonitorItem *) event; - pinos_log_debug ("v4l2-monitor %p: changed: \"%s\"", this, item->name); + pinos_log_debug ("monitor %p: changed: \"%s\"", this, item->name); break; } default: @@ -187,64 +140,74 @@ on_monitor_event (SpaMonitor *monitor, } } -static void -monitor_destroy (PinosObject * object) +PinosSpaMonitor * +pinos_spa_monitor_load (PinosCore *core, + const char *lib, + const char *factory_name, + const char *args) { - PinosSpaV4l2MonitorImpl *impl = SPA_CONTAINER_OF (object, PinosSpaV4l2MonitorImpl, object); - PinosSpaV4l2Monitor *this = &impl->this; - - pinos_log_debug ("spa-monitor %p: dispose", this); - spa_handle_clear (impl->handle); - free (impl->handle); - g_hash_table_unref (impl->nodes); - free (impl); -} - - -PinosSpaV4l2Monitor * -pinos_spa_v4l2_monitor_new (PinosCore *core) -{ - PinosSpaV4l2MonitorImpl *impl; - PinosSpaV4l2Monitor *this; + PinosSpaMonitorImpl *impl; + PinosSpaMonitor *this; SpaHandle *handle; SpaResult res; void *iface; - void *state = NULL; + void *hnd, *state = NULL; + SpaEnumHandleFactoryFunc enum_func; + const SpaHandleFactory *factory; - if ((res = make_handle (core, - &handle, - "build/spa/plugins/v4l2/libspa-v4l2.so", - "v4l2-monitor", - NULL)) < 0) { - pinos_log_error ("can't create v4l2-monitor: %d", res); + if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { + pinos_log_error ("can't load %s: %s", lib, dlerror()); return NULL; } + if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { + pinos_log_error ("can't find enum function"); + goto no_symbol; + } + while (true) { + if ((res = enum_func (&factory, &state)) < 0) { + if (res != SPA_RESULT_ENUM_END) + pinos_log_error ("can't enumerate factories: %d", res); + goto enum_failed; + } + if (strcmp (factory->name, factory_name) == 0) + break; + } + handle = calloc (1, factory->size); + if ((res = spa_handle_factory_init (factory, + handle, + NULL, + core->support, + core->n_support)) < 0) { + pinos_log_error ("can't make factory instance: %d", res); + goto init_failed; + } if ((res = spa_handle_get_interface (handle, core->registry.uri.spa_monitor, &iface)) < 0) { free (handle); pinos_log_error ("can't get MONITOR interface: %d", res); - return NULL; + goto interface_failed; } - impl = calloc (1, sizeof (PinosSpaV4l2MonitorImpl)); + impl = calloc (1, sizeof (PinosSpaMonitorImpl)); impl->core = core; - - pinos_object_init (&impl->object, - core->registry.uri.monitor, - impl, - monitor_destroy); + impl->hnd = hnd; this = &impl->this; + pinos_signal_init (&this->destroy_signal); this->monitor = iface; + this->lib = strdup (lib); + this->factory_name = strdup (factory_name); + this->handle = handle; impl->nodes = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, - g_object_unref); + free, + NULL); - while (TRUE) { + state = NULL; + while (true) { SpaMonitorItem *item; SpaResult res; @@ -257,7 +220,32 @@ pinos_spa_v4l2_monitor_new (PinosCore *core) } spa_monitor_set_event_callback (this->monitor, on_monitor_event, this); - pinos_registry_add_object (&core->registry, &impl->object); - return this; + +interface_failed: + spa_handle_clear (handle); +init_failed: + free (handle); +enum_failed: +no_symbol: + dlclose (hnd); + return NULL; + +} + +void +pinos_spa_monitor_destroy (PinosSpaMonitor * monitor) +{ + PinosSpaMonitorImpl *impl = SPA_CONTAINER_OF (monitor, PinosSpaMonitorImpl, this); + + pinos_log_debug ("spa-monitor %p: dispose", impl); + pinos_signal_emit (&monitor->destroy_signal, monitor); + + spa_handle_clear (monitor->handle); + free (monitor->handle); + free (monitor->lib); + free (monitor->factory_name); + g_hash_table_unref (impl->nodes); + dlclose (impl->hnd); + free (impl); } diff --git a/pinos/modules/spa/spa-v4l2-monitor.h b/pinos/modules/spa/spa-monitor.h similarity index 56% rename from pinos/modules/spa/spa-v4l2-monitor.h rename to pinos/modules/spa/spa-monitor.h index 2837430aa..480d4c84b 100644 --- a/pinos/modules/spa/spa-v4l2-monitor.h +++ b/pinos/modules/spa/spa-monitor.h @@ -17,26 +17,36 @@ * Boston, MA 02110-1301, USA. */ -#ifndef __PINOS_SPA_V4L2_MONITOR_H__ -#define __PINOS_SPA_V4L2_MONITOR_H__ +#ifndef __PINOS_SPA_MONITOR_H__ +#define __PINOS_SPA_MONITOR_H__ #include +#include #ifdef __cplusplus extern "C" { #endif -typedef struct _PinosSpaV4l2Monitor PinosSpaV4l2Monitor; +typedef struct _PinosSpaMonitor PinosSpaMonitor; -struct _PinosSpaV4l2Monitor { +struct _PinosSpaMonitor { SpaMonitor *monitor; + + char *lib; + char *factory_name; + SpaHandle *handle; + + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosSpaMonitor *monitor)); }; -PinosSpaV4l2Monitor * pinos_spa_v4l2_monitor_new (PinosCore *core); -void pinos_spa_v4l2_monitor_destroy (PinosSpaV4l2Monitor *monitor); +PinosSpaMonitor * pinos_spa_monitor_load (PinosCore *core, + const char *lib, + const char *factory_name, + const char *args); +void pinos_spa_monitor_destroy (PinosSpaMonitor *monitor); #ifdef __cplusplus } #endif -#endif /* __PINOS_SPA_V4L2_MONITOR_H__ */ +#endif /* __PINOS_SPA_MONITOR_H__ */ diff --git a/pinos/modules/spa/spa-node.c b/pinos/modules/spa/spa-node.c new file mode 100644 index 000000000..d9240ba8a --- /dev/null +++ b/pinos/modules/spa/spa-node.c @@ -0,0 +1,138 @@ +/* Pinos + * Copyright (C) 2015 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include +#include +#include + +#include + +#include "spa-node.h" + +typedef struct { + PinosSpaNode this; + PinosCore *core; + + void *hnd; +} PinosSpaNodeImpl; + +PinosSpaNode * +pinos_spa_node_load (PinosCore *core, + const char *lib, + const char *factory_name, + const char *name, + PinosProperties *properties, + const char *args) +{ + PinosSpaNode *this; + PinosSpaNodeImpl *impl; + SpaNode *spa_node; + SpaClock *spa_clock; + SpaResult res; + SpaHandle *handle; + void *hnd, *state = NULL; + SpaEnumHandleFactoryFunc enum_func; + const SpaHandleFactory *factory; + void *iface; + + if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { + pinos_log_error ("can't load %s: %s", lib, dlerror()); + return NULL; + } + if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { + pinos_log_error ("can't find enum function"); + goto no_symbol; + } + + while (true) { + if ((res = enum_func (&factory, &state)) < 0) { + if (res != SPA_RESULT_ENUM_END) + pinos_log_error ("can't enumerate factories: %d", res); + goto enum_failed; + } + if (strcmp (factory->name, factory_name) == 0) + break; + } + + handle = calloc (1, factory->size); + if ((res = spa_handle_factory_init (factory, + handle, + NULL, + core->support, + core->n_support)) < 0) { + pinos_log_error ("can't make factory instance: %d", res); + goto init_failed; + } + if ((res = spa_handle_get_interface (handle, + core->registry.uri.spa_node, + &iface)) < 0) { + pinos_log_error ("can't get interface %d", res); + goto interface_failed; + } + spa_node = iface; + + if ((res = spa_handle_get_interface (handle, + core->registry.uri.spa_clock, + &iface)) < 0) { + iface = NULL; + } + spa_clock = iface; + + impl = calloc (1, sizeof (PinosSpaNodeImpl)); + impl->core = core; + impl->hnd = hnd; + this = &impl->this; + this->node = pinos_node_new (core, + name, + spa_node, + spa_clock, + properties); + this->lib = strdup (lib); + this->factory_name = strdup (factory_name); + this->handle = handle; + + return this; + +interface_failed: + spa_handle_clear (handle); +init_failed: + free (handle); +enum_failed: +no_symbol: + dlclose (hnd); + return NULL; +} + +void +pinos_spa_node_destroy (PinosSpaNode * node) +{ + PinosSpaNodeImpl *impl = SPA_CONTAINER_OF (node, PinosSpaNodeImpl, this); + + pinos_log_debug ("spa-node %p: destroy", impl); + pinos_signal_emit (&node->destroy_signal, node); + + pinos_node_destroy (node->node); + + spa_handle_clear (node->handle); + free (node->handle); + free (node->lib); + free (node->factory_name); + dlclose (impl->hnd); + free (impl); +} diff --git a/pinos/modules/spa/spa-node.h b/pinos/modules/spa/spa-node.h new file mode 100644 index 000000000..0cc6e7875 --- /dev/null +++ b/pinos/modules/spa/spa-node.h @@ -0,0 +1,52 @@ +/* Pinos + * Copyright (C) 2015 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PINOS_SPA_NODE_H__ +#define __PINOS_SPA_NODE_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +typedef struct _PinosSpaNode PinosSpaNode; + +struct _PinosSpaNode { + PinosNode *node; + + char *lib; + char *factory_name; + SpaHandle *handle; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosSpaNode *node)); +}; + +PinosSpaNode * pinos_spa_node_load (PinosCore *core, + const char *lib, + const char *factory_name, + const char *name, + PinosProperties *properties, + const char *args); + +#ifdef __cplusplus +} +#endif + +#endif /* __PINOS_SPA_NODE_H__ */ diff --git a/pinos/modules/spa/spa-videotestsrc.c b/pinos/modules/spa/spa-videotestsrc.c deleted file mode 100644 index d44537bb7..000000000 --- a/pinos/modules/spa/spa-videotestsrc.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Pinos - * Copyright (C) 2016 Axis Communications AB - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include - -#include -#include - -#include "spa-videotestsrc.h" - -#define PINOS_SPA_VIDEOTESTSRC_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_VIDEOTESTSRC, PinosSpaVideoTestSrcPrivate)) - -struct _PinosSpaVideoTestSrcPrivate -{ - SpaHandle *handle; -}; - -enum { - PROP_0, -}; - -G_DEFINE_TYPE (PinosSpaVideoTestSrc, pinos_spa_videotestsrc, PINOS_TYPE_NODE); - -static SpaResult -make_node (PinosDaemon *daemon, SpaHandle **handle, SpaNode **node, const char *lib, const char *name) -{ - SpaResult res; - void *hnd, *state = NULL; - SpaEnumHandleFactoryFunc enum_func; - - if ((hnd = dlopen (lib, RTLD_NOW)) == NULL) { - g_error ("can't load %s: %s", lib, dlerror()); - return SPA_RESULT_ERROR; - } - if ((enum_func = dlsym (hnd, "spa_enum_handle_factory")) == NULL) { - g_error ("can't find enum function"); - return SPA_RESULT_ERROR; - } - - while (true) { - const SpaHandleFactory *factory; - void *iface; - - if ((res = enum_func (&factory, &state)) < 0) { - if (res != SPA_RESULT_ENUM_END) - g_error ("can't enumerate factories: %d", res); - break; - } - if (strcmp (factory->name, name)) - continue; - - *handle = calloc (1, factory->size); - if ((res = spa_handle_factory_init (factory, *handle, NULL, daemon->support, daemon->n_support)) < 0) { - g_error ("can't make factory instance: %d", res); - return res; - } - if ((res = spa_handle_get_interface (*handle, - daemon->registry.uri.spa_node, - &iface)) < 0) { - g_error ("can't get interface %d", res); - return res; - } - *node = iface; - return SPA_RESULT_OK; - } - return SPA_RESULT_ERROR; -} - -static void -get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -source_finalize (GObject * object) -{ - PinosSpaVideoTestSrc *source = PINOS_SPA_VIDEOTESTSRC (object); - PinosSpaVideoTestSrcPrivate *priv = source->priv; - - g_debug ("spa-source %p: dispose", source); - spa_handle_clear (priv->handle); - g_free (priv->handle); - - G_OBJECT_CLASS (pinos_spa_videotestsrc_parent_class)->finalize (object); -} - -static void -pinos_spa_videotestsrc_class_init (PinosSpaVideoTestSrcClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosSpaVideoTestSrcPrivate)); - - gobject_class->finalize = source_finalize; - gobject_class->get_property = get_property; - gobject_class->set_property = set_property; -} - -static void -pinos_spa_videotestsrc_init (PinosSpaVideoTestSrc * source) -{ - source->priv = PINOS_SPA_VIDEOTESTSRC_GET_PRIVATE (source); -} - -PinosNode * -pinos_spa_videotestsrc_new (PinosDaemon *daemon, - const gchar *name, - PinosProperties *properties) -{ - PinosNode *node; - SpaNode *n; - SpaResult res; - SpaHandle *handle; - - if ((res = make_node (daemon, - &handle, - &n, - "build/spa/plugins/videotestsrc/libspa-videotestsrc.so", - "videotestsrc")) < 0) { - g_error ("can't create videotestsrc: %d", res); - return NULL; - } - - node = g_object_new (PINOS_TYPE_SPA_VIDEOTESTSRC, - "daemon", daemon, - "name", name, - "properties", properties, - "node", n, - NULL); - - PINOS_SPA_VIDEOTESTSRC (node)->priv->handle = handle; - - return node; -} diff --git a/pinos/modules/spa/spa-videotestsrc.h b/pinos/modules/spa/spa-videotestsrc.h deleted file mode 100644 index 6f1871215..000000000 --- a/pinos/modules/spa/spa-videotestsrc.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Pinos - * Copyright (C) 2016 Axis Communications AB - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __PINOS_SPA_VIDEOTESTSRC_H__ -#define __PINOS_SPA_VIDEOTESTSRC_H__ - -#include - -#include -#include - -typedef struct _PinosSpaVideoTestSrc PinosSpaVideoTestSrc; - -G_BEGIN_DECLS - -struct _PinosSpaVideoTestSrc { - PinosNode *node; -}; - -PinosSpaVideoTestSrc * pinos_spa_videotestsrc_new (PinosCore *core, - const gchar *name, - PinosProperties *properties); -void pinos_spa_videotestsrc_destroy (PinosSpaVideoTestSrc *src); - -G_END_DECLS - -#endif /* __PINOS_SPA_VIDEOTESTSRC_H__ */ diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index b348bbd5f..25078c753 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -102,12 +102,12 @@ struct _SpaProxy SpaNodeEventCallback event_cb; void *user_data; - SpaPollFd fds[1]; - SpaPollItem poll; + SpaPollFd ctrl_fds[1]; + SpaPollItem ctrl_poll; PinosConnection *conn; - SpaPollFd rtfds[1]; - SpaPollItem rtpoll; + SpaPollFd data_fds[1]; + SpaPollItem data_poll; unsigned int max_inputs; unsigned int n_inputs; @@ -123,17 +123,15 @@ typedef struct { PinosClientNode this; - PinosObject object; - PinosInterface ifaces[1]; - PinosCore *core; SpaProxy proxy; PinosListener transport_changed; + PinosListener loop_changed; - int fd; - int rtfd; + int ctrl_fd; + int data_fd; } PinosClientNodeImpl; static void @@ -862,7 +860,7 @@ spa_proxy_node_port_reuse_buffer (SpaNode *node, rb.buffer_id = buffer_id; pinos_transport_add_event (pnode->transport, &rb.event); cmd = PINOS_TRANSPORT_CMD_HAVE_EVENT; - write (this->rtfds[0].fd, &cmd, 1); + write (this->data_fds[0].fd, &cmd, 1); return SPA_RESULT_OK; } @@ -931,7 +929,7 @@ spa_proxy_node_process_input (SpaNode *node) return SPA_RESULT_ERROR; cmd = PINOS_TRANSPORT_CMD_HAVE_DATA; - write (this->rtfds[0].fd, &cmd, 1); + write (this->data_fds[0].fd, &cmd, 1); return SPA_RESULT_OK; } @@ -1105,7 +1103,7 @@ proxy_on_fd_events (SpaPollNotifyData *data) } static int -proxy_on_rtfd_events (SpaPollNotifyData *data) +proxy_on_data_fd_events (SpaPollNotifyData *data) { SpaProxy *this = data->user_data; PinosNode *pnode = this->pnode; @@ -1113,7 +1111,7 @@ proxy_on_rtfd_events (SpaPollNotifyData *data) if (data->fds[0].revents & POLLIN) { uint8_t cmd; - read (this->rtfds[0].fd, &cmd, 1); + read (this->data_fds[0].fd, &cmd, 1); if (cmd & PINOS_TRANSPORT_CMD_HAVE_EVENT) { SpaNodeEvent event; @@ -1194,41 +1192,39 @@ proxy_init (SpaProxy *this, this->node = proxy_node; - this->fds[0].fd = -1; - this->fds[0].events = POLLIN | POLLPRI | POLLERR; - this->fds[0].revents = 0; - this->poll.id = 0; - this->poll.enabled = true; - this->poll.fds = this->fds; - this->poll.n_fds = 1; - this->poll.idle_cb = NULL; - this->poll.before_cb = NULL; - this->poll.after_cb = proxy_on_fd_events; - this->poll.user_data = this; + this->ctrl_fds[0].fd = -1; + this->ctrl_fds[0].events = POLLIN | POLLPRI | POLLERR; + this->ctrl_fds[0].revents = 0; + this->ctrl_poll.id = 0; + this->ctrl_poll.enabled = true; + this->ctrl_poll.fds = this->ctrl_fds; + this->ctrl_poll.n_fds = 1; + this->ctrl_poll.idle_cb = NULL; + this->ctrl_poll.before_cb = NULL; + this->ctrl_poll.after_cb = proxy_on_fd_events; + this->ctrl_poll.user_data = this; - this->rtfds[0].fd = -1; - this->rtfds[0].events = POLLIN | POLLPRI | POLLERR; - this->rtfds[0].revents = 0; - this->rtpoll.id = 0; - this->rtpoll.enabled = true; - this->rtpoll.fds = this->rtfds; - this->rtpoll.n_fds = 1; - this->rtpoll.idle_cb = NULL; - this->rtpoll.before_cb = NULL; - this->rtpoll.after_cb = proxy_on_rtfd_events; - this->rtpoll.user_data = this; + this->data_fds[0].fd = -1; + this->data_fds[0].events = POLLIN | POLLPRI | POLLERR; + this->data_fds[0].revents = 0; + this->data_poll.id = 0; + this->data_poll.enabled = true; + this->data_poll.fds = this->data_fds; + this->data_poll.n_fds = 1; + this->data_poll.idle_cb = NULL; + this->data_poll.before_cb = NULL; + this->data_poll.after_cb = proxy_on_data_fd_events; + this->data_poll.user_data = this; return SPA_RESULT_RETURN_ASYNC (this->seq++); } static void on_transport_changed (PinosListener *listener, - void *object, - void *data) + PinosNode *node) { PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, transport_changed); PinosClientNode *this = &impl->this; - PinosNode *node = object; PinosTransportInfo info; PinosMessageTransportUpdate tu; PinosConnection *conn = impl->proxy.conn; @@ -1244,6 +1240,14 @@ on_transport_changed (PinosListener *listener, pinos_log_error ("client-node %p: error writing connection", this); } +static void +on_loop_changed (PinosListener *listener, + PinosNode *node) +{ + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, loop_changed); + impl->proxy.data_loop = &node->data_loop->poll; +} + static SpaResult proxy_clear (SpaProxy *this) { @@ -1257,35 +1261,18 @@ proxy_clear (SpaProxy *this) if (this->out_ports[i].valid) clear_port (this, &this->out_ports[i], SPA_DIRECTION_OUTPUT, i); } - if (this->fds[0].fd != -1) { - spa_poll_remove_item (this->main_loop, &this->poll); - close (this->fds[0].fd); + if (this->ctrl_fds[0].fd != -1) { + spa_poll_remove_item (this->main_loop, &this->ctrl_poll); + close (this->ctrl_fds[0].fd); } - if (this->rtfds[0].fd != -1) { - spa_poll_remove_item (this->data_loop, &this->rtpoll); - close (this->rtfds[0].fd); + if (this->data_fds[0].fd != -1) { + spa_poll_remove_item (this->data_loop, &this->data_poll); + close (this->data_fds[0].fd); } return SPA_RESULT_OK; } -static void -client_node_destroy (PinosObject * object) -{ - PinosClientNodeImpl *impl = (PinosClientNodeImpl *) object; - PinosClientNode *this = &impl->this; - - pinos_log_debug ("client-node %p: destroy", this); - - proxy_clear (&impl->proxy); - - if (impl->fd != -1) - close (impl->fd); - if (impl->rtfd != -1) - close (impl->rtfd); - free (impl); -} - /** * pinos_client_node_new: * @daemon: a #PinosDaemon @@ -1310,16 +1297,12 @@ pinos_client_node_new (PinosCore *core, impl = calloc (1, sizeof (PinosClientNodeImpl)); impl->core = core; + impl->ctrl_fd = -1; + impl->data_fd = -1; this = &impl->this; pinos_log_debug ("client-node %p: new", impl); - impl->ifaces[0].type = impl->core->registry.uri.node; - impl->ifaces[0].iface = this; - - pinos_object_init (&this->object, - client_node_destroy, - 1, - impl->ifaces); + pinos_signal_init (&this->destroy_signal); proxy_init (&impl->proxy, NULL, core->support, core->n_support); @@ -1331,91 +1314,93 @@ pinos_client_node_new (PinosCore *core, impl->proxy.pnode = this->node; - impl->transport_changed.notify = on_transport_changed; - pinos_signal_add (&this->node->transport_changed, &impl->transport_changed); + pinos_signal_add (&this->node->transport_changed, + &impl->transport_changed, + on_transport_changed); + + pinos_signal_add (&this->node->loop_changed, + &impl->loop_changed, + on_loop_changed); return this; } +void +pinos_client_node_destroy (PinosClientNode * this) +{ + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); + + pinos_log_debug ("client-node %p: destroy", impl); + pinos_signal_emit (&this->destroy_signal, this); + + pinos_node_destroy (this->node); + + proxy_clear (&impl->proxy); + + if (impl->ctrl_fd != -1) + close (impl->ctrl_fd); + if (impl->data_fd != -1) + close (impl->data_fd); + free (impl); +} + /** - * pinos_client_node_get_socket_pair: + * pinos_client_node_get_ctrl_socket: * @node: a #PinosClientNode - * @error: a #GError + * @fd: a result socket * * Create or return a previously create socket pair for @node. The - * Socket for the other end is returned. + * socket for the other end is returned. * - * Returns: a socket that can be used to send/receive buffers to node. + * Returns: %SPA_RESULT_OK on success */ -int -pinos_client_node_get_socket_pair (PinosClientNode *this, - GError **error) +SpaResult +pinos_client_node_get_ctrl_socket (PinosClientNode *this, + int *fd) { - PinosClientNodeImpl *impl = (PinosClientNodeImpl *) this; + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); - g_return_val_if_fail (this, -1); - - if (impl->fd == -1) { + if (impl->ctrl_fd == -1) { int fd[2]; if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, fd) != 0) - goto no_sockets; + return SPA_RESULT_ERRNO; - impl->proxy.fds[0].fd = fd[0]; - impl->proxy.conn = pinos_connection_new (impl->proxy.fds[0].fd); - spa_poll_add_item (impl->proxy.main_loop, &impl->proxy.poll); - impl->fd = fd[1]; - } - return impl->fd; - - /* ERRORS */ -no_sockets: - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "could not create socketpair: %s", strerror (errno)); - return -1; + impl->proxy.ctrl_fds[0].fd = fd[0]; + impl->proxy.conn = pinos_connection_new (impl->proxy.ctrl_fds[0].fd); + spa_poll_add_item (impl->proxy.main_loop, &impl->proxy.ctrl_poll); + impl->ctrl_fd = fd[1]; } + *fd = impl->ctrl_fd; + return SPA_RESULT_OK; } /** - * pinos_client_node_get_rtsocket_pair: + * pinos_client_node_get_data_socket: * @node: a #PinosClientNode * @error: a #GError * * Create or return a previously create socket pair for @node. The * Socket for the other end is returned. * - * Returns: a #GSocket that can be used to send/receive buffers to node. + * Returns: %SPA_RESULT_OK on success */ -int -pinos_client_node_get_rtsocket_pair (PinosClientNode *this, - GError **error) +SpaResult +pinos_client_node_get_data_socket (PinosClientNode *this, + int *fd) { - PinosClientNodeImpl *impl = (PinosClientNodeImpl *) this; + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (this, PinosClientNodeImpl, this); - g_return_val_if_fail (this, -1); - - if (impl->fd == -1) { + if (impl->data_fd == -1) { int fd[2]; if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) != 0) - goto no_sockets; + return SPA_RESULT_ERRNO; - impl->proxy.rtfds[0].fd = fd[0]; - spa_poll_add_item (impl->proxy.data_loop, &impl->proxy.rtpoll); - impl->rtfd = fd[1]; - } - return impl->rtfd; - - /* ERRORS */ -no_sockets: - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "could not create socketpair: %s", strerror (errno)); - return -1; + impl->proxy.data_fds[0].fd = fd[0]; + spa_poll_add_item (impl->proxy.data_loop, &impl->proxy.data_poll); + impl->data_fd = fd[1]; } + *fd = impl->data_fd; + return SPA_RESULT_OK; } diff --git a/pinos/server/client-node.h b/pinos/server/client-node.h index 97da68405..10e677c41 100644 --- a/pinos/server/client-node.h +++ b/pinos/server/client-node.h @@ -20,14 +20,11 @@ #ifndef __PINOS_CLIENT_NODE_H__ #define __PINOS_CLIENT_NODE_H__ -#include - #include -G_BEGIN_DECLS - -#define PINOS_CLIENT_NODE_URI "http://pinos.org/ns/client-node" -#define PINOS_CLIENT_NODE_PREFIX PINOS_CLIENT_NODE_URI "#" +#ifdef __cplusplus +extern "C" { +#endif typedef struct _PinosClientNode PinosClientNode; @@ -39,20 +36,21 @@ typedef struct _PinosClientNode PinosClientNode; struct _PinosClientNode { PinosNode *node; - int (*get_ctrl_socket) (PinosClientNode *node, - GError **error); - int (*get_data_socket) (PinosClientNode *node, - GError **error); + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosClientNode *node)); }; -PinosObject * pinos_client_node_new (PinosCore *core, - PinosClient *client, - const gchar *name, - PinosProperties *properties); +PinosClientNode * pinos_client_node_new (PinosCore *core, + PinosClient *client, + const gchar *name, + PinosProperties *properties); +void pinos_client_node_destroy (PinosClientNode *node); -#define pinos_client_node_get_ctrl_socket(n) (n)->get_ctrl_socket(n,__VA_ARGS__) -#define pinos_client_node_get_data_socket(n) (n)->get_data_socket(n,__VA_ARGS__) +SpaResult pinos_client_node_get_ctrl_socket (PinosClientNode *node, int *fd); +SpaResult pinos_client_node_get_data_socket (PinosClientNode *node, int *fd); -G_END_DECLS +#ifdef __cplusplus +} +#endif #endif /* __PINOS_CLIENT_NODE_H__ */ diff --git a/pinos/server/client.c b/pinos/server/client.c index aebfef407..e07c5bbfe 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -26,10 +26,7 @@ typedef struct { - PinosClient client; - PinosObject object; - PinosInterface ifaces[1]; - PinosDaemon *daemon; + PinosClient this; guint id; PinosClient1 *iface; @@ -45,10 +42,18 @@ client_name_appeared_handler (GDBusConnection *connection, gpointer user_data) { PinosClientImpl *impl = user_data; - PinosClient *client = &impl->client; + PinosClient *this = &impl->this; + PinosObjectSkeleton *skel; - pinos_log_debug ("client %p: appeared %s %s", client, name, name_owner); - pinos_signal_emit (&client->appeared, client, NULL); + pinos_log_debug ("client %p: appeared %s %s", this, name, name_owner); + + skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_CLIENT); + pinos_object_skeleton_set_client1 (skel, impl->iface); + + this->global = pinos_core_add_global (this->core, + this->core->registry.uri.client, + this, + skel); } static void @@ -57,24 +62,24 @@ client_name_vanished_handler (GDBusConnection *connection, gpointer user_data) { PinosClientImpl *impl = user_data; - PinosClient *client = &impl->client; + PinosClient *this = &impl->this; - pinos_log_debug ("client %p: vanished %s", client, name); + pinos_log_debug ("client %p: vanished %s", this, name); + + pinos_core_remove_global (this->core, + this->global); + this->global = NULL; - pinos_signal_emit (&client->vanished, client, NULL); g_bus_unwatch_name (impl->id); } static void -client_watch_name (PinosClient *client) +client_watch_name (PinosClient *this) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - GDBusConnection *connection = NULL; + PinosClientImpl *impl = SPA_CONTAINER_OF (this, PinosClientImpl, this); -// g_object_get (impl->daemon, "connection", &connection, NULL); - - impl->id = g_bus_watch_name_on_connection (connection, - client->sender, + impl->id = g_bus_watch_name_on_connection (this->core->connection, + this->sender, G_BUS_NAME_WATCHER_FLAGS_NONE, client_name_appeared_handler, client_name_vanished_handler, @@ -82,65 +87,11 @@ client_watch_name (PinosClient *client) (GDestroyNotify) pinos_client_destroy); } -static void -client_register_object (PinosClient *client) +void +pinos_client_add_object (PinosClient *client, + PinosObject *object) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - PinosDaemon *daemon = impl->daemon; - PinosObjectSkeleton *skel; - - skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_CLIENT); - - pinos_object_skeleton_set_client1 (skel, impl->iface); - - g_free (impl->object_path); - impl->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); - g_object_unref (skel); - - pinos_log_debug ("client %p: register %s", client, impl->object_path); -} - -static void -client_unregister_object (PinosClient *client) -{ - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - PinosDaemon *daemon = impl->daemon; - - pinos_log_debug ("client %p: unregister", client); - pinos_daemon_unexport (daemon, impl->object_path); -} - -static void -client_destroy (PinosObject * object) -{ - PinosClientImpl *impl = SPA_CONTAINER_OF (object, PinosClientImpl, object); - PinosClient *client = &impl->client; - GList *copy; - - pinos_log_debug ("client %p: destroy", client); - pinos_registry_remove_object (&client->core->registry, &impl->object); - - copy = g_list_copy (impl->objects); - g_list_free_full (copy, NULL); - g_list_free (impl->objects); - - client_unregister_object (client); - - free (client->sender); - if (client->properties) - pinos_properties_free (client->properties); - - g_clear_object (&impl->iface); - free (impl->object_path); - free (object); -} - - -static void -client_add_object (PinosClient *client, - PinosObject *object) -{ - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); g_return_if_fail (client); g_return_if_fail (object); @@ -148,11 +99,11 @@ client_add_object (PinosClient *client, impl->objects = g_list_prepend (impl->objects, object); } -static void -client_remove_object (PinosClient *client, - PinosObject *object) +void +pinos_client_remove_object (PinosClient *client, + PinosObject *object) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); g_return_if_fail (client); g_return_if_fail (object); @@ -161,11 +112,11 @@ client_remove_object (PinosClient *client, pinos_object_destroy (object); } -static bool -client_has_object (PinosClient *client, - PinosObject *object) +bool +pinos_client_has_object (PinosClient *client, + PinosObject *object) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); GList *found; g_return_val_if_fail (client, false); @@ -192,36 +143,26 @@ pinos_client_new (PinosCore *core, const gchar *sender, PinosProperties *properties) { - PinosClient *client; + PinosClient *this; PinosClientImpl *impl; - impl = calloc (1, sizeof (PinosClientImpl *)); - client = &impl->client; - client->core = core; - client->sender = strdup (sender); - client->properties = properties; - client->add_object = client_add_object; - client->remove_object = client_remove_object; - client->has_object = client_has_object; - - impl->ifaces[0].type = client->core->registry.uri.client; - impl->ifaces[0].iface = client; - - pinos_object_init (&impl->object, - client_destroy, - 1, - impl->ifaces); - + impl = calloc (1, sizeof (PinosClientImpl)); pinos_log_debug ("client %p: new", impl); + this = &impl->this; + this->core = core; + this->sender = strdup (sender); + this->properties = properties; + + pinos_signal_init (&this->destroy_signal); + impl->iface = pinos_client1_skeleton_new (); - client_watch_name (client); - client_register_object (client); + client_watch_name (this); - pinos_registry_add_object (&client->core->registry, &impl->object); + spa_list_insert (core->client_list.prev, &this->list); - return client; + return this; } /** @@ -231,14 +172,27 @@ pinos_client_new (PinosCore *core, * Trigger removal of @client */ void -pinos_client_destroy (PinosClient *client) +pinos_client_destroy (PinosClient * client) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - - g_return_if_fail (client); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); + GList *copy; pinos_log_debug ("client %p: destroy", client); - pinos_object_destroy (&impl->object); + pinos_signal_emit (&client->destroy_signal, client); + + spa_list_remove (&client->list); + + copy = g_list_copy (impl->objects); + g_list_free_full (copy, NULL); + g_list_free (impl->objects); + + free (client->sender); + if (client->properties) + pinos_properties_free (client->properties); + + g_clear_object (&impl->iface); + free (impl->object_path); + free (impl); } /** @@ -252,7 +206,7 @@ pinos_client_destroy (PinosClient *client) const gchar * pinos_client_get_object_path (PinosClient *client) { - PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, this); g_return_val_if_fail (client, NULL); diff --git a/pinos/server/client.h b/pinos/server/client.h index 3b633dd2b..1314c25e6 100644 --- a/pinos/server/client.h +++ b/pinos/server/client.h @@ -20,9 +20,9 @@ #ifndef __PINOS_CLIENT_H__ #define __PINOS_CLIENT_H__ -#include - -G_BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif #define PINOS_CLIENT_URI "http://pinos.org/ns/client" #define PINOS_CLIENT_PREFIX PINOS_CLIENT_URI "#" @@ -38,33 +38,34 @@ typedef struct _PinosClient PinosClient; * Pinos client object class. */ struct _PinosClient { - PinosCore *core; + PinosCore *core; + SpaList list; + PinosGlobal *global; char *sender; - PinosProperties *properties; - PinosSignal appeared; - PinosSignal vanished; - - void (*add_object) (PinosClient *client, - PinosObject *object); - void (*remove_object) (PinosClient *client, - PinosObject *object); - bool (*has_object) (PinosClient *client, - PinosObject *object); + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosClient *client)); }; -PinosObject * pinos_client_new (PinosCore *core, +PinosClient * pinos_client_new (PinosCore *core, const gchar *sender, PinosProperties *properties); +void pinos_client_destroy (PinosClient *client); const gchar * pinos_client_get_object_path (PinosClient *client); -#define pinos_client_add_object(c,...) (c)->add_object ((c),__VA_ARGS__) -#define pinos_client_remove_object(c,...) (c)->remove_object ((c),__VA_ARGS__) -#define pinos_client_has_object(c,...) (c)->has_object ((c),__VA_ARGS__) -G_END_DECLS +void pinos_client_add_object (PinosClient *client, + PinosObject *object); +void pinos_client_remove_object (PinosClient *client, + PinosObject *object); +bool pinos_client_has_object (PinosClient *client, + PinosObject *object); + +#ifdef __cplusplus +} +#endif #endif /* __PINOS_CLIENT_H__ */ diff --git a/pinos/server/command.c b/pinos/server/command.c index 24ea83e0c..33946ab4e 100644 --- a/pinos/server/command.c +++ b/pinos/server/command.c @@ -18,46 +18,36 @@ * Boston, MA 02110-1301, USA. */ -#include #include #include +#include #include #include "command.h" -GQuark -pinos_command_error_quark (void) -{ - static GQuark quark = 0; - - if (quark == 0) { - quark = g_quark_from_static_string ("pinos_command_error"); - } - - return quark; -} - -typedef gboolean (*PinosCommandFunc) (PinosCommand *command, +typedef bool (*PinosCommandFunc) (PinosCommand *command, PinosCore *core, - GError **err); + char **err); -static gboolean execute_command_module_load (PinosCommand *command, +static bool execute_command_module_load (PinosCommand *command, PinosCore *core, - GError **err); + char **err); typedef PinosCommand * (*PinosCommandParseFunc) (const gchar *line, - GError **err); + char **err); static PinosCommand * parse_command_module_load (const gchar *line, - GError **err); + char **err); -struct _PinosCommand +typedef struct { + PinosCommand this; + PinosCommandFunc func; - gchar **args; - gint n_args; -}; + char **args; + int n_args; +} PinosCommandImpl; typedef struct _CommandParse { @@ -72,84 +62,40 @@ static const CommandParse parsers[] = { static const gchar whitespace[] = " \t"; -static gchar ** -tokenize (const gchar * line, gint max_tokens, gint * n_tokens) -{ - gchar **res; - GSList *tokens, *walk; - const gchar *s; - gint num; - - s = line + strspn (line, whitespace); - num = 0; - tokens = NULL; - - while (*s != '\0' && num + 1 < max_tokens) { - gsize len; - gchar *token; - - len = strcspn (s, whitespace); - token = g_strndup (s, len); - tokens = g_slist_prepend (tokens, token); - num++; - - s += len; - s += strspn (s, whitespace); - } - - if (*s != '\0') { - tokens = g_slist_prepend (tokens, g_strdup (s)); - num++; - } - - res = g_new (gchar *, num + 1); - res[num] = NULL; - for (walk = tokens; walk != NULL; walk = walk->next) { - res[--num] = walk->data; - } - g_slist_free (tokens); - - *n_tokens = num; - - return res; -} - static PinosCommand * -parse_command_module_load (const gchar * line, GError ** err) +parse_command_module_load (const char * line, char ** err) { - PinosCommand *command; + PinosCommandImpl *impl; - command = g_new0 (PinosCommand, 1); + impl = calloc (1, sizeof (PinosCommandImpl)); - command->func = execute_command_module_load; - command->args = tokenize (line, 3, &command->n_args); + impl->func = execute_command_module_load; + impl->args = pinos_split_strv (line, whitespace, 3, &impl->n_args); - if (command->args[1] == NULL) + if (impl->args[1] == NULL) goto no_module; - return command; + impl->this.name = impl->args[0]; + + return &impl->this; no_module: - g_set_error (err, PINOS_COMMAND_ERROR, PINOS_COMMAND_ERROR_PARSE, - "%s requires a module name", command->args[0]); - - g_strfreev (command->args); - + asprintf (err, "%s requires a module name", impl->args[0]); + pinos_free_strv (impl->args); return NULL; } -static gboolean +static bool execute_command_module_load (PinosCommand *command, PinosCore *core, - GError **err) + char **err) { - gchar *module; - gchar *args; + PinosCommandImpl *impl = SPA_CONTAINER_OF (command, PinosCommandImpl, this); - module = command->args[1]; - args = command->args[2]; - - return pinos_module_load (core, module, args, err) != NULL; + return pinos_module_load (core, + impl->args[1], + impl->args[2], + err) != NULL; } /** @@ -161,57 +107,47 @@ execute_command_module_load (PinosCommand *command, void pinos_command_free (PinosCommand * command) { - g_return_if_fail (command != NULL); + PinosCommandImpl *impl = SPA_CONTAINER_OF (command, PinosCommandImpl, this); - g_strfreev (command->args); - - g_free (command); + spa_list_remove (&command->link); + pinos_free_strv (impl->args); + free (impl); } /** * pinos_command_parse: - * @command: (out): Return location for a #PinosCommand * @line: command line to parse - * @err: Return location for a #GError, or %NULL + * @err: Return location for an error * - * Parses a command line, @line, and store the parsed command in @command. + * Parses a command line, @line, and return the parsed command. * A command can later be executed with pinos_command_run(). * - * Returns: %TRUE on success, %FALSE otherwise. + * Returns: The command or %NULL when @err is set. */ -gboolean -pinos_command_parse (PinosCommand ** command, - gchar * line, - GError ** err) +PinosCommand * +pinos_command_parse (const char *line, + char **err) { + PinosCommand *command = NULL; const CommandParse *parse; gchar *name; gsize len; - gboolean ret = FALSE; - - g_return_val_if_fail (command != NULL && *command == NULL, FALSE); - g_return_val_if_fail (line != NULL && *line != '\0', FALSE); len = strcspn (line, whitespace); - name = g_strndup (line, len); + name = strndup (line, len); for (parse = parsers; parse->name != NULL; parse++) { - if (g_strcmp0 (name, parse->name) == 0) { - *command = parse->func (line, err); - if (*command != NULL) - ret = TRUE; + if (strcmp (name, parse->name) == 0) { + command = parse->func (line, err); goto out; } } - g_set_error (err, PINOS_COMMAND_ERROR, PINOS_COMMAND_ERROR_NO_SUCH_COMMAND, - "Command \"%s\" does not exist", name); - + asprintf (err, "Command \"%s\" does not exist", name); out: - g_free (name); - - return ret; + free (name); + return command; } /** @@ -222,17 +158,16 @@ out: * * Run @command. * - * Returns: %TRUE if @command was executed successfully, %FALSE otherwise. + * Returns: %true if @command was executed successfully, %false otherwise. */ -gboolean +bool pinos_command_run (PinosCommand *command, PinosCore *core, - GError **err) + char **err) { - g_return_val_if_fail (command != NULL, FALSE); - g_return_val_if_fail (core, FALSE); + PinosCommandImpl *impl = SPA_CONTAINER_OF (command, PinosCommandImpl, this); - return command->func (command, core, err); + return impl->func (command, core, err); } /** @@ -243,10 +178,10 @@ pinos_command_run (PinosCommand *command, * * Returns: The name of @command. */ -const gchar * +const char * pinos_command_get_name (PinosCommand * command) { - g_return_val_if_fail (command != NULL, NULL); + PinosCommandImpl *impl = SPA_CONTAINER_OF (command, PinosCommandImpl, this); - return command->args[0]; + return impl->args[0]; } diff --git a/pinos/server/command.h b/pinos/server/command.h index 11cb27dbb..2be80b359 100644 --- a/pinos/server/command.h +++ b/pinos/server/command.h @@ -21,49 +21,30 @@ #ifndef __PINOS_COMMAND_H__ #define __PINOS_COMMAND_H__ -#include - -G_BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif #include typedef struct _PinosCommand PinosCommand; -GQuark pinos_command_error_quark (void); -/** - * PINOS_COMMAND_ERROR: - * - * Pinos command error. - */ -#define PINOS_COMMAND_ERROR (pinos_command_error_quark ()) -/** - * PinosCommandError: - * @PINOS_COMMAND_ERROR_GENERIC: Generic command error. - * @PINOS_COMMAND_ERROR_NO_SUCH_COMMAND: No such command. - * @PINOS_COMMAND_ERROR_PARSE: Failed to parse command. - * @PINOS_COMMAND_ERROR_FAILED: Command failed to execute. - * - * Error codes for Pinos command. - */ -typedef enum -{ - PINOS_COMMAND_ERROR_GENERIC, - PINOS_COMMAND_ERROR_NO_SUCH_COMMAND, - PINOS_COMMAND_ERROR_PARSE, - PINOS_COMMAND_ERROR_FAILED, -} PinosCommandError; +struct _PinosCommand { + SpaList link; + + const char *name; +}; void pinos_command_free (PinosCommand *command); -gboolean pinos_command_parse (PinosCommand **command, - gchar *line, - GError **err); -gboolean pinos_command_run (PinosCommand *command, +PinosCommand * pinos_command_parse (const char *line, + char **err); +bool pinos_command_run (PinosCommand *command, PinosCore *core, - GError **err); -const gchar * pinos_command_get_name (PinosCommand *command); - -G_END_DECLS + char **err); +#ifdef __cplusplus +} +#endif #endif /* __PINOS_COMMAND_H__ */ diff --git a/pinos/server/core.c b/pinos/server/core.c index d793318e6..4e9415416 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -21,46 +21,93 @@ #include typedef struct { - PinosCore object; + PinosCore this; - PinosDataLoop *data_loop; + GDBusObjectManagerServer *server_manager; SpaSupport support[4]; } PinosCoreImpl; -static void -core_destroy (PinosObject *object) -{ - free (object); -} - PinosCore * pinos_core_new (PinosMainLoop *main_loop) { PinosCoreImpl *impl; + PinosCore *this; impl = calloc (1, sizeof (PinosCoreImpl)); - pinos_registry_init (&impl->object.registry); + this = &impl->this; + pinos_registry_init (&this->registry); - pinos_object_init (&impl->object.object, - impl->object.registry.uri.core, - impl, - core_destroy); - - impl->data_loop = pinos_data_loop_new (); - impl->object.main_loop = main_loop; + this->data_loop = pinos_data_loop_new (); + this->main_loop = main_loop; impl->support[0].uri = SPA_ID_MAP_URI; - impl->support[0].data = impl->object.registry.map; + impl->support[0].data = this->registry.map; impl->support[1].uri = SPA_LOG_URI; impl->support[1].data = pinos_log_get (); impl->support[2].uri = SPA_POLL__DataLoop; - impl->support[2].data = &impl->data_loop->poll; + impl->support[2].data = &this->data_loop->poll; impl->support[3].uri = SPA_POLL__MainLoop; - impl->support[3].data = &impl->object.main_loop->poll; - impl->object.support = impl->support; - impl->object.n_support = 4; + impl->support[3].data = this->main_loop->poll; + this->support = impl->support; + this->n_support = 4; - return &impl->object; + spa_list_init (&this->global_list); + spa_list_init (&this->client_list); + spa_list_init (&this->node_list); + spa_list_init (&this->link_list); + pinos_signal_init (&this->destroy_signal); + pinos_signal_init (&this->global_added); + pinos_signal_init (&this->global_removed); + pinos_signal_init (&this->node_state_changed); + pinos_signal_init (&this->port_added); + pinos_signal_init (&this->port_removed); + pinos_signal_init (&this->port_unlinked); + pinos_signal_init (&this->link_state_changed); + + return this; +} + +void +pinos_core_destroy (PinosCore *core) +{ + PinosCoreImpl *impl = SPA_CONTAINER_OF (core, PinosCoreImpl, this); + + pinos_signal_emit (&core->destroy_signal, core); + + pinos_data_loop_destroy (core->data_loop); + + free (impl); +} + +PinosGlobal * +pinos_core_add_global (PinosCore *core, + uint32_t type, + void *object, + PinosObjectSkeleton *skel) +{ + PinosGlobal *global; + + global = calloc (1, sizeof (PinosGlobal)); + global->core = core; + global->id = 0; + global->type = type; + global->object = object; + global->skel = skel; + + spa_list_insert (core->global_list.prev, &global->list); + pinos_signal_emit (&core->global_added, core, global); + + return global; +} + +void +pinos_core_remove_global (PinosCore *core, + PinosGlobal *global) +{ + pinos_signal_emit (&core->global_removed, core, global); + + spa_list_remove (&global->list); + free (global); } diff --git a/pinos/server/core.h b/pinos/server/core.h index ac4b759c2..ed649ffbf 100644 --- a/pinos/server/core.h +++ b/pinos/server/core.h @@ -24,14 +24,30 @@ extern "C" { #endif -#define PINOS_CORE_URI "http://pinos.org/ns/core" -#define PINOS_CORE_PREFIX PINOS_CORE_URI "#" - typedef struct _PinosCore PinosCore; +typedef struct _PinosGlobal PinosGlobal; + +#include #include #include +#include #include +#include +#include + +#include "pinos/dbus/org-pinos.h" + +struct _PinosGlobal { + PinosCore *core; + SpaList list; + uint32_t id; + uint32_t type; + void *object; + + PinosObjectSkeleton *skel; + const char *object_path; +}; /** * PinosCore: @@ -39,17 +55,61 @@ typedef struct _PinosCore PinosCore; * Pinos core object class. */ struct _PinosCore { - PinosObject object; - PinosRegistry registry; + GDBusConnection *connection; + + SpaList global_list; + SpaList client_list; + SpaList node_list; + SpaList link_list; + + PinosMainLoop *main_loop; + PinosDataLoop *data_loop; SpaSupport *support; unsigned int n_support; + + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosCore *core)); + + + PINOS_SIGNAL (global_added, (PinosListener *listener, + PinosCore *core, + PinosGlobal *global)); + PINOS_SIGNAL (global_removed, (PinosListener *listener, + PinosCore *core, + PinosGlobal *global)); + + PINOS_SIGNAL (node_state_changed, (PinosListener *listener, + PinosNode *object, + PinosNodeState old, + PinosNodeState state)); + PINOS_SIGNAL (port_added, (PinosListener *listener, + PinosNode *node, + PinosPort *port)); + PINOS_SIGNAL (port_removed, (PinosListener *listener, + PinosNode *node, + PinosPort *port)); + + PINOS_SIGNAL (port_unlinked, (PinosListener *listener, + PinosLink *link, + PinosPort *port)); + PINOS_SIGNAL (link_state_changed, (PinosListener *listener, + PinosLink *link)); + }; -PinosCore * pinos_core_new (PinosMainLoop *main_loop); +PinosCore * pinos_core_new (PinosMainLoop *main_loop); +void pinos_core_destroy (PinosCore *core); + +PinosGlobal * pinos_core_add_global (PinosCore *core, + uint32_t type, + void *object, + PinosObjectSkeleton *skel); +void pinos_core_remove_global (PinosCore *core, + PinosGlobal *global); #ifdef __cplusplus } diff --git a/pinos/server/daemon.c b/pinos/server/daemon.c index 14be39d5b..cfa48a40e 100644 --- a/pinos/server/daemon.c +++ b/pinos/server/daemon.c @@ -19,6 +19,7 @@ #include #include +#include #include #include @@ -40,22 +41,20 @@ #include "pinos/dbus/org-pinos.h" typedef struct { - PinosDaemon daemon; - PinosObject object; + PinosDaemon this; + + GDBusObjectManagerServer *server_manager; PinosDaemon1 *iface; guint id; - GDBusConnection *connection; - GDBusObjectManagerServer *server_manager; - gchar *object_path; - - PinosDataLoop *data_loop; - - PinosListener object_added; - PinosListener object_removed; + PinosListener global_added; + PinosListener global_removed; + PinosListener port_added; + PinosListener port_removed; PinosListener port_unlinked; - PinosListener notify_state; + PinosListener node_state_changed; + PinosListener link_state_changed; GHashTable *clients; GHashTable *node_factories; @@ -63,60 +62,21 @@ typedef struct { static void try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *daemon); -static void -handle_client_appeared (PinosClient *client, gpointer user_data) -{ - PinosDaemonImpl *impl = user_data; - - pinos_log_debug ("daemon %p: appeared %p", impl, client); - - g_hash_table_insert (impl->clients, (gpointer) client->sender, client); -} - -static void -handle_client_vanished (PinosClient *client, gpointer user_data) -{ - PinosDaemonImpl *impl = user_data; - - pinos_log_debug ("daemon %p: vanished %p", daemon, client); - g_hash_table_remove (impl->clients, (gpointer) client->sender); -} - static PinosClient * sender_get_client (PinosDaemon *daemon, const gchar *sender, gboolean create) { - PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, this); PinosClient *client; client = g_hash_table_lookup (impl->clients, sender); if (client == NULL && create) { client = pinos_client_new (daemon->core, sender, NULL); - - pinos_log_debug ("daemon %p: new client %p for %s", daemon, client, sender); - g_signal_connect (client, - "appeared", - (GCallback) handle_client_appeared, - daemon); - g_signal_connect (client, - "vanished", - (GCallback) handle_client_vanished, - daemon); } return client; } -static void -handle_remove_node (PinosNode *node, - gpointer user_data) -{ - //PinosClient *client = user_data; - - //pinos_log_debug ("client %p: node %p remove", daemon, node); - //pinos_client_remove_object (client, &node->object); -} - static gboolean handle_create_node (PinosDaemon1 *interface, GDBusMethodInvocation *invocation, @@ -126,6 +86,7 @@ handle_create_node (PinosDaemon1 *interface, gpointer user_data) { PinosDaemonImpl *impl = user_data; + PinosDaemon *this = &impl->this; PinosNodeFactory *factory; PinosNode *node; PinosClient *client; @@ -133,7 +94,7 @@ handle_create_node (PinosDaemon1 *interface, PinosProperties *props; sender = g_dbus_method_invocation_get_sender (invocation); - client = sender_get_client (&impl->daemon, sender, TRUE); + client = sender_get_client (this, sender, TRUE); pinos_log_debug ("daemon %p: create node: %s", impl, sender); @@ -154,17 +115,10 @@ handle_create_node (PinosDaemon1 *interface, //pinos_client_add_object (client, &node->object); - //g_signal_connect (node, - // "remove", - // (GCallback) handle_remove_node, - // client); - - object_path = pinos_node_get_object_path (node); + object_path = node->global->object_path; pinos_log_debug ("daemon %p: added node %p with path %s", impl, node, object_path); g_dbus_method_invocation_return_value (invocation, g_variant_new ("(o)", object_path)); - g_object_unref (node); - return TRUE; /* ERRORS */ @@ -187,39 +141,34 @@ no_node: static void on_link_port_unlinked (PinosListener *listener, - void *object, - void *data) + PinosLink *link, + PinosPort *port) { - PinosLink *link = object; - PinosPort *port = data; PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, port_unlinked); pinos_log_debug ("daemon %p: link %p: port %p unlinked", impl, link, port); if (port->direction == PINOS_DIRECTION_OUTPUT && link->input) - try_link_port (link->input->node, link->input, &impl->daemon); + try_link_port (link->input->node, link->input, &impl->this); } static void -on_link_notify_state (PinosListener *listener, - void *object, - void *data) +on_link_state_changed (PinosListener *listener, + PinosLink *link) { - PinosLink *link = object; - PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, notify_state); - GError *error = NULL; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, link_state_changed); PinosLinkState state; - state = pinos_link_get_state (link, &error); + state = link->state; switch (state) { case PINOS_LINK_STATE_ERROR: { - pinos_log_debug ("daemon %p: link %p: state error: %s", impl, link, error->message); + pinos_log_debug ("daemon %p: link %p: state error: %s", impl, link, link->error->message); if (link->input && link->input->node) - pinos_node_report_error (link->input->node, g_error_copy (error)); + pinos_node_report_error (link->input->node, g_error_copy (link->error)); if (link->output && link->output->node) - pinos_node_report_error (link->output->node, g_error_copy (error)); + pinos_node_report_error (link->output->node, g_error_copy (link->error)); break; } @@ -251,10 +200,10 @@ on_link_notify_state (PinosListener *listener, static void try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *this) { - PinosDaemonImpl *impl = (PinosDaemonImpl *) this; - PinosClient *client; + //PinosDaemonImpl *impl = SPA_CONTAINER_OF (this, PinosDaemonImpl, this); + //PinosClient *client; PinosProperties *props; - const gchar *path; + const char *path; GError *error = NULL; PinosLink *link; @@ -284,19 +233,14 @@ try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *this) if (link == NULL) goto error; +#if 0 client = pinos_node_get_client (node); if (client) pinos_client_add_object (client, &link->object); +#endif - impl->port_unlinked.notify = on_link_port_unlinked; - pinos_signal_add (&link->port_unlinked, &impl->port_unlinked); - - impl->notify_state.notify = on_link_notify_state; - pinos_signal_add (&link->notify_state, &impl->notify_state); pinos_link_activate (link); - - g_object_unref (link); } return; @@ -308,62 +252,64 @@ error: } static void -on_port_added (PinosNode *node, PinosPort *port, PinosDaemon *this) +on_port_added (PinosListener *listener, + PinosNode *node, + PinosPort *port) { - try_link_port (node, port, this); + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, port_added); + + try_link_port (node, port, &impl->this); } static void -on_port_removed (PinosNode *node, PinosPort *port, PinosDaemon *this) +on_port_removed (PinosListener *listener, + PinosNode *node, + PinosPort *port) { } static void -on_node_created (PinosNode *node, - PinosDaemon *this) +on_node_created (PinosNode *node, + PinosDaemonImpl *impl) { GList *ports, *walk; ports = pinos_node_get_ports (node, PINOS_DIRECTION_INPUT); for (walk = ports; walk; walk = g_list_next (walk)) - on_port_added (node, walk->data, this); + on_port_added (&impl->port_added, node, walk->data); ports = pinos_node_get_ports (node, PINOS_DIRECTION_OUTPUT); for (walk = ports; walk; walk = g_list_next (walk)) - on_port_added (node, walk->data, this); - - g_signal_connect (node, "port-added", (GCallback) on_port_added, this); - g_signal_connect (node, "port-removed", (GCallback) on_port_removed, this); + on_port_added (&impl->port_added, node, walk->data); } - static void -on_node_state_change (PinosNode *node, - PinosNodeState old, - PinosNodeState state, - PinosDaemon *this) +on_node_state_changed (PinosListener *listener, + PinosNode *node, + PinosNodeState old, + PinosNodeState state) { - pinos_log_debug ("daemon %p: node %p state change %s -> %s", this, node, + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, node_state_changed); + + pinos_log_debug ("daemon %p: node %p state change %s -> %s", impl, node, pinos_node_state_as_string (old), pinos_node_state_as_string (state)); if (old == PINOS_NODE_STATE_CREATING && state == PINOS_NODE_STATE_SUSPENDED) - on_node_created (node, this); + on_node_created (node, impl); } static void on_node_added (PinosDaemon *daemon, PinosNode *node) { - PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, this); pinos_log_debug ("daemon %p: node %p added", impl, node); - g_object_set (node, "data-loop", impl->data_loop, NULL); - - g_signal_connect (node, "state-change", (GCallback) on_node_state_change, impl); + pinos_node_set_data_loop (node, daemon->core->data_loop); if (node->state > PINOS_NODE_STATE_CREATING) { - on_node_created (node, daemon); + on_node_created (node, impl); } } @@ -382,55 +328,53 @@ handle_create_client_node (PinosDaemon1 *interface, gpointer user_data) { PinosDaemonImpl *impl = user_data; - PinosDaemon *this = &impl->daemon; + PinosDaemon *this = &impl->this; PinosClientNode *node; PinosClient *client; - const gchar *sender, *object_path; + SpaResult res; + const char *sender, *object_path; PinosProperties *props; GError *error = NULL; GUnixFDList *fdlist; - int socket, rtsocket; - gint fdidx, rtfdidx; + int ctrl_fd, data_fd; + int ctrl_idx, data_idx; sender = g_dbus_method_invocation_get_sender (invocation); - client = sender_get_client (&impl->daemon, sender, TRUE); + client = sender_get_client (this, sender, TRUE); pinos_log_debug ("daemon %p: create client-node: %s", impl, sender); props = pinos_properties_from_variant (arg_properties); - node = pinos_client_node_new (this->core, - client, - arg_name, - props); - pinos_properties_free (props); + node = pinos_client_node_new (this->core, + client, + arg_name, + props); - socket = pinos_client_node_get_socket_pair (node, &error); - if (socket == -1) + if ((res = pinos_client_node_get_ctrl_socket (node, &ctrl_fd)) < 0) goto no_socket; - rtsocket = pinos_client_node_get_rtsocket_pair (node, &error); - if (rtsocket == -1) + if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) goto no_socket; //pinos_client_add_object (client, &node->object); - object_path = pinos_node_get_object_path (node->node); + object_path = node->node->global->object_path; pinos_log_debug ("daemon %p: add client-node %p, %s", impl, node, object_path); fdlist = g_unix_fd_list_new (); - fdidx = g_unix_fd_list_append (fdlist, socket, &error); - rtfdidx = g_unix_fd_list_append (fdlist, rtsocket, &error); + ctrl_idx = g_unix_fd_list_append (fdlist, ctrl_fd, &error); + data_idx = g_unix_fd_list_append (fdlist, data_fd, &error); g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(ohh)", object_path, fdidx, rtfdidx), fdlist); + g_variant_new ("(ohh)", object_path, ctrl_idx, data_idx), fdlist); g_object_unref (fdlist); return TRUE; no_socket: { - pinos_log_debug ("daemon %p: could not create socket %s", impl, error->message); - g_object_unref (node); + pinos_log_debug ("daemon %p: could not create socket: %s", impl, strerror (errno)); + pinos_client_node_destroy (node); goto exit_error; } exit_error: @@ -441,15 +385,14 @@ exit_error: } } +#if 0 static void export_server_object (PinosDaemon *daemon, GDBusObjectManagerServer *manager) { - PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; - PinosObjectSkeleton *skel; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, this); skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_SERVER); - pinos_object_skeleton_set_daemon1 (skel, impl->iface); g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (skel)); @@ -457,6 +400,7 @@ export_server_object (PinosDaemon *daemon, impl->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); g_object_unref (skel); } +#endif static void bus_acquired_handler (GDBusConnection *connection, @@ -464,12 +408,10 @@ bus_acquired_handler (GDBusConnection *connection, gpointer user_data) { PinosDaemonImpl *impl = user_data; + PinosDaemon *this = &impl->this; GDBusObjectManagerServer *manager = impl->server_manager; - impl->connection = connection; - - export_server_object (&impl->daemon, manager); - + this->core->connection = connection; g_dbus_object_manager_server_set_connection (manager, connection); } @@ -486,28 +428,17 @@ name_lost_handler (GDBusConnection *connection, gpointer user_data) { PinosDaemonImpl *impl = user_data; + PinosDaemon *this = &impl->this; GDBusObjectManagerServer *manager = impl->server_manager; - g_dbus_object_manager_server_unexport (manager, PINOS_DBUS_OBJECT_SERVER); g_dbus_object_manager_server_set_connection (manager, connection); - g_clear_pointer (&impl->object_path, g_free); - impl->connection = connection; -} - -const gchar * -pinos_daemon_get_object_path (PinosDaemon *daemon) -{ - PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; - - g_return_val_if_fail (impl, NULL); - - return impl->object_path; + this->core->connection = connection; } static SpaResult daemon_start (PinosDaemon *daemon) { - PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, daemon); + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, this); g_return_val_if_fail (impl, SPA_RESULT_INVALID_ARGUMENTS); g_return_val_if_fail (impl->id == 0, SPA_RESULT_INVALID_ARGUMENTS); @@ -529,7 +460,7 @@ daemon_start (PinosDaemon *daemon) static SpaResult daemon_stop (PinosDaemon *daemon) { - PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, daemon); + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, this); g_return_val_if_fail (impl, SPA_RESULT_INVALID_ARGUMENTS); @@ -542,90 +473,59 @@ daemon_stop (PinosDaemon *daemon) return SPA_RESULT_OK; } -/** - * pinos_daemon_export_uniquely: - * @daemon: a #PinosDaemon - * @skel: a #GDBusObjectSkeleton - * - * Export @skel with @daemon with a unique name - * - * Returns: the unique named used to export @skel. - */ -gchar * -pinos_daemon_export_uniquely (PinosDaemon *daemon, - GDBusObjectSkeleton *skel) -{ - PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; - - g_return_val_if_fail (impl, NULL); - g_return_val_if_fail (G_IS_DBUS_OBJECT_SKELETON (skel), NULL); - - g_dbus_object_manager_server_export_uniquely (impl->server_manager, skel); - - return g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); -} - -/** - * pinos_daemon_unexport: - * @daemon: a #PinosDaemon - * @object_path: an object path - * - * Unexport the object on @object_path - */ -void -pinos_daemon_unexport (PinosDaemon *daemon, - const gchar *object_path) -{ - PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; - - g_return_if_fail (impl); - g_return_if_fail (g_variant_is_object_path (object_path)); - - g_dbus_object_manager_server_unexport (impl->server_manager, object_path); -} - static void -on_registry_object_added (PinosListener *listener, - void *object, - void *data) +on_global_added (PinosListener *listener, + PinosCore *core, + PinosGlobal *global) { - PinosObject *obj = data; - PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, object_added); - PinosDaemon *this = &impl->daemon; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, global_added); + PinosDaemon *this = &impl->this; - if (obj->type == this->core->registry.uri.node) { - PinosNode *node = obj->implementation; + if (global->skel) { + g_dbus_object_manager_server_export_uniquely (impl->server_manager, + G_DBUS_OBJECT_SKELETON (global->skel)); + global->object_path = g_dbus_object_get_object_path (G_DBUS_OBJECT (global->skel)); + } + + if (global->type == this->core->registry.uri.node) { + PinosNode *node = global->object; on_node_added (this, node); - } else if (obj->type == this->core->registry.uri.node_factory) { - PinosNodeFactory *factory = obj->implementation; - gchar *name; + } else if (global->type == this->core->registry.uri.node_factory) { + PinosNodeFactory *factory = global->object; - g_object_get (factory, "name", &name, NULL); - g_hash_table_insert (impl->node_factories, name, g_object_ref (factory)); + g_hash_table_insert (impl->node_factories, (void *)factory->name, factory); + } else if (global->type == this->core->registry.uri.client) { + PinosClient *client = global->object; + + g_hash_table_insert (impl->clients, (gpointer) client->sender, client); } } static void -on_registry_object_removed (PinosListener *listener, - void *object, - void *data) +on_global_removed (PinosListener *listener, + PinosCore *core, + PinosGlobal *global) { - PinosObject *obj = data; - PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, object_added); - PinosDaemon *this = &impl->daemon; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, global_removed); + PinosDaemon *this = &impl->this; - if (obj->type == this->core->registry.uri.node) { - PinosNode *node = obj->implementation; + if (global->object_path) { + g_dbus_object_manager_server_unexport (impl->server_manager, global->object_path); + } + + if (global->type == this->core->registry.uri.node) { + PinosNode *node = global->object; on_node_removed (this, node); - } else if (obj->type == this->core->registry.uri.node_factory) { - PinosNodeFactory *factory = obj->implementation; - gchar *name; + } else if (global->type == this->core->registry.uri.node_factory) { + PinosNodeFactory *factory = global->object; - g_object_get (factory, "name", &name, NULL); - g_hash_table_remove (impl->node_factories, name); - g_free (name); + g_hash_table_remove (impl->node_factories, factory->name); + } else if (global->type == this->core->registry.uri.client) { + PinosClient *client = global->object; + + g_hash_table_remove (impl->clients, (gpointer) client->sender); } } @@ -645,15 +545,14 @@ on_registry_object_removed (PinosListener *listener, PinosPort * pinos_daemon_find_port (PinosDaemon *daemon, PinosPort *other_port, - const gchar *name, + const char *name, PinosProperties *props, GPtrArray *format_filters, GError **error) { PinosPort *best = NULL; gboolean have_name; - void *state = NULL; - PinosObject *o; + PinosNode *n; g_return_val_if_fail (daemon, NULL); @@ -661,15 +560,11 @@ pinos_daemon_find_port (PinosDaemon *daemon, pinos_log_debug ("name \"%s\", %d", name, have_name); - while ((o = pinos_registry_iterate_nodes (&daemon->core->registry, &state))) { - PinosNode *n = o->implementation; - if (o->flags & PINOS_OBJECT_FLAG_DESTROYING) - continue; - - pinos_log_debug ("node path \"%s\"", pinos_node_get_object_path (n)); + spa_list_for_each (n, &daemon->core->node_list, list) { + pinos_log_debug ("node path \"%s\"", n->global->object_path); if (have_name) { - if (g_str_has_suffix (pinos_node_get_object_path (n), name)) { + if (g_str_has_suffix (n->global->object_path, name)) { pinos_log_debug ("name \"%s\" matches node %p", name, n); best = pinos_node_get_free_port (n, pinos_direction_reverse (other_port->direction)); @@ -688,36 +583,6 @@ pinos_daemon_find_port (PinosDaemon *daemon, return best; } -static void -daemon_destroy (PinosObject *object) -{ - PinosDaemonImpl *impl = SPA_CONTAINER_OF (object, PinosDaemonImpl, object); - PinosDaemon *this = &impl->daemon; - - pinos_log_debug ("daemon %p: destroy", impl); - - pinos_daemon_stop (this); - - pinos_signal_remove (&impl->object_added); - pinos_signal_remove (&impl->object_removed); - - g_clear_object (&impl->server_manager); - g_clear_object (&impl->iface); - g_hash_table_unref (impl->clients); - g_hash_table_unref (impl->node_factories); - - pinos_registry_remove_object (&this->core->registry, &impl->object); - free (impl); -} - -void -pinos_daemon_destroy (PinosDaemon *daemon) -{ - PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, daemon); - - pinos_object_destroy (&impl->object); -} - /** * pinos_daemon_new: * @core: #PinosCore @@ -733,9 +598,10 @@ pinos_daemon_new (PinosCore *core, { PinosDaemonImpl *impl; PinosDaemon *this; + PinosObjectSkeleton *skel; impl = calloc (1, sizeof (PinosDaemonImpl)); - this = &impl->daemon; + this = &impl->this; pinos_log_debug ("daemon %p: new", impl); this->core = core; @@ -744,27 +610,29 @@ pinos_daemon_new (PinosCore *core, this->start = daemon_start; this->stop = daemon_stop; - pinos_object_init (&impl->object, - core->registry.uri.daemon, - impl, - daemon_destroy); + pinos_signal_init (&this->destroy_signal); - impl->object_added.notify = on_registry_object_added; - pinos_signal_add (&core->registry.object_added, &impl->object_added); - - impl->object_removed.notify = on_registry_object_removed; - pinos_signal_add (&core->registry.object_removed, &impl->object_removed); + pinos_signal_add (&core->global_added, &impl->global_added, on_global_added); + pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed); + pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed); + pinos_signal_add (&core->port_added, &impl->port_added, on_port_added); + pinos_signal_add (&core->port_removed, &impl->port_removed, on_port_removed); + pinos_signal_add (&core->port_unlinked, &impl->port_unlinked, on_link_port_unlinked); + pinos_signal_add (&core->link_state_changed, &impl->link_state_changed, on_link_state_changed); impl->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX); impl->clients = g_hash_table_new (g_str_hash, g_str_equal); impl->node_factories = g_hash_table_new_full (g_str_hash, g_str_equal, - g_free, - g_object_unref); + NULL, + NULL); impl->iface = pinos_daemon1_skeleton_new (); - g_signal_connect (impl->iface, "handle-create-node", (GCallback) handle_create_node, daemon); - g_signal_connect (impl->iface, "handle-create-client-node", (GCallback) handle_create_client_node, daemon); + g_signal_connect (impl->iface, "handle-create-node", (GCallback) handle_create_node, impl); + g_signal_connect (impl->iface, "handle-create-client-node", (GCallback) handle_create_client_node, impl); + + skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_SERVER); + pinos_object_skeleton_set_daemon1 (skel, impl->iface); pinos_daemon1_set_user_name (impl->iface, g_get_user_name ()); pinos_daemon1_set_host_name (impl->iface, g_get_host_name ()); @@ -773,7 +641,32 @@ pinos_daemon_new (PinosCore *core, pinos_daemon1_set_cookie (impl->iface, g_random_int()); pinos_daemon1_set_properties (impl->iface, pinos_properties_to_variant (this->properties)); - pinos_registry_add_object (&core->registry, &impl->object); + this->global = pinos_core_add_global (core, + core->registry.uri.daemon, + this, + skel); return this; } + +void +pinos_daemon_destroy (PinosDaemon *daemon) +{ + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, this); + + pinos_log_debug ("daemon %p: destroy", impl); + + pinos_signal_emit (&daemon->destroy_signal, daemon); + + pinos_daemon_stop (daemon); + + pinos_signal_remove (&impl->global_added); + pinos_signal_remove (&impl->global_removed); + + g_clear_object (&impl->server_manager); + g_clear_object (&impl->iface); + g_hash_table_unref (impl->clients); + g_hash_table_unref (impl->node_factories); + + free (impl); +} diff --git a/pinos/server/daemon.h b/pinos/server/daemon.h index 6fdfc2fb8..a4c2dedfd 100644 --- a/pinos/server/daemon.h +++ b/pinos/server/daemon.h @@ -39,25 +39,27 @@ typedef struct _PinosDaemon PinosDaemon; * Pinos daemon object class. */ struct _PinosDaemon { + PinosCore *core; + SpaList list; + PinosGlobal *global; + PinosProperties *properties; - PinosCore *core; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosDaemon *daemon)); SpaResult (*start) (PinosDaemon *daemon); SpaResult (*stop) (PinosDaemon *daemon); }; -PinosObject * pinos_daemon_new (PinosCore *core, +PinosDaemon * pinos_daemon_new (PinosCore *core, PinosProperties *properties); +void pinos_daemon_destroy (PinosDaemon *daemon); -const char * pinos_daemon_get_object_path (PinosDaemon *daemon); #define pinos_daemon_start(d) (d)->start(d) #define pinos_daemon_stop(d) (d)->stop(d) -char * pinos_daemon_export_uniquely (PinosDaemon *daemon, GDBusObjectSkeleton *skel); -void pinos_daemon_unexport (PinosDaemon *daemon, const char *name); - PinosPort * pinos_daemon_find_port (PinosDaemon *daemon, PinosPort *other_port, const char *name, diff --git a/pinos/server/data-loop.c b/pinos/server/data-loop.c index 5ce6bdb72..638f9fbd1 100644 --- a/pinos/server/data-loop.c +++ b/pinos/server/data-loop.c @@ -46,8 +46,10 @@ typedef struct { void *user_data; } InvokeItem; -struct _PinosDataLoopPrivate +typedef struct { + PinosDataLoop this; + SpaRingbuffer buffer; uint8_t buffer_data[DATAS_SIZE]; @@ -64,20 +66,7 @@ struct _PinosDataLoopPrivate bool running; pthread_t thread; - -}; - -G_DEFINE_TYPE (PinosDataLoop, pinos_data_loop, G_TYPE_OBJECT); - -enum -{ - PROP_0, -}; - -enum -{ - LAST_SIGNAL -}; +} PinosDataLoopImpl; static void make_realtime (PinosDataLoop *this) @@ -126,23 +115,23 @@ make_realtime (PinosDataLoop *this) static void * loop (void *user_data) { - PinosDataLoop *this = user_data; - PinosDataLoopPrivate *priv = this->priv; + PinosDataLoopImpl *impl = user_data; + PinosDataLoop *this = &impl->this; SpaPoll *p = &this->poll; unsigned int i, j; make_realtime (this); pinos_log_debug ("data-loop %p: enter thread", this); - while (priv->running) { + while (impl->running) { SpaPollNotifyData ndata; unsigned int n_idle = 0; int r; struct timespec ts; /* prepare */ - for (i = 0; i < priv->n_poll; i++) { - SpaPollItem *p = &priv->poll[i]; + for (i = 0; i < impl->n_poll; i++) { + SpaPollItem *p = &impl->poll[i]; if (p->enabled && p->idle_cb) { ndata.fds = NULL; @@ -157,28 +146,28 @@ loop (void *user_data) // continue; /* rebuild */ - if (priv->rebuild_fds) { - priv->n_fds = 1; - for (i = 0; i < priv->n_poll; i++) { - SpaPollItem *p = &priv->poll[i]; + if (impl->rebuild_fds) { + impl->n_fds = 1; + for (i = 0; i < impl->n_poll; i++) { + SpaPollItem *p = &impl->poll[i]; if (!p->enabled) continue; for (j = 0; j < p->n_fds; j++) - priv->fds[priv->n_fds + j] = p->fds[j]; - priv->idx[i] = priv->n_fds; - priv->n_fds += p->n_fds; + impl->fds[impl->n_fds + j] = p->fds[j]; + impl->idx[i] = impl->n_fds; + impl->n_fds += p->n_fds; } - priv->rebuild_fds = false; + impl->rebuild_fds = false; } /* before */ - for (i = 0; i < priv->n_poll; i++) { - SpaPollItem *p = &priv->poll[i]; + for (i = 0; i < impl->n_poll; i++) { + SpaPollItem *p = &impl->poll[i]; if (p->enabled && p->before_cb) { - ndata.fds = &priv->fds[priv->idx[i]]; + ndata.fds = &impl->fds[impl->idx[i]]; ndata.n_fds = p->n_fds; ndata.user_data = p->user_data; if (SPA_RESULT_IS_ERROR (p->before_cb (&ndata))) @@ -186,7 +175,7 @@ loop (void *user_data) } } - r = poll ((struct pollfd *) priv->fds, priv->n_fds, -1); + r = poll ((struct pollfd *) impl->fds, impl->n_fds, -1); if (r < 0) { if (errno == EINTR) continue; @@ -198,17 +187,17 @@ loop (void *user_data) } /* check wakeup */ - if (priv->fds[0].revents & POLLIN) { + if (impl->fds[0].revents & POLLIN) { uint64_t u; size_t offset; - if (read (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) + if (read (impl->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) pinos_log_warn ("data-loop %p: failed to read fd: %s", this, strerror (errno)); - while (spa_ringbuffer_get_read_offset (&priv->buffer, &offset) > 0) { - InvokeItem *item = SPA_MEMBER (priv->buffer_data, offset, InvokeItem); + while (spa_ringbuffer_get_read_offset (&impl->buffer, &offset) > 0) { + InvokeItem *item = SPA_MEMBER (impl->buffer_data, offset, InvokeItem); item->func (p, true, item->seq, item->size, item->data, item->user_data); - spa_ringbuffer_read_advance (&priv->buffer, item->item_size); + spa_ringbuffer_read_advance (&impl->buffer, item->item_size); } continue; } @@ -217,11 +206,11 @@ loop (void *user_data) // fprintf (stderr, "%llu\n", SPA_TIMESPEC_TO_TIME (&ts)); /* after */ - for (i = 0; i < priv->n_poll; i++) { - SpaPollItem *p = &priv->poll[i]; + for (i = 0; i < impl->n_poll; i++) { + SpaPollItem *p = &impl->poll[i]; - if (p->enabled && p->after_cb && (p->n_fds == 0 || priv->fds[priv->idx[i]].revents != 0)) { - ndata.fds = &priv->fds[priv->idx[i]]; + if (p->enabled && p->after_cb && (p->n_fds == 0 || impl->fds[impl->idx[i]].revents != 0)) { + ndata.fds = &impl->fds[impl->idx[i]]; ndata.n_fds = p->n_fds; ndata.user_data = p->user_data; if (SPA_RESULT_IS_ERROR (p->after_cb (&ndata))) @@ -235,40 +224,36 @@ loop (void *user_data) } static void -wakeup_thread (PinosDataLoop *this) +wakeup_thread (PinosDataLoopImpl *impl) { - PinosDataLoopPrivate *priv = this->priv; uint64_t u = 1; - if (write (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) - pinos_log_warn ("data-loop %p: failed to write fd: %s", this, strerror (errno)); + if (write (impl->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) + pinos_log_warn ("data-loop %p: failed to write fd: %s", impl, strerror (errno)); } static void -start_thread (PinosDataLoop *this) +start_thread (PinosDataLoopImpl *impl) { - PinosDataLoopPrivate *priv = this->priv; int err; - if (!priv->running) { - priv->running = true; - if ((err = pthread_create (&priv->thread, NULL, loop, this)) != 0) { - pinos_log_warn ("data-loop %p: can't create thread: %s", this, strerror (err)); - priv->running = false; + if (!impl->running) { + impl->running = true; + if ((err = pthread_create (&impl->thread, NULL, loop, impl)) != 0) { + pinos_log_warn ("data-loop %p: can't create thread: %s", impl, strerror (err)); + impl->running = false; } } } static void -stop_thread (PinosDataLoop *this, bool in_thread) +stop_thread (PinosDataLoopImpl *impl, bool in_thread) { - PinosDataLoopPrivate *priv = this->priv; - - if (priv->running) { - priv->running = false; + if (impl->running) { + impl->running = false; if (!in_thread) { - wakeup_thread (this); - pthread_join (priv->thread, NULL); + wakeup_thread (impl); + pthread_join (impl->thread, NULL); } } } @@ -278,18 +263,18 @@ do_add_item (SpaPoll *poll, SpaPollItem *item) { PinosDataLoop *this = SPA_CONTAINER_OF (poll, PinosDataLoop, poll); - PinosDataLoopPrivate *priv = this->priv; - bool in_thread = pthread_equal (priv->thread, pthread_self()); + PinosDataLoopImpl *impl = SPA_CONTAINER_OF (this, PinosDataLoopImpl, this); + bool in_thread = pthread_equal (impl->thread, pthread_self()); - item->id = ++priv->counter; - priv->poll[priv->n_poll] = *item; - priv->n_poll++; + item->id = ++impl->counter; + impl->poll[impl->n_poll] = *item; + impl->n_poll++; if (item->n_fds) - priv->rebuild_fds = true; + impl->rebuild_fds = true; if (!in_thread) { - wakeup_thread (this); - start_thread (this); + wakeup_thread (impl); + start_thread (impl); } return SPA_RESULT_OK; } @@ -300,19 +285,19 @@ do_update_item (SpaPoll *poll, SpaPollItem *item) { PinosDataLoop *this = SPA_CONTAINER_OF (poll, PinosDataLoop, poll); - PinosDataLoopPrivate *priv = this->priv; - bool in_thread = pthread_equal (priv->thread, pthread_self()); + PinosDataLoopImpl *impl = SPA_CONTAINER_OF (this, PinosDataLoopImpl, this); + bool in_thread = pthread_equal (impl->thread, pthread_self()); unsigned int i; - for (i = 0; i < priv->n_poll; i++) { - if (priv->poll[i].id == item->id) - priv->poll[i] = *item; + for (i = 0; i < impl->n_poll; i++) { + if (impl->poll[i].id == item->id) + impl->poll[i] = *item; } if (item->n_fds) - priv->rebuild_fds = true; + impl->rebuild_fds = true; if (!in_thread) - wakeup_thread (this); + wakeup_thread (impl); return SPA_RESULT_OK; } @@ -322,22 +307,22 @@ do_remove_item (SpaPoll *poll, SpaPollItem *item) { PinosDataLoop *this = SPA_CONTAINER_OF (poll, PinosDataLoop, poll); - PinosDataLoopPrivate *priv = this->priv; - bool in_thread = pthread_equal (priv->thread, pthread_self()); + PinosDataLoopImpl *impl = SPA_CONTAINER_OF (this, PinosDataLoopImpl, this); + bool in_thread = pthread_equal (impl->thread, pthread_self()); unsigned int i; - for (i = 0; i < priv->n_poll; i++) { - if (priv->poll[i].id == item->id) { - priv->n_poll--; - for (; i < priv->n_poll; i++) - priv->poll[i] = priv->poll[i+1]; + for (i = 0; i < impl->n_poll; i++) { + if (impl->poll[i].id == item->id) { + impl->n_poll--; + for (; i < impl->n_poll; i++) + impl->poll[i] = impl->poll[i+1]; break; } } if (item->n_fds) { - priv->rebuild_fds = true; + impl->rebuild_fds = true; if (!in_thread) - wakeup_thread (this); + wakeup_thread (impl); } return SPA_RESULT_OK; } @@ -351,8 +336,8 @@ do_invoke (SpaPoll *poll, void *user_data) { PinosDataLoop *this = SPA_CONTAINER_OF (poll, PinosDataLoop, poll); - PinosDataLoopPrivate *priv = this->priv; - bool in_thread = pthread_equal (priv->thread, pthread_self()); + PinosDataLoopImpl *impl = SPA_CONTAINER_OF (this, PinosDataLoopImpl, this); + bool in_thread = pthread_equal (impl->thread, pthread_self()); SpaRingbufferArea areas[2]; InvokeItem *item; SpaResult res; @@ -360,12 +345,12 @@ do_invoke (SpaPoll *poll, if (in_thread) { res = func (poll, false, seq, size, data, user_data); } else { - spa_ringbuffer_get_write_areas (&priv->buffer, areas); + spa_ringbuffer_get_write_areas (&impl->buffer, areas); if (areas[0].len < sizeof (InvokeItem)) { pinos_log_warn ("queue full"); return SPA_RESULT_ERROR; } - item = SPA_MEMBER (priv->buffer_data, areas[0].offset, InvokeItem); + item = SPA_MEMBER (impl->buffer_data, areas[0].offset, InvokeItem); item->seq = seq; item->func = func; item->user_data = user_data; @@ -377,14 +362,14 @@ do_invoke (SpaPoll *poll, if (areas[0].len < sizeof (InvokeItem) + item->item_size) item->item_size = areas[0].len; } else { - item->data = SPA_MEMBER (priv->buffer_data, areas[1].offset, void); + item->data = SPA_MEMBER (impl->buffer_data, areas[1].offset, void); item->item_size = areas[0].len + 1 + size; } memcpy (item->data, data, size); - spa_ringbuffer_write_advance (&priv->buffer, item->item_size); + spa_ringbuffer_write_advance (&impl->buffer, item->item_size); - wakeup_thread (this); + wakeup_thread (impl); if (seq != SPA_ID_INVALID) res = SPA_RESULT_RETURN_ASYNC (seq); @@ -394,72 +379,6 @@ do_invoke (SpaPoll *poll, return res; } -static void -pinos_data_loop_constructed (GObject * obj) -{ - PinosDataLoop *this = PINOS_DATA_LOOP (obj); - PinosDataLoopPrivate *priv = this->priv; - - pinos_log_debug ("data-loop %p: constructed", this); - - G_OBJECT_CLASS (pinos_data_loop_parent_class)->constructed (obj); - - priv->fds[0].fd = eventfd (0, 0); - priv->fds[0].events = POLLIN | POLLPRI | POLLERR; - priv->fds[0].revents = 0; - priv->n_fds = 1; -} - -static void -pinos_data_loop_dispose (GObject * obj) -{ - PinosDataLoop *this = PINOS_DATA_LOOP (obj); - - pinos_log_debug ("data-loop %p: dispose", this); - stop_thread (this, FALSE); - - G_OBJECT_CLASS (pinos_data_loop_parent_class)->dispose (obj); -} - -static void -pinos_data_loop_finalize (GObject * obj) -{ - PinosDataLoop *this = PINOS_DATA_LOOP (obj); - - pinos_log_debug ("data-loop %p: finalize", this); - - G_OBJECT_CLASS (pinos_data_loop_parent_class)->finalize (obj); -} - -static void -pinos_data_loop_class_init (PinosDataLoopClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosDataLoopPrivate)); - - gobject_class->constructed = pinos_data_loop_constructed; - gobject_class->dispose = pinos_data_loop_dispose; - gobject_class->finalize = pinos_data_loop_finalize; -} - -static void -pinos_data_loop_init (PinosDataLoop * this) -{ - PinosDataLoopPrivate *priv = this->priv = PINOS_DATA_LOOP_GET_PRIVATE (this); - - pinos_log_debug ("data-loop %p: new", this); - - this->poll.size = sizeof (SpaPoll); - this->poll.info = NULL; - this->poll.add_item = do_add_item; - this->poll.update_item = do_update_item; - this->poll.remove_item = do_remove_item; - this->poll.invoke = do_invoke; - - spa_ringbuffer_init (&priv->buffer, DATAS_SIZE); -} - /** * pinos_data_loop_new: * @@ -470,11 +389,45 @@ pinos_data_loop_init (PinosDataLoop * this) PinosDataLoop * pinos_data_loop_new (void) { - return g_object_new (PINOS_TYPE_DATA_LOOP, NULL); + PinosDataLoopImpl *impl; + PinosDataLoop *this; + + impl = calloc (1, sizeof (PinosDataLoopImpl)); + this = &impl->this; + + pinos_log_debug ("data-loop %p: new", impl); + + this->poll.size = sizeof (SpaPoll); + this->poll.info = NULL; + this->poll.add_item = do_add_item; + this->poll.update_item = do_update_item; + this->poll.remove_item = do_remove_item; + this->poll.invoke = do_invoke; + + impl->fds[0].fd = eventfd (0, 0); + impl->fds[0].events = POLLIN | POLLPRI | POLLERR; + impl->fds[0].revents = 0; + impl->n_fds = 1; + + spa_ringbuffer_init (&impl->buffer, DATAS_SIZE); + + return this; +} + +void +pinos_data_loop_destroy (PinosDataLoop * loop) +{ + PinosDataLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosDataLoopImpl, this); + + pinos_log_debug ("data-loop %p: destroy", impl); + stop_thread (impl, FALSE); + close (impl->fds[0].fd); + free (impl); } bool pinos_data_loop_in_thread (PinosDataLoop *loop) { - return pthread_equal (loop->priv->thread, pthread_self()); + PinosDataLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosDataLoopImpl, this); + return pthread_equal (impl->thread, pthread_self()); } diff --git a/pinos/server/data-loop.h b/pinos/server/data-loop.h index 2a1fb151e..d8ba9fed6 100644 --- a/pinos/server/data-loop.h +++ b/pinos/server/data-loop.h @@ -25,47 +25,20 @@ G_BEGIN_DECLS #include -#include typedef struct _PinosDataLoop PinosDataLoop; -typedef struct _PinosDataLoopClass PinosDataLoopClass; -typedef struct _PinosDataLoopPrivate PinosDataLoopPrivate; - -#define PINOS_TYPE_DATA_LOOP (pinos_data_loop_get_type ()) -#define PINOS_IS_DATA_LOOP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_DATA_LOOP)) -#define PINOS_IS_DATA_LOOP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_DATA_LOOP)) -#define PINOS_DATA_LOOP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_DATA_LOOP, PinosDataLoopClass)) -#define PINOS_DATA_LOOP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_DATA_LOOP, PinosDataLoop)) -#define PINOS_DATA_LOOP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_DATA_LOOP, PinosDataLoopClass)) -#define PINOS_DATA_LOOP_CAST(obj) ((PinosDataLoop*)(obj)) -#define PINOS_DATA_LOOP_CLASS_CAST(klass) ((PinosDataLoopClass*)(klass)) /** * PinosDataLoop: * - * Pinos rt-loop class. + * Pinos rt-loop object. */ struct _PinosDataLoop { - GObject object; - SpaPoll poll; - - PinosDataLoopPrivate *priv; }; -/** - * PinosDataLoopClass: - * - * Pinos rt-loop class. - */ -struct _PinosDataLoopClass { - GObjectClass parent_class; -}; - -/* normal GObject stuff */ -GType pinos_data_loop_get_type (void); - PinosDataLoop * pinos_data_loop_new (void); +void pinos_data_loop_destroy (PinosDataLoop *loop); bool pinos_data_loop_in_thread (PinosDataLoop *loop); diff --git a/pinos/server/link.c b/pinos/server/link.c index 4a5dc7910..243e3176c 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -38,22 +38,13 @@ typedef struct { - PinosLink link; + PinosLink this; - PinosObject object; - PinosInterface ifaces[1]; - - PinosCore *core; - PinosDaemon *daemon; PinosLink1 *iface; - gchar *object_path; GPtrArray *format_filter; PinosProperties *properties; - PinosLinkState state; - GError *error; - PinosListener input_port_destroy; PinosListener input_async_complete; PinosListener output_port_destroy; @@ -65,60 +56,27 @@ typedef struct unsigned int n_buffers; } PinosLinkImpl; -static void -link_register_object (PinosLink *this) -{ - PinosLinkImpl *impl = (PinosLinkImpl *) this; - PinosObjectSkeleton *skel; - gchar *name; - - name = g_strdup_printf (PINOS_DBUS_OBJECT_LINK); - skel = pinos_object_skeleton_new (name); - g_free (name); - - pinos_object_skeleton_set_link1 (skel, impl->iface); - - g_free (impl->object_path); - impl->object_path = pinos_daemon_export_uniquely (impl->daemon, G_DBUS_OBJECT_SKELETON (skel)); - g_object_unref (skel); - - pinos_log_debug ("link %p: register object %s", this, impl->object_path); -} - -static void -link_unregister_object (PinosLink *this) -{ - PinosLinkImpl *impl = (PinosLinkImpl *) this; - - pinos_log_debug ("link %p: unregister object", this); - pinos_daemon_unexport (impl->daemon, impl->object_path); -} - static void pinos_link_update_state (PinosLink *link, PinosLinkState state) { - PinosLinkImpl *impl = (PinosLinkImpl *) link; - - if (state != impl->state) { - g_clear_error (&impl->error); + if (state != link->state) { + g_clear_error (&link->error); pinos_log_debug ("link %p: update state %s -> %s", link, - pinos_link_state_as_string (impl->state), + pinos_link_state_as_string (link->state), pinos_link_state_as_string (state)); - impl->state = state; - pinos_signal_emit (&link->notify_state, link, NULL); + link->state = state; + pinos_signal_emit (&link->core->link_state_changed, link); } } static void pinos_link_report_error (PinosLink *link, GError *error) { - PinosLinkImpl *impl = (PinosLinkImpl *) link; - - g_clear_error (&impl->error); - impl->error = error; - impl->state = PINOS_LINK_STATE_ERROR; + g_clear_error (&link->error); + link->error = error; + link->state = PINOS_LINK_STATE_ERROR; pinos_log_debug ("link %p: got error state %s", link, error->message); - pinos_signal_emit (&link->notify_state, link, NULL); + pinos_signal_emit (&link->core->link_state_changed, link); } static SpaResult @@ -152,7 +110,7 @@ again: goto error; } } - pinos_log_debug ("Try filter:"); + pinos_log_debug ("Try filter: %p", filter); spa_debug_format (filter); if ((res = spa_node_port_enum_formats (this->output->node->node, @@ -269,7 +227,7 @@ find_meta_enable (const SpaPortInfo *info, SpaMetaType type) static SpaResult do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) { - PinosLinkImpl *impl = (PinosLinkImpl *) this; + PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); SpaResult res; const SpaPortInfo *iinfo, *oinfo; SpaPortInfoFlags in_flags, out_flags; @@ -608,7 +566,6 @@ check_states (PinosLink *this, SpaResult res) { SpaNodeState in_state, out_state; - PinosLinkImpl *impl = (PinosLinkImpl *) this; if (res != SPA_RESULT_OK) { pinos_log_warn ("link %p: error: %d", this, res); @@ -641,34 +598,34 @@ again: return SPA_RESULT_OK; exit: - pinos_main_loop_defer (impl->core->main_loop, this, res, (PinosDeferFunc) check_states, this, NULL); + pinos_main_loop_defer (this->core->main_loop, this, res, (PinosDeferFunc) check_states, this, NULL); return res; } static void on_input_async_complete_notify (PinosListener *listener, - void *object, - void *data) + PinosNode *node, + uint32_t seq, + SpaResult res) { - PinosNode *node = object; - PinosNodeAsyncCompleteData *d = data; PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, input_async_complete); + PinosLink *this = &impl->this; - pinos_log_debug ("link %p: node %p async complete %d %d", impl, node, d->seq, d->res); - pinos_main_loop_defer_complete (impl->core->main_loop, impl, d->seq, d->res); + pinos_log_debug ("link %p: node %p async complete %d %d", impl, node, seq, res); + pinos_main_loop_defer_complete (this->core->main_loop, impl, seq, res); } static void on_output_async_complete_notify (PinosListener *listener, - void *object, - void *data) + PinosNode *node, + uint32_t seq, + SpaResult res) { - PinosNode *node = object; - PinosNodeAsyncCompleteData *d = data; PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, output_async_complete); + PinosLink *this = &impl->this; - pinos_log_debug ("link %p: node %p async complete %d %d", impl, node, d->seq, d->res); - pinos_main_loop_defer_complete (impl->core->main_loop, impl, d->seq, d->res); + pinos_log_debug ("link %p: node %p async complete %d %d", impl, node, seq, res); + pinos_main_loop_defer_complete (this->core->main_loop, impl, seq, res); } #if 0 @@ -704,7 +661,7 @@ on_property_notify (GObject *obj, static void on_port_unlinked (PinosPort *port, PinosLink *this, SpaResult res, gulong id) { - pinos_signal_emit (&this->port_unlinked, this, port); + pinos_signal_emit (&this->core->port_unlinked, this, port); if (this->input == NULL || this->output == NULL) pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED); @@ -734,7 +691,7 @@ on_port_destroy (PinosLink *this, } res = pinos_port_unlink (port, this); - pinos_main_loop_defer (impl->core->main_loop, + pinos_main_loop_defer (this->core->main_loop, port, res, (PinosDeferFunc) on_port_unlinked, @@ -744,73 +701,34 @@ on_port_destroy (PinosLink *this, static void on_input_port_destroy (PinosListener *listener, - void *object, - void *data) + PinosPort *port) { PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, input_port_destroy); - PinosPort *port = object; - on_port_destroy (&impl->link, port); + on_port_destroy (&impl->this, port); pinos_signal_remove (listener); } static void on_output_port_destroy (PinosListener *listener, - void *object, - void *data) + PinosPort *port) { PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, output_port_destroy); - PinosPort *port = object; - on_port_destroy (&impl->link, port); + on_port_destroy (&impl->this, port); pinos_signal_remove (listener); } -static void -link_destroy (PinosObject * object) -{ - PinosLinkImpl *impl = (PinosLinkImpl *) object; - PinosLink *this = &impl->link; - - pinos_log_debug ("link %p: destroy", this); - - if (this->input) - pinos_signal_remove (&impl->input_port_destroy); - if (this->output) - pinos_signal_remove (&impl->output_port_destroy); - - if (this->input) - pinos_port_unlink (this->input, this); - if (this->output) - pinos_port_unlink (this->output, this); - - link_unregister_object (this); - - pinos_main_loop_defer_cancel (impl->core->main_loop, this, 0); - - g_clear_object (&impl->daemon); - g_clear_object (&impl->iface); - g_free (impl->object_path); - - if (impl->allocated) - pinos_memblock_free (&impl->buffer_mem); - - pinos_registry_remove_object (&impl->core->registry, &this->object); - - free (object); -} - - -static bool -link_activate (PinosLink *this) +bool +pinos_link_activate (PinosLink *this) { spa_ringbuffer_init (&this->ringbuffer, SPA_N_ELEMENTS (this->queue)); check_states (this, NULL, SPA_RESULT_OK); return true; } -static bool -pinos_link_deactivate (PinosLink *this) +bool +pinos_pinos_link_deactivate (PinosLink *this) { spa_ringbuffer_clear (&this->ringbuffer); return true; @@ -818,60 +736,61 @@ pinos_link_deactivate (PinosLink *this) PinosLink * pinos_link_new (PinosCore *core, - PinosPort *input, PinosPort *output, + PinosPort *input, GPtrArray *format_filter, PinosProperties *properties) { PinosLinkImpl *impl; PinosLink *this; + PinosObjectSkeleton *skel; impl = calloc (1, sizeof (PinosLinkImpl)); - this = &impl->link; + this = &impl->this; pinos_log_debug ("link %p: new", this); + this->core = core; this->properties = properties; this->state = PINOS_LINK_STATE_INIT; this->input = input; this->output = output; - pinos_signal_init (&this->notify_state); - pinos_signal_init (&this->port_unlinked); - - this->activate = link_activate; - this->deactivate = link_deactivate; + pinos_signal_init (&this->destroy_signal); impl->format_filter = format_filter; - impl->iface = pinos_link1_skeleton_new (); - impl->input_port_destroy.notify = on_input_port_destroy; - pinos_signal_add (&this->input->object.destroy_signal, &impl->input_port_destroy); + pinos_signal_add (&this->input->destroy_signal, + &impl->input_port_destroy, + on_input_port_destroy); - impl->output_port_destroy.notify = on_output_port_destroy; - pinos_signal_add (&this->output->object.destroy_signal, &impl->output_port_destroy); + pinos_signal_add (&this->output->destroy_signal, + &impl->output_port_destroy, + on_output_port_destroy); - impl->input_async_complete.notify = on_input_async_complete_notify; - pinos_signal_add (&this->input->node->async_complete, &impl->input_async_complete); + pinos_signal_add (&this->input->node->async_complete, + &impl->input_async_complete, + on_input_async_complete_notify); - impl->output_async_complete.notify = on_output_async_complete_notify; - pinos_signal_add (&this->output->node->async_complete, &impl->output_async_complete); - - impl->ifaces[0].type = core->registry.uri.link; - impl->ifaces[0].iface = this; - - pinos_object_init (&this->object, - link_destroy, - 1, - impl->ifaces); - pinos_registry_add_object (&core->registry, &this->object); + pinos_signal_add (&this->output->node->async_complete, + &impl->output_async_complete, + on_output_async_complete_notify); pinos_log_debug ("link %p: constructed %p:%d -> %p:%d", impl, this->output->node, this->output->port, this->input->node, this->input->port); - link_register_object (this); - return &this->object; + spa_list_insert (core->link_list.prev, &this->list); + + impl->iface = pinos_link1_skeleton_new (); + skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_LINK); + pinos_object_skeleton_set_link1 (skel, impl->iface); + + this->global = pinos_core_add_global (core, + core->registry.uri.link, + this, + skel); + return this; } /** @@ -881,40 +800,34 @@ pinos_link_new (PinosCore *core, * Trigger removal of @link */ void -pinos_link_destroy (PinosLink *this) +pinos_link_destroy (PinosLink * this) { - pinos_log_debug ("link %p: destroy", this); - pinos_signal_emit (&this->object.destroy_signal, this, NULL); -} - -/** - * pinos_link_get_object_path: - * @link: a #PinosLink - * - * Get the object patch of @link - * - * Returns: the object path of @source. - */ -const gchar * -pinos_link_get_object_path (PinosLink *this) -{ - PinosLinkImpl *impl = (PinosLinkImpl *) this; - - g_return_val_if_fail (impl, NULL); - - return impl->object_path; -} - -PinosLinkState -pinos_link_get_state (PinosLink *this, - GError **error) -{ - PinosLinkImpl *impl = (PinosLinkImpl *) this; - - g_return_val_if_fail (impl, PINOS_LINK_STATE_ERROR); - - if (error) - *error = impl->error; - - return impl->state; + PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this); + + pinos_log_debug ("link %p: destroy", impl); + pinos_signal_emit (&this->destroy_signal, this); + + if (this->input) { + pinos_signal_remove (&impl->input_port_destroy); + pinos_signal_remove (&impl->input_async_complete); + pinos_port_unlink (this->input, this); + } + if (this->output) { + pinos_signal_remove (&impl->output_port_destroy); + pinos_signal_remove (&impl->output_async_complete); + pinos_port_unlink (this->output, this); + } + + pinos_main_loop_defer_cancel (this->core->main_loop, this, 0); + + pinos_core_remove_global (this->core, this->global); + + spa_list_remove (&this->list); + + g_clear_object (&impl->iface); + + if (impl->allocated) + pinos_memblock_free (&impl->buffer_mem); + + free (impl); } diff --git a/pinos/server/link.h b/pinos/server/link.h index ad3e12814..469af32d6 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -24,11 +24,11 @@ G_BEGIN_DECLS +typedef struct _PinosLink PinosLink; + #define PINOS_LINK_URI "http://pinos.org/ns/link" #define PINOS_LINK_PREFIX PINOS_LINK_URI "#" -typedef struct _PinosLink PinosLink; - #include #include @@ -43,33 +43,38 @@ typedef struct _PinosLink PinosLink; * Pinos link interface. */ struct _PinosLink { + PinosCore *core; + SpaList list; + PinosGlobal *global; + PinosProperties *properties; PinosLinkState state; GError *error; + PINOS_SIGNAL (destroy_signal, (PinosListener *, + PinosLink *)); + PinosPort *output; PinosPort *input; - PinosSignal port_unlinked; - PinosSignal notify_state; - uint32_t queue[64]; SpaRingbuffer ringbuffer; gint in_ready; - - bool (*activate) (PinosLink *link); - bool (*deactivate) (PinosLink *link); }; -PinosObject * pinos_link_new (PinosCore *core, - PinosPort *input, - PinosPort *output, - GPtrArray *format_filter, - PinosProperties *properties); -#define pinos_link_activate(l) (l)->activate(l) -#define pinos_link_deactivate(l) (l)->deactivate(l) +PinosLink * pinos_link_new (PinosCore *core, + PinosPort *output, + PinosPort *input, + GPtrArray *format_filter, + PinosProperties *properties); +void pinos_link_destroy (PinosLink *link); + +bool pinos_link_activate (PinosLink *link); +bool pinos_link_deactivate (PinosLink *link); + + const gchar * pinos_link_get_object_path (PinosLink *link); diff --git a/pinos/server/main-loop.c b/pinos/server/main-loop.c index 7f11bba39..a526e4faf 100644 --- a/pinos/server/main-loop.c +++ b/pinos/server/main-loop.c @@ -62,8 +62,6 @@ typedef struct { PinosMainLoop this; - PinosObject object; - SpaPoll poll; GMainContext *context; @@ -343,6 +341,7 @@ static void main_loop_quit (PinosMainLoop *loop) { PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + pinos_log_debug ("main-loop %p: quit", impl); g_main_loop_quit (impl->loop); } @@ -350,20 +349,10 @@ static void main_loop_run (PinosMainLoop *loop) { PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + pinos_log_debug ("main-loop %p: run", impl); g_main_loop_run (impl->loop); } -void -pinos_main_loop_destroy (PinosMainLoop *loop) -{ - PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); - - pinos_log_debug ("main-loop %p: destroy", impl); - - g_slice_free_chain (WorkItem, impl->free_list, list.next); - free (impl); -} - /** * pinos_main_loop_new: * @context: a #GMainContext or %NULL to use the default context @@ -418,3 +407,18 @@ pinos_main_loop_new (GMainContext *context) return this; } + +void +pinos_main_loop_destroy (PinosMainLoop *loop) +{ + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + + pinos_log_debug ("main-loop %p: destroy", impl); + + g_main_loop_unref (impl->loop); + + close (impl->fds[0].fd); + + g_slice_free_chain (WorkItem, impl->free_list, list.next); + free (impl); +} diff --git a/pinos/server/module.c b/pinos/server/module.c index cb440a49c..9b5d4bdcc 100644 --- a/pinos/server/module.c +++ b/pinos/server/module.c @@ -22,10 +22,10 @@ #include "config.h" #endif -#include -#include +#include #include "pinos/client/pinos.h" +#include "pinos/client/utils.h" #include "pinos/server/module.h" #define PINOS_SYMBOL_MODULE_INIT "pinos__module_init" @@ -34,38 +34,11 @@ typedef struct { PinosModule this; - PinosObject object; - PinosInterface ifaces[1]; - - GModule *module; + void *hnd; } PinosModuleImpl; - -static void -module_destroy (PinosObject * object) -{ - PinosModuleImpl *impl = SPA_CONTAINER_OF (object, PinosModuleImpl, object); - PinosModule *this = &impl->this; - - free (this->name); - g_module_close (impl->module); - free (impl); -} - -GQuark -pinos_module_error_quark (void) -{ - static GQuark quark = 0; - - if (quark == 0) { - quark = g_quark_from_static_string ("pinos_module_error"); - } - - return quark; -} - -static gchar * -find_module (const gchar * path, const gchar *name) +static char * +find_module (const char * path, const char *name) { gchar *filename; GDir *dir; @@ -113,7 +86,7 @@ find_module (const gchar * path, const gchar *name) * @core: a #PinosCore * @name: name of the module to load * @args: A string with arguments for the module - * @err: Return location for a #GError, or %NULL + * @err: Return location for an error string, or %NULL * * Load module with @name. * @@ -123,96 +96,95 @@ PinosModule * pinos_module_load (PinosCore *core, const gchar *name, const gchar *args, - GError **err) + char **err) { PinosModule *this; PinosModuleImpl *impl; - GModule *gmodule; - gchar *filename = NULL; - const gchar *module_dir; + void *hnd; + char *filename = NULL; + const char *module_dir; PinosModuleInitFunc init_func; - g_return_val_if_fail (name != NULL && name[0] != '\0', NULL); - g_return_val_if_fail (core, NULL); - - if (!g_module_supported ()) { - g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_LOADING, - "Dynamic module loading not supported"); - return NULL; - } - - module_dir = g_getenv ("PINOS_MODULE_DIR"); + module_dir = getenv ("PINOS_MODULE_DIR"); if (module_dir != NULL) { - gchar **l; - gint i; + char **l; + int i, n_paths; pinos_log_debug ("PINOS_MODULE_DIR set to: %s", module_dir); - l = g_strsplit (module_dir, G_SEARCHPATH_SEPARATOR_S, 0); + l = pinos_split_strv (module_dir, G_SEARCHPATH_SEPARATOR_S, 0, &n_paths); for (i = 0; l[i] != NULL; i++) { filename = find_module (l[i], name); if (filename != NULL) break; } - g_strfreev (l); + pinos_free_strv (l); } else { pinos_log_debug ("moduledir set to: %s", MODULEDIR); filename = find_module (MODULEDIR, name); } - if (filename == NULL) { - g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_NOT_FOUND, - "No module \"%s\" was found", name); - return NULL; - } + if (filename == NULL) + goto not_found; pinos_log_debug ("trying to load module: %s (%s)", name, filename); - gmodule = g_module_open (filename, G_MODULE_BIND_LOCAL); - g_free (filename); + hnd = dlopen (filename, RTLD_NOW | RTLD_LOCAL); + free (filename); - if (gmodule == NULL) { - g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_LOADING, - "Failed to open module: %s", g_module_error ()); - return NULL; - } + if (hnd == NULL) + goto open_failed; - if (!g_module_symbol (gmodule, PINOS_SYMBOL_MODULE_INIT, - (gpointer *) &init_func)) { - g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_LOADING, - "\"%s\" is not a pinos module", name); - g_module_close (gmodule); - return NULL; - } + if ((init_func = dlsym (hnd, PINOS_SYMBOL_MODULE_INIT)) == NULL) + goto no_pinos_module; impl = calloc (1, sizeof (PinosModuleImpl)); - impl->module = gmodule; + impl->hnd = hnd; this = &impl->this; this->name = strdup (name); this->core = core; - impl->ifaces[0].type = impl->core->registry.uri.module; - impl->ifaces[0].iface = this; - - - pinos_object_init (&impl->object, - module_destroy, - 1, - impl->ifaces); - - /* don't unload this module again */ - g_module_make_resident (gmodule); - - if (!init_func (this, (gchar *) args)) { - g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_INIT, - "\"%s\" failed to initialize", name); - module_destroy (this); - return NULL; - } + if (!init_func (this, (gchar *) args)) + goto init_failed; pinos_log_debug ("loaded module: %s", this->name); - return &this->object; + return this; + +not_found: + { + asprintf (err, "No module \"%s\" was found", name); + return NULL; + } +open_failed: + { + asprintf (err, "Failed to open module: %s", dlerror ()); + return NULL; + } +no_pinos_module: + { + asprintf (err, "\"%s\" is not a pinos module", name); + dlclose (hnd); + return NULL; + } +init_failed: + { + asprintf (err, "\"%s\" failed to initialize", name); + pinos_module_destroy (this); + return NULL; + } +} + +void +pinos_module_destroy (PinosModule *this) +{ + PinosModuleImpl *impl = SPA_CONTAINER_OF (this, PinosModuleImpl, this); + + pinos_signal_emit (&this->destroy_signal, this); + + free (this->name); + dlclose (impl->hnd); + free (impl); } diff --git a/pinos/server/module.h b/pinos/server/module.h index 17cbbc210..6b566473e 100644 --- a/pinos/server/module.h +++ b/pinos/server/module.h @@ -21,47 +21,20 @@ #ifndef __PINOS_MODULE_H__ #define __PINOS_MODULE_H__ -#include - -G_BEGIN_DECLS #include -#define PINOS_MODULE_URI "http://pinos.org/ns/module" -#define PINOS_MODULE_PREFIX PINOS_MODULE_URI "#" - typedef struct _PinosModule PinosModule; struct _PinosModule { + SpaList link; gchar *name; PinosCore *core; + + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosModule *module)); }; -GQuark pinos_module_error_quark (void); -/** - * PINOS_MODULE_ERROR: - * - * Pinos module error. - */ -#define PINOS_MODULE_ERROR pinos_module_error_quark () - -/** - * PinosModuleError: - * @PINOS_MODULE_ERROR_GENERIC: Generic module error. - * @PINOS_MODULE_ERROR_NOT_FOUND: Module could not be found. - * @PINOS_MODULE_ERROR_LOADING: Module could not be loaded. - * @PINOS_MODULE_ERROR_INIT: The module failed to initialize. - * - * Error codes for Pinos modules. - */ -typedef enum -{ - PINOS_MODULE_ERROR_GENERIC, - PINOS_MODULE_ERROR_NOT_FOUND, - PINOS_MODULE_ERROR_LOADING, - PINOS_MODULE_ERROR_INIT, -} PinosModuleError; - /** * PinosModuleInitFunc: * @module: A #PinosModule @@ -70,14 +43,15 @@ typedef enum * A module should provide an init function with this signature. This function * will be called when a module is loaded. * - * Returns: %TRUE on success, %FALSE otherwise + * Returns: %true on success, %false otherwise */ -typedef gboolean (*PinosModuleInitFunc) (PinosModule *module, gchar *args); +typedef bool (*PinosModuleInitFunc) (PinosModule *module, char *args); -PinosObject * pinos_module_load (PinosCore *core, +PinosModule * pinos_module_load (PinosCore *core, const gchar *name, const gchar *args, - GError **err); + char **err); +void pinos_module_destroy (PinosModule *module); G_END_DECLS diff --git a/pinos/server/node.c b/pinos/server/node.c index 6573af1f9..468702548 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -40,6 +40,7 @@ new_pinos_port (PinosNode *node, PinosDirection direction, uint32_t port) np->direction = direction; np->port = port; np->links = g_ptr_array_new (); + pinos_signal_init (&np->destroy_signal); return np; } @@ -52,16 +53,10 @@ free_node_port (PinosPort *np) typedef struct { - PinosNode node; - PinosObject object; - PinosInterface ifaces[1]; - - PinosCore *core; - PinosDaemon *daemon; - PinosNode1 *iface; + PinosNode this; PinosClient *client; - gchar *object_path; + PinosNode1 *iface; uint32_t seq; @@ -74,8 +69,6 @@ typedef struct GError *error; guint idle_timeout; - PinosDataLoop *data_loop; - struct { GPtrArray *links; } rt; @@ -87,7 +80,7 @@ static void init_complete (PinosNode *this); static void update_port_ids (PinosNode *node, gboolean create) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); uint32_t *input_port_ids, *output_port_ids; guint n_input_ports, n_output_ports, max_input_ports, max_output_ports; guint i; @@ -130,7 +123,7 @@ update_port_ids (PinosNode *node, gboolean create) impl->input_ports = g_list_insert_before (impl->input_ports, ports, np); if (!impl->async_init) - pinos_signal_emit (&node->port_added, node, np); + pinos_signal_emit (&node->core->port_added, node, np); i++; } else if (p) { GList *next; @@ -141,7 +134,7 @@ update_port_ids (PinosNode *node, gboolean create) ports = next; if (!impl->async_init) - pinos_signal_emit (&node->port_removed, node, p); + pinos_signal_emit (&node->core->port_removed, node, p); free_node_port (p); } else @@ -164,7 +157,7 @@ update_port_ids (PinosNode *node, gboolean create) impl->output_ports = g_list_insert_before (impl->output_ports, ports, np); if (!impl->async_init) - pinos_signal_emit (&node->port_added, node, np); + pinos_signal_emit (&node->core->port_added, node, np); i++; } else if (p) { GList *next; @@ -175,7 +168,7 @@ update_port_ids (PinosNode *node, gboolean create) ports = next; if (!impl->async_init) - pinos_signal_emit (&node->port_removed, node, p); + pinos_signal_emit (&node->core->port_removed, node, p); free_node_port (p); } else @@ -196,7 +189,7 @@ update_port_ids (PinosNode *node, gboolean create) for (i = 0; i < max_output_ports; i++) spa_node_port_set_output (node->node, i, &node->transport->outputs[i]); - pinos_signal_emit (&node->transport_changed, node, node->transport); + pinos_signal_emit (&node->transport_changed, node); } static SpaResult @@ -234,7 +227,7 @@ start_node (PinosNode *this) static SpaResult suspend_node (PinosNode *this) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); SpaResult res = SPA_RESULT_OK; GList *walk; @@ -326,7 +319,7 @@ static void on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) { PinosNode *this = user_data; - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); switch (event->type) { case SPA_NODE_EVENT_TYPE_INVALID: @@ -340,9 +333,8 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) SpaNodeEventAsyncComplete *ac = (SpaNodeEventAsyncComplete *) event; pinos_log_debug ("node %p: async complete event %d %d", this, ac->seq, ac->res); - if (!pinos_main_loop_defer_complete (impl->core->main_loop, this, ac->seq, ac->res)) { - PinosNodeAsyncCompleteData acd = { ac->seq, ac->res }; - pinos_signal_emit (&this->async_complete, this, &acd); + if (!pinos_main_loop_defer_complete (this->core->main_loop, this, ac->seq, ac->res)) { + pinos_signal_emit (&this->async_complete, this, ac->seq, ac->res); } break; } @@ -359,7 +351,7 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) continue; link->in_ready++; - spa_poll_invoke (&((PinosNodeImpl*)link->input->node)->data_loop->poll, + spa_poll_invoke (&link->input->node->data_loop->poll, do_read_link, SPA_ID_INVALID, sizeof (PinosLink *), @@ -395,7 +387,7 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) link->queue[offset] = po->buffer_id; spa_ringbuffer_write_advance (&link->ringbuffer, 1); - spa_poll_invoke (&((PinosNodeImpl*)link->input->node)->data_loop->poll, + spa_poll_invoke (&link->input->node->data_loop->poll, do_read_link, SPA_ID_INVALID, sizeof (PinosLink *), @@ -441,105 +433,41 @@ handle_remove (PinosNode1 *interface, gpointer user_data) { PinosNode *this = user_data; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); pinos_log_debug ("node %p: remove", this); - pinos_object_destroy (&this->object); + pinos_node_destroy (this); g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); return TRUE; } -static void -node_register_object (PinosNode *this) -{ - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); - PinosDaemon *daemon = impl->daemon; - PinosObjectSkeleton *skel; - - skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_NODE); - - pinos_object_skeleton_set_node1 (skel, impl->iface); - - g_free (impl->object_path); - impl->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); - g_object_unref (skel); - - pinos_log_debug ("node %p: register object %s, id %u", this, impl->object_path, impl->object.id); - - return; -} - -static void -node_unregister_object (PinosNode *this) -{ - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); - - pinos_log_debug ("node %p: unregister object %s", this, impl->object_path); - pinos_daemon_unexport (impl->daemon, impl->object_path); - g_clear_pointer (&impl->object_path, g_free); -} - -static void -on_property_notify (GObject *obj, - GParamSpec *pspec, - gpointer user_data) -{ - PinosNode *this = user_data; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); - - if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "client") == 0) { - if (impl->client) - pinos_node1_set_owner (impl->iface, pinos_client_get_object_path (impl->client)); - else - pinos_node1_set_owner (impl->iface, pinos_daemon_get_object_path (impl->daemon)); - } - if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "name") == 0) { - pinos_node1_set_name (impl->iface, this->name); - } - if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "properties") == 0) { - PinosProperties *props = this->properties; - pinos_node1_set_properties (impl->iface, props ? pinos_properties_to_variant (props) : NULL); - } -} - static void init_complete (PinosNode *this) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); + PinosProperties *props = this->properties; - update_port_ids (this, FALSE); + update_port_ids (this, false); pinos_log_debug ("node %p: init completed", this); - impl->async_init = FALSE; - on_property_notify (G_OBJECT (this), NULL, this); + impl->async_init = false; + + if (impl->client) + pinos_node1_set_owner (impl->iface, this->global->object_path); + else + pinos_node1_set_owner (impl->iface, "/"); + pinos_node1_set_name (impl->iface, this->name); + pinos_node1_set_properties (impl->iface, props ? pinos_properties_to_variant (props) : NULL); + pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED); } -static void -node_destroy (PinosObject * obj) +void +pinos_node_set_data_loop (PinosNode *node, + PinosDataLoop *loop) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (obj, PinosNodeImpl, object); - PinosNode *this = &impl->node; - - pinos_log_debug ("node %p: destroy", this); - pinos_node_set_state (this, PINOS_NODE_STATE_SUSPENDED); - - node_unregister_object (this); - - pinos_main_loop_defer_cancel (impl->core->main_loop, this, 0); - - pinos_registry_remove_object (&impl->core->registry, &impl->object); - - g_clear_object (&impl->daemon); - g_clear_object (&impl->iface); - g_clear_object (&impl->data_loop); - free (this->name); - g_clear_error (&impl->error); - if (this->properties) - pinos_properties_free (this->properties); - - free (obj); + node->data_loop = loop; + pinos_signal_emit (&node->loop_changed, node); } PinosNode * @@ -551,31 +479,26 @@ pinos_node_new (PinosCore *core, { PinosNodeImpl *impl; PinosNode *this; + PinosObjectSkeleton *skel; impl = calloc (1, sizeof (PinosNodeImpl)); - impl->core = core; - this = &impl->node; + this = &impl->this; + this->core = core; pinos_log_debug ("node %p: new", this); - impl->ifaces[0].type = impl->core->registry.uri.node; - impl->ifaces[0].iface = this; - - pinos_object_init (&impl->object, - node_destroy, - 1, - impl->ifaces); - this->name = strdup (name); this->properties = properties; this->node = node; this->clock = clock; - pinos_signal_init (&this->state_change); - pinos_signal_init (&this->port_added); - pinos_signal_init (&this->port_removed); + if (spa_node_set_event_callback (this->node, on_node_event, this) < 0) + pinos_log_warn ("node %p: error setting callback", this); + + pinos_signal_init (&this->destroy_signal); pinos_signal_init (&this->async_complete); pinos_signal_init (&this->transport_changed); + pinos_signal_init (&this->loop_changed); impl->iface = pinos_node1_skeleton_new (); g_signal_connect (impl->iface, "handle-remove", @@ -589,8 +512,6 @@ pinos_node_new (PinosCore *core, //g_signal_connect (this, "notify", (GCallback) on_property_notify, this); - pinos_registry_add_object (&impl->core->registry, &impl->object); - if (this->node->info) { unsigned int i; @@ -607,34 +528,53 @@ pinos_node_new (PinosCore *core, init_complete (this); } else { impl->async_init = TRUE; - pinos_main_loop_defer (impl->core->main_loop, + pinos_main_loop_defer (this->core->main_loop, this, SPA_RESULT_RETURN_ASYNC (0), (PinosDeferFunc) init_complete, NULL, NULL); } - node_register_object (this); + spa_list_insert (core->node_list.prev, &this->list); + skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_NODE); + pinos_object_skeleton_set_node1 (skel, impl->iface); + + this->global = pinos_core_add_global (core, + core->registry.uri.node, + this, + skel); return this; } /** - * pinos_node_get_daemon: + * pinos_node_destroy: * @node: a #PinosNode * - * Get the daemon of @node. - * - * Returns: the daemon of @node. + * Remove @node. This will stop the transfer on the node and + * free the resources allocated by @node. */ -PinosDaemon * -pinos_node_get_daemon (PinosNode *node) +void +pinos_node_destroy (PinosNode * this) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); - g_return_val_if_fail (node, NULL); + pinos_log_debug ("node %p: destroy", impl); + pinos_signal_emit (&this->destroy_signal, this); - return impl->daemon; + pinos_node_set_state (this, PINOS_NODE_STATE_SUSPENDED); + + spa_list_remove (&this->list); + pinos_core_remove_global (this->core, this->global); + + pinos_main_loop_defer_cancel (this->core->main_loop, this, 0); + + g_clear_object (&impl->iface); + free (this->name); + g_clear_error (&impl->error); + if (this->properties) + pinos_properties_free (this->properties); + free (impl); } /** @@ -648,47 +588,9 @@ pinos_node_get_daemon (PinosNode *node) PinosClient * pinos_node_get_client (PinosNode *node) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - - g_return_val_if_fail (node, NULL); - + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); return impl->client; } -/** - * pinos_node_get_object_path: - * @node: a #PinosNode - * - * Get the object path of @node. - * - * Returns: the object path of @node. - */ -const gchar * -pinos_node_get_object_path (PinosNode *node) -{ - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - - g_return_val_if_fail (node, NULL); - - return impl->object_path; -} - -/** - * pinos_node_destroy: - * @node: a #PinosNode - * - * Remove @node. This will stop the transfer on the node and - * free the resources allocated by @node. - */ -void -pinos_node_destroy (PinosNode *node) -{ - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - - g_return_if_fail (impl); - - pinos_log_debug ("node %p: destroy", impl); - pinos_object_destroy (&impl->object); -} /** * pinos_node_get_free_port: @@ -703,7 +605,7 @@ PinosPort * pinos_node_get_free_port (PinosNode *node, PinosDirection direction) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); guint free_port, n_ports, max_ports; GList *ports, *walk; PinosPort *port = NULL; @@ -751,7 +653,7 @@ do_add_link (SpaPoll *poll, void *user_data) { PinosNode *this = user_data; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosLink *link = ((PinosLink**)data)[0]; g_ptr_array_add (impl->rt.links, link); @@ -812,9 +714,9 @@ pinos_port_link (PinosPort *output_port, g_return_val_if_fail (input_port != NULL, NULL); output_node = output_port->node; - output_impl = SPA_CONTAINER_OF (output_node, PinosNodeImpl, node); + output_impl = SPA_CONTAINER_OF (output_node, PinosNodeImpl, this); input_node = input_port->node; - input_impl = SPA_CONTAINER_OF (input_node, PinosNodeImpl, node); + input_impl = SPA_CONTAINER_OF (input_node, PinosNodeImpl, this); pinos_log_debug ("port link %p:%u -> %p:%u", output_node, output_port->port, input_node, input_port->port); @@ -826,15 +728,13 @@ pinos_port_link (PinosPort *output_port, link = find_link (output_port, input_port); - if (link) { - g_object_ref (link); - } else { + if (link == NULL) { input_node->live = output_node->live; if (output_node->clock) input_node->clock = output_node->clock; pinos_log_debug ("node %p: clock %p, live %d", output_node, output_node->clock, output_node->live); - link = pinos_link_new (output_impl->core, + link = pinos_link_new (output_node->core, output_port, input_port, format_filter, @@ -846,13 +746,13 @@ pinos_port_link (PinosPort *output_port, output_impl->n_used_output_links++; input_impl->n_used_input_links++; - spa_poll_invoke (&output_impl->data_loop->poll, + spa_poll_invoke (&output_node->data_loop->poll, do_add_link, SPA_ID_INVALID, sizeof (PinosLink *), &link, output_node); - spa_poll_invoke (&input_impl->data_loop->poll, + spa_poll_invoke (&input_node->data_loop->poll, do_add_link, SPA_ID_INVALID, sizeof (PinosLink *), @@ -902,7 +802,7 @@ do_remove_link_done (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosLink *link = ((PinosLink**)data)[0]; pinos_log_debug ("port %p: finish unlink", port); @@ -931,7 +831,7 @@ do_remove_link_done (SpaPoll *poll, port->n_buffers = 0; } - pinos_main_loop_defer_complete (impl->core->main_loop, + pinos_main_loop_defer_complete (this->core->main_loop, port, seq, SPA_RESULT_OK); @@ -951,7 +851,7 @@ do_remove_link (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this); PinosLink *link = ((PinosLink**)data)[0]; SpaResult res; @@ -962,7 +862,7 @@ do_remove_link (SpaPoll *poll, g_ptr_array_remove_fast (impl->rt.links, link); - res = spa_poll_invoke (impl->core->main_loop->poll, + res = spa_poll_invoke (this->core->main_loop->poll, do_remove_link_done, seq, sizeof (PinosLink *), @@ -975,13 +875,13 @@ SpaResult pinos_port_unlink (PinosPort *port, PinosLink *link) { SpaResult res; - PinosNodeImpl *impl = (PinosNodeImpl*)port->node; + PinosNodeImpl *impl = SPA_CONTAINER_OF (port->node, PinosNodeImpl, this); pinos_log_debug ("port %p: start unlink %p", port, link); g_object_ref (link); g_object_ref (port->node); - res = spa_poll_invoke (&impl->data_loop->poll, + res = spa_poll_invoke (&port->node->data_loop->poll, do_remove_link, impl->seq++, sizeof (PinosLink *), @@ -1000,7 +900,6 @@ do_clear_buffers_done (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); SpaResult res; pinos_log_debug ("port %p: clear buffers finish", port); @@ -1012,7 +911,7 @@ do_clear_buffers_done (SpaPoll *poll, port->buffers = NULL; port->n_buffers = 0; - pinos_main_loop_defer_complete (impl->core->main_loop, + pinos_main_loop_defer_complete (this->core->main_loop, port, seq, res); @@ -1029,12 +928,11 @@ do_clear_buffers (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); SpaResult res; pinos_port_pause (port); - res = spa_poll_invoke (impl->core->main_loop->poll, + res = spa_poll_invoke (this->core->main_loop->poll, do_clear_buffers_done, seq, 0, NULL, @@ -1046,10 +944,10 @@ SpaResult pinos_port_clear_buffers (PinosPort *port) { SpaResult res; - PinosNodeImpl *impl = SPA_CONTAINER_OF (port->node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (port->node, PinosNodeImpl, this); pinos_log_debug ("port %p: clear buffers", port); - res = spa_poll_invoke (&impl->data_loop->poll, + res = spa_poll_invoke (&port->node->data_loop->poll, do_clear_buffers, impl->seq++, 0, NULL, @@ -1070,7 +968,7 @@ GList * pinos_node_get_ports (PinosNode *node, PinosDirection direction) { GList *ports; - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); g_return_val_if_fail (node, NULL); @@ -1085,7 +983,7 @@ pinos_node_get_ports (PinosNode *node, PinosDirection direction) static void remove_idle_timeout (PinosNode *node) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); if (impl->idle_timeout) { g_source_remove (impl->idle_timeout); @@ -1124,7 +1022,6 @@ SpaResult pinos_node_set_state (PinosNode *node, PinosNodeState state) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); SpaResult res = SPA_RESULT_OK; g_return_val_if_fail (node, SPA_RESULT_INVALID_ARGUMENTS); @@ -1159,7 +1056,7 @@ pinos_node_set_state (PinosNode *node, if (SPA_RESULT_IS_ERROR (res)) return res; - pinos_main_loop_defer (impl->core->main_loop, + pinos_main_loop_defer (node->core->main_loop, node, res, (PinosDeferFunc) on_state_complete, @@ -1181,22 +1078,20 @@ void pinos_node_update_state (PinosNode *node, PinosNodeState state) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); PinosNodeState old; g_return_if_fail (node); old = node->state; if (old != state) { - PinosNodeStateChangeData sc = { old, state }; - pinos_log_debug ("node %p: update state from %s -> %s", node, pinos_node_state_as_string (old), pinos_node_state_as_string (state)); node->state = state; pinos_node1_set_state (impl->iface, state); - pinos_signal_emit (&node->state_change, node, &sc); + pinos_signal_emit (&node->core->node_state_changed, node, old, state); } } @@ -1211,25 +1106,25 @@ void pinos_node_report_error (PinosNode *node, GError *error) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - PinosNodeStateChangeData sc; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); + PinosNodeState old; g_return_if_fail (node); g_clear_error (&impl->error); remove_idle_timeout (node); impl->error = error; - sc.old = node->state; - sc.state = node->state = PINOS_NODE_STATE_ERROR; + old = node->state; + node->state = PINOS_NODE_STATE_ERROR; pinos_log_debug ("node %p: got error state %s", node, error->message); pinos_node1_set_state (impl->iface, PINOS_NODE_STATE_ERROR); - pinos_signal_emit (&node->state_change, node, &sc); + pinos_signal_emit (&node->core->node_state_changed, node, old, node->state); } static gboolean idle_timeout (PinosNode *node) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); impl->idle_timeout = 0; pinos_log_debug ("node %p: idle timeout", node); @@ -1248,7 +1143,7 @@ idle_timeout (PinosNode *node) void pinos_node_report_idle (PinosNode *node) { - PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this); g_return_if_fail (node); diff --git a/pinos/server/node.h b/pinos/server/node.h index 734c58d3f..e63075ef1 100644 --- a/pinos/server/node.h +++ b/pinos/server/node.h @@ -27,11 +27,8 @@ G_BEGIN_DECLS #define PINOS_NODE_URI "http://pinos.org/ns/node" #define PINOS_NODE_PREFIX PINOS_NODE_URI "#" -#define PINOS_PORT_URI PINOS_NODE_PREFIX "Port" - typedef struct _PinosPort PinosPort; typedef struct _PinosNode PinosNode; -typedef struct _PinosNodeListener PinosNodeListener; #include @@ -42,9 +39,10 @@ typedef struct _PinosNodeListener PinosNodeListener; #include #include #include +#include struct _PinosPort { - PinosObject object; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosPort *)); PinosNode *node; PinosDirection direction; @@ -74,12 +72,16 @@ typedef struct { * Pinos node class. */ struct _PinosNode { + PinosCore *core; + SpaList list; + PinosGlobal *global; + char *name; PinosProperties *properties; PinosNodeState state; + SpaHandle *handle; SpaNode *node; - bool live; SpaClock *clock; @@ -87,12 +89,20 @@ struct _PinosNode { gboolean have_outputs; PinosTransport *transport; - PinosSignal transport_changed; + PINOS_SIGNAL (transport_changed, (PinosListener *listener, + PinosNode *object)); - PinosSignal state_change; - PinosSignal port_added; - PinosSignal port_removed; - PinosSignal async_complete; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, + PinosNode *object)); + + PINOS_SIGNAL (async_complete, (PinosListener *listener, + PinosNode *node, + uint32_t seq, + SpaResult res)); + + PinosDataLoop *data_loop; + PINOS_SIGNAL (loop_changed, (PinosListener *listener, + PinosNode *object)); PinosPort * (*get_free_port) (PinosNode *node, PinosDirection direction); @@ -103,37 +113,18 @@ struct _PinosNode { PinosNodeState state); }; -struct _PinosNodeListener { - void (*async_complete) (PinosNodeListener *listener, - PinosNode *node, - uint32_t seq, - SpaResult res); - - void (*state_change) (PinosNodeListener *listener, - PinosNode *node, - PinosNodeState old, - PinosNodeState state); - - void (*port_added) (PinosNodeListener *listener, - PinosNode *node, - PinosPort *port); - - void (*port_removed) (PinosNodeListener *listener, - PinosNode *node, - PinosPort *port); -}; - - - -PinosObject * pinos_node_new (PinosCore *core, +PinosNode * pinos_node_new (PinosCore *core, const char *name, SpaNode *node, SpaClock *clock, PinosProperties *properties); +void pinos_node_destroy (PinosNode *node); + + +void pinos_node_set_data_loop (PinosNode *node, + PinosDataLoop *loop); -PinosDaemon * pinos_node_get_daemon (PinosNode *node); PinosClient * pinos_node_get_client (PinosNode *node); -const gchar * pinos_node_get_object_path (PinosNode *node); PinosPort * pinos_node_get_free_port (PinosNode *node, PinosDirection direction); diff --git a/pinos/server/registry.c b/pinos/server/registry.c index 096c53839..f9dba5f67 100644 --- a/pinos/server/registry.c +++ b/pinos/server/registry.c @@ -34,13 +34,11 @@ pinos_registry_init (PinosRegistry *reg) { reg->map = pinos_id_map_get_default(); - reg->uri.core = spa_id_map_get_id (reg->map, PINOS_CORE_URI); reg->uri.daemon = spa_id_map_get_id (reg->map, PINOS_DAEMON_URI); reg->uri.registry = spa_id_map_get_id (reg->map, PINOS_REGISTRY_URI); reg->uri.node = spa_id_map_get_id (reg->map, PINOS_NODE_URI); - reg->uri.port = spa_id_map_get_id (reg->map, PINOS_PORT_URI); - reg->uri.link = spa_id_map_get_id (reg->map, PINOS_LINK_URI); reg->uri.node_factory = spa_id_map_get_id (reg->map, PINOS_NODE_FACTORY_URI); + reg->uri.link = spa_id_map_get_id (reg->map, PINOS_LINK_URI); reg->uri.client = spa_id_map_get_id (reg->map, PINOS_CLIENT_URI); reg->uri.spa_node = spa_id_map_get_id (reg->map, SPA_NODE_URI); @@ -48,9 +46,6 @@ pinos_registry_init (PinosRegistry *reg) reg->uri.spa_monitor = spa_id_map_get_id (reg->map, SPA_MONITOR_URI); pinos_map_init (®->objects, 512); - - pinos_signal_init (®->object_added); - pinos_signal_init (®->object_removed); } PinosObject * @@ -65,7 +60,7 @@ pinos_registry_iterate_objects (PinosRegistry *reg, idx = SPA_PTR_TO_INT (*state); *state = SPA_INT_TO_PTR (idx+1); o = pinos_map_lookup (®->objects, idx); - if (o != NULL && (type == SPA_ID_INVALID || o->type == type)) + if (o != NULL) break; } return o; diff --git a/pinos/server/registry.h b/pinos/server/registry.h index f8d8fd49c..560b4fc0d 100644 --- a/pinos/server/registry.h +++ b/pinos/server/registry.h @@ -35,15 +35,13 @@ extern "C" { typedef struct _PinosRegistry PinosRegistry; typedef struct { - uint32_t core; uint32_t daemon; uint32_t registry; uint32_t node; - uint32_t port; - uint32_t link; uint32_t node_factory; + uint32_t link; uint32_t client; - uint32_t monitor; + uint32_t spa_node; uint32_t spa_clock; uint32_t spa_monitor; @@ -55,35 +53,13 @@ typedef struct { * Pinos registry struct. */ struct _PinosRegistry { - PinosObject object; - SpaIDMap *map; PinosURI uri; PinosMap objects; - - PinosSignal object_added; - PinosSignal object_removed; }; void pinos_registry_init (PinosRegistry *reg); -static inline void -pinos_registry_add_object (PinosRegistry *reg, - PinosObject *object) -{ - object->id = pinos_map_insert_new (®->objects, object); - pinos_signal_emit (®->object_added, reg, object); -} - -static inline void -pinos_registry_remove_object (PinosRegistry *reg, - PinosObject *object) -{ - pinos_signal_emit (®->object_removed, reg, object); - pinos_map_remove (®->objects, object->id); -} - - PinosObject * pinos_registry_iterate_objects (PinosRegistry *reg, uint32_t type, void **state); diff --git a/spa/include/spa/defs.h b/spa/include/spa/defs.h index 3dcc30167..96c3fb6d6 100644 --- a/spa/include/spa/defs.h +++ b/spa/include/spa/defs.h @@ -34,12 +34,13 @@ typedef enum { SPA_RESULT_MODIFIED = 1, SPA_RESULT_OK = 0, SPA_RESULT_ERROR = -1, - SPA_RESULT_INACTIVE = -2, - SPA_RESULT_NO_FORMAT = -3, - SPA_RESULT_INVALID_COMMAND = -4, - SPA_RESULT_INVALID_PORT = -5, - SPA_RESULT_HAVE_ENOUGH_INPUT = -6, - SPA_RESULT_NEED_MORE_INPUT = -7, + SPA_RESULT_ERRNO = -2, + SPA_RESULT_INACTIVE = -3, + SPA_RESULT_NO_FORMAT = -4, + SPA_RESULT_INVALID_COMMAND = -5, + SPA_RESULT_INVALID_PORT = -6, + SPA_RESULT_HAVE_ENOUGH_INPUT = -7, + SPA_RESULT_NEED_MORE_INPUT = -8, SPA_RESULT_PORTS_CHANGED = -9, SPA_RESULT_FORMAT_CHANGED = -10, SPA_RESULT_PROPERTIES_CHANGED = -11, diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index f9b9e7c0d..a2e59f660 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -515,6 +515,7 @@ spa_v4l2_source_node_port_enum_formats (SpaNode *node, this = SPA_CONTAINER_OF (node, SpaV4l2Source, node); + spa_log_debug (this->log, "%p %d %d", this, direction, port_id); if (!CHECK_PORT (this, direction, port_id)) return SPA_RESULT_INVALID_PORT;