From b361080768fe3875a4b6831e1813668fcd648d92 Mon Sep 17 00:00:00 2001 From: Michael Zhang Date: Tue, 4 Apr 2023 12:46:12 -0500 Subject: [PATCH] Not sure why it's not being able to create the audio device --- .envrc | 1 + .gitignore | 4 + CMakeLists.txt | 29 ++++-- assets/userscript.js | 9 +- cmake/FindPipeWire.cmake | 125 +++++++++++++++++++++++++ compile_commands.json | 1 + default.nix | 27 ++++++ flake.lock | 41 ++++++++ flake.nix | 28 ++++++ nix/rohrkabel.nix | 22 +++++ nix/rohrkabel.patch | 37 ++++++++ src/virtmic.cpp | 3 + wrapper.sh | 196 +++++++++++++++++++++++++++++++++++++++ 13 files changed, 515 insertions(+), 8 deletions(-) create mode 100644 .envrc create mode 100644 cmake/FindPipeWire.cmake create mode 120000 compile_commands.json create mode 100644 default.nix create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/rohrkabel.nix create mode 100644 nix/rohrkabel.patch create mode 100755 wrapper.sh diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 6c21971..f0b1a68 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ /build .vscode /submodules/arrpc + +.direnv +/result* +/.cache diff --git a/CMakeLists.txt b/CMakeLists.txt index 48544ac..847ff85 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,14 @@ include(version.cmake) determine_version("${CMAKE_CURRENT_SOURCE_DIR}" DISCORD_SCEENAUDIO) add_definitions( -DDISCORD_SCEENAUDIO_VERSION_FULL="${DISCORD_SCEENAUDIO_VERSION_FULL}" ) +# Generate the `compile_commands.json` file. +set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") + +if(CMAKE_EXPORT_COMPILE_COMMANDS) + set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES + ${CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES}) +endif() + set(CMAKE_CXX_STANDARD 17) set(CMAKE_INCLUDE_CURRENT_DIR ON) set(CMAKE_AUTOMOC ON) @@ -13,6 +21,8 @@ set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG") string(TIMESTAMP TIMESTAMP %s) # set(CMAKE_AUTOUIC ON) +find_package(spdlog REQUIRED) + find_package(Qt5 COMPONENTS Widgets) if (Qt5_FOUND) find_package(Qt5 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets) @@ -36,6 +46,11 @@ else() find_package(Qt6 CONFIG REQUIRED COMPONENTS Widgets WebEngineWidgets) endif() +# Find Pipewire +list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) +find_package(PipeWire REQUIRED) +include_directories(SYSTEM ${PipeWire_INCLUDE_DIRS} ${Spa_INCLUDE_DIRS}) + set(discord-screenaudio_SRC src/main.cpp src/mainwindow.cpp @@ -63,15 +78,17 @@ if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") endif() endif() -if(NOT EXISTS "${PROJECT_SOURCE_DIR}/submodules/rohrkabel/CMakeLists.txt") - message(FATAL_ERROR "Rohrkabel was not found since you are not in a Git checkout or have GIT_SUBMODULE disabled. Please provide rohrkabel manually to `./submodules/rohrkabel`.") -endif() - -add_subdirectory(submodules/rohrkabel) +# if(NOT EXISTS "${PROJECT_SOURCE_DIR}/submodules/rohrkabel/CMakeLists.txt") +# message(FATAL_ERROR "Rohrkabel was not found since you are not in a Git checkout or have GIT_SUBMODULE disabled. Please provide rohrkabel manually to `./submodules/rohrkabel`.") +# endif() +# +# add_subdirectory(submodules/rohrkabel) add_executable(discord-screenaudio ${discord-screenaudio_SRC}) -target_link_libraries(discord-screenaudio Qt::Widgets Qt::WebEngineWidgets rohrkabel) +target_link_libraries(discord-screenaudio Qt::Widgets Qt::WebEngineWidgets + rohrkabel spdlog::spdlog) +target_link_libraries(discord-screenaudio ${PipeWire_LIBRARIES}) if(KF5Notifications_FOUND) target_link_libraries(discord-screenaudio KF5::Notifications) diff --git a/assets/userscript.js b/assets/userscript.js index 72e0352..864f7ec 100644 --- a/assets/userscript.js +++ b/assets/userscript.js @@ -12,12 +12,17 @@ const getAudioDevice = async (nameOfAudioDevice) => { let audioDevice; while (audioDevice === undefined) { let devices = await navigator.mediaDevices.enumerateDevices(); + for (let device of devices) { + console.dir(device.label, device); + } audioDevice = devices.find(({ label }) => label === nameOfAudioDevice); + + const sleepTime = 500; if (!audioDevice) userscript.log( - `Did not find '${nameOfAudioDevice}', trying again in 100ms` + `Did not find '${nameOfAudioDevice}', trying again in ${sleepTime}ms` ); - await sleep(100); + await sleep(sleepTime); } userscript.log(`Found '${nameOfAudioDevice}'`); return audioDevice; diff --git a/cmake/FindPipeWire.cmake b/cmake/FindPipeWire.cmake new file mode 100644 index 0000000..38c626d --- /dev/null +++ b/cmake/FindPipeWire.cmake @@ -0,0 +1,125 @@ +# Code licensed under GPL-3.0 +# https://github.com/Soundux/Soundux/blob/master/FindPipeWire.cmake + +#.rst: +# FindPipeWire +# ------- +# +# Try to find PipeWire on a Unix system. +# +# This will define the following variables: +# +# ``PipeWire_FOUND`` +# True if (the requested version of) PipeWire is available +# ``PipeWire_VERSION`` +# The version of PipeWire +# ``PipeWire_LIBRARIES`` +# This can be passed to target_link_libraries() instead of the ``PipeWire::PipeWire`` +# target +# ``PipeWire_INCLUDE_DIRS`` +# This should be passed to target_include_directories() if the target is not +# used for linking +# ``PipeWire_DEFINITIONS`` +# This should be passed to target_compile_options() if the target is not +# used for linking +# +# If ``PipeWire_FOUND`` is TRUE, it will also define the following imported target: +# +# ``PipeWire::PipeWire`` +# The PipeWire library +# +# In general we recommend using the imported target, as it is easier to use. +# Bear in mind, however, that if the target is in the link interface of an +# exported library, it must be made available by the package config file. + +#============================================================================= +# Copyright 2014 Alex Merry +# Copyright 2014 Martin Gräßlin +# Copyright 2018-2020 Jan Grulich +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#============================================================================= + +# Use pkg-config to get the directories and then use these values +# in the FIND_PATH() and FIND_LIBRARY() calls +find_package(PkgConfig QUIET) + +pkg_search_module(PKG_PipeWire QUIET libpipewire-0.3 libpipewire-0.2) +pkg_search_module(PKG_Spa QUIET libspa-0.2 libspa-0.1) + +set(PipeWire_DEFINITIONS "${PKG_PipeWire_CFLAGS}" "${PKG_Spa_CFLAGS}") +set(PipeWire_VERSION "${PKG_PipeWire_VERSION}") + +find_path(PipeWire_INCLUDE_DIRS + NAMES + pipewire/pipewire.h + HINTS + ${PKG_PipeWire_INCLUDE_DIRS} + ${PKG_PipeWire_INCLUDE_DIRS}/pipewire-0.3 +) + +find_path(Spa_INCLUDE_DIRS + NAMES + spa/param/props.h + HINTS + ${PKG_Spa_INCLUDE_DIRS} + ${PKG_Spa_INCLUDE_DIRS}/spa-0.2 +) + +find_library(PipeWire_LIBRARIES + NAMES + pipewire-0.3 + pipewire-0.2 + HINTS + ${PKG_PipeWire_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PipeWire + FOUND_VAR + PipeWire_FOUND + REQUIRED_VARS + PipeWire_LIBRARIES + PipeWire_INCLUDE_DIRS + Spa_INCLUDE_DIRS + VERSION_VAR + PipeWire_VERSION +) + +if(PipeWire_FOUND AND NOT TARGET PipeWire::PipeWire) + add_library(PipeWire::PipeWire UNKNOWN IMPORTED) + set_target_properties(PipeWire::PipeWire PROPERTIES + IMPORTED_LOCATION "${PipeWire_LIBRARIES}" + INTERFACE_COMPILE_OPTIONS "${PipeWire_DEFINITIONS}" + INTERFACE_INCLUDE_DIRECTORIES "${PipeWire_INCLUDE_DIRS};${Spa_INCLUDE_DIRS}" + ) +endif() + +mark_as_advanced(PipeWire_LIBRARIES PipeWire_INCLUDE_DIRS) + +include(FeatureSummary) +set_package_properties(PipeWire PROPERTIES + URL "https://www.pipewire.org" + DESCRIPTION "PipeWire - multimedia processing" +) diff --git a/compile_commands.json b/compile_commands.json new file mode 120000 index 0000000..25eb4b2 --- /dev/null +++ b/compile_commands.json @@ -0,0 +1 @@ +build/compile_commands.json \ No newline at end of file diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..7e636da --- /dev/null +++ b/default.nix @@ -0,0 +1,27 @@ +{ stdenv, lib, cmake, ninja, libsForQt5, fetchFromGitHub, pkg-config, pipewire +, rohrkabel, tl-expected, spdlog }: + +with libsForQt5; +with libsForQt5.qt5; + +stdenv.mkDerivation rec { + pname = "discord-screenaudio"; + version = "1.7.1"; + + nativeBuildInputs = [ cmake ninja wrapQtAppsHook pkg-config ]; + buildInputs = [ + qtbase + qtwebengine + knotifications + kxmlgui + kglobalaccel + pipewire + rohrkabel + tl-expected + spdlog + ]; + + src = ./.; + + cmakeFlags = [ ]; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..f009578 --- /dev/null +++ b/flake.lock @@ -0,0 +1,41 @@ +{ + "nodes": { + "flake-utils": { + "locked": { + "lastModified": 1678901627, + "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6", + "type": "github" + }, + "original": { + "id": "flake-utils", + "type": "indirect" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1680623651, + "narHash": "sha256-gpLjYWQlSkjiIRPwzO9b3LSeQXbK7GM+ssTdAnt4xaM=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "1f6987ce7e4a1c88d3b38ff568a81822ed2c27e9", + "type": "github" + }, + "original": { + "owner": "nixos", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..94f92b3 --- /dev/null +++ b/flake.nix @@ -0,0 +1,28 @@ +{ + inputs = { nixpkgs.url = "github:nixos/nixpkgs"; }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + + flakePkgs = rec { + rohrkabel = pkgs.callPackage ./nix/rohrkabel.nix { }; + discord-screenaudio = pkgs.callPackage ./. { inherit rohrkabel; }; + }; + in rec { + packages = flake-utils.lib.flattenTree flakePkgs; + + defaultPackage = packages.discord-screenaudio; + + legacyPackages = pkgs; + + devShell = pkgs.mkShell { + inputsFrom = with flakePkgs; [ discord-screenaudio ]; + + packages = (with pkgs; [ pipewire.pulse clang-tools ]); + + PKG_CONFIG_PATH = with pkgs; "${pipewire.dev}/lib/pkgconfig"; + }; + }); +} diff --git a/nix/rohrkabel.nix b/nix/rohrkabel.nix new file mode 100644 index 0000000..4397904 --- /dev/null +++ b/nix/rohrkabel.nix @@ -0,0 +1,22 @@ +{ stdenv, lib, cmake, ninja, pkg-config, pipewire, fetchFromGitHub, tl-expected +}: + +stdenv.mkDerivation rec { + pname = "rohrkabel"; + version = "04bfb921c44fb0d2337df70f5660899bc8d2844f"; + + src = fetchFromGitHub { + owner = "Soundux"; + repo = pname; + rev = version; + sha256 = "sha256-8VEvieSEn021mZAtw1JoNg+Oxe3Zap4jMcP+RDgqWEU="; + fetchSubmodules = true; + }; + + nativeBuildInputs = [ cmake ninja pkg-config ]; + buildInputs = [ pipewire tl-expected ]; + + patches = [ ./rohrkabel.patch ]; + + cmakeFlags = [ "-Drohrkabel_prefer_remote=0" ]; +} diff --git a/nix/rohrkabel.patch b/nix/rohrkabel.patch new file mode 100644 index 0000000..e2ff956 --- /dev/null +++ b/nix/rohrkabel.patch @@ -0,0 +1,37 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 3729d3b..b8fede0 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -1,6 +1,10 @@ + cmake_minimum_required(VERSION 3.1) + project(rohrkabel LANGUAGES CXX VERSION 1.2) + ++include(CMakePackageConfigHelpers) ++include(CMakeDependentOption) ++include(GNUInstallDirs) ++ + # -------------------------------------------------------------------------------------------------------- + # Library options + # -------------------------------------------------------------------------------------------------------- +@@ -75,4 +79,9 @@ endif() + # -------------------------------------------------------------------------------------------------------- + + install(DIRECTORY "include/" TYPE INCLUDE) +-install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib INCLUDES DESTINATION include) +\ No newline at end of file ++install(TARGETS ${PROJECT_NAME} LIBRARY DESTINATION lib INCLUDES DESTINATION include) ++ ++configure_package_config_file( ++ "${PROJECT_SOURCE_DIR}/cmake/${PROJECT_NAME}-config.cmake.in" ++ "${PROJECT_BINARY_DIR}/${PROJECT_NAME}-config.cmake" ++ INSTALL_DESTINATION "share/cmake/${PROJECT_NAME}") +diff --git a/cmake/rohrkabel-config.cmake.in b/cmake/rohrkabel-config.cmake.in +new file mode 100644 +index 0000000..57ffe6c +--- /dev/null ++++ b/cmake/rohrkabel-config.cmake.in +@@ -0,0 +1,4 @@ ++@PACKAGE_INIT@ ++ ++include("${CMAKE_CURRENT_LIST_DIR}/rohrkabel-targets.cmake") ++ diff --git a/src/virtmic.cpp b/src/virtmic.cpp index ba29b09..535d73f 100644 --- a/src/virtmic.cpp +++ b/src/virtmic.cpp @@ -3,6 +3,7 @@ #include #include +#include namespace Virtmic { @@ -101,6 +102,7 @@ void start(QString _target) { std::string target = _target.toUtf8().toStdString(); + spdlog::info("Starting virtual mic..."); auto virtual_mic = core.create("adapter", {{"node.name", "discord-screenaudio-virtmic"}, {"media.class", "Audio/Source/Virtual"}, @@ -109,6 +111,7 @@ void start(QString _target) { {"audio.position", "FL,FR"}}, pipewire::node::type, pipewire::node::version, pipewire::update_strategy::none); + spdlog::info("Started."); if (target == "[None]") { while (true) { diff --git a/wrapper.sh b/wrapper.sh new file mode 100755 index 0000000..3da6ff7 --- /dev/null +++ b/wrapper.sh @@ -0,0 +1,196 @@ +#! /nix/store/0hx32wk55ml88jrb1qxwg5c5yazfm6gf-bash-5.2-p15/bin/bash -e +# +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/vjpm4nyl36fvw8pswzfzlfayw1c06135-qtbase-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/vjpm4nyl36fvw8pswzfzlfayw1c06135-qtbase-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/zignpsx1fzc19ni9qvxl56r69ryg297k-qtsvg-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/zignpsx1fzc19ni9qvxl56r69ryg297k-qtsvg-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/37w0qxwd3z1kgzxqjdgsfiafzbnkiyvl-qtdeclarative-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/37w0qxwd3z1kgzxqjdgsfiafzbnkiyvl-qtdeclarative-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/37w0qxwd3z1kgzxqjdgsfiafzbnkiyvl-qtdeclarative-5.15.8-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/37w0qxwd3z1kgzxqjdgsfiafzbnkiyvl-qtdeclarative-5.15.8-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/64pxx6j8irw6p1cqk6qg12daipn5bqa9-qtquickcontrols-5.15.8/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/64pxx6j8irw6p1cqk6qg12daipn5bqa9-qtquickcontrols-5.15.8/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/j2bkrmyr4wwm3d0h1rj6aqrpmn2ilxcc-qtwayland-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/j2bkrmyr4wwm3d0h1rj6aqrpmn2ilxcc-qtwayland-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/j2bkrmyr4wwm3d0h1rj6aqrpmn2ilxcc-qtwayland-5.15.8-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/j2bkrmyr4wwm3d0h1rj6aqrpmn2ilxcc-qtwayland-5.15.8-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/pxzcwyv1h4gzz6b83w8m42dxijav28nk-qtmultimedia-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/pxzcwyv1h4gzz6b83w8m42dxijav28nk-qtmultimedia-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/pxzcwyv1h4gzz6b83w8m42dxijav28nk-qtmultimedia-5.15.8-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/pxzcwyv1h4gzz6b83w8m42dxijav28nk-qtmultimedia-5.15.8-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/gx4hvma9030ny3gya15qzh4d7fk7vnzb-qtlocation-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/gx4hvma9030ny3gya15qzh4d7fk7vnzb-qtlocation-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/gx4hvma9030ny3gya15qzh4d7fk7vnzb-qtlocation-5.15.8-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/gx4hvma9030ny3gya15qzh4d7fk7vnzb-qtlocation-5.15.8-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/16sx3y9v1rls5pys2hp0ayflh7pnq00m-qtwebchannel-5.15.8-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/16sx3y9v1rls5pys2hp0ayflh7pnq00m-qtwebchannel-5.15.8-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/7vg5c0xd2zm574nh1qlbm29nqi5g76ad-qtwebengine-5.15.12-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/7vg5c0xd2zm574nh1qlbm29nqi5g76ad-qtwebengine-5.15.12-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/7vg5c0xd2zm574nh1qlbm29nqi5g76ad-qtwebengine-5.15.12-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/7vg5c0xd2zm574nh1qlbm29nqi5g76ad-qtwebengine-5.15.12-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/cvq0bhrfwnzcwp817gfrcafjby8838wy-qttools-5.15.8-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/cvq0bhrfwnzcwp817gfrcafjby8838wy-qttools-5.15.8-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/78b2qipixnrh0mwj45kykib463ksx82l-kwindowsystem-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/78b2qipixnrh0mwj45kykib463ksx82l-kwindowsystem-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/vay1grhhii2aqbad016gy3n95lbs8v11-phonon-4.11.1/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/vay1grhhii2aqbad016gy3n95lbs8v11-phonon-4.11.1/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/3nsb3ssilgr6sdcb1w6ilm5zibq80rb1-knotifications-5.104.0-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/3nsb3ssilgr6sdcb1w6ilm5zibq80rb1-knotifications-5.104.0-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/9yipd31s6vh1aj1i7q99bmhrcjqavqcr-kauth-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/9yipd31s6vh1aj1i7q99bmhrcjqavqcr-kauth-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/w712vgxb70jlpg6d7xa355pwlqg9k598-kwidgetsaddons-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/w712vgxb70jlpg6d7xa355pwlqg9k598-kwidgetsaddons-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/0ba5i8d64gwd3kcz47xjhaay5g5yzba2-ki18n-5.104.0-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/0ba5i8d64gwd3kcz47xjhaay5g5yzba2-ki18n-5.104.0-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/0ba5i8d64gwd3kcz47xjhaay5g5yzba2-ki18n-5.104.0-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/0ba5i8d64gwd3kcz47xjhaay5g5yzba2-ki18n-5.104.0-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/z7v6xihgdh76a9l9ihygakkd22h6h8r5-kconfigwidgets-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/z7v6xihgdh76a9l9ihygakkd22h6h8r5-kconfigwidgets-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/xz8bgfsx95i1y7hzrjf7wvdj67cjscbl-kglobalaccel-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/xz8bgfsx95i1y7hzrjf7wvdj67cjscbl-kglobalaccel-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/2k75mcjl6r388kaj08dyirc1zcrjbklw-kitemviews-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/2k75mcjl6r388kaj08dyirc1zcrjbklw-kitemviews-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/pvpq17zhzf0b6ia38dlx97lq9wdv2zjw-kiconthemes-5.104.0-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/pvpq17zhzf0b6ia38dlx97lq9wdv2zjw-kiconthemes-5.104.0-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/i4zrvicamgqiprahr53q9qkpr7cvd5i5-sonnet-5.104.0-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/i4zrvicamgqiprahr53q9qkpr7cvd5i5-sonnet-5.104.0-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH:+':'$QML2_IMPORT_PATH':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH/':''/nix/store/i4zrvicamgqiprahr53q9qkpr7cvd5i5-sonnet-5.104.0-bin/lib/qt-5.15.8/qml'':'/':'} +QML2_IMPORT_PATH='/nix/store/i4zrvicamgqiprahr53q9qkpr7cvd5i5-sonnet-5.104.0-bin/lib/qt-5.15.8/qml'$QML2_IMPORT_PATH +QML2_IMPORT_PATH=${QML2_IMPORT_PATH#':'} +QML2_IMPORT_PATH=${QML2_IMPORT_PATH%':'} +export QML2_IMPORT_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/42j1zdpwxvlmh4l41jx724rljymc0x4k-kcompletion-5.104.0/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/42j1zdpwxvlmh4l41jx724rljymc0x4k-kcompletion-5.104.0/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/6azxpdxkai8hlbzpczk829ynvggk27yb-ktextwidgets-5.104.0-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/6azxpdxkai8hlbzpczk829ynvggk27yb-ktextwidgets-5.104.0-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH:+':'$QT_PLUGIN_PATH':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH/':''/nix/store/nprrb489zby9124i509p2z8x8b56lwgj-kxmlgui-5.104.0-bin/lib/qt-5.15.8/plugins'':'/':'} +QT_PLUGIN_PATH='/nix/store/nprrb489zby9124i509p2z8x8b56lwgj-kxmlgui-5.104.0-bin/lib/qt-5.15.8/plugins'$QT_PLUGIN_PATH +QT_PLUGIN_PATH=${QT_PLUGIN_PATH#':'} +QT_PLUGIN_PATH=${QT_PLUGIN_PATH%':'} +export QT_PLUGIN_PATH +XDG_DATA_DIRS=${XDG_DATA_DIRS:+':'$XDG_DATA_DIRS':'} +XDG_DATA_DIRS=${XDG_DATA_DIRS/':''/nix/store/nkbwh1b9vihhcqwz2ln00rm8hfdpjgs0-discord-screenaudio-1.7.1/share'':'/':'} +XDG_DATA_DIRS='/nix/store/nkbwh1b9vihhcqwz2ln00rm8hfdpjgs0-discord-screenaudio-1.7.1/share'$XDG_DATA_DIRS +XDG_DATA_DIRS=${XDG_DATA_DIRS#':'} +XDG_DATA_DIRS=${XDG_DATA_DIRS%':'} +export XDG_DATA_DIRS + +exec "$@"