mirror of
https://github.com/badaix/snapcast.git
synced 2025-06-27 06:57:03 +02:00
renamed Reader => Stream
This commit is contained in:
parent
1f177e5119
commit
0eaa616ab6
15 changed files with 114 additions and 114 deletions
|
@ -13,7 +13,7 @@ CXX = /usr/bin/g++
|
||||||
CFLAGS = -std=c++0x -static-libgcc -static-libstdc++ -Wall -Wno-unused-function -O3 -pthread -DASIO_STANDALONE -DVERSION=\"$(VERSION)\" -I.. -I../externals/asio/asio/include -I../externals/popl/include
|
CFLAGS = -std=c++0x -static-libgcc -static-libstdc++ -Wall -Wno-unused-function -O3 -pthread -DASIO_STANDALONE -DVERSION=\"$(VERSION)\" -I.. -I../externals/asio/asio/include -I../externals/popl/include
|
||||||
LDFLAGS = -lrt -lvorbis -lvorbisenc -logg -lFLAC -lavahi-client -lavahi-common
|
LDFLAGS = -lrt -lvorbis -lvorbisenc -logg -lFLAC -lavahi-client -lavahi-common
|
||||||
|
|
||||||
OBJ = snapServer.o config.o controlServer.o controlSession.o streamServer.o streamSession.o json/jsonrpc.o pcmreader/readerUri.o pcmreader/streamManager.o pcmreader/pcmReader.o pcmreader/pipeReader.o pcmreader/fileReader.o encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o publishAvahi.o ../common/log.o ../message/pcmChunk.o ../message/sampleFormat.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 encoder/encoderFactory.o encoder/flacEncoder.o encoder/pcmEncoder.o encoder/oggEncoder.o publishAvahi.o ../common/log.o ../message/pcmChunk.o ../message/sampleFormat.o
|
||||||
BIN = snapserver
|
BIN = snapserver
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
|
@ -40,35 +40,35 @@ StreamServer::~StreamServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StreamServer::onStateChanged(const PcmReader* pcmReader, const ReaderState& state)
|
void StreamServer::onStateChanged(const PcmStream* pcmStream, const ReaderState& state)
|
||||||
{
|
{
|
||||||
logO << "onStateChanged (" << pcmReader->getName() << "): " << state << "\n";
|
logO << "onStateChanged (" << pcmStream->getName() << "): " << state << "\n";
|
||||||
// logO << pcmReader->toJson().dump(4);
|
// logO << pcmStream->toJson().dump(4);
|
||||||
json notification = JsonNotification::getJson("Stream.OnUpdate", pcmReader->toJson());
|
json notification = JsonNotification::getJson("Stream.OnUpdate", pcmStream->toJson());
|
||||||
controlServer_->send(notification.dump(), NULL);
|
controlServer_->send(notification.dump(), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StreamServer::onChunkRead(const PcmReader* pcmReader, const msg::PcmChunk* chunk, double duration)
|
void StreamServer::onChunkRead(const PcmStream* pcmStream, const msg::PcmChunk* chunk, double duration)
|
||||||
{
|
{
|
||||||
// logO << "onChunkRead (" << pcmReader->getName() << "): " << duration << "ms\n";
|
// logO << "onChunkRead (" << pcmStream->getName() << "): " << duration << "ms\n";
|
||||||
bool isDefaultStream(pcmReader == streamManager_->getDefaultStream().get());
|
bool isDefaultStream(pcmStream == streamManager_->getDefaultStream().get());
|
||||||
|
|
||||||
std::shared_ptr<const msg::BaseMessage> shared_message(chunk);
|
std::shared_ptr<const msg::BaseMessage> shared_message(chunk);
|
||||||
std::lock_guard<std::mutex> mlock(sessionsMutex_);
|
std::lock_guard<std::mutex> mlock(sessionsMutex_);
|
||||||
for (auto s : sessions_)
|
for (auto s : sessions_)
|
||||||
{
|
{
|
||||||
if (!s->pcmReader() && isDefaultStream)//->getName() == "default")
|
if (!s->pcmStream() && isDefaultStream)//->getName() == "default")
|
||||||
s->add(shared_message);
|
s->add(shared_message);
|
||||||
else if (s->pcmReader().get() == pcmReader)
|
else if (s->pcmStream().get() == pcmStream)
|
||||||
s->add(shared_message);
|
s->add(shared_message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StreamServer::onResync(const PcmReader* pcmReader, double ms)
|
void StreamServer::onResync(const PcmStream* pcmStream, double ms)
|
||||||
{
|
{
|
||||||
logO << "onResync (" << pcmReader->getName() << "): " << ms << "ms\n";
|
logO << "onResync (" << pcmStream->getName() << "): " << ms << "ms\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
||||||
else if (request.method == "Client.SetStream")
|
else if (request.method == "Client.SetStream")
|
||||||
{
|
{
|
||||||
string streamId = request.getParam("id").get<string>();
|
string streamId = request.getParam("id").get<string>();
|
||||||
PcmReaderPtr stream = streamManager_->getStream(streamId);
|
PcmStreamPtr stream = streamManager_->getStream(streamId);
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
throw JsonInternalErrorException("Stream not found", request.id);
|
throw JsonInternalErrorException("Stream not found", request.id);
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
||||||
if (session != NULL)
|
if (session != NULL)
|
||||||
{
|
{
|
||||||
session->add(stream->getHeader());
|
session->add(stream->getHeader());
|
||||||
session->setPcmReader(stream);
|
session->setPcmStream(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (request.method == "Client.SetLatency")
|
else if (request.method == "Client.SetLatency")
|
||||||
|
@ -303,7 +303,7 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
||||||
gettimeofday(&client->lastSeen, NULL);
|
gettimeofday(&client->lastSeen, NULL);
|
||||||
|
|
||||||
// Assign and update stream
|
// Assign and update stream
|
||||||
PcmReaderPtr stream = streamManager_->getStream(client->config.streamId);
|
PcmStreamPtr stream = streamManager_->getStream(client->config.streamId);
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
{
|
{
|
||||||
stream = streamManager_->getDefaultStream();
|
stream = streamManager_->getDefaultStream();
|
||||||
|
@ -311,8 +311,8 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
||||||
}
|
}
|
||||||
Config::instance().save();
|
Config::instance().save();
|
||||||
|
|
||||||
//TODO: wording pcmReader vs stream
|
//TODO: wording pcmStream vs stream
|
||||||
connection->setPcmReader(stream);
|
connection->setPcmStream(stream);
|
||||||
auto headerChunk = stream->getHeader();
|
auto headerChunk = stream->getHeader();
|
||||||
connection->send(headerChunk.get());
|
connection->send(headerChunk.get());
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "streamSession.h"
|
#include "streamSession.h"
|
||||||
#include "pcmreader/streamManager.h"
|
#include "streamreader/streamManager.h"
|
||||||
#include "common/queue.h"
|
#include "common/queue.h"
|
||||||
#include "message/message.h"
|
#include "message/message.h"
|
||||||
#include "message/header.h"
|
#include "message/header.h"
|
||||||
|
@ -64,7 +64,7 @@ struct StreamServerSettings
|
||||||
|
|
||||||
/// Forwars PCM data to the connected clients
|
/// Forwars PCM data to the connected clients
|
||||||
/**
|
/**
|
||||||
* Reads PCM data using PipeReader, implements PcmListener to get the (encoded) PCM stream.
|
* Reads PCM data using PipeStream, implements PcmListener to get the (encoded) PCM stream.
|
||||||
* Accepts and holds client connections (StreamSession)
|
* Accepts and holds client connections (StreamSession)
|
||||||
* Receives (via the MessageReceiver interface) and answers messages from the clients
|
* Receives (via the MessageReceiver interface) and answers messages from the clients
|
||||||
* Forwards PCM data to the clients
|
* Forwards PCM data to the clients
|
||||||
|
@ -89,9 +89,9 @@ public:
|
||||||
virtual void onMessageReceived(ControlSession* connection, const std::string& message);
|
virtual void onMessageReceived(ControlSession* connection, const std::string& message);
|
||||||
|
|
||||||
/// Implementation of PcmListener
|
/// Implementation of PcmListener
|
||||||
virtual void onStateChanged(const PcmReader* pcmReader, const ReaderState& state);
|
virtual void onStateChanged(const PcmStream* pcmStream, const ReaderState& state);
|
||||||
virtual void onChunkRead(const PcmReader* pcmReader, const msg::PcmChunk* chunk, double duration);
|
virtual void onChunkRead(const PcmStream* pcmStream, const msg::PcmChunk* chunk, double duration);
|
||||||
virtual void onResync(const PcmReader* pcmReader, double ms);
|
virtual void onResync(const PcmStream* pcmStream, double ms);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startAccept();
|
void startAccept();
|
||||||
|
|
|
@ -28,7 +28,7 @@ using namespace std;
|
||||||
|
|
||||||
|
|
||||||
StreamSession::StreamSession(MessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) :
|
StreamSession::StreamSession(MessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) :
|
||||||
active_(true), messageReceiver_(receiver), pcmReader_(nullptr)
|
active_(true), messageReceiver_(receiver), pcmStream_(nullptr)
|
||||||
{
|
{
|
||||||
socket_ = socket;
|
socket_ = socket;
|
||||||
}
|
}
|
||||||
|
@ -40,15 +40,15 @@ StreamSession::~StreamSession()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void StreamSession::setPcmReader(PcmReaderPtr pcmReader)
|
void StreamSession::setPcmStream(PcmStreamPtr pcmStream)
|
||||||
{
|
{
|
||||||
pcmReader_ = pcmReader;
|
pcmStream_ = pcmStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const PcmReaderPtr StreamSession::pcmReader() const
|
const PcmStreamPtr StreamSession::pcmStream() const
|
||||||
{
|
{
|
||||||
return pcmReader_;
|
return pcmStream_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "message/message.h"
|
#include "message/message.h"
|
||||||
#include "common/queue.h"
|
#include "common/queue.h"
|
||||||
#include "pcmreader/streamManager.h"
|
#include "streamreader/streamManager.h"
|
||||||
|
|
||||||
|
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
|
@ -80,8 +80,8 @@ public:
|
||||||
return socket_->remote_endpoint().address().to_string();
|
return socket_->remote_endpoint().address().to_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setPcmReader(PcmReaderPtr pcmReader);
|
void setPcmStream(PcmStreamPtr pcmStream);
|
||||||
const PcmReaderPtr pcmReader() const;
|
const PcmStreamPtr pcmStream() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void socketRead(void* _to, size_t _bytes);
|
void socketRead(void* _to, size_t _bytes);
|
||||||
|
@ -100,7 +100,7 @@ protected:
|
||||||
MessageReceiver* messageReceiver_;
|
MessageReceiver* messageReceiver_;
|
||||||
Queue<std::shared_ptr<const msg::BaseMessage>> messages_;
|
Queue<std::shared_ptr<const msg::BaseMessage>> messages_;
|
||||||
size_t bufferMs_;
|
size_t bufferMs_;
|
||||||
PcmReaderPtr pcmReader_;
|
PcmStreamPtr pcmStream_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "fileReader.h"
|
#include "fileStream.h"
|
||||||
#include "../encoder/encoderFactory.h"
|
#include "../encoder/encoderFactory.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
|
@ -32,7 +32,7 @@ using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FileReader::FileReader(PcmListener* pcmListener, const ReaderUri& uri) : PcmReader(pcmListener, uri)
|
FileStream::FileStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri)
|
||||||
{
|
{
|
||||||
ifs.open(uri_.path.c_str(), std::ifstream::in|std::ifstream::binary);
|
ifs.open(uri_.path.c_str(), std::ifstream::in|std::ifstream::binary);
|
||||||
if (!ifs.good())
|
if (!ifs.good())
|
||||||
|
@ -43,13 +43,13 @@ FileReader::FileReader(PcmListener* pcmListener, const ReaderUri& uri) : PcmRead
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FileReader::~FileReader()
|
FileStream::~FileStream()
|
||||||
{
|
{
|
||||||
ifs.close();
|
ifs.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void FileReader::worker()
|
void FileStream::worker()
|
||||||
{
|
{
|
||||||
timeval tvChunk;
|
timeval tvChunk;
|
||||||
std::unique_ptr<msg::PcmChunk> chunk(new msg::PcmChunk(sampleFormat_, pcmReadMs_));
|
std::unique_ptr<msg::PcmChunk> chunk(new msg::PcmChunk(sampleFormat_, pcmReadMs_));
|
|
@ -19,7 +19,7 @@
|
||||||
#ifndef FILE_READER_H
|
#ifndef FILE_READER_H
|
||||||
#define FILE_READER_H
|
#define FILE_READER_H
|
||||||
|
|
||||||
#include "pcmReader.h"
|
#include "pcmStream.h"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@
|
||||||
* Implements EncoderListener to get the encoded data.
|
* Implements EncoderListener to get the encoded data.
|
||||||
* Data is passed to the PcmListener
|
* Data is passed to the PcmListener
|
||||||
*/
|
*/
|
||||||
class FileReader : public PcmReader
|
class FileStream : public PcmStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// ctor. Encoded PCM data is passed to the PipeListener
|
/// ctor. Encoded PCM data is passed to the PipeListener
|
||||||
FileReader(PcmListener* pcmListener, const ReaderUri& uri);
|
FileStream(PcmListener* pcmListener, const StreamUri& uri);
|
||||||
virtual ~FileReader();
|
virtual ~FileStream();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void worker();
|
void worker();
|
|
@ -24,7 +24,7 @@
|
||||||
#include "../encoder/encoderFactory.h"
|
#include "../encoder/encoderFactory.h"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/compat.h"
|
#include "common/compat.h"
|
||||||
#include "pcmReader.h"
|
#include "pcmStream.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PcmReader::PcmReader(PcmListener* pcmListener, const ReaderUri& uri) : pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
|
PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) : pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
|
||||||
{
|
{
|
||||||
EncoderFactory encoderFactory;
|
EncoderFactory encoderFactory;
|
||||||
if (uri_.query.find("codec") == uri_.query.end())
|
if (uri_.query.find("codec") == uri_.query.end())
|
||||||
|
@ -46,55 +46,55 @@ PcmReader::PcmReader(PcmListener* pcmListener, const ReaderUri& uri) : pcmListen
|
||||||
if (uri_.query.find("sampleformat") == uri_.query.end())
|
if (uri_.query.find("sampleformat") == uri_.query.end())
|
||||||
throw SnapException("Stream URI must have a sampleformat");
|
throw SnapException("Stream URI must have a sampleformat");
|
||||||
sampleFormat_ = SampleFormat(uri_.query["sampleformat"]);
|
sampleFormat_ = SampleFormat(uri_.query["sampleformat"]);
|
||||||
logE << "PcmReader sampleFormat: " << sampleFormat_.getFormat() << "\n";
|
logE << "PcmStream sampleFormat: " << sampleFormat_.getFormat() << "\n";
|
||||||
|
|
||||||
if (uri_.query.find("buffer_ms") != uri_.query.end())
|
if (uri_.query.find("buffer_ms") != uri_.query.end())
|
||||||
pcmReadMs_ = cpt::stoul(uri_.query["buffer_ms"]);
|
pcmReadMs_ = cpt::stoul(uri_.query["buffer_ms"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PcmReader::~PcmReader()
|
PcmStream::~PcmStream()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::shared_ptr<msg::Header> PcmReader::getHeader()
|
std::shared_ptr<msg::Header> PcmStream::getHeader()
|
||||||
{
|
{
|
||||||
return encoder_->getHeader();
|
return encoder_->getHeader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const ReaderUri& PcmReader::getUri() const
|
const StreamUri& PcmStream::getUri() const
|
||||||
{
|
{
|
||||||
return uri_;
|
return uri_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::string& PcmReader::getName() const
|
const std::string& PcmStream::getName() const
|
||||||
{
|
{
|
||||||
return name_;
|
return name_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const SampleFormat& PcmReader::getSampleFormat() const
|
const SampleFormat& PcmStream::getSampleFormat() const
|
||||||
{
|
{
|
||||||
return sampleFormat_;
|
return sampleFormat_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PcmReader::start()
|
void PcmStream::start()
|
||||||
{
|
{
|
||||||
logE << "PcmReader start: " << sampleFormat_.getFormat() << "\n";
|
logE << "PcmStream start: " << sampleFormat_.getFormat() << "\n";
|
||||||
//TODO: wrong encoder settings leads to: terminate called after throwing an instance of 'std::system_error' what(): Invalid argument
|
//TODO: wrong encoder settings leads to: terminate called after throwing an instance of 'std::system_error' what(): Invalid argument
|
||||||
encoder_->init(this, sampleFormat_);
|
encoder_->init(this, sampleFormat_);
|
||||||
|
|
||||||
active_ = true;
|
active_ = true;
|
||||||
readerThread_ = thread(&PcmReader::worker, this);
|
readerThread_ = thread(&PcmStream::worker, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PcmReader::stop()
|
void PcmStream::stop()
|
||||||
{
|
{
|
||||||
if (active_)
|
if (active_)
|
||||||
{
|
{
|
||||||
|
@ -104,13 +104,13 @@ void PcmReader::stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ReaderState PcmReader::getState() const
|
ReaderState PcmStream::getState() const
|
||||||
{
|
{
|
||||||
return state_;
|
return state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PcmReader::setState(const ReaderState& newState)
|
void PcmStream::setState(const ReaderState& newState)
|
||||||
{
|
{
|
||||||
if (newState != state_)
|
if (newState != state_)
|
||||||
{
|
{
|
||||||
|
@ -120,7 +120,7 @@ void PcmReader::setState(const ReaderState& newState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PcmReader::onChunkEncoded(const Encoder* encoder, msg::PcmChunk* chunk, double duration)
|
void PcmStream::onChunkEncoded(const Encoder* encoder, msg::PcmChunk* chunk, double duration)
|
||||||
{
|
{
|
||||||
// logO << "onChunkEncoded: " << duration << " us\n";
|
// logO << "onChunkEncoded: " << duration << " us\n";
|
||||||
if (duration <= 0)
|
if (duration <= 0)
|
||||||
|
@ -133,7 +133,7 @@ void PcmReader::onChunkEncoded(const Encoder* encoder, msg::PcmChunk* chunk, dou
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
json PcmReader::toJson() const
|
json PcmStream::toJson() const
|
||||||
{
|
{
|
||||||
string state("unknown");
|
string state("unknown");
|
||||||
if (state_ == kIdle)
|
if (state_ == kIdle)
|
|
@ -23,14 +23,14 @@
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include "readerUri.h"
|
#include "streamUri.h"
|
||||||
#include "../encoder/encoder.h"
|
#include "../encoder/encoder.h"
|
||||||
#include "../json/json.hpp"
|
#include "../json/json.hpp"
|
||||||
#include "message/sampleFormat.h"
|
#include "message/sampleFormat.h"
|
||||||
#include "message/header.h"
|
#include "message/header.h"
|
||||||
|
|
||||||
|
|
||||||
class PcmReader;
|
class PcmStream;
|
||||||
|
|
||||||
enum ReaderState
|
enum ReaderState
|
||||||
{
|
{
|
||||||
|
@ -41,16 +41,16 @@ enum ReaderState
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/// Callback interface for users of PcmReader
|
/// Callback interface for users of PcmStream
|
||||||
/**
|
/**
|
||||||
* Users of PcmReader should implement this to get the data
|
* Users of PcmStream should implement this to get the data
|
||||||
*/
|
*/
|
||||||
class PcmListener
|
class PcmListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void onStateChanged(const PcmReader* pcmReader, const ReaderState& state) = 0;
|
virtual void onStateChanged(const PcmStream* pcmStream, const ReaderState& state) = 0;
|
||||||
virtual void onChunkRead(const PcmReader* pcmReader, const msg::PcmChunk* chunk, double duration) = 0;
|
virtual void onChunkRead(const PcmStream* pcmStream, const msg::PcmChunk* chunk, double duration) = 0;
|
||||||
virtual void onResync(const PcmReader* pcmReader, double ms) = 0;
|
virtual void onResync(const PcmStream* pcmStream, double ms) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,12 +60,12 @@ public:
|
||||||
* Implements EncoderListener to get the encoded data.
|
* Implements EncoderListener to get the encoded data.
|
||||||
* Data is passed to the PcmListener
|
* Data is passed to the PcmListener
|
||||||
*/
|
*/
|
||||||
class PcmReader : public EncoderListener
|
class PcmStream : public EncoderListener
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// ctor. Encoded PCM data is passed to the PcmListener
|
/// ctor. Encoded PCM data is passed to the PcmListener
|
||||||
PcmReader(PcmListener* pcmListener, const ReaderUri& uri);
|
PcmStream(PcmListener* pcmListener, const StreamUri& uri);
|
||||||
virtual ~PcmReader();
|
virtual ~PcmStream();
|
||||||
|
|
||||||
virtual void start();
|
virtual void start();
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
|
@ -74,7 +74,7 @@ public:
|
||||||
virtual void onChunkEncoded(const Encoder* encoder, msg::PcmChunk* chunk, double duration);
|
virtual void onChunkEncoded(const Encoder* encoder, msg::PcmChunk* chunk, double duration);
|
||||||
virtual std::shared_ptr<msg::Header> getHeader();
|
virtual std::shared_ptr<msg::Header> getHeader();
|
||||||
|
|
||||||
virtual const ReaderUri& getUri() const;
|
virtual const StreamUri& getUri() const;
|
||||||
virtual const std::string& getName() const;
|
virtual const std::string& getName() const;
|
||||||
virtual const SampleFormat& getSampleFormat() const;
|
virtual const SampleFormat& getSampleFormat() const;
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ protected:
|
||||||
std::atomic<bool> active_;
|
std::atomic<bool> active_;
|
||||||
std::thread readerThread_;
|
std::thread readerThread_;
|
||||||
PcmListener* pcmListener_;
|
PcmListener* pcmListener_;
|
||||||
ReaderUri uri_;
|
StreamUri uri_;
|
||||||
SampleFormat sampleFormat_;
|
SampleFormat sampleFormat_;
|
||||||
size_t pcmReadMs_;
|
size_t pcmReadMs_;
|
||||||
std::unique_ptr<Encoder> encoder_;
|
std::unique_ptr<Encoder> encoder_;
|
|
@ -21,7 +21,7 @@
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "pipeReader.h"
|
#include "pipeStream.h"
|
||||||
#include "../encoder/encoderFactory.h"
|
#include "../encoder/encoderFactory.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
|
@ -33,7 +33,7 @@ using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PipeReader::PipeReader(PcmListener* pcmListener, const ReaderUri& uri) : PcmReader(pcmListener, uri), fd_(-1)
|
PipeStream::PipeStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), fd_(-1)
|
||||||
{
|
{
|
||||||
umask(0);
|
umask(0);
|
||||||
if ((mkfifo(uri_.path.c_str(), 0666) != 0) && (errno != EEXIST))
|
if ((mkfifo(uri_.path.c_str(), 0666) != 0) && (errno != EEXIST))
|
||||||
|
@ -41,14 +41,14 @@ PipeReader::PipeReader(PcmListener* pcmListener, const ReaderUri& uri) : PcmRead
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PipeReader::~PipeReader()
|
PipeStream::~PipeStream()
|
||||||
{
|
{
|
||||||
if (fd_ != -1)
|
if (fd_ != -1)
|
||||||
close(fd_);
|
close(fd_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PipeReader::worker()
|
void PipeStream::worker()
|
||||||
{
|
{
|
||||||
timeval tvChunk;
|
timeval tvChunk;
|
||||||
std::unique_ptr<msg::PcmChunk> chunk(new msg::PcmChunk(sampleFormat_, pcmReadMs_));
|
std::unique_ptr<msg::PcmChunk> chunk(new msg::PcmChunk(sampleFormat_, pcmReadMs_));
|
|
@ -16,10 +16,10 @@
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#ifndef PIPE_READER_H
|
#ifndef PIPE_STREAM_H
|
||||||
#define PIPE_READER_H
|
#define PIPE_STREAM_H
|
||||||
|
|
||||||
#include "pcmReader.h"
|
#include "pcmStream.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@
|
||||||
* Implements EncoderListener to get the encoded data.
|
* Implements EncoderListener to get the encoded data.
|
||||||
* Data is passed to the PcmListener
|
* Data is passed to the PcmListener
|
||||||
*/
|
*/
|
||||||
class PipeReader : public PcmReader
|
class PipeStream : public PcmStream
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// ctor. Encoded PCM data is passed to the PipeListener
|
/// ctor. Encoded PCM data is passed to the PipeListener
|
||||||
PipeReader(PcmListener* pcmListener, const ReaderUri& uri);
|
PipeStream(PcmListener* pcmListener, const StreamUri& uri);
|
||||||
virtual ~PipeReader();
|
virtual ~PipeStream();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void worker();
|
void worker();
|
|
@ -18,8 +18,8 @@
|
||||||
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
#include "streamManager.h"
|
#include "streamManager.h"
|
||||||
#include "pipeReader.h"
|
#include "pipeStream.h"
|
||||||
#include "fileReader.h"
|
#include "fileStream.h"
|
||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
|
|
||||||
|
@ -32,51 +32,51 @@ StreamManager::StreamManager(PcmListener* pcmListener, const std::string& defaul
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PcmReader* StreamManager::addStream(const std::string& uri)
|
PcmStream* StreamManager::addStream(const std::string& uri)
|
||||||
{
|
{
|
||||||
ReaderUri readerUri(uri);
|
StreamUri streamUri(uri);
|
||||||
|
|
||||||
if (readerUri.query.find("sampleformat") == readerUri.query.end())
|
if (streamUri.query.find("sampleformat") == streamUri.query.end())
|
||||||
readerUri.query["sampleformat"] = sampleFormat_;
|
streamUri.query["sampleformat"] = sampleFormat_;
|
||||||
|
|
||||||
if (readerUri.query.find("codec") == readerUri.query.end())
|
if (streamUri.query.find("codec") == streamUri.query.end())
|
||||||
readerUri.query["codec"] = codec_;
|
streamUri.query["codec"] = codec_;
|
||||||
|
|
||||||
if (readerUri.query.find("buffer_ms") == readerUri.query.end())
|
if (streamUri.query.find("buffer_ms") == streamUri.query.end())
|
||||||
readerUri.query["buffer_ms"] = to_string(readBufferMs_);
|
streamUri.query["buffer_ms"] = to_string(readBufferMs_);
|
||||||
|
|
||||||
// logE << "\nURI: " << readerUri.uri << "\nscheme: " << readerUri.scheme << "\nhost: "
|
// logE << "\nURI: " << streamUri.uri << "\nscheme: " << streamUri.scheme << "\nhost: "
|
||||||
// << readerUri.host << "\npath: " << readerUri.path << "\nfragment: " << readerUri.fragment << "\n";
|
// << streamUri.host << "\npath: " << streamUri.path << "\nfragment: " << streamUri.fragment << "\n";
|
||||||
|
|
||||||
// for (auto kv: readerUri.query)
|
// for (auto kv: streamUri.query)
|
||||||
// logE << "key: '" << kv.first << "' value: '" << kv.second << "'\n";
|
// logE << "key: '" << kv.first << "' value: '" << kv.second << "'\n";
|
||||||
|
|
||||||
if (readerUri.scheme == "pipe")
|
if (streamUri.scheme == "pipe")
|
||||||
{
|
{
|
||||||
streams_.push_back(make_shared<PipeReader>(pcmListener_, readerUri));
|
streams_.push_back(make_shared<PipeStream>(pcmListener_, streamUri));
|
||||||
return streams_.back().get();
|
return streams_.back().get();
|
||||||
}
|
}
|
||||||
else if (readerUri.scheme == "file")
|
else if (streamUri.scheme == "file")
|
||||||
{
|
{
|
||||||
streams_.push_back(make_shared<FileReader>(pcmListener_, readerUri));
|
streams_.push_back(make_shared<FileStream>(pcmListener_, streamUri));
|
||||||
return streams_.back().get();
|
return streams_.back().get();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw SnapException("Unknown stream type: " + readerUri.scheme);
|
throw SnapException("Unknown stream type: " + streamUri.scheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::vector<PcmReaderPtr>& StreamManager::getStreams()
|
const std::vector<PcmStreamPtr>& StreamManager::getStreams()
|
||||||
{
|
{
|
||||||
return streams_;
|
return streams_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const PcmReaderPtr StreamManager::getDefaultStream()
|
const PcmStreamPtr StreamManager::getDefaultStream()
|
||||||
{
|
{
|
||||||
if (streams_.empty())
|
if (streams_.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -85,7 +85,7 @@ const PcmReaderPtr StreamManager::getDefaultStream()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const PcmReaderPtr StreamManager::getStream(const std::string& id)
|
const PcmStreamPtr StreamManager::getStream(const std::string& id)
|
||||||
{
|
{
|
||||||
for (auto stream: streams_)
|
for (auto stream: streams_)
|
||||||
{
|
{
|
|
@ -4,25 +4,25 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "pcmReader.h"
|
#include "pcmStream.h"
|
||||||
|
|
||||||
typedef std::shared_ptr<PcmReader> PcmReaderPtr;
|
typedef std::shared_ptr<PcmStream> PcmStreamPtr;
|
||||||
|
|
||||||
class StreamManager
|
class StreamManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
StreamManager(PcmListener* pcmListener, const std::string& defaultSampleFormat, const std::string& defaultCodec, size_t defaultReadBufferMs = 20);
|
StreamManager(PcmListener* pcmListener, const std::string& defaultSampleFormat, const std::string& defaultCodec, size_t defaultReadBufferMs = 20);
|
||||||
|
|
||||||
PcmReader* addStream(const std::string& uri);
|
PcmStream* addStream(const std::string& uri);
|
||||||
void start();
|
void start();
|
||||||
void stop();
|
void stop();
|
||||||
const std::vector<PcmReaderPtr>& getStreams();
|
const std::vector<PcmStreamPtr>& getStreams();
|
||||||
const PcmReaderPtr getDefaultStream();
|
const PcmStreamPtr getDefaultStream();
|
||||||
const PcmReaderPtr getStream(const std::string& id);
|
const PcmStreamPtr getStream(const std::string& id);
|
||||||
json toJson() const;
|
json toJson() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<PcmReaderPtr> streams_;
|
std::vector<PcmStreamPtr> streams_;
|
||||||
PcmListener* pcmListener_;
|
PcmListener* pcmListener_;
|
||||||
std::string sampleFormat_;
|
std::string sampleFormat_;
|
||||||
std::string codec_;
|
std::string codec_;
|
|
@ -20,27 +20,27 @@
|
||||||
#include <common/utils.h>
|
#include <common/utils.h>
|
||||||
#include <common/compat.h>
|
#include <common/compat.h>
|
||||||
#include <common/log.h>
|
#include <common/log.h>
|
||||||
#include "readerUri.h"
|
#include "streamUri.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
ReaderUri::ReaderUri(const std::string& readerUri)
|
StreamUri::StreamUri(const std::string& streamUri)
|
||||||
{
|
{
|
||||||
// https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
|
// https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
|
||||||
// scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
|
// scheme:[//[user:password@]host[:port]][/]path[?query][#fragment]
|
||||||
// would be more elegant with regex. Not yet supported on my dev machine's gcc 4.8 :(
|
// would be more elegant with regex. Not yet supported on my dev machine's gcc 4.8 :(
|
||||||
logE << "ReaderUri: " << readerUri << "\n";
|
logE << "StreamUri: " << streamUri << "\n";
|
||||||
size_t pos;
|
size_t pos;
|
||||||
uri = trim_copy(readerUri);
|
uri = trim_copy(streamUri);
|
||||||
while (!uri.empty() && ((uri[0] == '\'') || (uri[0] == '"')))
|
while (!uri.empty() && ((uri[0] == '\'') || (uri[0] == '"')))
|
||||||
uri = uri.substr(1);
|
uri = uri.substr(1);
|
||||||
while (!uri.empty() && ((uri[uri.length()-1] == '\'') || (uri[uri.length()-1] == '"')))
|
while (!uri.empty() && ((uri[uri.length()-1] == '\'') || (uri[uri.length()-1] == '"')))
|
||||||
uri = uri.substr(0, this->uri.length()-1);
|
uri = uri.substr(0, this->uri.length()-1);
|
||||||
|
|
||||||
string decodedUri = uriDecode(uri);
|
string decodedUri = uriDecode(uri);
|
||||||
logD << "ReaderUri: " << decodedUri << "\n";
|
logD << "StreamUri: " << decodedUri << "\n";
|
||||||
|
|
||||||
id_ = decodedUri;
|
id_ = decodedUri;
|
||||||
pos = id_.find('?');
|
pos = id_.find('?');
|
||||||
|
@ -106,7 +106,7 @@ ReaderUri::ReaderUri(const std::string& readerUri)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
json ReaderUri::toJson() const
|
json StreamUri::toJson() const
|
||||||
{
|
{
|
||||||
json j = {
|
json j = {
|
||||||
{"raw", uri},
|
{"raw", uri},
|
||||||
|
@ -120,7 +120,7 @@ json ReaderUri::toJson() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string ReaderUri::id() const
|
std::string StreamUri::id() const
|
||||||
{
|
{
|
||||||
return id_;
|
return id_;
|
||||||
}
|
}
|
|
@ -26,9 +26,9 @@
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
struct ReaderUri
|
struct StreamUri
|
||||||
{
|
{
|
||||||
ReaderUri(const std::string& uri);
|
StreamUri(const std::string& uri);
|
||||||
std::string uri;
|
std::string uri;
|
||||||
std::string scheme;
|
std::string scheme;
|
||||||
/* struct Authority
|
/* struct Authority
|
Loading…
Add table
Add a link
Reference in a new issue