From 60dc1aa48a798fd5eb3d8936184fc4c31b53079f Mon Sep 17 00:00:00 2001 From: badaix Date: Wed, 13 Jul 2022 14:14:00 +0200 Subject: [PATCH] Add support for controlscriptparams --- doc/configuration.md | 3 ++- doc/json_rpc_api/stream_plugin.md | 1 + server/etc/snapserver.conf | 3 ++- server/snapserver.cpp | 4 ++-- server/streamreader/pcm_stream.cpp | 11 +++++++---- server/streamreader/pcm_stream.hpp | 1 + server/streamreader/stream_control.cpp | 8 +++++++- server/streamreader/stream_control.hpp | 3 ++- 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/doc/configuration.md b/doc/configuration.md index 477723f9..50ac60c7 100644 --- a/doc/configuration.md +++ b/doc/configuration.md @@ -13,7 +13,7 @@ The following notation is used in this paragraph: The general format of an audio source is: ```sh -TYPE://host/path?name=[&codec=][&sampleformat=][&chunk_ms=][&controlscript=] +TYPE://host/path?name=[&codec=][&sampleformat=][&chunk_ms=][&controlscript=[&controlscriptparams=]] ``` Within the `[stream]` section there are some global parameters valid for all `source`s: @@ -37,6 +37,7 @@ Supported parameters for all source types: - `chunk_ms`: Override the global `chunk_ms` - `dryout_ms`: Supported by non-blocking sourced: when no new data is read from the source, send silence to the clients - `controlscript`: Script to control the stream source and read and provide meta data, see [stream_plugin.md](json_rpc_api/stream_plugin.md) +- `controlscriptparams`: Control script command line arguments, must be url-encoded (use `%20` instead of a space ` `), e.g. `--mopidy-host=192.168.42.23%20--debug` Available audio source types are: diff --git a/doc/json_rpc_api/stream_plugin.md b/doc/json_rpc_api/stream_plugin.md index 9c2ac7bb..5eeae05e 100644 --- a/doc/json_rpc_api/stream_plugin.md +++ b/doc/json_rpc_api/stream_plugin.md @@ -11,6 +11,7 @@ source = pipe:///tmp/snapfifo?name=MPD&controlscript=meta_mpd.py ``` If a relative path is given, Snapserver will search the script in `/usr/share/snapserver/plug-ins`. An example script `meta_mpd.py` is shipped with the server installation, that can be used with mpd stream sources. +Paramters are passed to the control script using the `controlscriptparams` stream source parameter. A Stream plugin must support and handle the following [requests](#requests), sent by the Snapcast server diff --git a/server/etc/snapserver.conf b/server/etc/snapserver.conf index e68a78d8..74029060 100644 --- a/server/etc/snapserver.conf +++ b/server/etc/snapserver.conf @@ -114,7 +114,7 @@ doc_root = /usr/share/snapserver/snapweb # [square brackets]: the whole expression is optional and can be left out # [key=value]: if you leave this option out, "value" will be the default for "key" # -# Format: TYPE://host/path?name=[&codec=][&sampleformat=][&chunk_ms=][&controlscript=] +# Format: TYPE://host/path?name=[&codec=][&sampleformat=][&chunk_ms=][&controlscript=[&controlscriptparams=]] # parameters have the form "key=value", they are concatenated with an "&" character # parameter "name" is mandatory for all sources, while codec, sampleformat and chunk_ms are optional # and will override the default codec, sampleformat or chunk_ms settings @@ -157,6 +157,7 @@ source = pipe:///tmp/snapfifo?name=default #send_to_muted = false # + # Streaming client options #################################################### # [streaming_client] diff --git a/server/snapserver.cpp b/server/snapserver.cpp index da633b58..51b6c417 100644 --- a/server/snapserver.cpp +++ b/server/snapserver.cpp @@ -119,8 +119,8 @@ int main(int argc, char* argv[]) &settings.stream.sendAudioToMutedClients); // streaming_client options - conf.add>("", "streaming_client.initial_volume", "Volume [percent] assigned to new streaming clients", settings.streamingclient.initialVolume, - &settings.streamingclient.initialVolume); + conf.add>("", "streaming_client.initial_volume", "Volume [percent] assigned to new streaming clients", + settings.streamingclient.initialVolume, &settings.streamingclient.initialVolume); // logging settings conf.add>("", "logging.sink", "log sink [null,system,stdout,stderr,file:]", settings.logging.sink, &settings.logging.sink); diff --git a/server/streamreader/pcm_stream.cpp b/server/streamreader/pcm_stream.cpp index e1217fb7..290e7a01 100644 --- a/server/streamreader/pcm_stream.cpp +++ b/server/streamreader/pcm_stream.cpp @@ -64,7 +64,10 @@ PcmStream::PcmStream(PcmStream::Listener* pcmListener, boost::asio::io_context& if (uri_.query.find(kControlScript) != uri_.query.end()) { - stream_ctrl_ = std::make_unique(strand_, uri_.query[kControlScript]); + std::string params; + if (uri_.query.find(kControlScriptParams) != uri_.query.end()) + params = uri_.query[kControlScriptParams]; + stream_ctrl_ = std::make_unique(strand_, uri_.query[kControlScript], params); } if (uri_.query.find(kUriChunkMs) != uri_.query.end()) @@ -442,7 +445,7 @@ void PcmStream::sendRequest(const std::string& method, const jsonrpcpp::Paramete jsonrpcpp::Request req(++req_id_, method, params); stream_ctrl_->command(req, [handler](const jsonrpcpp::Response& response) { - if (response.error().code()) + if (response.error().code() != 0) handler({static_cast(response.error().code()), response.error().data()}); else handler({ControlErrc::success}); @@ -463,7 +466,7 @@ void PcmStream::setProperties(const Properties& properties) if (props.metadata.has_value() && props.metadata->art_data.has_value() && !props.metadata->art_url.has_value()) { auto data = base64_decode(props.metadata->art_data->data); - auto md5 = server_settings_.http.image_cache.setImage(getName(), std::move(data), props.metadata->art_data->extension); + auto md5 = ServerSettings::Http::image_cache.setImage(getName(), std::move(data), props.metadata->art_data->extension); std::stringstream url; url << "http://" << server_settings_.http.host << ":" << server_settings_.http.port << "/__image_cache?name=" << md5; @@ -471,7 +474,7 @@ void PcmStream::setProperties(const Properties& properties) } else if (!props.metadata.has_value() || !props.metadata->art_data.has_value()) { - server_settings_.http.image_cache.clear(getName()); + ServerSettings::Http::image_cache.clear(getName()); } if (props == properties_) diff --git a/server/streamreader/pcm_stream.hpp b/server/streamreader/pcm_stream.hpp index 29839e83..75a868a9 100644 --- a/server/streamreader/pcm_stream.hpp +++ b/server/streamreader/pcm_stream.hpp @@ -91,6 +91,7 @@ static constexpr auto kUriName = "name"; static constexpr auto kUriSampleFormat = "sampleformat"; static constexpr auto kUriChunkMs = "chunk_ms"; static constexpr auto kControlScript = "controlscript"; +static constexpr auto kControlScriptParams = "controlscriptparams"; /// Reads and decodes PCM data diff --git a/server/streamreader/stream_control.cpp b/server/streamreader/stream_control.cpp index 8393bdde..a4b9407d 100644 --- a/server/streamreader/stream_control.cpp +++ b/server/streamreader/stream_control.cpp @@ -140,7 +140,8 @@ void StreamControl::onLog(std::string message) -ScriptStreamControl::ScriptStreamControl(const boost::asio::any_io_executor& executor, const std::string& script) : StreamControl(executor), script_(script) +ScriptStreamControl::ScriptStreamControl(const boost::asio::any_io_executor& executor, const std::string& script, const std::string& params) + : StreamControl(executor), script_(script), params_(params) { namespace fs = utils::file; if (!fs::exists(script_)) @@ -159,9 +160,14 @@ void ScriptStreamControl::doStart(const std::string& stream_id, const ServerSett pipe_stderr_ = bp::pipe(); pipe_stdout_ = bp::pipe(); stringstream params; + params << " " << params_; params << " \"--stream=" + stream_id + "\""; if (server_setttings.http.enabled) + { params << " --snapcast-port=" << server_setttings.http.port; + params << " --snapcast-host=" << server_setttings.http.host; + } + LOG(DEBUG, LOG_TAG) << "Starting control script: '" << script_ << "', params: '" << params.str() << "'\n"; try { process_ = bp::child( diff --git a/server/streamreader/stream_control.hpp b/server/streamreader/stream_control.hpp index 4793d595..872a9bf3 100644 --- a/server/streamreader/stream_control.hpp +++ b/server/streamreader/stream_control.hpp @@ -87,7 +87,7 @@ private: class ScriptStreamControl : public StreamControl { public: - ScriptStreamControl(const boost::asio::any_io_executor& executor, const std::string& script); + ScriptStreamControl(const boost::asio::any_io_executor& executor, const std::string& script, const std::string& params); virtual ~ScriptStreamControl() = default; void stop() override; @@ -109,6 +109,7 @@ protected: boost::asio::streambuf streambuf_stderr_; std::string script_; + std::string params_; bp::opstream in_; };