diff --git a/server/streamreader/airplay_stream.cpp b/server/streamreader/airplay_stream.cpp index 6ecd8430..2e78f5ca 100644 --- a/server/streamreader/airplay_stream.cpp +++ b/server/streamreader/airplay_stream.cpp @@ -44,9 +44,6 @@ string hex2str(string input) /* * Expat is used in metadata parsing from Shairport-sync. * Without HAS_EXPAT defined no parsing will occur. - * - * This is currently defined in airplayStream.h, prolly should - * move to Makefile? */ AirplayStream::AirplayStream(PcmListener* pcmListener, boost::asio::io_context& ioc, const StreamUri& uri) @@ -62,14 +59,8 @@ AirplayStream::AirplayStream(PcmListener* pcmListener, boost::asio::io_context& #ifdef HAS_EXPAT createParser(); -#endif - -#if 0 - // This thread is replaced with asio based "pipeReadLine". - // Also seems that this thread was leaking. - // The new implementation is _not tested_ - pipeReaderThread_ = thread(&AirplayStream::pipeReader, this); - pipeReaderThread_.detach(); +#else + LOG(INFO, LOG_TAG) << "Metadata support not enabled (HAS_EXPAT not defined)" << "\n"; #endif } @@ -134,7 +125,7 @@ void AirplayStream::push() void AirplayStream::setParamsAndPipePathFromPort() { pipePath_ = "/tmp/shairmeta." + cpt::to_string(getpid()) + "." + cpt::to_string(port_); - params_ = params_wo_port_ + " --metadata-pipename " + pipePath_ + " --port=" + cpt::to_string(port_); + params_ = params_wo_port_ + " \"--metadata-pipename=" + pipePath_ + "\" --port=" + cpt::to_string(port_); } @@ -153,7 +144,7 @@ void AirplayStream::pipeReadLine() { int fd = open(pipePath_.c_str(), O_RDONLY | O_NONBLOCK); pipe_fd_ = std::make_unique(ioc_, fd); - LOG(INFO, LOG_TAG) << "Metadata pipe opened:" + pipePath_ + "\n"; + LOG(INFO, LOG_TAG) << "Metadata pipe opened: " << pipePath_ << "\n"; } catch (const std::exception& e) { @@ -168,7 +159,14 @@ void AirplayStream::pipeReadLine() boost::asio::async_read_until(*pipe_fd_, streambuf_pipe_, delimiter, [this, delimiter](const std::error_code& ec, std::size_t bytes_transferred) { if (ec) { - LOG(ERROR, LOG_TAG) << "Error while reading from metadata pipe: " << ec.message() << "\n"; + if (ec.value() == boost::asio::error::eof) { + // For some reason, EOF is returned until the first metadata is written to the pipe. + // Is this a boost bug? + LOG(INFO, LOG_TAG) << "Waiting for metadata, retrying in 2500ms" << "\n"; + wait(pipe_open_timer_, 2500ms, [this] { pipeReadLine(); }); + } else { + LOG(ERROR, LOG_TAG) << "Error while reading from metadata pipe: " << ec.message() << "\n"; + } return; } @@ -187,38 +185,6 @@ void AirplayStream::pipeReadLine() }); } -#if 0 - // This thread is replaced with asio based "pipeReadLine". - // Also seems that this thread was leaking. - // The new implementation is _not tested_ -void AirplayStream::pipeReader() -{ -#ifdef HAS_EXPAT - createParser(); -#endif - - while (true) - { - ifstream pipe(pipePath_); - - if (pipe) - { - string line; - - while (getline(pipe, line)) - { -#ifdef HAS_EXPAT - parse(line); -#endif - } - } - - // Wait a little until we try to open it again - this_thread::sleep_for(chrono::milliseconds(500)); - } -} -#endif - void AirplayStream::initExeAndPath(const string& filename) { path_ = ""; diff --git a/server/streamreader/airplay_stream.hpp b/server/streamreader/airplay_stream.hpp index 1d1b4bb6..f8a5378f 100644 --- a/server/streamreader/airplay_stream.hpp +++ b/server/streamreader/airplay_stream.hpp @@ -65,10 +65,10 @@ public: protected: #ifdef HAS_EXPAT XML_Parser parser_; -#endif std::unique_ptr entry_; std::string buf_; json jtag_; +#endif void pipeReadLine(); #ifdef HAS_EXPAT