diff --git a/pinos/client/array.h b/pinos/client/array.h index ed981f269..050002f97 100644 --- a/pinos/client/array.h +++ b/pinos/client/array.h @@ -42,9 +42,9 @@ struct _PinosArray { #define pinos_array_get_unchecked(a,idx,t) pinos_array_get_unchecked_s(a,idx,sizeof(t),t) #define pinos_array_check_index(a,idx,t) pinos_array_check_index_s(a,idx,sizeof(t)) -#define pinos_array_for_each(pos, array) \ - for (pos = (array)->data; \ - (const char *) pos < ((const char *) (array)->data + (array)->size); \ +#define pinos_array_for_each(pos, array) \ + for (pos = (array)->data; \ + (const uint8_t *) pos < ((const uint8_t *) (array)->data + (array)->size); \ (pos)++) static inline void diff --git a/pinos/client/object.h b/pinos/client/object.h index 524ede53d..50e82d54d 100644 --- a/pinos/client/object.h +++ b/pinos/client/object.h @@ -29,6 +29,7 @@ extern "C" { #endif typedef struct _PinosObject PinosObject; +typedef struct _PinosInterface PinosInterface; typedef enum { PINOS_OBJECT_FLAG_NONE = 0, @@ -37,28 +38,53 @@ typedef enum { typedef void (*PinosDestroyFunc) (PinosObject *object); +struct _PinosInterface { + uint32_t type; + void *iface; +}; + struct _PinosObject { - uint32_t type; uint32_t id; - void *implementation; PinosObjectFlags flags; PinosDestroyFunc destroy; PinosSignal destroy_signal; + unsigned int n_interfaces; + PinosInterface *interfaces; }; static inline void pinos_object_init (PinosObject *object, - uint32_t type, - void *implementation, - PinosDestroyFunc destroy) + PinosDestroyFunc destroy, + unsigned int n_interfaces, + PinosInterface *interfaces) { - object->type = type; object->id = SPA_ID_INVALID; - object->implementation = implementation; + object->flags = 0; object->destroy = destroy; pinos_signal_init (&object->destroy_signal); + object->n_interfaces = n_interfaces; + object->interfaces = interfaces; } +static inline void * +pinos_object_get_interface (PinosObject *object, + uint32_t type) +{ + unsigned int i; + for (i = 0; i < object->n_interfaces; i++) + if (object->interfaces[i].type == type) + return object->interfaces[i].iface; + return NULL; +} + +static inline void +pinos_object_destroy (PinosObject *object) +{ + object->flags |= PINOS_OBJECT_FLAG_DESTROYING; + pinos_signal_emit (&object->destroy_signal, object, NULL); + if (object->destroy) + object->destroy (object); +} #ifdef __cplusplus } diff --git a/pinos/client/signal.h b/pinos/client/signal.h index 11ad8f1a9..913ad1080 100644 --- a/pinos/client/signal.h +++ b/pinos/client/signal.h @@ -31,8 +31,7 @@ typedef struct _PinosListener PinosListener; struct _PinosListener { SpaList link; - void (*notify) (PinosListener *listener, void *data); - void *user_data; + void (*notify) (PinosListener *listener, void *object, void *data); }; struct _PinosSignal { @@ -52,14 +51,21 @@ pinos_signal_add (PinosSignal *signal, spa_list_insert (signal->listeners.prev, &listener->link); } +static inline void +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, data); + l->notify (l, object, data); } #ifdef __cplusplus diff --git a/pinos/daemon/daemon-config.c b/pinos/daemon/daemon-config.c index 8e5040cbb..c4c766488 100644 --- a/pinos/daemon/daemon-config.c +++ b/pinos/daemon/daemon-config.c @@ -205,7 +205,7 @@ pinos_daemon_config_run_commands (PinosDaemonConfig * config, for (walk = config->commands; walk != NULL; walk = walk->next) { PinosCommand *command = (PinosCommand *)walk->data; - if (!pinos_command_run (command, daemon, &err)) { + 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); diff --git a/pinos/daemon/main.c b/pinos/daemon/main.c index 8d34c80cf..098c3a125 100644 --- a/pinos/daemon/main.c +++ b/pinos/daemon/main.c @@ -29,15 +29,17 @@ gint main (gint argc, gchar *argv[]) { + PinosCore *core; PinosDaemon *daemon; - GMainLoop *loop; + PinosMainLoop *loop; PinosDaemonConfig *config; PinosProperties *props; GError *err = NULL; pinos_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); + loop = pinos_main_loop_new (NULL); + core = pinos_core_new (loop); /* parse configuration */ config = pinos_daemon_config_new (); @@ -47,17 +49,18 @@ main (gint argc, gchar *argv[]) } props = pinos_properties_new ("test", "test", NULL); - daemon = pinos_daemon_new (props); + daemon = pinos_daemon_new (core, + props); pinos_daemon_config_run_commands (config, daemon); pinos_daemon_start (daemon); - g_main_loop_run (loop); + pinos_main_loop_run (loop); pinos_properties_free (props); - g_main_loop_unref (loop); - g_object_unref (daemon); + pinos_main_loop_destroy (loop); + pinos_daemon_destroy (daemon); return 0; } diff --git a/pinos/modules/spa/module.c b/pinos/modules/spa/module.c index 77d48abc7..974eba625 100644 --- a/pinos/modules/spa/module.c +++ b/pinos/modules/spa/module.c @@ -31,10 +31,10 @@ gboolean pinos__module_init (PinosModule *module, const gchar * args); G_MODULE_EXPORT gboolean pinos__module_init (PinosModule * module, G_GNUC_UNUSED const gchar * args) { - pinos_spa_alsa_monitor_new (module->daemon); - pinos_spa_v4l2_monitor_new (module->daemon); - pinos_spa_audiotestsrc_new (module->daemon, "audiotestsrc", NULL); - pinos_spa_videotestsrc_new (module->daemon, "videotestsrc", NULL); + 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); return TRUE; } diff --git a/pinos/modules/spa/spa-alsa-monitor.c b/pinos/modules/spa/spa-alsa-monitor.c index adbcf3d5f..8169ddab7 100644 --- a/pinos/modules/spa/spa-alsa-monitor.c +++ b/pinos/modules/spa/spa-alsa-monitor.c @@ -26,39 +26,28 @@ #include #include -#include - #include #include - #include +#include #include "spa-alsa-monitor.h" -#define PINOS_SPA_ALSA_MONITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_ALSA_MONITOR, PinosSpaALSAMonitorPrivate)) - -struct _PinosSpaALSAMonitorPrivate +typedef struct { - PinosDaemon *daemon; + PinosSpaALSAMonitor this; + + PinosObject object; + + PinosCore *core; SpaHandle *handle; - SpaMonitor *monitor; GHashTable *nodes; -}; - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_MONITOR, -}; - -G_DEFINE_TYPE (PinosSpaALSAMonitor, pinos_spa_alsa_monitor, G_TYPE_OBJECT); +} PinosSpaALSAMonitorImpl; static SpaResult -make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const char *name, const SpaDict *info) +make_handle (PinosCore *core, SpaHandle **handle, const char *lib, const char *name, const SpaDict *info) { SpaResult res; void *hnd, *state = NULL; @@ -85,7 +74,7 @@ make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const cha continue; *handle = g_malloc0 (factory->size); - if ((res = spa_handle_factory_init (factory, *handle, info, daemon->support, daemon->n_support)) < 0) { + 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; } @@ -97,7 +86,7 @@ make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const cha static void add_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) { - PinosSpaALSAMonitorPrivate *priv = this->priv; + PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaALSAMonitorImpl, this); SpaResult res; SpaHandle *handle; PinosNode *node; @@ -110,16 +99,16 @@ add_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) if ((res = spa_handle_factory_init (item->factory, handle, item->info, - priv->daemon->support, - priv->daemon->n_support)) < 0) { + 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, priv->daemon->registry.uri.spa_node, &node_iface)) < 0) { + 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, priv->daemon->registry.uri.spa_clock, &clock_iface)) < 0) { + 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; } @@ -135,29 +124,27 @@ add_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) item->info->items[i].value); } - node = g_object_new (PINOS_TYPE_NODE, - "daemon", priv->daemon, - "name", item->factory->name, - "node", node_iface, - "clock", clock_iface, - "properties", props, - NULL); + node = pinos_node_new (impl->core, + item->factory->name, + node_iface, + clock_iface, + props); - g_hash_table_insert (priv->nodes, g_strdup (item->id), node); + g_hash_table_insert (impl->nodes, strdup (item->id), node); } static void remove_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) { - PinosSpaALSAMonitorPrivate *priv = this->priv; + 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 (priv->nodes, item->id); + node = g_hash_table_lookup (impl->nodes, item->id); if (node) { - pinos_node_remove (node); - g_hash_table_remove (priv->nodes, item->id); + pinos_node_destroy (node); + g_hash_table_remove (impl->nodes, item->id); } } @@ -166,7 +153,8 @@ on_monitor_event (SpaMonitor *monitor, SpaMonitorEvent *event, void *user_data) { - PinosSpaALSAMonitor *this = user_data; + PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (monitor, PinosSpaALSAMonitorImpl, this); + PinosSpaALSAMonitor *this = &impl->this; switch (event->type) { case SPA_MONITOR_EVENT_TYPE_ADDED: @@ -192,143 +180,31 @@ on_monitor_event (SpaMonitor *monitor, } static void -monitor_constructed (GObject * object) +monitor_destroy (PinosObject * object) { - PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (object); - PinosSpaALSAMonitorPrivate *priv = this->priv; - SpaResult res; - void *state = NULL; + PinosSpaALSAMonitorImpl *impl = SPA_CONTAINER_OF (object, PinosSpaALSAMonitorImpl, object); + PinosSpaALSAMonitor *this = &impl->this; - pinos_log_debug ("spa-monitor %p: constructed", this); + pinos_log_debug ("spa-monitor %p: destroy", this); - G_OBJECT_CLASS (pinos_spa_alsa_monitor_parent_class)->constructed (object); + spa_handle_clear (impl->handle); + free (impl->handle); - while (TRUE) { - SpaMonitorItem *item; - - if ((res = spa_monitor_enum_items (priv->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 (priv->monitor, on_monitor_event, this); + g_hash_table_unref (impl->nodes); + free (impl); } -static void -monitor_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +PinosSpaALSAMonitor * +pinos_spa_alsa_monitor_new (PinosCore *core) { - PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (_object); - PinosSpaALSAMonitorPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_MONITOR: - g_value_set_pointer (value, priv->monitor); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -monitor_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (_object); - PinosSpaALSAMonitorPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_MONITOR: - priv->monitor = g_value_get_pointer (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -monitor_finalize (GObject * object) -{ - PinosSpaALSAMonitor *this = PINOS_SPA_ALSA_MONITOR (object); - PinosSpaALSAMonitorPrivate *priv = this->priv; - - pinos_log_debug ("spa-monitor %p: dispose", this); - spa_handle_clear (priv->handle); - g_free (priv->handle); - g_hash_table_unref (priv->nodes); - - G_OBJECT_CLASS (pinos_spa_alsa_monitor_parent_class)->finalize (object); -} - -static void -pinos_spa_alsa_monitor_class_init (PinosSpaALSAMonitorClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosSpaALSAMonitorPrivate)); - - gobject_class->constructed = monitor_constructed; - gobject_class->finalize = monitor_finalize; - gobject_class->set_property = monitor_set_property; - gobject_class->get_property = monitor_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The Daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_MONITOR, - g_param_spec_pointer ("monitor", - "Monitor", - "The SPA monitor", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} - -static void -pinos_spa_alsa_monitor_init (PinosSpaALSAMonitor * this) -{ - PinosSpaALSAMonitorPrivate *priv = this->priv = PINOS_SPA_ALSA_MONITOR_GET_PRIVATE (this); - - priv->nodes = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); -} - -GObject * -pinos_spa_alsa_monitor_new (PinosDaemon *daemon) -{ - GObject *monitor; + PinosSpaALSAMonitorImpl *impl; + PinosSpaALSAMonitor *this; SpaHandle *handle; SpaResult res; void *iface; + void *state = NULL; - if ((res = make_handle (daemon, &handle, + if ((res = make_handle (core, &handle, "build/spa/plugins/alsa/libspa-alsa.so", "alsa-monitor", NULL)) < 0) { @@ -338,16 +214,38 @@ pinos_spa_alsa_monitor_new (PinosDaemon *daemon) if ((res = spa_handle_get_interface (handle, - daemon->registry.uri.spa_monitor, + core->registry.uri.spa_monitor, &iface)) < 0) { - g_free (handle); - g_error ("can't get MONITOR interface: %d", res); + 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; - monitor = g_object_new (PINOS_TYPE_SPA_ALSA_MONITOR, - "daemon", daemon, - "monitor", iface, - NULL); - return monitor; + 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-alsa-monitor.h b/pinos/modules/spa/spa-alsa-monitor.h index a05a6e021..3875b9363 100644 --- a/pinos/modules/spa/spa-alsa-monitor.h +++ b/pinos/modules/spa/spa-alsa-monitor.h @@ -22,36 +22,20 @@ #include + +#include #include G_BEGIN_DECLS -#define PINOS_TYPE_SPA_ALSA_MONITOR (pinos_spa_alsa_monitor_get_type ()) -#define PINOS_IS_SPA_ALSA_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SPA_ALSA_MONITOR)) -#define PINOS_IS_SPA_ALSA_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SPA_ALSA_MONITOR)) -#define PINOS_SPA_ALSA_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SPA_ALSA_MONITOR, PinosSpaALSAMonitorClass)) -#define PINOS_SPA_ALSA_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SPA_ALSA_MONITOR, PinosSpaALSAMonitor)) -#define PINOS_SPA_ALSA_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SPA_ALSA_MONITOR, PinosSpaALSAMonitorClass)) -#define PINOS_SPA_ALSA_MONITOR_CAST(obj) ((PinosSpaALSAMonitor*)(obj)) -#define PINOS_SPA_ALSA_MONITOR_CLASS_CAST(klass) ((PinosSpaALSAMonitorClass*)(klass)) - typedef struct _PinosSpaALSAMonitor PinosSpaALSAMonitor; -typedef struct _PinosSpaALSAMonitorClass PinosSpaALSAMonitorClass; -typedef struct _PinosSpaALSAMonitorPrivate PinosSpaALSAMonitorPrivate; struct _PinosSpaALSAMonitor { - GObject object; - - PinosSpaALSAMonitorPrivate *priv; + SpaMonitor *monitor; }; -struct _PinosSpaALSAMonitorClass { - GObjectClass parent_class; -}; - -GType pinos_spa_alsa_monitor_get_type (void); - -GObject * pinos_spa_alsa_monitor_new (PinosDaemon *daemon); +PinosSpaALSAMonitor * pinos_spa_alsa_monitor_new (PinosCore *core); +void pinos_spa_alsa_monitor_destroy (PinosSpaALSAMonitor *monitor); G_END_DECLS diff --git a/pinos/modules/spa/spa-audiotestsrc.h b/pinos/modules/spa/spa-audiotestsrc.h index 4f2f993e2..d05c1e67f 100644 --- a/pinos/modules/spa/spa-audiotestsrc.h +++ b/pinos/modules/spa/spa-audiotestsrc.h @@ -27,32 +27,7 @@ G_BEGIN_DECLS -#define PINOS_TYPE_SPA_AUDIOTESTSRC (pinos_spa_audiotestsrc_get_type ()) -#define PINOS_IS_SPA_AUDIOTESTSRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC)) -#define PINOS_IS_SPA_AUDIOTESTSRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SPA_AUDIOTESTSRC)) -#define PINOS_SPA_AUDIOTESTSRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrcClass)) -#define PINOS_SPA_AUDIOTESTSRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrc)) -#define PINOS_SPA_AUDIOTESTSRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SPA_AUDIOTESTSRC, PinosSpaAudioTestSrcClass)) -#define PINOS_SPA_AUDIOTESTSRC_CAST(obj) ((PinosSpaAudioTestSrc*)(obj)) -#define PINOS_SPA_AUDIOTESTSRC_CLASS_CAST(klass) ((PinosSpaAudioTestSrcClass*)(klass)) - -typedef struct _PinosSpaAudioTestSrc PinosSpaAudioTestSrc; -typedef struct _PinosSpaAudioTestSrcClass PinosSpaAudioTestSrcClass; -typedef struct _PinosSpaAudioTestSrcPrivate PinosSpaAudioTestSrcPrivate; - -struct _PinosSpaAudioTestSrc { - PinosNode object; - - PinosSpaAudioTestSrcPrivate *priv; -}; - -struct _PinosSpaAudioTestSrcClass { - PinosNodeClass parent_class; -}; - -GType pinos_spa_audiotestsrc_get_type (void); - -PinosNode * pinos_spa_audiotestsrc_new (PinosDaemon *daemon, +PinosNode * pinos_spa_audiotestsrc_new (PinosCore *core, const gchar *name, PinosProperties *properties); diff --git a/pinos/modules/spa/spa-v4l2-monitor.c b/pinos/modules/spa/spa-v4l2-monitor.c index 563b1a7d0..5b4d1fcc4 100644 --- a/pinos/modules/spa/spa-v4l2-monitor.c +++ b/pinos/modules/spa/spa-v4l2-monitor.c @@ -29,44 +29,40 @@ #include #include #include +#include #include "spa-v4l2-monitor.h" -#define PINOS_SPA_V4L2_MONITOR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_V4L2_MONITOR, PinosSpaV4l2MonitorPrivate)) - -struct _PinosSpaV4l2MonitorPrivate +typedef struct { - PinosDaemon *daemon; + PinosSpaV4l2Monitor this; + + PinosObject object; + + PinosCore *core; SpaHandle *handle; - SpaMonitor *monitor; GHashTable *nodes; -}; - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_MONITOR, -}; - -G_DEFINE_TYPE (PinosSpaV4l2Monitor, pinos_spa_v4l2_monitor, G_TYPE_OBJECT); +} PinosSpaV4l2MonitorImpl; static SpaResult -make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const char *name, const SpaDict *info) +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()); + pinos_log_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"); + pinos_log_error ("can't find enum function"); return SPA_RESULT_ERROR; } @@ -75,15 +71,19 @@ make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const cha if ((res = enum_func (&factory, &state)) < 0) { if (res != SPA_RESULT_ENUM_END) - g_error ("can't enumerate factories: %d", res); + pinos_log_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, daemon->support, daemon->n_support)) < 0) { - g_error ("can't make factory instance: %d", res); + *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; @@ -94,7 +94,7 @@ make_handle (PinosDaemon *daemon, SpaHandle **handle, const char *lib, const cha static void add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) { - PinosSpaV4l2MonitorPrivate *priv = this->priv; + PinosSpaV4l2MonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaV4l2MonitorImpl, this); SpaResult res; SpaHandle *handle; PinosNode *node; @@ -108,17 +108,17 @@ add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) if ((res = spa_handle_factory_init (item->factory, handle, item->info, - priv->daemon->support, - priv->daemon->n_support)) < 0) { - g_error ("can't make factory instance: %d", res); + impl->core->support, + impl->core->n_support)) < 0) { + pinos_log_error ("can't make factory instance: %d", res); return; } - if ((res = spa_handle_get_interface (handle, priv->daemon->registry.uri.spa_node, &node_iface)) < 0) { - g_error ("can't get NODE interface: %d", res); + if ((res = spa_handle_get_interface (handle, impl->core->registry.uri.spa_node, &node_iface)) < 0) { + pinos_log_error ("can't get NODE interface: %d", res); return; } - if ((res = spa_handle_get_interface (handle, priv->daemon->registry.uri.spa_clock, &clock_iface)) < 0) { - g_error ("can't get CLOCK interface: %d", res); + if ((res = spa_handle_get_interface (handle, impl->core->registry.uri.spa_clock, &clock_iface)) < 0) { + pinos_log_error ("can't get CLOCK interface: %d", res); return; } @@ -133,29 +133,27 @@ add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) item->info->items[i].value); } - node = g_object_new (PINOS_TYPE_NODE, - "daemon", priv->daemon, - "name", item->factory->name, - "node", node_iface, - "clock", clock_iface, - "properties", props, - NULL); + node = pinos_node_new (impl->core, + item->factory->name, + node_iface, + clock_iface, + props); - g_hash_table_insert (priv->nodes, g_strdup (item->id), node); + g_hash_table_insert (impl->nodes, strdup (item->id), node); } static void remove_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) { - PinosSpaV4l2MonitorPrivate *priv = this->priv; + PinosSpaV4l2MonitorImpl *impl = SPA_CONTAINER_OF (this, PinosSpaV4l2MonitorImpl, this); PinosNode *node; pinos_log_debug ("v4l2-monitor %p: remove: \"%s\" (%s)", this, item->name, item->id); - node = g_hash_table_lookup (priv->nodes, item->id); + node = g_hash_table_lookup (impl->nodes, item->id); if (node) { - pinos_node_remove (node); - g_hash_table_remove (priv->nodes, item->id); + pinos_node_destroy (node); + g_hash_table_remove (impl->nodes, item->id); } } @@ -190,162 +188,76 @@ on_monitor_event (SpaMonitor *monitor, } static void -monitor_constructed (GObject * object) +monitor_destroy (PinosObject * object) { - PinosSpaV4l2Monitor *this = PINOS_SPA_V4L2_MONITOR (object); - PinosSpaV4l2MonitorPrivate *priv = this->priv; + 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; + SpaHandle *handle; SpaResult res; + void *iface; void *state = NULL; - pinos_log_debug ("spa-monitor %p: constructed", this); + 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); + return NULL; + } - G_OBJECT_CLASS (pinos_spa_v4l2_monitor_parent_class)->constructed (object); + 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 (PinosSpaV4l2MonitorImpl)); + impl->core = core; + + pinos_object_init (&impl->object, + core->registry.uri.monitor, + impl, + monitor_destroy); + + this = &impl->this; + this->monitor = iface; + + impl->nodes = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_object_unref); while (TRUE) { SpaMonitorItem *item; + SpaResult res; - if ((res = spa_monitor_enum_items (priv->monitor, &item, &state)) < 0) { + 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 (priv->monitor, on_monitor_event, this); -} - -static void -monitor_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosSpaV4l2Monitor *this = PINOS_SPA_V4L2_MONITOR (_object); - PinosSpaV4l2MonitorPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_MONITOR: - g_value_set_pointer (value, priv->monitor); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -monitor_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosSpaV4l2Monitor *this = PINOS_SPA_V4L2_MONITOR (_object); - PinosSpaV4l2MonitorPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_MONITOR: - priv->monitor = g_value_get_pointer (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -monitor_finalize (GObject * object) -{ - PinosSpaV4l2Monitor *this = PINOS_SPA_V4L2_MONITOR (object); - PinosSpaV4l2MonitorPrivate *priv = this->priv; - - pinos_log_debug ("spa-monitor %p: dispose", this); - spa_handle_clear (priv->handle); - g_free (priv->handle); - g_hash_table_unref (priv->nodes); - - G_OBJECT_CLASS (pinos_spa_v4l2_monitor_parent_class)->finalize (object); -} - -static void -pinos_spa_v4l2_monitor_class_init (PinosSpaV4l2MonitorClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosSpaV4l2MonitorPrivate)); - - gobject_class->constructed = monitor_constructed; - gobject_class->finalize = monitor_finalize; - gobject_class->set_property = monitor_set_property; - gobject_class->get_property = monitor_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The Daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_MONITOR, - g_param_spec_pointer ("monitor", - "Monitor", - "The SPA monitor", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} - -static void -pinos_spa_v4l2_monitor_init (PinosSpaV4l2Monitor * this) -{ - PinosSpaV4l2MonitorPrivate *priv = this->priv = PINOS_SPA_V4L2_MONITOR_GET_PRIVATE (this); - - priv->nodes = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - g_object_unref); -} - -GObject * -pinos_spa_v4l2_monitor_new (PinosDaemon *daemon) -{ - GObject *monitor; - SpaHandle *handle; - SpaResult res; - void *iface; - - if ((res = make_handle (daemon, - &handle, - "build/spa/plugins/v4l2/libspa-v4l2.so", - "v4l2-monitor", - NULL)) < 0) { - g_error ("can't create v4l2-monitor: %d", res); - return NULL; - } - - if ((res = spa_handle_get_interface (handle, - daemon->registry.uri.spa_monitor, - &iface)) < 0) { - g_free (handle); - g_error ("can't get MONITOR interface: %d", res); - return NULL; - } - - monitor = g_object_new (PINOS_TYPE_SPA_V4L2_MONITOR, - "daemon", daemon, - "monitor", iface, - NULL); - return monitor; + spa_monitor_set_event_callback (this->monitor, on_monitor_event, this); + + pinos_registry_add_object (&core->registry, &impl->object); + + return this; } diff --git a/pinos/modules/spa/spa-v4l2-monitor.h b/pinos/modules/spa/spa-v4l2-monitor.h index 008ed39c3..2837430aa 100644 --- a/pinos/modules/spa/spa-v4l2-monitor.h +++ b/pinos/modules/spa/spa-v4l2-monitor.h @@ -20,39 +20,23 @@ #ifndef __PINOS_SPA_V4L2_MONITOR_H__ #define __PINOS_SPA_V4L2_MONITOR_H__ -#include +#include -#include - -G_BEGIN_DECLS - -#define PINOS_TYPE_SPA_V4L2_MONITOR (pinos_spa_v4l2_monitor_get_type ()) -#define PINOS_IS_SPA_V4L2_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SPA_V4L2_MONITOR)) -#define PINOS_IS_SPA_V4L2_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SPA_V4L2_MONITOR)) -#define PINOS_SPA_V4L2_MONITOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SPA_V4L2_MONITOR, PinosSpaV4l2MonitorClass)) -#define PINOS_SPA_V4L2_MONITOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SPA_V4L2_MONITOR, PinosSpaV4l2Monitor)) -#define PINOS_SPA_V4L2_MONITOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SPA_V4L2_MONITOR, PinosSpaV4l2MonitorClass)) -#define PINOS_SPA_V4L2_MONITOR_CAST(obj) ((PinosSpaV4l2Monitor*)(obj)) -#define PINOS_SPA_V4L2_MONITOR_CLASS_CAST(klass) ((PinosSpaV4l2MonitorClass*)(klass)) +#ifdef __cplusplus +extern "C" { +#endif typedef struct _PinosSpaV4l2Monitor PinosSpaV4l2Monitor; -typedef struct _PinosSpaV4l2MonitorClass PinosSpaV4l2MonitorClass; -typedef struct _PinosSpaV4l2MonitorPrivate PinosSpaV4l2MonitorPrivate; struct _PinosSpaV4l2Monitor { - GObject object; - - PinosSpaV4l2MonitorPrivate *priv; + SpaMonitor *monitor; }; -struct _PinosSpaV4l2MonitorClass { - GObjectClass parent_class; -}; +PinosSpaV4l2Monitor * pinos_spa_v4l2_monitor_new (PinosCore *core); +void pinos_spa_v4l2_monitor_destroy (PinosSpaV4l2Monitor *monitor); -GType pinos_spa_v4l2_monitor_get_type (void); - -GObject * pinos_spa_v4l2_monitor_new (PinosDaemon *daemon); - -G_END_DECLS +#ifdef __cplusplus +} +#endif #endif /* __PINOS_SPA_V4L2_MONITOR_H__ */ diff --git a/pinos/modules/spa/spa-videotestsrc.h b/pinos/modules/spa/spa-videotestsrc.h index c8aae3706..6f1871215 100644 --- a/pinos/modules/spa/spa-videotestsrc.h +++ b/pinos/modules/spa/spa-videotestsrc.h @@ -25,36 +25,18 @@ #include #include +typedef struct _PinosSpaVideoTestSrc PinosSpaVideoTestSrc; + G_BEGIN_DECLS -#define PINOS_TYPE_SPA_VIDEOTESTSRC (pinos_spa_videotestsrc_get_type ()) -#define PINOS_IS_SPA_VIDEOTESTSRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_SPA_VIDEOTESTSRC)) -#define PINOS_IS_SPA_VIDEOTESTSRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_SPA_VIDEOTESTSRC)) -#define PINOS_SPA_VIDEOTESTSRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_SPA_VIDEOTESTSRC, PinosSpaVideoTestSrcClass)) -#define PINOS_SPA_VIDEOTESTSRC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_SPA_VIDEOTESTSRC, PinosSpaVideoTestSrc)) -#define PINOS_SPA_VIDEOTESTSRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_SPA_VIDEOTESTSRC, PinosSpaVideoTestSrcClass)) -#define PINOS_SPA_VIDEOTESTSRC_CAST(obj) ((PinosSpaVideoTestSrc*)(obj)) -#define PINOS_SPA_VIDEOTESTSRC_CLASS_CAST(klass) ((PinosSpaVideoTestSrcClass*)(klass)) - -typedef struct _PinosSpaVideoTestSrc PinosSpaVideoTestSrc; -typedef struct _PinosSpaVideoTestSrcClass PinosSpaVideoTestSrcClass; -typedef struct _PinosSpaVideoTestSrcPrivate PinosSpaVideoTestSrcPrivate; - struct _PinosSpaVideoTestSrc { - PinosNode object; - - PinosSpaVideoTestSrcPrivate *priv; + PinosNode *node; }; -struct _PinosSpaVideoTestSrcClass { - PinosNodeClass parent_class; -}; - -GType pinos_spa_videotestsrc_get_type (void); - -PinosNode * pinos_spa_videotestsrc_new (PinosDaemon *daemon, - const gchar *name, - PinosProperties *properties); +PinosSpaVideoTestSrc * pinos_spa_videotestsrc_new (PinosCore *core, + const gchar *name, + PinosProperties *properties); +void pinos_spa_videotestsrc_destroy (PinosSpaVideoTestSrc *src); G_END_DECLS diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index 309e5ac07..b348bbd5f 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -119,31 +119,22 @@ struct _SpaProxy uint32_t seq; }; -struct _PinosClientNodePrivate +typedef struct { - SpaProxy *proxy; + PinosClientNode this; - GSocket *sockets[2]; - GSocket *rtsockets[2]; -}; + PinosObject object; + PinosInterface ifaces[1]; -#define PINOS_CLIENT_NODE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_CLIENT_NODE, PinosClientNodePrivate)) + PinosCore *core; -G_DEFINE_TYPE (PinosClientNode, pinos_client_node, PINOS_TYPE_NODE); + SpaProxy proxy; -enum -{ - PROP_0, -}; + PinosListener transport_changed; -enum -{ - SIGNAL_NONE, - LAST_SIGNAL -}; - -//static guint signals[LAST_SIGNAL] = { 0 }; + int fd; + int rtfd; +} PinosClientNodeImpl; static void send_async_complete (SpaProxy *this, uint32_t seq, SpaResult res) @@ -1231,15 +1222,16 @@ proxy_init (SpaProxy *this, } static void -on_transport_changed (GObject *obj, - GParamSpec *pspec, - PinosClientNode *this) +on_transport_changed (PinosListener *listener, + void *object, + void *data) { - PinosNode *node = PINOS_NODE (obj); - PinosClientNodePrivate *priv = this->priv; + PinosClientNodeImpl *impl = SPA_CONTAINER_OF (listener, PinosClientNodeImpl, transport_changed); + PinosClientNode *this = &impl->this; + PinosNode *node = object; PinosTransportInfo info; PinosMessageTransportUpdate tu; - PinosConnection *conn = priv->proxy->conn; + PinosConnection *conn = impl->proxy.conn; pinos_transport_get_info (node->transport, &info); @@ -1265,108 +1257,33 @@ 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) + if (this->fds[0].fd != -1) { spa_poll_remove_item (this->main_loop, &this->poll); - if (this->rtfds[0].fd != -1) + close (this->fds[0].fd); + } + if (this->rtfds[0].fd != -1) { spa_poll_remove_item (this->data_loop, &this->rtpoll); + close (this->rtfds[0].fd); + } return SPA_RESULT_OK; } static void -pinos_client_node_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +client_node_destroy (PinosObject * object) { - PinosClientNode *node = PINOS_CLIENT_NODE (_object); + PinosClientNodeImpl *impl = (PinosClientNodeImpl *) object; + PinosClientNode *this = &impl->this; - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); - break; - } -} + pinos_log_debug ("client-node %p: destroy", this); -static void -pinos_client_node_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosClientNode *node = PINOS_CLIENT_NODE (_object); + proxy_clear (&impl->proxy); - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); - break; - } -} - -static void -pinos_client_node_dispose (GObject * object) -{ - PinosClientNode *this = PINOS_CLIENT_NODE (object); - PinosClientNodePrivate *priv = this->priv; - - pinos_log_debug ("client-node %p: dispose", this); - - proxy_clear (priv->proxy); - - G_OBJECT_CLASS (pinos_client_node_parent_class)->dispose (object); -} - -static void -pinos_client_node_finalize (GObject * object) -{ - PinosClientNode *this = PINOS_CLIENT_NODE (object); - PinosClientNodePrivate *priv = this->priv; - - pinos_log_debug ("client-node %p: finalize", this); - - g_clear_object (&priv->sockets[0]); - g_clear_object (&priv->sockets[1]); - g_clear_object (&priv->rtsockets[0]); - g_clear_object (&priv->rtsockets[1]); - - G_OBJECT_CLASS (pinos_client_node_parent_class)->finalize (object); -} - -static void -pinos_client_node_constructed (GObject * object) -{ - PinosClientNode *this = PINOS_CLIENT_NODE (object); - PinosClientNodePrivate *priv = this->priv; - - pinos_log_debug ("client-node %p: constructed", this); - - G_OBJECT_CLASS (pinos_client_node_parent_class)->constructed (object); - - g_signal_connect (object, "notify::transport", (GCallback) on_transport_changed, this); - - priv->proxy = (SpaProxy *) PINOS_NODE (this)->node; -} - -static void -pinos_client_node_class_init (PinosClientNodeClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosClientNodePrivate)); - - gobject_class->constructed = pinos_client_node_constructed; - gobject_class->dispose = pinos_client_node_dispose; - gobject_class->finalize = pinos_client_node_finalize; - gobject_class->set_property = pinos_client_node_set_property; - gobject_class->get_property = pinos_client_node_get_property; -} - -static void -pinos_client_node_init (PinosClientNode * node) -{ - node->priv = PINOS_CLIENT_NODE_GET_PRIVATE (node); - - pinos_log_debug ("client-node %p: new", node); + if (impl->fd != -1) + close (impl->fd); + if (impl->rtfd != -1) + close (impl->rtfd); + free (impl); } /** @@ -1380,30 +1297,44 @@ pinos_client_node_init (PinosClientNode * node) * * Returns: a new #PinosNode */ -PinosNode * -pinos_client_node_new (PinosDaemon *daemon, +PinosClientNode * +pinos_client_node_new (PinosCore *core, PinosClient *client, const gchar *name, PinosProperties *properties) { - PinosNode *node; - SpaProxy *p; + PinosClientNodeImpl *impl; + PinosClientNode *this; - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); + g_return_val_if_fail (core, NULL); - p = g_malloc0 (sizeof (SpaProxy)); - proxy_init (p, NULL, daemon->support, daemon->n_support); - node = g_object_new (PINOS_TYPE_CLIENT_NODE, - "daemon", daemon, - "client", client, - "name", name, - "properties", properties, - "node", p, - NULL); + impl = calloc (1, sizeof (PinosClientNodeImpl)); + impl->core = core; + this = &impl->this; + pinos_log_debug ("client-node %p: new", impl); - p->pnode = node; + impl->ifaces[0].type = impl->core->registry.uri.node; + impl->ifaces[0].iface = this; - return node; + pinos_object_init (&this->object, + client_node_destroy, + 1, + impl->ifaces); + + proxy_init (&impl->proxy, NULL, core->support, core->n_support); + + this->node = pinos_node_new (core, + name, + &impl->proxy.node, + NULL, + properties); + + impl->proxy.pnode = this->node; + + impl->transport_changed.notify = on_transport_changed; + pinos_signal_add (&this->node->transport_changed, &impl->transport_changed); + + return this; } /** @@ -1414,38 +1345,28 @@ pinos_client_node_new (PinosDaemon *daemon, * 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: a socket that can be used to send/receive buffers to node. */ -GSocket * +int pinos_client_node_get_socket_pair (PinosClientNode *this, GError **error) { - PinosClientNodePrivate *priv; + PinosClientNodeImpl *impl = (PinosClientNodeImpl *) this; - g_return_val_if_fail (PINOS_IS_CLIENT_NODE (this), FALSE); - priv = this->priv; + g_return_val_if_fail (this, -1); - if (priv->sockets[1] == NULL) { + if (impl->fd == -1) { int fd[2]; if (socketpair (AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0, fd) != 0) goto no_sockets; - priv->sockets[0] = g_socket_new_from_fd (fd[0], error); - if (priv->sockets[0] == NULL) - goto create_failed; - - priv->sockets[1] = g_socket_new_from_fd (fd[1], error); - if (priv->sockets[1] == NULL) - goto create_failed; - - priv->proxy->fds[0].fd = g_socket_get_fd (priv->sockets[0]); - priv->proxy->conn = pinos_connection_new (priv->proxy->fds[0].fd); - - spa_poll_add_item (priv->proxy->main_loop, &priv->proxy->poll); - + 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 g_object_ref (priv->sockets[1]); + return impl->fd; /* ERRORS */ no_sockets: @@ -1454,13 +1375,7 @@ no_sockets: G_IO_ERROR, g_io_error_from_errno (errno), "could not create socketpair: %s", strerror (errno)); - return NULL; - } -create_failed: - { - g_clear_object (&priv->sockets[0]); - g_clear_object (&priv->sockets[1]); - return NULL; + return -1; } } @@ -1474,34 +1389,25 @@ create_failed: * * Returns: a #GSocket that can be used to send/receive buffers to node. */ -GSocket * +int pinos_client_node_get_rtsocket_pair (PinosClientNode *this, GError **error) { - PinosClientNodePrivate *priv; + PinosClientNodeImpl *impl = (PinosClientNodeImpl *) this; - g_return_val_if_fail (PINOS_IS_CLIENT_NODE (this), FALSE); - priv = this->priv; + g_return_val_if_fail (this, -1); - if (priv->rtsockets[1] == NULL) { + if (impl->fd == -1) { int fd[2]; if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) != 0) goto no_sockets; - priv->rtsockets[0] = g_socket_new_from_fd (fd[0], error); - if (priv->rtsockets[0] == NULL) - goto create_failed; - - priv->rtsockets[1] = g_socket_new_from_fd (fd[1], error); - if (priv->rtsockets[1] == NULL) - goto create_failed; - - priv->proxy->rtfds[0].fd = g_socket_get_fd (priv->rtsockets[0]); - - spa_poll_add_item (priv->proxy->data_loop, &priv->proxy->rtpoll); + impl->proxy.rtfds[0].fd = fd[0]; + spa_poll_add_item (impl->proxy.data_loop, &impl->proxy.rtpoll); + impl->rtfd = fd[1]; } - return g_object_ref (priv->rtsockets[1]); + return impl->rtfd; /* ERRORS */ no_sockets: @@ -1510,12 +1416,6 @@ no_sockets: G_IO_ERROR, g_io_error_from_errno (errno), "could not create socketpair: %s", strerror (errno)); - return NULL; - } -create_failed: - { - g_clear_object (&priv->rtsockets[0]); - g_clear_object (&priv->rtsockets[1]); - return NULL; + return -1; } } diff --git a/pinos/server/client-node.h b/pinos/server/client-node.h index 57fd3a482..97da68405 100644 --- a/pinos/server/client-node.h +++ b/pinos/server/client-node.h @@ -26,51 +26,32 @@ G_BEGIN_DECLS -#define PINOS_TYPE_CLIENT_NODE (pinos_client_node_get_type ()) -#define PINOS_IS_CLIENT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_CLIENT_NODE)) -#define PINOS_IS_CLIENT_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_CLIENT_NODE)) -#define PINOS_CLIENT_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_CLIENT_NODE, PinosClientNodeClass)) -#define PINOS_CLIENT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_CLIENT_NODE, PinosClientNode)) -#define PINOS_CLIENT_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_CLIENT_NODE, PinosClientNodeClass)) -#define PINOS_CLIENT_NODE_CAST(obj) ((PinosClientNode*)(obj)) -#define PINOS_CLIENT_NODE_CLASS_CAST(klass) ((PinosClientNodeClass*)(klass)) +#define PINOS_CLIENT_NODE_URI "http://pinos.org/ns/client-node" +#define PINOS_CLIENT_NODE_PREFIX PINOS_CLIENT_NODE_URI "#" typedef struct _PinosClientNode PinosClientNode; -typedef struct _PinosClientNodeClass PinosClientNodeClass; -typedef struct _PinosClientNodePrivate PinosClientNodePrivate; /** * PinosClientNode: * - * Pinos client node object class. + * Pinos client node interface */ struct _PinosClientNode { - PinosNode object; + PinosNode *node; - PinosClientNodePrivate *priv; + int (*get_ctrl_socket) (PinosClientNode *node, + GError **error); + int (*get_data_socket) (PinosClientNode *node, + GError **error); }; -/** - * PinosClientNodeClass: - * - * Pinos client node object class. - */ -struct _PinosClientNodeClass { - PinosNodeClass parent_class; -}; - -/* normal GObject stuff */ -GType pinos_client_node_get_type (void); - -PinosNode * pinos_client_node_new (PinosDaemon *daemon, +PinosObject * pinos_client_node_new (PinosCore *core, PinosClient *client, const gchar *name, PinosProperties *properties); -GSocket * pinos_client_node_get_socket_pair (PinosClientNode *node, - GError **error); -GSocket * pinos_client_node_get_rtsocket_pair (PinosClientNode *node, - GError **error); +#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__) G_END_DECLS diff --git a/pinos/server/client.c b/pinos/server/client.c index a0c1fa4d3..aebfef407 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -24,43 +24,19 @@ #include "pinos/dbus/org-pinos.h" -struct _PinosClientPrivate +typedef struct { + PinosClient client; + PinosObject object; + PinosInterface ifaces[1]; PinosDaemon *daemon; - PinosClient1 *iface; guint id; - gchar *sender; + PinosClient1 *iface; gchar *object_path; - PinosProperties *properties; GList *objects; -}; - -#define PINOS_CLIENT_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_CLIENT, PinosClientPrivate)) - -G_DEFINE_TYPE (PinosClient, pinos_client, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_SENDER, - PROP_OBJECT_PATH, - PROP_PROPERTIES, -}; - -enum -{ - SIGNAL_APPEARED, - SIGNAL_VANISHED, - SIGNAL_REMOVE, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - +} PinosClientImpl; static void client_name_appeared_handler (GDBusConnection *connection, @@ -68,11 +44,11 @@ client_name_appeared_handler (GDBusConnection *connection, const gchar *name_owner, gpointer user_data) { - PinosClient *client = user_data; + PinosClientImpl *impl = user_data; + PinosClient *client = &impl->client; pinos_log_debug ("client %p: appeared %s %s", client, name, name_owner); - - g_signal_emit (client, signals[SIGNAL_APPEARED], 0, NULL); + pinos_signal_emit (&client->appeared, client, NULL); } static void @@ -80,274 +56,124 @@ client_name_vanished_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { - PinosClient *client = user_data; - PinosClientPrivate *priv = client->priv; + PinosClientImpl *impl = user_data; + PinosClient *client = &impl->client; pinos_log_debug ("client %p: vanished %s", client, name); - g_signal_emit (client, signals[SIGNAL_VANISHED], 0, NULL); - g_bus_unwatch_name (priv->id); + pinos_signal_emit (&client->vanished, client, NULL); + g_bus_unwatch_name (impl->id); } static void client_watch_name (PinosClient *client) { - PinosClientPrivate *priv = client->priv; - GDBusConnection *connection; + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + GDBusConnection *connection = NULL; - g_object_get (priv->daemon, "connection", &connection, NULL); +// g_object_get (impl->daemon, "connection", &connection, NULL); - priv->id = g_bus_watch_name_on_connection (connection, - priv->sender, + impl->id = g_bus_watch_name_on_connection (connection, + client->sender, G_BUS_NAME_WATCHER_FLAGS_NONE, client_name_appeared_handler, client_name_vanished_handler, - client, - (GDestroyNotify) g_object_unref); -} - -static void -pinos_client_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosClient *client = PINOS_CLIENT (_object); - PinosClientPrivate *priv = client->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_SENDER: - g_value_set_string (value, priv->sender); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec); - break; - } -} - -static void -pinos_client_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosClient *client = PINOS_CLIENT (_object); - PinosClientPrivate *priv = client->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_SENDER: - priv->sender = g_value_dup_string (value); - pinos_client1_set_sender (priv->iface, priv->sender); - break; - - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - pinos_client1_set_properties (priv->iface, priv->properties ? - pinos_properties_to_variant (priv->properties) : NULL); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (client, prop_id, pspec); - break; - } + impl, + (GDestroyNotify) pinos_client_destroy); } static void client_register_object (PinosClient *client) { - PinosClientPrivate *priv = client->priv; - PinosDaemon *daemon = priv->daemon; + 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, priv->iface); + pinos_object_skeleton_set_client1 (skel, impl->iface); - g_free (priv->object_path); - priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); + 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, priv->object_path); + pinos_log_debug ("client %p: register %s", client, impl->object_path); } static void client_unregister_object (PinosClient *client) { - PinosClientPrivate *priv = client->priv; - PinosDaemon *daemon = priv->daemon; + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + PinosDaemon *daemon = impl->daemon; pinos_log_debug ("client %p: unregister", client); - pinos_daemon_unexport (daemon, priv->object_path); + pinos_daemon_unexport (daemon, impl->object_path); } static void -pinos_client_dispose (GObject * object) +client_destroy (PinosObject * object) { - PinosClient *client = PINOS_CLIENT (object); - PinosClientPrivate *priv = client->priv; + PinosClientImpl *impl = SPA_CONTAINER_OF (object, PinosClientImpl, object); + PinosClient *client = &impl->client; GList *copy; - pinos_log_debug ("client %p: dispose", client); - copy = g_list_copy (priv->objects); - g_list_free_full (copy, g_object_unref); - g_list_free (priv->objects); + 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); - G_OBJECT_CLASS (pinos_client_parent_class)->dispose (object); -} + free (client->sender); + if (client->properties) + pinos_properties_free (client->properties); -static void -pinos_client_finalize (GObject * object) -{ - PinosClient *client = PINOS_CLIENT (object); - PinosClientPrivate *priv = client->priv; - - pinos_log_debug ("client %p: finalize", client); - - pinos_registry_remove_object (&priv->daemon->registry, &client->object); - - g_clear_object (&priv->daemon); - g_clear_object (&priv->iface); - g_free (priv->sender); - g_free (priv->object_path); - if (priv->properties) - pinos_properties_free (priv->properties); - - G_OBJECT_CLASS (pinos_client_parent_class)->finalize (object); -} - -static void -pinos_client_constructed (GObject * object) -{ - PinosClient *client = PINOS_CLIENT (object); - PinosClientPrivate *priv = client->priv; - - pinos_log_debug ("client %p: constructed", client); - - pinos_object_init (&client->object, - priv->daemon->registry.uri.client, - client, - NULL); - - pinos_registry_add_object (&priv->daemon->registry, &client->object); - - client_watch_name (client); - client_register_object (client); - - G_OBJECT_CLASS (pinos_client_parent_class)->constructed (object); + g_clear_object (&impl->iface); + free (impl->object_path); + free (object); } static void -pinos_client_class_init (PinosClientClass * klass) +client_add_object (PinosClient *client, + PinosObject *object) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - g_type_class_add_private (klass, sizeof (PinosClientPrivate)); + g_return_if_fail (client); + g_return_if_fail (object); - gobject_class->constructed = pinos_client_constructed; - gobject_class->dispose = pinos_client_dispose; - gobject_class->finalize = pinos_client_finalize; - gobject_class->set_property = pinos_client_set_property; - gobject_class->get_property = pinos_client_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_SENDER, - g_param_spec_string ("sender", - "Sender", - "The sender", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_OBJECT_PATH, - g_param_spec_string ("object-path", - "Object Path", - "The object path", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "Client properties", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - signals[SIGNAL_APPEARED] = g_signal_new ("appeared", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 0, - G_TYPE_NONE); - signals[SIGNAL_VANISHED] = g_signal_new ("vanished", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 0, - G_TYPE_NONE); - signals[SIGNAL_REMOVE] = g_signal_new ("remove", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 0, - G_TYPE_NONE); + impl->objects = g_list_prepend (impl->objects, object); } static void -pinos_client_init (PinosClient * client) +client_remove_object (PinosClient *client, + PinosObject *object) { - PinosClientPrivate *priv = client->priv = PINOS_CLIENT_GET_PRIVATE (client); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - priv->iface = pinos_client1_skeleton_new (); - pinos_log_debug ("client %p: new", client); + g_return_if_fail (client); + g_return_if_fail (object); + + impl->objects = g_list_remove (impl->objects, object); + pinos_object_destroy (object); +} + +static bool +client_has_object (PinosClient *client, + PinosObject *object) +{ + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); + GList *found; + + g_return_val_if_fail (client, false); + g_return_val_if_fail (object, false); + + found = g_list_find (impl->objects, object); + + return found != NULL; } /** @@ -362,93 +188,57 @@ pinos_client_init (PinosClient * client) * Returns: a new #PinosClient */ PinosClient * -pinos_client_new (PinosDaemon *daemon, +pinos_client_new (PinosCore *core, const gchar *sender, PinosProperties *properties) { - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); + PinosClient *client; + PinosClientImpl *impl; - return g_object_new (PINOS_TYPE_CLIENT, "daemon", daemon, - "sender", sender, - "properties", properties, - NULL); + 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); + + pinos_log_debug ("client %p: new", impl); + + impl->iface = pinos_client1_skeleton_new (); + + client_watch_name (client); + client_register_object (client); + + pinos_registry_add_object (&client->core->registry, &impl->object); + + return client; } /** - * pinos_client_remove: + * pinos_client_destroy: * @client: a #PinosClient * * Trigger removal of @client */ void -pinos_client_remove (PinosClient *client) +pinos_client_destroy (PinosClient *client) { - g_return_if_fail (PINOS_IS_CLIENT (client)); + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - pinos_log_debug ("client %p: remove", client); - g_signal_emit (client, signals[SIGNAL_REMOVE], 0, NULL); -} + g_return_if_fail (client); -void -pinos_client_add_object (PinosClient *client, - GObject *object) -{ - PinosClientPrivate *priv; - - g_return_if_fail (PINOS_IS_CLIENT (client)); - g_return_if_fail (G_IS_OBJECT (object)); - priv = client->priv; - - priv->objects = g_list_prepend (priv->objects, g_object_ref (object)); -} - -void -pinos_client_remove_object (PinosClient *client, - GObject *object) -{ - PinosClientPrivate *priv; - - g_return_if_fail (PINOS_IS_CLIENT (client)); - g_return_if_fail (G_IS_OBJECT (object)); - priv = client->priv; - - priv->objects = g_list_remove (priv->objects, object); - g_object_unref (object); -} - -gboolean -pinos_client_has_object (PinosClient *client, - GObject *object) -{ - PinosClientPrivate *priv; - GList *found; - - g_return_val_if_fail (PINOS_IS_CLIENT (client), FALSE); - g_return_val_if_fail (G_IS_OBJECT (object), FALSE); - priv = client->priv; - - found = g_list_find (priv->objects, object); - - return found != NULL; -} - -/** - * pinos_client_get_sender: - * @client: a #PinosClient - * - * Get the sender of @client. - * - * Returns: the sender of @client - */ -const gchar * -pinos_client_get_sender (PinosClient *client) -{ - PinosClientPrivate *priv; - - g_return_val_if_fail (PINOS_IS_CLIENT (client), NULL); - priv = client->priv; - - return priv->sender; + pinos_log_debug ("client %p: destroy", client); + pinos_object_destroy (&impl->object); } /** @@ -462,10 +252,9 @@ pinos_client_get_sender (PinosClient *client) const gchar * pinos_client_get_object_path (PinosClient *client) { - PinosClientPrivate *priv; + PinosClientImpl *impl = SPA_CONTAINER_OF (client, PinosClientImpl, client); - g_return_val_if_fail (PINOS_IS_CLIENT (client), NULL); - priv = client->priv; + g_return_val_if_fail (client, NULL); - return priv->object_path; + return impl->object_path; } diff --git a/pinos/server/client.h b/pinos/server/client.h index 0501a54ca..3b633dd2b 100644 --- a/pinos/server/client.h +++ b/pinos/server/client.h @@ -28,61 +28,42 @@ G_BEGIN_DECLS #define PINOS_CLIENT_PREFIX PINOS_CLIENT_URI "#" typedef struct _PinosClient PinosClient; -typedef struct _PinosClientClass PinosClientClass; -typedef struct _PinosClientPrivate PinosClientPrivate; #include #include -#define PINOS_TYPE_CLIENT (pinos_client_get_type ()) -#define PINOS_IS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_CLIENT)) -#define PINOS_IS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_CLIENT)) -#define PINOS_CLIENT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_CLIENT, PinosClientClass)) -#define PINOS_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_CLIENT, PinosClient)) -#define PINOS_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_CLIENT, PinosClientClass)) -#define PINOS_CLIENT_CAST(obj) ((PinosClient*)(obj)) -#define PINOS_CLIENT_CLASS_CAST(klass) ((PinosClientClass*)(klass)) - /** * PinosClient: * * Pinos client object class. */ struct _PinosClient { - GObject obj; + PinosCore *core; - PinosObject object; + char *sender; - PinosClientPrivate *priv; + 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); }; -/** - * PinosClientClass: - * - * Pinos client object class. - */ -struct _PinosClientClass { - GObjectClass parent_class; -}; - -/* normal GObject stuff */ -GType pinos_client_get_type (void); - -PinosClient * pinos_client_new (PinosDaemon *daemon, +PinosObject * pinos_client_new (PinosCore *core, const gchar *sender, PinosProperties *properties); -void pinos_client_remove (PinosClient *client); - -const gchar * pinos_client_get_sender (PinosClient *client); const gchar * pinos_client_get_object_path (PinosClient *client); -void pinos_client_add_object (PinosClient *client, - GObject *object); -void pinos_client_remove_object (PinosClient *client, - GObject *object); -gboolean pinos_client_has_object (PinosClient *client, - GObject *object); +#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 diff --git a/pinos/server/command.c b/pinos/server/command.c index f5403d973..24ea83e0c 100644 --- a/pinos/server/command.c +++ b/pinos/server/command.c @@ -39,11 +39,11 @@ pinos_command_error_quark (void) } typedef gboolean (*PinosCommandFunc) (PinosCommand *command, - PinosDaemon *daemon, + PinosCore *core, GError **err); static gboolean execute_command_module_load (PinosCommand *command, - PinosDaemon *daemon, + PinosCore *core, GError **err); typedef PinosCommand * (*PinosCommandParseFunc) (const gchar *line, @@ -139,9 +139,9 @@ no_module: } static gboolean -execute_command_module_load (PinosCommand * command, - PinosDaemon * daemon, - GError ** err) +execute_command_module_load (PinosCommand *command, + PinosCore *core, + GError **err) { gchar *module; gchar *args; @@ -149,7 +149,7 @@ execute_command_module_load (PinosCommand * command, module = command->args[1]; args = command->args[2]; - return pinos_module_load (daemon, module, args, err) != NULL; + return pinos_module_load (core, module, args, err) != NULL; } /** @@ -217,7 +217,7 @@ out: /** * pinos_command_run: * @command: A #PinosCommand - * @daemon: A #PinosDaemon + * @core: A #PinosCore * @err: Return location for a #GError, or %NULL * * Run @command. @@ -225,14 +225,14 @@ out: * Returns: %TRUE if @command was executed successfully, %FALSE otherwise. */ gboolean -pinos_command_run (PinosCommand * command, - PinosDaemon * daemon, - GError ** err) +pinos_command_run (PinosCommand *command, + PinosCore *core, + GError **err) { g_return_val_if_fail (command != NULL, FALSE); - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), FALSE); + g_return_val_if_fail (core, FALSE); - return command->func (command, daemon, err); + return command->func (command, core, err); } /** diff --git a/pinos/server/command.h b/pinos/server/command.h index 5051b1d06..11cb27dbb 100644 --- a/pinos/server/command.h +++ b/pinos/server/command.h @@ -60,7 +60,7 @@ gboolean pinos_command_parse (PinosCommand **command, gchar *line, GError **err); gboolean pinos_command_run (PinosCommand *command, - PinosDaemon *daemon, + PinosCore *core, GError **err); const gchar * pinos_command_get_name (PinosCommand *command); diff --git a/pinos/server/core.c b/pinos/server/core.c new file mode 100644 index 000000000..d793318e6 --- /dev/null +++ b/pinos/server/core.c @@ -0,0 +1,66 @@ +/* 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 + +typedef struct { + PinosCore object; + + PinosDataLoop *data_loop; + + SpaSupport support[4]; + +} PinosCoreImpl; + +static void +core_destroy (PinosObject *object) +{ + free (object); +} + +PinosCore * +pinos_core_new (PinosMainLoop *main_loop) +{ + PinosCoreImpl *impl; + + impl = calloc (1, sizeof (PinosCoreImpl)); + pinos_registry_init (&impl->object.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; + + impl->support[0].uri = SPA_ID_MAP_URI; + impl->support[0].data = impl->object.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[3].uri = SPA_POLL__MainLoop; + impl->support[3].data = &impl->object.main_loop->poll; + impl->object.support = impl->support; + impl->object.n_support = 4; + + return &impl->object; +} diff --git a/pinos/server/core.h b/pinos/server/core.h new file mode 100644 index 000000000..ac4b759c2 --- /dev/null +++ b/pinos/server/core.h @@ -0,0 +1,58 @@ +/* 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_CORE_H__ +#define __PINOS_CORE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define PINOS_CORE_URI "http://pinos.org/ns/core" +#define PINOS_CORE_PREFIX PINOS_CORE_URI "#" + +typedef struct _PinosCore PinosCore; + +#include +#include +#include + +/** + * PinosCore: + * + * Pinos core object class. + */ +struct _PinosCore { + PinosObject object; + + PinosRegistry registry; + + PinosMainLoop *main_loop; + + SpaSupport *support; + unsigned int n_support; +}; + +PinosCore * pinos_core_new (PinosMainLoop *main_loop); + +#ifdef __cplusplus +} +#endif + +#endif /* __PINOS_CORE_H__ */ diff --git a/pinos/server/daemon.c b/pinos/server/daemon.c index cbeb4106b..14be39d5b 100644 --- a/pinos/server/daemon.c +++ b/pinos/server/daemon.c @@ -31,20 +31,17 @@ #include "pinos/server/daemon.h" #include "pinos/server/node.h" #include "pinos/server/client-node.h" -#include "pinos/server/dbus-client-node.h" #include "pinos/server/client.h" #include "pinos/server/link.h" +#include "pinos/server/node-factory.h" #include "pinos/server/data-loop.h" #include "pinos/server/main-loop.h" #include "pinos/dbus/org-pinos.h" -#define PINOS_DAEMON_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_DAEMON, PinosDaemonPrivate)) - -struct _PinosDaemonPrivate -{ - PinosDaemon *daemon; +typedef struct { + PinosDaemon daemon; + PinosObject object; PinosDaemon1 *iface; guint id; @@ -53,49 +50,36 @@ struct _PinosDaemonPrivate gchar *object_path; - GHashTable *clients; PinosDataLoop *data_loop; - PinosMainLoop *main_loop; - - PinosProperties *properties; PinosListener object_added; PinosListener object_removed; + PinosListener port_unlinked; + PinosListener notify_state; + GHashTable *clients; GHashTable *node_factories; +} PinosDaemonImpl; - SpaSupport support[4]; -}; - -enum -{ - PROP_0, - PROP_CONNECTION, - PROP_PROPERTIES, - PROP_OBJECT_PATH, -}; - -static void try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *this); +static void try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *daemon); static void handle_client_appeared (PinosClient *client, gpointer user_data) { - PinosDaemon *daemon = user_data; - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = user_data; - pinos_log_debug ("daemon %p: appeared %p", daemon, client); + pinos_log_debug ("daemon %p: appeared %p", impl, client); - g_hash_table_insert (priv->clients, (gpointer) pinos_client_get_sender (client), client); + g_hash_table_insert (impl->clients, (gpointer) client->sender, client); } static void handle_client_vanished (PinosClient *client, gpointer user_data) { - PinosDaemon *daemon = user_data; - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = user_data; pinos_log_debug ("daemon %p: vanished %p", daemon, client); - g_hash_table_remove (priv->clients, (gpointer) pinos_client_get_sender (client)); + g_hash_table_remove (impl->clients, (gpointer) client->sender); } static PinosClient * @@ -103,12 +87,12 @@ sender_get_client (PinosDaemon *daemon, const gchar *sender, gboolean create) { - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; PinosClient *client; - client = g_hash_table_lookup (priv->clients, sender); + client = g_hash_table_lookup (impl->clients, sender); if (client == NULL && create) { - client = pinos_client_new (daemon, sender, NULL); + 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, @@ -127,10 +111,10 @@ static void handle_remove_node (PinosNode *node, gpointer user_data) { - PinosClient *client = user_data; + //PinosClient *client = user_data; - pinos_log_debug ("client %p: node %p remove", daemon, node); - pinos_client_remove_object (client, G_OBJECT (node)); + //pinos_log_debug ("client %p: node %p remove", daemon, node); + //pinos_client_remove_object (client, &node->object); } static gboolean @@ -141,8 +125,7 @@ handle_create_node (PinosDaemon1 *interface, GVariant *arg_properties, gpointer user_data) { - PinosDaemon *daemon = user_data; - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = user_data; PinosNodeFactory *factory; PinosNode *node; PinosClient *client; @@ -150,13 +133,13 @@ handle_create_node (PinosDaemon1 *interface, PinosProperties *props; sender = g_dbus_method_invocation_get_sender (invocation); - client = sender_get_client (daemon, sender, TRUE); + client = sender_get_client (&impl->daemon, sender, TRUE); - pinos_log_debug ("daemon %p: create node: %s", daemon, sender); + pinos_log_debug ("daemon %p: create node: %s", impl, sender); props = pinos_properties_from_variant (arg_properties); - factory = g_hash_table_lookup (priv->node_factories, arg_factory_name); + factory = g_hash_table_lookup (impl->node_factories, arg_factory_name); if (factory == NULL) goto no_factory; @@ -169,15 +152,15 @@ handle_create_node (PinosDaemon1 *interface, if (node == NULL) goto no_node; - pinos_client_add_object (client, G_OBJECT (node)); + //pinos_client_add_object (client, &node->object); - g_signal_connect (node, - "remove", - (GCallback) handle_remove_node, - client); + //g_signal_connect (node, + // "remove", + // (GCallback) handle_remove_node, + // client); object_path = pinos_node_get_object_path (node); - pinos_log_debug ("daemon %p: added node %p with path %s", daemon, node, 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); @@ -187,14 +170,14 @@ handle_create_node (PinosDaemon1 *interface, /* ERRORS */ no_factory: { - pinos_log_debug ("daemon %p: could find factory named %s", daemon, arg_factory_name); + pinos_log_debug ("daemon %p: could find factory named %s", impl, arg_factory_name); g_dbus_method_invocation_return_dbus_error (invocation, "org.pinos.Error", "can't find factory"); return TRUE; } no_node: { - pinos_log_debug ("daemon %p: could create node named %s from factory %s", daemon, arg_name, arg_factory_name); + pinos_log_debug ("daemon %p: could create node named %s from factory %s", impl, arg_name, arg_factory_name); g_dbus_method_invocation_return_dbus_error (invocation, "org.pinos.Error", "can't create node"); return TRUE; @@ -203,22 +186,27 @@ no_node: static void -on_link_port_unlinked (PinosLink *link, - PinosPort *port, - PinosDaemon *this) +on_link_port_unlinked (PinosListener *listener, + void *object, + void *data) { - pinos_log_debug ("daemon %p: link %p: port %p unlinked", this, link, 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, this); + try_link_port (link->input->node, link->input, &impl->daemon); } static void -on_link_state_notify (GObject *obj, - GParamSpec *pspec, - PinosDaemon *daemon) +on_link_notify_state (PinosListener *listener, + void *object, + void *data) { - PinosLink *link = PINOS_LINK (obj); + PinosLink *link = object; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, notify_state); GError *error = NULL; PinosLinkState state; @@ -226,7 +214,7 @@ on_link_state_notify (GObject *obj, switch (state) { case PINOS_LINK_STATE_ERROR: { - pinos_log_debug ("daemon %p: link %p: state error: %s", daemon, link, error->message); + pinos_log_debug ("daemon %p: link %p: state error: %s", impl, link, error->message); if (link->input && link->input->node) pinos_node_report_error (link->input->node, g_error_copy (error)); @@ -236,7 +224,7 @@ on_link_state_notify (GObject *obj, } case PINOS_LINK_STATE_UNLINKED: - pinos_log_debug ("daemon %p: link %p: unlinked", daemon, link); + pinos_log_debug ("daemon %p: link %p: unlinked", impl, link); #if 0 g_set_error (&error, @@ -263,13 +251,14 @@ on_link_state_notify (GObject *obj, static void try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *this) { + PinosDaemonImpl *impl = (PinosDaemonImpl *) this; PinosClient *client; PinosProperties *props; const gchar *path; GError *error = NULL; PinosLink *link; - props = pinos_node_get_properties (node); + props = node->properties; if (props == NULL) return; @@ -297,10 +286,14 @@ try_link_port (PinosNode *node, PinosPort *port, PinosDaemon *this) client = pinos_node_get_client (node); if (client) - pinos_client_add_object (client, G_OBJECT (link)); + pinos_client_add_object (client, &link->object); + + 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); - g_signal_connect (link, "port-unlinked", (GCallback) on_link_port_unlinked, this); - g_signal_connect (link, "notify::state", (GCallback) on_link_state_notify, this); pinos_link_activate (link); g_object_unref (link); @@ -361,17 +354,15 @@ on_node_state_change (PinosNode *node, static void on_node_added (PinosDaemon *daemon, PinosNode *node) { - PinosNodeState state; - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; - pinos_log_debug ("daemon %p: node %p added", daemon, node); + pinos_log_debug ("daemon %p: node %p added", impl, node); - g_object_set (node, "data-loop", priv->data_loop, NULL); + g_object_set (node, "data-loop", impl->data_loop, NULL); - g_signal_connect (node, "state-change", (GCallback) on_node_state_change, daemon); + g_signal_connect (node, "state-change", (GCallback) on_node_state_change, impl); - state = pinos_node_get_state (node); - if (state > PINOS_NODE_STATE_CREATING) { + if (node->state > PINOS_NODE_STATE_CREATING) { on_node_created (node, daemon); } } @@ -390,47 +381,45 @@ handle_create_client_node (PinosDaemon1 *interface, GVariant *arg_properties, gpointer user_data) { - PinosDaemon *daemon = user_data; - PinosNode *node; + PinosDaemonImpl *impl = user_data; + PinosDaemon *this = &impl->daemon; + PinosClientNode *node; PinosClient *client; const gchar *sender, *object_path; PinosProperties *props; GError *error = NULL; GUnixFDList *fdlist; - GSocket *socket, *rtsocket; + int socket, rtsocket; gint fdidx, rtfdidx; sender = g_dbus_method_invocation_get_sender (invocation); - client = sender_get_client (daemon, sender, TRUE); + client = sender_get_client (&impl->daemon, sender, TRUE); - pinos_log_debug ("daemon %p: create client-node: %s", daemon, sender); + pinos_log_debug ("daemon %p: create client-node: %s", impl, sender); props = pinos_properties_from_variant (arg_properties); - node = pinos_client_node_new (daemon, + node = pinos_client_node_new (this->core, client, arg_name, props); pinos_properties_free (props); - socket = pinos_client_node_get_socket_pair (PINOS_CLIENT_NODE (node), &error); - if (socket == NULL) + socket = pinos_client_node_get_socket_pair (node, &error); + if (socket == -1) goto no_socket; - rtsocket = pinos_client_node_get_rtsocket_pair (PINOS_CLIENT_NODE (node), &error); - if (rtsocket == NULL) + rtsocket = pinos_client_node_get_rtsocket_pair (node, &error); + if (rtsocket == -1) goto no_socket; - pinos_client_add_object (client, G_OBJECT (node)); + //pinos_client_add_object (client, &node->object); - object_path = pinos_node_get_object_path (PINOS_NODE (node)); - pinos_log_debug ("daemon %p: add client-node %p, %s", daemon, node, object_path); - g_object_unref (node); + object_path = pinos_node_get_object_path (node->node); + 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, g_socket_get_fd (socket), &error); - rtfdidx = g_unix_fd_list_append (fdlist, g_socket_get_fd (rtsocket), &error); - g_object_unref (socket); - g_object_unref (rtsocket); + fdidx = g_unix_fd_list_append (fdlist, socket, &error); + rtfdidx = g_unix_fd_list_append (fdlist, rtsocket, &error); g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, g_variant_new ("(ohh)", object_path, fdidx, rtfdidx), fdlist); @@ -440,7 +429,7 @@ handle_create_client_node (PinosDaemon1 *interface, no_socket: { - pinos_log_debug ("daemon %p: could not create socket %s", daemon, error->message); + pinos_log_debug ("daemon %p: could not create socket %s", impl, error->message); g_object_unref (node); goto exit_error; } @@ -456,16 +445,16 @@ static void export_server_object (PinosDaemon *daemon, GDBusObjectManagerServer *manager) { - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; PinosObjectSkeleton *skel; skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_SERVER); - pinos_object_skeleton_set_daemon1 (skel, priv->iface); + pinos_object_skeleton_set_daemon1 (skel, impl->iface); g_dbus_object_manager_server_export (manager, G_DBUS_OBJECT_SKELETON (skel)); - g_free (priv->object_path); - priv->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); + g_free (impl->object_path); + impl->object_path = g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); g_object_unref (skel); } @@ -474,13 +463,12 @@ bus_acquired_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { - PinosDaemon *daemon = user_data; - PinosDaemonPrivate *priv = daemon->priv; - GDBusObjectManagerServer *manager = priv->server_manager; + PinosDaemonImpl *impl = user_data; + GDBusObjectManagerServer *manager = impl->server_manager; - priv->connection = connection; + impl->connection = connection; - export_server_object (daemon, manager); + export_server_object (&impl->daemon, manager); g_dbus_object_manager_server_set_connection (manager, connection); } @@ -497,60 +485,36 @@ name_lost_handler (GDBusConnection *connection, const gchar *name, gpointer user_data) { - PinosDaemon *daemon = user_data; - PinosDaemonPrivate *priv = daemon->priv; - GDBusObjectManagerServer *manager = priv->server_manager; + PinosDaemonImpl *impl = user_data; + 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 (&priv->object_path, g_free); - priv->connection = connection; -} - -/** - * pinos_daemon_new: - * @properties: #PinosProperties - * - * Make a new #PinosDaemon object with given @properties - * - * Returns: a new #PinosDaemon - */ -PinosDaemon * -pinos_daemon_new (PinosProperties *properties) -{ - return g_object_new (PINOS_TYPE_DAEMON, "properties", properties, NULL); + g_clear_pointer (&impl->object_path, g_free); + impl->connection = connection; } const gchar * pinos_daemon_get_object_path (PinosDaemon *daemon) { - PinosDaemonPrivate *priv; + PinosDaemonImpl *impl = (PinosDaemonImpl *) daemon; - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); - priv = daemon->priv; + g_return_val_if_fail (impl, NULL); - return priv->object_path; + return impl->object_path; } -/** - * pinos_daemon_start: - * @daemon: a #PinosDaemon - * - * Start the @daemon. - */ -void -pinos_daemon_start (PinosDaemon *daemon) +static SpaResult +daemon_start (PinosDaemon *daemon) { - PinosDaemonPrivate *priv; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, daemon); - g_return_if_fail (PINOS_IS_DAEMON (daemon)); - - priv = daemon->priv; - g_return_if_fail (priv->id == 0); + g_return_val_if_fail (impl, SPA_RESULT_INVALID_ARGUMENTS); + g_return_val_if_fail (impl->id == 0, SPA_RESULT_INVALID_ARGUMENTS); pinos_log_debug ("daemon %p: start", daemon); - priv->id = g_bus_own_name (G_BUS_TYPE_SESSION, + impl->id = g_bus_own_name (G_BUS_TYPE_SESSION, PINOS_DBUS_SERVICE, G_BUS_NAME_OWNER_FLAGS_REPLACE, bus_acquired_handler, @@ -558,27 +522,24 @@ pinos_daemon_start (PinosDaemon *daemon) name_lost_handler, daemon, NULL); + + return SPA_RESULT_OK; } -/** - * pinos_daemon_stop: - * @daemon: a #PinosDaemon - * - * Stop the @daemon. - */ -void -pinos_daemon_stop (PinosDaemon *daemon) +static SpaResult +daemon_stop (PinosDaemon *daemon) { - PinosDaemonPrivate *priv = daemon->priv; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, daemon); - g_return_if_fail (PINOS_IS_DAEMON (daemon)); + g_return_val_if_fail (impl, SPA_RESULT_INVALID_ARGUMENTS); pinos_log_debug ("daemon %p: stop", daemon); - if (priv->id != 0) { - g_bus_unown_name (priv->id); - priv->id = 0; + if (impl->id != 0) { + g_bus_unown_name (impl->id); + impl->id = 0; } + return SPA_RESULT_OK; } /** @@ -594,10 +555,12 @@ gchar * pinos_daemon_export_uniquely (PinosDaemon *daemon, GDBusObjectSkeleton *skel) { - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); + 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 (daemon->priv->server_manager, skel); + g_dbus_object_manager_server_export_uniquely (impl->server_manager, skel); return g_strdup (g_dbus_object_get_object_path (G_DBUS_OBJECT (skel))); } @@ -613,51 +576,55 @@ void pinos_daemon_unexport (PinosDaemon *daemon, const gchar *object_path) { - g_return_if_fail (PINOS_IS_DAEMON (daemon)); + 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 (daemon->priv->server_manager, 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) { - PinosObject *object = data; - PinosDaemonPrivate *priv = SPA_CONTAINER_OF (listener, PinosDaemonPrivate, object_added); - PinosDaemon *daemon = priv->daemon; + PinosObject *obj = data; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, object_added); + PinosDaemon *this = &impl->daemon; - if (object->type == daemon->registry.uri.node) { - PinosNode *node = object->implementation; + if (obj->type == this->core->registry.uri.node) { + PinosNode *node = obj->implementation; - on_node_added (daemon, node); - } else if (object->type == daemon->registry.uri.node_factory) { - PinosNodeFactory *factory = object->implementation; + on_node_added (this, node); + } else if (obj->type == this->core->registry.uri.node_factory) { + PinosNodeFactory *factory = obj->implementation; gchar *name; g_object_get (factory, "name", &name, NULL); - g_hash_table_insert (priv->node_factories, name, g_object_ref (factory)); + g_hash_table_insert (impl->node_factories, name, g_object_ref (factory)); } } static void on_registry_object_removed (PinosListener *listener, + void *object, void *data) { - PinosObject *object = data; - PinosDaemonPrivate *priv = SPA_CONTAINER_OF (listener, PinosDaemonPrivate, object_added); - PinosDaemon *daemon = priv->daemon; + PinosObject *obj = data; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (listener, PinosDaemonImpl, object_added); + PinosDaemon *this = &impl->daemon; - if (object->type == daemon->registry.uri.node) { - PinosNode *node = object->implementation; + if (obj->type == this->core->registry.uri.node) { + PinosNode *node = obj->implementation; - on_node_removed (daemon, node); - } else if (object->type == daemon->registry.uri.node_factory) { - PinosNodeFactory *factory = object->implementation; + on_node_removed (this, node); + } else if (obj->type == this->core->registry.uri.node_factory) { + PinosNodeFactory *factory = obj->implementation; gchar *name; g_object_get (factory, "name", &name, NULL); - g_hash_table_remove (priv->node_factories, name); + g_hash_table_remove (impl->node_factories, name); g_free (name); } } @@ -685,23 +652,18 @@ pinos_daemon_find_port (PinosDaemon *daemon, { PinosPort *best = NULL; gboolean have_name; - guint i; + void *state = NULL; + PinosObject *o; - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); + g_return_val_if_fail (daemon, NULL); have_name = name ? strlen (name) > 0 : FALSE; pinos_log_debug ("name \"%s\", %d", name, have_name); - for (i = 0; i < pinos_map_get_size (&daemon->registry.objects); i++) { - PinosObject *o = pinos_map_lookup (&daemon->registry.objects, i); - PinosNode *n; - - if (o->type != daemon->registry.uri.node) - continue; - - n = o->implementation; - if (n == NULL || n->flags & PINOS_NODE_FLAG_REMOVING) + 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)); @@ -726,198 +688,92 @@ pinos_daemon_find_port (PinosDaemon *daemon, return best; } - -G_DEFINE_TYPE (PinosDaemon, pinos_daemon, G_TYPE_OBJECT); - static void -pinos_daemon_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) +daemon_destroy (PinosObject *object) { - PinosDaemon *this = PINOS_DAEMON (_object); - PinosDaemonPrivate *priv = this->priv; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (object, PinosDaemonImpl, object); + PinosDaemon *this = &impl->daemon; - switch (prop_id) { - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - case PROP_CONNECTION: - g_value_set_object (value, priv->connection); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -pinos_daemon_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosDaemon *this = PINOS_DAEMON (_object); - PinosDaemonPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -pinos_daemon_constructed (GObject * object) -{ - PinosDaemon *this = PINOS_DAEMON_CAST (object); - PinosDaemonPrivate *priv = this->priv; - - pinos_log_debug ("daemon %p: constructed", object); - pinos_daemon1_set_user_name (priv->iface, g_get_user_name ()); - pinos_daemon1_set_host_name (priv->iface, g_get_host_name ()); - pinos_daemon1_set_version (priv->iface, PACKAGE_VERSION); - pinos_daemon1_set_name (priv->iface, PACKAGE_NAME); - pinos_daemon1_set_cookie (priv->iface, g_random_int()); - pinos_daemon1_set_properties (priv->iface, pinos_properties_to_variant (priv->properties)); - - G_OBJECT_CLASS (pinos_daemon_parent_class)->constructed (object); - - pinos_object_init (&this->object, - this->registry.uri.daemon, - this, - NULL); - pinos_registry_add_object (&this->registry, &this->object); -} - -static void -pinos_daemon_dispose (GObject * object) -{ - PinosDaemon *this = PINOS_DAEMON_CAST (object); - - pinos_log_debug ("daemon %p: dispose", object); + pinos_log_debug ("daemon %p: destroy", impl); pinos_daemon_stop (this); + pinos_signal_remove (&impl->object_added); + pinos_signal_remove (&impl->object_removed); - G_OBJECT_CLASS (pinos_daemon_parent_class)->dispose (object); + 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); } -static void -pinos_daemon_finalize (GObject * object) +void +pinos_daemon_destroy (PinosDaemon *daemon) { - PinosDaemon *this = PINOS_DAEMON_CAST (object); - PinosDaemonPrivate *priv = this->priv; + PinosDaemonImpl *impl = SPA_CONTAINER_OF (daemon, PinosDaemonImpl, daemon); - pinos_log_debug ("daemon %p: finalize", object); - - pinos_registry_remove_object (&this->registry, &this->object); - - g_clear_object (&priv->server_manager); - g_clear_object (&priv->iface); - g_clear_object (&priv->data_loop); - g_hash_table_unref (priv->clients); - g_hash_table_unref (priv->node_factories); - - G_OBJECT_CLASS (pinos_daemon_parent_class)->finalize (object); + pinos_object_destroy (&impl->object); } -static void -pinos_daemon_class_init (PinosDaemonClass * klass) +/** + * pinos_daemon_new: + * @core: #PinosCore + * @properties: #PinosProperties + * + * Make a new #PinosDaemon object with given @properties + * + * Returns: a new #PinosDaemon + */ +PinosDaemon * +pinos_daemon_new (PinosCore *core, + PinosProperties *properties) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + PinosDaemonImpl *impl; + PinosDaemon *this; - g_type_class_add_private (klass, sizeof (PinosDaemonPrivate)); + impl = calloc (1, sizeof (PinosDaemonImpl)); + this = &impl->daemon; + pinos_log_debug ("daemon %p: new", impl); - gobject_class->constructed = pinos_daemon_constructed; - gobject_class->dispose = pinos_daemon_dispose; - gobject_class->finalize = pinos_daemon_finalize; + this->core = core; + this->properties = properties; - gobject_class->set_property = pinos_daemon_set_property; - gobject_class->get_property = pinos_daemon_get_property; + this->start = daemon_start; + this->stop = daemon_stop; - g_object_class_install_property (gobject_class, - PROP_CONNECTION, - g_param_spec_object ("connection", - "Connection", - "The DBus connection", - G_TYPE_DBUS_CONNECTION, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + pinos_object_init (&impl->object, + core->registry.uri.daemon, + impl, + daemon_destroy); - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "Client properties", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); + impl->object_added.notify = on_registry_object_added; + pinos_signal_add (&core->registry.object_added, &impl->object_added); - g_object_class_install_property (gobject_class, - PROP_OBJECT_PATH, - g_param_spec_string ("object-path", - "Object Path", - "The object path", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); + impl->object_removed.notify = on_registry_object_removed; + pinos_signal_add (&core->registry.object_removed, &impl->object_removed); -} - -static void -pinos_daemon_init (PinosDaemon * daemon) -{ - PinosDaemonPrivate *priv = daemon->priv = PINOS_DAEMON_GET_PRIVATE (daemon); - - priv->daemon = daemon; - - pinos_log_debug ("daemon %p: new", daemon); - priv->iface = pinos_daemon1_skeleton_new (); - g_signal_connect (priv->iface, "handle-create-node", (GCallback) handle_create_node, daemon); - g_signal_connect (priv->iface, "handle-create-client-node", (GCallback) handle_create_client_node, daemon); - - pinos_registry_init (&daemon->registry); - - priv->object_added.notify = on_registry_object_added; - pinos_signal_add (&daemon->registry.object_added, &priv->object_added); - - priv->object_removed.notify = on_registry_object_removed; - pinos_signal_add (&daemon->registry.object_removed, &priv->object_removed); - - priv->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX); - priv->clients = g_hash_table_new (g_str_hash, g_str_equal); - priv->node_factories = g_hash_table_new_full (g_str_hash, + 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); - daemon->main_loop = pinos_main_loop_new (g_main_context_get_thread_default ()); - priv->data_loop = pinos_data_loop_new(); + 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); - daemon->log = pinos_log_get(); + pinos_daemon1_set_user_name (impl->iface, g_get_user_name ()); + pinos_daemon1_set_host_name (impl->iface, g_get_host_name ()); + pinos_daemon1_set_version (impl->iface, PACKAGE_VERSION); + pinos_daemon1_set_name (impl->iface, PACKAGE_NAME); + pinos_daemon1_set_cookie (impl->iface, g_random_int()); + pinos_daemon1_set_properties (impl->iface, pinos_properties_to_variant (this->properties)); - priv->support[0].uri = SPA_ID_MAP_URI; - priv->support[0].data = daemon->registry.map; - priv->support[1].uri = SPA_LOG_URI; - priv->support[1].data = daemon->log; - priv->support[2].uri = SPA_POLL__DataLoop; - priv->support[2].data = &priv->data_loop->poll; - priv->support[3].uri = SPA_POLL__MainLoop; - priv->support[3].data = &daemon->main_loop->poll; - daemon->support = priv->support; - daemon->n_support = 4; + pinos_registry_add_object (&core->registry, &impl->object); + + return this; } diff --git a/pinos/server/daemon.h b/pinos/server/daemon.h index bfbe16dc3..6fdfc2fb8 100644 --- a/pinos/server/daemon.h +++ b/pinos/server/daemon.h @@ -27,27 +27,11 @@ G_BEGIN_DECLS #define PINOS_DAEMON_URI "http://pinos.org/ns/daemon" #define PINOS_DAEMON_PREFIX PINOS_DAEMON_URI "#" -#define PINOS_TYPE_DAEMON (pinos_daemon_get_type ()) -#define PINOS_IS_DAEMON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_DAEMON)) -#define PINOS_IS_DAEMON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_DAEMON)) -#define PINOS_DAEMON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_DAEMON, PinosDaemonClass)) -#define PINOS_DAEMON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_DAEMON, PinosDaemon)) -#define PINOS_DAEMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_DAEMON, PinosDaemonClass)) -#define PINOS_DAEMON_CAST(obj) ((PinosDaemon*)(obj)) -#define PINOS_DAEMON_CLASS_CAST(klass) ((PinosDaemonClass*)(klass)) - typedef struct _PinosDaemon PinosDaemon; -typedef struct _PinosDaemonClass PinosDaemonClass; -typedef struct _PinosDaemonPrivate PinosDaemonPrivate; -#include -#include -#include -#include -#include -#include #include -#include +#include +#include /** * PinosDaemon: @@ -55,46 +39,28 @@ typedef struct _PinosDaemonPrivate PinosDaemonPrivate; * Pinos daemon object class. */ struct _PinosDaemon { - GObject obj; + PinosProperties *properties; - PinosObject object; + PinosCore *core; - SpaLog *log; - - PinosMainLoop *main_loop; - - SpaSupport *support; - unsigned int n_support; - - PinosRegistry registry; - - PinosDaemonPrivate *priv; + SpaResult (*start) (PinosDaemon *daemon); + SpaResult (*stop) (PinosDaemon *daemon); }; -/** - * PinosDaemonClass: - * - * Pinos daemon object class. - */ -struct _PinosDaemonClass { - GObjectClass parent_class; -}; +PinosObject * pinos_daemon_new (PinosCore *core, + PinosProperties *properties); -/* normal GObject stuff */ -GType pinos_daemon_get_type (void); +const char * pinos_daemon_get_object_path (PinosDaemon *daemon); -PinosDaemon * pinos_daemon_new (PinosProperties *properties); -const gchar * pinos_daemon_get_object_path (PinosDaemon *daemon); +#define pinos_daemon_start(d) (d)->start(d) +#define pinos_daemon_stop(d) (d)->stop(d) -void pinos_daemon_start (PinosDaemon *daemon); -void pinos_daemon_stop (PinosDaemon *daemon); - -gchar * pinos_daemon_export_uniquely (PinosDaemon *daemon, GDBusObjectSkeleton *skel); -void pinos_daemon_unexport (PinosDaemon *daemon, const gchar *name); +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 gchar *name, + const char *name, PinosProperties *props, GPtrArray *format_filter, GError **error); diff --git a/pinos/server/dbus-client-node.c b/pinos/server/dbus-client-node.c deleted file mode 100644 index 861f1e52f..000000000 --- a/pinos/server/dbus-client-node.c +++ /dev/null @@ -1,333 +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 "spa/lib/props.h" - -#include "pinos/client/pinos.h" -#include "pinos/client/enumtypes.h" -#include "pinos/client/private.h" - -#include "pinos/server/daemon.h" -#include "pinos/server/dbus-client-node.h" - -#include "pinos/dbus/org-pinos.h" - -struct _PinosDBusClientNodePrivate -{ - int fd; - GSocket *sockets[2]; - SpaHandle *handle; -}; - -#define PINOS_DBUS_CLIENT_NODE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_DBUS_CLIENT_NODE, PinosDBusClientNodePrivate)) - -G_DEFINE_TYPE (PinosDBusClientNode, pinos_dbus_client_node, PINOS_TYPE_NODE); - -enum -{ - PROP_0, -}; - -enum -{ - SIGNAL_NONE, - LAST_SIGNAL -}; - -//static guint signals[LAST_SIGNAL] = { 0 }; - -static void -pinos_dbus_client_node_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosDBusClientNode *node = PINOS_DBUS_CLIENT_NODE (_object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); - break; - } -} - -static void -pinos_dbus_client_node_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosDBusClientNode *node = PINOS_DBUS_CLIENT_NODE (_object); - - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec); - break; - } -} - -/** - * pinos_dbus_client_node_get_socket_pair: - * @node: a #PinosDBusClientNode - * @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. - */ -GSocket * -pinos_dbus_client_node_get_socket_pair (PinosDBusClientNode *this, - GError **error) -{ - PinosNode *node; - PinosDBusClientNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_DBUS_CLIENT_NODE (this), FALSE); - node = PINOS_NODE (this); - priv = this->priv; - - if (priv->sockets[1] == NULL) { - SpaProps *props; - SpaPropValue value; - int fd[2]; - - if (socketpair (AF_UNIX, SOCK_STREAM, 0, fd) != 0) - goto no_sockets; - - priv->sockets[0] = g_socket_new_from_fd (fd[0], error); - if (priv->sockets[0] == NULL) - goto create_failed; - - priv->sockets[1] = g_socket_new_from_fd (fd[1], error); - if (priv->sockets[1] == NULL) - goto create_failed; - - priv->fd = g_socket_get_fd (priv->sockets[0]); - - spa_node_get_props (node->node, &props); - value.value = &priv->fd; - value.size = sizeof (int); - spa_props_set_value (props, spa_props_index_for_name (props, "socket"), &value); - spa_node_set_props (node->node, props); - } - return g_object_ref (priv->sockets[1]); - - /* ERRORS */ -no_sockets: - { - g_set_error (error, - G_IO_ERROR, - g_io_error_from_errno (errno), - "could not create socketpair: %s", strerror (errno)); - return NULL; - } -create_failed: - { - g_clear_object (&priv->sockets[0]); - g_clear_object (&priv->sockets[1]); - return NULL; - } -} - -static void -pinos_dbus_client_node_dispose (GObject * object) -{ - PinosDBusClientNode *this = PINOS_DBUS_CLIENT_NODE (object); - PinosNode *node = PINOS_NODE (this); - SpaProps *props; - SpaPropValue value; - int fd = -1; - - g_debug ("client-node %p: dispose", this); - - spa_node_get_props (node->node, &props); - value.value = &fd; - value.size = sizeof (int); - spa_props_set_value (props, spa_props_index_for_name (props, "socket"), &value); - - value.value = NULL; - value.size = sizeof (void *); - spa_props_set_value (props, spa_props_index_for_name (props, "connection"), &value); - spa_node_set_props (node->node, props); - - G_OBJECT_CLASS (pinos_dbus_client_node_parent_class)->dispose (object); -} - -static void -pinos_dbus_client_node_finalize (GObject * object) -{ - PinosDBusClientNode *this = PINOS_DBUS_CLIENT_NODE (object); - PinosDBusClientNodePrivate *priv = this->priv; - - g_debug ("client-node %p: finalize", this); - - g_clear_object (&priv->sockets[0]); - g_clear_object (&priv->sockets[1]); - spa_handle_clear (priv->handle); - g_free (priv->handle); - - G_OBJECT_CLASS (pinos_dbus_client_node_parent_class)->finalize (object); -} - -static void -pinos_dbus_client_node_constructed (GObject * object) -{ - PinosDBusClientNode *this = PINOS_DBUS_CLIENT_NODE (object); - - g_debug ("client-node %p: constructed", this); - - G_OBJECT_CLASS (pinos_dbus_client_node_parent_class)->constructed (object); -} - -static void -pinos_dbus_client_node_class_init (PinosDBusClientNodeClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosDBusClientNodePrivate)); - - gobject_class->constructed = pinos_dbus_client_node_constructed; - gobject_class->dispose = pinos_dbus_client_node_dispose; - gobject_class->finalize = pinos_dbus_client_node_finalize; - gobject_class->set_property = pinos_dbus_client_node_set_property; - gobject_class->get_property = pinos_dbus_client_node_get_property; -} - -static void -pinos_dbus_client_node_init (PinosDBusClientNode * node) -{ - node->priv = PINOS_DBUS_CLIENT_NODE_GET_PRIVATE (node); - - g_debug ("client-node %p: new", 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 = 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; -} - -/** - * pinos_dbus_client_node_new: - * @daemon: a #PinosDaemon - * @client: the client owner - * @path: a dbus path - * @properties: extra properties - * - * Create a new #PinosNode. - * - * Returns: a new #PinosNode - */ -PinosNode * -pinos_dbus_client_node_new (PinosDaemon *daemon, - PinosClient *client, - const gchar *path, - PinosProperties *properties) -{ - SpaNode *n; - SpaResult res; - SpaHandle *handle; - PinosNode *node; - SpaProps *props; - SpaPropValue value; - - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); - - if ((res = make_node (daemon, - &handle, - &n, - "build/spa/plugins/remote/libspa-remote.so", - "dbus-proxy")) < 0) { - g_error ("can't create proxy: %d", res); - return NULL; - } - - spa_node_get_props (n, &props); - g_object_get (daemon, "connection", &value.value, NULL); - value.size = sizeof (void *); - spa_props_set_value (props, spa_props_index_for_name (props, "connection"), &value); - spa_node_set_props (n, props); - - node = g_object_new (PINOS_TYPE_DBUS_CLIENT_NODE, - "daemon", daemon, - "client", client, - "name", path, - "properties", properties, - "node", n, - NULL); - - PINOS_DBUS_CLIENT_NODE (node)->priv->handle = handle; - - return node; -} diff --git a/pinos/server/dbus-client-node.h b/pinos/server/dbus-client-node.h deleted file mode 100644 index dd0c2bfe7..000000000 --- a/pinos/server/dbus-client-node.h +++ /dev/null @@ -1,75 +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_DBUS_CLIENT_NODE_H__ -#define __PINOS_DBUS_CLIENT_NODE_H__ - -#include - -#include - -G_BEGIN_DECLS - -#define PINOS_TYPE_DBUS_CLIENT_NODE (pinos_dbus_client_node_get_type ()) -#define PINOS_IS_DBUS_CLIENT_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_DBUS_CLIENT_NODE)) -#define PINOS_IS_DBUS_CLIENT_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_DBUS_CLIENT_NODE)) -#define PINOS_DBUS_CLIENT_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_DBUS_CLIENT_NODE, PinosDBusClientNodeClass)) -#define PINOS_DBUS_CLIENT_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_DBUS_CLIENT_NODE, PinosDBusClientNode)) -#define PINOS_DBUS_CLIENT_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_DBUS_CLIENT_NODE, PinosDBusClientNodeClass)) -#define PINOS_DBUS_CLIENT_NODE_CAST(obj) ((PinosDBusClientNode*)(obj)) -#define PINOS_DBUS_CLIENT_NODE_CLASS_CAST(klass) ((PinosDBusClientNodeClass*)(klass)) - -typedef struct _PinosDBusClientNode PinosDBusClientNode; -typedef struct _PinosDBusClientNodeClass PinosDBusClientNodeClass; -typedef struct _PinosDBusClientNodePrivate PinosDBusClientNodePrivate; - -/** - * PinosDBusClientNode: - * - * Pinos client node object class. - */ -struct _PinosDBusClientNode { - PinosNode object; - - PinosDBusClientNodePrivate *priv; -}; - -/** - * PinosDBusClientNodeClass: - * - * Pinos client node object class. - */ -struct _PinosDBusClientNodeClass { - PinosNodeClass parent_class; -}; - -/* normal GObject stuff */ -GType pinos_dbus_client_node_get_type (void); - -PinosNode * pinos_dbus_client_node_new (PinosDaemon *daemon, - PinosClient *client, - const gchar *path, - PinosProperties *properties); - -GSocket * pinos_dbus_client_node_get_socket_pair (PinosDBusClientNode *node, - GError **error); - -G_END_DECLS - -#endif /* __PINOS_DBUS_CLIENT_NODE_H__ */ diff --git a/pinos/server/link.c b/pinos/server/link.c index 08c4e609b..4a5dc7910 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -36,8 +36,14 @@ #define MAX_BUFFERS 16 -struct _PinosLinkPrivate +typedef struct { + PinosLink link; + + PinosObject object; + PinosInterface ifaces[1]; + + PinosCore *core; PinosDaemon *daemon; PinosLink1 *iface; @@ -45,128 +51,24 @@ struct _PinosLinkPrivate GPtrArray *format_filter; PinosProperties *properties; - PinosMainLoop *main_loop; - PinosLinkState state; GError *error; + PinosListener input_port_destroy; + PinosListener input_async_complete; + PinosListener output_port_destroy; + PinosListener output_async_complete; + gboolean allocated; PinosMemblock buffer_mem; SpaBuffer **buffers; unsigned int n_buffers; -}; - -G_DEFINE_TYPE (PinosLink, pinos_link, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_OBJECT_PATH, - PROP_OUTPUT_PORT, - PROP_INPUT_PORT, - PROP_FORMAT_FILTER, - PROP_PROPERTIES, - PROP_STATE, -}; - -enum -{ - SIGNAL_REMOVE, - SIGNAL_PORT_UNLINKED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = { 0 }; - -static void -pinos_link_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosLink *this = PINOS_LINK (_object); - PinosLinkPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - case PROP_OUTPUT_PORT: - g_value_set_pointer (value, this->output); - break; - - case PROP_INPUT_PORT: - g_value_set_pointer (value, this->input); - break; - - case PROP_FORMAT_FILTER: - g_value_set_boxed (value, priv->format_filter); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - case PROP_STATE: - g_value_set_enum (value, priv->state); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -pinos_link_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosLink *this = PINOS_LINK (_object); - PinosLinkPrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_OBJECT_PATH: - priv->object_path = g_value_dup_string (value); - break; - - case PROP_OUTPUT_PORT: - this->output = g_value_get_pointer (value); - break; - - case PROP_INPUT_PORT: - this->input = g_value_get_pointer (value); - break; - - case PROP_FORMAT_FILTER: - priv->format_filter = g_value_dup_boxed (value); - break; - - case PROP_PROPERTIES: - priv->properties = g_value_dup_boxed (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} +} PinosLinkImpl; static void link_register_object (PinosLink *this) { - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; PinosObjectSkeleton *skel; gchar *name; @@ -174,49 +76,49 @@ link_register_object (PinosLink *this) skel = pinos_object_skeleton_new (name); g_free (name); - pinos_object_skeleton_set_link1 (skel, priv->iface); + pinos_object_skeleton_set_link1 (skel, impl->iface); - g_free (priv->object_path); - priv->object_path = pinos_daemon_export_uniquely (priv->daemon, G_DBUS_OBJECT_SKELETON (skel)); + 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, id %u", this, priv->object_path, this->object.id); + pinos_log_debug ("link %p: register object %s", this, impl->object_path); } static void link_unregister_object (PinosLink *this) { - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; pinos_log_debug ("link %p: unregister object", this); - pinos_daemon_unexport (priv->daemon, priv->object_path); + pinos_daemon_unexport (impl->daemon, impl->object_path); } static void pinos_link_update_state (PinosLink *link, PinosLinkState state) { - PinosLinkPrivate *priv = link->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) link; - if (state != priv->state) { - g_clear_error (&priv->error); + if (state != impl->state) { + g_clear_error (&impl->error); pinos_log_debug ("link %p: update state %s -> %s", link, - pinos_link_state_as_string (priv->state), + pinos_link_state_as_string (impl->state), pinos_link_state_as_string (state)); - priv->state = state; - g_object_notify (G_OBJECT (link), "state"); + impl->state = state; + pinos_signal_emit (&link->notify_state, link, NULL); } } static void pinos_link_report_error (PinosLink *link, GError *error) { - PinosLinkPrivate *priv = link->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) link; - g_clear_error (&priv->error); - priv->error = error; - priv->state = PINOS_LINK_STATE_ERROR; + g_clear_error (&impl->error); + impl->error = error; + impl->state = PINOS_LINK_STATE_ERROR; pinos_log_debug ("link %p: got error state %s", link, error->message); - g_object_notify (G_OBJECT (link), "state"); + pinos_signal_emit (&link->notify_state, link, NULL); } static SpaResult @@ -367,7 +269,7 @@ find_meta_enable (const SpaPortInfo *info, SpaMetaType type) static SpaResult do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) { - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; SpaResult res; const SpaPortInfo *iinfo, *oinfo; SpaPortInfoFlags in_flags, out_flags; @@ -446,7 +348,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) } else return SPA_RESULT_OK; - if (priv->buffers == NULL) { + if (impl->buffers == NULL) { SpaAllocParamBuffers *in_alloc, *out_alloc; SpaAllocParamMetaEnableRingbuffer *in_me, *out_me; guint max_buffers; @@ -484,10 +386,10 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) if (this->output->allocated) { out_flags = 0; in_flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS; - priv->n_buffers = this->output->n_buffers; - priv->buffers = this->output->buffers; - priv->allocated = FALSE; - pinos_log_debug ("reusing %d output buffers %p", priv->n_buffers, priv->buffers); + impl->n_buffers = this->output->n_buffers; + impl->buffers = this->output->buffers; + impl->allocated = FALSE; + pinos_log_debug ("reusing %d output buffers %p", impl->n_buffers, impl->buffers); } else { guint i, j; size_t hdr_size, buf_size, arr_size; @@ -513,24 +415,24 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) buf_size = SPA_ROUND_UP_N (hdr_size + (minsize * blocks), 64); - priv->n_buffers = max_buffers; + impl->n_buffers = max_buffers; pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD | PINOS_MEMBLOCK_FLAG_MAP_READWRITE | PINOS_MEMBLOCK_FLAG_SEAL, - priv->n_buffers * (sizeof (SpaBuffer*) + buf_size), - &priv->buffer_mem); + impl->n_buffers * (sizeof (SpaBuffer*) + buf_size), + &impl->buffer_mem); - arr_size = priv->n_buffers * sizeof (SpaBuffer*); - priv->buffers = p = priv->buffer_mem.ptr; + arr_size = impl->n_buffers * sizeof (SpaBuffer*); + impl->buffers = p = impl->buffer_mem.ptr; p = SPA_MEMBER (p, arr_size, void); - for (i = 0; i < priv->n_buffers; i++) { + for (i = 0; i < impl->n_buffers; i++) { SpaBuffer *b; SpaData *d; void *pd; guint mi; - b = priv->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer); + b = impl->buffers[i] = SPA_MEMBER (p, buf_size * i, SpaBuffer); b->id = i; b->n_metas = n_metas; @@ -568,9 +470,9 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) if (minsize > 0) { d->type = SPA_DATA_TYPE_MEMFD; d->flags = 0; - d->data = priv->buffer_mem.ptr; - d->fd = priv->buffer_mem.fd; - d->maxsize = priv->buffer_mem.size; + d->data = impl->buffer_mem.ptr; + d->fd = impl->buffer_mem.fd; + d->maxsize = impl->buffer_mem.size; d->offset = arr_size + hdr_size + (buf_size * i); d->size = minsize; d->stride = stride; @@ -579,8 +481,8 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) d->data = NULL; } } - pinos_log_debug ("allocated %d buffers %p %zd", priv->n_buffers, priv->buffers, minsize); - priv->allocated = TRUE; + pinos_log_debug ("allocated %d buffers %p %zd", impl->n_buffers, impl->buffers, minsize); + impl->allocated = TRUE; } if (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { @@ -588,72 +490,72 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state) SPA_DIRECTION_OUTPUT, this->output->port, iinfo->params, iinfo->n_params, - priv->buffers, &priv->n_buffers)) < 0) { + impl->buffers, &impl->n_buffers)) < 0) { g_set_error (&error, PINOS_ERROR, PINOS_ERROR_BUFFER_ALLOCATION, "error alloc output buffers: %d", res); goto error; } - this->output->buffers = priv->buffers; - this->output->n_buffers = priv->n_buffers; + this->output->buffers = impl->buffers; + this->output->n_buffers = impl->n_buffers; this->output->allocated = TRUE; - this->output->buffer_mem = priv->buffer_mem; - priv->allocated = FALSE; - pinos_log_debug ("allocated %d buffers %p from output port", priv->n_buffers, priv->buffers); + this->output->buffer_mem = impl->buffer_mem; + impl->allocated = FALSE; + pinos_log_debug ("allocated %d buffers %p from output port", impl->n_buffers, impl->buffers); } else if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) { if ((res = spa_node_port_alloc_buffers (this->input->node->node, SPA_DIRECTION_INPUT, this->input->port, oinfo->params, oinfo->n_params, - priv->buffers, &priv->n_buffers)) < 0) { + impl->buffers, &impl->n_buffers)) < 0) { g_set_error (&error, PINOS_ERROR, PINOS_ERROR_BUFFER_ALLOCATION, "error alloc input buffers: %d", res); goto error; } - this->input->buffers = priv->buffers; - this->input->n_buffers = priv->n_buffers; + this->input->buffers = impl->buffers; + this->input->n_buffers = impl->n_buffers; this->input->allocated = TRUE; - this->input->buffer_mem = priv->buffer_mem; - priv->allocated = FALSE; - pinos_log_debug ("allocated %d buffers %p from input port", priv->n_buffers, priv->buffers); + this->input->buffer_mem = impl->buffer_mem; + impl->allocated = FALSE; + pinos_log_debug ("allocated %d buffers %p from input port", impl->n_buffers, impl->buffers); } } if (in_flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS) { - pinos_log_debug ("using %d buffers %p on input port", priv->n_buffers, priv->buffers); + pinos_log_debug ("using %d buffers %p on input port", impl->n_buffers, impl->buffers); if ((res = spa_node_port_use_buffers (this->input->node->node, SPA_DIRECTION_INPUT, this->input->port, - priv->buffers, - priv->n_buffers)) < 0) { + impl->buffers, + impl->n_buffers)) < 0) { g_set_error (&error, PINOS_ERROR, PINOS_ERROR_BUFFER_ALLOCATION, "error use input buffers: %d", res); goto error; } - this->input->buffers = priv->buffers; - this->input->n_buffers = priv->n_buffers; + this->input->buffers = impl->buffers; + this->input->n_buffers = impl->n_buffers; this->input->allocated = FALSE; } else if (out_flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS) { - pinos_log_debug ("using %d buffers %p on output port", priv->n_buffers, priv->buffers); + pinos_log_debug ("using %d buffers %p on output port", impl->n_buffers, impl->buffers); if ((res = spa_node_port_use_buffers (this->output->node->node, SPA_DIRECTION_OUTPUT, this->output->port, - priv->buffers, - priv->n_buffers)) < 0) { + impl->buffers, + impl->n_buffers)) < 0) { g_set_error (&error, PINOS_ERROR, PINOS_ERROR_BUFFER_ALLOCATION, "error use output buffers: %d", res); goto error; } - this->output->buffers = priv->buffers; - this->output->n_buffers = priv->n_buffers; + this->output->buffers = impl->buffers; + this->output->n_buffers = impl->n_buffers; this->output->allocated = FALSE; } else { g_set_error (&error, @@ -706,7 +608,7 @@ check_states (PinosLink *this, SpaResult res) { SpaNodeState in_state, out_state; - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; if (res != SPA_RESULT_OK) { pinos_log_warn ("link %p: error: %d", this, res); @@ -739,143 +641,143 @@ again: return SPA_RESULT_OK; exit: - pinos_main_loop_defer (priv->main_loop, this, res, (PinosDeferFunc) check_states, this, NULL); + pinos_main_loop_defer (impl->core->main_loop, this, res, (PinosDeferFunc) check_states, this, NULL); return res; } static void -on_async_complete_notify (PinosNode *node, - guint seq, - guint res, - PinosLink *this) +on_input_async_complete_notify (PinosListener *listener, + void *object, + void *data) { - PinosLinkPrivate *priv = this->priv; - pinos_log_debug ("link %p: node %p async complete %d %d", this, node, seq, res); - pinos_main_loop_defer_complete (priv->main_loop, this, seq, res); + PinosNode *node = object; + PinosNodeAsyncCompleteData *d = data; + PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, input_async_complete); + + 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); } +static void +on_output_async_complete_notify (PinosListener *listener, + void *object, + void *data) +{ + PinosNode *node = object; + PinosNodeAsyncCompleteData *d = data; + PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, output_async_complete); + + 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); +} + +#if 0 static void on_property_notify (GObject *obj, GParamSpec *pspec, gpointer user_data) { PinosLink *this = user_data; - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "output-port") == 0) { if (this->output) { - pinos_link1_set_output_node (priv->iface, pinos_node_get_object_path (this->output->node)); - pinos_link1_set_output_port (priv->iface, this->output->port); + pinos_link1_set_output_node (impl->iface, pinos_node_get_object_path (this->output->node)); + pinos_link1_set_output_port (impl->iface, this->output->port); } else { - pinos_link1_set_output_node (priv->iface, "/"); - pinos_link1_set_output_port (priv->iface, -1); + pinos_link1_set_output_node (impl->iface, "/"); + pinos_link1_set_output_port (impl->iface, -1); } } if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "input-port") == 0) { if (this->input) { - pinos_link1_set_input_node (priv->iface, pinos_node_get_object_path (this->input->node)); - pinos_link1_set_input_port (priv->iface, this->input->port); + pinos_link1_set_input_node (impl->iface, pinos_node_get_object_path (this->input->node)); + pinos_link1_set_input_port (impl->iface, this->input->port); } else { - pinos_link1_set_input_node (priv->iface, "/"); - pinos_link1_set_input_port (priv->iface, -1); + pinos_link1_set_input_node (impl->iface, "/"); + pinos_link1_set_input_port (impl->iface, -1); } } } - -typedef struct { - PinosLink *link; - PinosPort *port; -} UnlinkedData; +#endif static void on_port_unlinked (PinosPort *port, PinosLink *this, SpaResult res, gulong id) { - g_signal_emit (this, signals[SIGNAL_PORT_UNLINKED], 0, port); + pinos_signal_emit (&this->port_unlinked, this, port); if (this->input == NULL || this->output == NULL) pinos_link_update_state (this, PINOS_LINK_STATE_UNLINKED); } static void -on_node_remove (PinosNode *node, PinosLink *this) +on_port_destroy (PinosLink *this, + PinosPort *port) { - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; + PinosPort *other; SpaResult res = SPA_RESULT_OK; - PinosPort *port, *other; - g_signal_handlers_disconnect_by_data (node, this); - - if (this->input && node == this->input->node) { - port = this->input; + if (port == this->input) { other = this->output; - } else if (this->output && node == this->output->node) { - port = this->output; + } else if (port == this->output) { other = this->input; } else return; if (port->allocated) { - priv->buffers = NULL; - priv->n_buffers = 0; + impl->buffers = NULL; + impl->n_buffers = 0; pinos_log_debug ("link %p: clear input allocated buffers on port %p", link, other); pinos_port_clear_buffers (other); } res = pinos_port_unlink (port, this); - pinos_main_loop_defer (priv->main_loop, + pinos_main_loop_defer (impl->core->main_loop, port, res, (PinosDeferFunc) on_port_unlinked, - g_object_ref (this), - g_object_unref); + this, + NULL); } static void -pinos_link_constructed (GObject * object) +on_input_port_destroy (PinosListener *listener, + void *object, + void *data) { - PinosLink *this = PINOS_LINK (object); - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, input_port_destroy); + PinosPort *port = object; - priv->main_loop = priv->daemon->main_loop; - - g_signal_connect (this->input->node, "remove", (GCallback) on_node_remove, this); - g_signal_connect (this->output->node, "remove", (GCallback) on_node_remove, this); - - g_signal_connect (this->input->node, "async-complete", (GCallback) on_async_complete_notify, this); - g_signal_connect (this->output->node, "async-complete", (GCallback) on_async_complete_notify, this); - - g_signal_connect (this, "notify", (GCallback) on_property_notify, this); - - G_OBJECT_CLASS (pinos_link_parent_class)->constructed (object); - - pinos_object_init (&this->object, - priv->daemon->registry.uri.link, - this, - NULL); - pinos_registry_add_object (&priv->daemon->registry, &this->object); - - on_property_notify (G_OBJECT (this), NULL, this); - pinos_log_debug ("link %p: constructed %p:%d -> %p:%d", this, - this->output->node, this->output->port, - this->input->node, this->input->port); - link_register_object (this); + on_port_destroy (&impl->link, port); + pinos_signal_remove (listener); } static void -pinos_link_dispose (GObject * object) +on_output_port_destroy (PinosListener *listener, + void *object, + void *data) { - PinosLink *this = PINOS_LINK (object); - PinosLinkPrivate *priv = this->priv; + PinosLinkImpl *impl = SPA_CONTAINER_OF (listener, PinosLinkImpl, output_port_destroy); + PinosPort *port = object; - pinos_log_debug ("link %p: dispose", this); + on_port_destroy (&impl->link, port); + pinos_signal_remove (listener); +} - if (this->input && this->input->node) - g_signal_handlers_disconnect_by_data (this->input->node, this); - if (this->output && this->output->node) - g_signal_handlers_disconnect_by_data (this->output->node, this); +static void +link_destroy (PinosObject * object) +{ + PinosLinkImpl *impl = (PinosLinkImpl *) object; + PinosLink *this = &impl->link; - g_signal_emit (this, signals[SIGNAL_REMOVE], 0, NULL); + 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); @@ -884,145 +786,105 @@ pinos_link_dispose (GObject * object) link_unregister_object (this); - pinos_main_loop_defer_cancel (priv->main_loop, this, 0); + pinos_main_loop_defer_cancel (impl->core->main_loop, this, 0); - G_OBJECT_CLASS (pinos_link_parent_class)->dispose (object); + 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 void -pinos_link_finalize (GObject * object) + +static bool +link_activate (PinosLink *this) { - PinosLink *this = PINOS_LINK (object); - PinosLinkPrivate *priv = this->priv; - - pinos_log_debug ("link %p: finalize", this); - - pinos_registry_remove_object (&priv->daemon->registry, &this->object); - - g_clear_object (&priv->daemon); - g_clear_object (&priv->iface); - g_free (priv->object_path); - - if (priv->allocated) - pinos_memblock_free (&priv->buffer_mem); - - G_OBJECT_CLASS (pinos_link_parent_class)->finalize (object); + spa_ringbuffer_init (&this->ringbuffer, SPA_N_ELEMENTS (this->queue)); + check_states (this, NULL, SPA_RESULT_OK); + return true; } -static void -pinos_link_class_init (PinosLinkClass * klass) +static bool +pinos_link_deactivate (PinosLink *this) { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - //PinosLinkClass *link_class = PINOS_LINK_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosLinkPrivate)); - - gobject_class->constructed = pinos_link_constructed; - gobject_class->dispose = pinos_link_dispose; - gobject_class->finalize = pinos_link_finalize; - gobject_class->set_property = pinos_link_set_property; - gobject_class->get_property = pinos_link_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The Daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_OUTPUT_PORT, - g_param_spec_pointer ("output-port", - "Output Port", - "The output port", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_INPUT_PORT, - g_param_spec_pointer ("input-port", - "Input Port", - "The input port", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_FORMAT_FILTER, - g_param_spec_boxed ("format-filter", - "format Filter", - "The format filter", - G_TYPE_PTR_ARRAY, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "The properties of the link", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_STATE, - g_param_spec_enum ("state", - "State", - "The state of the link", - PINOS_TYPE_LINK_STATE, - PINOS_LINK_STATE_INIT, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - signals[SIGNAL_REMOVE] = g_signal_new ("remove", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 0, - G_TYPE_NONE); - signals[SIGNAL_PORT_UNLINKED] = g_signal_new ("port-unlinked", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); + spa_ringbuffer_clear (&this->ringbuffer); + return true; } -static void -pinos_link_init (PinosLink * this) +PinosLink * +pinos_link_new (PinosCore *core, + PinosPort *input, + PinosPort *output, + GPtrArray *format_filter, + PinosProperties *properties) { - PinosLinkPrivate *priv = this->priv = PINOS_LINK_GET_PRIVATE (this); + PinosLinkImpl *impl; + PinosLink *this; - priv->iface = pinos_link1_skeleton_new (); + impl = calloc (1, sizeof (PinosLinkImpl)); + this = &impl->link; pinos_log_debug ("link %p: new", this); - priv->state = PINOS_LINK_STATE_INIT; + + 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; + + 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); + + impl->output_port_destroy.notify = on_output_port_destroy; + pinos_signal_add (&this->output->object.destroy_signal, &impl->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); + + 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_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; } /** - * pinos_link_remove: + * pinos_link_destroy: * @link: a #PinosLink * * Trigger removal of @link */ void -pinos_link_remove (PinosLink *this) +pinos_link_destroy (PinosLink *this) { - pinos_log_debug ("link %p: remove", this); - g_signal_emit (this, signals[SIGNAL_REMOVE], 0, NULL); + pinos_log_debug ("link %p: destroy", this); + pinos_signal_emit (&this->object.destroy_signal, this, NULL); } /** @@ -1036,43 +898,23 @@ pinos_link_remove (PinosLink *this) const gchar * pinos_link_get_object_path (PinosLink *this) { - PinosLinkPrivate *priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; - g_return_val_if_fail (PINOS_IS_LINK (this), NULL); - priv = this->priv; + g_return_val_if_fail (impl, NULL); - return priv->object_path; + return impl->object_path; } PinosLinkState pinos_link_get_state (PinosLink *this, GError **error) { - PinosLinkPrivate *priv; + PinosLinkImpl *impl = (PinosLinkImpl *) this; - g_return_val_if_fail (PINOS_IS_LINK (this), PINOS_LINK_STATE_ERROR); - priv = this->priv; + g_return_val_if_fail (impl, PINOS_LINK_STATE_ERROR); if (error) - *error = priv->error; + *error = impl->error; - return priv->state; -} - -gboolean -pinos_link_activate (PinosLink *this) -{ - g_return_val_if_fail (PINOS_IS_LINK (this), FALSE); - - spa_ringbuffer_init (&this->ringbuffer, SPA_N_ELEMENTS (this->queue)); - check_states (this, NULL, SPA_RESULT_OK); - - return TRUE; -} - -gboolean -pinos_link_deactivate (PinosLink *this) -{ - spa_ringbuffer_clear (&this->ringbuffer); - return TRUE; + return impl->state; } diff --git a/pinos/server/link.h b/pinos/server/link.h index 721090344..ad3e12814 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -28,8 +28,6 @@ G_BEGIN_DECLS #define PINOS_LINK_PREFIX PINOS_LINK_URI "#" typedef struct _PinosLink PinosLink; -typedef struct _PinosLinkClass PinosLinkClass; -typedef struct _PinosLinkPrivate PinosLinkPrivate; #include @@ -39,59 +37,42 @@ typedef struct _PinosLinkPrivate PinosLinkPrivate; #include #include -#define PINOS_TYPE_LINK (pinos_link_get_type ()) -#define PINOS_IS_LINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_LINK)) -#define PINOS_IS_LINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_LINK)) -#define PINOS_LINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_LINK, PinosLinkClass)) -#define PINOS_LINK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_LINK, PinosLink)) -#define PINOS_LINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_LINK, PinosLinkClass)) -#define PINOS_LINK_CAST(obj) ((PinosLink*)(obj)) -#define PINOS_LINK_CLASS_CAST(klass)((PinosLinkClass*)(klass)) - /** * PinosLink: * - * Pinos link object class. + * Pinos link interface. */ struct _PinosLink { - GObject obj; + PinosProperties *properties; - PinosObject object; + PinosLinkState state; + GError *error; PinosPort *output; PinosPort *input; + PinosSignal port_unlinked; + PinosSignal notify_state; + uint32_t queue[64]; SpaRingbuffer ringbuffer; gint in_ready; - PinosLinkPrivate *priv; + bool (*activate) (PinosLink *link); + bool (*deactivate) (PinosLink *link); }; -/** - * PinosLinkClass: - * - * Pinos link object class. - */ -struct _PinosLinkClass { - GObjectClass parent_class; -}; +PinosObject * pinos_link_new (PinosCore *core, + PinosPort *input, + PinosPort *output, + GPtrArray *format_filter, + PinosProperties *properties); -/* normal GObject stuff */ -GType pinos_link_get_type (void); - -void pinos_link_remove (PinosLink *link); - -PinosProperties * pinos_link_get_properties (PinosLink *link); +#define pinos_link_activate(l) (l)->activate(l) +#define pinos_link_deactivate(l) (l)->deactivate(l) const gchar * pinos_link_get_object_path (PinosLink *link); -gboolean pinos_link_activate (PinosLink *link); -gboolean pinos_link_deactivate (PinosLink *link); - -PinosLinkState pinos_link_get_state (PinosLink *link, - GError **error); - G_END_DECLS #endif /* __PINOS_LINK_H__ */ diff --git a/pinos/server/main-loop.c b/pinos/server/main-loop.c index f98669245..7f11bba39 100644 --- a/pinos/server/main-loop.c +++ b/pinos/server/main-loop.c @@ -28,6 +28,7 @@ #include "spa/include/spa/list.h" #include "spa/include/spa/ringbuffer.h" #include "pinos/client/log.h" +#include "pinos/client/object.h" #include "pinos/server/main-loop.h" #define PINOS_MAIN_LOOP_GET_PRIVATE(loop) \ @@ -48,21 +49,27 @@ typedef struct _WorkItem WorkItem; struct _WorkItem { gulong id; - gpointer obj; + void *obj; uint32_t seq; SpaResult res; PinosDeferFunc func; - gpointer *data; + void *data; GDestroyNotify notify; SpaList list; }; -struct _PinosMainLoopPrivate +typedef struct { + PinosMainLoop this; + + PinosObject object; + + SpaPoll poll; + GMainContext *context; GMainLoop *loop; - gulong counter; + uint32_t counter; SpaRingbuffer buffer; uint8_t buffer_data[DATAS_SIZE]; @@ -74,20 +81,7 @@ struct _PinosMainLoopPrivate WorkItem *free_list; gulong work_id; -}; - -G_DEFINE_TYPE (PinosMainLoop, pinos_main_loop, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_MAIN_CONTEXT, -}; - -enum -{ - LAST_SIGNAL -}; +} PinosMainLoopImpl; typedef struct { PinosMainLoop *loop; @@ -97,7 +91,7 @@ typedef struct { static gboolean poll_event (GIOChannel *source, GIOCondition condition, - gpointer user_data) + void * user_data) { PollData *data = user_data; SpaPollNotifyData d; @@ -160,20 +154,19 @@ do_remove_item (SpaPoll *poll, static int main_loop_dispatch (SpaPollNotifyData *data) { - PinosMainLoop *this = data->user_data; - PinosMainLoopPrivate *priv = this->priv; - SpaPoll *p = &this->poll; + PinosMainLoopImpl *impl = data->user_data; + SpaPoll *p = &impl->poll; uint64_t u; size_t offset; InvokeItem *item; - 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 ("main-loop %p: failed to read fd", strerror (errno)); - while (spa_ringbuffer_get_read_offset (&priv->buffer, &offset) > 0) { - item = SPA_MEMBER (priv->buffer_data, offset, InvokeItem); + while (spa_ringbuffer_get_read_offset (&impl->buffer, &offset) > 0) { + 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); } return 0; @@ -187,8 +180,7 @@ do_invoke (SpaPoll *poll, void *data, void *user_data) { - PinosMainLoop *this = SPA_CONTAINER_OF (poll, PinosMainLoop, poll); - PinosMainLoopPrivate *priv = this->priv; + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (poll, PinosMainLoopImpl, poll); gboolean in_thread = FALSE; SpaRingbufferArea areas[2]; InvokeItem *item; @@ -198,12 +190,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; @@ -215,14 +207,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); - if (write (priv->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) + if (write (impl->fds[0].fd, &u, sizeof(uint64_t)) != sizeof(uint64_t)) pinos_log_warn ("data-loop %p: failed to write fd", strerror (errno)); res = SPA_RESULT_RETURN_ASYNC (seq); @@ -230,164 +222,15 @@ do_invoke (SpaPoll *poll, return res; } -static void -pinos_main_loop_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosMainLoop *loop = PINOS_MAIN_LOOP (_object); - PinosMainLoopPrivate *priv = loop->priv; - - switch (prop_id) { - case PROP_MAIN_CONTEXT: - g_value_set_boxed (value, priv->context); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (loop, prop_id, pspec); - break; - } -} - -static void -pinos_main_loop_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosMainLoop *loop = PINOS_MAIN_LOOP (_object); - PinosMainLoopPrivate *priv = loop->priv; - - switch (prop_id) { - case PROP_MAIN_CONTEXT: - priv->context = g_value_dup_boxed (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (loop, prop_id, pspec); - break; - } -} - - -static void -pinos_main_loop_constructed (GObject * obj) -{ - PinosMainLoop *this = PINOS_MAIN_LOOP (obj); - PinosMainLoopPrivate *priv = this->priv; - - pinos_log_debug ("main-loop %p: constructed", this); - priv->loop = g_main_loop_new (priv->context, FALSE); - - priv->fds[0].fd = eventfd (0, 0); - priv->fds[0].events = POLLIN | POLLPRI | POLLERR; - priv->fds[0].revents = 0; - - priv->wakeup.id = SPA_ID_INVALID; - priv->wakeup.enabled = false; - priv->wakeup.fds = priv->fds; - priv->wakeup.n_fds = 1; - priv->wakeup.idle_cb = NULL; - priv->wakeup.before_cb = NULL; - priv->wakeup.after_cb = main_loop_dispatch; - priv->wakeup.user_data = this; - do_add_item (&this->poll, &priv->wakeup); - - G_OBJECT_CLASS (pinos_main_loop_parent_class)->constructed (obj); -} - -static void -pinos_main_loop_dispose (GObject * obj) -{ - PinosMainLoop *this = PINOS_MAIN_LOOP (obj); - - pinos_log_debug ("main-loop %p: dispose", this); - - G_OBJECT_CLASS (pinos_main_loop_parent_class)->dispose (obj); -} - -static void -pinos_main_loop_finalize (GObject * obj) -{ - PinosMainLoop *this = PINOS_MAIN_LOOP (obj); - PinosMainLoopPrivate *priv = this->priv; - - pinos_log_debug ("main-loop %p: finalize", this); - - g_slice_free_chain (WorkItem, priv->free_list, list.next); - - G_OBJECT_CLASS (pinos_main_loop_parent_class)->finalize (obj); -} - -static void -pinos_main_loop_class_init (PinosMainLoopClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosMainLoopPrivate)); - - gobject_class->constructed = pinos_main_loop_constructed; - gobject_class->dispose = pinos_main_loop_dispose; - gobject_class->finalize = pinos_main_loop_finalize; - gobject_class->set_property = pinos_main_loop_set_property; - gobject_class->get_property = pinos_main_loop_get_property; - - g_object_class_install_property (gobject_class, - PROP_MAIN_CONTEXT, - g_param_spec_boxed ("main-context", - "Main Context", - "The main context to use", - G_TYPE_MAIN_CONTEXT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - -} - -static void -pinos_main_loop_init (PinosMainLoop * this) -{ - PinosMainLoopPrivate *priv = this->priv = PINOS_MAIN_LOOP_GET_PRIVATE (this); - - pinos_log_debug ("main-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_list_init (&priv->work); - spa_ringbuffer_init (&priv->buffer, DATAS_SIZE); -} - -/** - * pinos_main_loop_new: - * @context: a #GMainContext or %NULL to use the default context - * - * Create a new #PinosMainLoop. - * - * Returns: a new #PinosMainLoop - */ -PinosMainLoop * -pinos_main_loop_new (GMainContext *context) -{ - return g_object_new (PINOS_TYPE_MAIN_LOOP, - "main-context", context, - NULL); -} - static gboolean process_work_queue (PinosMainLoop *this) { - PinosMainLoopPrivate *priv = this->priv; + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (this, PinosMainLoopImpl, this); WorkItem *item, *tmp; - priv->work_id = 0; + impl->work_id = 0; - spa_list_for_each_safe (item, tmp, &priv->work, list) { + spa_list_for_each_safe (item, tmp, &impl->work, list) { if (item->seq != SPA_ID_INVALID) continue; @@ -400,34 +243,31 @@ process_work_queue (PinosMainLoop *this) if (item->notify) item->notify (item->data); - item->list.next = &priv->free_list->list; - priv->free_list = item; + item->list.next = &impl->free_list->list; + impl->free_list = item; } return FALSE; } -gulong -pinos_main_loop_defer (PinosMainLoop *loop, - gpointer obj, - SpaResult res, - PinosDeferFunc func, - gpointer data, - GDestroyNotify notify) +static uint32_t +main_loop_defer (PinosMainLoop *loop, + void *obj, + SpaResult res, + PinosDeferFunc func, + void *data, + GDestroyNotify notify) { - PinosMainLoopPrivate *priv; + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); WorkItem *item; - gboolean have_work = FALSE; + bool have_work = false; - g_return_val_if_fail (PINOS_IS_MAIN_LOOP (loop), 0); - priv = loop->priv; - - if (priv->free_list) { - item = priv->free_list; - priv->free_list = SPA_CONTAINER_OF (item->list.next, WorkItem, list); + if (impl->free_list) { + item = impl->free_list; + impl->free_list = SPA_CONTAINER_OF (item->list.next, WorkItem, list); } else { item = g_slice_new (WorkItem); } - item->id = ++priv->counter; + item->id = ++impl->counter; item->obj = obj; item->func = func; item->data = data; @@ -443,52 +283,46 @@ pinos_main_loop_defer (PinosMainLoop *loop, have_work = TRUE; pinos_log_debug ("main-loop %p: defer object %p", loop, obj); } - spa_list_insert (priv->work.prev, &item->list); + spa_list_insert (impl->work.prev, &item->list); - if (priv->work_id == 0 && have_work) - priv->work_id = g_idle_add ((GSourceFunc) process_work_queue, loop); + if (impl->work_id == 0 && have_work) + impl->work_id = g_idle_add ((GSourceFunc) process_work_queue, loop); return item->id; } -void -pinos_main_loop_defer_cancel (PinosMainLoop *loop, - gpointer obj, - gulong id) +static void +main_loop_defer_cancel (PinosMainLoop *loop, + void *obj, + uint32_t id) { - PinosMainLoopPrivate *priv; - gboolean have_work = FALSE; + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + bool have_work = false; WorkItem *item; - g_return_if_fail (PINOS_IS_MAIN_LOOP (loop)); - priv = loop->priv; - - spa_list_for_each (item, &priv->work, list) { + spa_list_for_each (item, &impl->work, list) { if ((id == 0 || item->id == id) && (obj == NULL || item->obj == obj)) { pinos_log_debug ("main-loop %p: cancel defer %d for object %p", loop, item->seq, item->obj); item->seq = SPA_ID_INVALID; item->func = NULL; - have_work = TRUE; + have_work = true; } } - if (priv->work_id == 0 && have_work) - priv->work_id = g_idle_add ((GSourceFunc) process_work_queue, loop); + if (impl->work_id == 0 && have_work) + impl->work_id = g_idle_add ((GSourceFunc) process_work_queue, loop); } -gboolean -pinos_main_loop_defer_complete (PinosMainLoop *loop, - gpointer obj, - uint32_t seq, - SpaResult res) +static bool +main_loop_defer_complete (PinosMainLoop *loop, + void *obj, + uint32_t seq, + SpaResult res) { WorkItem *item; - PinosMainLoopPrivate *priv; - gboolean have_work = FALSE; + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + bool have_work = false; - g_return_val_if_fail (PINOS_IS_MAIN_LOOP (loop), FALSE); - priv = loop->priv; - - spa_list_for_each (item, &priv->work, list) { + spa_list_for_each (item, &impl->work, list) { if (item->obj == obj && item->seq == seq) { pinos_log_debug ("main-loop %p: found defered %d for object %p", loop, seq, obj); item->seq = SPA_ID_INVALID; @@ -499,32 +333,88 @@ pinos_main_loop_defer_complete (PinosMainLoop *loop, if (!have_work) pinos_log_debug ("main-loop %p: no defered %d found for object %p", loop, seq, obj); - if (priv->work_id == 0 && have_work) - priv->work_id = g_idle_add ((GSourceFunc) process_work_queue, loop); + if (impl->work_id == 0 && have_work) + impl->work_id = g_idle_add ((GSourceFunc) process_work_queue, loop); return have_work; } -GMainLoop * -pinos_main_loop_get_impl (PinosMainLoop *loop) +static void +main_loop_quit (PinosMainLoop *loop) { - g_return_val_if_fail (PINOS_IS_MAIN_LOOP (loop), NULL); + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + g_main_loop_quit (impl->loop); +} - return loop->priv->loop; +static void +main_loop_run (PinosMainLoop *loop) +{ + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); + g_main_loop_run (impl->loop); } void -pinos_main_loop_quit (PinosMainLoop *loop) +pinos_main_loop_destroy (PinosMainLoop *loop) { - g_return_if_fail (PINOS_IS_MAIN_LOOP (loop)); + PinosMainLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosMainLoopImpl, this); - g_main_loop_quit (loop->priv->loop); + pinos_log_debug ("main-loop %p: destroy", impl); + + g_slice_free_chain (WorkItem, impl->free_list, list.next); + free (impl); } -void -pinos_main_loop_run (PinosMainLoop *loop) +/** + * pinos_main_loop_new: + * @context: a #GMainContext or %NULL to use the default context + * + * Create a new #PinosMainLoop. + * + * Returns: a new #PinosMainLoop + */ +PinosMainLoop * +pinos_main_loop_new (GMainContext *context) { - g_return_if_fail (PINOS_IS_MAIN_LOOP (loop)); + PinosMainLoopImpl *impl; + PinosMainLoop *this; - g_main_loop_run (loop->priv->loop); + impl = calloc (1, sizeof (PinosMainLoopImpl)); + pinos_log_debug ("main-loop %p: new", impl); + + impl->context = context; + this = &impl->this; + this->run = main_loop_run; + this->quit = main_loop_quit; + this->defer = main_loop_defer; + this->defer_cancel = main_loop_defer_cancel; + this->defer_complete = main_loop_defer_complete; + + impl->poll.size = sizeof (SpaPoll); + impl->poll.info = NULL; + impl->poll.add_item = do_add_item; + impl->poll.update_item = do_update_item; + impl->poll.remove_item = do_remove_item; + impl->poll.invoke = do_invoke; + this->poll = &impl->poll; + + spa_list_init (&impl->work); + spa_ringbuffer_init (&impl->buffer, DATAS_SIZE); + + impl->loop = g_main_loop_new (impl->context, FALSE); + + impl->fds[0].fd = eventfd (0, 0); + impl->fds[0].events = POLLIN | POLLPRI | POLLERR; + impl->fds[0].revents = 0; + + impl->wakeup.id = SPA_ID_INVALID; + impl->wakeup.enabled = false; + impl->wakeup.fds = impl->fds; + impl->wakeup.n_fds = 1; + impl->wakeup.idle_cb = NULL; + impl->wakeup.before_cb = NULL; + impl->wakeup.after_cb = main_loop_dispatch; + impl->wakeup.user_data = impl; + do_add_item (&impl->poll, &impl->wakeup); + + return this; } diff --git a/pinos/server/main-loop.h b/pinos/server/main-loop.h index 0b65e3ecd..4c6ebd44b 100644 --- a/pinos/server/main-loop.h +++ b/pinos/server/main-loop.h @@ -28,67 +28,47 @@ G_BEGIN_DECLS #include typedef struct _PinosMainLoop PinosMainLoop; -typedef struct _PinosMainLoopClass PinosMainLoopClass; -typedef struct _PinosMainLoopPrivate PinosMainLoopPrivate; -#define PINOS_TYPE_MAIN_LOOP (pinos_main_loop_get_type ()) -#define PINOS_IS_MAIN_LOOP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_MAIN_LOOP)) -#define PINOS_IS_MAIN_LOOP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_MAIN_LOOP)) -#define PINOS_MAIN_LOOP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_MAIN_LOOP, PinosMainLoopClass)) -#define PINOS_MAIN_LOOP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_MAIN_LOOP, PinosMainLoop)) -#define PINOS_MAIN_LOOP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_MAIN_LOOP, PinosMainLoopClass)) -#define PINOS_MAIN_LOOP_CAST(obj) ((PinosMainLoop*)(obj)) -#define PINOS_MAIN_LOOP_CLASS_CAST(klass) ((PinosMainLoopClass*)(klass)) +typedef void (*PinosDeferFunc) (void *obj, + void *data, + SpaResult res, + gulong id); /** * PinosMainLoop: * - * Pinos rt-loop class. + * Pinos main-loop interface. */ struct _PinosMainLoop { - GObject object; + SpaPoll *poll; - SpaPoll poll; + void (*run) (PinosMainLoop *loop); + void (*quit) (PinosMainLoop *loop); - PinosMainLoopPrivate *priv; + uint32_t (*defer) (PinosMainLoop *loop, + void *obj, + SpaResult res, + PinosDeferFunc func, + void *data, + GDestroyNotify notify); + void (*defer_cancel) (PinosMainLoop *loop, + void *obj, + uint32_t id); + bool (*defer_complete) (PinosMainLoop *loop, + void *obj, + uint32_t seq, + SpaResult res); }; -/** - * PinosMainLoopClass: - * - * Pinos rt-loop class. - */ -struct _PinosMainLoopClass { - GObjectClass parent_class; -}; - -typedef void (*PinosDeferFunc) (gpointer obj, - gpointer data, - SpaResult res, - gulong id); - -/* normal GObject stuff */ -GType pinos_main_loop_get_type (void); - PinosMainLoop * pinos_main_loop_new (GMainContext *context); +void pinos_main_loop_destroy (PinosMainLoop *loop); -GMainLoop * pinos_main_loop_get_impl (PinosMainLoop *loop); -void pinos_main_loop_run (PinosMainLoop *loop); -void pinos_main_loop_quit (PinosMainLoop *loop); +#define pinos_main_loop_run(m) (m)->run(m) +#define pinos_main_loop_quit(m) (m)->quit(m) -gulong pinos_main_loop_defer (PinosMainLoop *loop, - gpointer obj, - SpaResult res, - PinosDeferFunc func, - gpointer data, - GDestroyNotify notify); -void pinos_main_loop_defer_cancel (PinosMainLoop *loop, - gpointer obj, - gulong id); -gboolean pinos_main_loop_defer_complete (PinosMainLoop *loop, - gpointer obj, - uint32_t seq, - SpaResult res); +#define pinos_main_loop_defer(m,...) (m)->defer(m,__VA_ARGS__) +#define pinos_main_loop_defer_cancel(m,...) (m)->defer_cancel(m,__VA_ARGS__) +#define pinos_main_loop_defer_complete(m,...) (m)->defer_complete(m,__VA_ARGS__) G_END_DECLS diff --git a/pinos/server/meson.build b/pinos/server/meson.build index 81af53048..599b1048e 100644 --- a/pinos/server/meson.build +++ b/pinos/server/meson.build @@ -2,9 +2,9 @@ pinoscore_headers = [ 'client.h', 'client-node.h', 'command.h', + 'core.h', 'daemon.h', 'data-loop.h', - 'dbus-client-node.h', 'link.h', 'main-loop.h', 'module.h', @@ -17,9 +17,9 @@ pinoscore_sources = [ 'client.c', 'client-node.c', 'command.c', + 'core.c', 'daemon.c', 'data-loop.c', - 'dbus-client-node.c', 'link.c', 'main-loop.c', 'module.c', diff --git a/pinos/server/module.c b/pinos/server/module.c index 1b36862f5..cb440a49c 100644 --- a/pinos/server/module.c +++ b/pinos/server/module.c @@ -30,115 +30,26 @@ #define PINOS_SYMBOL_MODULE_INIT "pinos__module_init" -#define PINOS_MODULE_GET_PRIVATE(module) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((module), PINOS_TYPE_MODULE, PinosModulePrivate)) - -struct _PinosModulePrivate +typedef struct { + PinosModule this; + + PinosObject object; + PinosInterface ifaces[1]; + GModule *module; -}; +} PinosModuleImpl; -G_DEFINE_TYPE (PinosModule, pinos_module, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_NAME, -}; static void -pinos_module_finalize (GObject * object) +module_destroy (PinosObject * object) { - PinosModule *module = PINOS_MODULE (object); - PinosModulePrivate *priv = module->priv; + PinosModuleImpl *impl = SPA_CONTAINER_OF (object, PinosModuleImpl, object); + PinosModule *this = &impl->this; - g_clear_object (&module->daemon); - g_free (module->name); - g_module_close (priv->module); - - G_OBJECT_CLASS (pinos_module_parent_class)->finalize (object); -} - -static void -pinos_module_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosModule *module = PINOS_MODULE (object); - - switch (prop_id) { - case PROP_DAEMON: - module->daemon = g_value_dup_object (value); - break; - case PROP_NAME: - module->name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -pinos_module_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosModule *module = PINOS_MODULE (object); - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, module->daemon); - break; - case PROP_NAME: - g_value_set_string (value, module->name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -pinos_module_class_init (PinosModuleClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosModulePrivate)); - - gobject_class->finalize = pinos_module_finalize; - gobject_class->set_property = pinos_module_set_property; - gobject_class->get_property = pinos_module_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "A Pinos Daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "The name of the plugin", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} - -static void -pinos_module_init (PinosModule * module) -{ - PinosModulePrivate *priv = PINOS_MODULE_GET_PRIVATE (module); - module->priv = priv; + free (this->name); + g_module_close (impl->module); + free (impl); } GQuark @@ -153,12 +64,6 @@ pinos_module_error_quark (void) return quark; } -static PinosModule * -pinos_module_new (const gchar * name, PinosDaemon * daemon) -{ - return g_object_new (PINOS_TYPE_MODULE, "name", name, "daemon", daemon, NULL); -} - static gchar * find_module (const gchar * path, const gchar *name) { @@ -205,7 +110,7 @@ find_module (const gchar * path, const gchar *name) /** * pinos_module_load: - * @daemon: a #PinosDaemon + * @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 @@ -215,20 +120,20 @@ find_module (const gchar * path, const gchar *name) * Returns: A #PinosModule if the module could be loaded, or %NULL on failure. */ PinosModule * -pinos_module_load (PinosDaemon * daemon, - const gchar * name, - const gchar * args, - GError ** err) +pinos_module_load (PinosCore *core, + const gchar *name, + const gchar *args, + GError **err) { - PinosModule *module; - PinosModulePrivate *priv; + PinosModule *this; + PinosModuleImpl *impl; GModule *gmodule; gchar *filename = NULL; const gchar *module_dir; PinosModuleInitFunc init_func; g_return_val_if_fail (name != NULL && name[0] != '\0', NULL); - g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL); + g_return_val_if_fail (core, NULL); if (!g_module_supported ()) { g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_LOADING, @@ -281,21 +186,33 @@ pinos_module_load (PinosDaemon * daemon, return NULL; } - module = pinos_module_new (name, daemon); - priv = module->priv; - priv->module = gmodule; + impl = calloc (1, sizeof (PinosModuleImpl)); + impl->module = gmodule; + + 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 (module, (gchar *) args)) { + if (!init_func (this, (gchar *) args)) { g_set_error (err, PINOS_MODULE_ERROR, PINOS_MODULE_ERROR_INIT, "\"%s\" failed to initialize", name); - g_object_unref (module); + module_destroy (this); return NULL; } - pinos_log_debug ("loaded module: %s", module->name); + pinos_log_debug ("loaded module: %s", this->name); - return module; + return &this->object; } diff --git a/pinos/server/module.h b/pinos/server/module.h index 92d681458..17cbbc210 100644 --- a/pinos/server/module.h +++ b/pinos/server/module.h @@ -25,32 +25,16 @@ G_BEGIN_DECLS -#include +#include -#define PINOS_TYPE_MODULE (pinos_module_get_type ()) -#define PINOS_IS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_MODULE)) -#define PINOS_IS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_MODULE)) -#define PINOS_MODULE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_MODULE, PinosModuleClass)) -#define PINOS_MODULE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_MODULE, PinosModule)) -#define PINOS_MODULE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_MODULE, PinosModuleClass)) -#define PINOS_MODULE_CAST(obj) ((PinosModule*)(obj)) -#define PINOS_MODULE_CLASS_CAST(klass) ((PinosModuleClass*)(klass)) +#define PINOS_MODULE_URI "http://pinos.org/ns/module" +#define PINOS_MODULE_PREFIX PINOS_MODULE_URI "#" typedef struct _PinosModule PinosModule; -typedef struct _PinosModuleClass PinosModuleClass; -typedef struct _PinosModulePrivate PinosModulePrivate; struct _PinosModule { - GObject object; - gchar *name; - PinosDaemon *daemon; - - PinosModulePrivate *priv; -}; - -struct _PinosModuleClass { - GObjectClass parent_class; + PinosCore *core; }; GQuark pinos_module_error_quark (void); @@ -90,9 +74,7 @@ typedef enum */ typedef gboolean (*PinosModuleInitFunc) (PinosModule *module, gchar *args); -GType pinos_module_get_type (void); - -PinosModule * pinos_module_load (PinosDaemon *daemon, +PinosObject * pinos_module_load (PinosCore *core, const gchar *name, const gchar *args, GError **err); diff --git a/pinos/server/node-factory.c b/pinos/server/node-factory.c index 26c0dba96..5443b742f 100644 --- a/pinos/server/node-factory.c +++ b/pinos/server/node-factory.c @@ -19,191 +19,3 @@ #include "pinos/client/pinos.h" #include "pinos/server/node-factory.h" - -#define PINOS_NODE_FACTORY_GET_PRIVATE(factory) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((factory), PINOS_TYPE_NODE_FACTORY, PinosNodeFactoryPrivate)) - -struct _PinosNodeFactoryPrivate -{ - PinosDaemon *daemon; - - gchar *name; -}; - -G_DEFINE_ABSTRACT_TYPE (PinosNodeFactory, pinos_node_factory, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_NAME, -}; - -static void -pinos_node_factory_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosNodeFactory *factory = PINOS_NODE_FACTORY (_object); - PinosNodeFactoryPrivate *priv = factory->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec); - break; - } -} - -static void -pinos_node_factory_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosNodeFactory *factory = PINOS_NODE_FACTORY (_object); - PinosNodeFactoryPrivate *priv = factory->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_NAME: - priv->name = g_value_dup_string (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (factory, prop_id, pspec); - break; - } -} - -static void -pinos_node_factory_constructed (GObject * obj) -{ - PinosNodeFactory *factory = PINOS_NODE_FACTORY (obj); - PinosNodeFactoryPrivate *priv = factory->priv; - - g_debug ("node factory %p: constructed", factory); - - pinos_object_init (&factory->object, - priv->daemon->registry.uri.node_factory, - factory, - NULL); - - pinos_registry_add_object (&priv->daemon->registry, &factory->object); - - G_OBJECT_CLASS (pinos_node_factory_parent_class)->constructed (obj); -} - -static void -pinos_node_factory_finalize (GObject * obj) -{ - PinosNodeFactory *factory = PINOS_NODE_FACTORY (obj); - PinosNodeFactoryPrivate *priv = factory->priv; - - g_debug ("node factory %p: finalize", factory); - pinos_registry_remove_object (&priv->daemon->registry, &factory->object); - - g_free (priv->name); - - G_OBJECT_CLASS (pinos_node_factory_parent_class)->finalize (obj); -} - -static void -pinos_node_factory_class_init (PinosNodeFactoryClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosNodeFactoryPrivate)); - - gobject_class->constructed = pinos_node_factory_constructed; - gobject_class->finalize = pinos_node_factory_finalize; - gobject_class->set_property = pinos_node_factory_set_property; - gobject_class->get_property = pinos_node_factory_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The Daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "The node factory name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); -} - -static void -pinos_node_factory_init (PinosNodeFactory * factory) -{ - factory->priv = PINOS_NODE_FACTORY_GET_PRIVATE (factory); - - g_debug ("node_factory %p: new", factory); -} - -/** - * pinos_node_factory_get_name: - * @factory: a #PinosNodeFactory - * - * Get the name of @factory - * - * Returns: the name of @factory - */ -const gchar * -pinos_node_factory_get_name (PinosNodeFactory *factory) -{ - PinosNodeFactoryPrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE_FACTORY (factory), NULL); - priv = factory->priv; - - return priv->name; -} - -/** - * pinos_node_factory_create_node: - * @factory: A #PinosNodeFactory - * @client: the owner client - * @name: node name - * @props: #PinosProperties for the node - * - * Create a #PinosNode - * - * Returns: (transfer full) (nullable): a new #PinosNode. - */ -PinosNode * -pinos_node_factory_create_node (PinosNodeFactory *factory, - PinosClient *client, - const gchar *name, - PinosProperties *props) -{ - PinosNodeFactoryClass *klass; - - g_return_val_if_fail (PINOS_IS_NODE_FACTORY (factory), NULL); - - klass = PINOS_NODE_FACTORY_GET_CLASS (factory); - if (!klass->create_node) - return NULL; - - g_debug ("node factory %p: create node", factory); - return klass->create_node (factory, factory->priv->daemon, client, name, props); -} diff --git a/pinos/server/node-factory.h b/pinos/server/node-factory.h index 41819a070..548005a79 100644 --- a/pinos/server/node-factory.h +++ b/pinos/server/node-factory.h @@ -28,59 +28,25 @@ G_BEGIN_DECLS #define PINOS_NODE_FACTORY_PREFIX PINOS_NODE_FACTORY_URI "#" typedef struct _PinosNodeFactory PinosNodeFactory; -typedef struct _PinosNodeFactoryClass PinosNodeFactoryClass; -typedef struct _PinosNodeFactoryPrivate PinosNodeFactoryPrivate; -#include +#include #include -#define PINOS_TYPE_NODE_FACTORY (pinos_node_factory_get_type ()) -#define PINOS_IS_NODE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_NODE_FACTORY)) -#define PINOS_IS_NODE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_NODE_FACTORY)) -#define PINOS_NODE_FACTORY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_NODE_FACTORY, PinosNodeFactoryClass)) -#define PINOS_NODE_FACTORY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_NODE_FACTORY, PinosNodeFactory)) -#define PINOS_NODE_FACTORY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_NODE_FACTORY, PinosNodeFactoryClass)) -#define PINOS_NODE_FACTORY_CAST(obj) ((PinosNodeFactory*)(obj)) -#define PINOS_NODE_FACTORY_CLASS_CAST(klass) ((PinosNodeFactoryClass*)(klass)) - /** * PinosNodeFactory: * - * Pinos node factory class. + * Pinos node factory interface. */ struct _PinosNodeFactory { - GObject obj; - - PinosObject object; - - PinosNodeFactoryPrivate *priv; -}; - -/** - * PinosNodeFactoryClass: - * @create_node: make a new node - * - * Pinos node factory class. - */ -struct _PinosNodeFactoryClass { - GObjectClass parent_class; + const char *name; PinosNode * (*create_node) (PinosNodeFactory *factory, - PinosDaemon *daemon, PinosClient *client, const gchar *name, PinosProperties *properties); }; -/* normal GObject stuff */ -GType pinos_node_factory_get_type (void); - -PinosNode * pinos_node_factory_create_node (PinosNodeFactory *factory, - PinosClient *client, - const gchar *name, - PinosProperties *props); - -const gchar * pinos_node_factory_get_name (PinosNodeFactory *node_factory); +#define pinos_node_factory_create_node(f,...) (f)->create_node((f),__VA_ARGS__) G_END_DECLS diff --git a/pinos/server/node.c b/pinos/server/node.c index c7d22b2a1..6573af1f9 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -31,14 +31,11 @@ #include "pinos/dbus/org-pinos.h" -#define PINOS_NODE_GET_PRIVATE(node) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((node), PINOS_TYPE_NODE, PinosNodePrivate)) - static PinosPort * new_pinos_port (PinosNode *node, PinosDirection direction, uint32_t port) { PinosPort *np; - np = g_slice_new0 (PinosPort); + np = calloc (1, sizeof (PinosPort)); np->node = node; np->direction = direction; np->port = port; @@ -53,14 +50,18 @@ free_node_port (PinosPort *np) g_slice_free (PinosPort, np); } -struct _PinosNodePrivate +typedef struct { + PinosNode node; + PinosObject object; + PinosInterface ifaces[1]; + + PinosCore *core; PinosDaemon *daemon; PinosNode1 *iface; PinosClient *client; gchar *object_path; - gchar *name; uint32_t seq; @@ -70,54 +71,23 @@ struct _PinosNodePrivate guint n_used_output_links; guint n_used_input_links; - PinosNodeState state; GError *error; guint idle_timeout; - PinosProperties *properties; - PinosDataLoop *data_loop; - PinosMainLoop *main_loop; struct { GPtrArray *links; } rt; -}; +} PinosNodeImpl; -G_DEFINE_TYPE (PinosNode, pinos_node, G_TYPE_OBJECT); - -enum -{ - PROP_0, - PROP_DAEMON, - PROP_CLIENT, - PROP_DATA_LOOP, - PROP_OBJECT_PATH, - PROP_NAME, - PROP_PROPERTIES, - PROP_NODE, - PROP_CLOCK, - PROP_TRANSPORT, -}; - -enum -{ - SIGNAL_REMOVE, - SIGNAL_STATE_CHANGE, - SIGNAL_PORT_ADDED, - SIGNAL_PORT_REMOVED, - SIGNAL_ASYNC_COMPLETE, - LAST_SIGNAL -}; static void init_complete (PinosNode *this); -static guint signals[LAST_SIGNAL] = { 0 }; - static void update_port_ids (PinosNode *node, gboolean create) { - PinosNodePrivate *priv = node->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); uint32_t *input_port_ids, *output_port_ids; guint n_input_ports, n_output_ports, max_input_ports, max_output_ports; guint i; @@ -145,7 +115,7 @@ update_port_ids (PinosNode *node, gboolean create) n_input_ports, max_input_ports, n_output_ports, max_output_ports); i = 0; - ports = priv->input_ports; + ports = impl->input_ports; while (true) { PinosPort *p = (ports ? ports->data : NULL); @@ -157,21 +127,21 @@ update_port_ids (PinosNode *node, gboolean create) pinos_log_debug ("node %p: input port added %d", node, input_port_ids[i]); np = new_pinos_port (node, PINOS_DIRECTION_INPUT, input_port_ids[i]); - priv->input_ports = g_list_insert_before (priv->input_ports, ports, np); + impl->input_ports = g_list_insert_before (impl->input_ports, ports, np); - if (!priv->async_init) - g_signal_emit (node, signals[SIGNAL_PORT_ADDED], 0, np); + if (!impl->async_init) + pinos_signal_emit (&node->port_added, node, np); i++; } else if (p) { GList *next; pinos_log_debug ("node %p: input port removed %d", node, p->port); next = g_list_next (ports); - priv->input_ports = g_list_delete_link (priv->input_ports, ports); + impl->input_ports = g_list_delete_link (impl->input_ports, ports); ports = next; - if (!priv->async_init) - g_signal_emit (node, signals[SIGNAL_PORT_REMOVED], 0, p); + if (!impl->async_init) + pinos_signal_emit (&node->port_removed, node, p); free_node_port (p); } else @@ -179,7 +149,7 @@ update_port_ids (PinosNode *node, gboolean create) } i = 0; - ports = priv->output_ports; + ports = impl->output_ports; while (true) { PinosPort *p = (ports ? ports->data : NULL); @@ -191,21 +161,21 @@ update_port_ids (PinosNode *node, gboolean create) pinos_log_debug ("node %p: output port added %d", node, output_port_ids[i]); np = new_pinos_port (node, PINOS_DIRECTION_OUTPUT, output_port_ids[i]); - priv->output_ports = g_list_insert_before (priv->output_ports, ports, np); + impl->output_ports = g_list_insert_before (impl->output_ports, ports, np); - if (!priv->async_init) - g_signal_emit (node, signals[SIGNAL_PORT_ADDED], 0, np); + if (!impl->async_init) + pinos_signal_emit (&node->port_added, node, np); i++; } else if (p) { GList *next; pinos_log_debug ("node %p: output port removed %d", node, p->port); next = g_list_next (ports); - priv->output_ports = g_list_delete_link (priv->output_ports, ports); + impl->output_ports = g_list_delete_link (impl->output_ports, ports); ports = next; - if (!priv->async_init) - g_signal_emit (node, signals[SIGNAL_PORT_REMOVED], 0, p); + if (!impl->async_init) + pinos_signal_emit (&node->port_removed, node, p); free_node_port (p); } else @@ -226,7 +196,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]); - g_object_notify (G_OBJECT (node), "transport"); + pinos_signal_emit (&node->transport_changed, node, node->transport); } static SpaResult @@ -264,13 +234,13 @@ start_node (PinosNode *this) static SpaResult suspend_node (PinosNode *this) { - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); SpaResult res = SPA_RESULT_OK; GList *walk; pinos_log_debug ("node %p: suspend node", this); - for (walk = priv->input_ports; walk; walk = g_list_next (walk)) { + for (walk = impl->input_ports; walk; walk = g_list_next (walk)) { PinosPort *p = walk->data; if ((res = spa_node_port_set_format (this->node, SPA_DIRECTION_INPUT, p->port, 0, NULL)) < 0) pinos_log_warn ("error unset format output: %d", res); @@ -280,7 +250,7 @@ suspend_node (PinosNode *this) pinos_memblock_free (&p->buffer_mem); p->allocated = FALSE; } - for (walk = priv->output_ports; walk; walk = g_list_next (walk)) { + for (walk = impl->output_ports; walk; walk = g_list_next (walk)) { PinosPort *p = walk->data; if ((res = spa_node_port_set_format (this->node, SPA_DIRECTION_OUTPUT, p->port, 0, NULL)) < 0) pinos_log_warn ("error unset format output: %d", res); @@ -356,7 +326,7 @@ static void on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) { PinosNode *this = user_data; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); switch (event->type) { case SPA_NODE_EVENT_TYPE_INVALID: @@ -370,8 +340,10 @@ 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 (priv->main_loop, this, ac->seq, ac->res)) - g_signal_emit (this, signals[SIGNAL_ASYNC_COMPLETE], 0, 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); + } break; } @@ -380,14 +352,14 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) SpaNodeEventNeedInput *ni = (SpaNodeEventNeedInput *) event; guint i; - for (i = 0; i < priv->rt.links->len; i++) { - PinosLink *link = g_ptr_array_index (priv->rt.links, i); + for (i = 0; i < impl->rt.links->len; i++) { + PinosLink *link = g_ptr_array_index (impl->rt.links, i); if (link->input == NULL || link->input->port != ni->port_id) continue; link->in_ready++; - spa_poll_invoke (&link->input->node->priv->data_loop->poll, + spa_poll_invoke (&((PinosNodeImpl*)link->input->node)->data_loop->poll, do_read_link, SPA_ID_INVALID, sizeof (PinosLink *), @@ -409,8 +381,8 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) break; } - for (i = 0; i < priv->rt.links->len; i++) { - PinosLink *link = g_ptr_array_index (priv->rt.links, i); + for (i = 0; i < impl->rt.links->len; i++) { + PinosLink *link = g_ptr_array_index (impl->rt.links, i); PinosPort *output = link->output; PinosPort *input = link->input; size_t offset; @@ -423,7 +395,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 (&link->input->node->priv->data_loop->poll, + spa_poll_invoke (&((PinosNodeImpl*)link->input->node)->data_loop->poll, do_read_link, SPA_ID_INVALID, sizeof (PinosLink *), @@ -444,8 +416,8 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) SpaNodeEventReuseBuffer *rb = (SpaNodeEventReuseBuffer *) event; guint i; - for (i = 0; i < priv->rt.links->len; i++) { - PinosLink *link = g_ptr_array_index (priv->rt.links, i); + for (i = 0; i < impl->rt.links->len; i++) { + PinosLink *link = g_ptr_array_index (impl->rt.links, i); if (link->input == NULL || link->input->port != rb->port_id || link->output == NULL) continue; @@ -469,141 +441,32 @@ 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_node_remove (this); + pinos_object_destroy (&this->object); g_dbus_method_invocation_return_value (invocation, g_variant_new ("()")); return TRUE; } -static void -pinos_node_get_property (GObject *_object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - PinosNode *this = PINOS_NODE (_object); - PinosNodePrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - g_value_set_object (value, priv->daemon); - break; - - case PROP_CLIENT: - g_value_set_object (value, priv->client); - break; - - case PROP_DATA_LOOP: - g_value_set_object (value, priv->data_loop); - break; - - case PROP_OBJECT_PATH: - g_value_set_string (value, priv->object_path); - break; - - case PROP_NAME: - g_value_set_string (value, priv->name); - break; - - case PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - - case PROP_NODE: - g_value_set_pointer (value, this->node); - break; - - case PROP_CLOCK: - g_value_set_pointer (value, this->clock); - break; - - case PROP_TRANSPORT: - g_value_set_pointer (value, this->transport); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - -static void -pinos_node_set_property (GObject *_object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - PinosNode *this = PINOS_NODE (_object); - PinosNodePrivate *priv = this->priv; - - switch (prop_id) { - case PROP_DAEMON: - priv->daemon = g_value_dup_object (value); - break; - - case PROP_CLIENT: - priv->client = g_value_get_object (value); - break; - - case PROP_DATA_LOOP: - { - SpaResult res; - - if (priv->data_loop) - g_object_unref (priv->data_loop); - priv->data_loop = g_value_dup_object (value); - - if (priv->data_loop) { - if ((res = spa_node_set_event_callback (this->node, on_node_event, this)) < 0) - pinos_log_warn ("node %p: error setting callback", this); - } - break; - } - - case PROP_NAME: - priv->name = g_value_dup_string (value); - break; - - case PROP_PROPERTIES: - if (priv->properties) - pinos_properties_free (priv->properties); - priv->properties = g_value_dup_boxed (value); - break; - - case PROP_NODE: - { - this->node = g_value_get_pointer (value); - break; - } - case PROP_CLOCK: - this->clock = g_value_get_pointer (value); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (this, prop_id, pspec); - break; - } -} - static void node_register_object (PinosNode *this) { - PinosNodePrivate *priv = this->priv; - PinosDaemon *daemon = priv->daemon; + 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, priv->iface); + pinos_object_skeleton_set_node1 (skel, impl->iface); - g_free (priv->object_path); - priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); + 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, priv->object_path, this->object.id); + pinos_log_debug ("node %p: register object %s, id %u", this, impl->object_path, impl->object.id); return; } @@ -611,11 +474,11 @@ node_register_object (PinosNode *this) static void node_unregister_object (PinosNode *this) { - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); - pinos_log_debug ("node %p: unregister object %s", this, priv->object_path); - pinos_daemon_unexport (priv->daemon, priv->object_path); - g_clear_pointer (&priv->object_path, g_free); + 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 @@ -624,63 +487,118 @@ on_property_notify (GObject *obj, gpointer user_data) { PinosNode *this = user_data; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "client") == 0) { - if (priv->client) - pinos_node1_set_owner (priv->iface, pinos_client_get_object_path (priv->client)); + if (impl->client) + pinos_node1_set_owner (impl->iface, pinos_client_get_object_path (impl->client)); else - pinos_node1_set_owner (priv->iface, pinos_daemon_get_object_path (priv->daemon)); + 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 (priv->iface, pinos_node_get_name (this)); + pinos_node1_set_name (impl->iface, this->name); } if (pspec == NULL || strcmp (g_param_spec_get_name (pspec), "properties") == 0) { - PinosProperties *props = pinos_node_get_properties (this); - pinos_node1_set_properties (priv->iface, props ? pinos_properties_to_variant (props) : NULL); + PinosProperties *props = this->properties; + pinos_node1_set_properties (impl->iface, props ? pinos_properties_to_variant (props) : NULL); } } static void init_complete (PinosNode *this) { - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); update_port_ids (this, FALSE); pinos_log_debug ("node %p: init completed", this); - priv->async_init = FALSE; + impl->async_init = FALSE; on_property_notify (G_OBJECT (this), NULL, this); pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED); } static void -pinos_node_constructed (GObject * obj) +node_destroy (PinosObject * obj) { - PinosNode *this = PINOS_NODE (obj); - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (obj, PinosNodeImpl, object); + PinosNode *this = &impl->node; - pinos_log_debug ("node %p: constructed", this); + pinos_log_debug ("node %p: destroy", this); + pinos_node_set_state (this, PINOS_NODE_STATE_SUSPENDED); - priv->main_loop = priv->daemon->main_loop; + node_unregister_object (this); - g_signal_connect (this, "notify", (GCallback) on_property_notify, this); - G_OBJECT_CLASS (pinos_node_parent_class)->constructed (obj); + pinos_main_loop_defer_cancel (impl->core->main_loop, this, 0); - pinos_object_init (&this->object, - priv->daemon->registry.uri.node, - this, - NULL); + pinos_registry_remove_object (&impl->core->registry, &impl->object); - pinos_registry_add_object (&priv->daemon->registry, &this->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); +} + +PinosNode * +pinos_node_new (PinosCore *core, + const char *name, + SpaNode *node, + SpaClock *clock, + PinosProperties *properties) +{ + PinosNodeImpl *impl; + PinosNode *this; + + impl = calloc (1, sizeof (PinosNodeImpl)); + impl->core = core; + this = &impl->node; + 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); + pinos_signal_init (&this->async_complete); + pinos_signal_init (&this->transport_changed); + + impl->iface = pinos_node1_skeleton_new (); + g_signal_connect (impl->iface, "handle-remove", + (GCallback) handle_remove, + node); + + this->state = PINOS_NODE_STATE_CREATING; + pinos_node1_set_state (impl->iface, this->state); + + impl->rt.links = g_ptr_array_new_full (256, NULL); + + //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; - if (priv->properties == NULL) - priv->properties = pinos_properties_new (NULL, NULL); + if (this->properties == NULL) + this->properties = pinos_properties_new (NULL, NULL); for (i = 0; i < this->node->info->n_items; i++) - pinos_properties_set (priv->properties, + pinos_properties_set (this->properties, this->node->info->items[i].key, this->node->info->items[i].value); } @@ -688,8 +606,8 @@ pinos_node_constructed (GObject * obj) if (this->node->state > SPA_NODE_STATE_INIT) { init_complete (this); } else { - priv->async_init = TRUE; - pinos_main_loop_defer (priv->main_loop, + impl->async_init = TRUE; + pinos_main_loop_defer (impl->core->main_loop, this, SPA_RESULT_RETURN_ASYNC (0), (PinosDeferFunc) init_complete, @@ -697,264 +615,8 @@ pinos_node_constructed (GObject * obj) NULL); } node_register_object (this); -} -static void -pinos_node_dispose (GObject * obj) -{ - PinosNode *node = PINOS_NODE (obj); - PinosNodePrivate *priv = node->priv; - - pinos_log_debug ("node %p: dispose", node); - pinos_node_set_state (node, PINOS_NODE_STATE_SUSPENDED); - - node_unregister_object (node); - - pinos_main_loop_defer_cancel (priv->main_loop, node, 0); - - G_OBJECT_CLASS (pinos_node_parent_class)->dispose (obj); -} - -static void -pinos_node_finalize (GObject * obj) -{ - PinosNode *node = PINOS_NODE (obj); - PinosNodePrivate *priv = node->priv; - - pinos_log_debug ("node %p: finalize", node); - - pinos_registry_remove_object (&priv->daemon->registry, &node->object); - - g_clear_object (&priv->daemon); - g_clear_object (&priv->iface); - g_clear_object (&priv->data_loop); - g_free (priv->name); - g_clear_error (&priv->error); - if (priv->properties) - pinos_properties_free (priv->properties); - - G_OBJECT_CLASS (pinos_node_parent_class)->finalize (obj); -} - -static void -pinos_node_class_init (PinosNodeClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - - g_type_class_add_private (klass, sizeof (PinosNodePrivate)); - - gobject_class->constructed = pinos_node_constructed; - gobject_class->dispose = pinos_node_dispose; - gobject_class->finalize = pinos_node_finalize; - gobject_class->set_property = pinos_node_set_property; - gobject_class->get_property = pinos_node_get_property; - - g_object_class_install_property (gobject_class, - PROP_DAEMON, - g_param_spec_object ("daemon", - "Daemon", - "The Daemon", - PINOS_TYPE_DAEMON, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_CLIENT, - g_param_spec_object ("client", - "Client", - "The Client", - PINOS_TYPE_CLIENT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_OBJECT_PATH, - g_param_spec_string ("object-path", - "Object Path", - "The object path", - NULL, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_NAME, - g_param_spec_string ("name", - "Name", - "The node name", - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_PROPERTIES, - g_param_spec_boxed ("properties", - "Properties", - "The properties of the node", - PINOS_TYPE_PROPERTIES, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, - PROP_NODE, - g_param_spec_pointer ("node", - "Node", - "The SPA node", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_CLOCK, - g_param_spec_pointer ("clock", - "Clock", - "The SPA clock", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_DATA_LOOP, - g_param_spec_object ("data-loop", - "Data Loop", - "The Data Loop", - PINOS_TYPE_DATA_LOOP, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, - PROP_TRANSPORT, - g_param_spec_pointer ("transport", - "Transport", - "The Transport", - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - - signals[SIGNAL_REMOVE] = g_signal_new ("remove", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 0, - G_TYPE_NONE); - signals[SIGNAL_STATE_CHANGE] = g_signal_new ("state-change", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 2, - PINOS_TYPE_NODE_STATE, - PINOS_TYPE_NODE_STATE); - signals[SIGNAL_PORT_ADDED] = g_signal_new ("port-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); - signals[SIGNAL_PORT_REMOVED] = g_signal_new ("port-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 1, - G_TYPE_POINTER); - signals[SIGNAL_ASYNC_COMPLETE] = g_signal_new ("async-complete", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, - NULL, - g_cclosure_marshal_generic, - G_TYPE_NONE, - 2, - G_TYPE_UINT, - G_TYPE_UINT); -} - -static void -pinos_node_init (PinosNode * node) -{ - PinosNodePrivate *priv = node->priv = PINOS_NODE_GET_PRIVATE (node); - - pinos_log_debug ("node %p: new", node); - priv->iface = pinos_node1_skeleton_new (); - g_signal_connect (priv->iface, "handle-remove", - (GCallback) handle_remove, - node); - priv->state = PINOS_NODE_STATE_CREATING; - pinos_node1_set_state (priv->iface, priv->state); - priv->rt.links = g_ptr_array_new_full (256, NULL); -} - -/** - * pinos_node_get_name: - * @node: a #PinosNode - * - * Get the name of @node - * - * Returns: the name of @node - */ -const gchar * -pinos_node_get_name (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; - - return priv->name; -} - -/** - * pinos_node_get_state: - * @node: a #PinosNode - * - * Get the state of @node - * - * Returns: the state of @node - */ -PinosNodeState -pinos_node_get_state (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE (node), PINOS_NODE_STATE_ERROR); - priv = node->priv; - - return priv->state; -} - -/** - * pinos_node_get_properties: - * @node: a #PinosNode - * - * Get the properties of @node - * - * Returns: the properties of @node - */ -PinosProperties * -pinos_node_get_properties (PinosNode *node) -{ - PinosNodePrivate *priv; - - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; - - return priv->properties; + return this; } /** @@ -968,12 +630,11 @@ pinos_node_get_properties (PinosNode *node) PinosDaemon * pinos_node_get_daemon (PinosNode *node) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; + g_return_val_if_fail (node, NULL); - return priv->daemon; + return impl->daemon; } /** @@ -987,12 +648,11 @@ pinos_node_get_daemon (PinosNode *node) PinosClient * pinos_node_get_client (PinosNode *node) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; + g_return_val_if_fail (node, NULL); - return priv->client; + return impl->client; } /** * pinos_node_get_object_path: @@ -1005,32 +665,29 @@ pinos_node_get_client (PinosNode *node) const gchar * pinos_node_get_object_path (PinosNode *node) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; + g_return_val_if_fail (node, NULL); - return priv->object_path; + return impl->object_path; } /** - * pinos_node_remove: + * 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_remove (PinosNode *node) +pinos_node_destroy (PinosNode *node) { - g_return_if_fail (PINOS_IS_NODE (node)); + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - if (node->flags & PINOS_NODE_FLAG_REMOVING) - return; + g_return_if_fail (impl); - pinos_log_debug ("node %p: remove", node); - node->flags |= PINOS_NODE_FLAG_REMOVING; - g_signal_emit (node, signals[SIGNAL_REMOVE], 0, NULL); + pinos_log_debug ("node %p: destroy", impl); + pinos_object_destroy (&impl->object); } /** @@ -1046,22 +703,21 @@ PinosPort * pinos_node_get_free_port (PinosNode *node, PinosDirection direction) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); guint free_port, n_ports, max_ports; GList *ports, *walk; PinosPort *port = NULL; - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; + g_return_val_if_fail (node, NULL); if (direction == PINOS_DIRECTION_INPUT) { max_ports = node->transport->area->max_inputs; n_ports = node->transport->area->n_inputs; - ports = priv->input_ports; + ports = impl->input_ports; } else { max_ports = node->transport->area->max_outputs; n_ports = node->transport->area->n_outputs; - ports = priv->output_ports; + ports = impl->output_ports; } free_port = 0; @@ -1095,10 +751,10 @@ do_add_link (SpaPoll *poll, void *user_data) { PinosNode *this = user_data; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); PinosLink *link = ((PinosLink**)data)[0]; - g_ptr_array_add (priv->rt.links, link); + g_ptr_array_add (impl->rt.links, link); return SPA_RESULT_OK; } @@ -1148,7 +804,7 @@ pinos_port_link (PinosPort *output_port, PinosProperties *properties, GError **error) { - PinosNodePrivate *priv; + PinosNodeImpl *input_impl, *output_impl; PinosNode *input_node, *output_node; PinosLink *link; @@ -1156,8 +812,9 @@ pinos_port_link (PinosPort *output_port, g_return_val_if_fail (input_port != NULL, NULL); output_node = output_port->node; - priv = output_node->priv; + output_impl = SPA_CONTAINER_OF (output_node, PinosNodeImpl, node); input_node = input_port->node; + input_impl = SPA_CONTAINER_OF (input_node, PinosNodeImpl, node); pinos_log_debug ("port link %p:%u -> %p:%u", output_node, output_port->port, input_node, input_port->port); @@ -1177,27 +834,25 @@ pinos_port_link (PinosPort *output_port, input_node->clock = output_node->clock; pinos_log_debug ("node %p: clock %p, live %d", output_node, output_node->clock, output_node->live); - link = g_object_new (PINOS_TYPE_LINK, - "daemon", priv->daemon, - "output-port", output_port, - "input-port", input_port, - "format-filter", format_filter, - "properties", properties, - NULL); + link = pinos_link_new (output_impl->core, + output_port, + input_port, + format_filter, + properties); g_ptr_array_add (output_port->links, link); g_ptr_array_add (input_port->links, link); - output_node->priv->n_used_output_links++; - input_node->priv->n_used_input_links++; + output_impl->n_used_output_links++; + input_impl->n_used_input_links++; - spa_poll_invoke (&priv->data_loop->poll, + spa_poll_invoke (&output_impl->data_loop->poll, do_add_link, SPA_ID_INVALID, sizeof (PinosLink *), &link, output_node); - spa_poll_invoke (&input_node->priv->data_loop->poll, + spa_poll_invoke (&input_impl->data_loop->poll, do_add_link, SPA_ID_INVALID, sizeof (PinosLink *), @@ -1247,22 +902,22 @@ do_remove_link_done (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); PinosLink *link = ((PinosLink**)data)[0]; pinos_log_debug ("port %p: finish unlink", port); if (port->direction == PINOS_DIRECTION_OUTPUT) { if (g_ptr_array_remove_fast (port->links, link)) - priv->n_used_output_links--; + impl->n_used_output_links--; link->output = NULL; } else { if (g_ptr_array_remove_fast (port->links, link)) - priv->n_used_input_links--; + impl->n_used_input_links--; link->input = NULL; } - if (priv->n_used_output_links == 0 && - priv->n_used_input_links == 0) { + if (impl->n_used_output_links == 0 && + impl->n_used_input_links == 0) { pinos_node_report_idle (this); } @@ -1276,7 +931,7 @@ do_remove_link_done (SpaPoll *poll, port->n_buffers = 0; } - pinos_main_loop_defer_complete (priv->main_loop, + pinos_main_loop_defer_complete (impl->core->main_loop, port, seq, SPA_RESULT_OK); @@ -1296,7 +951,7 @@ do_remove_link (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); PinosLink *link = ((PinosLink**)data)[0]; SpaResult res; @@ -1305,9 +960,9 @@ do_remove_link (SpaPoll *poll, pinos_port_pause (port); #endif - g_ptr_array_remove_fast (priv->rt.links, link); + g_ptr_array_remove_fast (impl->rt.links, link); - res = spa_poll_invoke (&priv->main_loop->poll, + res = spa_poll_invoke (impl->core->main_loop->poll, do_remove_link_done, seq, sizeof (PinosLink *), @@ -1320,14 +975,15 @@ SpaResult pinos_port_unlink (PinosPort *port, PinosLink *link) { SpaResult res; + PinosNodeImpl *impl = (PinosNodeImpl*)port->node; pinos_log_debug ("port %p: start unlink %p", port, link); g_object_ref (link); g_object_ref (port->node); - res = spa_poll_invoke (&port->node->priv->data_loop->poll, + res = spa_poll_invoke (&impl->data_loop->poll, do_remove_link, - port->node->priv->seq++, + impl->seq++, sizeof (PinosLink *), &link, port); @@ -1344,7 +1000,7 @@ do_clear_buffers_done (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); SpaResult res; pinos_log_debug ("port %p: clear buffers finish", port); @@ -1356,7 +1012,7 @@ do_clear_buffers_done (SpaPoll *poll, port->buffers = NULL; port->n_buffers = 0; - pinos_main_loop_defer_complete (priv->main_loop, + pinos_main_loop_defer_complete (impl->core->main_loop, port, seq, res); @@ -1373,12 +1029,12 @@ do_clear_buffers (SpaPoll *poll, { PinosPort *port = user_data; PinosNode *this = port->node; - PinosNodePrivate *priv = this->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, node); SpaResult res; pinos_port_pause (port); - res = spa_poll_invoke (&priv->main_loop->poll, + res = spa_poll_invoke (impl->core->main_loop->poll, do_clear_buffers_done, seq, 0, NULL, @@ -1390,11 +1046,12 @@ SpaResult pinos_port_clear_buffers (PinosPort *port) { SpaResult res; + PinosNodeImpl *impl = SPA_CONTAINER_OF (port->node, PinosNodeImpl, node); pinos_log_debug ("port %p: clear buffers", port); - res = spa_poll_invoke (&port->node->priv->data_loop->poll, + res = spa_poll_invoke (&impl->data_loop->poll, do_clear_buffers, - port->node->priv->seq++, + impl->seq++, 0, NULL, port); return res; @@ -1413,15 +1070,14 @@ GList * pinos_node_get_ports (PinosNode *node, PinosDirection direction) { GList *ports; - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; + g_return_val_if_fail (node, NULL); if (direction == PINOS_DIRECTION_INPUT) { - ports = priv->input_ports; + ports = impl->input_ports; } else { - ports = priv->output_ports; + ports = impl->output_ports; } return ports; } @@ -1429,11 +1085,11 @@ pinos_node_get_ports (PinosNode *node, PinosDirection direction) static void remove_idle_timeout (PinosNode *node) { - PinosNodePrivate *priv = node->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - if (priv->idle_timeout) { - g_source_remove (priv->idle_timeout); - priv->idle_timeout = 0; + if (impl->idle_timeout) { + g_source_remove (impl->idle_timeout); + impl->idle_timeout = 0; } } @@ -1468,11 +1124,10 @@ SpaResult pinos_node_set_state (PinosNode *node, PinosNodeState state) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); SpaResult res = SPA_RESULT_OK; - g_return_val_if_fail (PINOS_IS_NODE (node), SPA_RESULT_INVALID_ARGUMENTS); - priv = node->priv; + g_return_val_if_fail (node, SPA_RESULT_INVALID_ARGUMENTS); remove_idle_timeout (node); @@ -1504,7 +1159,7 @@ pinos_node_set_state (PinosNode *node, if (SPA_RESULT_IS_ERROR (res)) return res; - pinos_main_loop_defer (priv->main_loop, + pinos_main_loop_defer (impl->core->main_loop, node, res, (PinosDeferFunc) on_state_complete, @@ -1526,20 +1181,22 @@ void pinos_node_update_state (PinosNode *node, PinosNodeState state) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); PinosNodeState old; - g_return_if_fail (PINOS_IS_NODE (node)); - priv = node->priv; + g_return_if_fail (node); - old = priv->state; + 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)); - priv->state = state; - pinos_node1_set_state (priv->iface, state); - g_signal_emit (node, signals[SIGNAL_STATE_CHANGE], 0, old, priv->state); + + node->state = state; + pinos_node1_set_state (impl->iface, state); + pinos_signal_emit (&node->state_change, node, &sc); } } @@ -1554,28 +1211,27 @@ void pinos_node_report_error (PinosNode *node, GError *error) { - PinosNodePrivate *priv; - PinosNodeState old; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); + PinosNodeStateChangeData sc; - g_return_if_fail (PINOS_IS_NODE (node)); - priv = node->priv; + g_return_if_fail (node); - old = priv->state; - g_clear_error (&priv->error); + g_clear_error (&impl->error); remove_idle_timeout (node); - priv->error = error; - priv->state = PINOS_NODE_STATE_ERROR; + impl->error = error; + sc.old = node->state; + sc.state = node->state = PINOS_NODE_STATE_ERROR; pinos_log_debug ("node %p: got error state %s", node, error->message); - pinos_node1_set_state (priv->iface, PINOS_NODE_STATE_ERROR); - g_signal_emit (node, signals[SIGNAL_STATE_CHANGE], 0, old, priv->state); + pinos_node1_set_state (impl->iface, PINOS_NODE_STATE_ERROR); + pinos_signal_emit (&node->state_change, node, &sc); } static gboolean idle_timeout (PinosNode *node) { - PinosNodePrivate *priv = node->priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - priv->idle_timeout = 0; + impl->idle_timeout = 0; pinos_log_debug ("node %p: idle timeout", node); pinos_node_set_state (node, PINOS_NODE_STATE_SUSPENDED); @@ -1592,15 +1248,14 @@ idle_timeout (PinosNode *node) void pinos_node_report_idle (PinosNode *node) { - PinosNodePrivate *priv; + PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, node); - g_return_if_fail (PINOS_IS_NODE (node)); - priv = node->priv; + g_return_if_fail (node); pinos_log_debug ("node %p: report idle", node); pinos_node_set_state (node, PINOS_NODE_STATE_IDLE); - priv->idle_timeout = g_timeout_add_seconds (3, + impl->idle_timeout = g_timeout_add_seconds (3, (GSourceFunc) idle_timeout, node); } @@ -1615,7 +1270,7 @@ pinos_node_report_idle (PinosNode *node) void pinos_node_report_busy (PinosNode *node) { - g_return_if_fail (PINOS_IS_NODE (node)); + g_return_if_fail (node); pinos_log_debug ("node %p: report busy", node); pinos_node_set_state (node, PINOS_NODE_STATE_RUNNING); diff --git a/pinos/server/node.h b/pinos/server/node.h index 4a5043869..734c58d3f 100644 --- a/pinos/server/node.h +++ b/pinos/server/node.h @@ -31,14 +31,7 @@ G_BEGIN_DECLS typedef struct _PinosPort PinosPort; typedef struct _PinosNode PinosNode; -typedef struct _PinosNodeClass PinosNodeClass; -typedef struct _PinosNodePrivate PinosNodePrivate; - - -typedef enum { - PINOS_NODE_FLAG_NONE = 0, - PINOS_NODE_FLAG_REMOVING = (1 << 0), -} PinosNodeFlags; +typedef struct _PinosNodeListener PinosNodeListener; #include @@ -52,24 +45,28 @@ typedef enum { struct _PinosPort { PinosObject object; + PinosNode *node; PinosDirection direction; uint32_t port; + gboolean allocated; PinosMemblock buffer_mem; SpaBuffer **buffers; guint n_buffers; + GPtrArray *links; }; -#define PINOS_TYPE_NODE (pinos_node_get_type ()) -#define PINOS_IS_NODE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), PINOS_TYPE_NODE)) -#define PINOS_IS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), PINOS_TYPE_NODE)) -#define PINOS_NODE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), PINOS_TYPE_NODE, PinosNodeClass)) -#define PINOS_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), PINOS_TYPE_NODE, PinosNode)) -#define PINOS_NODE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), PINOS_TYPE_NODE, PinosNodeClass)) -#define PINOS_NODE_CAST(obj) ((PinosNode*)(obj)) -#define PINOS_NODE_CLASS_CAST(klass) ((PinosNodeClass*)(klass)) +typedef struct { + uint32_t seq; + SpaResult res; +} PinosNodeAsyncCompleteData; + +typedef struct { + PinosNodeState old; + PinosNodeState state; +} PinosNodeStateChangeData; /** * PinosNode: @@ -77,11 +74,9 @@ struct _PinosPort { * Pinos node class. */ struct _PinosNode { - GObject obj; - - PinosObject object; - - PinosNodeFlags flags; + char *name; + PinosProperties *properties; + PinosNodeState state; SpaNode *node; @@ -92,27 +87,49 @@ struct _PinosNode { gboolean have_outputs; PinosTransport *transport; + PinosSignal transport_changed; - PinosNodePrivate *priv; + PinosSignal state_change; + PinosSignal port_added; + PinosSignal port_removed; + PinosSignal async_complete; + + PinosPort * (*get_free_port) (PinosNode *node, + PinosDirection direction); + PinosPort * (*enum_ports) (PinosNode *node, + PinosDirection direction, + void **state); + SpaResult (*set_state) (PinosNode *node, + PinosNodeState state); }; -/** - * PinosNodeClass: - * @set_state: called to change the current state of the node - * - * Pinos node class. - */ -struct _PinosNodeClass { - GObjectClass parent_class; +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); }; -/* normal GObject stuff */ -GType pinos_node_get_type (void); -void pinos_node_remove (PinosNode *node); -const gchar * pinos_node_get_name (PinosNode *node); -PinosProperties * pinos_node_get_properties (PinosNode *node); +PinosObject * pinos_node_new (PinosCore *core, + const char *name, + SpaNode *node, + SpaClock *clock, + PinosProperties *properties); PinosDaemon * pinos_node_get_daemon (PinosNode *node); PinosClient * pinos_node_get_client (PinosNode *node); @@ -124,7 +141,6 @@ PinosPort * pinos_node_get_free_port (PinosNode *node, GList * pinos_node_get_ports (PinosNode *node, PinosDirection direction); -PinosNodeState pinos_node_get_state (PinosNode *node); gboolean pinos_node_set_state (PinosNode *node, PinosNodeState state); void pinos_node_update_state (PinosNode *node, PinosNodeState state); diff --git a/pinos/server/registry.c b/pinos/server/registry.c index e1bb62253..096c53839 100644 --- a/pinos/server/registry.c +++ b/pinos/server/registry.c @@ -20,6 +20,7 @@ #include #include "pinos/client/pinos.h" +#include "pinos/server/core.h" #include "pinos/server/daemon.h" #include "pinos/server/registry.h" #include "pinos/server/node.h" @@ -33,6 +34,7 @@ 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); @@ -50,3 +52,21 @@ pinos_registry_init (PinosRegistry *reg) pinos_signal_init (®->object_added); pinos_signal_init (®->object_removed); } + +PinosObject * +pinos_registry_iterate_objects (PinosRegistry *reg, + uint32_t type, + void **state) +{ + unsigned int idx; + PinosObject *o; + + while (true) { + 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)) + break; + } + return o; +} diff --git a/pinos/server/registry.h b/pinos/server/registry.h index 1aa5ecdbf..f8d8fd49c 100644 --- a/pinos/server/registry.h +++ b/pinos/server/registry.h @@ -35,6 +35,7 @@ extern "C" { typedef struct _PinosRegistry PinosRegistry; typedef struct { + uint32_t core; uint32_t daemon; uint32_t registry; uint32_t node; @@ -42,6 +43,7 @@ typedef struct { uint32_t link; uint32_t node_factory; uint32_t client; + uint32_t monitor; uint32_t spa_node; uint32_t spa_clock; uint32_t spa_monitor; @@ -70,17 +72,27 @@ pinos_registry_add_object (PinosRegistry *reg, PinosObject *object) { object->id = pinos_map_insert_new (®->objects, object); - pinos_signal_emit (®->object_added, object); + pinos_signal_emit (®->object_added, reg, object); } static inline void pinos_registry_remove_object (PinosRegistry *reg, PinosObject *object) { - pinos_signal_emit (®->object_removed, 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); + +#define pinos_registry_iterate_nodes(reg,state) \ + pinos_registry_iterate_objects(reg, (reg)->uri.node,state) +#define pinos_registry_iterate_node_factoriess(reg,state) \ + pinos_registry_iterate_objects(reg, (reg)->uri.node_factory,state) + #ifdef __cplusplus } #endif diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index 85471228b..b81ce2f71 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -33,7 +33,7 @@ typedef struct _SpaALSAState SpaALSASink; static const char default_device[] = "default"; static const uint32_t default_buffer_time = 4000; -static const uint32_t default_period_time = 500; +static const uint32_t default_period_time = 100; static const bool default_period_event = 0; static void