From 15dd6b3cd089ced676a6dfd1f709a305ad40525e Mon Sep 17 00:00:00 2001 From: loki Date: Sat, 18 Jan 2020 00:58:27 +0100 Subject: [PATCH] Provide option to select the source for audio on Linux --- README.txt | 4 ++++ assets/sunshine.conf | 7 +++++++ sunshine/config.cpp | 4 ++++ sunshine/config.h | 5 +++++ sunshine/platform/linux.cpp | 12 ++++++++++-- 5 files changed, 30 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt index 5071b660..f3e07d10 100644 --- a/README.txt +++ b/README.txt @@ -75,6 +75,10 @@ Trouleshooting: * If you get "Could not create Sunshine Gamepad: Permission Denied" Try the following steps before running sunshine: * sudo chown root:input /dev/uinput * sudo chmod 660 /dev/uinput + * If Sunshine sends audio from the microphone instead of the speaker, try the following steps: + * pacmd list-sources | grep "name:" + * Copy the name to the configuration option "audio_sink" + * restart sunshine When an application is started, if there is an application already running, it will be terminated. When the application has been shutdown, the stream shuts down as well. diff --git a/assets/sunshine.conf b/assets/sunshine.conf index 45749b93..15237110 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -57,6 +57,13 @@ fec_percentage = 10 # If back_button_timeout < 0, then the Home/Guide button will not be emulated # back_button_timeout = 2000 +# The name of the audio sink used for Audio Loopback +# If you do not specify this variable, pulseaudio will select a default device, which could be a microphone instead of a speaker +# +# You can find the name of the audio sink using the following command: +# pacmd list-sources | grep "name:" +# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo.monitor + ############################################### # FFmpeg software encoding parameters diff --git a/sunshine/config.cpp b/sunshine/config.cpp index adee428b..6d2c315e 100644 --- a/sunshine/config.cpp +++ b/sunshine/config.cpp @@ -26,6 +26,8 @@ video_t video { "zerolatency"s // tune }; +audio_t audio {}; + stream_t stream { 2s, // ping_timeout @@ -172,6 +174,8 @@ void parse_file(const char *file) { string_f(vars, "file_devices", nvhttp.file_devices); string_f(vars, "external_ip", nvhttp.external_ip); + string_f(vars, "audio_sink", audio.sink); + string_restricted_f(vars, "origin_pin_allowed", nvhttp.origin_pin_allowed, { "pc"sv, "lan"sv, "wan"sv }); diff --git a/sunshine/config.h b/sunshine/config.h index 1fa7b13e..4b24655d 100644 --- a/sunshine/config.h +++ b/sunshine/config.h @@ -19,6 +19,10 @@ struct video_t { std::string tune; }; +struct audio_t { + std::string sink; +}; + struct stream_t { std::chrono::milliseconds ping_timeout; @@ -52,6 +56,7 @@ struct sunshine_t { }; extern video_t video; +extern audio_t audio; extern stream_t stream; extern nvhttp_t nvhttp; extern input_t input; diff --git a/sunshine/platform/linux.cpp b/sunshine/platform/linux.cpp index 40615d61..5630d20b 100644 --- a/sunshine/platform/linux.cpp +++ b/sunshine/platform/linux.cpp @@ -23,6 +23,7 @@ #include #include +#include namespace platf { using namespace std::literals; @@ -330,15 +331,22 @@ std::unique_ptr microphone(std::uint32_t sample_rate) { }; int status; + + const char *audio_sink = nullptr; + if(!config::audio.sink.empty()) { + audio_sink = config::audio.sink.c_str(); + } + mic->mic.reset( - pa_simple_new(nullptr, "sunshine", pa_stream_direction_t::PA_STREAM_RECORD, nullptr, "sunshine_record", &mic->ss, nullptr, nullptr, &status) + pa_simple_new(nullptr, "sunshine", pa_stream_direction_t::PA_STREAM_RECORD, audio_sink, "sunshine_record", &mic->ss, nullptr, nullptr, &status) ); if(!mic->mic) { auto err_str = pa_strerror(status); BOOST_LOG(error) << "pa_simple_new() failed: "sv << err_str; - exit(1); + log_flush(); + std::abort(); } return mic;