Initial commit
This commit is contained in:
14
meson.build
Normal file
14
meson.build
Normal 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
191
src/core.c
Normal 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, ®istry_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
37
src/core.h
Normal 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
79
src/loop-source.c
Normal 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
39
src/loop-source.h
Normal 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
58
src/main.c
Normal 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
13
src/meson.build
Normal 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
22
src/utils.c
Normal 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
40
src/utils.h
Normal 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
|
Reference in New Issue
Block a user