serialize stream to json

This commit is contained in:
badaix 2016-01-25 23:09:32 +01:00
parent 7bec5b8744
commit 95e4a98fef
11 changed files with 172 additions and 113 deletions

View file

@ -9,6 +9,14 @@ else
TARGET_DIR ?= /usr TARGET_DIR ?= /usr
endif endif
# MIPS
# export STAGING_DIR=/home/johannes/Develop/openwrt/staging_dir
# TOOLCHAIN_DIR=$(STAGING_DIR)/toolchain-mips_34kc_gcc-4.8-linaro_uClibc-0.9.33.2
# LDCFLAGS=$(TOOLCHAIN_DIR)/usr/lib
# LD_LIBRARY_PATH=$(TOOLCHAIN_DIR)/usr/lib
# PATH=$(TOOLCHAIN_DIR)/bin:$PATH
# CXX = $(TOOLCHAIN_DIR)/bin/mips-openwrt-linux-g++
ifdef ANDROID ifdef ANDROID
# Android NDK setup: (http://developer.android.com/ndk/guides/standalone_toolchain.html) # Android NDK setup: (http://developer.android.com/ndk/guides/standalone_toolchain.html)
# 1. Download NDK: http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin # 1. Download NDK: http://dl.google.com/android/ndk/android-ndk-r10e-linux-x86_64.bin

View file

@ -19,6 +19,7 @@
#ifndef MESSAGE_H #ifndef MESSAGE_H
#define MESSAGE_H #define MESSAGE_H
#include <cstdlib>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
#include <streambuf> #include <streambuf>

View file

@ -13,7 +13,7 @@ CXX = /usr/bin/g++
CFLAGS = -std=c++0x -Wall -Wno-unused-function -O3 -pthread -DASIO_STANDALONE -DVERSION=\"$(VERSION)\" -I.. -I../externals/asio/asio/include -I../externals/popl/include CFLAGS = -std=c++0x -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/streamManager.o pcmreader/pcmReader.o pcmreader/pipeReader.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 pcmreader/readerUri.o pcmreader/streamManager.o pcmreader/pcmReader.o pcmreader/pipeReader.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)

View file

@ -66,34 +66,6 @@ struct Volume
}; };
struct Stream
{
//TODO
Stream() : id("TODO_ID"), name("TODO_NAME"), uri("file:///tmp/snapfifo")
{
}
void fromJson(const json& j)
{
id = jGet<std::string>(j, "id", "TODO_ID");
name = jGet<std::string>(j, "name", "TODO_NAME");
uri = jGet<std::string>(j, "uri", "file:///tmp/snapfifo");
}
json toJson()
{
json j;
j["id"] = id;
j["name"] = name;
j["uri"] = uri;
return j;
}
std::string id;
std::string name;
std::string uri;
};
struct ClientInfo struct ClientInfo
{ {

View file

@ -21,75 +21,16 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include "pcmReader.h"
#include "../encoder/encoderFactory.h" #include "../encoder/encoderFactory.h"
#include "common/utils.h"
#include "common/compat.h"
#include "common/snapException.h" #include "common/snapException.h"
#include "common/compat.h"
#include "pcmReader.h"
#include "common/log.h" #include "common/log.h"
using namespace std; using namespace std;
ReaderUri::ReaderUri(const std::string& uri)
{
// https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
// 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 :(
size_t pos;
this->uri = uri;
string tmp(uri);
pos = tmp.find(':');
if (pos == string::npos)
throw invalid_argument("missing ':'");
scheme = tmp.substr(0, pos);
tmp = tmp.substr(pos + 1);
logE << "scheme: '" << scheme << "' tmp: '" << tmp << "'\n";
if (tmp.find("//") != 0)
throw invalid_argument("missing host separator: '//'");
tmp = tmp.substr(2);
pos = tmp.find('/');
if (pos == string::npos)
throw invalid_argument("missing path separator: '/'");
host = tmp.substr(0, pos);
tmp = tmp.substr(pos);
path = tmp;
logE << "host: '" << host << "' tmp: '" << tmp << "' path: '" << path << "'\n";
pos = tmp.find('?');
if (pos == string::npos)
return;
path = tmp.substr(0, pos);
tmp = tmp.substr(pos + 1);
string queryStr = tmp;
logE << "path: '" << path << "' tmp: '" << tmp << "' query: '" << queryStr << "'\n";
pos = tmp.find('#');
if (pos != string::npos)
{
queryStr = tmp.substr(0, pos);
tmp = tmp.substr(pos + 1);
fragment = tmp;
logE << "query: '" << queryStr << "' fragment: '" << fragment << "' tmp: '" << tmp << "'\n";
}
vector<string> keyValueList = split(queryStr, '&');
for (auto& kv: keyValueList)
{
pos = kv.find('=');
if (pos != string::npos)
query[kv.substr(0, pos)] = kv.substr(pos+1);
}
// for (auto& kv: query)
// logD << "key: '" << kv.first << "' value: '" << kv.second << "'\n";
}
PcmReader::PcmReader(PcmListener* pcmListener, const ReaderUri& uri) : pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20) PcmReader::PcmReader(PcmListener* pcmListener, const ReaderUri& uri) : pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20)
{ {

View file

@ -23,6 +23,7 @@
#include <atomic> #include <atomic>
#include <string> #include <string>
#include <map> #include <map>
#include "readerUri.h"
#include "../encoder/encoder.h" #include "../encoder/encoder.h"
#include "message/sampleFormat.h" #include "message/sampleFormat.h"
#include "message/header.h" #include "message/header.h"
@ -43,27 +44,6 @@ public:
}; };
struct ReaderUri
{
ReaderUri(const std::string& uri);
std::string uri;
std::string scheme;
/* struct Authority
{
std::string username;
std::string password;
std::string host;
size_t port;
};
Authority authority;
*/
std::string host;
std::string path;
std::map<std::string, std::string> query;
std::string fragment;
};
/// Reads and decodes PCM data /// Reads and decodes PCM data
/** /**
* Reads PCM and passes the data to an encoder. * Reads PCM and passes the data to an encoder.

View file

@ -0,0 +1,96 @@
/***
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 <common/utils.h>
#include <common/compat.h>
#include <common/log.h>
#include "readerUri.h"
using namespace std;
ReaderUri::ReaderUri(const std::string& uri)
{
// https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
// 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 :(
size_t pos;
this->uri = uri;
string tmp(uri);
pos = tmp.find(':');
if (pos == string::npos)
throw invalid_argument("missing ':'");
scheme = tmp.substr(0, pos);
tmp = tmp.substr(pos + 1);
logE << "scheme: '" << scheme << "' tmp: '" << tmp << "'\n";
if (tmp.find("//") != 0)
throw invalid_argument("missing host separator: '//'");
tmp = tmp.substr(2);
pos = tmp.find('/');
if (pos == string::npos)
throw invalid_argument("missing path separator: '/'");
host = tmp.substr(0, pos);
tmp = tmp.substr(pos);
path = tmp;
logE << "host: '" << host << "' tmp: '" << tmp << "' path: '" << path << "'\n";
pos = tmp.find('?');
if (pos == string::npos)
return;
path = tmp.substr(0, pos);
tmp = tmp.substr(pos + 1);
string queryStr = tmp;
logE << "path: '" << path << "' tmp: '" << tmp << "' query: '" << queryStr << "'\n";
pos = tmp.find('#');
if (pos != string::npos)
{
queryStr = tmp.substr(0, pos);
tmp = tmp.substr(pos + 1);
fragment = tmp;
logE << "query: '" << queryStr << "' fragment: '" << fragment << "' tmp: '" << tmp << "'\n";
}
vector<string> keyValueList = split(queryStr, '&');
for (auto& kv: keyValueList)
{
pos = kv.find('=');
if (pos != string::npos)
query[kv.substr(0, pos)] = kv.substr(pos+1);
}
}
json ReaderUri::toJson() const
{
json j;
j["uri"] = uri;
j["scheme"] = scheme;
j["host"] = host;
j["path"] = path;
j["fragment"] = fragment;
j["query"] = json(query);
return j;
}

View file

@ -0,0 +1,52 @@
/***
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 READER_URI_H
#define READER_URI_H
#include <string>
#include <map>
#include "../json/json.hpp"
using json = nlohmann::json;
struct ReaderUri
{
ReaderUri(const std::string& uri);
std::string uri;
std::string scheme;
/* struct Authority
{
std::string username;
std::string password;
std::string host;
size_t port;
};
Authority authority;
*/
std::string host;
std::string path;
std::map<std::string, std::string> query;
std::string fragment;
json toJson() const;
};
#endif

View file

@ -88,4 +88,12 @@ void StreamManager::stop()
} }
json StreamManager::toJson() const
{
json result = json::array();
for (auto stream: streams_)
result.push_back(stream->getUri().toJson());
return result;
}

View file

@ -18,6 +18,7 @@ public:
void stop(); void stop();
const std::vector<PcmReaderPtr>& getStreams(); const std::vector<PcmReaderPtr>& getStreams();
const PcmReaderPtr getDefaultStream(); const PcmReaderPtr getDefaultStream();
json toJson() const;
private: private:
std::vector<PcmReaderPtr> streams_; std::vector<PcmReaderPtr> streams_;

View file

@ -164,7 +164,7 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
{"version", VERSION} {"version", VERSION}
}}, }},
{"clients", jClient}, {"clients", jClient},
{"streams", "TODO"} {"streams", streamManager_->toJson()}
}; };
} }
else if (request.method == "Server.DeleteClient") else if (request.method == "Server.DeleteClient")
@ -342,7 +342,7 @@ void StreamServer::start()
streamManager_.reset(new StreamManager(this, settings_.sampleFormat, settings_.codec, settings_.streamReadMs)); streamManager_.reset(new StreamManager(this, settings_.sampleFormat, settings_.codec, settings_.streamReadMs));
for (auto& streamUri: settings_.pcmStreams) for (auto& streamUri: settings_.pcmStreams)
streamManager_->addStream(streamUri); logE << "Stream: " << streamManager_->addStream(streamUri)->getUri().toJson() << "\n";
streamManager_->start(); streamManager_->start();