Initial commit

This commit is contained in:
George Kiagiadakis
2019-04-03 18:31:05 +03:00
commit 43c44fb7cf
9 changed files with 493 additions and 0 deletions

14
meson.build Normal file
View File

@@ -0,0 +1,14 @@
project('wireplumber', ['c'],
version : '0.0.1',
license : 'LGPL',
meson_version : '>= 0.47.0',
default_options : [
'warning_level=1',
'buildtype=debugoptimized'
]
)
glib_dep = dependency('gobject-2.0')
pipewire_dep = dependency('libpipewire-0.3')
subdir('src')

191
src/core.c Normal file
View File

@@ -0,0 +1,191 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "wireplumber-core"
#include "core.h"
#include "loop-source.h"
#include "utils.h"
#include <pipewire/pipewire.h>
#include <glib-unix.h>
struct _WpCore
{
GObject parent;
GMainLoop *loop;
GSource *source;
struct pw_core *core;
struct pw_remote *remote;
struct spa_hook remote_listener;
struct pw_core_proxy *core_proxy;
struct spa_hook core_proxy_listener;
struct pw_registry_proxy *registry_proxy;
struct spa_hook registry_proxy_listener;
GError *exit_error;
};
G_DEFINE_TYPE (WpCore, wp_core, G_TYPE_OBJECT);
static const struct pw_registry_proxy_events registry_events = {
PW_VERSION_REGISTRY_PROXY_EVENTS,
//.global = registry_global,
//.global_remove = registry_global_remove,
};
static const struct pw_core_proxy_events core_events = {
PW_VERSION_CORE_EVENTS,
//.done = core_done
};
static void on_state_changed (void * data,
enum pw_remote_state old_state,
enum pw_remote_state new_state,
const char * error)
{
WpCore *self = WP_CORE (data);
g_debug ("remote state changed, old:%s new:%s",
pw_remote_state_as_string (old_state),
pw_remote_state_as_string (new_state));
switch (new_state) {
case PW_REMOTE_STATE_CONNECTED:
self->core_proxy = pw_remote_get_core_proxy (self->remote);
pw_core_proxy_add_listener (self->core_proxy, &self->core_proxy_listener,
&core_events, self);
self->registry_proxy = pw_core_proxy_get_registry (self->core_proxy,
PW_TYPE_INTERFACE_Registry, PW_VERSION_REGISTRY, 0);
pw_registry_proxy_add_listener (self->registry_proxy,
&self->registry_proxy_listener, &registry_events, self);
break;
case PW_REMOTE_STATE_UNCONNECTED:
self->core_proxy = NULL;
self->registry_proxy = NULL;
wp_core_exit (self, WP_DOMAIN_CORE, WP_CODE_DISCONNECTED, "disconnected");
break;
case PW_REMOTE_STATE_ERROR:
wp_core_exit (self, WP_DOMAIN_CORE, WP_CODE_REMOTE_ERROR,
"pipewire remote error: %s", error);
break;
default:
break;
}
}
static const struct pw_remote_events remote_events = {
PW_VERSION_REMOTE_EVENTS,
.state_changed = on_state_changed,
};
static void
wp_core_init (WpCore * self)
{
self->loop = g_main_loop_new (NULL, FALSE);
self->source = wp_loop_source_new ();
g_source_attach (self->source, NULL);
self->core = pw_core_new (wp_loop_source_get_loop (self->source), NULL, 0);
self->remote = pw_remote_new (self->core, NULL, 0);
pw_remote_add_listener (self->remote, &self->remote_listener, &remote_events,
self);
}
static void
wp_core_finalize (GObject * obj)
{
WpCore *self = WP_CORE (obj);
spa_hook_remove (&self->remote_listener);
pw_remote_destroy (self->remote);
pw_core_destroy (self->core);
g_source_destroy (self->source);
g_source_unref (self->source);
g_main_loop_unref (self->loop);
g_warn_if_fail (self->exit_error == NULL);
g_clear_error (&self->exit_error);
}
static void
wp_core_class_init (WpCoreClass * klass)
{
GObjectClass * object_class = (GObjectClass *) klass;
object_class->finalize = wp_core_finalize;
}
WpCore *
wp_core_get_instance (void)
{
static WpCore *instance = NULL;
if (G_UNLIKELY (!instance)) {
instance = g_object_new (wp_core_get_type (), NULL);
}
return instance;
}
static gboolean
signal_handler (gpointer data)
{
WpCore *self = WP_CORE (data);
wp_core_exit (self, WP_DOMAIN_CORE, WP_CODE_INTERRUPTED,
"interrupted by signal");
return G_SOURCE_CONTINUE;
}
void
wp_core_run (WpCore * self, GError ** error)
{
g_unix_signal_add (SIGINT, signal_handler, self);
g_unix_signal_add (SIGTERM, signal_handler, self);
g_unix_signal_add (SIGHUP, signal_handler, self);
g_idle_add ((GSourceFunc) pw_remote_connect, self->remote);
g_main_loop_run (self->loop);
if (self->exit_error) {
g_propagate_error (error, self->exit_error);
self->exit_error = NULL;
}
}
void
wp_core_exit (WpCore * self, GQuark domain, gint code,
const gchar *format, ...)
{
va_list args;
va_start (args, format);
self->exit_error = g_error_new_valist (domain, code, format, args);
va_end (args);
g_main_loop_quit (self->loop);
}

37
src/core.h Normal file
View File

@@ -0,0 +1,37 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __WIREPLUMBER_CORE_H__
#define __WIREPLUMBER_CORE_H__
#include <glib-object.h>
G_BEGIN_DECLS
G_DECLARE_FINAL_TYPE (WpCore, wp_core, WP, CORE, GObject);
WpCore * wp_core_get_instance (void);
void wp_core_run (WpCore * self, GError ** error);
void wp_core_exit (WpCore * self, GQuark domain, gint code,
const gchar *format, ...);
G_END_DECLS
#endif

79
src/loop-source.c Normal file
View File

@@ -0,0 +1,79 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "wireplumber-loop"
#include "loop-source.h"
#define WP_LOOP_SOURCE(x) ((WpLoopSource *) x)
typedef struct _WpLoopSource WpLoopSource;
struct _WpLoopSource
{
GSource parent;
struct pw_loop *loop;
};
static gboolean
wp_loop_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
{
int result;
pw_loop_enter (WP_LOOP_SOURCE(s)->loop);
result = pw_loop_iterate (WP_LOOP_SOURCE(s)->loop, 0);
pw_loop_leave (WP_LOOP_SOURCE(s)->loop);
if (G_UNLIKELY (result < 0))
g_warning ("pw_loop_iterate failed: %s", spa_strerror (result));
return G_SOURCE_CONTINUE;
}
static void
wp_loop_source_finalize (GSource * s)
{
pw_loop_destroy (WP_LOOP_SOURCE(s)->loop);
}
static GSourceFuncs source_funcs = {
NULL,
NULL,
wp_loop_source_dispatch,
wp_loop_source_finalize
};
GSource *
wp_loop_source_new (void)
{
GSource *s = g_source_new (&source_funcs, sizeof (WpLoopSource));
WP_LOOP_SOURCE(s)->loop = pw_loop_new (NULL);
g_source_add_unix_fd (s,
pw_loop_get_fd (WP_LOOP_SOURCE(s)->loop),
G_IO_IN | G_IO_ERR | G_IO_HUP);
return (GSource *) s;
}
struct pw_loop *
wp_loop_source_get_loop (GSource *s)
{
return WP_LOOP_SOURCE(s)->loop;
}

39
src/loop-source.h Normal file
View File

@@ -0,0 +1,39 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __WIREPLUMBER_LOOP_SOURCE_H__
#define __WIREPLUMBER_LOOP_SOURCE_H__
#include <glib.h>
#include <pipewire/pipewire.h>
G_BEGIN_DECLS
/*
* A GSource that integrates a pw_loop with GMainLoop.
* Use g_source_ref/unref to manage lifetime.
* The pw_loop is owned by the GSource.
*/
GSource * wp_loop_source_new (void);
struct pw_loop * wp_loop_source_get_loop (GSource * s);
G_END_DECLS
#endif

58
src/main.c Normal file
View File

@@ -0,0 +1,58 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#define G_LOG_DOMAIN "wireplumber"
#include "core.h"
#include "utils.h"
#include <pipewire/pipewire.h>
static GOptionEntry entries[] =
{
{ NULL }
};
gint
main (gint argc, gchar **argv)
{
g_autoptr (GOptionContext) context = NULL;
g_autoptr (GError) error = NULL;
g_autoptr (WpCore) core = NULL;
gint ret = 0;
context = g_option_context_new ("- PipeWire Session/Policy Manager");
g_option_context_add_main_entries (context, entries, NULL);
if (!g_option_context_parse (context, &argc, &argv, &error))
goto out;
pw_init (NULL, NULL);
core = wp_core_get_instance ();
wp_core_run (core, &error);
out:
if (error) {
ret = error->code;
if (error->domain != WP_DOMAIN_CORE)
ret += 100;
g_message ("exit code %d; %s", ret, error->message);
}
return ret;
}

13
src/meson.build Normal file
View File

@@ -0,0 +1,13 @@
wp_sources = [
'core.c',
'loop-source.c',
'main.c',
'utils.c',
]
executable('wireplumber',
wp_sources,
c_args : [ '-D_GNU_SOURCE', '-DG_LOG_USE_STRUCTURED' ],
install: true,
dependencies : [glib_dep, pipewire_dep],
)

22
src/utils.c Normal file
View File

@@ -0,0 +1,22 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include "utils.h"
G_DEFINE_QUARK (wireplumber-core, wp_domain_core);

40
src/utils.h Normal file
View File

@@ -0,0 +1,40 @@
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __WIREPLUMBER_UTILS_H__
#define __WIREPLUMBER_UTILS_H__
#include <glib.h>
G_BEGIN_DECLS
GQuark wp_domain_core_quark (void);
#define WP_DOMAIN_CORE (wp_domain_core_quark ())
enum WpCoreCode {
WP_CODE_DISCONNECTED = 0,
WP_CODE_INTERRUPTED,
WP_CODE_OPERATION_FAILED,
WP_CODE_INVALID_ARGUMENT,
WP_CODE_REMOTE_ERROR,
};
G_END_DECLS
#endif