Skip to content
Snippets Groups Projects
Commit 43c44fb7 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

Initial commit

parents
No related branches found
No related tags found
No related merge requests found
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')
/* 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);
}
/* 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
/* 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;
}
/* 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
/* 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;
}
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],
)
/* 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);
/* 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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment