output/snapcast: Zeroconf support

This commit is contained in:
Max Kellermann 2021-02-23 22:12:43 +01:00
parent e4fccc85c8
commit 7a68775e6c
5 changed files with 37 additions and 3 deletions

View File

@ -1167,6 +1167,9 @@ connect to it and receive audio data from MPD.
- Binds the Snapcast server to the specified address. Multiple - Binds the Snapcast server to the specified address. Multiple
addresses in parallel are not supported. The default is to addresses in parallel are not supported. The default is to
bind on all addresses on port :samp:`1704`. bind on all addresses on port :samp:`1704`.
* - **zeroconf yes|no**
- Publish the Snapcast server as service type ``_snapcast._tcp``
via Zeroconf (Avahi or Bonjour). Default is :samp:`yes`.
solaris solaris

View File

@ -369,6 +369,8 @@ subdir('src/lib/yajl')
subdir('src/lib/crypto') subdir('src/lib/crypto')
subdir('src/zeroconf')
subdir('src/fs') subdir('src/fs')
subdir('src/config') subdir('src/config')
subdir('src/tag') subdir('src/tag')
@ -384,7 +386,6 @@ subdir('src/decoder')
subdir('src/encoder') subdir('src/encoder')
subdir('src/song') subdir('src/song')
subdir('src/playlist') subdir('src/playlist')
subdir('src/zeroconf')
if curl_dep.found() if curl_dep.found()
sources += 'src/RemoteTagCache.cxx' sources += 'src/RemoteTagCache.cxx'

View File

@ -119,7 +119,7 @@ if get_option('snapcast')
'snapcast/SnapcastOutputPlugin.cxx', 'snapcast/SnapcastOutputPlugin.cxx',
'snapcast/Client.cxx', 'snapcast/Client.cxx',
] ]
output_plugins_deps += [ event_dep, net_dep, yajl_dep ] output_plugins_deps += [ event_dep, net_dep, yajl_dep, zeroconf_dep ]
output_features.set('HAVE_YAJL', yajl_dep.found()) output_features.set('HAVE_YAJL', yajl_dep.found())

View File

@ -30,14 +30,21 @@
#include "util/AllocatedArray.hxx" #include "util/AllocatedArray.hxx"
#include "util/IntrusiveList.hxx" #include "util/IntrusiveList.hxx"
#include "config.h" // for HAVE_ZEROCONF
#include <memory> #include <memory>
struct ConfigBlock; struct ConfigBlock;
class SnapcastClient; class SnapcastClient;
class PreparedEncoder; class PreparedEncoder;
class Encoder; class Encoder;
class ZeroconfHelper;
class SnapcastOutput final : AudioOutput, ServerSocket { class SnapcastOutput final : AudioOutput, ServerSocket {
#ifdef HAVE_ZEROCONF
unsigned zeroconf_port = 0;
#endif
/** /**
* True if the audio output is open and accepts client * True if the audio output is open and accepts client
* connections. * connections.
@ -46,6 +53,10 @@ class SnapcastOutput final : AudioOutput, ServerSocket {
InjectEvent inject_event; InjectEvent inject_event;
#ifdef HAVE_ZEROCONF
std::unique_ptr<ZeroconfHelper> zeroconf_helper;
#endif
/** /**
* The configured encoder plugin. * The configured encoder plugin.
*/ */

View File

@ -32,6 +32,10 @@
#include "util/DeleteDisposer.hxx" #include "util/DeleteDisposer.hxx"
#include "config/Net.hxx" #include "config/Net.hxx"
#ifdef HAVE_ZEROCONF
#include "zeroconf/Helper.hxx"
#endif
#ifdef HAVE_YAJL #ifdef HAVE_YAJL
#include "lib/yajl/Gen.hxx" #include "lib/yajl/Gen.hxx"
#endif #endif
@ -49,8 +53,14 @@ SnapcastOutput::SnapcastOutput(EventLoop &_loop, const ConfigBlock &block)
// TODO: support other encoder plugins? // TODO: support other encoder plugins?
prepared_encoder(encoder_init(wave_encoder_plugin, block)) prepared_encoder(encoder_init(wave_encoder_plugin, block))
{ {
const unsigned port = block.GetBlockValue("port", 1704U);
ServerSocketAddGeneric(*this, block.GetBlockValue("bind_to_address"), ServerSocketAddGeneric(*this, block.GetBlockValue("bind_to_address"),
block.GetBlockValue("port", 1704U)); port);
#ifdef HAVE_ZEROCONF
if (block.GetBlockValue("zeroconf", true))
zeroconf_port = port;
#endif
} }
SnapcastOutput::~SnapcastOutput() noexcept = default; SnapcastOutput::~SnapcastOutput() noexcept = default;
@ -62,6 +72,13 @@ SnapcastOutput::Bind()
BlockingCall(GetEventLoop(), [this](){ BlockingCall(GetEventLoop(), [this](){
ServerSocket::Open(); ServerSocket::Open();
#ifdef HAVE_ZEROCONF
if (zeroconf_port > 0)
zeroconf_helper = std::make_unique<ZeroconfHelper>
(GetEventLoop(), "Music Player Daemon",
"_snapcast._tcp", zeroconf_port);
#endif
}); });
// TODO: Zeroconf integration // TODO: Zeroconf integration
@ -73,6 +90,8 @@ SnapcastOutput::Unbind() noexcept
assert(!open); assert(!open);
BlockingCall(GetEventLoop(), [this](){ BlockingCall(GetEventLoop(), [this](){
zeroconf_helper.reset();
ServerSocket::Close(); ServerSocket::Close();
}); });
} }