diff --git a/changelog.md b/changelog.md index bd62475d..76cc3455 100644 --- a/changelog.md +++ b/changelog.md @@ -12,6 +12,7 @@ - Server: Check open syscall error in PipeStream::do_connect (PR #1150) - Server: Tweak Airplay support (#1102) - Server: Lower log severity for shairport-sync (Issue #891) +- Server: Emits notifications for streams with codec=null (Issue #1205) - Improve connect handling in meta_mopidy.py - Fix cppcheck issues @@ -20,7 +21,7 @@ - CI: Build debian bookworm and bullseye packages for amd64, arm and arm64 - CI: Add cppcheck static analysis - Update documentation (PR #1130, PR #1067) -- Delete deprecated Makefiles, CMake is the only buildsystem +- Delete deprecated Makefiles, CMake is the only supported buildsystem - Snapweb: Update to v0.7.0 _Johannes Pohl Sun, 24 Mar 2024 00:13:37 +0200_ diff --git a/server/encoder/null_encoder.hpp b/server/encoder/null_encoder.hpp index 58fee4ae..f39214ba 100644 --- a/server/encoder/null_encoder.hpp +++ b/server/encoder/null_encoder.hpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2020 Johannes Pohl + Copyright (C) 2014-2024 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -23,6 +23,15 @@ namespace encoder { +/// Null Encoder class +/** + * Dummy encoder that will not encode any PcmChunk and thus will also never call + * "Encoder::encoded_callback_", i.e. the "OnEncodedCallback" to report any encoded data + * to the listener. + * Typically used as input stream for a MetaStream, which will do it's own encoding. + * Streams that use the null encoder cannot be listened to directly, nor they are visible + * on the RPC interface. + */ class NullEncoder : public Encoder { public: diff --git a/server/streamreader/stream_manager.cpp b/server/streamreader/stream_manager.cpp index 2b9a82d4..05fb6534 100644 --- a/server/streamreader/stream_manager.cpp +++ b/server/streamreader/stream_manager.cpp @@ -1,6 +1,6 @@ /*** This file is part of snapcast - Copyright (C) 2014-2022 Johannes Pohl + Copyright (C) 2014-2024 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -77,22 +77,31 @@ PcmStreamPtr StreamManager::addStream(StreamUri& streamUri) // LOG(DEBUG) << "key: '" << kv.first << "' value: '" << kv.second << "'\n"; PcmStreamPtr stream(nullptr); + PcmStream::Listener* listener = pcmListener_; + if ((streamUri.query[kUriCodec] == "null") && (streamUri.scheme != "meta")) + { + // Streams with null codec are "invisible" and will not report any updates to the listener. + // If the stream is used as input for a Meta stream, then the meta stream will add himself + // as another listener to the stream, so that updates are indirect reported through it. + listener = nullptr; + } + if (streamUri.scheme == "pipe") { - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } else if (streamUri.scheme == "file") { - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } else if (streamUri.scheme == "process") { - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } #ifdef HAS_ALSA else if (streamUri.scheme == "alsa") { - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } #endif else if ((streamUri.scheme == "spotify") || (streamUri.scheme == "librespot")) @@ -101,7 +110,7 @@ PcmStreamPtr StreamManager::addStream(StreamUri& streamUri) // that all constructors of all parent classes also use the overwritten sample // format. streamUri.query[kUriSampleFormat] = "44100:16:2"; - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } else if (streamUri.scheme == "airplay") { @@ -109,15 +118,15 @@ PcmStreamPtr StreamManager::addStream(StreamUri& streamUri) // that all constructors of all parent classes also use the overwritten sample // format. streamUri.query[kUriSampleFormat] = "44100:16:2"; - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } else if (streamUri.scheme == "tcp") { - stream = make_shared(pcmListener_, io_context_, settings_, streamUri); + stream = make_shared(listener, io_context_, settings_, streamUri); } else if (streamUri.scheme == "meta") { - stream = make_shared(pcmListener_, streams_, io_context_, settings_, streamUri); + stream = make_shared(listener, streams_, io_context_, settings_, streamUri); } else { @@ -210,8 +219,11 @@ json StreamManager::toJson() const { json result = json::array(); for (const auto& stream : streams_) + { + // A stream with "null" codec will only serve as input for a meta stream, i.e. is not a "stand alone" stream if (stream->getCodec() != "null") result.push_back(stream->toJson()); + } return result; }