From c6afbf8942831f90f10dbd3de341d89a84a59d62 Mon Sep 17 00:00:00 2001 From: Martijn Braam Date: Fri, 10 Jul 2020 15:38:33 +0200 Subject: [PATCH] temp/wys-pinephone: new aport (MR 1406) --- ...-daemon-to-only-switch-card-profiles.patch | 2846 +++++++++++++++++ temp/wys-pinephone/APKBUILD | 48 + temp/wys-pinephone/wys.desktop | 11 + 3 files changed, 2905 insertions(+) create mode 100644 temp/wys-pinephone/0001-Simplify-daemon-to-only-switch-card-profiles.patch create mode 100644 temp/wys-pinephone/APKBUILD create mode 100644 temp/wys-pinephone/wys.desktop diff --git a/temp/wys-pinephone/0001-Simplify-daemon-to-only-switch-card-profiles.patch b/temp/wys-pinephone/0001-Simplify-daemon-to-only-switch-card-profiles.patch new file mode 100644 index 000000000..f981e146f --- /dev/null +++ b/temp/wys-pinephone/0001-Simplify-daemon-to-only-switch-card-profiles.patch @@ -0,0 +1,2846 @@ +From f66610d26395de15e3928cf4284573ca9cfabf26 Mon Sep 17 00:00:00 2001 +From: Arnaud Ferraris +Date: Fri, 6 Mar 2020 02:01:52 +0100 +Subject: [PATCH] Simplify daemon to only switch card profiles + +As a PoC for the PinePhone, we want to only switch card profiles: +- when a call starts, use the "Voice Call" profile: audio is output on +the earpiece, and the internal microphone is unmuted +- when a call is terminated, switch back to the default "HiFi" profile, +using the main speaker + +This should fully cover the most basic use-case. Headset will not work, +and there is also no support for a "silent mode", but this is enough to +demonstrate voice calls for the PinePhone. +--- + machine-check/blacklist | 1 - + machine-conf/Purism Librem 5 devkit/codec | 1 - + machine-conf/Purism Librem 5 devkit/modem | 1 - + machine-conf/Purism Librem 5/codec | 1 - + machine-conf/Purism Librem 5/modem | 1 - + meson.build | 16 - + src/main.c | 363 ++--- + src/meson.build | 10 - + src/wys-audio.c | 1259 ----------------- + src/wys-audio.h | 47 - + src/wys-direction.c | 40 - + src/wys-direction.h | 42 - + src/wys-modem.c | 138 +- + .../libmachine-check/mchk-machine-check.c | 328 ----- + .../libmachine-check/mchk-machine-check.h | 38 - + subprojects/libmachine-check/meson.build | 81 -- + 18 files changed, 146 insertions(+), 2228 deletions(-) + delete mode 100644 machine-check/blacklist + delete mode 100644 machine-conf/Purism Librem 5 devkit/codec + delete mode 100644 machine-conf/Purism Librem 5 devkit/modem + delete mode 100644 machine-conf/Purism Librem 5/codec + delete mode 100644 machine-conf/Purism Librem 5/modem + delete mode 100644 src/wys-audio.c + delete mode 100644 src/wys-audio.h + delete mode 100644 src/wys-direction.c + delete mode 100644 src/wys-direction.h + delete mode 100644 subprojects/libmachine-check/mchk-machine-check.c + delete mode 100644 subprojects/libmachine-check/mchk-machine-check.h + delete mode 100644 subprojects/libmachine-check/meson.build + +--- a/machine-check/blacklist ++++ /dev/null +@@ -1 +0,0 @@ +-Purism Librem 5 devkit +diff --git a/machine-conf/Purism Librem 5 devkit/codec b/machine-conf/Purism Librem 5 devkit/codec +deleted file mode 100644 +index 7af7303..0000000 +--- a/machine-conf/Purism Librem 5 devkit/codec ++++ /dev/null +@@ -1 +0,0 @@ +-sgtl5000 +diff --git a/machine-conf/Purism Librem 5 devkit/modem b/machine-conf/Purism Librem 5 devkit/modem +deleted file mode 100644 +index b10552d..0000000 +--- a/machine-conf/Purism Librem 5 devkit/modem ++++ /dev/null +@@ -1 +0,0 @@ +-SIMCom SIM7100 +diff --git a/machine-conf/Purism Librem 5/codec b/machine-conf/Purism Librem 5/codec +deleted file mode 100644 +index 6d39251..0000000 +--- a/machine-conf/Purism Librem 5/codec ++++ /dev/null +@@ -1 +0,0 @@ +-wm8962 +diff --git a/machine-conf/Purism Librem 5/modem b/machine-conf/Purism Librem 5/modem +deleted file mode 100644 +index d9b0f2a..0000000 +--- a/machine-conf/Purism Librem 5/modem ++++ /dev/null +@@ -1 +0,0 @@ +-MODEM +diff --git a/meson.build b/meson.build +index 5938cec..7516208 100644 +--- a/meson.build ++++ b/meson.build +@@ -33,11 +33,6 @@ project ( + ], + ) + +- +-libmchk_proj = subproject('libmachine-check') +-libmchk_dep = libmchk_proj.get_variable('libmachine_check_dep') +- +- + app_name = meson.project_name() + + prefix = get_option('prefix') +@@ -63,14 +58,3 @@ config_data.set_quoted('DATADIR', full_datadir) + config_data.set_quoted('SYSCONFDIR', full_sysconfdir) + + subdir('src') +- +-install_subdir ( +- 'machine-conf', +- install_dir : join_paths(datadir, app_name) +-) +- +-install_subdir ( +- 'machine-check', +- install_dir : join_paths(datadir, 'machine-check', app_name), +- strip_directory : true +-) +diff --git a/src/main.c b/src/main.c +index 587a5f3..4631a33 100644 +--- a/src/main.c ++++ b/src/main.c +@@ -23,10 +23,8 @@ + */ + + #include "wys-modem.h" +-#include "wys-audio.h" + #include "util.h" + #include "config.h" +-#include "mchk-machine-check.h" + + #include + #include +@@ -50,8 +48,6 @@ static GMainLoop *main_loop = NULL; + + struct wys_data + { +- /** PulseAudio interface */ +- WysAudio *audio; + /** ID for the D-Bus watch */ + guint watch_id; + /** ModemManager object proxy */ +@@ -59,51 +55,112 @@ struct wys_data + /** Map of D-Bus object paths to WysModems */ + GHashTable *modems; + /** How many modems have audio, in each direction */ +- guint audio_count[2]; ++ guint audio_count; + }; + ++static gboolean ++ugly_system (const gchar *cmd) ++{ ++ gchar *out = NULL, *err = NULL; ++ gint status; ++ GError *error = NULL; ++ gboolean ok; ++ ++ g_debug ("Executing command `%s'", cmd); ++ ++ ok = g_spawn_command_line_sync ++ (cmd, &out, &err, &status, &error); ++ ++ if (!ok) ++ { ++ g_warning ("Error spawning command `%s': %s'", ++ cmd, error->message); ++ g_error_free (error); ++ return FALSE; ++ } ++ ++ ok = g_spawn_check_exit_status (status, &error); ++ if (ok) ++ { ++ g_debug ("Command `%s' executed successfully" ++ "; stdout: `%s'; stderr: `%s'", ++ cmd, out, err); ++ } ++ else ++ { ++ g_warning ("Command `%s' failed: %s" ++ "; stdout: `%s'; stderr: `%s'", ++ cmd, error->message, out, err); ++ g_error_free (error); ++ } ++ ++ g_free (out); ++ g_free (err); ++ ++ return ok; ++} ++ ++#define UGLY_CARD "alsa_card.platform-sound" ++ ++static gboolean ++ugly_set_card_profile (const gchar *card, ++ const gchar *profile) ++{ ++ g_autofree gchar *cmd = NULL; ++ ++ cmd = g_strdup_printf ("pactl set-card-profile '%s' '%s'", card, profile); ++ ++ return ugly_system (cmd); ++} ++ ++static gboolean ++ugly_set_voice_call (void) ++{ ++ return ugly_set_card_profile (UGLY_CARD, "Voice Call"); ++} ++ ++static gboolean ++ugly_set_hifi (void) ++{ ++ return ugly_set_card_profile (UGLY_CARD, "HiFi"); ++} + + static void + update_audio_count (struct wys_data *data, +- WysDirection direction, + gint delta) + { +- const guint old_count = data->audio_count[direction]; ++ const guint old_count = data->audio_count; + +- g_assert (delta >= 0 || data->audio_count[direction] > 0); ++ g_assert (delta >= 0 || data->audio_count > 0); + +- data->audio_count[direction] += delta; ++ data->audio_count += delta; + +- if (data->audio_count[direction] > 0 && old_count == 0) ++ if (data->audio_count > 0 && old_count == 0) + { +- g_debug ("Audio %s now present", +- wys_direction_get_description (direction)); +- wys_audio_ensure_loopback (data->audio, direction); ++ g_message ("Audio now present"); ++ ugly_set_voice_call (); + } +- else if (data->audio_count[direction] == 0 && old_count > 0) ++ else if (data->audio_count == 0 && old_count > 0) + { +- g_debug ("Audio %s now absent", +- wys_direction_get_description (direction)); +- wys_audio_ensure_no_loopback (data->audio, direction); ++ g_message ("Audio now absent"); ++ ugly_set_hifi (); + } + } + + + static void + audio_present_cb (struct wys_data *data, +- WysDirection direction, + WysModem *modem) + { +- update_audio_count (data, direction, +1); ++ update_audio_count (data, +1); + } + + + static void + audio_absent_cb (struct wys_data *data, +- WysDirection direction, + WysModem *modem) + { +- update_audio_count (data, direction, -1); ++ update_audio_count (data, -1); + } + + +@@ -123,7 +180,7 @@ add_modem (struct wys_data *data, + return; + } + +- g_debug ("Adding new voice-capable modem `%s'", path); ++ g_message ("Adding new voice-capable modem `%s'", path); + + g_assert (MM_IS_OBJECT (object)); + voice = mm_object_get_modem_voice (MM_OBJECT (object)); +@@ -153,7 +210,7 @@ interface_added_cb (struct wys_data *data, + + info = g_dbus_interface_get_info (interface); + +- g_debug ("ModemManager interface `%s' found on object `%s'", ++ g_message ("ModemManager interface `%s' found on object `%s'", + info->name, + g_dbus_object_get_object_path (object)); + +@@ -184,7 +241,7 @@ interface_removed_cb (struct wys_data *data, + path = g_dbus_object_get_object_path (object); + info = g_dbus_interface_get_info (interface); + +- g_debug ("ModemManager interface `%s' removed on object `%s'", ++ g_message ("ModemManager interface `%s' removed on object `%s'", + info->name, path); + + if (g_strcmp0 (info->name, MM_DBUS_INTERFACE_MODEM_VOICE) == 0) +@@ -229,7 +286,7 @@ void + object_added_cb (struct wys_data *data, + GDBusObject *object) + { +- g_debug ("ModemManager object `%s' added", ++ g_message ("ModemManager object `%s' added", + g_dbus_object_get_object_path (object)); + + add_mm_object (data, object); +@@ -243,7 +300,7 @@ object_removed_cb (struct wys_data *data, + const gchar *path; + + path = g_dbus_object_get_object_path (object); +- g_debug ("ModemManager object `%s' removed", path); ++ g_message ("ModemManager object `%s' removed", path); + + remove_modem_object (data, path, object); + } +@@ -286,7 +343,7 @@ mm_appeared_cb (GDBusConnection *connection, + const gchar *name_owner, + struct wys_data *data) + { +- g_debug ("ModemManager appeared on D-Bus"); ++ g_message ("ModemManager appeared on D-Bus"); + + mm_manager_new (connection, + G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE, +@@ -310,18 +367,14 @@ mm_vanished_cb (GDBusConnection *connection, + const gchar *name, + struct wys_data *data) + { +- g_debug ("ModemManager vanished from D-Bus"); ++ g_message ("ModemManager vanished from D-Bus"); + clear_dbus (data); + } + + + static void +-set_up (struct wys_data *data, +- const gchar *codec, +- const gchar *modem) ++set_up (struct wys_data *data) + { +- data->audio = wys_audio_new (codec, modem); +- + data->modems = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, g_object_unref); + +@@ -333,7 +386,7 @@ set_up (struct wys_data *data, + (GBusNameVanishedCallback)mm_vanished_cb, + data, NULL); + +- g_debug ("Watching for ModemManager"); ++ g_message ("Watching for ModemManager"); + } + + +@@ -343,23 +396,19 @@ tear_down (struct wys_data *data) + clear_dbus (data); + g_bus_unwatch_name (data->watch_id); + g_hash_table_unref (data->modems); +- g_object_unref (G_OBJECT (data->audio)); + } + + + static void +-run (const gchar *codec, +- const gchar *modem) ++run (void) + { + struct wys_data data; + + memset (&data, 0, sizeof (struct wys_data)); +- set_up (&data, codec, modem); ++ set_up (&data); + + main_loop = g_main_loop_new (NULL, FALSE); + +- printf (APPLICATION_NAME " started with codec `%s', modem `%s'\n", +- codec, modem); + g_main_loop_run (main_loop); + + g_main_loop_unref (main_loop); +@@ -368,33 +417,6 @@ run (const gchar *codec, + tear_down (&data); + } + +- +-static void +-check_machine (const gchar *machine) +-{ +- gboolean ok, passed; +- GError *error = NULL; +- +- ok = mchk_check_machine (APP_DATA_NAME, +- machine, +- &passed, +- &error); +- if (!ok) +- { +- g_warning ("Error checking machine name against" +- " whitelist/blacklist, continuing anyway"); +- g_error_free (error); +- } +- else if (!passed) +- { +- g_message ("Machine name `%s' did not pass" +- " whitelist/blacklist check, exiting", +- machine); +- exit (EXIT_SUCCESS); +- } +-} +- +- + static void + terminate (int signal) + { +@@ -429,221 +451,18 @@ setup_signals () + #undef try_setup + } + +- +-/** This function will close @fd */ +-static gchar * +-read_machine_conf_file (const gchar *filename, +- int fd) +-{ +- GInputStream *unix_stream; +- GDataInputStream *data_stream; +- gboolean try_again; +- gchar *line; +- GError *error = NULL; +- +- g_debug ("Reading machine configuration file `%s'", filename); +- +- unix_stream = g_unix_input_stream_new (fd, TRUE); +- g_assert (unix_stream != NULL); +- +- data_stream = g_data_input_stream_new (unix_stream); +- g_assert (data_stream != NULL); +- g_object_unref (unix_stream); +- +- do +- { +- try_again = FALSE; +- +- line = g_data_input_stream_read_line_utf8 +- (data_stream, NULL, NULL, &error); +- +- if (error) +- { +- g_warning ("Error reading from machine" +- " configuration file `%s': %s", +- filename, error->message); +- g_error_free (error); +- } +- else if (line) +- { +- g_strstrip (line); +- +- // Skip comments and empty lines +- if (line[0] == '#' || line[0] == '\0') +- { +- g_free (line); +- try_again = TRUE; +- } +- } +- } +- while (try_again); +- +- g_object_unref (data_stream); +- return line; +-} +- +- +-static gchar * +-dir_machine_conf (const gchar *dir, +- const gchar *machine, +- const gchar *key) +-{ +- gchar *filename; +- int fd; +- gchar *value = NULL; +- +- filename = g_build_filename (dir, APP_DATA_NAME, +- "machine-conf", +- machine, key, NULL); +- +- g_debug ("Trying machine configuration file `%s'", +- filename); +- +- fd = g_open (filename, O_RDONLY, 0); +- if (fd == -1) +- { +- if (errno != ENOENT) +- { +- // The error isn't that the file doesn't exist +- g_warning ("Error opening machine" +- " configuration file `%s': %s", +- filename, g_strerror (errno)); +- } +- } +- else +- { +- value = read_machine_conf_file (filename, fd); +- } +- +- g_free (filename); +- return value; +-} +- +- +-static gchar * +-machine_conf (const gchar *machine, +- const gchar *key) +-{ +- gchar *value = NULL; +- const gchar * const *dirs, * const *dir; +- +- +-#define try_dir(d) \ +- value = dir_machine_conf (d, machine, key); \ +- if (value) \ +- { \ +- return value; \ +- } +- +- +- try_dir (g_get_user_config_dir ()); +- +- dirs = g_get_system_config_dirs (); +- for (dir = dirs; *dir; ++dir) +- { +- try_dir (*dir); +- } +- +- try_dir (SYSCONFDIR); +- try_dir (DATADIR); +- +- dirs = g_get_system_data_dirs (); +- for (dir = dirs; *dir; ++dir) +- { +- try_dir (*dir); +- } +- +-#undef try_dir +- +- return NULL; +-} +- +- +-static void +-ensure_alsa_card (const gchar *machine, +- const gchar *var, +- const gchar *key, +- gchar **name) +-{ +- const gchar *env; +- +- if (*name) +- { +- return; +- } +- +- env = g_getenv (var); +- if (env) +- { +- *name = g_strdup (env); +- return; +- } +- +- if (machine) +- { +- *name = machine_conf (machine, key); +- if (*name) +- { +- return; +- } +- } +- +- g_warning ("No %s specified, refusing to run", key); +- exit (EXIT_SUCCESS); +-} +- +- + int + main (int argc, char **argv) + { + GError *error = NULL; + GOptionContext *context; + gboolean ok; +- g_autofree gchar *codec = NULL; +- g_autofree gchar *modem = NULL; +- g_autofree gchar *machine = NULL; +- +- GOptionEntry options[] = +- { +- { "codec", 'c', 0, G_OPTION_ARG_STRING, &codec, "Name of the codec's ALSA card", "NAME" }, +- { "modem", 'm', 0, G_OPTION_ARG_STRING, &modem, "Name of the modem's ALSA card", "NAME" }, +- { NULL } +- }; + + setlocale(LC_ALL, ""); + +- machine = mchk_read_machine (NULL); +- if (machine) +- { +- check_machine (machine); +- } +- else +- { +- g_warning ("Could not read machine name, continuing without machine check"); +- } +- +- +- context = g_option_context_new ("- set up PulseAudio loopback for phone call audio"); +- g_option_context_add_main_entries (context, options, NULL); +- ok = g_option_context_parse (context, &argc, &argv, &error); +- if (!ok) +- { +- g_print ("Error parsing options: %s\n", error->message); +- } +- +- +- if (machine) +- { +- /* Convert any directory separator characters to "_" */ +- g_strdelimit (machine, G_DIR_SEPARATOR_S, '_'); +- } +- +- ensure_alsa_card (machine, "WYS_CODEC", "codec", &codec); +- ensure_alsa_card (machine, "WYS_MODEM", "modem", &modem); +- + setup_signals (); + +- run (codec, modem); ++ run (); + + return 0; + } +diff --git a/src/meson.build b/src/meson.build +index 7b99235..a8a30d7 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -22,13 +22,10 @@ + gnome = import('gnome') + + wys_deps = [ +- libmchk_dep, + dependency('gobject-2.0'), + dependency('gio-unix-2.0'), + dependency('ModemManager'), + dependency('mm-glib'), +- dependency('libpulse'), +- dependency('libpulse-mainloop-glib'), + ] + + config_h = configure_file ( +@@ -36,20 +33,13 @@ config_h = configure_file ( + configuration: config_data + ) + +-wys_enum_headers = files(['wys-direction.h']) +-wys_enum_sources = gnome.mkenums_simple('enum-types', +- sources : wys_enum_headers) +- + executable ( + 'wys', + config_h, +- wys_enum_sources, + [ + 'main.c', + 'util.h', 'util.c', +- 'wys-direction.h', 'wys-direction.c', + 'wys-modem.h', 'wys-modem.c', +- 'wys-audio.h', 'wys-audio.c', + ], + dependencies : wys_deps, + include_directories : include_directories('..'), +diff --git a/src/wys-audio.c b/src/wys-audio.c +deleted file mode 100644 +index 4a3c7fd..0000000 +--- a/src/wys-audio.c ++++ /dev/null +@@ -1,1259 +0,0 @@ +-/* +- * copyright (C) 2018, 2019 Purism SPC +- * +- * This file is part of Wys. +- * +- * Wys is free software: you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Wys 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 General Public +- * License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Wys. If not, see . +- * +- * Author: Bob Ham +- * +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- */ +- +-#include "wys-audio.h" +-#include "util.h" +- +-#include +-#include +-#include +-#include +- +- +-struct _WysAudio +-{ +- GObject parent_instance; +- +- gchar *codec; +- gchar *modem; +- pa_glib_mainloop *loop; +- pa_context *ctx; +-}; +- +-G_DEFINE_TYPE (WysAudio, wys_audio, G_TYPE_OBJECT); +- +- +-enum { +- PROP_0, +- PROP_CODEC, +- PROP_MODEM, +- PROP_LAST_PROP, +-}; +-static GParamSpec *props[PROP_LAST_PROP]; +- +- +-static void +-proplist_set (pa_proplist *props, +- const char *key, +- const char *value) +-{ +- int err = pa_proplist_sets (props, key, value); +- if (err != 0) +- { +- wys_error ("Error setting PulseAudio property list" +- " property: %s", pa_strerror (err)); +- } +-} +- +- +-static void +-context_notify_cb (pa_context *audio, gboolean *ready) +-{ +- pa_context_state_t audio_state; +- +- audio_state = pa_context_get_state (audio); +- switch (audio_state) +- { +- case PA_CONTEXT_UNCONNECTED: +- case PA_CONTEXT_CONNECTING: +- case PA_CONTEXT_AUTHORIZING: +- case PA_CONTEXT_SETTING_NAME: +- *ready = FALSE; +- break; +- case PA_CONTEXT_FAILED: +- wys_error ("Error in PulseAudio context: %s", +- pa_strerror (pa_context_errno (audio))); +- break; +- case PA_CONTEXT_TERMINATED: +- case PA_CONTEXT_READY: +- *ready = TRUE; +- break; +- } +-} +- +- +-static void +-set_up_audio_context (WysAudio *self) +-{ +- pa_proplist *props; +- int err; +- static gboolean ready = FALSE; +- +- /* Meta data */ +- props = pa_proplist_new (); +- g_assert (props != NULL); +- +- proplist_set (props, PA_PROP_APPLICATION_NAME, APPLICATION_NAME); +- proplist_set (props, PA_PROP_APPLICATION_ID, APPLICATION_ID); +- +- self->loop = pa_glib_mainloop_new (NULL); +- if (!self->loop) +- { +- wys_error ("Error creating PulseAudio main loop"); +- } +- +- self->ctx = pa_context_new (pa_glib_mainloop_get_api (self->loop), +- APPLICATION_NAME); +- if (!self->ctx) +- { +- wys_error ("Error creating PulseAudio context"); +- } +- +- pa_context_set_state_callback (self->ctx, +- (pa_context_notify_cb_t)context_notify_cb, +- &ready); +- err = pa_context_connect(self->ctx, NULL, PA_CONTEXT_NOFAIL, 0); +- if (err < 0) +- { +- wys_error ("Error connecting PulseAudio context: %s", +- pa_strerror (err)); +- } +- +- while (!ready) +- { +- g_main_context_iteration (NULL, TRUE); +- } +- +- pa_context_set_state_callback (self->ctx, NULL, NULL); +-} +- +- +-static void +-set_property (GObject *object, +- guint property_id, +- const GValue *value, +- GParamSpec *pspec) +-{ +- WysAudio *self = WYS_AUDIO (object); +- +- switch (property_id) { +- case PROP_CODEC: +- self->codec = g_value_dup_string (value); +- break; +- +- case PROP_MODEM: +- self->modem = g_value_dup_string (value); +- break; +- +- default: +- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +- break; +- } +-} +- +- +-static void +-constructed (GObject *object) +-{ +- GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT); +- WysAudio *self = WYS_AUDIO (object); +- +- set_up_audio_context (self); +- +- parent_class->constructed (object); +-} +- +- +-static void +-dispose (GObject *object) +-{ +- GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT); +- WysAudio *self = WYS_AUDIO (object); +- +- if (self->ctx) +- { +- pa_context_disconnect (self->ctx); +- pa_context_unref (self->ctx); +- self->ctx = NULL; +- +- pa_glib_mainloop_free (self->loop); +- self->loop = NULL; +- } +- +- +- parent_class->dispose (object); +-} +- +- +-static void +-finalize (GObject *object) +-{ +- GObjectClass *parent_class = g_type_class_peek (G_TYPE_OBJECT); +- WysAudio *self = WYS_AUDIO (object); +- +- g_free (self->modem); +- g_free (self->codec); +- +- parent_class->finalize (object); +-} +- +- +-static void +-wys_audio_class_init (WysAudioClass *klass) +-{ +- GObjectClass *object_class = G_OBJECT_CLASS (klass); +- +- object_class->set_property = set_property; +- object_class->constructed = constructed; +- object_class->dispose = dispose; +- object_class->finalize = finalize; +- +- props[PROP_CODEC] = +- g_param_spec_string ("codec", +- _("Codec"), +- _("The ALSA card name for the codec"), +- "sgtl5000", +- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); +- +- props[PROP_MODEM] = +- g_param_spec_string ("modem", +- _("Modem"), +- _("The ALSA card name for the modem"), +- "SIMcom SIM7100", +- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY); +- +- g_object_class_install_properties (object_class, PROP_LAST_PROP, props); +-} +- +- +-static void +-wys_audio_init (WysAudio *self) +-{ +-} +- +- +-WysAudio * +-wys_audio_new (const gchar *codec, +- const gchar *modem) +-{ +- return g_object_new (WYS_TYPE_AUDIO, +- "codec", codec, +- "modem", modem, +- NULL); +-} +- +- +-/**************** Get single info ****************/ +- +-struct callback_data +-{ +- GCallback callback; +- gpointer userdata; +-}; +- +- +-#define GET_SINGLE_INFO_CALLBACK(SingleInfo, single_info) \ +- typedef void (*Get##SingleInfo##Callback) \ +- (pa_context *ctx, \ +- const pa_##single_info##_info *info, \ +- gpointer userdata); +- +- +-#define GET_SINGLE_INFO_CB(SingleInfo, single_info) \ +- static void \ +- get_##single_info##_cb (pa_context *ctx, \ +- const pa_##single_info##_info *info, \ +- int eol, \ +- void *userdata) \ +- { \ +- struct callback_data *data = userdata; \ +- Get##SingleInfo##Callback func; \ +- \ +- if (eol == -1) \ +- { \ +- wys_error ("Error getting PulseAudio " \ +- #single_info ": %s", \ +- pa_strerror (pa_context_errno (ctx))); \ +- } \ +- \ +- if (eol) \ +- { \ +- if (data->callback) \ +- { \ +- func = (Get##SingleInfo##Callback)data->callback; \ +- func (ctx, NULL, data->userdata); \ +- } \ +- \ +- g_free (data); \ +- return; \ +- } \ +- \ +- g_assert (info != NULL); \ +- \ +- /* We should only be called once with data */ \ +- g_assert (data->callback != NULL); \ +- \ +- func = (Get##SingleInfo##Callback)data->callback; \ +- func (ctx, info, data->userdata); \ +- \ +- data->callback = NULL; \ +- } +- +- +-#define GET_SINGLE_INFO(single_info, single_info_func) \ +- static void \ +- get_##single_info (pa_context *ctx, \ +- uint32_t index, \ +- GCallback callback, \ +- gpointer userdata) \ +- { \ +- pa_operation *op; \ +- struct callback_data *data; \ +- \ +- data = g_new (struct callback_data, 1); \ +- data->callback = callback; \ +- data->userdata = userdata; \ +- \ +- op = pa_context_get_##single_info_func \ +- (ctx, \ +- index, \ +- get_##single_info##_cb, \ +- data); \ +- \ +- pa_operation_unref (op); \ +- } +- +- +-#define DECLARE_GET_SINGLE_INFO(SingleInfo, single_info, single_info_func) \ +- GET_SINGLE_INFO_CALLBACK(SingleInfo, single_info) \ +- GET_SINGLE_INFO_CB(SingleInfo, single_info) \ +- GET_SINGLE_INFO(single_info, single_info_func) +- +- +-DECLARE_GET_SINGLE_INFO(Source, source, source_info_by_index); +-DECLARE_GET_SINGLE_INFO(Module, module, module_info); +-DECLARE_GET_SINGLE_INFO(Sink, sink, sink_info_by_index); +- +- +-/**************** PulseAudio properties ****************/ +- +-static gboolean +-prop_matches (pa_proplist *props, +- const gchar *key, +- const gchar *needle) +-{ +- const char *value; +- +- value = pa_proplist_gets (props, key); +- +- if (!value) +- { +- return FALSE; +- } +- +- return strcmp (value, needle) == 0; +-} +- +- +-static gboolean +-props_name_alsa_card (pa_proplist *props, +- const gchar *alsa_card) +-{ +-#define check(key,val) \ +- if (!prop_matches (props, key, val)) \ +- { \ +- return FALSE; \ +- } +- +- check ("device.class", "sound"); +- check ("device.api", "alsa"); +- check ("alsa.card_name", alsa_card); +- +-#undef check +- +- return TRUE; +-} +- +- +-/**************** Find loopback data ****************/ +- +-typedef void (*FindLoopbackCallback) (gchar *source_alsa_card, +- gchar *sink_alsa_card, +- GList *modules, +- gpointer userdata); +- +- +-struct find_loopback_data +-{ +- gchar *source_alsa_card; +- gchar *sink_alsa_card; +- GCallback callback; +- gpointer userdata; +- GList *modules; +-}; +- +- +-static struct find_loopback_data * +-find_loopback_data_new (const gchar *source_alsa_card, +- const gchar *sink_alsa_card) +-{ +- struct find_loopback_data *data; +- +- data = g_rc_box_new0 (struct find_loopback_data); +- data->source_alsa_card = g_strdup (source_alsa_card); +- data->sink_alsa_card = g_strdup (sink_alsa_card); +- +- return data; +-} +- +- +-static void +-find_loopback_data_clear (struct find_loopback_data *data) +-{ +- FindLoopbackCallback func = (FindLoopbackCallback)data->callback; +- +- func (data->source_alsa_card, +- data->sink_alsa_card, +- data->modules, +- data->userdata); +- +- g_list_free (data->modules); +- g_free (data->sink_alsa_card); +- g_free (data->source_alsa_card); +-} +- +- +-static inline void +-find_loopback_data_release (struct find_loopback_data *data) +-{ +- g_rc_box_release_full (data, (GDestroyNotify)find_loopback_data_clear); +-} +- +- +-/**************** Loopback module data ****************/ +- +-struct loopback_module_data +-{ +- struct find_loopback_data *loopback_data; +- uint32_t module_index; +-}; +- +- +-static struct loopback_module_data * +-loopback_module_data_new (struct find_loopback_data *loopback_data, +- uint32_t module_index) +-{ +- struct loopback_module_data * module_data; +- +- module_data = g_rc_box_new0 (struct loopback_module_data); +- module_data->module_index = module_index; +- +- g_rc_box_acquire (loopback_data); +- module_data->loopback_data = loopback_data; +- +- return module_data; +-} +- +- +-static inline void +-loopback_module_data_clear (struct loopback_module_data *module_data) +-{ +- find_loopback_data_release (module_data->loopback_data); +-} +- +- +-static inline void +-loopback_module_data_release (struct loopback_module_data *module_data) +-{ +- g_rc_box_release_full (module_data, +- (GDestroyNotify)loopback_module_data_clear); +-} +- +- +-/**************** Sink ****************/ +- +-static void +-find_loopback_get_sink_cb (pa_context *ctx, +- const pa_sink_info *info, +- struct loopback_module_data *module_data) +-{ +- struct find_loopback_data *loopback_data = module_data->loopback_data; +- +- if (!info) +- { +- g_warning ("Could not get sink for module %" PRIu32 +- " owning ALSA card `%s' source output", +- module_data->module_index, +- loopback_data->source_alsa_card); +- goto release; +- } +- +- if (!props_name_alsa_card (info->proplist, +- loopback_data->sink_alsa_card)) +- { +- g_debug ("Sink %" PRIu32 " `%s' for module %" PRIu32 +- " is not ALSA card `%s'", +- info->index, info->name, +- module_data->module_index, +- loopback_data->sink_alsa_card); +- goto release; +- } +- +- +- g_debug ("Loopback module %" PRIu32 " has ALSA card `%s' source" +- " and ALSA card `%s' sink", +- module_data->module_index, +- loopback_data->source_alsa_card, +- loopback_data->sink_alsa_card); +- +- loopback_data->modules = g_list_append +- (loopback_data->modules, +- GUINT_TO_POINTER (module_data->module_index)); +- +- release: +- loopback_module_data_release (module_data); +-} +- +-/**************** Sink input list ****************/ +- +-static void +-find_loopback_sink_input_list_cb (pa_context *ctx, +- const pa_sink_input_info *info, +- int eol, +- void *userdata) +-{ +- struct loopback_module_data *module_data = userdata; +- struct find_loopback_data *loopback_data = module_data->loopback_data; +- +- if (eol == -1) +- { +- wys_error ("Error listing sink inputs: %s", +- pa_strerror (pa_context_errno (ctx))); +- } +- +- if (eol) +- { +- g_debug ("End of sink input list reached"); +- loopback_module_data_release (module_data); +- return; +- } +- +- if (info->owner_module != module_data->module_index) +- { +- g_debug ("Sink input %" PRIu32 " `%s' has" +- " owner module %" PRIu32 " which does" +- " not match sought module %" PRIu32 +- " for ALSA card `%s' source output", +- info->index, +- info->name, +- info->owner_module, +- module_data->module_index, +- loopback_data->source_alsa_card); +- return; +- } +- +- g_debug ("Checking whether sink %" PRIu32 +- " for sink input %" PRIu32 +- " `%s' owned by module %" PRIu32 +- " has ALSA card name `%s'", +- info->sink, +- info->index, +- info->name, +- info->owner_module, +- loopback_data->sink_alsa_card); +- +- g_rc_box_acquire (module_data); +- get_sink (ctx, +- info->sink, +- G_CALLBACK (find_loopback_get_sink_cb), +- module_data); +-} +- +-static void +-find_sink_input (pa_context *ctx, +- struct loopback_module_data *module_data) +-{ +- pa_operation *op; +- +- op = pa_context_get_sink_input_info_list +- (ctx, find_loopback_sink_input_list_cb, module_data); +- +- pa_operation_unref (op); +-} +- +- +-/**************** Module ****************/ +- +-static void +-find_loopback_get_module_cb (pa_context *ctx, +- const pa_module_info *info, +- struct loopback_module_data *module_data) +-{ +- struct find_loopback_data *loopback_data = module_data->loopback_data; +- +- if (!info) +- { +- g_warning ("Could not get module %" PRIu32 +- " for ALSA card `%s' source output", +- module_data->module_index, +- loopback_data->source_alsa_card); +- loopback_module_data_release (module_data); +- return; +- } +- +- if (strcmp (info->name, "module-loopback") != 0) +- { +- g_debug ("Module %" PRIu32 " for ALSA card `%s` source output" +- " is not a loopback module", +- info->index, loopback_data->source_alsa_card); +- loopback_module_data_release (module_data); +- return; +- } +- +- +- g_debug ("Module %" PRIu32 " for ALSA card `%s' source output is a" +- " loopback module, finding sink input with matching module", +- info->index, loopback_data->source_alsa_card); +- +- find_sink_input (ctx, module_data); +-} +- +- +-/**************** Source ****************/ +- +-static void +-find_loopback_get_source_cb (pa_context *ctx, +- const pa_source_info *info, +- struct loopback_module_data *module_data) +-{ +- struct find_loopback_data *loopback_data = module_data->loopback_data; +- +- if (!info) +- { +- g_warning ("Couldn't find source for source output" +- " while finding ALSA card `%s' source", +- loopback_data->source_alsa_card); +- loopback_module_data_release (module_data); +- return; +- } +- +- if (!props_name_alsa_card (info->proplist, +- loopback_data->source_alsa_card)) +- { +- g_debug ("Source %" PRIu32 " `%s' is not ALSA card `%s'", +- info->index, info->name, +- loopback_data->source_alsa_card); +- loopback_module_data_release (module_data); +- return; +- } +- +- +- g_debug ("Checking whether module %" PRIu32 +- " for ALSA card `%s' source output" +- " is a loopback module", +- module_data->module_index, +- loopback_data->source_alsa_card); +- +- get_module (ctx, +- module_data->module_index, +- G_CALLBACK (find_loopback_get_module_cb), +- module_data); +-} +- +- +-/**************** Find loopback (source output list) ****************/ +- +-static void +-find_loopback_source_output_list_cb (pa_context *ctx, +- const pa_source_output_info *info, +- int eol, +- void *userdata) +-{ +- struct find_loopback_data *loopback_data = userdata; +- struct loopback_module_data *module_data; +- +- if (eol == -1) +- { +- wys_error ("Error listing PulseAudio source outputs: %s", +- pa_strerror (pa_context_errno (ctx))); +- } +- +- if (eol) +- { +- g_debug ("End of source output list reached"); +- find_loopback_data_release (loopback_data); +- return; +- } +- +- if (info->owner_module == PA_INVALID_INDEX) +- { +- g_debug ("Source output %" PRIu32 " `%s'" +- " is not owned by a module", +- info->index, info->name); +- return; +- } +- +- module_data = loopback_module_data_new (loopback_data, +- info->owner_module); +- +- g_debug ("Getting source %" PRIu32 +- " of source output %" PRIu32 " `%s'", +- info->source, info->index, info->name); +- get_source (ctx, +- info->source, +- G_CALLBACK (find_loopback_get_source_cb), +- module_data); +-} +- +- +-/** Find any loopback module between the specified source and sink +- alsa cards. +- +- 1. Loop through all source outputs. +- 1. Skip any source output that doesn't have the specified +- alsa card as its source. +- 2. Skip any source output that isn't a loopback module. +- 3. Loop through all sink inputs. +- 1. Skip any sink input whose module index doesn't match. +- 2. Skip any sink input which doesn't have the specified alsa +- card as its sink. +- 3. Found a loopback. +-*/ +-static void +-find_loopback (pa_context *ctx, +- const gchar *source_alsa_card, +- const gchar *sink_alsa_card, +- GCallback callback, +- gpointer userdata) +-{ +- struct find_loopback_data *data; +- pa_operation *op; +- +- data = find_loopback_data_new (source_alsa_card, sink_alsa_card); +- data->callback = callback; +- data->userdata = userdata; +- +- g_debug ("Finding ALSA card `%s' source output", +- source_alsa_card); +- op = pa_context_get_source_output_info_list +- (ctx, find_loopback_source_output_list_cb, data); +- +- pa_operation_unref (op); +-} +- +- +-/**************** Find ALSA card data ****************/ +- +-typedef void (*FindALSACardCallback) (const gchar *alsa_card_name, +- const gchar *pulse_object_name, +- gpointer userdata); +- +-struct find_alsa_card_data +-{ +- gchar *alsa_card_name; +- GCallback callback; +- gpointer userdata; +- gchar *pulse_object_name; +-}; +- +- +-static struct find_alsa_card_data * +-find_alsa_card_data_new (const gchar *alsa_card_name) +-{ +- struct find_alsa_card_data *data; +- +- data = g_rc_box_new0 (struct find_alsa_card_data); +- data->alsa_card_name = g_strdup (alsa_card_name); +- +- return data; +-} +- +- +-static void +-find_alsa_card_data_clear (struct find_alsa_card_data *data) +-{ +- FindALSACardCallback func = (FindALSACardCallback)data->callback; +- +- func (data->alsa_card_name, +- data->pulse_object_name, +- data->userdata); +- +- g_free (data->pulse_object_name); +- g_free (data->alsa_card_name); +-} +- +- +-static inline void +-find_alsa_card_data_release (struct find_alsa_card_data *data) +-{ +- g_rc_box_release_full (data, (GDestroyNotify)find_alsa_card_data_clear); +-} +- +- +-/**************** Find ALSA card ****************/ +- +-#define FIND_ALSA_CARD_LIST_CB(object_type) \ +- static void \ +- find_alsa_card_##object_type##list_cb \ +- (pa_context *ctx, \ +- const pa_##object_type##_info *info, \ +- int eol, \ +- void *userdata) \ +- { \ +- struct find_alsa_card_data *alsa_card_data = userdata; \ +- \ +- if (eol == -1) \ +- { \ +- wys_error ("Error listing PulseAudio " #object_type "s: %s", \ +- pa_strerror (pa_context_errno (ctx))); \ +- } \ +- \ +- if (eol) \ +- { \ +- g_debug ("End of " #object_type " list reached"); \ +- find_alsa_card_data_release (alsa_card_data); \ +- return; \ +- } \ +- \ +- if (alsa_card_data->pulse_object_name != NULL) \ +- { \ +- /* Already found our object */ \ +- g_debug ("Skipping " #object_type \ +- " %" PRIu32 " `%s'", \ +- info->index, info->name); \ +- return; \ +- } \ +- \ +- g_assert (info != NULL); \ +- \ +- if (!props_name_alsa_card (info->proplist, \ +- alsa_card_data->alsa_card_name)) \ +- { \ +- g_debug ("The " #object_type " %" PRIu32 \ +- " `%s' is not ALSA card `%s'", \ +- info->index, \ +- info->name, \ +- alsa_card_data->alsa_card_name); \ +- return; \ +- } \ +- \ +- g_debug ("The " #object_type " %" PRIu32 \ +- " `%s' is ALSA card `%s'", \ +- info->index, \ +- info->name, \ +- alsa_card_data->alsa_card_name); \ +- alsa_card_data->pulse_object_name = g_strdup (info->name); \ +- } +- +- +-#define FIND_ALSA_CARD(object_type) \ +- static void \ +- find_alsa_card_##object_type (pa_context *ctx, \ +- const gchar *alsa_card_name, \ +- GCallback callback, \ +- gpointer userdata) \ +- { \ +- pa_operation *op; \ +- struct find_alsa_card_data *data; \ +- \ +- data = find_alsa_card_data_new (alsa_card_name); \ +- data->callback = callback; \ +- data->userdata = userdata; \ +- \ +- op = pa_context_get_##object_type##_info_list \ +- (ctx, find_alsa_card_##object_type##list_cb, data); \ +- \ +- pa_operation_unref (op); \ +- } +- +-#define DECLARE_FIND_ALSA_CARD(object_type) \ +- FIND_ALSA_CARD_LIST_CB(object_type) \ +- FIND_ALSA_CARD(object_type) +- +- +-DECLARE_FIND_ALSA_CARD(source); +-DECLARE_FIND_ALSA_CARD(sink); +- +- +-/**************** Instantiate loopback data ****************/ +- +-typedef void (*InstantiateLoopbackCallback) (gchar *source_alsa_card, +- gchar *sink_alsa_card, +- gchar *source, +- gchar *sink, +- gpointer userdata); +- +- +-struct instantiate_loopback_data +-{ +- pa_context *ctx; +- gchar *source_alsa_card; +- gchar *sink_alsa_card; +- gchar *media_name; +- gchar *source; +- gchar *sink; +-}; +- +- +-static struct instantiate_loopback_data * +-instantiate_loopback_data_new (pa_context *ctx, +- const gchar *source_alsa_card, +- const gchar *sink_alsa_card, +- const gchar *media_name) +-{ +- struct instantiate_loopback_data *data; +- +- data = g_rc_box_new0 (struct instantiate_loopback_data); +- +- pa_context_ref (ctx); +- data->ctx = ctx; +- +- data->source_alsa_card = g_strdup (source_alsa_card); +- data->sink_alsa_card = g_strdup (sink_alsa_card); +- data->media_name = g_strdup (media_name); +- +- return data; +-} +- +- +-static void +-instantiate_loopback_data_clear (struct instantiate_loopback_data *data) +-{ +- g_free (data->sink); +- g_free (data->source); +- g_free (data->media_name); +- g_free (data->sink_alsa_card); +- g_free (data->source_alsa_card); +- pa_context_unref (data->ctx); +-} +- +- +-static inline void +-instantiate_loopback_data_release (struct instantiate_loopback_data *data) +-{ +- g_rc_box_release_full (data, (GDestroyNotify)instantiate_loopback_data_clear); +-} +- +- +-/**************** Instantiate loopback ****************/ +- +-static void +-instantiate_loopback_load_module_cb (pa_context *ctx, +- uint32_t index, +- void *userdata) +-{ +- struct instantiate_loopback_data *data = userdata; +- +- if (index == PA_INVALID_INDEX) +- { +- g_warning ("Error instantiating loopback module with source `%s'" +- " (ALSA card `%s') and sink `%s' (ALSA card `%s'): %s", +- data->source, +- data->source_alsa_card, +- data->sink, +- data->sink_alsa_card, +- pa_strerror (pa_context_errno (ctx))); +- } +- else +- { +- g_debug ("Instantiated loopback module %" PRIu32 +- " with source `%s' (ALSA card `%s')" +- " and sink `%s' (ALSA card `%s')", +- index, +- data->source, +- data->source_alsa_card, +- data->sink, +- data->sink_alsa_card); +- } +- +- instantiate_loopback_data_release (data); +-} +- +- +-static void +-instantiate_loopback_sink_cb (const gchar *alsa_card_name, +- const gchar *pulse_object_name, +- gpointer userdata) +-{ +- struct instantiate_loopback_data *data = userdata; +- pa_proplist *stream_props; +- gchar *stream_props_str; +- gchar *arg; +- pa_operation *op; +- +- if (!pulse_object_name) +- { +- g_warning ("Could not find sink for ALSA card `%s'", +- alsa_card_name); +- instantiate_loopback_data_release (data); +- return; +- } +- +- data->sink = g_strdup (pulse_object_name); +- +- g_debug ("Instantiating loopback module with source `%s'" +- " (ALSA card `%s') and sink `%s' (ALSA card `%s')", +- data->source, +- data->source_alsa_card, +- data->sink, +- data->sink_alsa_card); +- +- stream_props = pa_proplist_new (); +- g_assert (stream_props != NULL); +- proplist_set (stream_props, "media.role", "phone"); +- proplist_set (stream_props, "media.icon_name", "phone"); +- proplist_set (stream_props, "media.name", data->media_name); +- +- stream_props_str = pa_proplist_to_string (stream_props); +- pa_proplist_free (stream_props); +- +- arg = g_strdup_printf ("source=%s" +- " sink=%s" +- " source_dont_move=true" +- " sink_dont_move=true" +- " fast_adjust_threshold_msec=100" +- " max_latency_msec=25" +- " sink_input_properties='%s'" +- " source_output_properties='%s'", +- data->source, +- data->sink, +- stream_props_str, +- stream_props_str); +- pa_xfree (stream_props_str); +- +- op = pa_context_load_module (data->ctx, +- "module-loopback", +- arg, +- instantiate_loopback_load_module_cb, +- data); +- +- pa_operation_unref (op); +- g_free (arg); +-} +- +- +-static void +-instantiate_loopback_source_cb (const gchar *alsa_card_name, +- const gchar *pulse_object_name, +- gpointer userdata) +-{ +- struct instantiate_loopback_data *data = userdata; +- +- if (!pulse_object_name) +- { +- g_warning ("Could not find source for ALSA card `%s'", +- alsa_card_name); +- instantiate_loopback_data_release (data); +- return; +- } +- +- data->source = g_strdup (pulse_object_name); +- +- g_debug ("Finding sink for ALSA card `%s'", data->sink_alsa_card); +- find_alsa_card_sink (data->ctx, +- data->sink_alsa_card, +- G_CALLBACK (instantiate_loopback_sink_cb), +- data); +-} +- +- +-static void +-instantiate_loopback (pa_context *ctx, +- const gchar *source_alsa_card, +- const gchar *sink_alsa_card, +- const gchar *media_name) +-{ +- struct instantiate_loopback_data *loopback_data; +- +- loopback_data = instantiate_loopback_data_new (ctx, +- source_alsa_card, +- sink_alsa_card, +- media_name); +- +- g_debug ("Finding source for ALSA card `%s'", source_alsa_card); +- find_alsa_card_source (ctx, +- source_alsa_card, +- G_CALLBACK (instantiate_loopback_source_cb), +- loopback_data); +-} +- +- +-/**************** Ensure loopback ****************/ +- +-struct ensure_loopback_data +-{ +- pa_context *ctx; +- const gchar *media_name; +-}; +- +- +-static void +-ensure_loopback_find_loopback_cb (gchar *source_alsa_card, +- gchar *sink_alsa_card, +- GList *modules, +- struct ensure_loopback_data *data) +-{ +- if (modules != NULL) +- { +- g_warning ("%u loopback module(s) for ALSA card `%s' source ->" +- " ALSA card `%s' sink already exist", +- g_list_length (modules), +- source_alsa_card, sink_alsa_card); +- } +- else +- { +- g_debug ("Instantiating loopback module for ALSA card `%s' source ->" +- " ALSA card `%s' sink", +- source_alsa_card, sink_alsa_card); +- +- instantiate_loopback (data->ctx, source_alsa_card, +- sink_alsa_card, data->media_name); +- } +- +- g_free (data); +-} +- +- +-static void +-ensure_loopback (pa_context *ctx, +- const gchar *source_alsa_card, +- const gchar *sink_alsa_card, +- const gchar *media_name) +-{ +- struct ensure_loopback_data *data; +- +- data = g_new (struct ensure_loopback_data, 1); +- data->ctx = ctx; +- // This is a static string so we don't need a copy +- data->media_name = media_name; +- +- find_loopback (ctx, source_alsa_card, sink_alsa_card, +- G_CALLBACK (ensure_loopback_find_loopback_cb), +- data); +-} +- +- +-void +-wys_audio_ensure_loopback (WysAudio *self, +- WysDirection direction) +-{ +- switch (direction) +- { +- case WYS_DIRECTION_FROM_NETWORK: +- ensure_loopback (self->ctx, self->modem, self->codec, +- "Voice call audio (to speaker)"); +- break; +- case WYS_DIRECTION_TO_NETWORK: +- ensure_loopback (self->ctx, self->codec, self->modem, +- "Voice call audio (from mic)"); +- break; +- default: +- break; +- } +-} +- +- +-/**************** Ensure no loopback ****************/ +- +-static void +-ensure_no_loopback_unload_module_cb (pa_context *ctx, +- int success, +- void *userdata) +-{ +- const guint module_index = GPOINTER_TO_UINT (userdata); +- +- if (success) +- { +- g_debug ("Successfully deinstantiated loopback module %u", +- module_index); +- } +- else +- { +- g_warning ("Error deinstantiating loopback module %u: %s", +- module_index, +- pa_strerror (pa_context_errno (ctx))); +- } +-} +- +- +-static void +-ensure_no_loopback_modules_cb (gpointer data, +- pa_context *ctx) +-{ +- const uint32_t module_index = GPOINTER_TO_UINT (data); +- pa_operation *op; +- +- g_debug ("Deinstantiating loopback module %" PRIu32, +- module_index); +- +- op = pa_context_unload_module (ctx, +- module_index, +- ensure_no_loopback_unload_module_cb, +- data); +- +- pa_operation_unref (op); +-} +- +- +-static void +-ensure_no_loopback_find_loopback_cb (gchar *source_alsa_card, +- gchar *sink_alsa_card, +- GList *modules, +- pa_context *ctx) +-{ +- if (modules == NULL) +- { +- g_warning ("No loopback module(s) for ALSA card `%s' source ->" +- " ALSA card `%s' sink", +- source_alsa_card, sink_alsa_card); +- return; +- } +- +- g_debug ("Deinstantiating loopback modules for ALSA card `%s' source ->" +- " ALSA card `%s' sink", +- source_alsa_card, sink_alsa_card); +- +- g_list_foreach (modules, +- (GFunc)ensure_no_loopback_modules_cb, +- ctx); +-} +- +- +-static void +-ensure_no_loopback (pa_context *ctx, +- const gchar *source_alsa_card, +- const gchar *sink_alsa_card) +-{ +- find_loopback (ctx, source_alsa_card, sink_alsa_card, +- G_CALLBACK (ensure_no_loopback_find_loopback_cb), +- ctx); +-} +- +- +-void +-wys_audio_ensure_no_loopback (WysAudio *self, +- WysDirection direction) +-{ +- switch (direction) +- { +- case WYS_DIRECTION_FROM_NETWORK: +- ensure_no_loopback (self->ctx, self->modem, self->codec); +- break; +- case WYS_DIRECTION_TO_NETWORK: +- ensure_no_loopback (self->ctx, self->codec, self->modem); +- break; +- default: +- break; +- } +-} +diff --git a/src/wys-audio.h b/src/wys-audio.h +deleted file mode 100644 +index ce74009..0000000 +--- a/src/wys-audio.h ++++ /dev/null +@@ -1,47 +0,0 @@ +-/* +- * Copyright (C) 2018, 2019 Purism SPC +- * +- * This file is part of Wys. +- * +- * Wys is free software: you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Wys 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 General Public +- * License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Wys. If not, see . +- * +- * Author: Bob Ham +- * +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- */ +- +-#ifndef WYS_AUDIO_H__ +-#define WYS_AUDIO_H__ +- +-#include "wys-direction.h" +- +-#include +- +-G_BEGIN_DECLS +- +-#define WYS_TYPE_AUDIO (wys_audio_get_type ()) +- +-G_DECLARE_FINAL_TYPE (WysAudio, wys_audio, WYS, AUDIO, GObject); +- +-WysAudio *wys_audio_new (const gchar *codec, +- const gchar *modem); +-void wys_audio_ensure_loopback (WysAudio *self, +- WysDirection direction); +-void wys_audio_ensure_no_loopback (WysAudio *self, +- WysDirection direction); +- +-G_END_DECLS +- +-#endif /* WYS_AUDIO_H__ */ +diff --git a/src/wys-direction.c b/src/wys-direction.c +deleted file mode 100644 +index 1a84847..0000000 +--- a/src/wys-direction.c ++++ /dev/null +@@ -1,40 +0,0 @@ +-/* +- * Copyright (C) 2019 Purism SPC +- * +- * This file is part of Wys. +- * +- * Wys is free software: you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Wys 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 General Public +- * License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Wys. If not, see . +- * +- * Author: Bob Ham +- * +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- */ +- +- +-#include "wys-direction.h" +- +-const gchar * +-wys_direction_get_description (WysDirection direction) +-{ +- switch (direction) +- { +- case WYS_DIRECTION_FROM_NETWORK: +- return "from network"; +- case WYS_DIRECTION_TO_NETWORK: +- return "to network"; +- default: +- return NULL; +- } +-} +diff --git a/src/wys-direction.h b/src/wys-direction.h +deleted file mode 100644 +index 5c8de8b..0000000 +--- a/src/wys-direction.h ++++ /dev/null +@@ -1,42 +0,0 @@ +-/* +- * Copyright (C) 2019 Purism SPC +- * +- * This file is part of Wys. +- * +- * Wys is free software: you can redistribute it and/or modify it +- * under the terms of the GNU General Public License as published by +- * the Free Software Foundation, either version 3 of the License, or +- * (at your option) any later version. +- * +- * Wys 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 General Public +- * License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with Wys. If not, see . +- * +- * Author: Bob Ham +- * +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- */ +- +-#ifndef WYS_DIRECTION_H__ +-#define WYS_DIRECTION_H__ +- +-#include +- +-G_BEGIN_DECLS +- +-typedef enum +-{ +- WYS_DIRECTION_FROM_NETWORK = 0, +- WYS_DIRECTION_TO_NETWORK +-} WysDirection; +- +-const gchar *wys_direction_get_description (WysDirection direction); +- +-G_END_DECLS +- +-#endif /* WYS_DIRECTION_H__ */ +diff --git a/src/wys-modem.c b/src/wys-modem.c +index 212f992..51a0575 100644 +--- a/src/wys-modem.c ++++ b/src/wys-modem.c +@@ -24,18 +24,10 @@ + + + #include "wys-modem.h" +-#include "wys-direction.h" + #include "util.h" +-#include "enum-types.h" + + #include + +-static const gchar * const WYS_MODEM_HAS_AUDIO[] = +- { +- [WYS_DIRECTION_FROM_NETWORK] = "wys-has-audio-from-network", +- [WYS_DIRECTION_TO_NETWORK] = "wys-has-audio-to-network" +- }; +- + struct _WysModem + { + GObject parent_instance; +@@ -43,8 +35,8 @@ struct _WysModem + MMModemVoice *voice; + /** Map of D-Bus object paths to MMCall objects */ + GHashTable *calls; +- /** How many calls have audio, in each direction */ +- guint audio_count[2]; ++ /** How many calls have audio */ ++ guint audio_count; + }; + + G_DEFINE_TYPE(WysModem, wys_modem, G_TYPE_OBJECT) +@@ -65,15 +57,11 @@ static guint signals [SIGNAL_LAST_SIGNAL]; + + + static gboolean +-call_state_has_audio (WysDirection direction, +- MMCallState state) ++call_state_has_audio (MMCallState state) + { + switch (state) + { + case MM_CALL_STATE_RINGING_OUT: +- return +- (direction == WYS_DIRECTION_FROM_NETWORK) +- ? TRUE : FALSE; + case MM_CALL_STATE_ACTIVE: + return TRUE; + default: +@@ -84,39 +72,35 @@ call_state_has_audio (WysDirection direction, + + static void + update_audio_count (WysModem *self, +- WysDirection direction, + gint delta) + { +- const guint old_count = self->audio_count[direction]; ++ const guint old_count = self->audio_count; + +- g_assert (delta >= 0 || self->audio_count[direction] > 0); ++ g_assert (delta >= 0 || self->audio_count > 0); + +- self->audio_count[direction] += delta; ++ self->audio_count += delta; + +- if (self->audio_count[direction] > 0 && old_count == 0) ++ if (self->audio_count > 0 && old_count == 0) + { +- g_debug ("Modem `%s' audio %s now present", +- mm_modem_voice_get_path (self->voice), +- wys_direction_get_description (direction)); +- g_signal_emit_by_name (self, "audio-present", direction); ++ g_message ("Modem `%s' audio now present", ++ mm_modem_voice_get_path (self->voice)); ++ g_signal_emit_by_name (self, "audio-present"); + } +- else if (self->audio_count[direction] == 0 && old_count > 0) ++ else if (self->audio_count == 0 && old_count > 0) + { +- g_debug ("Modem `%s' audio now absent", +- mm_modem_voice_get_path (self->voice)); +- g_signal_emit_by_name (self, "audio-absent", direction); ++ g_message ("Modem `%s' audio now absent", ++ mm_modem_voice_get_path (self->voice)); ++ g_signal_emit_by_name (self, "audio-absent"); + } + } + + + static gboolean +-get_call_has_audio (MMCall *mm_call, +- WysDirection direction) ++get_call_has_audio (MMCall *mm_call) + { + gpointer data; + +- data = g_object_get_data (G_OBJECT (mm_call), +- WYS_MODEM_HAS_AUDIO[direction]); ++ data = g_object_get_data (G_OBJECT (mm_call), "audio-state"); + + return (gboolean)(GPOINTER_TO_UINT (data)); + } +@@ -124,42 +108,38 @@ get_call_has_audio (MMCall *mm_call, + + static void + set_call_has_audio (MMCall *mm_call, +- WysDirection direction, + gboolean has_audio) + { + g_object_set_data (G_OBJECT (mm_call), +- WYS_MODEM_HAS_AUDIO[direction], ++ "audio-state", + GUINT_TO_POINTER ((guint)has_audio)); + } + + + static void +-update_direction_state (WysModem *self, +- MMCall *mm_call, +- const gchar *path, +- WysDirection direction, +- MMCallState old_state, +- MMCallState new_state) ++update_call_state (WysModem *self, ++ MMCall *mm_call, ++ const gchar *path, ++ MMCallState old_state, ++ MMCallState new_state) + { +- gboolean had_audio = call_state_has_audio (direction, old_state); +- gboolean have_audio = call_state_has_audio (direction, new_state); ++ gboolean had_audio = call_state_has_audio (old_state); ++ gboolean have_audio = call_state_has_audio (new_state); + + if (!had_audio && have_audio) + { +- g_debug ("Call `%s' gained audio %s", path, +- wys_direction_get_description (direction)); +- update_audio_count (self, direction, +1); ++ g_message ("Call `%s' gained audio", path); ++ update_audio_count (self, +1); + } + else if (had_audio && !have_audio) + { +- g_debug ("Call `%s' lost audio %s", path, +- wys_direction_get_description (direction)); +- update_audio_count (self, direction, -1); ++ g_message ("Call `%s' lost audio", path); ++ update_audio_count (self, -1); + } + + if (had_audio != have_audio) + { +- set_call_has_audio (mm_call, direction, have_audio); ++ set_call_has_audio (mm_call, have_audio); + } + } + +@@ -174,34 +154,28 @@ call_state_changed_cb (MmGdbusCall *mm_gdbus_call, + MMCall *mm_call = MM_CALL (mm_gdbus_call); + const gchar * path = mm_call_get_path (mm_call); + +- g_debug ("Call `%s' state changed, new: %i, old: %i", ++ g_message ("Call `%s' state changed, new: %i, old: %i", + path, (int)new_state, (int)old_state); + + // FIXME: deal with calls being put on hold (one call goes + // non-audio, another call goes audio after) + +- update_direction_state (self, mm_call, path, +- WYS_DIRECTION_FROM_NETWORK, +- old_state, new_state); +- update_direction_state (self, mm_call, path, +- WYS_DIRECTION_TO_NETWORK, +- old_state, new_state); ++ update_call_state (self, mm_call, path, old_state, new_state); + } + + + static void +-init_call_direction (WysModem *self, +- MMCall *mm_call, +- MMCallState state, +- WysDirection direction) ++init_call_audio (WysModem *self, ++ MMCall *mm_call, ++ MMCallState state) + { +- gboolean has_audio = call_state_has_audio (direction, state); ++ gboolean has_audio = call_state_has_audio (state); + +- set_call_has_audio (mm_call, direction, has_audio); ++ set_call_has_audio (mm_call, has_audio); + + if (has_audio) + { +- update_audio_count (self, direction, +1); ++ update_audio_count (self, +1); + } + } + +@@ -223,12 +197,9 @@ add_call (WysModem *self, + self); + + state = mm_call_get_state (mm_call); +- init_call_direction (self, mm_call, state, +- WYS_DIRECTION_FROM_NETWORK); +- init_call_direction (self, mm_call, state, +- WYS_DIRECTION_TO_NETWORK); ++ init_call_audio (self, mm_call, state); + +- g_debug ("Call `%s' added, state: %i", path, (int)state); ++ g_message ("Call `%s' added, state: %i", path, (int)state); + } + + +@@ -322,16 +293,14 @@ call_added_cb (MMModemVoice *voice, + + + static void +-clear_call_direction (WysModem *self, +- MMCall *mm_call, +- WysDirection direction) ++clear_call_state (WysModem *self, ++ MMCall *mm_call) + { +- gboolean has_audio = +- get_call_has_audio (mm_call, direction); ++ gboolean has_audio = get_call_has_audio (mm_call); + + if (has_audio) + { +- update_audio_count (self, direction, -1); ++ update_audio_count (self, -1); + } + } + +@@ -343,7 +312,7 @@ call_deleted_cb (MMModemVoice *voice, + { + MMCall *mm_call; + +- g_debug ("Removing call `%s'", path); ++ g_message ("Removing call `%s'", path); + + mm_call = g_hash_table_lookup (self->calls, path); + if (!mm_call) +@@ -352,14 +321,11 @@ call_deleted_cb (MMModemVoice *voice, + return; + } + +- clear_call_direction (self, mm_call, +- WYS_DIRECTION_FROM_NETWORK); +- clear_call_direction (self, mm_call, +- WYS_DIRECTION_TO_NETWORK); ++ clear_call_state (self, mm_call); + + g_hash_table_remove (self->calls, path); + +- g_debug ("Call `%s' removed", path); ++ g_message ("Call `%s' removed", path); + } + + +@@ -444,11 +410,9 @@ dispose (GObject *object) + if (g_hash_table_size (self->calls) > 0) + { + g_hash_table_remove_all (self->calls); +- if (self->audio_count[WYS_DIRECTION_FROM_NETWORK] > 0 || +- self->audio_count[WYS_DIRECTION_TO_NETWORK] > 0) ++ if (self->audio_count > 0) + { +- self->audio_count[WYS_DIRECTION_FROM_NETWORK] = +- self->audio_count[WYS_DIRECTION_TO_NETWORK] = 0; ++ self->audio_count = 0; + g_signal_emit_by_name (self, "audio-absent"); + } + } +@@ -504,8 +468,7 @@ wys_modem_class_init (WysModemClass *klass) + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, +- 1, +- WYS_TYPE_DIRECTION); ++ 0); + + /** + * WysModem::audio-absent: +@@ -520,8 +483,7 @@ wys_modem_class_init (WysModemClass *klass) + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, NULL, + G_TYPE_NONE, +- 1, +- WYS_TYPE_DIRECTION); ++ 0); + } + + +diff --git a/subprojects/libmachine-check/mchk-machine-check.c b/subprojects/libmachine-check/mchk-machine-check.c +deleted file mode 100644 +index 2c54bda..0000000 +--- a/subprojects/libmachine-check/mchk-machine-check.c ++++ /dev/null +@@ -1,328 +0,0 @@ +-/* +- * Copyright (C) 2019 Purism SPC +- * +- * This file is part of libmachine-check. +- * +- * libmachine-check is free software: you can redistribute it and/or +- * modify it under the terms of the GNU General Public License as +- * published by the Free Software Foundation, either version 3 of the +- * License, or (at your option) any later version. +- * +- * libmachine-check 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 +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with libmachine-check. If not, see +- * . +- * +- * Author: Bob Ham +- * +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- */ +- +-#include "mchk-machine-check.h" +-#include "config.h" +- +-#include +-#include +- +-#include +-#include +-#include +-#include +- +- +-/** +- * mchk_read_machine: +- * @error: (allow-none): return location for an error, or %NULL +- * +- * Read the machine name from /proc/device-tree/machine. If the +- * machine name could not be read, %NULL is returned and @error is +- * set. +- * +- * Returns: (nullable) (transfer full): The machine name or %NULL on +- * error. +- */ +-gchar * +-mchk_read_machine (GError **error_out) +-{ +- static const gchar *MODEL_FILENAME = "/proc/device-tree/model"; +- gchar *machine; +- GError *error = NULL; +- +- g_return_val_if_fail (error_out == NULL || *error_out == NULL, NULL); +- +- g_file_get_contents (MODEL_FILENAME, +- &machine, +- NULL, +- &error); +- if (error) +- { +- g_warning ("Error reading machine name from `%s': %s", +- MODEL_FILENAME, error->message); +- g_propagate_error (error_out, error); +- } +- +- return machine; +-} +- +- +-static gboolean +-check_list_lines (const gchar *filename, +- int fd, +- const gchar *machine, +- gboolean *present, +- GError **error_out) +-{ +- GInputStream *unix_stream; +- g_autoptr(GDataInputStream) data_stream = NULL; +- GError *error = NULL; +- +- g_debug ("Reading list file `%s'", filename); +- +- unix_stream = g_unix_input_stream_new (fd, TRUE); +- g_assert (unix_stream != NULL); +- +- data_stream = g_data_input_stream_new (unix_stream); +- g_assert (data_stream != NULL); +- g_object_unref (unix_stream); +- +- for (;;) +- { +- g_autofree gchar *line = +- g_data_input_stream_read_line_utf8 +- (data_stream, NULL, NULL, &error); +- +- if (error) +- { +- g_warning ("Error reading from check" +- " list file `%s': %s", +- filename, error->message); +- g_propagate_error (error_out, error); +- return FALSE; +- } +- +- if (line) +- { +- g_strstrip (line); +- +- // Skip comments and empty lines +- if (line[0] == '#' || line[0] == '\0') +- { +- continue; +- } +- +- // Check for the machine name +- if (strcmp (line, machine) == 0) +- { +- *present = TRUE; +- return TRUE; +- } +- } +- else // EOF +- { +- *present = FALSE; +- return TRUE; +- } +- } +-} +- +- +-static gboolean +-check_list (const gchar *dirname, +- const gchar *list, +- gboolean *list_exists, +- const gchar *machine, +- gboolean *present, +- GError **error) +-{ +- g_autofree gchar *filename = NULL; +- int fd; +- +- filename = g_build_filename (dirname, list, NULL); +- +- fd = g_open (filename, O_RDONLY, 0); +- if (fd == -1) +- { +- if (errno == ENOENT) // The file doesn't exist +- { +- if (list_exists) +- { +- *list_exists = FALSE; +- } +- *present = FALSE; +- return TRUE; +- } +- +- g_warning ("Error opening check" +- " list file `%s': %s", +- filename, g_strerror (errno)); +- return FALSE; +- } +- +- if (list_exists) +- { +- *list_exists = TRUE; +- } +- +- return check_list_lines (filename, +- fd, +- machine, +- present, +- error); +-} +- +- +-static gboolean +-check_dir_machine (const gchar *dir, +- const gchar *param, +- const gchar *machine, +- gboolean *done, +- gboolean *passed, +- GError **error) +-{ +- g_autofree gchar *check_dirname = NULL; +- gboolean list_exists, present, ok; +- +- check_dirname = g_build_filename (dir, "machine-check", +- param, NULL); +- +- // Check the blacklist +- ok = check_list (check_dirname, +- "blacklist", +- NULL, +- machine, +- &present, +- error); +- if (!ok) +- { +- return FALSE; +- } +- +- if (present) +- { +- g_debug ("Machine present in blacklist under `%s'", +- check_dirname); +- if (passed) +- { +- *passed = FALSE; +- } +- *done = TRUE; +- return TRUE; +- } +- +- // Check the whitelist +- ok = check_list (check_dirname, +- "whitelist", +- &list_exists, +- machine, +- &present, +- error); +- if (!ok) +- { +- return FALSE; +- } +- +- if (list_exists) +- { +- g_debug ("Machine whitelist exists under `%s'" +- ", machine %spresent", +- check_dirname, +- present ? "" : "not "); +- *done = TRUE; +- if (passed) +- { +- *passed = present; +- } +- } +- +- g_debug ("No machine whitelist or blacklist under `%s'", +- check_dirname); +- return TRUE; +-} +- +- +-/** +- * mchk_check_machine: +- * @param: the name of the machine-check sub-directory whose blacklist +- * and whitelist should be used +- * @machine: (allow-none): the machine name to check, or %NULL +- * @passed: (out) (allow-none): return location for the check result, +- * or %NULL +- * @error: (allow-none): return location for an error, or %NULL +- * +- * Check whether the machine name is not present in a blacklist and/or +- * present in a whitelist within a machine-check sub-directory +- * named @param. If @machine is %NULL then mchk_read_machine() will +- * be used to get the machine name. If an error is encountered, +- * @error will be set and %FALSE will be returned. +- * +- * Returns: %TRUE on success or %FALSE on error. +- */ +-gboolean +-mchk_check_machine (const gchar *param, +- const gchar *machine, +- gboolean *passed, +- GError **error) +-{ +- g_autofree gchar *mach = NULL; +- const gchar * const *dirs, * const *dir; +- gboolean done = FALSE, ok; +- +- g_return_val_if_fail (param != NULL, FALSE); +- g_return_val_if_fail (error == NULL || *error == NULL, FALSE); +- +- // Get the machine name +- if (machine) +- { +- mach = g_strdup (machine); +- } +- else +- { +- mach = mchk_read_machine (error); +- if (!mach) +- { +- return FALSE; +- } +- } +- +- // Iterate over possible whitelist/blacklist locations +-#define try_dir(d) \ +- ok = check_dir_machine (d, param, mach, \ +- &done, passed, error); \ +- if (!ok || done) \ +- { \ +- return ok; \ +- } +- +- +- try_dir (g_get_user_config_dir ()); +- +- dirs = g_get_system_config_dirs (); +- for (dir = dirs; *dir; ++dir) +- { +- try_dir (*dir); +- } +- +- try_dir (SYSCONFDIR); +- try_dir (DATADIR); +- +- dirs = g_get_system_data_dirs (); +- for (dir = dirs; *dir; ++dir) +- { +- try_dir (*dir); +- } +- +-#undef try_dir +- +- +- g_debug ("Defaulting to pass"); +- if (passed) +- { +- *passed = TRUE; +- } +- return TRUE; +-} +diff --git a/subprojects/libmachine-check/mchk-machine-check.h b/subprojects/libmachine-check/mchk-machine-check.h +deleted file mode 100644 +index 35e5e7c..0000000 +--- a/subprojects/libmachine-check/mchk-machine-check.h ++++ /dev/null +@@ -1,38 +0,0 @@ +-/* +- * Copyright (C) 2019 Purism SPC +- * +- * This file is part of libmachine-check. +- * +- * libmachine-check is free software: you can redistribute it and/or +- * modify it under the terms of the GNU General Public License as +- * published by the Free Software Foundation, either version 3 of the +- * License, or (at your option) any later version. +- * +- * libmachine-check 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 +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with libmachine-check. If not, see +- * . +- * +- * Author: Bob Ham +- * +- * SPDX-License-Identifier: GPL-3.0-or-later +- * +- */ +- +-#pragma once +- +-#include +- +-G_BEGIN_DECLS +- +-gchar * mchk_read_machine (GError **error); +-gboolean mchk_check_machine (const gchar *param, +- const gchar *machine, +- gboolean *passed, +- GError **error); +- +-G_END_DECLS +diff --git a/subprojects/libmachine-check/meson.build b/subprojects/libmachine-check/meson.build +deleted file mode 100644 +index eb83c36..0000000 +--- a/subprojects/libmachine-check/meson.build ++++ /dev/null +@@ -1,81 +0,0 @@ +-# +-# Copyright (C) 2019 Purism SPC +-# +-# This file is part of libmachine-check. +-# +-# libmachine-check is free software: you can redistribute it and/or +-# modify it under the terms of the GNU General Public License as +-# published by the Free Software Foundation, either version 3 of the +-# License, or (at your option) any later version. +-# +-# libmachine-check 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 +-# General Public License for more details. +-# +-# You should have received a copy of the GNU General Public License +-# along with libmachine-check. If not, see +-# . +-# +-# SPDX-License-Identifier: GPL-3.0-or-later +-# +- +-project ( +- 'libmachine-check', +- 'c', +- version: '0.1.0', +- license: 'GPLv3+', +- default_options: +- [ +- 'warning_level=1', +- 'buildtype=debugoptimized', +- 'c_std=gnu11' +- ], +-) +- +-prefix = get_option('prefix') +-datadir = get_option('datadir') +-sysconfdir = get_option('sysconfdir') +- +-if datadir.startswith('/') +- full_datadir = datadir +-else +- full_datadir = join_paths(prefix, datadir) +-endif +- +-if sysconfdir.startswith('/') +- full_sysconfdir = sysconfdir +-else +- full_sysconfdir = join_paths(prefix, sysconfdir) +-endif +- +-config_data = configuration_data() +-config_data.set_quoted('DATADIR', full_datadir) +-config_data.set_quoted('SYSCONFDIR', full_sysconfdir) +- +-config_h = configure_file ( +- output: 'config.h', +- configuration: config_data +-) +- +-libmachine_check_deps = [ +- dependency('gio-unix-2.0'), +-] +- +-libmachine_check_inc = include_directories('.') +- +-libmachine_check = static_library ( +- 'machine-check', +- config_h, +- [ +- 'mchk-machine-check.h', 'mchk-machine-check.c', +- ], +- dependencies : libmachine_check_deps, +- include_directories : libmachine_check_inc, +-) +- +-libmachine_check_dep = declare_dependency ( +- dependencies: libmachine_check_deps, +- link_with: libmachine_check, +- include_directories: libmachine_check_inc, +-) +-- +2.26.2 diff --git a/temp/wys-pinephone/APKBUILD b/temp/wys-pinephone/APKBUILD new file mode 100644 index 000000000..bf75b5507 --- /dev/null +++ b/temp/wys-pinephone/APKBUILD @@ -0,0 +1,48 @@ +# Special package with additional patch to make it work on the pinephone. Can be removed +# once that's upstreamed to Purism or another solution has been implemented. +# +# differences with upsteam wys: +# * added patch for switching pulse profiles +# * added pulseaudio-utils dependency for pactl command +# Maintainer: Martijn Braam +pkgname=wys-pinephone +pkgver=0.1.7 +pkgrel=0 +pkgdesc="A daemon to bring up and take down PulseAudio loopbacks for phone call audio." +arch="all" +url="https://source.puri.sm/Librem5/wys" +license="GPL-3.0-or-later" +depends="pulseaudio-utils" +makedepends="meson pulseaudio-dev glib-dev modemmanager-dev" +source=" + $pkgname-$pkgver.tar.gz::https://source.puri.sm/Librem5/wys/-/archive/v$pkgver/wys-v$pkgver.tar.gz + 0001-Simplify-daemon-to-only-switch-card-profiles.patch + wys.desktop" + +builddir="$srcdir"/wys-v$pkgver + +build() { + meson \ + -Dprefix=$pkgdir/usr \ + -Dsysconfdir=$pkgdir/etc \ + -Dmandir=share/man \ + -Dlocalstatedir=$pkgdir/var \ + -Dbuildtype=plain \ + build + + ninja -C ./build +} + +check() { + ninja -C ./build test +} + +package() { + mkdir -p $pkgdir + ninja -C $builddir/build install + install -D -m644 $srcdir/wys.desktop $pkgdir/etc/xdg/autostart/wys.desktop +} + +sha512sums="81a9f97cced2ceee0823bf3e45bb8fd6b79d8ae6d8fb1b459f8a5e24ebde0884899924c5af601466317ff397246028aafeec97504179f54c78e83eee7f322437 wys-pinephone-0.1.7.tar.gz +ad825ad3e47f5cb7cc188ef845ed37654c591669d4d3b7733fd5242057a1b613618599f776ebe86d0c8ee6254c78b68a69f01e8b0483c31e302cec41700f92b6 0001-Simplify-daemon-to-only-switch-card-profiles.patch +0f67c24d9af727e803d5cdb2dc01c7d99a2bfe33414fdc29cf5ec34c5a308b3a5f65970832087310e25e4ba7dc706b5a1d1ae99ab595d7264e972047a08f71e4 wys.desktop" diff --git a/temp/wys-pinephone/wys.desktop b/temp/wys-pinephone/wys.desktop new file mode 100644 index 000000000..1284dc41f --- /dev/null +++ b/temp/wys-pinephone/wys.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Wys +Name[es]=Wys +Comment=Daemon for managing PulseAudio for phone call audio +Comment[es]=Demonio para manejar PulseAudio por audio de llamadas telefónicas +Exec=/usr/bin/wys +NoDisplay=true +Terminal=false +Type=Application +StartupNotify=true +X-GNOME-AutoRestart=true