diff -Nru pipewire-0.2.3/config.h.meson pipewire-0.2.5/config.h.meson --- pipewire-0.2.3/config.h.meson 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/config.h.meson 2018-12-20 09:06:16.000000000 +0000 @@ -317,6 +317,9 @@ /* Define to 1 if you have the header file. */ #mesondefine HAVE_WINSOCK2_H +/* for the systemd header files */ +#mesondefine HAVE_SYSTEMD_DAEMON + /* the host CPU */ #mesondefine HOST_CPU diff -Nru pipewire-0.2.3/debian/changelog pipewire-0.2.5/debian/changelog --- pipewire-0.2.3/debian/changelog 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/changelog 2019-01-04 19:24:46.000000000 +0000 @@ -1,3 +1,19 @@ +pipewire (0.2.5-1) unstable; urgency=medium + + [ Jeremy Bicha ] + * New upstream release + * Bump minimum meson to 0.47 + * debian/libpipewire-0.2-1.symbols: Add new symbol + * Drop all patches: applied in new release + * Bump Standards-Version to 4.3.0 + + [ Laurent Bigonville ] + * debian/libpipewire-0.2-1.symbols: Add the Build-Depends-Package annotation + * debian/control: Set Section to net for the main pipewire package + (Closes: #908524) + + -- Jeremy Bicha Fri, 04 Jan 2019 14:24:46 -0500 + pipewire (0.2.3-3) unstable; urgency=medium * Team upload. diff -Nru pipewire-0.2.3/debian/control pipewire-0.2.5/debian/control --- pipewire-0.2.3/debian/control 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/control 2019-01-04 19:24:46.000000000 +0000 @@ -18,13 +18,13 @@ libva-dev, libv4l-dev, libx11-dev, - meson (>= 0.36.0), + meson (>= 0.47), pkg-config (>= 0.22), systemd, xmltoman, Build-Depends-Indep: doxygen , graphviz , -Standards-Version: 4.1.3 +Standards-Version: 4.3.0 Vcs-Browser: https://salsa.debian.org/utopia-team/pipewire Vcs-Git: https://salsa.debian.org/utopia-team/pipewire.git Homepage: https://pipewire.org/ @@ -100,6 +100,7 @@ Architecture: linux-any Depends: ${misc:Depends}, ${shlibs:Depends} +Section: net Description: PipeWire multimedia server PipeWire is a server and user space API to deal with multimedia pipelines. This includes: diff -Nru pipewire-0.2.3/debian/libpipewire-0.2-1.symbols pipewire-0.2.5/debian/libpipewire-0.2-1.symbols --- pipewire-0.2.3/debian/libpipewire-0.2-1.symbols 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/libpipewire-0.2-1.symbols 2019-01-04 19:24:46.000000000 +0000 @@ -1,4 +1,5 @@ libpipewire-0.2.so.1 libpipewire-0.2-1 #MINVER# +* Build-Depends-Package: libpipewire-0.2-dev pw_client_add_listener@Base 0.1.4 pw_client_destroy@Base 0.1.4 pw_client_find_resource@Base 0.1.8 @@ -191,6 +192,7 @@ pw_properties_new_string@Base 0.2.2 pw_properties_set@Base 0.1.4 pw_properties_setf@Base 0.1.4 + pw_properties_setva@Base 0.2.5 pw_protocol_add_listener@Base 0.1.4 pw_protocol_add_marshal@Base 0.1.4 pw_protocol_destroy@Base 0.1.4 diff -Nru pipewire-0.2.3/debian/patches/Fix-build-with-clang.patch pipewire-0.2.5/debian/patches/Fix-build-with-clang.patch --- pipewire-0.2.3/debian/patches/Fix-build-with-clang.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/Fix-build-with-clang.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,45 +0,0 @@ -From: Tomas Popela -Date: Thu, 6 Sep 2018 12:38:44 +0200 -Subject: Fix build with clang - -By using __typeof__ instead of typeof: - -/usr/include/pipewire/array.h:85:11: error: use of undeclared identifier 'typeof'; did you mean 'typeid'? - alloc = SPA_MAX(alloc, arr->extend); ---- - spa/include/spa/utils/defs.h | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - -diff --git a/spa/include/spa/utils/defs.h b/spa/include/spa/utils/defs.h -index 0486c02..e0ad462 100644 ---- a/spa/include/spa/utils/defs.h -+++ b/spa/include/spa/utils/defs.h -@@ -68,21 +68,21 @@ struct spa_fraction { - - #define SPA_MIN(a,b) \ - ({ \ -- typeof(a) _a = (a); \ -- typeof(b) _b = (b); \ -+ __typeof__(a) _a = (a); \ -+ __typeof__(b) _b = (b); \ - _a < _b ? _a : _b; \ - }) - #define SPA_MAX(a,b) \ - ({ \ -- typeof(a) _a = (a); \ -- typeof(b) _b = (b); \ -+ __typeof__(a) _a = (a); \ -+ __typeof__(b) _b = (b); \ - _a > _b ? _a : _b; \ - }) - #define SPA_CLAMP(v,low,high) \ - ({ \ -- typeof(v) _v = (v); \ -- typeof(low) _low = (low); \ -- typeof(high) _high = (high); \ -+ __typeof__(v) _v = (v); \ -+ __typeof__(low) _low = (low); \ -+ __typeof__(high) _high = (high); \ - _v > _high ? _high : ( _v < _low ? _low : _v); \ - }) - diff -Nru pipewire-0.2.3/debian/patches/Fix-memory-leak-in-pw_properties_set.patch pipewire-0.2.5/debian/patches/Fix-memory-leak-in-pw_properties_set.patch --- pipewire-0.2.3/debian/patches/Fix-memory-leak-in-pw_properties_set.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/Fix-memory-leak-in-pw_properties_set.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,56 +0,0 @@ -From: Jesse Pullinen -Date: Thu, 30 Aug 2018 19:40:40 +0300 -Subject: Fix memory leak in pw_properties_set - -removing a property leaked the key ---- - src/pipewire/properties.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/src/pipewire/properties.c b/src/pipewire/properties.c -index 269b77f..6271685 100644 ---- a/src/pipewire/properties.c -+++ b/src/pipewire/properties.c -@@ -247,13 +247,13 @@ void pw_properties_free(struct pw_properties *properties) - free(impl); - } - --static int do_replace(struct pw_properties *properties, char *key, char *value) -+static int do_replace(struct pw_properties *properties, const char *key, char *value) - { - struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this); - int index = find_index(properties, key); - - if (index == -1) { -- add_func(properties, key, value); -+ add_func(properties, strdup(key), value); - } else { - struct spa_dict_item *item = - pw_array_get_unchecked(&impl->items, index, struct spa_dict_item); -@@ -267,7 +267,7 @@ static int do_replace(struct pw_properties *properties, char *key, char *value) - item->value = other->value; - impl->items.size -= sizeof(struct spa_dict_item); - } else { -- item->key = key; -+ item->key = strdup(key); - item->value = value; - } - } -@@ -288,7 +288,7 @@ static int do_replace(struct pw_properties *properties, char *key, char *value) - */ - int pw_properties_set(struct pw_properties *properties, const char *key, const char *value) - { -- return do_replace(properties, strdup(key), value ? strdup(value) : NULL); -+ return do_replace(properties, key, value ? strdup(value) : NULL); - } - - /** Set a property value by format -@@ -312,7 +312,7 @@ int pw_properties_setf(struct pw_properties *properties, const char *key, const - vasprintf(&value, format, varargs); - va_end(varargs); - -- return do_replace(properties, strdup(key), value); -+ return do_replace(properties, key, value); - } - - /** Get a property diff -Nru pipewire-0.2.3/debian/patches/man-fix-man-page-install-path.patch pipewire-0.2.5/debian/patches/man-fix-man-page-install-path.patch --- pipewire-0.2.3/debian/patches/man-fix-man-page-install-path.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/man-fix-man-page-install-path.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,20 +0,0 @@ -From: Wim Taymans -Date: Wed, 19 Sep 2018 16:06:29 +0200 -Subject: man: fix man page install path - -Fixes #85 ---- - man/meson.build | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/man/meson.build b/man/meson.build -index 6c6d13d..ffa3321 100644 ---- a/man/meson.build -+++ b/man/meson.build -@@ -27,5 +27,5 @@ foreach m : manpages - command : [xmltoman, '@INPUT@'], - capture : true, - install : true, -- install_dir : join_paths(get_option('mandir'), 'man', m.get(1))) -+ install_dir : join_paths(get_option('mandir'), 'man' + m.get(1))) - endforeach diff -Nru pipewire-0.2.3/debian/patches/man-install-manpages-in-the-right-directory.patch pipewire-0.2.5/debian/patches/man-install-manpages-in-the-right-directory.patch --- pipewire-0.2.3/debian/patches/man-install-manpages-in-the-right-directory.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/man-install-manpages-in-the-right-directory.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,47 +0,0 @@ -From: Wim Taymans -Date: Thu, 30 Aug 2018 14:49:08 +0200 -Subject: man: install manpages in the right directory - ---- - man/meson.build | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/man/meson.build b/man/meson.build -index 1d7045b..6c6d13d 100644 ---- a/man/meson.build -+++ b/man/meson.build -@@ -7,22 +7,25 @@ manpage_conf.set('PIPEWIRE_CONFIG_DIR', pipewire_configdir) - manpage_conf.set('top_srcdir', meson.source_root()) - manpage_conf.set('top_builddir', meson.build_root()) - --manpages = ['pipewire.1', -- 'pipewire.conf.5', -- 'pipewire-cli.1', -- 'pipewire-monitor.1' ] -+manpages = [ -+ [ 'pipewire', '1' ], -+ [ 'pipewire.conf', '5' ], -+ [ 'pipewire-cli', '1' ], -+ [ 'pipewire-monitor', '1' ] -+] - - foreach m : manpages -- infile = m + '.xml.in' -- outfile = m + '.xml' -+ file = m.get(0) + '.' + m.get(1) -+ infile = file + '.xml.in' -+ outfile = file + '.xml' - xml = configure_file(input : infile, - output : outfile, - configuration : manpage_conf) -- custom_target(m + '.target', -- output : m, -+ custom_target(file + '.target', -+ output : file, - input : xml, - command : [xmltoman, '@INPUT@'], - capture : true, - install : true, -- install_dir : join_paths(get_option('mandir'), 'man1')) -+ install_dir : join_paths(get_option('mandir'), 'man', m.get(1))) - endforeach diff -Nru pipewire-0.2.3/debian/patches/meson-Use-pkgconfig.generate.patch pipewire-0.2.5/debian/patches/meson-Use-pkgconfig.generate.patch --- pipewire-0.2.3/debian/patches/meson-Use-pkgconfig.generate.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/meson-Use-pkgconfig.generate.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,146 +0,0 @@ -From: "Jan Alexander Steffens (heftig)" -Date: Sun, 2 Sep 2018 03:22:14 +0200 -Subject: meson: Use pkgconfig.generate - -Also fixes the moduledir having a duplicated prefix. ---- - meson.build | 4 ++-- - pkgconfig/libpipewire.pc.in | 11 ----------- - pkgconfig/libspa.pc.in | 7 ------- - pkgconfig/meson.build | 25 ------------------------- - spa/meson.build | 6 ++++++ - src/pipewire/meson.build | 11 ++++++++++- - 6 files changed, 18 insertions(+), 46 deletions(-) - delete mode 100644 pkgconfig/libpipewire.pc.in - delete mode 100644 pkgconfig/libspa.pc.in - delete mode 100644 pkgconfig/meson.build - -diff --git a/meson.build b/meson.build -index 443da44..bcbe35e 100644 ---- a/meson.build -+++ b/meson.build -@@ -1,6 +1,6 @@ - project('pipewire', 'c', - version : '0.2.3', -- meson_version : '>= 0.36.0', -+ meson_version : '>= 0.42.0', - default_options : [ 'warning_level=1', - 'c_std=gnu99', - 'buildtype=debugoptimized' ]) -@@ -34,6 +34,7 @@ modules_install_dir = join_paths(pipewire_libdir, 'pipewire-@0@'.format(apiversi - spa_plugindir = join_paths(pipewire_libdir, 'spa') - - gnome = import('gnome') -+pkgconfig = import('pkgconfig') - - cc = meson.get_compiler('c') - -@@ -164,7 +165,6 @@ endif - - subdir('spa') - subdir('src') --subdir('pkgconfig') - - if get_option('docs') - doxygen = find_program('doxygen', required : false) -diff --git a/pkgconfig/libpipewire.pc.in b/pkgconfig/libpipewire.pc.in -deleted file mode 100644 -index ca302fb..0000000 ---- a/pkgconfig/libpipewire.pc.in -+++ /dev/null -@@ -1,11 +0,0 @@ --prefix=@prefix@ --exec_prefix=@exec_prefix@ --libdir=@libdir@ --includedir=@includedir@/ --moduledir=@moduledir@ -- --Name: libpipewire --Description: PipeWire Interface --Version: @VERSION@ --Libs: -L${libdir} -lpipewire-@PIPEWIRE_API_VERSION@ --Cflags: -I${includedir} -D_REENTRANT -diff --git a/pkgconfig/libspa.pc.in b/pkgconfig/libspa.pc.in -deleted file mode 100644 -index e5878d2..0000000 ---- a/pkgconfig/libspa.pc.in -+++ /dev/null -@@ -1,7 +0,0 @@ --prefix=@prefix@ --includedir=@includedir@/ -- --Name: libspa --Description: Simple Plugin API --Version: @VERSION@ --Cflags: -I${includedir} -D_REENTRANT -diff --git a/pkgconfig/meson.build b/pkgconfig/meson.build -deleted file mode 100644 -index 9d57578..0000000 ---- a/pkgconfig/meson.build -+++ /dev/null -@@ -1,25 +0,0 @@ --pkgconf = configuration_data() -- --pkgconf.set('prefix', get_option('prefix')) --pkgconf.set('exec_prefix', '${prefix}') --pkgconf.set('libdir', '${prefix}/@0@'.format(get_option('libdir'))) --pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir'))) --pkgconf.set('moduledir', '${prefix}/@0@'.format(modules_install_dir)) --pkgconf.set('PIPEWIRE_API_VERSION', apiversion) --pkgconf.set('VERSION', pipewire_version) -- --pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir')) -- --pkg_files = [ -- [ 'libpipewire', apiversion ], -- [ 'libspa', spaversion ], --] -- --foreach p : pkg_files -- infile = p.get(0) + '.pc.in' -- outfile = p.get(0) + '-@0@.pc'.format(p.get(1)) -- configure_file(input : infile, -- output : outfile, -- configuration : pkgconf, -- install_dir : pkg_install_dir) --endforeach -diff --git a/spa/meson.build b/spa/meson.build -index 09e1c2f..d190b9b 100644 ---- a/spa/meson.build -+++ b/spa/meson.build -@@ -24,3 +24,9 @@ subdir('include') - subdir('plugins') - subdir('tools') - subdir('tests') -+ -+pkgconfig.generate(filebase : 'libspa-@0@'.format(spaversion), -+ name : 'libspa', -+ description : 'Simple Plugin API', -+ version : pipewire_version, -+ extra_cflags : '-D_REENTRANT') -diff --git a/src/pipewire/meson.build b/src/pipewire/meson.build -index 8aeb6f5..d2d75b8 100644 ---- a/src/pipewire/meson.build -+++ b/src/pipewire/meson.build -@@ -74,7 +74,8 @@ libpipewire_c_args = [ - '-D_POSIX_C_SOURCE', - ] - --libpipewire = shared_library('pipewire-@0@'.format(apiversion), pipewire_sources, -+libpipewire_name = 'pipewire-@0@'.format(apiversion) -+libpipewire = shared_library(libpipewire_name, pipewire_sources, - version : libversion, - soversion : soversion, - c_args : libpipewire_c_args, -@@ -87,3 +88,11 @@ pipewire_dep = declare_dependency(link_with : libpipewire, - include_directories : [pipewire_inc, configinc, spa_inc], - dependencies : [pthread_lib], - ) -+ -+pkgconfig.generate(filebase : 'lib@0@'.format(libpipewire_name), -+ libraries : [libpipewire], -+ name : 'libpipewire', -+ description : 'PipeWire Interface', -+ version : pipewire_version, -+ extra_cflags : '-D_REENTRANT', -+ variables : ['moduledir=${libdir}/@0@'.format(libpipewire_name)]) diff -Nru pipewire-0.2.3/debian/patches/pipewire-fix-leak-of-dbus-interface.patch pipewire-0.2.5/debian/patches/pipewire-fix-leak-of-dbus-interface.patch --- pipewire-0.2.3/debian/patches/pipewire-fix-leak-of-dbus-interface.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/pipewire-fix-leak-of-dbus-interface.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,229 +0,0 @@ -From: Wim Taymans -Date: Wed, 19 Sep 2018 15:58:05 +0200 -Subject: pipewire: fix leak of dbus interface - -Track loaded interfaces. -Add a method to release the dbus interface when the core is -destroyed. -Free SDL resources in video-play example ---- - src/examples/video-play.c | 4 +++ - src/pipewire/core.c | 6 +++- - src/pipewire/pipewire.c | 72 ++++++++++++++++++++++++++++++++++++++++------- - src/pipewire/pipewire.h | 1 + - src/pipewire/private.h | 2 ++ - 5 files changed, 74 insertions(+), 11 deletions(-) - -diff --git a/src/examples/video-play.c b/src/examples/video-play.c -index 8ec70b8..b259a86 100644 ---- a/src/examples/video-play.c -+++ b/src/examples/video-play.c -@@ -449,5 +449,9 @@ int main(int argc, char *argv[]) - pw_core_destroy(data.core); - pw_main_loop_destroy(data.loop); - -+ SDL_DestroyTexture(data.texture); -+ SDL_DestroyRenderer(data.renderer); -+ SDL_DestroyWindow(data.window); -+ - return 0; - } -diff --git a/src/pipewire/core.c b/src/pipewire/core.c -index a844eb4..6134a6e 100644 ---- a/src/pipewire/core.c -+++ b/src/pipewire/core.c -@@ -391,12 +391,14 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop, struct pw_properties *pro - spa_graph_init(&this->rt.graph); - spa_graph_set_callbacks(&this->rt.graph, &spa_graph_impl_default, NULL); - -+ this->dbus_iface = pw_get_spa_dbus(this->main_loop); -+ - this->support[0] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, this->type.map); - this->support[1] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__DataLoop, this->data_loop->loop); - this->support[2] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__MainLoop, this->main_loop->loop); - this->support[3] = SPA_SUPPORT_INIT(SPA_TYPE__LoopUtils, this->main_loop->utils); - this->support[4] = SPA_SUPPORT_INIT(SPA_TYPE__Log, pw_log_get()); -- this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE__DBus, pw_get_spa_dbus(this->main_loop)); -+ this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE__DBus, this->dbus_iface); - this->n_support = 6; - - pw_log_debug("%p", this->support[5].data); -@@ -494,6 +496,8 @@ void pw_core_destroy(struct pw_core *core) - - pw_data_loop_destroy(core->data_loop_impl); - -+ pw_release_spa_dbus(core->dbus_iface); -+ - pw_properties_free(core->properties); - - pw_map_clear(&core->globals); -diff --git a/src/pipewire/pipewire.c b/src/pipewire/pipewire.c -index 925e8af..d1c6746 100644 ---- a/src/pipewire/pipewire.c -+++ b/src/pipewire/pipewire.c -@@ -44,6 +44,19 @@ static struct support_info { - uint32_t n_support; - } support_info; - -+struct interface { -+ struct spa_list link; -+ struct spa_handle *handle; -+ uint32_t type; -+ void *iface; -+}; -+ -+struct registry { -+ struct spa_list interfaces; -+}; -+ -+static struct registry global_registry; -+ - static bool - open_support(const char *path, - const char *lib, -@@ -92,7 +105,7 @@ static const struct spa_handle_factory *get_factory(struct support_info *info, c - return NULL; - } - --static void * -+static struct interface * - load_interface(struct support_info *info, - const char *factory_name, - const char *type) -@@ -101,7 +114,8 @@ load_interface(struct support_info *info, - struct spa_handle *handle; - uint32_t type_id; - const struct spa_handle_factory *factory; -- void *iface; -+ struct interface *iface; -+ void *ptr; - struct spa_type_map *map = NULL; - - factory = get_factory(info, factory_name); -@@ -118,12 +132,22 @@ load_interface(struct support_info *info, - map = pw_get_support_interface(SPA_TYPE__TypeMap); - type_id = map ? spa_type_map_get_id(map, type) : 0; - -- if ((res = spa_handle_get_interface(handle, type_id, &iface)) < 0) { -+ if ((res = spa_handle_get_interface(handle, type_id, &ptr)) < 0) { - fprintf(stderr, "can't get %s interface %d\n", type, res); - goto interface_failed; - } -+ -+ if ((iface = calloc(1, sizeof(struct interface))) == NULL) -+ goto alloc_failed; -+ -+ iface->handle = handle; -+ iface->type = type_id; -+ iface->iface = ptr; -+ spa_list_append(&global_registry.interfaces, &iface->link); -+ - return iface; - -+ alloc_failed: - interface_failed: - spa_handle_clear(handle); - init_failed: -@@ -175,6 +199,7 @@ void *pw_get_spa_dbus(struct pw_loop *loop) - { - struct support_info dbus_support_info; - const char *str; -+ struct interface *iface; - - dbus_support_info.n_support = support_info.n_support; - memcpy(dbus_support_info.support, support_info.support, -@@ -186,11 +211,36 @@ void *pw_get_spa_dbus(struct pw_loop *loop) - if ((str = getenv("SPA_PLUGIN_DIR")) == NULL) - str = PLUGINDIR; - -- if (open_support(str, "support/libspa-dbus", &dbus_support_info)) -- return load_interface(&dbus_support_info, "dbus", SPA_TYPE__DBus); -- -+ if (open_support(str, "support/libspa-dbus", &dbus_support_info)) { -+ iface = load_interface(&dbus_support_info, "dbus", SPA_TYPE__DBus); -+ if (iface != NULL) -+ return iface->iface; -+ } - return NULL; - } -+static struct interface *find_interface(void *iface) -+{ -+ struct interface *i; -+ spa_list_for_each(i, &global_registry.interfaces, link) { -+ if (i->iface == iface) -+ return i; -+ } -+ return NULL; -+} -+ -+int pw_release_spa_dbus(void *dbus) -+{ -+ struct interface *iface; -+ -+ if ((iface = find_interface(dbus)) == NULL) -+ return -ENOENT; -+ -+ spa_list_remove(&iface->link); -+ spa_handle_clear(iface->handle); -+ free(iface->handle); -+ free(iface); -+ return 0; -+} - - /** Initialize PipeWire - * -@@ -207,7 +257,7 @@ void *pw_get_spa_dbus(struct pw_loop *loop) - void pw_init(int *argc, char **argv[]) - { - const char *str; -- void *iface; -+ struct interface *iface; - struct support_info *info = &support_info; - - if ((str = getenv("PIPEWIRE_DEBUG"))) -@@ -219,15 +269,17 @@ void pw_init(int *argc, char **argv[]) - if (support_info.n_support > 0) - return; - -+ spa_list_init(&global_registry.interfaces); -+ - if (open_support(str, "support/libspa-support", info)) { - iface = load_interface(info, "mapper", SPA_TYPE__TypeMap); - if (iface != NULL) -- info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface); -+ info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface->iface); - - iface = load_interface(info, "logger", SPA_TYPE__Log); - if (iface != NULL) { -- info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface); -- pw_log_set(iface); -+ info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface->iface); -+ pw_log_set(iface->iface); - } - } - pw_log_info("version %s", pw_get_library_version()); -diff --git a/src/pipewire/pipewire.h b/src/pipewire/pipewire.h -index dcf705e..16bc284 100644 ---- a/src/pipewire/pipewire.h -+++ b/src/pipewire/pipewire.h -@@ -134,6 +134,7 @@ void * - pw_get_support_interface(const char *type); - - void *pw_get_spa_dbus(struct pw_loop *loop); -+int pw_release_spa_dbus(void *dbus); - - const struct spa_handle_factory * - pw_get_support_factory(const char *factory_name); -diff --git a/src/pipewire/private.h b/src/pipewire/private.h -index 2b2682a..a9b189a 100644 ---- a/src/pipewire/private.h -+++ b/src/pipewire/private.h -@@ -183,6 +183,8 @@ struct pw_core { - struct pw_loop *data_loop; /**< data loop for data passing */ - struct pw_data_loop *data_loop_impl; - -+ void *dbus_iface; -+ - struct spa_support support[16]; /**< support for spa plugins */ - uint32_t n_support; /**< number of support items */ - diff -Nru pipewire-0.2.3/debian/patches/series pipewire-0.2.5/debian/patches/series --- pipewire-0.2.3/debian/patches/series 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/series 2019-01-04 19:24:46.000000000 +0000 @@ -1,7 +0,0 @@ -man-install-manpages-in-the-right-directory.patch -Fix-memory-leak-in-pw_properties_set.patch -meson-Use-pkgconfig.generate.patch -Fix-build-with-clang.patch -stream-improve-cleanup.patch -pipewire-fix-leak-of-dbus-interface.patch -man-fix-man-page-install-path.patch diff -Nru pipewire-0.2.3/debian/patches/stream-improve-cleanup.patch pipewire-0.2.5/debian/patches/stream-improve-cleanup.patch --- pipewire-0.2.3/debian/patches/stream-improve-cleanup.patch 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/patches/stream-improve-cleanup.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -From: Wim Taymans -Date: Mon, 17 Sep 2018 12:24:15 +0200 -Subject: stream: improve cleanup - -Destroy proxies before disconnect, they might still need the connection. -Destroy the stream related objects when the stream node is destroyed. -Don't try to remove the mainloop sources from the data loop. -Don't try to create properties in _connect, we already created them -in _new. -In disconnect, make the server destroy the node and destroy our local -proxy. ---- - src/pipewire/remote.c | 11 +++++------ - src/pipewire/stream.c | 47 +++++++++++++++++++++++------------------------ - 2 files changed, 28 insertions(+), 30 deletions(-) - -diff --git a/src/pipewire/remote.c b/src/pipewire/remote.c -index 99a3c68..26e6568 100644 ---- a/src/pipewire/remote.c -+++ b/src/pipewire/remote.c -@@ -180,11 +180,10 @@ static void core_event_remove_id(void *data, uint32_t id) - struct pw_remote *this = data; - struct pw_proxy *proxy; - -- proxy = pw_map_lookup(&this->objects, id); -- if (proxy) { -- pw_log_debug("remote %p: object remove %u", this, id); -+ pw_log_debug("remote %p: object remove %u", this, id); -+ if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) - pw_proxy_destroy(proxy); -- } -+ - pw_map_remove(&this->objects, id); - } - -@@ -442,12 +441,12 @@ int pw_remote_disconnect(struct pw_remote *remote) - spa_list_for_each_safe(stream, s2, &remote->stream_list, link) - pw_stream_disconnect(stream); - -- pw_protocol_client_disconnect (remote->conn); -- - spa_list_for_each_safe(proxy, t2, &remote->proxy_list, link) - pw_proxy_destroy(proxy); - remote->core_proxy = NULL; - -+ pw_protocol_client_disconnect (remote->conn); -+ - pw_map_clear(&remote->objects); - pw_map_clear(&remote->types); - remote->n_types = 0; -diff --git a/src/pipewire/stream.c b/src/pipewire/stream.c -index c7736be..fa8922c 100644 ---- a/src/pipewire/stream.c -+++ b/src/pipewire/stream.c -@@ -229,7 +229,7 @@ static void clear_buffers(struct pw_stream *stream) - struct buffer *b; - int i, j; - -- pw_log_debug("stream %p: clear buffers", stream); -+ pw_log_debug("stream %p: clear %d buffers", stream, impl->n_buffers); - - for (i = 0; i < impl->n_buffers; i++) { - b = &impl->buffers[i]; -@@ -534,33 +534,21 @@ void pw_stream_destroy(struct pw_stream *stream) - - pw_stream_events_destroy(stream); - -- if (impl->node_proxy) -- spa_hook_remove(&impl->proxy_listener); -- - pw_stream_disconnect(stream); - - spa_list_remove(&stream->link); - -- set_init_params(stream, 0, NULL); -- set_params(stream, 0, NULL); -- -- if (impl->format) -- free(impl->format); -+ pw_array_clear(&impl->mem_ids); - - if (stream->error) - free(stream->error); - -- clear_buffers(stream); -- -- clear_mems(stream); -- pw_array_clear(&impl->mem_ids); -+ if (stream->name) -+ free(stream->name); - - if (stream->properties) - pw_properties_free(stream->properties); - -- if (stream->name) -- free(stream->name); -- - free(impl); - } - -@@ -821,7 +809,7 @@ on_rtsocket_condition(void *data, int fd, enum spa_io mask) - - if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { - pw_log_warn("got error"); -- unhandle_socket(stream); -+ do_remove_sources(stream->remote->core->data_loop->loop, false, 0, NULL, 0, impl); - return; - } - -@@ -1241,6 +1229,21 @@ static void on_node_proxy_destroy(void *data) - impl->node_proxy = NULL; - spa_hook_remove(&impl->proxy_listener); - -+ set_init_params(this, 0, NULL); -+ set_params(this, 0, NULL); -+ -+ clear_buffers(this); -+ clear_mems(this); -+ -+ if (impl->format) { -+ free(impl->format); -+ impl->format = NULL; -+ } -+ if (impl->trans) { -+ pw_client_node_transport_destroy(impl->trans); -+ impl->trans = NULL; -+ } -+ - stream_set_state(this, PW_STREAM_STATE_UNCONNECTED, NULL); - } - -@@ -1268,8 +1271,6 @@ pw_stream_connect(struct pw_stream *stream, - - stream_set_state(stream, PW_STREAM_STATE_CONNECTING, NULL); - -- if (stream->properties == NULL) -- stream->properties = pw_properties_new(NULL, NULL); - if (port_path) - pw_properties_set(stream->properties, PW_NODE_PROP_TARGET_NODE, port_path); - if (flags & PW_STREAM_FLAG_AUTOCONNECT) -@@ -1332,17 +1333,15 @@ int pw_stream_disconnect(struct pw_stream *stream) - { - struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); - -+ pw_log_debug("stream %p: disconnect", stream); -+ - impl->disconnecting = true; - - unhandle_socket(stream); - - if (impl->node_proxy) { - pw_client_node_proxy_destroy(impl->node_proxy); -- impl->node_proxy = NULL; -- } -- if (impl->trans) { -- pw_client_node_transport_destroy(impl->trans); -- impl->trans = NULL; -+ pw_proxy_destroy((struct pw_proxy *)impl->node_proxy); - } - return 0; - } diff -Nru pipewire-0.2.3/debian/rules pipewire-0.2.5/debian/rules --- pipewire-0.2.3/debian/rules 2018-09-25 23:40:56.000000000 +0000 +++ pipewire-0.2.5/debian/rules 2019-01-04 19:24:46.000000000 +0000 @@ -1,21 +1,17 @@ #!/usr/bin/make -f -include /usr/share/dpkg/default.mk export DEB_BUILD_MAINT_OPTIONS = hardening=+all export DEB_LDFLAGS_MAINT_APPEND = -Wl,-z,defs -Wl,--as-needed %: - dh $@ --buildsystem=meson + dh $@ - -MESON_OPTS = \ - -Dgstreamer=true \ +override_dh_auto_configure: + dh_auto_configure -- \ + -Dgstreamer=enabled \ -Dman=true \ -Ddocs=true -override_dh_auto_configure: - dh_auto_configure -- $(MESON_OPTS) - override_dh_missing: dh_missing --fail-missing diff -Nru pipewire-0.2.3/.gitignore pipewire-0.2.5/.gitignore --- pipewire-0.2.3/.gitignore 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/.gitignore 2018-12-20 09:06:16.000000000 +0000 @@ -6,5 +6,32 @@ *.tar.gz *.tar.xz *.o +build/ config.h.meson +cscope.out +cscope.in.out +cscope.po.out +# Created by https://www.gitignore.io/api/vim + +### Vim ### +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + + +# End of https://www.gitignore.io/api/vim diff -Nru pipewire-0.2.3/man/meson.build pipewire-0.2.5/man/meson.build --- pipewire-0.2.3/man/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/man/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -7,22 +7,25 @@ manpage_conf.set('top_srcdir', meson.source_root()) manpage_conf.set('top_builddir', meson.build_root()) -manpages = ['pipewire.1', - 'pipewire.conf.5', - 'pipewire-cli.1', - 'pipewire-monitor.1' ] +manpages = [ + [ 'pipewire', '1' ], + [ 'pipewire.conf', '5' ], + [ 'pipewire-cli', '1' ], + [ 'pipewire-monitor', '1' ] +] foreach m : manpages - infile = m + '.xml.in' - outfile = m + '.xml' + file = m.get(0) + '.' + m.get(1) + infile = file + '.xml.in' + outfile = file + '.xml' xml = configure_file(input : infile, output : outfile, configuration : manpage_conf) - custom_target(m + '.target', - output : m, + custom_target(file + '.target', + output : file, input : xml, command : [xmltoman, '@INPUT@'], capture : true, install : true, - install_dir : join_paths(get_option('mandir'), 'man1')) + install_dir : join_paths(get_option('mandir'), 'man' + m.get(1))) endforeach diff -Nru pipewire-0.2.3/meson.build pipewire-0.2.5/meson.build --- pipewire-0.2.3/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -1,6 +1,6 @@ project('pipewire', 'c', - version : '0.2.3', - meson_version : '>= 0.36.0', + version : '0.2.5', + meson_version : '>= 0.47.0', default_options : [ 'warning_level=1', 'c_std=gnu99', 'buildtype=debugoptimized' ]) @@ -34,6 +34,7 @@ spa_plugindir = join_paths(pipewire_libdir, 'spa') gnome = import('gnome') +pkgconfig = import('pkgconfig') cc = meson.get_compiler('c') @@ -124,6 +125,16 @@ cdata.set('HAVE_MEMFD_CREATE', 1) endif +if get_option('systemd') + systemd = dependency('systemd', required: false) + systemd_dep = dependency('libsystemd', required: false) + if systemd.found() and systemd_dep.found() + cdata.set('HAVE_SYSTEMD_DAEMON', 1) + else + warning('Systemd integration was enabled, but systemd is not available') + endif +endif + configure_file(input : 'config.h.meson', output : 'config.h', configuration : cdata) @@ -150,21 +161,29 @@ pthread_lib = dependency('threads') dbus_dep = dependency('dbus-1') -if get_option('gstreamer') - glib_dep = dependency('glib-2.0', version : '>=2.32.0') - gobject_dep = dependency('gobject-2.0') - gmodule_dep = dependency('gmodule-2.0') - gio_dep = [dependency('gio-2.0'), dependency('gio-unix-2.0')] - gst_dep = [dependency('gstreamer-1.0'), - dependency('gstreamer-plugins-base-1.0'), - dependency('gstreamer-video-1.0'), - dependency('gstreamer-audio-1.0'), - dependency('gstreamer-allocators-1.0'),] +if not get_option('gstreamer').disabled() + build_gst = true + glib_dep = [dependency('glib-2.0', version : '>=2.32.0', required: get_option('gstreamer'))] + gobject_dep = [dependency('gobject-2.0', required: get_option('gstreamer'))] + gmodule_dep = [dependency('gmodule-2.0', required: get_option('gstreamer'))] + gio_dep = [dependency('gio-2.0', required: get_option('gstreamer')), dependency('gio-unix-2.0', required: get_option('gstreamer'))] + gst_dep = [dependency('gstreamer-1.0', required: get_option('gstreamer')), + dependency('gstreamer-plugins-base-1.0', required: get_option('gstreamer')), + dependency('gstreamer-video-1.0', required: get_option('gstreamer')), + dependency('gstreamer-audio-1.0', required: get_option('gstreamer')), + dependency('gstreamer-allocators-1.0', required: get_option('gstreamer')),] + foreach dep: glib_dep + gobject_dep + gio_dep + gst_dep + if build_gst and not dep.found() + build_gst = false + message('@0@ not found, disabling GStreamer'.format(dep)) + endif + endforeach +else + build_gst = false endif subdir('spa') subdir('src') -subdir('pkgconfig') if get_option('docs') doxygen = find_program('doxygen', required : false) @@ -183,3 +202,6 @@ warning('Man page generation was enabled, but xmltoman is not available') endif endif + +setenv = find_program('pw-uninstalled.sh') +run_target('uninstalled', command : [setenv, '-b@0@'.format(meson.build_root())]) diff -Nru pipewire-0.2.3/meson_options.txt pipewire-0.2.5/meson_options.txt --- pipewire-0.2.3/meson_options.txt 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/meson_options.txt 2018-12-20 09:06:16.000000000 +0000 @@ -8,8 +8,8 @@ value: false) option('gstreamer', description: 'Build GStreamer plugins', - type: 'boolean', - value: false) + type: 'feature', + value: 'auto') option('systemd', description: 'Enable systemd integration', type: 'boolean', diff -Nru pipewire-0.2.3/NEWS pipewire-0.2.5/NEWS --- pipewire-0.2.3/NEWS 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/NEWS 2018-12-20 09:06:16.000000000 +0000 @@ -1,16 +1,11 @@ -PipeWire 0.2.3 +PipeWire 0.2.5 -- Fix deviceprovider caps introspection -- Refcounting fixes in pipewiresrc -- Remove clock interpolation from stream -- Improve clock in gstreamer elements -- Remove spalib -- Fix crash with pw_map -- Add version number to hook list -- Improve driver mode in gstreamer elements -- add daemon options -- add man pages +- build fixes for systemd +- Add cursor and bitmap metadata. This can be used to send a cursor + sprite with the video stream. +- permissions were set too strict for non-flatpak clients +- Fix crash in loop caused by thread unsafe hook emission +- Add more error checking for thread-loop +- Small cleanups and bugfixes -Work is ongoing in the work branch that features a completely new -scheduling method that will enable audio support. Some of these -API changes are backported in this branch. +This is mostly a bugfix release. diff -Nru pipewire-0.2.3/pkgconfig/libpipewire.pc.in pipewire-0.2.5/pkgconfig/libpipewire.pc.in --- pipewire-0.2.3/pkgconfig/libpipewire.pc.in 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/pkgconfig/libpipewire.pc.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,11 +0,0 @@ -prefix=@prefix@ -exec_prefix=@exec_prefix@ -libdir=@libdir@ -includedir=@includedir@/ -moduledir=@moduledir@ - -Name: libpipewire -Description: PipeWire Interface -Version: @VERSION@ -Libs: -L${libdir} -lpipewire-@PIPEWIRE_API_VERSION@ -Cflags: -I${includedir} -D_REENTRANT diff -Nru pipewire-0.2.3/pkgconfig/libspa.pc.in pipewire-0.2.5/pkgconfig/libspa.pc.in --- pipewire-0.2.3/pkgconfig/libspa.pc.in 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/pkgconfig/libspa.pc.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -prefix=@prefix@ -includedir=@includedir@/ - -Name: libspa -Description: Simple Plugin API -Version: @VERSION@ -Cflags: -I${includedir} -D_REENTRANT diff -Nru pipewire-0.2.3/pkgconfig/meson.build pipewire-0.2.5/pkgconfig/meson.build --- pipewire-0.2.3/pkgconfig/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/pkgconfig/meson.build 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -pkgconf = configuration_data() - -pkgconf.set('prefix', get_option('prefix')) -pkgconf.set('exec_prefix', '${prefix}') -pkgconf.set('libdir', '${prefix}/@0@'.format(get_option('libdir'))) -pkgconf.set('includedir', '${prefix}/@0@'.format(get_option('includedir'))) -pkgconf.set('moduledir', '${prefix}/@0@'.format(modules_install_dir)) -pkgconf.set('PIPEWIRE_API_VERSION', apiversion) -pkgconf.set('VERSION', pipewire_version) - -pkg_install_dir = '@0@/pkgconfig'.format(get_option('libdir')) - -pkg_files = [ - [ 'libpipewire', apiversion ], - [ 'libspa', spaversion ], -] - -foreach p : pkg_files - infile = p.get(0) + '.pc.in' - outfile = p.get(0) + '-@0@.pc'.format(p.get(1)) - configure_file(input : infile, - output : outfile, - configuration : pkgconf, - install_dir : pkg_install_dir) -endforeach diff -Nru pipewire-0.2.3/pw-uninstalled.sh pipewire-0.2.5/pw-uninstalled.sh --- pipewire-0.2.3/pw-uninstalled.sh 1970-01-01 00:00:00.000000000 +0000 +++ pipewire-0.2.5/pw-uninstalled.sh 2018-12-20 09:06:16.000000000 +0000 @@ -0,0 +1,38 @@ +#!/bin/sh + +set -e + +while getopts ":b:" opt; do + case ${opt} in + b) + BUILDDIR=${OPTARG} + ;; + \?) + echo "Invalid option: -${OPTARG}" + exit -1 + ;; + :) + echo "Option -${OPTARG} requires an argument" + exit -1 + ;; + esac +done + +if [ -z "${BUILDDIR}" ]; then + BUILDDIR=${PWD}/build + echo "Using default build directory: ${BUILDDIR}" +fi + +if [ ! -d ${BUILDDIR} ]; then + echo "Invalid build directory: ${BUILDDIR}" + exit -1 +fi + +export PIPEWIRE_CONFIG_FILE="${BUILDDIR}/src/daemon/pipewire.conf" +export SPA_PLUGIN_DIR="${BUILDDIR}/spa/plugins" +export PIPEWIRE_MODULE_DIR="${BUILDDIR}/src/modules" +export PATH="${BUILDDIR}/src/daemon:${PATH}" +export GST_PLUGIN_PATH="${BUILDDIR}/src/gst/:${GST_PLUGIN_PATH}" + +# FIXME: find a nice, shell-neutral way to specify a prompt +${SHELL} diff -Nru pipewire-0.2.3/spa/include/spa/buffer/meta.h pipewire-0.2.5/spa/include/spa/buffer/meta.h --- pipewire-0.2.3/spa/include/spa/buffer/meta.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/spa/include/spa/buffer/meta.h 2018-12-20 09:06:16.000000000 +0000 @@ -36,6 +36,8 @@ #define SPA_TYPE_META__Header SPA_TYPE_META_BASE "Header" #define SPA_TYPE_META__VideoCrop SPA_TYPE_META_BASE "VideoCrop" +#define SPA_TYPE_META__Bitmap SPA_TYPE_META_BASE "Bitmap" +#define SPA_TYPE_META__Cursor SPA_TYPE_META_BASE "Cursor" /** * A metadata element. @@ -84,6 +86,32 @@ uint32_t offset; /**< offset in buffer memory */ }; +#define spa_meta_bitmap_is_valid(m) ((m)->format != 0) + +/** + * Bitmap information + */ +struct spa_meta_bitmap { + uint32_t format; /**< bitmap video format, 0 invalid */ + struct spa_rectangle size; /**< width and height of bitmap */ + int32_t stride; /**< stride of bitmap data */ + uint32_t offset; /**< offset of bitmap data in this structure */ +}; + +#define spa_meta_cursor_is_valid(m) ((m)->id != 0) + +/** + * Cursor information + */ +struct spa_meta_cursor { + uint32_t id; /**< cursor id, 0 for no cursor */ + uint32_t flags; /**< extra flags */ + struct spa_point position; /**< position on screen */ + struct spa_point hotspot; /**< offsets for hotspot in bitmap */ + uint32_t bitmap_offset; /**< offset of bitmap meta in this structure */ +}; + + struct spa_type_meta { uint32_t Header; uint32_t VideoCrop; diff -Nru pipewire-0.2.3/spa/include/spa/support/loop.h pipewire-0.2.5/spa/include/spa/support/loop.h --- pipewire-0.2.3/spa/include/spa/support/loop.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/spa/include/spa/support/loop.h 2018-12-20 09:06:16.000000000 +0000 @@ -111,8 +111,8 @@ void (*after) (void *data); }; -#define spa_loop_control_hook_before(l) spa_hook_list_call(l, struct spa_loop_control_hooks, before, 0) -#define spa_loop_control_hook_after(l) spa_hook_list_call(l, struct spa_loop_control_hooks, after, 0) +#define spa_loop_control_hook_before(l) spa_hook_list_call_simple(l, struct spa_loop_control_hooks, before, 0) +#define spa_loop_control_hook_after(l) spa_hook_list_call_simple(l, struct spa_loop_control_hooks, after, 0) /** * Control an event loop diff -Nru pipewire-0.2.3/spa/include/spa/utils/defs.h pipewire-0.2.5/spa/include/spa/utils/defs.h --- pipewire-0.2.3/spa/include/spa/utils/defs.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/spa/include/spa/utils/defs.h 2018-12-20 09:06:16.000000000 +0000 @@ -52,12 +52,23 @@ }; #define SPA_RECTANGLE(width,height) (struct spa_rectangle){ width, height } - struct spa_rectangle { uint32_t width; uint32_t height; }; +#define SPA_POINT(x,y) (struct spa_point){ x, y } +struct spa_point { + int32_t x; + int32_t y; +}; + +#define SPA_REGION(x,y,width,height) (struct spa_region){ SPA_POINT(x,y), SPA_RECTANGLE(width,height) } +struct spa_region { + struct spa_point position; + struct spa_rectangle size; +}; + #define SPA_FRACTION(num,denom) (struct spa_fraction){ num, denom } struct spa_fraction { uint32_t num; @@ -68,25 +79,25 @@ #define SPA_MIN(a,b) \ ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ _a < _b ? _a : _b; \ }) #define SPA_MAX(a,b) \ ({ \ - typeof(a) _a = (a); \ - typeof(b) _b = (b); \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ _a > _b ? _a : _b; \ }) #define SPA_CLAMP(v,low,high) \ ({ \ - typeof(v) _v = (v); \ - typeof(low) _low = (low); \ - typeof(high) _high = (high); \ + __typeof__(v) _v = (v); \ + __typeof__(low) _low = (low); \ + __typeof__(high) _high = (high); \ _v > _high ? _high : ( _v < _low ? _low : _v); \ }) -#define SPA_MEMBER(b,o,t) ((t*)((uint8_t*)(b) + (o))) +#define SPA_MEMBER(b,o,t) ((t*)((uint8_t*)(b) + (int)(o))) #define SPA_CONTAINER_OF(p,t,m) (t*)((uint8_t*)p - offsetof (t,m)) diff -Nru pipewire-0.2.3/spa/include/spa/utils/hook.h pipewire-0.2.5/spa/include/spa/utils/hook.h --- pipewire-0.2.3/spa/include/spa/utils/hook.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/spa/include/spa/utils/hook.h 2018-12-20 09:06:16.000000000 +0000 @@ -82,6 +82,18 @@ hook->removed(hook); } +#define spa_hook_list_call_simple(l,type,method,vers,...) \ +({ \ + struct spa_hook_list *list = l; \ + struct spa_hook *ci; \ + spa_list_for_each(ci, &list->list, link) { \ + const type *cb = ci->funcs; \ + if (cb && cb->version >= vers && cb->method) { \ + cb->method(ci->data, ## __VA_ARGS__); \ + } \ + } \ +}) + /** Call all hooks in a list, starting from the given one and optionally stopping * after calling the first non-NULL function, returns the number of methods * called */ diff -Nru pipewire-0.2.3/spa/meson.build pipewire-0.2.5/spa/meson.build --- pipewire-0.2.3/spa/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/spa/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -24,3 +24,9 @@ subdir('plugins') subdir('tools') subdir('tests') + +pkgconfig.generate(filebase : 'libspa-@0@'.format(spaversion), + name : 'libspa', + description : 'Simple Plugin API', + version : pipewire_version, + extra_cflags : '-D_REENTRANT') diff -Nru pipewire-0.2.3/spa/plugins/v4l2/v4l2-utils.c pipewire-0.2.5/spa/plugins/v4l2/v4l2-utils.c --- pipewire-0.2.3/spa/plugins/v4l2/v4l2-utils.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/spa/plugins/v4l2/v4l2-utils.c 2018-12-20 09:06:16.000000000 +0000 @@ -1194,7 +1194,8 @@ if (source->rmask & SPA_IO_ERR) { struct port *port = &this->out_ports[0]; spa_log_error(this->log, "v4l2 %p: error %d", this, source->rmask); - spa_loop_remove_source(port->data_loop, &port->source); + if (port->source.loop) + spa_loop_remove_source(port->data_loop, &port->source); return; } @@ -1470,7 +1471,8 @@ void *user_data) { struct port *port = user_data; - spa_loop_remove_source(port->data_loop, &port->source); + if (port->source.loop) + spa_loop_remove_source(port->data_loop, &port->source); return 0; } diff -Nru pipewire-0.2.3/src/daemon/daemon-config.c pipewire-0.2.5/src/daemon/daemon-config.c --- pipewire-0.2.3/src/daemon/daemon-config.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/daemon/daemon-config.c 2018-12-20 09:06:16.000000000 +0000 @@ -90,7 +90,7 @@ struct pw_command *cmd, *tmp; spa_list_for_each_safe(cmd, tmp, &config->commands, link) - pw_command_free(cmd); + pw_command_free(cmd); free(config); } diff -Nru pipewire-0.2.3/src/daemon/meson.build pipewire-0.2.5/src/daemon/meson.build --- pipewire-0.2.3/src/daemon/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/daemon/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -13,12 +13,11 @@ '-DG_LOG_DOMAIN=g_log_domain_pipewire', ] -conf_config = configuration_data() conf_install_dir = join_paths(get_option('sysconfdir'), 'pipewire') configure_file(input : 'pipewire.conf.in', output : 'pipewire.conf', - configuration : conf_config, + copy : true, install_dir : conf_install_dir) @@ -30,11 +29,6 @@ dependencies : [pipewire_dep], ) -if get_option('systemd') - systemd = dependency('systemd', required: false) - if systemd.found() - subdir('systemd') - else - warning('Systemd integration was enabled, but systemd is not available') - endif +if get_option('systemd') and systemd.found() + subdir('systemd') endif diff -Nru pipewire-0.2.3/src/examples/meson.build pipewire-0.2.5/src/examples/meson.build --- pipewire-0.2.3/src/examples/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/examples/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -1,7 +1,7 @@ executable('video-src', 'video-src.c', install: false, - dependencies : [pipewire_dep], + dependencies : [pipewire_dep, mathlib], ) executable('export-source', 'export-source.c', diff -Nru pipewire-0.2.3/src/examples/README pipewire-0.2.5/src/examples/README --- pipewire-0.2.3/src/examples/README 1970-01-01 00:00:00.000000000 +0000 +++ pipewire-0.2.5/src/examples/README 2018-12-20 09:06:16.000000000 +0000 @@ -0,0 +1,19 @@ +# Running the examples + +A pipewire daemon needs to be running for the examples to connect to: + +``` shell +./pw-uninstalled.sh +./build/src/daemon/pipewire +``` + +You can then run the examples in a second terminal, for example: + +``` shell +./pw-uninstalled.sh +./build/src/examples/local-v4l2 +``` + +This assumes the development package for `SDL2` was installed, check the meson +build definition in `src/examples` to find out the dependencies for each +example. diff -Nru pipewire-0.2.3/src/examples/video-play.c pipewire-0.2.5/src/examples/video-play.c --- pipewire-0.2.3/src/examples/video-play.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/examples/video-play.c 2018-12-20 09:06:16.000000000 +0000 @@ -36,6 +36,7 @@ struct spa_type_media_subtype media_subtype; struct spa_type_format_video format_video; struct spa_type_video_format video_format; + uint32_t meta_cursor; }; static inline void init_type(struct type *type, struct spa_type_map *map) @@ -44,6 +45,7 @@ spa_type_media_subtype_map(map, &type->media_subtype); spa_type_format_video_map(map, &type->format_video); spa_type_video_format_map(map, &type->video_format); + type->meta_cursor = spa_type_map_get_id(map, SPA_TYPE_META__Cursor); } #define WIDTH 640 @@ -58,6 +60,7 @@ SDL_Renderer *renderer; SDL_Window *window; SDL_Texture *texture; + SDL_Texture *cursor; struct pw_main_loop *loop; @@ -73,8 +76,12 @@ int32_t stride; int counter; + SDL_Rect rect; + SDL_Rect cursor_rect; }; +static Uint32 id_to_sdl_format(struct data *data, uint32_t id); + static void handle_events(struct data *data) { SDL_Event event; @@ -96,8 +103,11 @@ struct spa_buffer *b; void *sdata, *ddata; int sstride, dstride, ostride; + struct spa_meta_video_crop *mc; + struct spa_meta_cursor *mcs; uint32_t i; uint8_t *src, *dst; + bool render_cursor = false; handle_events(data); @@ -114,6 +124,53 @@ fprintf(stderr, "Couldn't lock texture: %s\n", SDL_GetError()); goto done; } + if ((mc = spa_buffer_find_meta(b, data->t->meta.VideoCrop))) { + data->rect.x = mc->x; + data->rect.y = mc->y; + data->rect.w = mc->width; + data->rect.h = mc->height; + } + if ((mcs = spa_buffer_find_meta(b, data->type.meta_cursor)) && + spa_meta_cursor_is_valid(mcs)) { + struct spa_meta_bitmap *mb; + void *cdata; + int cstride; + + data->cursor_rect.x = mcs->position.x; + data->cursor_rect.y = mcs->position.y; + + mb = SPA_MEMBER(mcs, mcs->bitmap_offset, struct spa_meta_bitmap); + data->cursor_rect.w = mb->size.width; + data->cursor_rect.h = mb->size.height; + + if (data->cursor == NULL) { + data->cursor = SDL_CreateTexture(data->renderer, + id_to_sdl_format(data, mb->format), + SDL_TEXTUREACCESS_STREAMING, + mb->size.width, mb->size.height); + SDL_SetTextureBlendMode(data->cursor, SDL_BLENDMODE_BLEND); + } + + + if (SDL_LockTexture(data->cursor, NULL, &cdata, &cstride) < 0) { + fprintf(stderr, "Couldn't lock cursor texture: %s\n", SDL_GetError()); + goto done; + } + + src = SPA_MEMBER(mb, mb->offset, uint8_t); + dst = cdata; + ostride = SPA_MIN(cstride, mb->stride); + + for (i = 0; i < mb->size.height; i++) { + memcpy(dst, src, ostride); + dst += cstride; + src += mb->stride; + } + SDL_UnlockTexture(data->cursor); + + render_cursor = true; + } + sstride = b->datas[0].chunk->stride; ostride = SPA_MIN(sstride, dstride); @@ -127,7 +184,10 @@ SDL_UnlockTexture(data->texture); SDL_RenderClear(data->renderer); - SDL_RenderCopy(data->renderer, data->texture, NULL, NULL); + SDL_RenderCopy(data->renderer, data->texture, &data->rect, NULL); + if (render_cursor) { + SDL_RenderCopy(data->renderer, data->cursor, NULL, &data->cursor_rect); + } SDL_RenderPresent(data->renderer); done: @@ -226,7 +286,7 @@ struct pw_type *t = data->t; uint8_t params_buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); - const struct spa_pod *params[2]; + const struct spa_pod *params[4]; Uint32 sdl_format; void *d; @@ -254,6 +314,11 @@ SDL_LockTexture(data->texture, NULL, &d, &data->stride); SDL_UnlockTexture(data->texture); + data->rect.x = 0; + data->rect.y = 0; + data->rect.w = data->format.size.width; + data->rect.h = data->format.size.height; + params[0] = spa_pod_builder_object(&b, t->param.idBuffers, t->param_buffers.Buffers, ":", t->param_buffers.size, "i", data->stride * data->format.size.height, @@ -266,8 +331,20 @@ t->param.idMeta, t->param_meta.Meta, ":", t->param_meta.type, "I", t->meta.Header, ":", t->param_meta.size, "i", sizeof(struct spa_meta_header)); + params[2] = spa_pod_builder_object(&b, + t->param.idMeta, t->param_meta.Meta, + ":", t->param_meta.type, "I", t->meta.VideoCrop, + ":", t->param_meta.size, "i", sizeof(struct spa_meta_video_crop)); +#define CURSOR_META_SIZE(w,h) (sizeof(struct spa_meta_cursor) + \ + sizeof(struct spa_meta_bitmap) + w * h * 4) + params[3] = spa_pod_builder_object(&b, + t->param.idMeta, t->param_meta.Meta, + ":", t->param_meta.type, "I", data->type.meta_cursor, + ":", t->param_meta.size, "iru", CURSOR_META_SIZE(64,64), + SPA_POD_PROP_MIN_MAX(CURSOR_META_SIZE(1,1), + CURSOR_META_SIZE(256,256))); - pw_stream_finish_format(stream, 0, params, 2); + pw_stream_finish_format(stream, 0, params, 4); } static const struct pw_stream_events stream_events = { @@ -449,5 +526,11 @@ pw_core_destroy(data.core); pw_main_loop_destroy(data.loop); + SDL_DestroyTexture(data.texture); + if (data.cursor) + SDL_DestroyTexture(data.cursor); + SDL_DestroyRenderer(data.renderer); + SDL_DestroyWindow(data.window); + return 0; } diff -Nru pipewire-0.2.3/src/examples/video-src.c pipewire-0.2.5/src/examples/video-src.c --- pipewire-0.2.3/src/examples/video-src.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/examples/video-src.c 2018-12-20 09:06:16.000000000 +0000 @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,7 @@ struct spa_type_media_subtype media_subtype; struct spa_type_format_video format_video; struct spa_type_video_format video_format; + uint32_t meta_cursor; }; static inline void init_type(struct type *type, struct spa_type_map *map) @@ -42,9 +44,18 @@ spa_type_media_subtype_map(map, &type->media_subtype); spa_type_format_video_map(map, &type->format_video); spa_type_video_format_map(map, &type->video_format); + type->meta_cursor = spa_type_map_get_id(map, SPA_TYPE_META__Cursor); } -#define BPP 3 +#define BPP 3 +#define WIDTH 320 +#define HEIGHT 200 +#define CROP 8 +#define CURSOR_WIDTH 64 +#define CURSOR_HEIGHT 64 +#define CURSOR_BPP 4 + +#define M_PI_M2 ( M_PI + M_PI ) struct data { struct type type; @@ -65,14 +76,36 @@ int counter; uint32_t seq; + double crop; + double accumulator; }; +static void draw_elipse(uint32_t *dst, int width, int height, uint32_t color) +{ + int i, j, r1, r2, r12, r22, r122; + + r1 = width/2; + r12 = r1 * r1; + r2 = height/2; + r22 = r2 * r2; + r122 = r12 * r22; + + for (i = -r2; i < r2; i++) { + for (j = -r1; j < r1; j++) { + dst[(i + r2)*width+(j+r1)] = + (i * i * r12 + j * j * r22 <= r122) ? color : 0x00000000; + } + } +} + static void on_timeout(void *userdata, uint64_t expirations) { struct data *data = userdata; int i, j; uint8_t *p; struct spa_meta_header *h; + struct spa_meta_video_crop *mc; + struct spa_meta_cursor *mcs; struct pw_buffer *buf; struct spa_buffer *b; @@ -97,6 +130,37 @@ h->seq = data->seq++; h->dts_offset = 0; } + if ((mc = spa_buffer_find_meta(b, data->t->meta.VideoCrop))) { + data->crop = (sin(data->accumulator) + 1.0) * 32.0; + mc->x = data->crop; + mc->y = data->crop; + mc->width = WIDTH - data->crop*2; + mc->height = HEIGHT - data->crop*2; + } + if ((mcs = spa_buffer_find_meta(b, data->type.meta_cursor))) { + struct spa_meta_bitmap *mb; + uint32_t *bitmap, color; + + mcs->id = 1; /* 0 is invalid cursor, anything else is valid */ + mcs->position.x = (sin(data->accumulator) + 1.0) * 160.0 + 80; + mcs->position.y = (cos(data->accumulator) + 1.0) * 100.0 + 50; + mcs->hotspot.x = 0; + mcs->hotspot.y = 0; + mcs->bitmap_offset = sizeof(struct spa_meta_cursor); + + mb = SPA_MEMBER(mcs, mcs->bitmap_offset, struct spa_meta_bitmap); + mb->format = data->type.video_format.ARGB; + mb->size.width = CURSOR_WIDTH; + mb->size.height = CURSOR_HEIGHT; + mb->stride = CURSOR_WIDTH * CURSOR_BPP; + mb->offset = sizeof(struct spa_meta_bitmap); + + bitmap = SPA_MEMBER(mb, mb->offset, uint32_t); + color = (cos(data->accumulator) + 1.0) * (1 << 23); + color |= 0xff000000; + + draw_elipse(bitmap, mb->size.width, mb->size.height, color); + } for (i = 0; i < data->format.size.height; i++) { for (j = 0; j < data->format.size.width * BPP; j++) { @@ -106,6 +170,10 @@ data->counter += 13; } + data->accumulator += M_PI_M2 / 50.0; + if (data->accumulator >= M_PI_M2) + data->accumulator -= M_PI_M2; + b->datas[0].chunk->size = b->datas[0].maxsize; done: @@ -148,7 +216,7 @@ struct pw_type *t = data->t; uint8_t params_buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(params_buffer, sizeof(params_buffer)); - const struct spa_pod *params[2]; + const struct spa_pod *params[4]; if (format == NULL) { pw_stream_finish_format(stream, 0, NULL, 0); @@ -170,8 +238,18 @@ t->param.idMeta, t->param_meta.Meta, ":", t->param_meta.type, "I", t->meta.Header, ":", t->param_meta.size, "i", sizeof(struct spa_meta_header)); + params[2] = spa_pod_builder_object(&b, + t->param.idMeta, t->param_meta.Meta, + ":", t->param_meta.type, "I", t->meta.VideoCrop, + ":", t->param_meta.size, "i", sizeof(struct spa_meta_video_crop)); +#define CURSOR_META_SIZE(w,h) (sizeof(struct spa_meta_cursor) + \ + sizeof(struct spa_meta_bitmap) + w * h * CURSOR_BPP) + params[3] = spa_pod_builder_object(&b, + t->param.idMeta, t->param_meta.Meta, + ":", t->param_meta.type, "I", data->type.meta_cursor, + ":", t->param_meta.size, "i", CURSOR_META_SIZE(CURSOR_WIDTH,CURSOR_HEIGHT)); - pw_stream_finish_format(stream, 0, params, 2); + pw_stream_finish_format(stream, 0, params, 4); } static const struct pw_stream_events stream_events = { @@ -214,7 +292,7 @@ "I", data->type.media_type.video, "I", data->type.media_subtype.raw, ":", data->type.format_video.format, "I", data->type.video_format.RGB, - ":", data->type.format_video.size, "Rru", &SPA_RECTANGLE(320, 240), + ":", data->type.format_video.size, "Rru", &SPA_RECTANGLE(WIDTH, HEIGHT), SPA_POD_PROP_MIN_MAX(&SPA_RECTANGLE(1, 1), &SPA_RECTANGLE(4096, 4096)), ":", data->type.format_video.framerate, "F", &SPA_FRACTION(25, 1)); diff -Nru pipewire-0.2.3/src/meson.build pipewire-0.2.5/src/meson.build --- pipewire-0.2.3/src/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -6,6 +6,6 @@ subdir('modules') subdir('examples') -if get_option('gstreamer') +if build_gst subdir('gst') endif diff -Nru pipewire-0.2.3/src/modules/meson.build pipewire-0.2.5/src/modules/meson.build --- pipewire-0.2.3/src/modules/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/modules/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -71,6 +71,12 @@ # dependencies : [glib_dep, gio_dep, mathlib, dl_lib, pipewire_dep], #) +pipewire_module_protocol_native_deps = [mathlib, dl_lib, pipewire_dep] + +if get_option('systemd') + pipewire_module_protocol_native_deps += systemd_dep +endif + pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native', [ 'module-protocol-native.c', 'module-protocol-native/local-socket.c', @@ -81,7 +87,7 @@ include_directories : [configinc, spa_inc], install : true, install_dir : modules_install_dir, - dependencies : [mathlib, dl_lib, pipewire_dep], + dependencies : pipewire_module_protocol_native_deps, ) pipewire_module_audio_dsp = shared_library('pipewire-module-audio-dsp', diff -Nru pipewire-0.2.3/src/modules/module-flatpak.c pipewire-0.2.5/src/modules/module-flatpak.c --- pipewire-0.2.3/src/modules/module-flatpak.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/modules/module-flatpak.c 2018-12-20 09:06:16.000000000 +0000 @@ -56,9 +56,12 @@ struct spa_list link; struct impl *impl; struct pw_client *client; + struct spa_hook client_listener; struct spa_list resources; struct spa_list async_pending; + bool checked; bool camera_allowed; + bool sandboxed; }; struct async_pending { @@ -128,6 +131,7 @@ spa_list_for_each_safe(p, tp, &cinfo->async_pending, link) free_pending(p); + spa_hook_remove(&cinfo->client_listener); spa_list_remove(&cinfo->link); free(cinfo); } @@ -279,6 +283,7 @@ cinfo->camera_allowed = false; pw_log_debug("camera access not allowed"); } + cinfo->checked = true; pw_core_for_each_global(cinfo->impl->core, set_global_permissions, cinfo); free_pending(p); @@ -380,6 +385,32 @@ return; } +static void client_info_changed(void *data, struct pw_client_info *info) +{ + struct client_info *cinfo = data; + const char *str; + + if (info->props == NULL) + return; + + if ((str = spa_dict_lookup(info->props, "pipewire.access")) == NULL) + return; + + if (strcmp(str, "flatpak") != 0) + return; + + if (cinfo->checked) + return; + + pw_log_debug("module %p: client %p set to flatpak access", cinfo->impl, cinfo->client); + do_portal_check(cinfo); +} + +static const struct pw_client_events client_events = { + PW_VERSION_CLIENT_EVENTS, + .info_changed = client_info_changed +}; + static void core_global_added(void *data, struct pw_global *global) { @@ -390,11 +421,21 @@ if (pw_global_get_type(global) == impl->type->client) { struct pw_client *client = pw_global_get_object(global); + /* clients are placed in a list and we do a portal check when needed */ + cinfo = calloc(1, sizeof(struct client_info)); + cinfo->impl = impl; + cinfo->client = client; + spa_list_init(&cinfo->async_pending); + pw_client_add_listener(client, &cinfo->client_listener, &client_events, cinfo); + + spa_list_append(&impl->client_list, &cinfo->link); + res = check_sandboxed(client); if (res == 0) { pw_log_debug("module %p: non sandboxed client %p", impl, client); return; } + cinfo->sandboxed = true; if (res < 0) { pw_log_warn("module %p: client %p sandbox check failed: %s", @@ -404,20 +445,13 @@ pw_log_debug("module %p: sandboxed client %p added", impl, client); } - /* sandboxed clients are placed in a list and we do a portal check */ - cinfo = calloc(1, sizeof(struct client_info)); - cinfo->impl = impl; - cinfo->client = client; - - spa_list_init(&cinfo->async_pending); - - spa_list_append(&impl->client_list, &cinfo->link); - do_portal_check(cinfo); } else { - spa_list_for_each(cinfo, &impl->client_list, link) - set_global_permissions(cinfo, global); + spa_list_for_each(cinfo, &impl->client_list, link) { + if (cinfo->sandboxed) + set_global_permissions(cinfo, global); + } } } diff -Nru pipewire-0.2.3/src/modules/module-protocol-dbus.c pipewire-0.2.5/src/modules/module-protocol-dbus.c --- pipewire-0.2.3/src/modules/module-protocol-dbus.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/modules/module-protocol-dbus.c 2018-12-20 09:06:16.000000000 +0000 @@ -211,6 +211,7 @@ if (this->sender) { spa_list_remove(&this->link); free(this->sender); + this->sender = NULL; } } diff -Nru pipewire-0.2.3/src/modules/module-protocol-native.c pipewire-0.2.5/src/modules/module-protocol-native.c --- pipewire-0.2.3/src/modules/module-protocol-native.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/modules/module-protocol-native.c 2018-12-20 09:06:16.000000000 +0000 @@ -32,6 +32,10 @@ #include "config.h" +#ifdef HAVE_SYSTEMD_DAEMON +#include +#endif + #include "pipewire/pipewire.h" #include "pipewire/private.h" #include "pipewire/log.h" @@ -88,6 +92,7 @@ int fd_lock; struct sockaddr_un addr; char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN]; + bool activated; struct pw_loop *loop; struct spa_source *source; @@ -386,8 +391,6 @@ static bool lock_socket(struct server *s) { - struct stat socket_stat; - snprintf(s->lock_addr, sizeof(s->lock_addr), "%s%s", s->addr.sun_path, LOCK_SUFFIX); s->fd_lock = open(s->lock_addr, O_CREAT | O_CLOEXEC, @@ -403,15 +406,6 @@ s->lock_addr); goto err_fd; } - - if (stat(s->addr.sun_path, &socket_stat) < 0) { - if (errno != ENOENT) { - pw_log_error("did not manage to stat file %s\n", s->addr.sun_path); - goto err_fd; - } - } else if (socket_stat.st_mode & S_IWUSR || socket_stat.st_mode & S_IWGRP) { - unlink(s->addr.sun_path); - } return true; err_fd: @@ -455,24 +449,43 @@ static bool add_socket(struct pw_protocol *protocol, struct server *s) { socklen_t size; - int fd; - - if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) - goto error; + int fd = -1; + bool activated = false; - size = offsetof(struct sockaddr_un, sun_path) + strlen(s->addr.sun_path); - if (bind(fd, (struct sockaddr *) &s->addr, size) < 0) { - pw_log_error("bind() failed with error: %m"); - goto error_close; +#ifdef HAVE_SYSTEMD_DAEMON + { + int i, n = sd_listen_fds(0); + for (i = 0; i < n; ++i) { + if (sd_is_socket_unix(SD_LISTEN_FDS_START + i, SOCK_STREAM, + 1, s->addr.sun_path, 0) > 0) { + fd = SD_LISTEN_FDS_START + i; + activated = true; + pw_log_info("Found socket activation socket for '%s'", s->addr.sun_path); + break; + } + } } +#endif - if (listen(fd, 128) < 0) { - pw_log_error("listen() failed with error: %m"); - goto error_close; + if (fd < 0) { + if ((fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) + goto error; + + size = offsetof(struct sockaddr_un, sun_path) + strlen(s->addr.sun_path); + if (bind(fd, (struct sockaddr *) &s->addr, size) < 0) { + pw_log_error("bind() failed with error: %m"); + goto error_close; + } + + if (listen(fd, 128) < 0) { + pw_log_error("listen() failed with error: %m"); + goto error_close; + } } s->loop = pw_core_get_main_loop(protocol->core); s->source = pw_loop_add_io(s->loop, fd, SPA_IO_IN, true, socket_data, s); + s->activated = activated; if (s->source == NULL) goto error_close; @@ -712,11 +725,11 @@ if (s->source) pw_loop_destroy_source(s->loop, s->source); - if (s->addr.sun_path[0]) + if (s->addr.sun_path[0] && !s->activated) unlink(s->addr.sun_path); if (s->lock_addr[0]) unlink(s->lock_addr); - if (s->fd_lock != 1) + if (s->fd_lock != -1) close(s->fd_lock); free(s); } @@ -915,7 +928,7 @@ val = pw_properties_get(pw_core_get_properties(core), PW_CORE_PROP_DAEMON); if (val && pw_properties_parse_bool(val)) { if (impl_add_server(this, core, properties) == NULL) - return -ENOMEM; + return -errno; } pw_module_add_listener(module, &d->module_listener, &module_events, d); diff -Nru pipewire-0.2.3/src/modules/module-rtkit.c pipewire-0.2.5/src/modules/module-rtkit.c --- pipewire-0.2.3/src/modules/module-rtkit.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/modules/module-rtkit.c 2018-12-20 09:06:16.000000000 +0000 @@ -95,6 +95,10 @@ #define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" #define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" +#ifndef RLIMIT_RTTIME +#define RLIMIT_RTTIME 15 +#endif + /** \cond */ struct pw_rtkit_bus { DBusConnection *bus; diff -Nru pipewire-0.2.3/src/pipewire/client.c pipewire-0.2.5/src/pipewire/client.c --- pipewire-0.2.3/src/pipewire/client.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/client.c 2018-12-20 09:06:16.000000000 +0000 @@ -196,7 +196,7 @@ pw_core_add_listener(core, &impl->core_listener, &core_events, impl); - this->info.props = this->properties ? &this->properties->dict : NULL; + this->info.props = &this->properties->dict; return this; } @@ -323,8 +323,7 @@ pw_map_clear(&client->types); pw_array_clear(&impl->permissions); - if (client->properties) - pw_properties_free(client->properties); + pw_properties_free(client->properties); free(impl); } @@ -356,21 +355,19 @@ int pw_client_update_properties(struct pw_client *client, const struct spa_dict *dict) { struct pw_resource *resource; + uint32_t i, changed = 0; - if (client->properties == NULL) { - if (dict) - client->properties = pw_properties_new_dict(dict); - } else { - uint32_t i; - - for (i = 0; i < dict->n_items; i++) - pw_properties_set(client->properties, - dict->items[i].key, dict->items[i].value); - } + for (i = 0; i < dict->n_items; i++) + changed += pw_properties_set(client->properties, + dict->items[i].key, dict->items[i].value); - client->info.change_mask |= PW_CLIENT_CHANGE_MASK_PROPS; - client->info.props = client->properties ? &client->properties->dict : NULL; + pw_log_debug("client %p: updated %d properties", client, changed); + + if (!changed) + return 0; + client->info.change_mask |= PW_CLIENT_CHANGE_MASK_PROPS; + client->info.props = &client->properties->dict; pw_client_events_info_changed(client, &client->info); spa_list_for_each(resource, &client->resource_list, link) @@ -378,7 +375,7 @@ client->info.change_mask = 0; - return 0; + return changed; } struct permissions_update { diff -Nru pipewire-0.2.3/src/pipewire/core.c pipewire-0.2.5/src/pipewire/core.c --- pipewire-0.2.3/src/pipewire/core.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/core.c 2018-12-20 09:06:16.000000000 +0000 @@ -391,12 +391,14 @@ spa_graph_init(&this->rt.graph); spa_graph_set_callbacks(&this->rt.graph, &spa_graph_impl_default, NULL); + this->dbus_iface = pw_get_spa_dbus(this->main_loop); + this->support[0] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, this->type.map); this->support[1] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__DataLoop, this->data_loop->loop); this->support[2] = SPA_SUPPORT_INIT(SPA_TYPE_LOOP__MainLoop, this->main_loop->loop); this->support[3] = SPA_SUPPORT_INIT(SPA_TYPE__LoopUtils, this->main_loop->utils); this->support[4] = SPA_SUPPORT_INIT(SPA_TYPE__Log, pw_log_get()); - this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE__DBus, pw_get_spa_dbus(this->main_loop)); + this->support[5] = SPA_SUPPORT_INIT(SPA_TYPE__DBus, this->dbus_iface); this->n_support = 6; pw_log_debug("%p", this->support[5].data); @@ -494,6 +496,8 @@ pw_data_loop_destroy(core->data_loop_impl); + pw_release_spa_dbus(core->dbus_iface); + pw_properties_free(core->properties); pw_map_clear(&core->globals); @@ -553,10 +557,15 @@ int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(core->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(core->properties, dict->items[i].key, dict->items[i].value); + + pw_log_debug("core %p: updated %d properties", core, changed); + + if (!changed) + return 0; core->info.change_mask = PW_CORE_CHANGE_MASK_PROPS; core->info.props = &core->properties->dict; @@ -568,7 +577,7 @@ core->info.change_mask = 0; - return 0; + return changed; } int pw_core_for_each_global(struct pw_core *core, diff -Nru pipewire-0.2.3/src/pipewire/factory.c pipewire-0.2.5/src/pipewire/factory.c --- pipewire-0.2.3/src/pipewire/factory.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/factory.c 2018-12-20 09:06:16.000000000 +0000 @@ -67,8 +67,7 @@ spa_hook_remove(&factory->global_listener); pw_global_destroy(factory->global); } - if (factory->info.name) - free((char *)factory->info.name); + free((char *)factory->info.name); if (factory->properties) pw_properties_free(factory->properties); diff -Nru pipewire-0.2.3/src/pipewire/introspect.c pipewire-0.2.5/src/pipewire/introspect.c --- pipewire-0.2.3/src/pipewire/introspect.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/introspect.c 2018-12-20 09:06:16.000000000 +0000 @@ -130,23 +130,19 @@ info->change_mask = update->change_mask; if (update->change_mask & PW_CORE_CHANGE_MASK_USER_NAME) { - if (info->user_name) - free((void *) info->user_name); + free((void *) info->user_name); info->user_name = update->user_name ? strdup(update->user_name) : NULL; } if (update->change_mask & PW_CORE_CHANGE_MASK_HOST_NAME) { - if (info->host_name) - free((void *) info->host_name); + free((void *) info->host_name); info->host_name = update->host_name ? strdup(update->host_name) : NULL; } if (update->change_mask & PW_CORE_CHANGE_MASK_VERSION) { - if (info->version) - free((void *) info->version); + free((void *) info->version); info->version = update->version ? strdup(update->version) : NULL; } if (update->change_mask & PW_CORE_CHANGE_MASK_NAME) { - if (info->name) - free((void *) info->name); + free((void *) info->name); info->name = update->name ? strdup(update->name) : NULL; } if (update->change_mask & PW_CORE_CHANGE_MASK_COOKIE) @@ -161,14 +157,10 @@ void pw_core_info_free(struct pw_core_info *info) { - if (info->user_name) - free((void *) info->user_name); - if (info->host_name) - free((void *) info->host_name); - if (info->version) - free((void *) info->version); - if (info->name) - free((void *) info->name); + free((void *) info->user_name); + free((void *) info->host_name); + free((void *) info->version); + free((void *) info->name); if (info->props) pw_spa_dict_destroy(info->props); free(info); @@ -190,8 +182,7 @@ info->change_mask = update->change_mask; if (update->change_mask & PW_NODE_CHANGE_MASK_NAME) { - if (info->name) - free((void *) info->name); + free((void *) info->name); info->name = update->name ? strdup(update->name) : NULL; } if (update->change_mask & PW_NODE_CHANGE_MASK_INPUT_PORTS) { @@ -205,8 +196,7 @@ if (update->change_mask & PW_NODE_CHANGE_MASK_STATE) { info->state = update->state; - if (info->error) - free((void *) info->error); + free((void *) info->error); info->error = update->error ? strdup(update->error) : NULL; } if (update->change_mask & PW_NODE_CHANGE_MASK_PROPS) { @@ -220,10 +210,8 @@ void pw_node_info_free(struct pw_node_info *info) { - if (info->name) - free((void *) info->name); - if (info->error) - free((void *) info->error); + free((void *) info->name); + free((void *) info->error); if (info->props) pw_spa_dict_destroy(info->props); free(info); @@ -245,8 +233,7 @@ info->change_mask = update->change_mask; if (update->change_mask & PW_PORT_CHANGE_MASK_NAME) { - if (info->name) - free((void *) info->name); + free((void *) info->name); info->name = update->name ? strdup(update->name) : NULL; } if (update->change_mask & PW_PORT_CHANGE_MASK_PROPS) { @@ -260,8 +247,7 @@ void pw_port_info_free(struct pw_port_info *info) { - if (info->name) - free((void *) info->name); + free((void *) info->name); if (info->props) pw_spa_dict_destroy(info->props); free(info); @@ -279,8 +265,7 @@ return NULL; } info->id = update->id; - if (info->name) - free((void *) info->name); + free((void *) info->name); info->name = update->name ? strdup(update->name) : NULL; info->type = update->type; info->version = update->version; @@ -296,8 +281,7 @@ void pw_factory_info_free(struct pw_factory_info *info) { - if (info->name) - free((void *) info->name); + free((void *) info->name); if (info->props) pw_spa_dict_destroy(info->props); free(info); @@ -318,18 +302,15 @@ info->change_mask = update->change_mask; if (update->change_mask & PW_MODULE_CHANGE_MASK_NAME) { - if (info->name) - free((void *) info->name); + free((void *) info->name); info->name = update->name ? strdup(update->name) : NULL; } if (update->change_mask & PW_MODULE_CHANGE_MASK_FILENAME) { - if (info->filename) - free((void *) info->filename); + free((void *) info->filename); info->filename = update->filename ? strdup(update->filename) : NULL; } if (update->change_mask & PW_MODULE_CHANGE_MASK_ARGS) { - if (info->args) - free((void *) info->args); + free((void *) info->args); info->args = update->args ? strdup(update->args) : NULL; } if (update->change_mask & PW_MODULE_CHANGE_MASK_PROPS) { @@ -342,12 +323,9 @@ void pw_module_info_free(struct pw_module_info *info) { - if (info->name) - free((void *) info->name); - if (info->filename) - free((void *) info->filename); - if (info->args) - free((void *) info->args); + free((void *) info->name); + free((void *) info->filename); + free((void *) info->args); if (info->props) pw_spa_dict_destroy(info->props); free(info); @@ -406,8 +384,7 @@ info->input_port_id = update->input_port_id; } if (update->change_mask & PW_LINK_CHANGE_MASK_FORMAT) { - if (info->format) - free(info->format); + free(info->format); info->format = pw_spa_pod_copy(update->format); } return info; @@ -415,7 +392,6 @@ void pw_link_info_free(struct pw_link_info *info) { - if (info->format) - free(info->format); + free(info->format); free(info); } diff -Nru pipewire-0.2.3/src/pipewire/link.c pipewire-0.2.5/src/pipewire/link.c --- pipewire-0.2.3/src/pipewire/link.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/link.c 2018-12-20 09:06:16.000000000 +0000 @@ -215,9 +215,7 @@ pw_work_queue_add(impl->work, input->node, res2, complete_ready, input); } - - if (this->info.format) - free(this->info.format); + free(this->info.format); this->info.format = format; if (changed) { @@ -235,8 +233,7 @@ error: pw_link_update_state(this, PW_LINK_STATE_ERROR, error); - if (format) - free(format); + free(format); return res; } @@ -1288,6 +1285,9 @@ if (link->registered) spa_list_remove(&link->link); + if (link->output->node->clock == link->input->node->clock) + link->input->node->clock = NULL; + input_remove(link, link->input); output_remove(link, link->output); @@ -1308,9 +1308,7 @@ if (link->properties) pw_properties_free(link->properties); - if (link->info.format) - free(link->info.format); - + free(link->info.format); free(impl); } diff -Nru pipewire-0.2.3/src/pipewire/meson.build pipewire-0.2.5/src/pipewire/meson.build --- pipewire-0.2.3/src/pipewire/meson.build 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/meson.build 2018-12-20 09:06:16.000000000 +0000 @@ -74,7 +74,8 @@ '-D_POSIX_C_SOURCE', ] -libpipewire = shared_library('pipewire-@0@'.format(apiversion), pipewire_sources, +libpipewire_name = 'pipewire-@0@'.format(apiversion) +libpipewire = shared_library(libpipewire_name, pipewire_sources, version : libversion, soversion : soversion, c_args : libpipewire_c_args, @@ -87,3 +88,11 @@ include_directories : [pipewire_inc, configinc, spa_inc], dependencies : [pthread_lib], ) + +pkgconfig.generate(filebase : 'lib@0@'.format(libpipewire_name), + libraries : [libpipewire], + name : 'libpipewire', + description : 'PipeWire Interface', + version : pipewire_version, + extra_cflags : '-D_REENTRANT', + variables : ['moduledir=${libdir}/@0@'.format(libpipewire_name)]) diff -Nru pipewire-0.2.3/src/pipewire/module.c pipewire-0.2.5/src/pipewire/module.c --- pipewire-0.2.3/src/pipewire/module.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/module.c 2018-12-20 09:06:16.000000000 +0000 @@ -299,12 +299,9 @@ spa_list_for_each_safe(resource, tmp, &module->resource_list, link) pw_resource_destroy(resource); - if (module->info.name) - free((char *) module->info.name); - if (module->info.filename) - free((char *) module->info.filename); - if (module->info.args) - free((char *) module->info.args); + free((char *) module->info.name); + free((char *) module->info.filename); + free((char *) module->info.args); dlclose(impl->hnd); free(impl); diff -Nru pipewire-0.2.3/src/pipewire/node.c pipewire-0.2.5/src/pipewire/node.c --- pipewire-0.2.3/src/pipewire/node.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/node.c 2018-12-20 09:06:16.000000000 +0000 @@ -477,15 +477,19 @@ int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(node->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(node->properties, dict->items[i].key, dict->items[i].value); + + pw_log_debug("node %p: updated %d properties", node, changed); + + if (!changed) + return 0; check_properties(node); node->info.props = &node->properties->dict; - node->info.change_mask |= PW_NODE_CHANGE_MASK_PROPS; pw_node_events_info_changed(node, &node->info); @@ -494,7 +498,7 @@ node->info.change_mask = 0; - return 0; + return changed; } static void node_done(void *data, int seq, int res) @@ -650,8 +654,7 @@ pw_map_clear(&node->input_port_map); pw_map_clear(&node->output_port_map); - if (node->properties) - pw_properties_free(node->properties); + pw_properties_free(node->properties); clear_info(node); @@ -918,8 +921,7 @@ pw_log_debug("node %p: update state from %s -> %s", node, pw_node_state_as_string(old), pw_node_state_as_string(state)); - if (node->info.error) - free((char*)node->info.error); + free((char*)node->info.error); node->info.error = error; node->info.state = state; diff -Nru pipewire-0.2.3/src/pipewire/pipewire.c pipewire-0.2.5/src/pipewire/pipewire.c --- pipewire-0.2.3/src/pipewire/pipewire.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/pipewire.c 2018-12-20 09:06:16.000000000 +0000 @@ -44,6 +44,19 @@ uint32_t n_support; } support_info; +struct interface { + struct spa_list link; + struct spa_handle *handle; + uint32_t type; + void *iface; +}; + +struct registry { + struct spa_list interfaces; +}; + +static struct registry global_registry; + static bool open_support(const char *path, const char *lib, @@ -92,7 +105,7 @@ return NULL; } -static void * +static struct interface * load_interface(struct support_info *info, const char *factory_name, const char *type) @@ -101,7 +114,8 @@ struct spa_handle *handle; uint32_t type_id; const struct spa_handle_factory *factory; - void *iface; + struct interface *iface; + void *ptr; struct spa_type_map *map = NULL; factory = get_factory(info, factory_name); @@ -118,12 +132,22 @@ map = pw_get_support_interface(SPA_TYPE__TypeMap); type_id = map ? spa_type_map_get_id(map, type) : 0; - if ((res = spa_handle_get_interface(handle, type_id, &iface)) < 0) { + if ((res = spa_handle_get_interface(handle, type_id, &ptr)) < 0) { fprintf(stderr, "can't get %s interface %d\n", type, res); goto interface_failed; } + + if ((iface = calloc(1, sizeof(struct interface))) == NULL) + goto alloc_failed; + + iface->handle = handle; + iface->type = type_id; + iface->iface = ptr; + spa_list_append(&global_registry.interfaces, &iface->link); + return iface; + alloc_failed: interface_failed: spa_handle_clear(handle); init_failed: @@ -175,6 +199,7 @@ { struct support_info dbus_support_info; const char *str; + struct interface *iface; dbus_support_info.n_support = support_info.n_support; memcpy(dbus_support_info.support, support_info.support, @@ -186,11 +211,36 @@ if ((str = getenv("SPA_PLUGIN_DIR")) == NULL) str = PLUGINDIR; - if (open_support(str, "support/libspa-dbus", &dbus_support_info)) - return load_interface(&dbus_support_info, "dbus", SPA_TYPE__DBus); - + if (open_support(str, "support/libspa-dbus", &dbus_support_info)) { + iface = load_interface(&dbus_support_info, "dbus", SPA_TYPE__DBus); + if (iface != NULL) + return iface->iface; + } return NULL; } +static struct interface *find_interface(void *iface) +{ + struct interface *i; + spa_list_for_each(i, &global_registry.interfaces, link) { + if (i->iface == iface) + return i; + } + return NULL; +} + +int pw_release_spa_dbus(void *dbus) +{ + struct interface *iface; + + if ((iface = find_interface(dbus)) == NULL) + return -ENOENT; + + spa_list_remove(&iface->link); + spa_handle_clear(iface->handle); + free(iface->handle); + free(iface); + return 0; +} /** Initialize PipeWire * @@ -207,7 +257,7 @@ void pw_init(int *argc, char **argv[]) { const char *str; - void *iface; + struct interface *iface; struct support_info *info = &support_info; if ((str = getenv("PIPEWIRE_DEBUG"))) @@ -219,15 +269,17 @@ if (support_info.n_support > 0) return; + spa_list_init(&global_registry.interfaces); + if (open_support(str, "support/libspa-support", info)) { iface = load_interface(info, "mapper", SPA_TYPE__TypeMap); if (iface != NULL) - info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface); + info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__TypeMap, iface->iface); iface = load_interface(info, "logger", SPA_TYPE__Log); if (iface != NULL) { - info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface); - pw_log_set(iface); + info->support[info->n_support++] = SPA_SUPPORT_INIT(SPA_TYPE__Log, iface->iface); + pw_log_set(iface->iface); } } pw_log_info("version %s", pw_get_library_version()); diff -Nru pipewire-0.2.3/src/pipewire/pipewire.h pipewire-0.2.5/src/pipewire/pipewire.h --- pipewire-0.2.3/src/pipewire/pipewire.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/pipewire.h 2018-12-20 09:06:16.000000000 +0000 @@ -134,6 +134,7 @@ pw_get_support_interface(const char *type); void *pw_get_spa_dbus(struct pw_loop *loop); +int pw_release_spa_dbus(void *dbus); const struct spa_handle_factory * pw_get_support_factory(const char *factory_name); diff -Nru pipewire-0.2.3/src/pipewire/port.c pipewire-0.2.5/src/pipewire/port.c --- pipewire-0.2.3/src/pipewire/port.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/port.c 2018-12-20 09:06:16.000000000 +0000 @@ -247,13 +247,17 @@ int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict) { struct pw_resource *resource; - uint32_t i; + uint32_t i, changed = 0; for (i = 0; i < dict->n_items; i++) - pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value); + changed += pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value); - port->info.props = &port->properties->dict; + pw_log_debug("port %p: updated %d properties", port, changed); + + if (!changed) + return 0; + port->info.props = &port->properties->dict; port->info.change_mask |= PW_PORT_CHANGE_MASK_PROPS; pw_port_events_info_changed(port, &port->info); @@ -262,7 +266,7 @@ port->info.change_mask = 0; - return 0; + return changed; } struct pw_node *pw_port_get_node(struct pw_port *port) @@ -560,8 +564,7 @@ pw_map_clear(&port->mix_port_map); - if (port->properties) - pw_properties_free(port->properties); + pw_properties_free(port->properties); free(port); } diff -Nru pipewire-0.2.3/src/pipewire/private.h pipewire-0.2.5/src/pipewire/private.h --- pipewire-0.2.3/src/pipewire/private.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/private.h 2018-12-20 09:06:16.000000000 +0000 @@ -183,6 +183,8 @@ struct pw_loop *data_loop; /**< data loop for data passing */ struct pw_data_loop *data_loop_impl; + void *dbus_iface; + struct spa_support support[16]; /**< support for spa plugins */ uint32_t n_support; /**< number of support items */ diff -Nru pipewire-0.2.3/src/pipewire/properties.c pipewire-0.2.5/src/pipewire/properties.c --- pipewire-0.2.3/src/pipewire/properties.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/properties.c 2018-12-20 09:06:16.000000000 +0000 @@ -98,7 +98,8 @@ va_start(varargs, key); while (key != NULL) { value = va_arg(varargs, char *); - add_func(&impl->this, strdup(key), value ? strdup(value) : NULL); + if (value) + add_func(&impl->this, strdup(key), strdup(value)); key = va_arg(varargs, char *); } va_end(varargs); @@ -123,9 +124,9 @@ return NULL; for (i = 0; i < dict->n_items; i++) { - if (dict->items[i].key != NULL) + if (dict->items[i].key != NULL && dict->items[i].value != NULL) add_func(&impl->this, strdup(dict->items[i].key), - dict->items[i].value ? strdup(dict->items[i].value) : NULL); + strdup(dict->items[i].value)); } return &impl->this; @@ -186,7 +187,7 @@ return NULL; pw_array_for_each(item, &impl->items) - add_func(copy, strdup(item->key), item->value ? strdup(item->value) : NULL); + add_func(copy, strdup(item->key), strdup(item->value)); return copy; } @@ -241,37 +242,45 @@ struct spa_dict_item *item; pw_array_for_each(item, &impl->items) - clear_item(item); + clear_item(item); pw_array_clear(&impl->items); free(impl); } -static int do_replace(struct pw_properties *properties, char *key, char *value) +static int do_replace(struct pw_properties *properties, const char *key, char *value, bool copy) { struct properties *impl = SPA_CONTAINER_OF(properties, struct properties, this); int index = find_index(properties, key); if (index == -1) { - add_func(properties, key, value); + if (value == NULL) + return 0; + add_func(properties, strdup(key), copy ? strdup(value) : value); } else { struct spa_dict_item *item = pw_array_get_unchecked(&impl->items, index, struct spa_dict_item); - clear_item(item); + if (value && strcmp(item->value, value) == 0) { + if (!copy) + free(value); + return 0; + } + if (value == NULL) { struct spa_dict_item *other = pw_array_get_unchecked(&impl->items, pw_array_get_len(&impl->items, struct spa_dict_item) - 1, struct spa_dict_item); + clear_item(item); item->key = other->key; item->value = other->value; impl->items.size -= sizeof(struct spa_dict_item); } else { - item->key = key; - item->value = value; + free((char *) item->value); + item->value = copy ? strdup(value) : value; } } - return 0; + return 1; } /** Set a property value @@ -279,6 +288,9 @@ * \param properties the properties to change * \param key a key * \param value a value or NULL to remove the key + * \return 1 if the properties were changed. 0 if nothing was changed because + * the property already existed with the same value or because the key to remove + * did not exist. * * Set the property in \a properties with \a key to \a value. Any previous value * of \a key will be overwritten. When \a value is NULL, the key will be @@ -288,7 +300,16 @@ */ int pw_properties_set(struct pw_properties *properties, const char *key, const char *value) { - return do_replace(properties, strdup(key), value ? strdup(value) : NULL); + return do_replace(properties, key, (char*)value, true); +} + +int +pw_properties_setva(struct pw_properties *properties, + const char *key, const char *format, va_list args) +{ + char *value; + vasprintf(&value, format, args); + return do_replace(properties, key, value, false); } /** Set a property value by format @@ -297,6 +318,8 @@ * \param key a key * \param format a value * \param ... extra arguments + * \return 1 if the properties were changed. 0 if nothing was changed because + * the property already existed with the same value. * * Set the property in \a properties with \a key to the value in printf style \a format * Any previous value of \a key will be overwritten. @@ -305,14 +328,14 @@ */ int pw_properties_setf(struct pw_properties *properties, const char *key, const char *format, ...) { + int res; va_list varargs; - char *value; va_start(varargs, format); - vasprintf(&value, format, varargs); + res = pw_properties_setva(properties, key, format, varargs); va_end(varargs); - return do_replace(properties, strdup(key), value); + return res; } /** Get a property diff -Nru pipewire-0.2.3/src/pipewire/remote.c pipewire-0.2.5/src/pipewire/remote.c --- pipewire-0.2.3/src/pipewire/remote.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/remote.c 2018-12-20 09:06:16.000000000 +0000 @@ -124,8 +124,7 @@ enum pw_remote_state old = remote->state; if (old != state) { - if (remote->error) - free(remote->error); + free(remote->error); if (fmt) { va_list varargs; @@ -180,11 +179,10 @@ struct pw_remote *this = data; struct pw_proxy *proxy; - proxy = pw_map_lookup(&this->objects, id); - if (proxy) { - pw_log_debug("remote %p: object remove %u", this, id); + pw_log_debug("remote %p: object remove %u", this, id); + if ((proxy = pw_map_lookup(&this->objects, id)) != NULL) pw_proxy_destroy(proxy); - } + pw_map_remove(&this->objects, id); } @@ -306,8 +304,9 @@ spa_list_remove(&remote->link); - if (remote->properties) - pw_properties_free(remote->properties); + pw_log_debug("remote %p: free", remote); + pw_properties_free(remote->properties); + free(remote->error); free(impl); } @@ -442,18 +441,18 @@ spa_list_for_each_safe(stream, s2, &remote->stream_list, link) pw_stream_disconnect(stream); - pw_protocol_client_disconnect (remote->conn); - spa_list_for_each_safe(proxy, t2, &remote->proxy_list, link) pw_proxy_destroy(proxy); remote->core_proxy = NULL; + pw_protocol_client_disconnect (remote->conn); + pw_map_clear(&remote->objects); pw_map_clear(&remote->types); remote->n_types = 0; if (remote->info) { - pw_core_info_free (remote->info); + pw_core_info_free(remote->info); remote->info = NULL; } pw_remote_update_state(remote, PW_REMOTE_STATE_UNCONNECTED, NULL); diff -Nru pipewire-0.2.3/src/pipewire/stream.c pipewire-0.2.5/src/pipewire/stream.c --- pipewire-0.2.3/src/pipewire/stream.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/stream.c 2018-12-20 09:06:16.000000000 +0000 @@ -229,7 +229,7 @@ struct buffer *b; int i, j; - pw_log_debug("stream %p: clear buffers", stream); + pw_log_debug("stream %p: clear %d buffers", stream, impl->n_buffers); for (i = 0; i < impl->n_buffers; i++) { b = &impl->buffers[i]; @@ -304,8 +304,7 @@ enum pw_stream_state old = stream->state; bool res = old != state; if (res) { - if (stream->error) - free(stream->error); + free(stream->error); stream->error = error; pw_log_debug("stream %p: update state from %s -> %s (%s)", stream, @@ -534,32 +533,16 @@ pw_stream_events_destroy(stream); - if (impl->node_proxy) - spa_hook_remove(&impl->proxy_listener); - pw_stream_disconnect(stream); spa_list_remove(&stream->link); - set_init_params(stream, 0, NULL); - set_params(stream, 0, NULL); - - if (impl->format) - free(impl->format); - - if (stream->error) - free(stream->error); - - clear_buffers(stream); - - clear_mems(stream); pw_array_clear(&impl->mem_ids); - if (stream->properties) - pw_properties_free(stream->properties); + free(stream->error); + free(stream->name); - if (stream->name) - free(stream->name); + pw_properties_free(stream->properties); free(impl); } @@ -821,7 +804,7 @@ if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { pw_log_warn("got error"); - unhandle_socket(stream); + do_remove_sources(stream->remote->core->data_loop->loop, false, 0, NULL, 0, impl); return; } @@ -960,8 +943,7 @@ pw_log_debug("stream %p: format changed %d", stream, seq); - if (impl->format) - free(impl->format); + free(impl->format); if (spa_pod_is_object_type(param, t->spa_format)) { impl->format = pw_spa_pod_copy(param); @@ -1241,6 +1223,21 @@ impl->node_proxy = NULL; spa_hook_remove(&impl->proxy_listener); + set_init_params(this, 0, NULL); + set_params(this, 0, NULL); + + clear_buffers(this); + clear_mems(this); + + if (impl->format) { + free(impl->format); + impl->format = NULL; + } + if (impl->trans) { + pw_client_node_transport_destroy(impl->trans); + impl->trans = NULL; + } + stream_set_state(this, PW_STREAM_STATE_UNCONNECTED, NULL); } @@ -1268,8 +1265,6 @@ stream_set_state(stream, PW_STREAM_STATE_CONNECTING, NULL); - if (stream->properties == NULL) - stream->properties = pw_properties_new(NULL, NULL); if (port_path) pw_properties_set(stream->properties, PW_NODE_PROP_TARGET_NODE, port_path); if (flags & PW_STREAM_FLAG_AUTOCONNECT) @@ -1332,17 +1327,15 @@ { struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); + pw_log_debug("stream %p: disconnect", stream); + impl->disconnecting = true; unhandle_socket(stream); if (impl->node_proxy) { pw_client_node_proxy_destroy(impl->node_proxy); - impl->node_proxy = NULL; - } - if (impl->trans) { - pw_client_node_transport_destroy(impl->trans); - impl->trans = NULL; + pw_proxy_destroy((struct pw_proxy *)impl->node_proxy); } return 0; } diff -Nru pipewire-0.2.3/src/pipewire/thread-loop.c pipewire-0.2.5/src/pipewire/thread-loop.c --- pipewire-0.2.3/src/pipewire/thread-loop.c 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/thread-loop.c 2018-12-20 09:06:16.000000000 +0000 @@ -18,6 +18,7 @@ */ #include +#include #include #include "pipewire.h" @@ -96,28 +97,45 @@ this = calloc(1, sizeof(struct pw_thread_loop)); if (this == NULL) - return NULL; + goto error1; pw_log_debug("thread-loop %p: new", this); this->loop = loop; this->name = name ? strdup(name) : NULL; - pw_loop_add_hook(loop, &this->hook, &impl_hooks, this); - spa_hook_list_init(&this->listener_list); pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(&this->lock, &attr); + if ((errno = pthread_mutex_init(&this->lock, &attr)) != 0) + goto error2; + pthread_condattr_init(&cattr); pthread_condattr_setclock(&cattr, CLOCK_REALTIME); - pthread_cond_init(&this->cond, &cattr); - pthread_cond_init(&this->accept_cond, &cattr); + if ((errno = pthread_cond_init(&this->cond, &cattr)) != 0) + goto error3; + if ((errno = pthread_cond_init(&this->accept_cond, &cattr)) != 0) + goto error4; - this->event = pw_loop_add_event(this->loop, do_stop, this); + if ((this->event = pw_loop_add_event(this->loop, do_stop, this)) == NULL) + goto error5; + + pw_loop_add_hook(loop, &this->hook, &impl_hooks, this); return this; + + error5: + pthread_cond_destroy(&this->accept_cond); + error4: + pthread_cond_destroy(&this->cond); + error3: + pthread_mutex_destroy(&this->lock); + error2: + free(this->name); + free(this); + error1: + return NULL; } /** Destroy a threaded loop \memberof pw_thread_loop */ @@ -127,8 +145,7 @@ pw_thread_loop_stop(loop); - if (loop->name) - free(loop->name); + free(loop->name); pthread_mutex_destroy(&loop->lock); pthread_cond_destroy(&loop->cond); pthread_cond_destroy(&loop->accept_cond); diff -Nru pipewire-0.2.3/src/pipewire/utils.h pipewire-0.2.5/src/pipewire/utils.h --- pipewire-0.2.3/src/pipewire/utils.h 2018-08-30 10:45:18.000000000 +0000 +++ pipewire-0.2.5/src/pipewire/utils.h 2018-12-20 09:06:16.000000000 +0000 @@ -51,9 +51,17 @@ static inline struct spa_pod * pw_spa_pod_copy(const struct spa_pod *pod) { - return pod ? - (struct spa_pod *) memcpy(malloc(SPA_POD_SIZE(pod)), pod, SPA_POD_SIZE(pod)) - : NULL; + size_t size; + struct spa_pod *c; + + if (pod == NULL) + return NULL; + + size = SPA_POD_SIZE(pod); + if ((c = malloc(size)) == NULL) + return NULL; + + return (struct spa_pod *) memcpy(c, pod, size); } #ifdef __cplusplus