/* * Copyright 2018-2021 Wim Taymans * Copyright 2021 Collabora Ltd. * * SPDX-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include "wrap-pipewire.h" /* From Pipewire 0.3.27 */ #define PW_DEFAULT_REMOTE "pipewire-0" #define DEFAULT_SYSTEM_RUNTIME_DIR "/run/pipewire" /* Adapted from Pipewire 0.3.27 */ static const char * get_remote (void) { const char *name = NULL; name = getenv("PIPEWIRE_REMOTE"); if (name == NULL || name[0] == '\0') name = PW_DEFAULT_REMOTE; return name; } /* Adapted from Pipewire 0.3.27 */ static const char * get_runtime_dir (void) { const char *runtime_dir; runtime_dir = g_getenv ("PIPEWIRE_RUNTIME_DIR"); if (runtime_dir == NULL) runtime_dir = g_getenv ("XDG_RUNTIME_DIR"); if (runtime_dir == NULL) runtime_dir = g_getenv ("HOME"); if (runtime_dir == NULL) runtime_dir = g_getenv ("USERPROFILE"); if (runtime_dir == NULL) runtime_dir = g_get_home_dir (); return runtime_dir; } void pv_wrap_add_pipewire_args (FlatpakBwrap *sharing_bwrap, PvEnviron *container_env) { g_autoptr(GDir) dir = NULL; const char *remote = get_remote (); const char *runtime_dir = get_runtime_dir (); const char *member; /* Make Pipewire look in the container's XDG_RUNTIME_DIR */ pv_environ_lock_env (container_env, "PIPEWIRE_RUNTIME_DIR", NULL); if (g_file_test (DEFAULT_SYSTEM_RUNTIME_DIR, G_FILE_TEST_IS_DIR)) flatpak_bwrap_add_args (sharing_bwrap, "--ro-bind", DEFAULT_SYSTEM_RUNTIME_DIR, DEFAULT_SYSTEM_RUNTIME_DIR, NULL); dir = g_dir_open (runtime_dir, 0, NULL); if (dir == NULL) return; for (member = g_dir_read_name (dir); member != NULL; member = g_dir_read_name (dir)) { /* Assume that anything starting with pipewire- is a (default or * extra) Pipewire socket */ if (g_str_has_prefix (member, "pipewire-")) { g_autofree gchar *host_socket = g_build_filename (runtime_dir, member, NULL); g_autofree gchar *container_socket = g_strdup_printf ("/run/user/%d/%s", getuid (), member); flatpak_bwrap_add_args (sharing_bwrap, "--ro-bind", host_socket, container_socket, NULL); } } if (!g_str_has_prefix (remote, "pipewire-")) { /* If the configured Pipewire socket is something weird, remap it * to be named pv-pipewire to avoid colliding with anything else */ g_autofree gchar *host_socket = g_build_filename (runtime_dir, remote, NULL); if (g_file_test (host_socket, G_FILE_TEST_EXISTS)) { g_autofree gchar *container_socket = g_strdup_printf ("/run/user/%d/pv-pipewire", getuid ()); pv_environ_lock_env (container_env, "PIPEWIRE_REMOTE", "pv-pipewire"); flatpak_bwrap_add_args (sharing_bwrap, "--ro-bind", host_socket, container_socket, NULL); } else { pv_environ_lock_env (container_env, "PIPEWIRE_REMOTE", NULL); } } }