diff --git a/pinos/client/array.h b/pinos/client/array.h index 28a03b4b9..fa4801597 100644 --- a/pinos/client/array.h +++ b/pinos/client/array.h @@ -42,7 +42,7 @@ 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) \ +#define PINOS_ARRAY_FOREACH(pos, array) \ for (pos = (array)->data; \ (const char *) pos < ((const char *) (array)->data + (array)->size); \ (pos)++) @@ -67,7 +67,7 @@ pinos_array_ensure_size (PinosArray *arr, size_t alloc, need; alloc = arr->alloc; - need = alloc + size; + need = arr->size + size; if (SPA_UNLIKELY (alloc < need)) { void *data; @@ -97,6 +97,21 @@ pinos_array_add (PinosArray *arr, return p; } +static inline void * +pinos_array_add_fixed (PinosArray *arr, + size_t size) +{ + void *p; + + if (SPA_UNLIKELY (arr->alloc < arr->size + size)) + return NULL; + + p = arr->data + arr->size; + arr->size += size; + + return p; +} + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/pinos/client/list.h b/pinos/client/list.h new file mode 100644 index 000000000..80bf71ce3 --- /dev/null +++ b/pinos/client/list.h @@ -0,0 +1,83 @@ +/* Simple Plugin API + * Copyright (C) 2016 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __PINOS_LIST_H__ +#define __PINOS_LIST_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _PinosList PinosList; + +#include + +struct _PinosList { + PinosList *next; + PinosList *prev; +}; + +static inline void +pinos_list_init (PinosList *list) +{ + list->next = list; + list->prev = list; +} + +static inline void +pinos_list_insert (PinosList *list, + PinosList *elem) +{ + elem->prev = list; + elem->next = list->next; + list->next = elem; + elem->next->prev = elem; +} + +static inline void +pinos_list_remove (PinosList *elem) +{ + elem->prev->next = elem->next; + elem->next->prev = elem->prev; + elem->next = NULL; + elem->prev = NULL; +} + +#define PINOS_CONTAINER_OF(ptr, sample, member) \ + (__typeof__(sample))((char *)(ptr) - \ + offsetof(__typeof__(*sample), member)) + +#define PINOS_LIST_FOREACH(pos, head, member) \ + for (pos = PINOS_CONTAINER_OF((head)->next, pos, member); \ + &pos->member != (head); \ + pos = PINOS_CONTAINER_OF(pos->member.next, pos, member)) + +#define PINOS_LIST_FOREACH_SAFE(pos, tmp, head, member) \ + for (pos = PINOS_CONTAINER_OF((head)->next, pos, member), \ + tmp = PINOS_CONTAINER_OF((pos)->member.next, tmp, member); \ + &pos->member != (head); \ + pos = tmp, \ + tmp = PINOS_CONTAINER_OF(pos->member.next, tmp, member)) + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __PINOS_LIST_H__ */ diff --git a/pinos/client/object.h b/pinos/client/object.h new file mode 100644 index 000000000..524ede53d --- /dev/null +++ b/pinos/client/object.h @@ -0,0 +1,67 @@ +/* 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_OBJECT_H__ +#define __PINOS_OBJECT_H__ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _PinosObject PinosObject; + +typedef enum { + PINOS_OBJECT_FLAG_NONE = 0, + PINOS_OBJECT_FLAG_DESTROYING = (1 << 0), +} PinosObjectFlags; + +typedef void (*PinosDestroyFunc) (PinosObject *object); + +struct _PinosObject { + uint32_t type; + uint32_t id; + void *implementation; + PinosObjectFlags flags; + PinosDestroyFunc destroy; + PinosSignal destroy_signal; +}; + +static inline void +pinos_object_init (PinosObject *object, + uint32_t type, + void *implementation, + PinosDestroyFunc destroy) +{ + object->type = type; + object->id = SPA_ID_INVALID; + object->implementation = implementation; + object->destroy = destroy; + pinos_signal_init (&object->destroy_signal); +} + + +#ifdef __cplusplus +} +#endif + +#endif /* __PINOS_OBJECT_H__ */ diff --git a/pinos/client/rtkit.c b/pinos/client/rtkit.c index cb2f51a24..1189ca788 100644 --- a/pinos/client/rtkit.c +++ b/pinos/client/rtkit.c @@ -18,25 +18,68 @@ */ #include +#include +#include #include "rtkit.h" +#include + +struct _PinosRTKitBus { + GDBusConnection *bus; +}; + static pid_t _gettid(void) { return (pid_t) syscall(SYS_gettid); } -gboolean -pinos_rtkit_make_realtime (GDBusConnection *system_bus, +static int +translate_error (GError *error) +{ + const gchar *name = g_dbus_error_get_remote_error (error); + + if (strcmp (name, "org.freedesktop.DBus.Error.NoMemory") == 0) + return -ENOMEM; + if (strcmp (name, "org.freedesktop.DBus.Error.ServiceUnknown") == 0 || + strcmp (name, "org.freedesktop.DBus.Error.NameHasNoOwner") == 0) + return -ENOENT; + if (strcmp (name, "org.freedesktop.DBus.Error.AccessDenied") == 0 || + strcmp (name, "org.freedesktop.DBus.Error.AuthFailed") == 0) + return -EACCES; + + return -EIO; +} + +PinosRTKitBus * +pinos_rtkit_bus_get_system (void) +{ + PinosRTKitBus *bus; + + bus = g_slice_new (PinosRTKitBus); + bus->bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); + + return bus; +} + +void +pinos_rtkit_bus_free (PinosRTKitBus *system_bus) +{ + g_object_unref (system_bus->bus); + g_slice_free (PinosRTKitBus, system_bus); +} + +int +pinos_rtkit_make_realtime (PinosRTKitBus *system_bus, pid_t thread, - gint priority, - GError **error) + int priority) { GVariant *v; + GError *error = NULL; if (thread == 0) thread = _gettid(); - v = g_dbus_connection_call_sync (system_bus, + v = g_dbus_connection_call_sync (system_bus->bus, RTKIT_SERVICE_NAME, RTKIT_OBJECT_PATH, "org.freedesktop.RealtimeKit1", @@ -48,25 +91,27 @@ pinos_rtkit_make_realtime (GDBusConnection *system_bus, G_DBUS_CALL_FLAGS_NONE, -1, NULL, - error); - if (v) - g_variant_unref (v); + &error); + if (v == NULL) + return translate_error (error); - return v != NULL; + g_variant_unref (v); + + return 0; } -gboolean -pinos_rtkit_make_high_priority (GDBusConnection *system_bus, +int +pinos_rtkit_make_high_priority (PinosRTKitBus *system_bus, pid_t thread, - gint nice_level, - GError **error) + int nice_level) { GVariant *v; + GError *error = NULL; if (thread == 0) thread = _gettid(); - v = g_dbus_connection_call_sync (system_bus, + v = g_dbus_connection_call_sync (system_bus->bus, RTKIT_SERVICE_NAME, RTKIT_OBJECT_PATH, "org.freedesktop.RealtimeKit1", @@ -78,19 +123,20 @@ pinos_rtkit_make_high_priority (GDBusConnection *system_bus, G_DBUS_CALL_FLAGS_NONE, -1, NULL, - error); - if (v) - g_variant_unref (v); + &error); + if (v == NULL) + return translate_error (error); + g_variant_unref (v); - return v != NULL; + return 0; } -int pinos_rtkit_get_max_realtime_priority (GDBusConnection *system_bus) +int pinos_rtkit_get_max_realtime_priority (PinosRTKitBus *system_bus) { return 0; } -int pinos_rtkit_get_min_nice_level (GDBusConnection *system_bus, int* min_nice_level) +int pinos_rtkit_get_min_nice_level (PinosRTKitBus *system_bus, int* min_nice_level) { return 0; } @@ -98,7 +144,7 @@ int pinos_rtkit_get_min_nice_level (GDBusConnection *system_bus, int* min_nice_l /* Return the maximum value of RLIMIT_RTTIME to set before attempting a * realtime request. A negative value is an errno style error code. */ -long long rtkit_get_rttime_usec_max (GDBusConnection *system_bus) +long long pinos_rtkit_get_rttime_usec_max (PinosRTKitBus *system_bus) { return 0; } diff --git a/pinos/client/rtkit.h b/pinos/client/rtkit.h index 87b3da923..9de91d11c 100644 --- a/pinos/client/rtkit.h +++ b/pinos/client/rtkit.h @@ -20,49 +20,59 @@ #ifndef __PINOS_RTKIT_H__ #define __PINOS_RTKIT_H__ -#include -#include +#include +#include -G_BEGIN_DECLS +#ifdef __cplusplus +extern "C" { +#endif #define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" #define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" +typedef struct _PinosRTKitBus PinosRTKitBus; + +PinosRTKitBus * pinos_rtkit_bus_get_system (void); +void pinos_rtkit_bus_free (PinosRTKitBus *system_bus); + + /* This is mostly equivalent to sched_setparam(thread, SCHED_RR, { * .sched_priority = priority }). 'thread' needs to be a kernel thread * id as returned by gettid(), not a pthread_t! If 'thread' is 0 the - * current thread is used. - */ -gboolean pinos_rtkit_make_realtime (GDBusConnection *system_bus, - pid_t thread, - gint priority, - GError **error); + * current thread is used. The returned value is a negative errno + * style error code, or 0 on success. */ +int pinos_rtkit_make_realtime (PinosRTKitBus *system_bus, + pid_t thread, + int priority); /* This is mostly equivalent to setpriority(PRIO_PROCESS, thread, * nice_level). 'thread' needs to be a kernel thread id as returned by * gettid(), not a pthread_t! If 'thread' is 0 the current thread is - * used. */ -gboolean pinos_rtkit_make_high_priority (GDBusConnection *system_bus, - pid_t thread, - gint nice_level, - GError **error); + * used. The returned value is a negative errno style error code, or + * 0 on success. */ +int pinos_rtkit_make_high_priority (PinosRTKitBus *system_bus, + pid_t thread, + int nice_level); /* Return the maximum value of realtime priority available. Realtime requests * above this value will fail. A negative value is an errno style error code. */ -int pinos_rtkit_get_max_realtime_priority (GDBusConnection *system_bus); +int pinos_rtkit_get_max_realtime_priority (PinosRTKitBus *system_bus); /* Retreive the minimum value of nice level available. High prio requests * below this value will fail. The returned value is a negative errno * style error code, or 0 on success.*/ -int pinos_rtkit_get_min_nice_level (GDBusConnection *system_bus, int* min_nice_level); +int pinos_rtkit_get_min_nice_level (PinosRTKitBus *system_bus, + int *min_nice_level); /* Return the maximum value of RLIMIT_RTTIME to set before attempting a * realtime request. A negative value is an errno style error code. */ -long long rtkit_get_rttime_usec_max (GDBusConnection *system_bus); +long long pinos_rtkit_get_rttime_usec_max (PinosRTKitBus *system_bus); -G_END_DECLS +#ifdef __cplusplus +} +#endif #endif /* __PINOS_RTKIT_H__ */ diff --git a/pinos/client/signal.h b/pinos/client/signal.h new file mode 100644 index 000000000..1d42573e3 --- /dev/null +++ b/pinos/client/signal.h @@ -0,0 +1,69 @@ +/* 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_SIGNAL_H__ +#define __PINOS_SIGNAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _PinosSignal PinosSignal; +typedef struct _PinosListener PinosListener; + +struct _PinosListener { + PinosList link; + void (*notify) (PinosListener *listener, void *data); + void *user_data; +}; + +struct _PinosSignal { + PinosList listeners; +}; + +static inline void +pinos_signal_init (PinosSignal *signal) +{ + pinos_list_init (&signal->listeners); +} + +static inline void +pinos_signal_add (PinosSignal *signal, + PinosListener *listener) +{ + pinos_list_insert (signal->listeners.prev, &listener->link); +} + +static inline void +pinos_signal_emit (PinosSignal *signal, + void *data) +{ + PinosListener *l, *next; + + PINOS_LIST_FOREACH_SAFE (l, next, &signal->listeners, link) + l->notify (l, data); +} + +#ifdef __cplusplus +} +#endif + +#endif /* __PINOS_SIGNAL_H__ */ diff --git a/pinos/client/stream.c b/pinos/client/stream.c index c6d5a1cfa..148d60127 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -142,7 +142,7 @@ clear_buffers (PinosStream *stream) PinosStreamPrivate *priv = stream->priv; BufferId *bid; - pinos_array_for_each (bid, &priv->buffer_ids) { + PINOS_ARRAY_FOREACH (bid, &priv->buffer_ids) { g_signal_emit (stream, signals[SIGNAL_REMOVE_BUFFER], 0, bid->id); bid->buf = NULL; } @@ -730,7 +730,7 @@ find_mem (PinosStream *stream, uint32_t id) PinosStreamPrivate *priv = stream->priv; MemId *mid; - pinos_array_for_each (mid, &priv->mem_ids) { + PINOS_ARRAY_FOREACH (mid, &priv->mem_ids) { if (mid->id == id) return mid; } @@ -747,7 +747,7 @@ find_buffer (PinosStream *stream, uint32_t id) } else { BufferId *bid; - pinos_array_for_each (bid, &priv->buffer_ids) { + PINOS_ARRAY_FOREACH (bid, &priv->buffer_ids) { if (bid->id == id) return bid; } @@ -1378,61 +1378,6 @@ exit_error: } } -static void -on_node_registered (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - PinosStream *stream = user_data; - PinosStreamPrivate *priv = stream->priv; - PinosContext *context = priv->context; - GVariant *ret; - GError *error = NULL; - GUnixFDList *fd_list; - gint fd_idx, fd; - - g_assert (context->priv->daemon == G_DBUS_PROXY (source_object)); - - ret = g_dbus_proxy_call_with_unix_fd_list_finish (context->priv->daemon, - &fd_list, - res, &error); - if (ret == NULL) - goto create_failed; - - g_variant_get (ret, "(h)", &fd_idx); - g_variant_unref (ret); - - if ((fd = g_unix_fd_list_get (fd_list, fd_idx, &error)) < 0) - goto fd_failed; - - priv->fd = fd; - g_object_unref (fd_list); - - handle_socket (stream, -1, priv->fd); - - return; - - /* ERRORS */ -create_failed: - { - pinos_log_warn ("failed to connect: %s", error->message); - goto exit_error; - } -fd_failed: - { - pinos_log_warn ("failed to get FD: %s", error->message); - g_object_unref (fd_list); - goto exit_error; - } -exit_error: - { - stream_set_state (stream, PINOS_STREAM_STATE_ERROR, error); - g_object_unref (stream); - return; - } -} - - static gboolean do_connect (PinosStream *stream) { @@ -1445,38 +1390,16 @@ do_connect (PinosStream *stream) pinos_properties_set (priv->properties, "pinos.target.node", priv->path); - if (FALSE) { - PinosClientNode1 *iface; - - iface = pinos_client_node1_skeleton_new (); - - g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (iface), - priv->context->priv->connection, - "/org/pinos/stream", - NULL); - - g_dbus_proxy_call (context->priv->daemon, - "RegisterClientNode", - g_variant_new ("(@a{sv}o)", - pinos_properties_to_variant (priv->properties), - "/org/pinos/stream"), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable *cancellable */ - on_node_registered, - stream); - } else { - g_dbus_proxy_call (context->priv->daemon, - "CreateClientNode", - g_variant_new ("(s@a{sv})", - "client-node", - pinos_properties_to_variant (priv->properties)), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, /* GCancellable *cancellable */ - on_node_created, - stream); - } + g_dbus_proxy_call (context->priv->daemon, + "CreateClientNode", + g_variant_new ("(s@a{sv})", + "client-node", + pinos_properties_to_variant (priv->properties)), + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, /* GCancellable *cancellable */ + on_node_created, + stream); return FALSE; } @@ -1783,7 +1706,7 @@ pinos_stream_get_empty_buffer (PinosStream *stream) priv = stream->priv; g_return_val_if_fail (priv->direction == SPA_DIRECTION_OUTPUT, FALSE); - pinos_array_for_each (bid, &priv->buffer_ids) { + PINOS_ARRAY_FOREACH (bid, &priv->buffer_ids) { if (!bid->used) return bid->id; } diff --git a/pinos/dbus/org.pinos.xml b/pinos/dbus/org.pinos.xml index fb89bbf49..b24e0a395 100644 --- a/pinos/dbus/org.pinos.xml +++ b/pinos/dbus/org.pinos.xml @@ -52,13 +52,6 @@ - - - - - - - @@ -119,79 +112,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pinos/modules/spa/spa-alsa-monitor.c b/pinos/modules/spa/spa-alsa-monitor.c index c9fa090a4..adbcf3d5f 100644 --- a/pinos/modules/spa/spa-alsa-monitor.c +++ b/pinos/modules/spa/spa-alsa-monitor.c @@ -38,11 +38,6 @@ #define PINOS_SPA_ALSA_MONITOR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_ALSA_MONITOR, PinosSpaALSAMonitorPrivate)) -typedef struct { - uint32_t node; - uint32_t clock; -} URI; - struct _PinosSpaALSAMonitorPrivate { PinosDaemon *daemon; @@ -50,8 +45,6 @@ struct _PinosSpaALSAMonitorPrivate SpaHandle *handle; SpaMonitor *monitor; - URI uri; - GHashTable *nodes; }; @@ -122,11 +115,11 @@ add_item (PinosSpaALSAMonitor *this, SpaMonitorItem *item) g_error ("can't make factory instance: %d", res); return; } - if ((res = spa_handle_get_interface (handle, priv->uri.node, &node_iface)) < 0) { + 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); return; } - if ((res = spa_handle_get_interface (handle, priv->uri.clock, &clock_iface)) < 0) { + if ((res = spa_handle_get_interface (handle, priv->daemon->registry.uri.spa_clock, &clock_iface)) < 0) { pinos_log_debug ("can't get CLOCK interface: %d", res); clock_iface = NULL; } @@ -210,9 +203,6 @@ monitor_constructed (GObject * object) G_OBJECT_CLASS (pinos_spa_alsa_monitor_parent_class)->constructed (object); - priv->uri.node = spa_id_map_get_id (priv->daemon->map, SPA_NODE_URI); - priv->uri.clock = spa_id_map_get_id (priv->daemon->map, SPA_CLOCK_URI); - while (TRUE) { SpaMonitorItem *item; @@ -348,7 +338,7 @@ pinos_spa_alsa_monitor_new (PinosDaemon *daemon) if ((res = spa_handle_get_interface (handle, - spa_id_map_get_id (daemon->map, SPA_MONITOR_URI), + daemon->registry.uri.spa_monitor, &iface)) < 0) { g_free (handle); g_error ("can't get MONITOR interface: %d", res); diff --git a/pinos/modules/spa/spa-audiotestsrc.c b/pinos/modules/spa/spa-audiotestsrc.c index 75e5209ba..66aabe092 100644 --- a/pinos/modules/spa/spa-audiotestsrc.c +++ b/pinos/modules/spa/spa-audiotestsrc.c @@ -79,7 +79,7 @@ make_node (PinosDaemon *daemon, SpaHandle **handle, SpaNode **node, const char * return res; } if ((res = spa_handle_get_interface (*handle, - spa_id_map_get_id (daemon->map, SPA_NODE_URI), + daemon->registry.uri.spa_node, &iface)) < 0) { g_error ("can't get interface %d", res); return res; diff --git a/pinos/modules/spa/spa-v4l2-monitor.c b/pinos/modules/spa/spa-v4l2-monitor.c index 0642e4c58..563b1a7d0 100644 --- a/pinos/modules/spa/spa-v4l2-monitor.c +++ b/pinos/modules/spa/spa-v4l2-monitor.c @@ -35,11 +35,6 @@ #define PINOS_SPA_V4L2_MONITOR_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_V4L2_MONITOR, PinosSpaV4l2MonitorPrivate)) -typedef struct { - uint32_t node; - uint32_t clock; -} URI; - struct _PinosSpaV4l2MonitorPrivate { PinosDaemon *daemon; @@ -47,8 +42,6 @@ struct _PinosSpaV4l2MonitorPrivate SpaHandle *handle; SpaMonitor *monitor; - URI uri; - GHashTable *nodes; }; @@ -120,11 +113,11 @@ add_item (PinosSpaV4l2Monitor *this, SpaMonitorItem *item) g_error ("can't make factory instance: %d", res); return; } - if ((res = spa_handle_get_interface (handle, priv->uri.node, &node_iface)) < 0) { + 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); return; } - if ((res = spa_handle_get_interface (handle, priv->uri.clock, &clock_iface)) < 0) { + 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); return; } @@ -208,9 +201,6 @@ monitor_constructed (GObject * object) G_OBJECT_CLASS (pinos_spa_v4l2_monitor_parent_class)->constructed (object); - priv->uri.node = spa_id_map_get_id (priv->daemon->map, SPA_NODE_URI); - priv->uri.clock = spa_id_map_get_id (priv->daemon->map, SPA_CLOCK_URI); - while (TRUE) { SpaMonitorItem *item; @@ -346,7 +336,7 @@ pinos_spa_v4l2_monitor_new (PinosDaemon *daemon) } if ((res = spa_handle_get_interface (handle, - spa_id_map_get_id (daemon->map, SPA_MONITOR_URI), + daemon->registry.uri.spa_monitor, &iface)) < 0) { g_free (handle); g_error ("can't get MONITOR interface: %d", res); diff --git a/pinos/modules/spa/spa-videotestsrc.c b/pinos/modules/spa/spa-videotestsrc.c index b60684563..d44537bb7 100644 --- a/pinos/modules/spa/spa-videotestsrc.c +++ b/pinos/modules/spa/spa-videotestsrc.c @@ -72,7 +72,7 @@ make_node (PinosDaemon *daemon, SpaHandle **handle, SpaNode **node, const char * return res; } if ((res = spa_handle_get_interface (*handle, - spa_id_map_get_id (daemon->map, SPA_NODE_URI), + daemon->registry.uri.spa_node, &iface)) < 0) { g_error ("can't get interface %d", res); return res; diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index c991480fc..0e30f32d3 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -86,9 +86,7 @@ typedef struct { ProxyBuffer buffers[MAX_BUFFERS]; uint32_t buffer_mem_id; - int buffer_mem_fd; - size_t buffer_mem_size; - void *buffer_mem_ptr; + PinosMemblock buffer_mem; SpaQueue ready; } SpaProxyPort; @@ -168,8 +166,7 @@ clear_buffers (SpaProxy *this, SpaProxyPort *port) if (port->n_buffers) { spa_log_info (this->log, "proxy %p: clear buffers", this); - munmap (port->buffer_mem_ptr, port->buffer_mem_size); - close (port->buffer_mem_fd); + pinos_memblock_free (&port->buffer_mem); port->n_buffers = 0; SPA_QUEUE_INIT (&port->ready); @@ -718,23 +715,15 @@ spa_proxy_node_port_use_buffers (SpaNode *node, if (n_buffers > 0) { /* make mem for the buffers */ port->buffer_mem_id = n_mem++; - port->buffer_mem_size = size; - port->buffer_mem_fd = memfd_create ("spa-memfd", MFD_CLOEXEC | MFD_ALLOW_SEALING); - - if (ftruncate (port->buffer_mem_fd, size) < 0) { - spa_log_error (this->log, "Failed to truncate temporary file: %s", strerror (errno)); - close (port->buffer_mem_fd); + if (pinos_memblock_alloc (PINOS_MEMBLOCK_FLAG_WITH_FD | + PINOS_MEMBLOCK_FLAG_MAP_READWRITE | + PINOS_MEMBLOCK_FLAG_SEAL, + size, + &port->buffer_mem) < 0) { + spa_log_error (this->log, "Failed to allocate buffer memory"); return SPA_RESULT_ERROR; } -#if 0 - { - unsigned int seals = F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL; - if (fcntl (port->buffer_mem_fd, F_ADD_SEALS, seals) == -1) { - spa_log_error (this->log, "Failed to add seals: %s", strerror (errno)); - } - } -#endif - p = port->buffer_mem_ptr = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, port->buffer_mem_fd, 0); + p = port->buffer_mem.ptr; for (i = 0; i < n_buffers; i++) { ProxyBuffer *b = &port->buffers[i]; @@ -763,7 +752,7 @@ spa_proxy_node_port_use_buffers (SpaNode *node, am.port_id = port_id; am.mem_id = port->buffer_mem_id; am.type = SPA_DATA_TYPE_MEMFD; - am.fd_index = pinos_connection_add_fd (this->conn, port->buffer_mem_fd, false); + am.fd_index = pinos_connection_add_fd (this->conn, port->buffer_mem.fd, false); am.flags = 0; am.offset = 0; am.size = size; @@ -1049,8 +1038,6 @@ parse_connection (SpaProxy *this) spa_log_info (this->log, "proxy %p: got node update %d, max_in %u, max_out %u", this, type, this->max_inputs, this->max_outputs); -#if 0 -#endif break; } diff --git a/pinos/server/client.c b/pinos/server/client.c index 6e8ecdbc1..f3059d67f 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -186,8 +186,6 @@ client_register_object (PinosClient *client) priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); g_object_unref (skel); - client->id = pinos_map_insert_new (&daemon->registry.clients, client); - pinos_log_debug ("client %p: register %s", client, priv->object_path); } @@ -199,7 +197,6 @@ client_unregister_object (PinosClient *client) pinos_log_debug ("client %p: unregister", client); pinos_daemon_unexport (daemon, priv->object_path); - pinos_map_remove (&daemon->registry.clients, client->id); } static void @@ -214,6 +211,7 @@ pinos_client_dispose (GObject * object) g_list_free_full (copy, g_object_unref); g_list_free (priv->objects); + pinos_registry_remove_object (&priv->daemon->registry, &client->object); client_unregister_object (client); G_OBJECT_CLASS (pinos_client_parent_class)->dispose (object); @@ -240,8 +238,17 @@ 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); diff --git a/pinos/server/client.h b/pinos/server/client.h index 7ae26e443..0501a54ca 100644 --- a/pinos/server/client.h +++ b/pinos/server/client.h @@ -24,10 +24,14 @@ G_BEGIN_DECLS +#define PINOS_CLIENT_URI "http://pinos.org/ns/client" +#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 ()) @@ -45,9 +49,9 @@ typedef struct _PinosClientPrivate PinosClientPrivate; * Pinos client object class. */ struct _PinosClient { - GObject object; + GObject obj; - uint32_t id; + PinosObject object; PinosClientPrivate *priv; }; diff --git a/pinos/server/daemon.c b/pinos/server/daemon.c index b21210da1..282148142 100644 --- a/pinos/server/daemon.c +++ b/pinos/server/daemon.c @@ -44,6 +44,8 @@ struct _PinosDaemonPrivate { + PinosDaemon *daemon; + PinosDaemon1 *iface; guint id; GDBusConnection *connection; @@ -57,6 +59,9 @@ struct _PinosDaemonPrivate PinosProperties *properties; + PinosListener object_added; + PinosListener object_removed; + GHashTable *node_factories; SpaSupport support[4]; @@ -447,66 +452,6 @@ exit_error: } } -static gboolean -handle_register_client_node (PinosDaemon1 *interface, - GDBusMethodInvocation *invocation, - GVariant *arg_properties, - const gchar *arg_path, - gpointer user_data) -{ - PinosDaemon *daemon = user_data; - PinosNode *node; - PinosClient *client; - const gchar *sender; - PinosProperties *props; - GError *error = NULL; - GUnixFDList *fdlist; - gint fdidx; - GSocket *socket; - - sender = g_dbus_method_invocation_get_sender (invocation); - client = sender_get_client (daemon, sender, TRUE); - - pinos_log_debug ("daemon %p: register client-node: %s", daemon, sender); - props = pinos_properties_from_variant (arg_properties); - - node = pinos_dbus_client_node_new (daemon, - client, - arg_path, - props); - pinos_properties_free (props); - - socket = pinos_dbus_client_node_get_socket_pair (PINOS_DBUS_CLIENT_NODE (node), &error); - if (socket == NULL) - goto no_socket; - - pinos_client_add_object (client, G_OBJECT (node)); - g_object_unref (node); - - fdlist = g_unix_fd_list_new (); - fdidx = g_unix_fd_list_append (fdlist, g_socket_get_fd (socket), &error); - g_object_unref (socket); - - g_dbus_method_invocation_return_value_with_unix_fd_list (invocation, - g_variant_new ("(h)", fdidx), fdlist); - g_object_unref (fdlist); - - return TRUE; - -no_socket: - { - pinos_log_debug ("daemon %p: could not create socket %s", daemon, error->message); - g_object_unref (node); - goto exit_error; - } -exit_error: - { - g_dbus_method_invocation_return_gerror (invocation, error); - g_clear_error (&error); - return TRUE; - } -} - static void export_server_object (PinosDaemon *daemon, GDBusObjectManagerServer *manager) @@ -674,38 +619,47 @@ pinos_daemon_unexport (PinosDaemon *daemon, g_dbus_object_manager_server_unexport (daemon->priv->server_manager, object_path); } -/** - * pinos_daemon_add_node: - * @daemon: a #PinosDaemon - * @node: a #PinosNode - * - * Add @node to @daemon. - */ -void -pinos_daemon_add_node (PinosDaemon *daemon, - PinosNode *node) +static void +on_registry_object_added (PinosListener *listener, + void *data) { - g_return_if_fail (PINOS_IS_DAEMON (daemon)); - g_return_if_fail (PINOS_IS_NODE (node)); + PinosObject *object = data; + PinosDaemonPrivate *priv = SPA_CONTAINER_OF (listener, PinosDaemonPrivate, object_added); + PinosDaemon *daemon = priv->daemon; - on_node_added (daemon, node); + if (object->type == daemon->registry.uri.node) { + PinosNode *node = object->implementation; + + on_node_added (daemon, node); + } else if (object->type == daemon->registry.uri.node_factory) { + PinosNodeFactory *factory = object->implementation; + gchar *name; + + g_object_get (factory, "name", &name, NULL); + g_hash_table_insert (priv->node_factories, name, g_object_ref (factory)); + } } -/** - * pinos_daemon_remove_node: - * @daemon: a #PinosDaemon - * @node: a #PinosNode - * - * Remove @node from @daemon. - */ -void -pinos_daemon_remove_node (PinosDaemon *daemon, - PinosNode *node) +static void +on_registry_object_removed (PinosListener *listener, + void *data) { - g_return_if_fail (PINOS_IS_DAEMON (daemon)); - g_return_if_fail (PINOS_IS_NODE (node)); + PinosObject *object = data; + PinosDaemonPrivate *priv = SPA_CONTAINER_OF (listener, PinosDaemonPrivate, object_added); + PinosDaemon *daemon = priv->daemon; - on_node_removed (daemon, node); + if (object->type == daemon->registry.uri.node) { + PinosNode *node = object->implementation; + + on_node_removed (daemon, node); + } else if (object->type == daemon->registry.uri.node_factory) { + PinosNodeFactory *factory = object->implementation; + gchar *name; + + g_object_get (factory, "name", &name, NULL); + g_hash_table_remove (priv->node_factories, name); + g_free (name); + } } /** @@ -739,9 +693,14 @@ pinos_daemon_find_port (PinosDaemon *daemon, pinos_log_debug ("name \"%s\", %d", name, have_name); - for (i = 0; i < pinos_map_get_size (&daemon->registry.nodes); i++) { - PinosNode *n = pinos_map_lookup (&daemon->registry.nodes, i); + 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) continue; @@ -823,8 +782,8 @@ pinos_daemon_set_property (GObject *_object, static void pinos_daemon_constructed (GObject * object) { - PinosDaemon *daemon = PINOS_DAEMON_CAST (object); - PinosDaemonPrivate *priv = daemon->priv; + 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 ()); @@ -835,16 +794,24 @@ pinos_daemon_constructed (GObject * object) 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 *daemon = PINOS_DAEMON_CAST (object); + PinosDaemon *this = PINOS_DAEMON_CAST (object); pinos_log_debug ("daemon %p: dispose", object); - pinos_daemon_stop (daemon); + pinos_daemon_stop (this); + + pinos_registry_remove_object (&this->registry, &this->object); G_OBJECT_CLASS (pinos_daemon_parent_class)->dispose (object); } @@ -914,13 +881,19 @@ 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); - g_signal_connect (priv->iface, "handle-register-client-node", (GCallback) handle_register_client_node, daemon); + + priv->object_added.notify = on_registry_object_added; + priv->object_removed.notify = on_registry_object_removed; pinos_registry_init (&daemon->registry); + pinos_signal_add (&daemon->registry.object_added, &priv->object_added); + 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); @@ -932,11 +905,10 @@ pinos_daemon_init (PinosDaemon * daemon) daemon->main_loop = pinos_main_loop_new (g_main_context_get_thread_default ()); priv->data_loop = pinos_data_loop_new(); - daemon->map = pinos_id_map_get_default(); daemon->log = pinos_log_get(); priv->support[0].uri = SPA_ID_MAP_URI; - priv->support[0].data = daemon->map; + 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; @@ -946,46 +918,3 @@ pinos_daemon_init (PinosDaemon * daemon) daemon->support = priv->support; daemon->n_support = 4; } - -/** - * pinos_daemon_add_node_factory: - * @daemon: a #PinosDaemon - * @factory: a #PinosNodeFactory - * - * Add a #PinosNodeFactory in the daemon that will be used for creating nodes. - */ -void -pinos_daemon_add_node_factory (PinosDaemon *daemon, - PinosNodeFactory *factory) -{ - PinosDaemonPrivate *priv = daemon->priv; - gchar *name; - - g_return_if_fail (PINOS_IS_DAEMON (daemon)); - g_return_if_fail (PINOS_IS_NODE_FACTORY (factory)); - - g_object_get (factory, "name", &name, NULL); - g_hash_table_insert (priv->node_factories, name, g_object_ref (factory)); -} - -/** - * pinos_daemon_add_node_factory: - * @daemon: a #PinosDaemon - * @factory: a #PinosNodeFactory - * - * Remove a #PinosNodeFactory from the daemon. - */ -void -pinos_daemon_remove_node_factory (PinosDaemon *daemon, - PinosNodeFactory *factory) -{ - PinosDaemonPrivate *priv = daemon->priv; - gchar *name; - - g_return_if_fail (PINOS_IS_DAEMON (daemon)); - g_return_if_fail (PINOS_IS_NODE_FACTORY (factory)); - - g_object_get (factory, "name", &name, NULL); - g_hash_table_remove (priv->node_factories, name); - g_free (name); -} diff --git a/pinos/server/daemon.h b/pinos/server/daemon.h index 6e7ab7317..bfbe16dc3 100644 --- a/pinos/server/daemon.h +++ b/pinos/server/daemon.h @@ -24,6 +24,9 @@ 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)) @@ -52,9 +55,10 @@ typedef struct _PinosDaemonPrivate PinosDaemonPrivate; * Pinos daemon object class. */ struct _PinosDaemon { - GObject object; + GObject obj; + + PinosObject object; - SpaIDMap *map; SpaLog *log; PinosMainLoop *main_loop; @@ -88,9 +92,6 @@ void pinos_daemon_stop (PinosDaemon *daemon); gchar * pinos_daemon_export_uniquely (PinosDaemon *daemon, GDBusObjectSkeleton *skel); void pinos_daemon_unexport (PinosDaemon *daemon, const gchar *name); -void pinos_daemon_add_node (PinosDaemon *daemon, PinosNode *node); -void pinos_daemon_remove_node (PinosDaemon *daemon, PinosNode *node); - PinosPort * pinos_daemon_find_port (PinosDaemon *daemon, PinosPort *other_port, const gchar *name, @@ -98,11 +99,6 @@ PinosPort * pinos_daemon_find_port (PinosDaemon *daemon, GPtrArray *format_filter, GError **error); -void pinos_daemon_add_node_factory (PinosDaemon *daemon, - PinosNodeFactory *factory); -void pinos_daemon_remove_node_factory (PinosDaemon *daemon, - PinosNodeFactory *factory); - G_END_DECLS #endif /* __PINOS_DAEMON_H__ */ diff --git a/pinos/server/data-loop.c b/pinos/server/data-loop.c index f0737782b..5ce6bdb72 100644 --- a/pinos/server/data-loop.c +++ b/pinos/server/data-loop.c @@ -83,8 +83,7 @@ static void make_realtime (PinosDataLoop *this) { struct sched_param sp; - GDBusConnection *system_bus; - GError *error = NULL; + PinosRTKitBus *system_bus; struct rlimit rl; int r, rtprio; long long rttime; @@ -99,7 +98,7 @@ make_realtime (PinosDataLoop *this) pinos_log_debug ("SCHED_OTHER|SCHED_RESET_ON_FORK worked."); return; } - system_bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL); + system_bus = pinos_rtkit_bus_get_system (); rl.rlim_cur = rl.rlim_max = rttime; if ((r = setrlimit (RLIMIT_RTTIME, &rl)) < 0) @@ -116,13 +115,12 @@ make_realtime (PinosDataLoop *this) } } - if (!pinos_rtkit_make_realtime (system_bus, 0, rtprio, &error)) { - pinos_log_debug ("could not make thread realtime: %s", error->message); - g_clear_error (&error); + if ((r = pinos_rtkit_make_realtime (system_bus, 0, rtprio)) < 0) { + pinos_log_debug ("could not make thread realtime: %s", strerror (r)); } else { pinos_log_debug ("thread made realtime"); } - g_object_unref (system_bus); + pinos_rtkit_bus_free (system_bus); } static void * diff --git a/pinos/server/dbus-client-node.c b/pinos/server/dbus-client-node.c index dd9b2af96..861f1e52f 100644 --- a/pinos/server/dbus-client-node.c +++ b/pinos/server/dbus-client-node.c @@ -267,7 +267,7 @@ make_node (PinosDaemon *daemon, SpaHandle **handle, SpaNode **node, const char * return res; } if ((res = spa_handle_get_interface (*handle, - spa_id_map_get_id (daemon->map, SPA_NODE_URI), + daemon->registry.uri.spa_node, &iface)) < 0) { g_error ("can't get interface %d", res); return res; diff --git a/pinos/server/link.c b/pinos/server/link.c index b6d713df4..2c6e20b56 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -180,9 +180,7 @@ link_register_object (PinosLink *this) priv->object_path = pinos_daemon_export_uniquely (priv->daemon, G_DBUS_OBJECT_SKELETON (skel)); g_object_unref (skel); - this->id = pinos_map_insert_new (&priv->daemon->registry.links, this); - - pinos_log_debug ("link %p: register object %s, id %u", this, priv->object_path, this->id); + pinos_log_debug ("link %p: register object %s, id %u", this, priv->object_path, this->object.id); } static void @@ -192,7 +190,6 @@ link_unregister_object (PinosLink *this) pinos_log_debug ("link %p: unregister object", this); pinos_daemon_unexport (priv->daemon, priv->object_path); - pinos_map_remove (&priv->daemon->registry.links, this->id); } static void @@ -852,6 +849,12 @@ pinos_link_constructed (GObject * object) 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, @@ -879,6 +882,8 @@ pinos_link_dispose (GObject * object) if (this->output) pinos_port_unlink (this->output, this); + pinos_registry_remove_object (&priv->daemon->registry, &this->object); + link_unregister_object (this); pinos_main_loop_defer_cancel (priv->main_loop, this, 0); diff --git a/pinos/server/link.h b/pinos/server/link.h index 86675517d..721090344 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -24,6 +24,9 @@ G_BEGIN_DECLS +#define PINOS_LINK_URI "http://pinos.org/ns/link" +#define PINOS_LINK_PREFIX PINOS_LINK_URI "#" + typedef struct _PinosLink PinosLink; typedef struct _PinosLinkClass PinosLinkClass; typedef struct _PinosLinkPrivate PinosLinkPrivate; @@ -31,6 +34,7 @@ typedef struct _PinosLinkPrivate PinosLinkPrivate; #include #include +#include #include #include @@ -50,9 +54,9 @@ typedef struct _PinosLinkPrivate PinosLinkPrivate; * Pinos link object class. */ struct _PinosLink { - GObject object; + GObject obj; - uint32_t id; + PinosObject object; PinosPort *output; PinosPort *input; diff --git a/pinos/server/node-factory.c b/pinos/server/node-factory.c index c727a522d..26c0dba96 100644 --- a/pinos/server/node-factory.c +++ b/pinos/server/node-factory.c @@ -95,7 +95,12 @@ pinos_node_factory_constructed (GObject * obj) g_debug ("node factory %p: constructed", factory); - factory->id = pinos_map_insert_new (&priv->daemon->registry.node_factories, 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); } @@ -107,7 +112,7 @@ pinos_node_factory_finalize (GObject * obj) PinosNodeFactoryPrivate *priv = factory->priv; g_debug ("node factory %p: finalize", factory); - pinos_map_remove (&priv->daemon->registry.node_factories, factory->id); + pinos_registry_remove_object (&priv->daemon->registry, &factory->object); g_free (priv->name); diff --git a/pinos/server/node-factory.h b/pinos/server/node-factory.h index 9849451df..41819a070 100644 --- a/pinos/server/node-factory.h +++ b/pinos/server/node-factory.h @@ -24,6 +24,9 @@ G_BEGIN_DECLS +#define PINOS_NODE_FACTORY_URI "http://pinos.org/ns/node-factory" +#define PINOS_NODE_FACTORY_PREFIX PINOS_NODE_FACTORY_URI "#" + typedef struct _PinosNodeFactory PinosNodeFactory; typedef struct _PinosNodeFactoryClass PinosNodeFactoryClass; typedef struct _PinosNodeFactoryPrivate PinosNodeFactoryPrivate; @@ -46,9 +49,9 @@ typedef struct _PinosNodeFactoryPrivate PinosNodeFactoryPrivate; * Pinos node factory class. */ struct _PinosNodeFactory { - GObject object; + GObject obj; - uint32_t id; + PinosObject object; PinosNodeFactoryPrivate *priv; }; diff --git a/pinos/server/node.c b/pinos/server/node.c index 8cbba1bdd..6cdf4a59f 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -603,10 +603,7 @@ node_register_object (PinosNode *this) priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel)); g_object_unref (skel); - this->id = pinos_map_insert_new (&daemon->registry.nodes, this); - pinos_log_debug ("node %p: register object %s, id %u", this, priv->object_path, this->id); - - pinos_daemon_add_node (daemon, this); + pinos_log_debug ("node %p: register object %s, id %u", this, priv->object_path, this->object.id); return; } @@ -619,8 +616,6 @@ node_unregister_object (PinosNode *this) 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_daemon_remove_node (priv->daemon, this); - pinos_map_remove (&priv->daemon->registry.nodes, this->id); } static void @@ -671,6 +666,13 @@ pinos_node_constructed (GObject * obj) g_signal_connect (this, "notify", (GCallback) on_property_notify, this); G_OBJECT_CLASS (pinos_node_parent_class)->constructed (obj); + pinos_object_init (&this->object, + priv->daemon->registry.uri.node, + this, + NULL); + + pinos_registry_add_object (&priv->daemon->registry, &this->object); + if (this->node->info) { unsigned int i; @@ -706,6 +708,7 @@ pinos_node_dispose (GObject * obj) pinos_log_debug ("node %p: dispose", node); pinos_node_set_state (node, PINOS_NODE_STATE_SUSPENDED); + pinos_registry_remove_object (&priv->daemon->registry, &node->object); node_unregister_object (node); pinos_main_loop_defer_cancel (priv->main_loop, node, 0); diff --git a/pinos/server/node.h b/pinos/server/node.h index 6113e27fc..4a5043869 100644 --- a/pinos/server/node.h +++ b/pinos/server/node.h @@ -24,6 +24,11 @@ G_BEGIN_DECLS +#define PINOS_NODE_URI "http://pinos.org/ns/node" +#define PINOS_NODE_PREFIX PINOS_NODE_URI "#" + +#define PINOS_PORT_URI PINOS_NODE_PREFIX "Port" + typedef struct _PinosPort PinosPort; typedef struct _PinosNode PinosNode; typedef struct _PinosNodeClass PinosNodeClass; @@ -46,7 +51,7 @@ typedef enum { #include struct _PinosPort { - uint32_t id; + PinosObject object; PinosNode *node; PinosDirection direction; uint32_t port; @@ -72,9 +77,9 @@ struct _PinosPort { * Pinos node class. */ struct _PinosNode { - GObject object; + GObject obj; - uint32_t id; + PinosObject object; PinosNodeFlags flags; diff --git a/pinos/server/registry.c b/pinos/server/registry.c index b711f24ff..e1bb62253 100644 --- a/pinos/server/registry.c +++ b/pinos/server/registry.c @@ -20,17 +20,33 @@ #include #include "pinos/client/pinos.h" +#include "pinos/server/daemon.h" #include "pinos/server/registry.h" +#include "pinos/server/node.h" +#include "pinos/server/node-factory.h" +#include "pinos/server/client.h" + +#include "spa/include/spa/monitor.h" void pinos_registry_init (PinosRegistry *reg) { reg->map = pinos_id_map_get_default(); - pinos_map_init (®->clients, 64); - pinos_map_init (®->nodes, 128); - pinos_map_init (®->ports, 512); - pinos_map_init (®->links, 256); - pinos_map_init (®->modules, 128); - pinos_map_init (®->monitors, 64); + reg->uri.daemon = spa_id_map_get_id (reg->map, PINOS_DAEMON_URI); + reg->uri.registry = spa_id_map_get_id (reg->map, PINOS_REGISTRY_URI); + reg->uri.node = spa_id_map_get_id (reg->map, PINOS_NODE_URI); + reg->uri.port = spa_id_map_get_id (reg->map, PINOS_PORT_URI); + reg->uri.link = spa_id_map_get_id (reg->map, PINOS_LINK_URI); + reg->uri.node_factory = spa_id_map_get_id (reg->map, PINOS_NODE_FACTORY_URI); + reg->uri.client = spa_id_map_get_id (reg->map, PINOS_CLIENT_URI); + + reg->uri.spa_node = spa_id_map_get_id (reg->map, SPA_NODE_URI); + reg->uri.spa_clock = spa_id_map_get_id (reg->map, SPA_CLOCK_URI); + reg->uri.spa_monitor = spa_id_map_get_id (reg->map, SPA_MONITOR_URI); + + pinos_map_init (®->objects, 512); + + pinos_signal_init (®->object_added); + pinos_signal_init (®->object_removed); } diff --git a/pinos/server/registry.h b/pinos/server/registry.h index aa4fe274d..1aa5ecdbf 100644 --- a/pinos/server/registry.h +++ b/pinos/server/registry.h @@ -20,38 +20,69 @@ #ifndef __PINOS_REGISTRY_H__ #define __PINOS_REGISTRY_H__ -#include +#ifdef __cplusplus +extern "C" { +#endif -G_BEGIN_DECLS +#define PINOS_REGISTRY_URI "http://pinos.org/ns/registry" +#define PINOS_REGISTRY_PREFIX PINOS_REGISTRY_URI "#" #include +#include +#include #include typedef struct _PinosRegistry PinosRegistry; +typedef struct { + uint32_t daemon; + uint32_t registry; + uint32_t node; + uint32_t port; + uint32_t link; + uint32_t node_factory; + uint32_t client; + uint32_t spa_node; + uint32_t spa_clock; + uint32_t spa_monitor; +} PinosURI; + /** * PinosRegistry: * * Pinos registry struct. */ struct _PinosRegistry { - SpaIDMap *map; + PinosObject object; + SpaIDMap *map; + PinosURI uri; PinosMap objects; - PinosMap clients; - PinosMap node_factories; - PinosMap nodes; - PinosMap ports; - PinosMap links; - PinosMap modules; - PinosMap monitors; - PinosMap devices; + PinosSignal object_added; + PinosSignal object_removed; }; +void pinos_registry_init (PinosRegistry *reg); -void pinos_registry_init (PinosRegistry *reg); +static inline void +pinos_registry_add_object (PinosRegistry *reg, + PinosObject *object) +{ + object->id = pinos_map_insert_new (®->objects, object); + pinos_signal_emit (®->object_added, object); +} -G_END_DECLS +static inline void +pinos_registry_remove_object (PinosRegistry *reg, + PinosObject *object) +{ + pinos_signal_emit (®->object_removed, object); + pinos_map_remove (®->objects, object->id); +} + +#ifdef __cplusplus +} +#endif #endif /* __PINOS_REGISTRY_H__ */