added watchdog to restart librespot

This commit is contained in:
badaix 2016-11-04 10:30:20 +01:00
parent 5dc3a9c0b1
commit 46b794498e
5 changed files with 172 additions and 3 deletions

View file

@ -10,7 +10,7 @@ else
endif
CXXFLAGS += -std=c++0x -Wall -Wno-unused-function -O3 -DASIO_STANDALONE -DVERSION=\"$(VERSION)\" -I. -I.. -I../externals/asio/asio/include -I../externals/popl/include
OBJ = snapServer.o config.o controlServer.o controlSession.o streamServer.o streamSession.o json/jsonrpc.o streamreader/streamUri.o streamreader/streamManager.o streamreader/pcmStream.o streamreader/pipeStream.o streamreader/fileStream.o streamreader/processStream.o streamreader/spotifyStream.o encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o ../common/log.o ../common/sampleFormat.o ../message/pcmChunk.o
OBJ = snapServer.o config.o controlServer.o controlSession.o streamServer.o streamSession.o json/jsonrpc.o streamreader/streamUri.o streamreader/streamManager.o streamreader/pcmStream.o streamreader/pipeStream.o streamreader/fileStream.o streamreader/processStream.o streamreader/spotifyStream.o streamreader/watchdog.o encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o ../common/log.o ../common/sampleFormat.o ../message/pcmChunk.o
ifeq ($(ENDIAN), BIG)
CXXFLAGS += -DIS_BIG_ENDIAN

View file

@ -86,6 +86,7 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
// 2016-11-03 09-00-18 [out] INFO:librespot::main_helper: librespot 6fa4e4d (2016-09-21). Built on 2016-10-27.
// 2016-11-03 09-00-18 [out] INFO:librespot::session: Connecting to AP lon3-accesspoint-a34.ap.spotify.com:443
// 2016-11-03 09-00-18 [out] INFO:librespot::session: Authenticated !
watchdog_->trigger();
string logmsg = trim_copy(string(buffer, n));
if ((logmsg.find("allocated stream") == string::npos) &&
(logmsg.find("Got channel") == string::npos) &&
@ -96,3 +97,20 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
}
}
void SpotifyStream::stderrReader()
{
watchdog_.reset(new Watchdog(this));
/// 70min
watchdog_->start(70*60*1000);
ProcessStream::stderrReader();
}
void SpotifyStream::onTimeout(const Watchdog* watchdog, size_t ms)
{
if (process_)
process_->kill();
}

View file

@ -20,7 +20,7 @@
#define SPOTIFY_STREAM_H
#include "processStream.h"
#include "watchdog.h"
/// Starts librespot and reads and PCM data from stdout
/**
@ -30,7 +30,7 @@
* usage:
* snapserver -s "spotify:///librespot?name=Spotify&username=<my username>&password=<my password>[&devicename=Snapcast][&bitrate=320]"
*/
class SpotifyStream : public ProcessStream
class SpotifyStream : public ProcessStream, WatchdogListener
{
public:
/// ctor. Encoded PCM data is passed to the PipeListener
@ -38,8 +38,13 @@ public:
virtual ~SpotifyStream();
protected:
std::unique_ptr<Watchdog> watchdog_;
virtual void stderrReader();
virtual void onStderrMsg(const char* buffer, size_t n);
virtual void initExeAndPath(const std::string& filename);
virtual void onTimeout(const Watchdog* watchdog, size_t ms);
};

View file

@ -0,0 +1,83 @@
/***
This file is part of snapcast
Copyright (C) 2014-2016 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "watchdog.h"
#include <chrono>
using namespace std;
Watchdog::Watchdog(WatchdogListener* listener) : listener_(listener), thread_(nullptr), active_(false)
{
}
Watchdog::~Watchdog()
{
stop();
}
void Watchdog::start(size_t timeoutMs)
{
timeoutMs_ = timeoutMs;
if (!thread_ || !active_)
{
active_ = true;
thread_.reset(new thread(&Watchdog::worker, this));
}
else
trigger();
}
void Watchdog::stop()
{
active_ = false;
trigger();
if (thread_ && thread_->joinable())
thread_->join();
thread_ = nullptr;
}
void Watchdog::trigger()
{
std::unique_lock<std::mutex> lck(mtx_);
cv_.notify_one();
}
void Watchdog::worker()
{
while (active_)
{
std::unique_lock<std::mutex> lck(mtx_);
if (cv_.wait_for(lck, std::chrono::milliseconds(timeoutMs_)) == std::cv_status::timeout)
{
if (listener_)
{
listener_->onTimeout(this, timeoutMs_);
break;
}
}
}
active_ = false;
}

View file

@ -0,0 +1,63 @@
/***
This file is part of snapcast
Copyright (C) 2014-2016 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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#ifndef WATCH_DOG_H
#define WATCH_DOG_H
#include <mutex>
#include <thread>
#include <memory>
#include <atomic>
#include <condition_variable>
class Watchdog;
class WatchdogListener
{
public:
virtual void onTimeout(const Watchdog* watchdog, size_t ms) = 0;
};
/// Watchdog
class Watchdog
{
public:
Watchdog(WatchdogListener* listener = nullptr);
virtual ~Watchdog();
void start(size_t timeoutMs);
void stop();
void trigger();
private:
WatchdogListener* listener_;
std::condition_variable cv_;
std::mutex mtx_;
std::unique_ptr<std::thread> thread_;
size_t timeoutMs_;
std::atomic<bool> active_;
void worker();
};
#endif