1
0
Fork 0
mirror of https://github.com/badaix/snapcast.git synced 2025-07-12 14:17:46 +02:00

add clang-format file

reformat code
This commit is contained in:
badaix 2019-09-24 22:42:36 +02:00
parent b733f646ea
commit b20add3815
105 changed files with 7773 additions and 7723 deletions

20
.clang-format Normal file
View file

@ -0,0 +1,20 @@
---
AccessModifierOffset: '-4'
AllowShortBlocksOnASingleLine: 'false'
AllowShortCaseLabelsOnASingleLine: 'false'
AllowShortFunctionsOnASingleLine: None
AllowShortIfStatementsOnASingleLine: 'false'
AllowShortLoopsOnASingleLine: 'false'
AlwaysBreakTemplateDeclarations: 'true'
BreakBeforeBraces: Allman
ColumnLimit: '160'
IndentCaseLabels: 'true'
IndentWidth: '4'
Language: Cpp
MaxEmptyLinesToKeep: '3'
PenaltyBreakComment: '100000'
PointerAlignment: Left
Standard: Cpp11
UseTab: Never
...

View file

@ -1,5 +1,5 @@
# This file is part of snapcast
# Copyright (C) 2014-2018 Johannes Pohl
# Copyright (C) 2014-2019 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

47
client/browseZeroConf/browseAvahi.cpp Executable file → Normal file
View file

@ -18,13 +18,13 @@
***/
#include "browseAvahi.h"
#include <stdio.h>
#include "aixlog.hpp"
#include "common/snapException.h"
#include <assert.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <iostream>
#include "common/snapException.h"
#include "aixlog.hpp"
static AvahiSimplePoll* simple_poll = NULL;
@ -57,19 +57,9 @@ void BrowseAvahi::cleanUp()
}
void BrowseAvahi::resolve_callback(
AvahiServiceResolver *r,
AVAHI_GCC_UNUSED AvahiIfIndex interface,
AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event,
const char *name,
const char *type,
const char *domain,
const char *host_name,
const AvahiAddress *address,
uint16_t port,
AvahiStringList *txt,
AvahiLookupResultFlags flags,
void BrowseAvahi::resolve_callback(AvahiServiceResolver* r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event, const char* name, const char* type, const char* domain, const char* host_name,
const AvahiAddress* address, uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags flags,
AVAHI_GCC_UNUSED void* userdata)
{
BrowseAvahi* browseAvahi = static_cast<BrowseAvahi*>(userdata);
@ -80,7 +70,8 @@ void BrowseAvahi::resolve_callback(
switch (event)
{
case AVAHI_RESOLVER_FAILURE:
LOG(ERROR) << "(Resolver) Failed to resolve service '" << name << "' of type '" << type << "' in domain '" << domain << "': " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))) << "\n";
LOG(ERROR) << "(Resolver) Failed to resolve service '" << name << "' of type '" << type << "' in domain '" << domain
<< "': " << avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))) << "\n";
break;
case AVAHI_RESOLVER_FOUND:
@ -116,16 +107,8 @@ void BrowseAvahi::resolve_callback(
}
void BrowseAvahi::browse_callback(
AvahiServiceBrowser *b,
AvahiIfIndex interface,
AvahiProtocol protocol,
AvahiBrowserEvent event,
const char *name,
const char *type,
const char *domain,
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
void* userdata)
void BrowseAvahi::browse_callback(AvahiServiceBrowser* b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char* name,
const char* type, const char* domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata)
{
// AvahiClient* client = (AvahiClient*)userdata;
@ -149,7 +132,8 @@ void BrowseAvahi::browse_callback(
the callback function is called the server will free
the resolver for us. */
if (!(avahi_service_resolver_new(browseAvahi->client_, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0, resolve_callback, userdata)))
if (!(avahi_service_resolver_new(browseAvahi->client_, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0,
resolve_callback, userdata)))
LOG(ERROR) << "Failed to resolve service '" << name << "': " << avahi_strerror(avahi_client_errno(browseAvahi->client_)) << "\n";
break;
@ -195,7 +179,8 @@ bool BrowseAvahi::browse(const std::string& serviceName, mDNSResult& result, int
throw SnapException("BrowseAvahi - Failed to create client: " + std::string(avahi_strerror(error)));
/* Create the service browser */
if (!(sb_ = avahi_service_browser_new(client_, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, serviceName.c_str(), NULL, (AvahiLookupFlags)0, browse_callback, this)))
if (!(sb_ =
avahi_service_browser_new(client_, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET, serviceName.c_str(), NULL, (AvahiLookupFlags)0, browse_callback, this)))
throw SnapException("BrowseAvahi - Failed to create service browser: " + std::string(avahi_strerror(avahi_client_errno(client_))));
result_.valid = false;
@ -220,5 +205,3 @@ bool BrowseAvahi::browse(const std::string& serviceName, mDNSResult& result, int
throw;
}
}

14
client/browseZeroConf/browseAvahi.h Executable file → Normal file
View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -21,9 +21,9 @@
#include <avahi-client/client.h>
#include <avahi-client/lookup.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/malloc.h>
#include <avahi-common/simple-watch.h>
class BrowseAvahi;
@ -38,8 +38,12 @@ public:
private:
void cleanUp();
static void resolve_callback(AvahiServiceResolver *r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, AVAHI_GCC_UNUSED void* userdata);
static void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata);
static void resolve_callback(AvahiServiceResolver* r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol,
AvahiResolverEvent event, const char* name, const char* type, const char* domain, const char* host_name,
const AvahiAddress* address, uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags flags,
AVAHI_GCC_UNUSED void* userdata);
static void browse_callback(AvahiServiceBrowser* b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char* name,
const char* type, const char* domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata);
static void client_callback(AvahiClient* c, AvahiClientState state, AVAHI_GCC_UNUSED void* userdata);
AvahiClient* client_;
mDNSResult result_;

61
client/browseZeroConf/browseBonjour.cpp Executable file → Normal file
View file

@ -1,14 +1,14 @@
#include "browseBonjour.h"
#include <memory>
#include <iostream>
#include <deque>
#include <iostream>
#include <memory>
#ifdef WINDOWS
#include <WinSock2.h>
#include <Ws2tcpip.h>
#else
#include <sys/socket.h>
#include <netdb.h>
#include <sys/socket.h>
#endif
#include "aixlog.hpp"
@ -141,7 +141,9 @@ struct mDNSResolve
uint16_t port;
};
#define CHECKED(err) if((err)!=kDNSServiceErr_NoError)throw SnapException(BonjourGetError(err) + ":" + to_string(__LINE__));
#define CHECKED(err) \
if ((err) != kDNSServiceErr_NoError) \
throw SnapException(BonjourGetError(err) + ":" + to_string(__LINE__));
void runService(const DNSServiceHandle& service)
{
@ -173,20 +175,14 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
{
DNSServiceHandle service(new DNSServiceRef(NULL));
CHECKED(DNSServiceBrowse(service.get(), 0, 0, serviceName.c_str(), "local.",
[](DNSServiceRef service,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char* serviceName,
const char* regtype,
const char* replyDomain,
void* context)
{
[](DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
const char* serviceName, const char* regtype, const char* replyDomain, void* context) {
auto replyCollection = static_cast<deque<mDNSReply>*>(context);
CHECKED(errorCode);
replyCollection->push_back(mDNSReply{string(serviceName), string(regtype), string(replyDomain)});
}, &replyCollection));
},
&replyCollection));
runService(service);
}
@ -196,23 +192,16 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
{
DNSServiceHandle service(new DNSServiceRef(NULL));
for (auto& reply : replyCollection)
CHECKED(DNSServiceResolve(service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
[](DNSServiceRef service,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char* fullName,
const char* hosttarget,
uint16_t port,
uint16_t txtLen,
const unsigned char* txtRecord,
void* context)
{
CHECKED(
DNSServiceResolve(service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
[](DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* fullName,
const char* hosttarget, uint16_t port, uint16_t txtLen, const unsigned char* txtRecord, void* context) {
auto resultCollection = static_cast<deque<mDNSResolve>*>(context);
CHECKED(errorCode);
resultCollection->push_back(mDNSResolve{string(hosttarget), ntohs(port)});
}, &resolveCollection));
},
&resolveCollection));
runService(service);
}
@ -226,15 +215,8 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
{
resultCollection[i].port = resolve.port;
CHECKED(DNSServiceGetAddrInfo(service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
[](DNSServiceRef service,
DNSServiceFlags flags,
uint32_t interfaceIndex,
DNSServiceErrorType errorCode,
const char* hostname,
const sockaddr* address,
uint32_t ttl,
void* context)
{
[](DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
const char* hostname, const sockaddr* address, uint32_t ttl, void* context) {
auto result = static_cast<mDNSResult*>(context);
result->host = string(hostname);
@ -243,15 +225,14 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
char hostIP[NI_MAXHOST];
char hostService[NI_MAXSERV];
if (getnameinfo(address, sizeof(*address),
hostIP, sizeof(hostIP),
hostService, sizeof(hostService),
if (getnameinfo(address, sizeof(*address), hostIP, sizeof(hostIP), hostService, sizeof(hostService),
NI_NUMERICHOST | NI_NUMERICSERV) == 0)
result->ip = string(hostIP);
else
return;
result->valid = true;
}, &resultCollection[i++]));
},
&resultCollection[i++]));
}
runService(service);
}

0
client/browseZeroConf/browseBonjour.h Executable file → Normal file
View file

0
client/browseZeroConf/browsemDNS.h Executable file → Normal file
View file

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,19 +16,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "clientConnection.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "message/hello.h"
#include <iostream>
#include <mutex>
#include "clientConnection.h"
#include "common/strCompat.h"
#include "common/snapException.h"
#include "message/hello.h"
#include "aixlog.hpp"
using namespace std;
ClientConnection::ClientConnection(MessageReceiver* receiver, const std::string& host, size_t port) : socket_(nullptr), active_(false), connected_(false), messageReceiver_(receiver), reqId_(1), host_(host), port_(port), readerThread_(NULL), sumTimeout_(chronos::msec(0))
ClientConnection::ClientConnection(MessageReceiver* receiver, const std::string& host, size_t port)
: socket_(nullptr), active_(false), connected_(false), messageReceiver_(receiver), reqId_(1), host_(host), port_(port), readerThread_(NULL),
sumTimeout_(chronos::msec(0))
{
}
@ -49,8 +51,7 @@ void ClientConnection::socketRead(void* _to, size_t _bytes)
len += socket_->read_some(asio::buffer((char*)_to + len, toRead));
// cout << "len: " << len << ", error: " << error << endl;
toRead = _bytes - len;
}
while (toRead > 0);
} while (toRead > 0);
}
@ -99,9 +100,11 @@ void ClientConnection::stop()
if (socket_)
{
socket_->shutdown(asio::ip::tcp::socket::shutdown_both, ec);
if (ec) LOG(ERROR) << "Error in socket shutdown: " << ec.message() << endl;
if (ec)
LOG(ERROR) << "Error in socket shutdown: " << ec.message() << endl;
socket_->close(ec);
if (ec) LOG(ERROR) << "Error in socket close: " << ec.message() << endl;
if (ec)
LOG(ERROR) << "Error in socket close: " << ec.message() << endl;
}
if (readerThread_)
{
@ -174,7 +177,8 @@ void ClientConnection::getNextMessage()
vector<char> buffer(baseMsgSize);
socketRead(&buffer[0], baseMsgSize);
baseMessage.deserialize(&buffer[0]);
// LOG(DEBUG) << "getNextMessage: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " << baseMessage.refersTo << "\n";
// LOG(DEBUG) << "getNextMessage: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " <<
//baseMessage.refersTo << "\n";
if (baseMessage.size > buffer.size())
buffer.resize(baseMessage.size);
// {
@ -186,7 +190,8 @@ void ClientConnection::getNextMessage()
{
std::unique_lock<std::mutex> lock(pendingRequestsMutex_);
// LOG(DEBUG) << "got lock - getNextMessage: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " << baseMessage.refersTo << "\n";
// LOG(DEBUG) << "got lock - getNextMessage: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ",
//refers: " << baseMessage.refersTo << "\n";
{
for (auto req : pendingRequests_)
{
@ -230,7 +235,3 @@ void ClientConnection::reader()
connected_ = false;
active_ = false;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,16 +19,16 @@
#ifndef CLIENT_CONNECTION_H
#define CLIENT_CONNECTION_H
#include "common/timeDefs.h"
#include "message/message.h"
#include <asio.hpp>
#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <thread>
#include <atomic>
#include <mutex>
#include <memory>
#include <asio.hpp>
#include <condition_variable>
#include <set>
#include "message/message.h"
#include "common/timeDefs.h"
using asio::ip::tcp;
@ -130,7 +130,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,37 +16,29 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <iostream>
#include <string>
#include <memory>
#include "controller.h"
#include "decoder/pcmDecoder.h"
#include <iostream>
#include <memory>
#include <string>
#if defined(HAS_OGG) && (defined(HAS_TREMOR) || defined(HAS_VORBIS))
#include "decoder/oggDecoder.h"
#endif
#if defined(HAS_FLAC)
#include "decoder/flacDecoder.h"
#endif
#include "timeProvider.h"
#include "message/time.h"
#include "message/hello.h"
#include "common/snapException.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "message/hello.h"
#include "message/time.h"
#include "timeProvider.h"
using namespace std;
Controller::Controller(const std::string& hostId, size_t instance, std::shared_ptr<MetadataAdapter> meta) : MessageReceiver(),
hostId_(hostId),
instance_(instance),
active_(false),
latency_(0),
stream_(nullptr),
decoder_(nullptr),
player_(nullptr),
meta_(meta),
serverSettings_(nullptr),
async_exception_(nullptr)
Controller::Controller(const std::string& hostId, size_t instance, std::shared_ptr<MetadataAdapter> meta)
: MessageReceiver(), hostId_(hostId), instance_(instance), active_(false), latency_(0), stream_(nullptr), decoder_(nullptr), player_(nullptr), meta_(meta),
serverSettings_(nullptr), async_exception_(nullptr)
{
}
@ -72,7 +64,8 @@ void Controller::onMessageReceived(ClientConnection* connection, const msg::Base
{
// TODO: do decoding in thread?
stream_->addChunk(pcmChunk);
//LOG(DEBUG) << ", decoded: " << pcmChunk->payloadSize << ", Duration: " << pcmChunk->getDuration() << ", sec: " << pcmChunk->timestamp.sec << ", usec: " << pcmChunk->timestamp.usec/1000 << ", type: " << pcmChunk->type << "\n";
// LOG(DEBUG) << ", decoded: " << pcmChunk->payloadSize << ", Duration: " << pcmChunk->getDuration() << ", sec: " << pcmChunk->timestamp.sec <<
// ", usec: " << pcmChunk->timestamp.usec/1000 << ", type: " << pcmChunk->type << "\n";
}
else
delete pcmChunk;
@ -88,7 +81,8 @@ void Controller::onMessageReceived(ClientConnection* connection, const msg::Base
{
serverSettings_.reset(new msg::ServerSettings());
serverSettings_->deserialize(baseMessage, buffer);
LOG(INFO) << "ServerSettings - buffer: " << serverSettings_->getBufferMs() << ", latency: " << serverSettings_->getLatency() << ", volume: " << serverSettings_->getVolume() << ", muted: " << serverSettings_->isMuted() << "\n";
LOG(INFO) << "ServerSettings - buffer: " << serverSettings_->getBufferMs() << ", latency: " << serverSettings_->getLatency()
<< ", volume: " << serverSettings_->getVolume() << ", muted: " << serverSettings_->isMuted() << "\n";
if (stream_ && player_)
{
player_->setVolume(serverSettings_->getVolume() / 100.);
@ -254,6 +248,3 @@ void Controller::worker()
}
LOG(DEBUG) << "Thread stopped\n";
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,13 +19,13 @@
#ifndef CONTROLLER_H
#define CONTROLLER_H
#include <thread>
#include <atomic>
#include "decoder/decoder.h"
#include "message/message.h"
#include "message/serverSettings.h"
#include "message/streamTags.h"
#include "player/pcmDevice.h"
#include <atomic>
#include <thread>
#ifdef HAS_ALSA
#include "player/alsaPlayer.h"
#elif HAS_OPENSL
@ -34,8 +34,8 @@
#include "player/coreAudioPlayer.h"
#endif
#include "clientConnection.h"
#include "stream.h"
#include "metadata.h"
#include "stream.h"
/// Forwards PCM data to the audio player
@ -86,4 +86,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -18,10 +18,10 @@
#ifndef DECODER_H
#define DECODER_H
#include <mutex>
#include "message/pcmChunk.h"
#include "message/codecHeader.h"
#include "common/sampleFormat.h"
#include "message/codecHeader.h"
#include "message/pcmChunk.h"
#include <mutex>
class Decoder
@ -38,5 +38,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,20 +16,21 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <iostream>
#include <cstring>
#include <cmath>
#include "flacDecoder.h"
#include "common/snapException.h"
#include "common/endian.hpp"
#include "aixlog.hpp"
#include "common/endian.hpp"
#include "common/snapException.h"
#include <cmath>
#include <cstring>
#include <iostream>
using namespace std;
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data);
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[],
void* client_data);
static void metadata_callback(const FLAC__StreamDecoder* decoder, const FLAC__StreamMetadata* metadata, void* client_data);
static void error_callback(const FLAC__StreamDecoder* decoder, FLAC__StreamDecoderErrorStatus status, void* client_data);
@ -144,7 +145,8 @@ FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder *decoder,
}
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 * const buffer[], void *client_data)
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__StreamDecoder* decoder, const FLAC__Frame* frame, const FLAC__int32* const buffer[],
void* client_data)
{
(void)decoder;
@ -199,10 +201,7 @@ void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMet
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
{
static_cast<FlacDecoder*>(client_data)->cacheInfo_.sampleRate_ = metadata->data.stream_info.sample_rate;
sampleFormat.setFormat(
metadata->data.stream_info.sample_rate,
metadata->data.stream_info.bits_per_sample,
metadata->data.stream_info.channels);
sampleFormat.setFormat(metadata->data.stream_info.sample_rate, metadata->data.stream_info.bits_per_sample, metadata->data.stream_info.channels);
}
}
@ -223,8 +222,3 @@ void error_callback(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderError
// Oct 27 17:47:13 kitchen snapclient[869]: Got error callback: FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM
// Oct 27 17:47:13 kitchen snapclient[869]: Got error callback: FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -60,5 +60,3 @@ public:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,14 +16,14 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstring>
#include <iostream>
#include "oggDecoder.h"
#include "common/snapException.h"
#include "common/endian.hpp"
#include "aixlog.hpp"
#include "common/endian.hpp"
#include "common/snapException.h"
#include "oggDecoder.h"
using namespace std;
@ -229,7 +229,8 @@ SampleFormat OggDecoder::setHeader(msg::CodecHeader* chunk)
std::string comment(*ptr);
if (comment.find("SAMPLE_FORMAT=") == 0)
sampleFormat_.setFormat(comment.substr(comment.find("=") + 1));
LOG(INFO) << "comment: " << comment << "\n";;
LOG(INFO) << "comment: " << comment << "\n";
;
++ptr;
}
@ -237,6 +238,3 @@ SampleFormat OggDecoder::setHeader(msg::CodecHeader* chunk)
return sampleFormat_;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -39,8 +39,10 @@ private:
template <typename T>
T clip(const T& value, const T& lower, const T& upper) const
{
if (value > upper) return upper;
if (value < lower) return lower;
if (value > upper)
return upper;
if (value < lower)
return lower;
return value;
}
@ -59,5 +61,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,10 +16,10 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "common/snapException.h"
#include "common/endian.hpp"
#include "aixlog.hpp"
#include "pcmDecoder.h"
#include "aixlog.hpp"
#include "common/endian.hpp"
#include "common/snapException.h"
#define ID_RIFF 0x46464952
@ -108,21 +108,13 @@ SampleFormat PcmDecoder::setHeader(msg::CodecHeader* chunk)
/// Unknown chunk, skip bytes
pos += SWAP_32(chunk_header.sz);
}
}
while (moreChunks);
} while (moreChunks);
if (SWAP_32(chunk_fmt.sample_rate) == 0)
throw SnapException("Sample format not found");
SampleFormat sampleFormat(
SWAP_32(chunk_fmt.sample_rate),
SWAP_16(chunk_fmt.bits_per_sample),
SWAP_16(chunk_fmt.num_channels));
SampleFormat sampleFormat(SWAP_32(chunk_fmt.sample_rate), SWAP_16(chunk_fmt.bits_per_sample), SWAP_16(chunk_fmt.num_channels));
return sampleFormat;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -31,5 +31,3 @@ public:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,8 +19,8 @@
#ifndef DOUBLE_BUFFER_H
#define DOUBLE_BUFFER_H
#include<deque>
#include <algorithm>
#include <deque>
/// Size limited queue
@ -126,11 +126,8 @@ public:
private:
size_t bufferSize;
std::deque<T> buffer;
};
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -98,7 +98,6 @@ public:
std::cerr << serialize() << "\n";
return 0;
}
};
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -26,8 +26,7 @@
using namespace std;
AlsaPlayer::AlsaPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
Player(pcmDevice, stream), handle_(NULL), buff_(NULL)
AlsaPlayer::AlsaPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) : Player(pcmDevice, stream), handle_(NULL), buff_(NULL)
{
}
@ -273,9 +272,12 @@ vector<PcmDevice> AlsaPlayer::pcm_list(void)
if (io != NULL && strcmp(io, "Output") != 0)
goto __end;
pcmDevice.name = name;
if(descr == NULL) {
if (descr == NULL)
{
pcmDevice.description = "";
} else {
}
else
{
pcmDevice.description = descr;
}
pcmDevice.idx = idx++;
@ -293,4 +295,3 @@ __end:
snd_device_name_free_hint(hints);
return result;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -54,4 +54,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -17,8 +17,8 @@
***/
//#include <CoreServices/CoreServices.h>
#include <CoreAudio/CoreAudio.h>
#include "coreAudioPlayer.h"
#include <CoreAudio/CoreAudio.h>
#define NUM_BUFFERS 2
@ -33,10 +33,7 @@ void callback(void *custom_data, AudioQueueRef queue, AudioQueueBufferRef buffer
}
CoreAudioPlayer::CoreAudioPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
Player(pcmDevice, stream),
ms_(100),
pubStream_(stream)
CoreAudioPlayer::CoreAudioPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) : Player(pcmDevice, stream), ms_(100), pubStream_(stream)
{
}
@ -51,9 +48,7 @@ std::vector<PcmDevice> CoreAudioPlayer::pcm_list(void)
{
UInt32 propsize;
AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster };
AudioObjectPropertyAddress theAddress = {kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &theAddress, 0, NULL, &propsize);
int nDevices = propsize / sizeof(AudioDeviceID);

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -58,4 +58,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,10 +19,10 @@
#include <assert.h>
#include <iostream>
#include "openslPlayer.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "openslPlayer.h"
using namespace std;
@ -43,19 +43,9 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
OpenslPlayer::OpenslPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
Player(pcmDevice, stream),
engineObject(NULL),
engineEngine(NULL),
outputMixObject(NULL),
bqPlayerObject(NULL),
bqPlayerPlay(NULL),
bqPlayerBufferQueue(NULL),
bqPlayerVolume(NULL),
curBuffer(0),
ms_(50),
buff_size(0),
pubStream_(stream)
OpenslPlayer::OpenslPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream)
: Player(pcmDevice, stream), engineObject(NULL), engineEngine(NULL), outputMixObject(NULL), bqPlayerObject(NULL), bqPlayerPlay(NULL),
bqPlayerBufferQueue(NULL), bqPlayerVolume(NULL), curBuffer(0), ms_(50), buff_size(0), pubStream_(stream)
{
initOpensl();
}
@ -200,10 +190,7 @@ void OpenslPlayer::initOpensl()
SLresult result;
// create engine
SLEngineOption engineOption[] =
{
{(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
};
SLEngineOption engineOption[] = {{(SLuint32)SL_ENGINEOPTION_THREADSAFE, (SLuint32)SL_BOOLEAN_TRUE}};
result = slCreateEngine(&engineObject, 1, engineOption, 0, NULL, NULL);
throwUnsuccess("slCreateEngine", result);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
@ -284,16 +271,9 @@ void OpenslPlayer::initOpensl()
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm =
{
SL_DATAFORMAT_PCM,
format.channels,
samplesPerSec,
bitsPerSample,
containerSize,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN
};
SLDataFormat_PCM format_pcm = {
SL_DATAFORMAT_PCM, format.channels, samplesPerSec, bitsPerSample, containerSize, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
@ -413,4 +393,3 @@ void OpenslPlayer::stop()
void OpenslPlayer::worker()
{
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -74,4 +74,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -24,15 +24,9 @@
struct PcmDevice
{
PcmDevice() :
idx(-1), name("default")
{
};
PcmDevice() : idx(-1), name("default"){};
PcmDevice(int idx, const std::string& name, const std::string& description = "") :
idx(idx), name(name), description(description)
{
};
PcmDevice(int idx, const std::string& name, const std::string& description = "") : idx(idx), name(name), description(description){};
int idx;
std::string name;
@ -41,4 +35,3 @@ struct PcmDevice
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,23 +16,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <iostream>
#include <cmath>
#include <iostream>
#include "player.h"
#include "aixlog.hpp"
#include "player.h"
using namespace std;
Player::Player(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
active_(false),
stream_(stream),
pcmDevice_(pcmDevice),
volume_(1.0),
muted_(false),
volCorrection_(1.0)
Player::Player(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream)
: active_(false), stream_(stream), pcmDevice_(pcmDevice), volume_(1.0), muted_(false), volCorrection_(1.0)
{
}
@ -113,5 +108,3 @@ void Player::setMute(bool mute)
{
muted_ = mute;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,14 +19,14 @@
#ifndef PLAYER_H
#define PLAYER_H
#include "aixlog.hpp"
#include "common/endian.hpp"
#include "pcmDevice.h"
#include "stream.h"
#include <atomic>
#include <string>
#include <thread>
#include <atomic>
#include <vector>
#include "stream.h"
#include "pcmDevice.h"
#include "common/endian.hpp"
#include "aixlog.hpp"
/// Audio Player
@ -72,4 +72,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,9 +19,9 @@
#include <iostream>
#include <sys/resource.h>
#include "popl.hpp"
#include "controller.h"
#include "browseZeroConf/browsemDNS.h"
#include "controller.h"
#include "popl.hpp"
#ifdef HAS_ALSA
#include "player/alsaPlayer.h"
@ -131,8 +131,7 @@ int main (int argc, char **argv)
vector<PcmDevice> pcmDevices = AlsaPlayer::pcm_list();
for (auto dev : pcmDevices)
{
cout << dev.idx << ": " << dev.name << "\n"
<< dev.description << "\n\n";
cout << dev.idx << ": " << dev.name << "\n" << dev.description << "\n\n";
}
exit(EXIT_SUCCESS);
}
@ -162,7 +161,8 @@ int main (int argc, char **argv)
{
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::trace, AixLog::Type::all, "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
if (!debugOption->value().empty())
AixLog::Log::instance().add_logsink<AixLog::SinkFile>(AixLog::Severity::trace, AixLog::Type::all, debugOption->value(), "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
AixLog::Log::instance().add_logsink<AixLog::SinkFile>(AixLog::Severity::trace, AixLog::Type::all, debugOption->value(),
"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
}
else
{
@ -268,5 +268,3 @@ int main (int argc, char **argv)
SLOG(NOTICE) << "daemon terminated." << endl;
exit(exitcode);
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -17,18 +17,19 @@
***/
#include "stream.h"
#include "aixlog.hpp"
#include "timeProvider.h"
#include <cmath>
#include <iostream>
#include <string.h>
#include "aixlog.hpp"
#include "timeProvider.h"
using namespace std;
// using namespace chronos;
namespace cs = chronos;
Stream::Stream(const SampleFormat& sampleFormat) : format_(sampleFormat), sleep_(0), median_(0), shortMedian_(0), lastUpdate_(0), playedFrames_(0), bufferMs_(cs::msec(500))
Stream::Stream(const SampleFormat& sampleFormat)
: format_(sampleFormat), sleep_(0), median_(0), shortMedian_(0), lastUpdate_(0), playedFrames_(0), bufferMs_(cs::msec(500))
{
buffer_.setSize(500);
shortBuffer_.setSize(100);
@ -242,7 +243,8 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
{
LOG(INFO) << "sleep < -bufferDuration/2: " << cs::duration<cs::msec>(sleep_) << " < " << -cs::duration<cs::msec>(bufferDuration) / 2 << ", ";
// We're early: not enough chunks_. play silence. Reference chunk_ is the oldest (front) one
sleep_ = chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - getSilentPlayerChunk(outputBuffer, framesPerBuffer) - bufferMs_ + outputBufferDacTime);
sleep_ = chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - getSilentPlayerChunk(outputBuffer, framesPerBuffer) - bufferMs_ +
outputBufferDacTime);
LOG(INFO) << "sleep: " << cs::duration<cs::msec>(sleep_) << "\n";
if (sleep_ < -bufferDuration / 2)
return true;
@ -253,7 +255,9 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
// We're late: discard oldest chunks
while (sleep_ > chunk_->duration<cs::usec>())
{
LOG(INFO) << "sleep > chunkDuration: " << cs::duration<cs::msec>(sleep_) << " > " << chunk_->duration<cs::msec>().count() << ", chunks: " << chunks_.size() << ", out: " << cs::duration<cs::msec>(outputBufferDacTime) << ", needed: " << cs::duration<cs::msec>(bufferDuration) << "\n";
LOG(INFO) << "sleep > chunkDuration: " << cs::duration<cs::msec>(sleep_) << " > " << chunk_->duration<cs::msec>().count()
<< ", chunks: " << chunks_.size() << ", out: " << cs::duration<cs::msec>(outputBufferDacTime)
<< ", needed: " << cs::duration<cs::msec>(bufferDuration) << "\n";
sleep_ = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - chunk_->start() - bufferMs_ + outputBufferDacTime);
if (!chunks_.try_pop(chunk_, outputBufferDacTime))
{
@ -294,7 +298,9 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
playedFrames_ -= abs(correctAfterXFrames_);
}
age = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - getNextPlayerChunk(outputBuffer, outputBufferDacTime, framesPerBuffer, framesCorrection) - bufferMs_ + outputBufferDacTime);
age = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() -
getNextPlayerChunk(outputBuffer, outputBufferDacTime, framesPerBuffer, framesCorrection) - bufferMs_ +
outputBufferDacTime);
setRealSampleRate(format_.rate);
if (sleep_.count() == 0)
@ -341,7 +347,8 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
if (lastAge != msAge)
{
lastAge = msAge;
LOG(INFO) << "Sleep " << cs::duration<cs::msec>(sleep_) << ", age: " << msAge << ", bufferDuration: " << cs::duration<cs::msec>(bufferDuration) << "\n";
LOG(INFO) << "Sleep " << cs::duration<cs::msec>(sleep_) << ", age: " << msAge << ", bufferDuration: " << cs::duration<cs::msec>(bufferDuration)
<< "\n";
}
}
else if (shortBuffer_.full())
@ -361,8 +368,10 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
lastUpdate_ = now;
median_ = buffer_.median();
shortMedian_ = shortBuffer_.median();
LOG(INFO) << "Chunk: " << age.count()/100 << "\t" << miniBuffer_.median()/100 << "\t" << shortMedian_/100 << "\t" << median_/100 << "\t" << buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\n";
// LOG(INFO) << "Chunk: " << age.count()/1000 << "\t" << miniBuffer_.median()/1000 << "\t" << shortMedian_/1000 << "\t" << median_/1000 << "\t" << buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\n";
LOG(INFO) << "Chunk: " << age.count() / 100 << "\t" << miniBuffer_.median() / 100 << "\t" << shortMedian_ / 100 << "\t" << median_ / 100 << "\t"
<< buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\n";
// LOG(INFO) << "Chunk: " << age.count()/1000 << "\t" << miniBuffer_.median()/1000 << "\t" << shortMedian_/1000 << "\t" << median_/1000 << "\t"
//<< buffer_.size() << "\t" << cs::duration<cs::msec>(outputBufferDacTime) << "\n";
}
return (abs(cs::duration<cs::msec>(age)) < 500);
}
@ -372,6 +381,3 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
return false;
}
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -25,13 +25,13 @@
//#include <chrono>
//#include "common/timeUtils.h"
#include <deque>
#include <memory>
#include "common/queue.h"
#include "common/sampleFormat.h"
#include "doubleBuffer.h"
#include "message/message.h"
#include "message/pcmChunk.h"
#include "common/sampleFormat.h"
#include "common/queue.h"
#include <deque>
#include <memory>
/// Time synchronized audio stream
@ -94,5 +94,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -61,4 +61,3 @@ long TimeProvider::getPercentileDiffToServer(size_t percentile)
return diffBuffer.percentile(percentile);
}
*/

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,11 +19,11 @@
#ifndef TIME_PROVIDER_H
#define TIME_PROVIDER_H
#include <atomic>
#include <chrono>
#include "common/timeDefs.h"
#include "doubleBuffer.h"
#include "message/message.h"
#include "common/timeDefs.h"
#include <atomic>
#include <chrono>
/// Provides local and server time
@ -87,5 +87,3 @@ private:
#endif

View file

@ -1,5 +1,5 @@
# This file is part of snapcast
# Copyright (C) 2014-2018 Johannes Pohl
# Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -18,27 +18,24 @@
#include "daemon.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <syslog.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <grp.h>
#include <iostream>
#include "common/snapException.h"
#include "common/strCompat.h"
#include "common/utils/file_utils.h"
#include "common/utils.h"
#include "common/utils/file_utils.h"
#include <fcntl.h>
#include <grp.h>
#include <iostream>
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <syslog.h>
#include <unistd.h>
Daemon::Daemon(const std::string& user, const std::string& group, const std::string& pidfile) :
pidFilehandle_(-1),
user_(user),
group_(group),
pidfile_(pidfile)
Daemon::Daemon(const std::string& user, const std::string& group, const std::string& pidfile)
: pidFilehandle_(-1), user_(user), group_(group), pidfile_(pidfile)
{
if (pidfile.empty() || pidfile.find('/') == std::string::npos)
throw SnapException("invalid pid file \"" + pidfile + "\"");
@ -166,6 +163,3 @@ void Daemon::daemonize()
close(STDOUT_FILENO);
close(STDERR_FILENO);
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -62,10 +62,7 @@ protected:
writeVal(stream, payload, payloadSize);
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,9 +19,9 @@
#ifndef HELLO_MSG_H
#define HELLO_MSG_H
#include "jsonMessage.h"
#include "common/utils.h"
#include "common/strCompat.h"
#include "common/utils.h"
#include "jsonMessage.h"
#include <string>
@ -108,10 +108,7 @@ public:
return id;
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,8 +19,8 @@
#ifndef JSON_MESSAGE_H
#define JSON_MESSAGE_H
#include "message.h"
#include "common/json.hpp"
#include "message.h"
using json = nlohmann::json;
@ -76,10 +76,7 @@ protected:
}
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,14 +19,14 @@
#ifndef MESSAGE_H
#define MESSAGE_H
#include "common/endian.hpp"
#include "common/timeDefs.h"
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <streambuf>
#include <vector>
#include <sys/time.h>
#include "common/endian.hpp"
#include "common/timeDefs.h"
#include <vector>
/*
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
@ -290,9 +290,7 @@ protected:
}
virtual void doserialize(std::ostream& stream) const
{
};
virtual void doserialize(std::ostream& stream) const {};
};
@ -306,9 +304,6 @@ struct SerializedMessage
BaseMessage message;
char* buffer;
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,10 +19,10 @@
#ifndef PCM_CHUNK_H
#define PCM_CHUNK_H
#include <chrono>
#include "common/sampleFormat.h"
#include "message.h"
#include "wireChunk.h"
#include "common/sampleFormat.h"
#include <chrono>
namespace msg
@ -36,17 +36,11 @@ namespace msg
class PcmChunk : public WireChunk
{
public:
PcmChunk(const SampleFormat& sampleFormat, size_t ms) :
WireChunk(sampleFormat.rate*sampleFormat.frameSize*ms / 1000),
format(sampleFormat),
idx_(0)
PcmChunk(const SampleFormat& sampleFormat, size_t ms) : WireChunk(sampleFormat.rate * sampleFormat.frameSize * ms / 1000), format(sampleFormat), idx_(0)
{
}
PcmChunk(const PcmChunk& pcmChunk) :
WireChunk(pcmChunk),
format(pcmChunk.format),
idx_(0)
PcmChunk(const PcmChunk& pcmChunk) : WireChunk(pcmChunk), format(pcmChunk.format), idx_(0)
{
}
@ -70,7 +64,8 @@ public:
memcpy((char*)outputBuffer, (char*)(payload) + format.frameSize * idx_, format.frameSize * result);
idx_ += result;
//logd << ", new idx: " << idx << ", result: " << result << ", wireChunk->length: " << wireChunk->length << ", format.frameSize: " << format.frameSize << "\n";//std::endl;
// logd << ", new idx: " << idx << ", result: " << result << ", wireChunk->length: " << wireChunk->length << ", format.frameSize: " << format.frameSize
// << "\n";//std::endl;
return result;
}
@ -89,11 +84,8 @@ public:
virtual chronos::time_point_clk start() const
{
return chronos::time_point_clk(
chronos::sec(timestamp.sec) +
chronos::usec(timestamp.usec) +
chronos::usec((chronos::usec::rep)(1000000. * ((double)idx_ / (double)format.rate)))
);
return chronos::time_point_clk(chronos::sec(timestamp.sec) + chronos::usec(timestamp.usec) +
chronos::usec((chronos::usec::rep)(1000000. * ((double)idx_ / (double)format.rate))));
}
inline chronos::time_point_clk end() const
@ -133,9 +125,6 @@ public:
private:
uint32_t idx_;
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -82,10 +82,7 @@ public:
msg["muted"] = muted;
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -69,10 +69,7 @@ public:
{
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -55,10 +55,7 @@ protected:
writeVal(stream, latency.usec);
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,14 +19,14 @@
#ifndef WIRE_CHUNK_H
#define WIRE_CHUNK_H
#include "common/timeDefs.h"
#include "message.h"
#include <chrono>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <streambuf>
#include <vector>
#include "message.h"
#include "common/timeDefs.h"
namespace msg
@ -84,10 +84,7 @@ protected:
writeVal(stream, payload, payloadSize);
}
};
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,17 +19,16 @@
#ifndef QUEUE_H
#define QUEUE_H
#include <deque>
#include <atomic>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <deque>
#include <mutex>
#include <thread>
template <typename T>
class Queue
{
public:
T pop()
{
std::unique_lock<std::mutex> mlock(mutex_);
@ -161,5 +160,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,15 +16,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <vector>
#include <iostream>
#include <sstream>
#include <vector>
#include "sampleFormat.h"
#include "common/strCompat.h"
#include "common/utils/string_utils.h"
#include "common/utils.h"
#include "aixlog.hpp"
#include "common/strCompat.h"
#include "common/utils.h"
#include "common/utils/string_utils.h"
#include "sampleFormat.h"
using namespace std;
@ -60,10 +60,7 @@ void SampleFormat::setFormat(const std::string& format)
std::vector<std::string> strs;
strs = utils::string::split(format, ':');
if (strs.size() == 3)
setFormat(
cpt::stoul(strs[0]),
cpt::stoul(strs[1]),
cpt::stoul(strs[2]));
setFormat(cpt::stoul(strs[0]), cpt::stoul(strs[1]), cpt::stoul(strs[2]));
}
@ -81,5 +78,3 @@ void SampleFormat::setFormat(uint32_t rate, uint16_t bits, uint16_t channels)
frameSize = channels * sampleSize;
// LOG(DEBUG) << "SampleFormat: " << rate << ":" << bits << ":" << channels << "\n";
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -31,7 +31,8 @@
* 1 frame represents 1 analog sample from all channels; here we have 2 channels, and so:
* 1 frame = (num_channels) * (1 sample in bytes) = (2 channels) * (2 bytes (16 bits) per sample) = 4 bytes (32 bits)
* To sustain 2x 44.1 KHz analog rate - the system must be capable of data transfer rate, in Bytes/sec:
* Bps_rate = (num_channels) * (1 sample in bytes) * (analog_rate) = (1 frame) * (analog_rate) = ( 2 channels ) * (2 bytes/sample) * (44100 samples/sec) = 2*2*44100 = 176400 Bytes/sec (link to formula img)
* Bps_rate = (num_channels) * (1 sample in bytes) * (analog_rate) = (1 frame) * (analog_rate) = ( 2 channels ) * (2 bytes/sample) * (44100 samples/sec) =
* 2*2*44100 = 176400 Bytes/sec (link to formula img)
*/
class SampleFormat
{
@ -73,4 +74,3 @@ public:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -47,5 +47,3 @@ void signal_handler(int sig)
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,13 +19,15 @@
#ifndef SNAP_EXCEPTION_H
#define SNAP_EXCEPTION_H
#include <cstring> // std::strlen, std::strcpy
#include <exception>
#include <string>
#include <cstring> // std::strlen, std::strcpy
// text_exception uses a dynamically-allocated internal c-string for what():
class SnapException : public std::exception {
class SnapException : public std::exception
{
char* text_;
public:
SnapException(const char* text)
{
@ -78,5 +80,3 @@ public:
#endif

View file

@ -2,16 +2,16 @@
#define COMPAT_H
#include <string>
#include <clocale>
#include <string>
#ifdef NO_CPP11_STRING
#include <sstream>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <stdexcept>
#include <cerrno>
#include <climits>
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <stdexcept>
#endif
@ -103,4 +103,3 @@ namespace cpt
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -20,8 +20,8 @@
#define TIME_DEFS_H
#include <chrono>
#include <thread>
#include <sys/time.h>
#include <thread>
#ifdef MACOS
#include <mach/clock.h>
#include <mach/mach.h>
@ -119,5 +119,3 @@ namespace chronos
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -22,34 +22,34 @@
#include "common/strCompat.h"
#include "common/utils/string_utils.h"
#include <functional>
#include <cctype>
#include <locale>
#include <string>
#include <cstring>
#include <vector>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <memory>
#include <cerrno>
#include <cstring>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iomanip>
#include <iterator>
#include <sys/ioctl.h>
#include <locale>
#include <memory>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sstream>
#include <string>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <iomanip>
#include <vector>
#ifndef FREEBSD
#include <sys/sysinfo.h>
#endif
#include <sys/utsname.h>
#ifdef MACOS
#include <ifaddrs.h>
#include <net/if_dl.h>
#include <IOKit/IOCFPlugIn.h>
#include <IOKit/IOTypes.h>
#include <ifaddrs.h>
#include <net/if_dl.h>
#endif
#ifdef ANDROID
#include <sys/system_properties.h>
@ -186,12 +186,9 @@ static std::string generateUUID()
initialized = true;
}
std::stringstream ss;
ss << std::setfill('0') << std::hex
<< std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff)
<< "-" << std::setw(4) << (std::rand() % 0xffff)
<< "-" << std::setw(4) << (std::rand() % 0xffff)
<< "-" << std::setw(4) << (std::rand() % 0xffff)
<< "-" << std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff);
ss << std::setfill('0') << std::hex << std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff) << "-" << std::setw(4)
<< (std::rand() % 0xffff) << "-" << std::setw(4) << (std::rand() % 0xffff) << "-" << std::setw(4) << (std::rand() % 0xffff) << "-" << std::setw(4)
<< (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff);
return ss.str();
}
@ -278,7 +275,9 @@ static std::string getMacAddress(int sock)
}
}
}
else { /* handle error */ }
else
{ /* handle error */
}
it = (struct ifreq*)((char*)it + len);
i += len;
@ -289,13 +288,13 @@ static std::string getMacAddress(int sock)
char mac[19];
#ifndef FREEBSD
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifr.ifr_hwaddr.sa_data[0], (unsigned char)ifr.ifr_hwaddr.sa_data[1], (unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3], (unsigned char)ifr.ifr_hwaddr.sa_data[4], (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)ifr.ifr_hwaddr.sa_data[0], (unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2], (unsigned char)ifr.ifr_hwaddr.sa_data[3], (unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
#else
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
(unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[0], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[1], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[2],
(unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[3], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[4], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[5]);
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x", (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[0], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[1],
(unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[2], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[3],
(unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[4], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[5]);
#endif
return mac;
}
@ -343,5 +342,3 @@ static std::string getHostId(const std::string defaultId = "")
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,12 +19,12 @@
#ifndef FILE_UTILS_H
#define FILE_UTILS_H
#include "string_utils.h"
#include <fstream>
#include <grp.h>
#include <pwd.h>
#include <stdexcept>
#include <vector>
#include <fstream>
#include "string_utils.h"
namespace utils
@ -93,4 +93,3 @@ static int mkdirRecursive(const char *path, mode_t mode)
} // namespace utils
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,10 +19,10 @@
#ifndef STRING_UTILS_H
#define STRING_UTILS_H
#include <stdio.h>
#include <algorithm>
#include <string>
#include <sstream>
#include <stdio.h>
#include <string>
#include <vector>
namespace utils
@ -72,7 +72,8 @@ static inline std::string trim_copy(const std::string &s)
}
// decode %xx to char
static std::string uriDecode(const std::string& src) {
static std::string uriDecode(const std::string& src)
{
std::string ret;
char ch;
for (size_t i = 0; i < src.length(); i++)
@ -118,4 +119,3 @@ static std::vector<std::string> split(const std::string &s, char delim)
} // namespace utils
#endif

179
doc/snapcast_plain_icon.svg Normal file
View file

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="220mm"
height="220mm"
viewBox="0 0 779.52756 779.52755"
id="svg2"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="snapcast_plain_icon.svg"
inkscape:export-filename="/home/adminuser/Desktop/drawing.png"
inkscape:export-xdpi="90"
inkscape:export-ydpi="90">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffc107"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:zoom="0.70710678"
inkscape:cx="379.04793"
inkscape:cy="415.07164"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
inkscape:snap-page="true"
inkscape:snap-grids="true"
inkscape:snap-object-midpoints="true"
inkscape:snap-center="true"
inkscape:window-width="1440"
inkscape:window-height="847"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
borderlayer="false"
inkscape:showpageshadow="true" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-272.83465)">
<path
style="fill:#c8c8c8;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:33.33300018;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="M 500.92383 225.22852 L 386.56445 324.14062 L 278.33008 324.14062 L 278.33008 451.42773 L 384.92383 451.42773 L 500.92383 551.76758 L 500.92383 225.22852 z "
transform="translate(0,272.83462)"
id="polygon1-3" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="360.297"
sodipodi:ry="360.297"
sodipodi:start="5.7595865"
sodipodi:end="0.52359878"
d="m 701.65376,483.21367 a 360.297,360.297 0 0 1 0,360.29701"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-6"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="299.98151"
sodipodi:ry="299.98151"
sodipodi:start="5.8119464"
sodipodi:end="0.4712389"
d="m 656.91289,527.17343 a 299.98151,299.98151 0 0 1 0,272.37751"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-6-5"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="240.16534"
sodipodi:ry="240.16534"
sodipodi:start="5.8643063"
sodipodi:end="0.41887902"
d="m 609.02937,565.67814 a 240.16534,240.16534 0 0 1 0,195.36809"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-1"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="360.297"
sodipodi:ry="360.297"
sodipodi:start="3.6651914"
sodipodi:end="4.712389"
d="M 77.601053,483.21369 A 360.297,360.297 0 0 1 389.62742,303.06519"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-6-2"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="299.98151"
sodipodi:ry="299.98151"
sodipodi:start="3.7175513"
sodipodi:end="4.6600291"
d="M 138.04175,499.98055 A 299.98151,299.98151 0 0 1 373.92759,363.79179"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-6-5-7"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="240.16534"
sodipodi:ry="240.16534"
sodipodi:start="3.7699112"
sodipodi:end="4.6076692"
d="M 195.32957,522.19653 A 240.16534,240.16534 0 0 1 364.52329,424.51249"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-1-6"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="360.297"
sodipodi:ry="360.297"
sodipodi:start="1.5707963"
sodipodi:end="2.6179939"
d="M 389.62742,1023.6592 A 360.297,360.297 0 0 1 77.601055,843.51067"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-6-2-0"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="299.98151"
sodipodi:ry="299.98151"
sodipodi:start="1.6231562"
sodipodi:end="2.565634"
d="M 373.92759,962.93257 A 299.98151,299.98151 0 0 1 138.04175,826.74382"
sodipodi:open="true" />
<path
style="fill:#000000;fill-rule:evenodd;stroke:#ffffff;stroke-width:35;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:0"
id="path3353-6-5-7-6"
sodipodi:type="arc"
sodipodi:cx="389.62741"
sodipodi:cy="663.36218"
sodipodi:rx="240.16534"
sodipodi:ry="240.16534"
sodipodi:start="1.6755161"
sodipodi:end="2.5132741"
d="M 364.52329,902.21188 A 240.16534,240.16534 0 0 1 195.32957,804.52783"
sodipodi:open="true" />
</g>
</svg>

After

(image error) Size: 7.2 KiB

2
externals/Makefile vendored
View file

@ -1,5 +1,5 @@
# This file is part of snapcast
# Copyright (C) 2014-2018 Johannes Pohl
# Copyright (C) 2014-2019 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

View file

@ -1,5 +1,5 @@
# This file is part of snapcast
# Copyright (C) 2014-2018 Johannes Pohl
# Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -17,15 +17,15 @@
***/
#include "config.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <fstream>
#include <cerrno>
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "common/utils/file_utils.h"
#include "aixlog.hpp"
#include <cerrno>
#include <fcntl.h>
#include <fstream>
#include <sys/stat.h>
#include <sys/types.h>
using namespace std;
@ -120,10 +120,7 @@ void Config::save()
if (filename_.empty())
init();
std::ofstream ofs(filename_.c_str(), std::ofstream::out | std::ofstream::trunc);
json clients = {
{"ConfigVersion", 2},
{"Groups", getGroups()}
};
json clients = {{"ConfigVersion", 2}, {"Groups", getGroups()}};
ofs << std::setw(4) << clients;
ofs.close();
}
@ -207,14 +204,11 @@ json Config::getServerStatus(const json& streams) const
host.update();
// TODO: Set MAC and IP
Snapserver snapserver("Snapserver", VERSION);
json serverStatus = {
{"server", {
{"host", host.toJson()},//getHostName()},
{"snapserver", snapserver.toJson()}
}},
json serverStatus = {{"server",
{{"host", host.toJson()}, // getHostName()},
{"snapserver", snapserver.toJson()}}},
{"groups", getGroups()},
{"streams", streams}
};
{"streams", streams}};
return serverStatus;
}
@ -287,5 +281,3 @@ GroupPtr Config::setGroupForClient(const std::string& groupId, const std::string
return newGroup;
}
*/

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,14 +19,14 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <string>
#include <memory>
#include <vector>
#include <string>
#include <sys/time.h>
#include <vector>
#include "common/json.hpp"
#include "common/utils/string_utils.h"
#include "common/utils.h"
#include "common/utils/string_utils.h"
namespace strutils = utils::string;

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,13 +16,13 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include "jsonrpcpp.hpp"
#include "controlServer.h"
#include "message/time.h"
#include "aixlog.hpp"
#include "common/utils.h"
#include "common/snapException.h"
#include "common/utils.h"
#include "config.h"
#include "jsonrpcpp.hpp"
#include "message/time.h"
#include <iostream>
using namespace std;
@ -30,12 +30,8 @@ using namespace std;
using json = nlohmann::json;
ControlServer::ControlServer(asio::io_service* io_service, size_t port, ControlMessageReceiver* controlMessageReceiver) :
acceptor_v4_(nullptr),
acceptor_v6_(nullptr),
io_service_(io_service),
port_(port),
controlMessageReceiver_(controlMessageReceiver)
ControlServer::ControlServer(asio::io_service* io_service, size_t port, ControlMessageReceiver* controlMessageReceiver)
: acceptor_v4_(nullptr), acceptor_v6_(nullptr), io_service_(io_service), port_(port), controlMessageReceiver_(controlMessageReceiver)
{
}
@ -199,4 +195,3 @@ void ControlServer::stop()
for (auto s : sessions_)
s->stop();
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -20,18 +20,18 @@
#define CONTROL_SERVER_H
#include <asio.hpp>
#include <vector>
#include <thread>
#include <memory>
#include <mutex>
#include <set>
#include <sstream>
#include <mutex>
#include <thread>
#include <vector>
#include "controlSession.h"
#include "common/queue.h"
#include "common/sampleFormat.h"
#include "message/message.h"
#include "controlSession.h"
#include "message/codecHeader.h"
#include "message/message.h"
#include "message/serverSettings.h"
@ -77,5 +77,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,18 +16,17 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <iostream>
#include <mutex>
#include "controlSession.h"
#include "aixlog.hpp"
#include "message/pcmChunk.h"
#include <iostream>
#include <mutex>
using namespace std;
ControlSession::ControlSession(ControlMessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) :
active_(false), messageReceiver_(receiver)
ControlSession::ControlSession(ControlMessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) : active_(false), messageReceiver_(receiver)
{
socket_ = socket;
}
@ -62,9 +61,11 @@ void ControlSession::stop()
{
std::lock_guard<std::recursive_mutex> socketLock(socketMutex_);
socket_->shutdown(asio::ip::tcp::socket::shutdown_both, ec);
if (ec) LOG(ERROR) << "Error in socket shutdown: " << ec.message() << "\n";
if (ec)
LOG(ERROR) << "Error in socket shutdown: " << ec.message() << "\n";
socket_->close(ec);
if (ec) LOG(ERROR) << "Error in socket close: " << ec.message() << "\n";
if (ec)
LOG(ERROR) << "Error in socket close: " << ec.message() << "\n";
}
if (readerThread_.joinable())
{
@ -170,5 +171,3 @@ void ControlSession::writer()
}
active_ = false;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,16 +19,16 @@
#ifndef CONTROL_SESSION_H
#define CONTROL_SESSION_H
#include "common/queue.h"
#include "message/message.h"
#include <asio.hpp>
#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <thread>
#include <atomic>
#include <mutex>
#include <memory>
#include <asio.hpp>
#include <condition_variable>
#include <set>
#include "message/message.h"
#include "common/queue.h"
using asio::ip::tcp;
@ -87,9 +87,4 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,12 +19,12 @@
#ifndef ENCODER_H
#define ENCODER_H
#include <string>
#include <memory>
#include <string>
#include "message/pcmChunk.h"
#include "message/codecHeader.h"
#include "common/sampleFormat.h"
#include "message/codecHeader.h"
#include "message/pcmChunk.h"
class Encoder;
@ -100,5 +100,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -24,9 +24,9 @@
#if defined(HAS_FLAC)
#include "flacEncoder.h"
#endif
#include "common/utils/string_utils.h"
#include "common/snapException.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/utils/string_utils.h"
using namespace std;
@ -69,6 +69,3 @@ Encoder* EncoderFactory::createEncoder(const std::string& codecSettings) const
}
*/
}

View file

@ -1,8 +1,8 @@
#ifndef ENCODER_FACTORY_H
#define ENCODER_FACTORY_H
#include <string>
#include "encoder.h"
#include <string>
class EncoderFactory
{

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -18,10 +18,10 @@
#include <iostream>
#include "flacEncoder.h"
#include "common/strCompat.h"
#include "common/snapException.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "flacEncoder.h"
using namespace std;
@ -71,7 +71,8 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
{
int samples = chunk->getSampleCount();
int frames = chunk->getFrameCount();
// LOG(INFO) << "payload: " << chunk->payloadSize << "\tframes: " << frames << "\tsamples: " << samples << "\tduration: " << chunk->duration<chronos::msec>().count() << "\n";
// LOG(INFO) << "payload: " << chunk->payloadSize << "\tframes: " << frames << "\tsamples: " << samples << "\tduration: " <<
//chunk->duration<chronos::msec>().count() << "\n";
if (pcmBufferSize_ < samples)
{
@ -112,10 +113,7 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
}
FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEncoder *encoder,
const FLAC__byte buffer[],
size_t bytes,
unsigned samples,
FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
unsigned current_frame)
{
// LOG(INFO) << "write_callback: " << bytes << ", " << samples << ", " << current_frame << "\n";
@ -136,12 +134,8 @@ FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEnc
}
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder,
const FLAC__byte buffer[],
size_t bytes,
unsigned samples,
unsigned current_frame,
void *client_data)
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
unsigned current_frame, void* client_data)
{
FlacEncoder* flacEncoder = (FlacEncoder*)client_data;
return flacEncoder->write_callback(encoder, buffer, bytes, samples, current_frame);
@ -187,15 +181,13 @@ void FlacEncoder::initEncoder()
throw SnapException("error setting up encoder");
// now add some metadata; we'll add some tags and a padding block
if (
(metadata_[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
if ((metadata_[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
(metadata_[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == NULL ||
// there are many tag (vorbiscomment) functions but these are convenient for this particular use:
!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "TITLE", "SnapStream") ||
!FLAC__metadata_object_vorbiscomment_append_comment(metadata_[0], entry, false) ||
!FLAC__metadata_object_vorbiscomment_entry_from_name_value_pair(&entry, "VERSION", VERSION) ||
!FLAC__metadata_object_vorbiscomment_append_comment(metadata_[0], entry, false)
)
!FLAC__metadata_object_vorbiscomment_append_comment(metadata_[0], entry, false))
throw SnapException("out of memory or tag error");
metadata_[1]->length = 1234; // set the padding length
@ -208,4 +200,3 @@ void FlacEncoder::initEncoder()
if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
throw SnapException("ERROR: initializing encoder: " + string(FLAC__StreamEncoderInitStatusString[init_status]));
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -37,7 +37,8 @@ public:
virtual std::string getDefaultOptions() const;
virtual std::string name() const;
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder *encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame);
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
unsigned current_frame);
protected:
virtual void initEncoder();
@ -54,5 +55,3 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,15 +16,15 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <iostream>
#include <cstring>
#include <iostream>
#include "oggEncoder.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "common/utils/string_utils.h"
#include "common/utils.h"
#include "aixlog.hpp"
#include "common/utils/string_utils.h"
#include "oggEncoder.h"
using namespace std;
@ -55,7 +55,8 @@ std::string OggEncoder::name() const
void OggEncoder::encode(const msg::PcmChunk* chunk)
{
double res = 0;
LOG(DEBUG) << "payload: " << chunk->payloadSize << "\tframes: " << chunk->getFrameCount() << "\tduration: " << chunk->duration<chronos::msec>().count() << "\n";
LOG(DEBUG) << "payload: " << chunk->payloadSize << "\tframes: " << chunk->getFrameCount() << "\tduration: " << chunk->duration<chronos::msec>().count()
<< "\n";
int frames = chunk->getFrameCount();
float** buffer = vorbis_analysis_buffer(&vd_, frames);
@ -256,5 +257,3 @@ void OggEncoder::initEncoder()
pos += og_.body_len;
}
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,8 +19,8 @@
#ifndef OGG_ENCODER_H
#define OGG_ENCODER_H
#include "encoder.h"
#include <vorbis/vorbisenc.h>
#include <ogg/ogg.h>
#include <vorbis/vorbisenc.h>
class OggEncoder : public Encoder
{
@ -50,5 +50,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,9 +16,9 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <memory>
#include "common/endian.hpp"
#include "pcmEncoder.h"
#include "common/endian.hpp"
#include <memory>
#define ID_RIFF 0x46464952
@ -65,5 +65,3 @@ std::string PcmEncoder::name() const
{
return "pcm";
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -41,5 +41,3 @@ protected:
#endif

View file

@ -17,18 +17,17 @@
USA.
***/
#include <cstdio>
#include <cstdlib>
#include "publishAvahi.h"
#include "aixlog.hpp"
#include <cstdio>
#include <cstdlib>
static AvahiEntryGroup* group;
static AvahiSimplePoll* simple_poll;
static char* name;
PublishAvahi::PublishAvahi(const std::string& serviceName) : PublishmDNS(serviceName),
client_(NULL), active_(false)
PublishAvahi::PublishAvahi(const std::string& serviceName) : PublishmDNS(serviceName), client_(NULL), active_(false)
{
group = NULL;
simple_poll = NULL;
@ -64,7 +63,8 @@ void PublishAvahi::publish(const std::vector<mDNSService>& services)
void PublishAvahi::worker()
{
while (active_ && (avahi_simple_poll_iterate(simple_poll, 100) == 0));
while (active_ && (avahi_simple_poll_iterate(simple_poll, 100) == 0))
;
}
@ -121,8 +121,7 @@ void PublishAvahi::entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState
break;
case AVAHI_ENTRY_GROUP_UNCOMMITED:
case AVAHI_ENTRY_GROUP_REGISTERING:
;
case AVAHI_ENTRY_GROUP_REGISTERING:;
}
}
@ -150,7 +149,8 @@ void PublishAvahi::create_services(AvahiClient *c)
/// We will now add two services and one subtype to the entry group
for (const auto& service : services_)
{
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, service.name_.c_str(), NULL, NULL, service.port_, NULL)) < 0)
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, service.name_.c_str(), NULL, NULL,
service.port_, NULL)) < 0)
{
if (ret == AVAHI_ERR_COLLISION)
goto collision;
@ -161,7 +161,8 @@ void PublishAvahi::create_services(AvahiClient *c)
}
/// Add an additional (hypothetic) subtype
/* if ((ret = avahi_entry_group_add_service_subtype(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, "_printer._tcp", NULL, "_magic._sub._printer._tcp") < 0))
/* if ((ret = avahi_entry_group_add_service_subtype(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AvahiPublishFlags(0), name, "_printer._tcp",
NULL, "_magic._sub._printer._tcp") < 0))
{
fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret));
goto fail;
@ -229,10 +230,6 @@ void PublishAvahi::client_callback(AvahiClient *c, AvahiClientState state, AVAHI
avahi_entry_group_reset(group);
break;
case AVAHI_CLIENT_CONNECTING:
;
case AVAHI_CLIENT_CONNECTING:;
}
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -23,15 +23,15 @@
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <atomic>
#include <avahi-common/alternative.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
#include <avahi-common/malloc.h>
#include <avahi-common/simple-watch.h>
#include <avahi-common/timeval.h>
#include <string>
#include <vector>
#include <thread>
#include <atomic>
#include <vector>
class PublishAvahi;
@ -57,5 +57,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,10 +19,13 @@
#include <cstdlib>
#include <thread>
#include "publishBonjour.h"
#include "aixlog.hpp"
#include "publishBonjour.h"
typedef union { unsigned char b[2]; unsigned short NotAnInteger; } Opaque16;
typedef union {
unsigned char b[2];
unsigned short NotAnInteger;
} Opaque16;
PublishBonjour::PublishBonjour(const std::string& serviceName) : PublishmDNS(serviceName), active_(false)
@ -108,7 +111,8 @@ void PublishBonjour::worker()
}
static void DNSSD_API reg_reply(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context)
static void DNSSD_API reg_reply(DNSServiceRef sdref, const DNSServiceFlags flags, DNSServiceErrorType errorCode, const char* name, const char* regtype,
const char* domain, void* context)
{
(void)sdref; // Unused
(void)flags; // Unused
@ -146,14 +150,12 @@ void PublishBonjour::publish(const std::vector<mDNSService>& services)
DNSServiceFlags flags = 0;
Opaque16 registerPort = {{static_cast<unsigned char>(service.port_ >> 8), static_cast<unsigned char>(service.port_ & 0xFF)}};
DNSServiceRef client = NULL;
// DNSServiceRegister(&client, flags, kDNSServiceInterfaceIndexAny, serviceName_.c_str(), service.name_.c_str(), NULL, NULL, registerPort.NotAnInteger, service.txt_.size(), service.txt_.empty()?NULL:service.txt_.c_str(), reg_reply, this);
DNSServiceRegister(&client, flags, kDNSServiceInterfaceIndexAny, serviceName_.c_str(), service.name_.c_str(), NULL, NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, this);
// DNSServiceRegister(&client, flags, kDNSServiceInterfaceIndexAny, serviceName_.c_str(), service.name_.c_str(), NULL, NULL,
//registerPort.NotAnInteger, service.txt_.size(), service.txt_.empty()?NULL:service.txt_.c_str(), reg_reply, this);
DNSServiceRegister(&client, flags, kDNSServiceInterfaceIndexAny, serviceName_.c_str(), service.name_.c_str(), NULL, NULL, registerPort.NotAnInteger, 0,
NULL, reg_reply, this);
clients.push_back(client);
}
pollThread_ = std::thread(&PublishBonjour::worker, this);
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -20,8 +20,8 @@
#ifndef PUBLISH_BONJOUR_H
#define PUBLISH_BONJOUR_H
#include <string>
#include <dns_sd.h>
#include <string>
class PublishBonjour;
@ -43,5 +43,3 @@ private:
#endif

0
server/publishZeroConf/publishmDNS.h Executable file → Normal file
View file

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -24,19 +24,19 @@
#ifdef HAS_DAEMON
#include "common/daemon.h"
#endif
#include "common/timeDefs.h"
#include "common/utils/string_utils.h"
#include "common/sampleFormat.h"
#include "common/signalHandler.h"
#include "common/snapException.h"
#include "common/sampleFormat.h"
#include "message/message.h"
#include "common/timeDefs.h"
#include "common/utils/string_utils.h"
#include "encoder/encoderFactory.h"
#include "message/message.h"
#include "streamServer.h"
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
#include "publishZeroConf/publishmDNS.h"
#endif
#include "config.h"
#include "aixlog.hpp"
#include "config.h"
volatile sig_atomic_t g_terminated = false;
@ -65,10 +65,13 @@ int main(int argc, char* argv[])
auto versionSwitch = op.add<Switch>("v", "version", "Show version number");
/*auto portValue =*/op.add<Value<size_t>>("p", "port", "Server port", settings.port, &settings.port);
/*auto controlPortValue =*/op.add<Value<size_t>>("", "controlPort", "Remote control port", settings.controlPort, &settings.controlPort);
auto streamValue = op.add<Value<string>>("s", "stream", "URI of the PCM input stream.\nFormat: TYPE://host/path?name=NAME\n[&codec=CODEC]\n[&sampleformat=SAMPLEFORMAT]", pcmStream, &pcmStream);
auto streamValue = op.add<Value<string>>(
"s", "stream", "URI of the PCM input stream.\nFormat: TYPE://host/path?name=NAME\n[&codec=CODEC]\n[&sampleformat=SAMPLEFORMAT]", pcmStream,
&pcmStream);
/*auto sampleFormatValue =*/op.add<Value<string>>("", "sampleformat", "Default sample format", settings.sampleFormat, &settings.sampleFormat);
/*auto codecValue =*/ op.add<Value<string>>("c", "codec", "Default transport codec\n(flac|ogg|pcm)[:options]\nType codec:? to get codec specific options", settings.codec, &settings.codec);
/*auto codecValue =*/op.add<Value<string>>(
"c", "codec", "Default transport codec\n(flac|ogg|pcm)[:options]\nType codec:? to get codec specific options", settings.codec, &settings.codec);
/*auto streamBufferValue =*/op.add<Value<size_t>>("", "streamBuffer", "Default stream read buffer [ms]", settings.streamReadMs, &settings.streamReadMs);
/*auto bufferValue =*/op.add<Value<int>>("b", "buffer", "Buffer [ms]", settings.bufferMs, &settings.bufferMs);
/*auto muteSwitch =*/op.add<Switch>("", "sendToMuted", "Send audio to muted clients", &settings.sendAudioToMutedClients);
@ -140,7 +143,8 @@ int main(int argc, char* argv[])
{
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::trace, AixLog::Type::all, "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
if (!debugOption->value().empty())
AixLog::Log::instance().add_logsink<AixLog::SinkFile>(AixLog::Severity::trace, AixLog::Type::all, debugOption->value(), "%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
AixLog::Log::instance().add_logsink<AixLog::SinkFile>(AixLog::Severity::trace, AixLog::Type::all, debugOption->value(),
"%Y-%m-%d %H-%M-%S.#ms [#severity] (#tag_func)");
}
else
{
@ -190,11 +194,8 @@ int main(int argc, char* argv[])
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
PublishZeroConf publishZeroConfg("Snapcast");
publishZeroConfg.publish({
mDNSService("_snapcast._tcp", settings.port),
mDNSService("_snapcast-jsonrpc._tcp", settings.controlPort),
mDNSService("_snapcastjsonrpc._tcp", settings.controlPort)
});
publishZeroConfg.publish({mDNSService("_snapcast._tcp", settings.port), mDNSService("_snapcast-jsonrpc._tcp", settings.controlPort),
mDNSService("_snapcastjsonrpc._tcp", settings.controlPort)});
#endif
if (settings.bufferMs < 400)
@ -226,4 +227,3 @@ int main(int argc, char* argv[])
SLOG(NOTICE) << "daemon terminated." << endl;
exit(exitcode);
}

View file

@ -17,11 +17,11 @@
***/
#include "streamServer.h"
#include "message/time.h"
#include "message/hello.h"
#include "message/streamTags.h"
#include "aixlog.hpp"
#include "config.h"
#include "message/hello.h"
#include "message/streamTags.h"
#include "message/time.h"
#include <iostream>
using namespace std;
@ -29,11 +29,8 @@ using namespace std;
using json = nlohmann::json;
StreamServer::StreamServer(asio::io_service* io_service, const StreamServerSettings& streamServerSettings) :
io_service_(io_service),
acceptor_v4_(nullptr),
acceptor_v6_(nullptr),
settings_(streamServerSettings)
StreamServer::StreamServer(asio::io_service* io_service, const StreamServerSettings& streamServerSettings)
: io_service_(io_service), acceptor_v4_(nullptr), acceptor_v6_(nullptr), settings_(streamServerSettings)
{
}
@ -45,7 +42,8 @@ StreamServer::~StreamServer()
void StreamServer::onMetaChanged(const PcmStream* pcmStream)
{
/// Notification: {"jsonrpc":"2.0","method":"Stream.OnMetadata","params":{"id":"stream 1", "meta": {"album": "some album", "artist": "some artist", "track": "some track"...}}
/// Notification: {"jsonrpc":"2.0","method":"Stream.OnMetadata","params":{"id":"stream 1", "meta": {"album": "some album", "artist": "some artist", "track":
/// "some track"...}}
// Send meta to all connected clients
const auto meta = pcmStream->getMeta();
@ -65,7 +63,9 @@ void StreamServer::onMetaChanged(const PcmStream* pcmStream)
void StreamServer::onStateChanged(const PcmStream* pcmStream, const ReaderState& state)
{
/// Notification: {"jsonrpc":"2.0","method":"Stream.OnUpdate","params":{"id":"stream 1","stream":{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}}}}
/// Notification: {"jsonrpc":"2.0","method":"Stream.OnUpdate","params":{"id":"stream 1","stream":{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}}}}
LOG(INFO) << "onStateChanged (" << pcmStream->getName() << "): " << state << "\n";
// LOG(INFO) << pcmStream->toJson().dump(4);
json notification = jsonrpcpp::Notification("Stream.OnUpdate", jsonrpcpp::Parameter("id", pcmStream->getId(), "stream", pcmStream->toJson())).to_json();
@ -144,8 +144,12 @@ void StreamServer::onDisconnect(StreamSession* streamSession)
/// in case of a duplicate client id
if (getStreamSession(clientInfo->id) == nullptr)
{
/// Notification: {"jsonrpc":"2.0","method":"Client.OnDisconnect","params":{"client":{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":81}},"connected":false,"host":{"arch":"x86_64","ip":"192.168.0.54","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025523,"usec":814067},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},"id":"00:21:6a:7d:74:fc"}}
json notification = jsonrpcpp::Notification("Client.OnDisconnect", jsonrpcpp::Parameter("id", clientInfo->id, "client", clientInfo->toJson())).to_json();
/// Notification:
/// {"jsonrpc":"2.0","method":"Client.OnDisconnect","params":{"client":{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":81}},"connected":false,"host":{"arch":"x86_64","ip":"192.168.0.54","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025523,"usec":814067},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},"id":"00:21:6a:7d:74:fc"}}
json notification =
jsonrpcpp::Notification("Client.OnDisconnect", jsonrpcpp::Parameter("id", clientInfo->id, "client", clientInfo->toJson())).to_json();
controlServer_->send(notification.dump());
////cout << "Notification: " << notification.dump() << "\n";
}
@ -169,7 +173,10 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
if (request->method() == "Client.GetStatus")
{
/// Request: {"id":8,"jsonrpc":"2.0","method":"Client.GetStatus","params":{"id":"00:21:6a:7d:74:fc"}}
/// Response: {"id":8,"jsonrpc":"2.0","result":{"client":{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":74}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488026416,"usec":135973},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}}}
/// Response:
/// {"id":8,"jsonrpc":"2.0","result":{"client":{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":74}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488026416,"usec":135973},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}}}
result["client"] = clientInfo->toJson();
}
else if (request->method() == "Client.SetVolume")
@ -179,7 +186,8 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
/// Notification: {"jsonrpc":"2.0","method":"Client.OnVolumeChanged","params":{"id":"00:21:6a:7d:74:fc","volume":{"muted":false,"percent":74}}}
clientInfo->config.volume.fromJson(request->params().get("volume"));
result["volume"] = clientInfo->config.volume.toJson();
notification.reset(new jsonrpcpp::Notification("Client.OnVolumeChanged", jsonrpcpp::Parameter("id", clientInfo->id, "volume", clientInfo->config.volume.toJson())));
notification.reset(new jsonrpcpp::Notification("Client.OnVolumeChanged",
jsonrpcpp::Parameter("id", clientInfo->id, "volume", clientInfo->config.volume.toJson())));
}
else if (request->method() == "Client.SetLatency")
{
@ -193,7 +201,8 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
latency = settings_.bufferMs;
clientInfo->config.latency = latency; //, -10000, settings_.bufferMs);
result["latency"] = clientInfo->config.latency;
notification.reset(new jsonrpcpp::Notification("Client.OnLatencyChanged", jsonrpcpp::Parameter("id", clientInfo->id, "latency", clientInfo->config.latency)));
notification.reset(
new jsonrpcpp::Notification("Client.OnLatencyChanged", jsonrpcpp::Parameter("id", clientInfo->id, "latency", clientInfo->config.latency)));
}
else if (request->method() == "Client.SetName")
{
@ -202,7 +211,8 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
/// Notification: {"jsonrpc":"2.0","method":"Client.OnNameChanged","params":{"id":"00:21:6a:7d:74:fc#2","name":"Laptop"}}
clientInfo->config.name = request->params().get<std::string>("name");
result["name"] = clientInfo->config.name;
notification.reset(new jsonrpcpp::Notification("Client.OnNameChanged", jsonrpcpp::Parameter("id", clientInfo->id, "name", clientInfo->config.name)));
notification.reset(
new jsonrpcpp::Notification("Client.OnNameChanged", jsonrpcpp::Parameter("id", clientInfo->id, "name", clientInfo->config.name)));
}
else
throw jsonrpcpp::MethodNotFoundException(request->id());
@ -233,7 +243,13 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
if (request->method() == "Group.GetStatus")
{
/// Request: {"id":5,"jsonrpc":"2.0","method":"Group.GetStatus","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1"}}
/// Response: {"id":5,"jsonrpc":"2.0","result":{"group":{"clients":[{"config":{"instance":2,"latency":10,"name":"Laptop","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488026485,"usec":644997},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":74}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488026481,"usec":223747},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":true,"name":"","stream_id":"stream 1"}}}
/// Response:
/// {"id":5,"jsonrpc":"2.0","result":{"group":{"clients":[{"config":{"instance":2,"latency":10,"name":"Laptop","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488026485,"usec":644997},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":74}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488026481,"usec":223747},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":true,"name":"","stream_id":"stream
/// 1"}}}
result["group"] = group->toJson();
}
else if (request->method() == "Group.SetMute")
@ -265,9 +281,11 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
}
else if (request->method() == "Group.SetStream")
{
/// Request: {"id":4,"jsonrpc":"2.0","method":"Group.SetStream","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","stream_id":"stream 1"}}
/// Request: {"id":4,"jsonrpc":"2.0","method":"Group.SetStream","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","stream_id":"stream
/// 1"}}
/// Response: {"id":4,"jsonrpc":"2.0","result":{"stream_id":"stream 1"}}
/// Notification: {"jsonrpc":"2.0","method":"Group.OnStreamChanged","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","stream_id":"stream 1"}}
/// Notification: {"jsonrpc":"2.0","method":"Group.OnStreamChanged","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","stream_id":"stream
/// 1"}}
string streamId = request->params().get<std::string>("stream_id");
PcmStreamPtr stream = streamManager_->getStream(streamId);
if (stream == nullptr)
@ -293,9 +311,33 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
}
else if (request->method() == "Group.SetClients")
{
/// Request: {"id":3,"jsonrpc":"2.0","method":"Group.SetClients","params":{"clients":["00:21:6a:7d:74:fc#2","00:21:6a:7d:74:fc"],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1"}}
/// Response: {"id":3,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025901,"usec":864472},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025905,"usec":45238},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3 Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Notification: {"jsonrpc":"2.0","method":"Server.OnUpdate","params":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025901,"usec":864472},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025905,"usec":45238},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3 Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Request:
/// {"id":3,"jsonrpc":"2.0","method":"Group.SetClients","params":{"clients":["00:21:6a:7d:74:fc#2","00:21:6a:7d:74:fc"],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1"}}
/// Response: {"id":3,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
/// 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025901,"usec":864472},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025905,"usec":45238},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream
/// 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3
/// Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream
/// 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Notification:
/// {"jsonrpc":"2.0","method":"Server.OnUpdate","params":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
/// 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025901,"usec":864472},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025905,"usec":45238},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream
/// 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3
/// Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream
/// 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
vector<string> clients = request->params().get("clients");
/// Remove clients from group
for (auto iter = group->clients.begin(); iter != group->clients.end();)
@ -368,14 +410,44 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
else if (request->method() == "Server.GetStatus")
{
/// Request: {"id":1,"jsonrpc":"2.0","method":"Server.GetStatus"}
/// Response: {"id":1,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025696,"usec":578142},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":81}},"connected":true,"host":{"arch":"x86_64","ip":"192.168.0.54","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025696,"usec":611255},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3 Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Response: {"id":1,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
/// 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025696,"usec":578142},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":81}},"connected":true,"host":{"arch":"x86_64","ip":"192.168.0.54","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025696,"usec":611255},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream
/// 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3
/// Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream
/// 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
result["server"] = Config::instance().getServerStatus(streamManager_->toJson());
}
else if (request->method() == "Server.DeleteClient")
{
/// Request: {"id":2,"jsonrpc":"2.0","method":"Server.DeleteClient","params":{"id":"00:21:6a:7d:74:fc"}}
/// Response: {"id":2,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025751,"usec":654777},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3 Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Notification: {"jsonrpc":"2.0","method":"Server.OnUpdate","params":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025751,"usec":654777},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3 Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Response: {"id":2,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
/// 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025751,"usec":654777},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream
/// 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3
/// Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream
/// 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Notification:
/// {"jsonrpc":"2.0","method":"Server.OnUpdate","params":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
/// 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025751,"usec":654777},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream
/// 2"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3
/// Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream
/// 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
ClientInfoPtr clientInfo = Config::instance().getClientInfo(request->params().get<std::string>("id"));
if (clientInfo == nullptr)
throw jsonrpcpp::InternalErrorException("Client not found", request->id());
@ -505,14 +577,17 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
void StreamServer::onMessageReceived(StreamSession* streamSession, const msg::BaseMessage& baseMessage, char* buffer)
{
// LOG(DEBUG) << "onMessageReceived: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " << baseMessage.refersTo << ", sent: " << baseMessage.sent.sec << "," << baseMessage.sent.usec << ", recv: " << baseMessage.received.sec << "," << baseMessage.received.usec << "\n";
// LOG(DEBUG) << "onMessageReceived: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " <<
//baseMessage.refersTo << ", sent: " << baseMessage.sent.sec << "," << baseMessage.sent.usec << ", recv: " << baseMessage.received.sec << "," <<
//baseMessage.received.usec << "\n";
if (baseMessage.type == message_type::kTime)
{
auto timeMsg = make_shared<msg::Time>();
timeMsg->deserialize(baseMessage, buffer);
timeMsg->refersTo = timeMsg->id;
timeMsg->latency = timeMsg->received - timeMsg->sent;
// LOG(INFO) << "Latency sec: " << timeMsg.latency.sec << ", usec: " << timeMsg.latency.usec << ", refers to: " << timeMsg.refersTo << "\n";
// LOG(INFO) << "Latency sec: " << timeMsg.latency.sec << ", usec: " << timeMsg.latency.usec << ", refers to: " << timeMsg.refersTo <<
//"\n";
streamSession->sendAsync(timeMsg);
// refresh streamSession state
@ -583,7 +658,20 @@ void StreamServer::onMessageReceived(StreamSession* streamSession, const msg::Ba
if (newGroup)
{
/// Notification: {"jsonrpc":"2.0","method":"Server.OnUpdate","params":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025796,"usec":714671},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream 2"},{"clients":[{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025798,"usec":728305},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"c5da8f7a-f377-1e51-8266-c5cc61099b71","muted":false,"name":"","stream_id":"stream 1"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3 Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
/// Notification:
/// {"jsonrpc":"2.0","method":"Server.OnUpdate","params":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
/// 456","volume":{"muted":false,"percent":48}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc#2","lastSeen":{"sec":1488025796,"usec":714671},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1","muted":false,"name":"","stream_id":"stream
/// 2"},{"clients":[{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":100}},"connected":true,"host":{"arch":"x86_64","ip":"127.0.0.1","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025798,"usec":728305},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}}],"id":"c5da8f7a-f377-1e51-8266-c5cc61099b71","muted":false,"name":"","stream_id":"stream
/// 1"}],"server":{"host":{"arch":"x86_64","ip":"","mac":"","name":"T400","os":"Linux Mint 17.3
/// Rosa"},"snapserver":{"controlProtocolVersion":1,"name":"Snapserver","protocolVersion":1,"version":"0.10.0"}},"streams":[{"id":"stream
/// 1","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 1","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 1","scheme":"pipe"}},{"id":"stream
/// 2","status":"idle","uri":{"fragment":"","host":"","path":"/tmp/snapfifo","query":{"buffer_ms":"20","codec":"flac","name":"stream
/// 2","sampleformat":"48000:16:2"},"raw":"pipe:///tmp/snapfifo?name=stream 2","scheme":"pipe"}}]}}}
json server = Config::instance().getServerStatus(streamManager_->toJson());
json notification = jsonrpcpp::Notification("Server.OnUpdate", jsonrpcpp::Parameter("server", server)).to_json();
controlServer_->send(notification.dump());
@ -591,7 +679,10 @@ void StreamServer::onMessageReceived(StreamSession* streamSession, const msg::Ba
}
else
{
/// Notification: {"jsonrpc":"2.0","method":"Client.OnConnect","params":{"client":{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":81}},"connected":true,"host":{"arch":"x86_64","ip":"192.168.0.54","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux Mint 17.3 Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025524,"usec":876332},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},"id":"00:21:6a:7d:74:fc"}}
/// Notification:
/// {"jsonrpc":"2.0","method":"Client.OnConnect","params":{"client":{"config":{"instance":1,"latency":0,"name":"","volume":{"muted":false,"percent":81}},"connected":true,"host":{"arch":"x86_64","ip":"192.168.0.54","mac":"00:21:6a:7d:74:fc","name":"T400","os":"Linux
/// Mint 17.3
/// Rosa"},"id":"00:21:6a:7d:74:fc","lastSeen":{"sec":1488025524,"usec":876332},"snapclient":{"name":"Snapclient","protocolVersion":2,"version":"0.10.0"}},"id":"00:21:6a:7d:74:fc"}}
json notification = jsonrpcpp::Notification("Client.OnConnect", jsonrpcpp::Parameter("id", client->id, "client", client->toJson())).to_json();
controlServer_->send(notification.dump());
////cout << "Notification: " << notification.dump() << "\n";
@ -769,4 +860,3 @@ void StreamServer::stop()
acceptor_v6_ = nullptr;
}
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -20,22 +20,22 @@
#define STREAM_SERVER_H
#include <asio.hpp>
#include <vector>
#include <thread>
#include <memory>
#include <mutex>
#include <set>
#include <sstream>
#include <mutex>
#include <thread>
#include <vector>
#include "jsonrpcpp.hpp"
#include "streamSession.h"
#include "streamreader/streamManager.h"
#include "common/queue.h"
#include "common/sampleFormat.h"
#include "message/message.h"
#include "message/codecHeader.h"
#include "message/serverSettings.h"
#include "controlServer.h"
#include "jsonrpcpp.hpp"
#include "message/codecHeader.h"
#include "message/message.h"
#include "message/serverSettings.h"
#include "streamSession.h"
#include "streamreader/streamManager.h"
using asio::ip::tcp;
@ -44,14 +44,8 @@ typedef std::shared_ptr<StreamSession> session_ptr;
struct StreamServerSettings
{
StreamServerSettings() :
port(1704),
controlPort(1705),
codec("flac"),
bufferMs(1000),
sampleFormat("48000:16:2"),
streamReadMs(20),
sendAudioToMutedClients(false)
StreamServerSettings()
: port(1704), controlPort(1705), codec("flac"), bufferMs(1000), sampleFormat("48000:16:2"), streamReadMs(20), sendAudioToMutedClients(false)
{
}
size_t port;
@ -118,5 +112,3 @@ private:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -18,17 +18,17 @@
#include "streamSession.h"
#include <iostream>
#include <mutex>
#include "aixlog.hpp"
#include "message/pcmChunk.h"
#include <iostream>
#include <mutex>
using namespace std;
StreamSession::StreamSession(MessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) :
active_(false), readerThread_(nullptr), writerThread_(nullptr), messageReceiver_(receiver), pcmStream_(nullptr)
StreamSession::StreamSession(MessageReceiver* receiver, std::shared_ptr<tcp::socket> socket)
: active_(false), readerThread_(nullptr), writerThread_(nullptr), messageReceiver_(receiver), pcmStream_(nullptr)
{
socket_ = socket;
}
@ -80,9 +80,11 @@ void StreamSession::stop()
{
std::lock_guard<std::mutex> socketLock(socketMutex_);
socket_->shutdown(asio::ip::tcp::socket::shutdown_both, ec);
if (ec) LOG(ERROR) << "Error in socket shutdown: " << ec.message() << "\n";
if (ec)
LOG(ERROR) << "Error in socket shutdown: " << ec.message() << "\n";
socket_->close(ec);
if (ec) LOG(ERROR) << "Error in socket close: " << ec.message() << "\n";
if (ec)
LOG(ERROR) << "Error in socket close: " << ec.message() << "\n";
}
if (readerThread_ && readerThread_->joinable())
{
@ -113,8 +115,7 @@ void StreamSession::socketRead(void* _to, size_t _bytes)
do
{
read += socket_->read_some(asio::buffer((char*)_to + read, _bytes - read));
}
while (active_ && (read < _bytes));
} while (active_ && (read < _bytes));
}
@ -188,7 +189,8 @@ void StreamSession::getNextMessage()
throw std::runtime_error(ss.str().c_str());
}
// LOG(INFO) << "getNextMessage: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " << baseMessage.refersTo << "\n";
// LOG(INFO) << "getNextMessage: " << baseMessage.type << ", size: " << baseMessage.size << ", id: " << baseMessage.id << ", refers: " <<
//baseMessage.refersTo << "\n";
if (baseMessage.size > buffer.size())
buffer.resize(baseMessage.size);
// {
@ -259,5 +261,3 @@ void StreamSession::writer()
if (active_ && (messageReceiver_ != NULL))
messageReceiver_->onDisconnect(this);
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,17 +19,17 @@
#ifndef STREAM_SESSION_H
#define STREAM_SESSION_H
#include "common/queue.h"
#include "message/message.h"
#include "streamreader/streamManager.h"
#include <asio.hpp>
#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <set>
#include <string>
#include <thread>
#include <atomic>
#include <memory>
#include <asio.hpp>
#include <condition_variable>
#include <set>
#include <mutex>
#include "message/message.h"
#include "common/queue.h"
#include "streamreader/streamManager.h"
using asio::ip::tcp;
@ -104,9 +104,4 @@ protected:
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -17,11 +17,11 @@
***/
#include "airplayStream.h"
#include "common/snapException.h"
#include "common/utils/string_utils.h"
#include "common/utils.h"
#include "base64.h"
#include "aixlog.hpp"
#include "base64.h"
#include "common/snapException.h"
#include "common/utils.h"
#include "common/utils/string_utils.h"
using namespace std;
@ -106,11 +106,15 @@ void AirplayStream::push()
if (entry_->type == "ssnc" && entry_->code == "mdst")
jtag_ = json();
if(entry_->code == "asal") jtag_["ALBUM"] = data;
if(entry_->code == "asar") jtag_["ARTIST"] = data;
if(entry_->code == "minm") jtag_["TITLE"] = data;
if (entry_->code == "asal")
jtag_["ALBUM"] = data;
if (entry_->code == "asar")
jtag_["ARTIST"] = data;
if (entry_->code == "minm")
jtag_["TITLE"] = data;
if(entry_->type == "ssnc" && entry_->code == "mden"){
if (entry_->type == "ssnc" && entry_->code == "mden")
{
// LOG(INFO) << "metadata=" << jtag_.dump(4) << "\n";
setMeta(jtag_);
}
@ -127,10 +131,12 @@ void AirplayStream::pipeReader()
{
ifstream pipe(pipePath_);
if(pipe){
if (pipe)
{
string line;
while(getline(pipe, line)){
while (getline(pipe, line))
{
#ifdef HAS_EXPAT
parse(line);
#endif
@ -187,9 +193,11 @@ void XMLCALL AirplayStream::element_start(void *userdata, const char *element_na
string name(element_name);
self->buf_.assign("");
if(name == "item") self->entry_.reset(new TageEntry);
if (name == "item")
self->entry_.reset(new TageEntry);
for(int i = 0; attr[i]; i += 2){
for (int i = 0; attr[i]; i += 2)
{
string name(attr[i]);
string value(attr[i + 1]);
if (name == "encoding")
@ -217,8 +225,10 @@ void XMLCALL AirplayStream::element_end(void *userdata, const char *element_name
else if (name == "item")
self->push();
else if(name == "metatags") ;
else cout << "Unknown tag <" << name << ">\n";
else if (name == "metatags")
;
else
cout << "Unknown tag <" << name << ">\n";
}
void XMLCALL AirplayStream::data(void* userdata, const char* content, int length)
@ -228,4 +238,3 @@ void XMLCALL AirplayStream::data(void *userdata, const char *content, int length
self->buf_.append(value);
}
#endif

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -32,7 +32,9 @@
class TageEntry
{
public:
TageEntry(): isBase64(false), length(0) {}
TageEntry() : isBase64(false), length(0)
{
}
std::string code;
std::string type;

View file

@ -26,26 +26,29 @@
*/
#include "base64.h"
static const std::string base64_chars =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz"
"0123456789+/";
static inline bool is_base64(unsigned char c) {
static inline bool is_base64(unsigned char c)
{
return (isalnum(c) || (c == '+') || (c == '/'));
}
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) {
std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len)
{
std::string ret;
int i = 0;
int j = 0;
unsigned char char_array_3[3];
unsigned char char_array_4[4];
while (in_len--) {
while (in_len--)
{
char_array_3[i++] = *(bytes_to_encode++);
if (i == 3) {
if (i == 3)
{
char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
@ -72,13 +75,12 @@ std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_
while ((i++ < 3))
ret += '=';
}
return ret;
}
std::string base64_decode(std::string const& encoded_string) {
std::string base64_decode(std::string const& encoded_string)
{
int in_len = encoded_string.size();
int i = 0;
int j = 0;
@ -86,9 +88,12 @@ std::string base64_decode(std::string const& encoded_string) {
unsigned char char_array_4[4], char_array_3[3];
std::string ret;
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
char_array_4[i++] = encoded_string[in_]; in_++;
if (i ==4) {
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
{
char_array_4[i++] = encoded_string[in_];
in_++;
if (i == 4)
{
for (i = 0; i < 4; i++)
char_array_4[i] = base64_chars.find(char_array_4[i]);
@ -102,7 +107,8 @@ std::string base64_decode(std::string const& encoded_string) {
}
}
if (i) {
if (i)
{
for (j = i; j < 4; j++)
char_array_4[j] = 0;
@ -113,9 +119,9 @@ std::string base64_decode(std::string const& encoded_string) {
char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2);
char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3];
for (j = 0; (j < i - 1); j++) ret += char_array_3[j];
for (j = 0; (j < i - 1); j++)
ret += char_array_3[j];
}
return ret;
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,21 +16,20 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
#include <memory>
#include <sys/stat.h>
#include <fcntl.h>
#include "fileStream.h"
#include "encoder/encoderFactory.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "encoder/encoderFactory.h"
#include "fileStream.h"
using namespace std;
FileStream::FileStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri)
{
ifs.open(uri_.path.c_str(), std::ifstream::in | std::ifstream::binary);
@ -84,7 +83,8 @@ void FileStream::worker()
ifs.read(chunk->payload + count, toRead - count);
encoder_->encode(chunk.get());
if (!active_) break;
if (!active_)
break;
nextTick += pcmReadMs_;
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
long currentTick = chronos::getTickCount();

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,23 +16,22 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <fcntl.h>
#include <memory>
#include <sys/stat.h>
#include <fcntl.h>
#include "encoder/encoderFactory.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "encoder/encoderFactory.h"
#include "pcmStream.h"
#include "aixlog.hpp"
using namespace std;
PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) :
active_(false), pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) : active_(false), pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
{
EncoderFactory encoderFactory;
if (uri_.query.find("codec") == uri_.query.end())
@ -170,9 +169,7 @@ json PcmStream::toJson() const
state = "disabled";
json j = {
{"uri", uri_.toJson()},
{"id", getId()},
{"status", state},
{"uri", uri_.toJson()}, {"id", getId()}, {"status", state},
};
if (meta_)
@ -196,4 +193,3 @@ void PcmStream::setMeta(json jtag)
if (pcmListener_)
pcmListener_->onMetaChanged(this);
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -19,18 +19,18 @@
#ifndef PCM_STREAM_H
#define PCM_STREAM_H
#include <thread>
#include <atomic>
#include <string>
#include <mutex>
#include <condition_variable>
#include <map>
#include "streamUri.h"
#include "encoder/encoder.h"
#include "common/sampleFormat.h"
#include "common/json.hpp"
#include "common/sampleFormat.h"
#include "encoder/encoder.h"
#include "message/codecHeader.h"
#include "message/streamTags.h"
#include "streamUri.h"
#include <atomic>
#include <condition_variable>
#include <map>
#include <mutex>
#include <string>
#include <thread>
class PcmStream;

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,24 +16,23 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <cerrno>
#include <fcntl.h>
#include <memory>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <cerrno>
#include "pipeStream.h"
#include "encoder/encoderFactory.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "aixlog.hpp"
#include "encoder/encoderFactory.h"
#include "pipeStream.h"
using namespace std;
PipeStream::PipeStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), fd_(-1)
{
umask(0);
@ -108,15 +107,16 @@ void PipeStream::worker()
len += count;
idleBytes = 0;
}
}
while ((len < toRead) && active_);
} while ((len < toRead) && active_);
if (!active_) break;
if (!active_)
break;
/// TODO: use less raw pointers, make this encoding more transparent
encoder_->encode(chunk.get());
if (!active_) break;
if (!active_)
break;
nextTick += pcmReadMs_;
chronos::addUs(tvChunk, pcmReadMs_ * 1000);

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -17,21 +17,20 @@
***/
#include <sys/stat.h>
#include <limits.h>
#include <fcntl.h>
#include "processStream.h"
#include "common/snapException.h"
#include "common/utils/string_utils.h"
#include "common/utils.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/utils.h"
#include "common/utils/string_utils.h"
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
using namespace std;
ProcessStream::ProcessStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), path_(""), process_(nullptr)
{
params_ = uri_.getQuery("params");
@ -191,14 +190,15 @@ void ProcessStream::worker()
len += count;
idleBytes = 0;
}
}
while ((len < toRead) && active_);
} while ((len < toRead) && active_);
if (!active_) break;
if (!active_)
break;
encoder_->encode(chunk.get());
if (!active_) break;
if (!active_)
break;
nextTick += pcmReadMs_;
chronos::addUs(tvChunk, pcmReadMs_ * 1000);

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -16,19 +16,18 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
***/
#include <regex>
#include "spotifyStream.h"
#include "common/snapException.h"
#include "common/utils/string_utils.h"
#include "common/utils.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/utils.h"
#include "common/utils/string_utils.h"
#include <regex>
using namespace std;
SpotifyStream::SpotifyStream(PcmListener* pcmListener, const StreamUri& uri) : ProcessStream(pcmListener, uri)
{
sampleFormat_ = SampleFormat("44100:16:2");
@ -119,9 +118,7 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
watchdog_->trigger();
string logmsg = utils::string::trim_copy(string(buffer, n));
if ((logmsg.find("allocated stream") == string::npos) &&
(logmsg.find("Got channel") == string::npos) &&
(logmsg.find('\0') == string::npos) &&
if ((logmsg.find("allocated stream") == string::npos) && (logmsg.find("Got channel") == string::npos) && (logmsg.find('\0') == string::npos) &&
(logmsg.size() > 4))
{
LOG(INFO) << "(" << getName() << ") " << logmsg << "\n";
@ -141,9 +138,7 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
{
LOG(INFO) << "metadata: <" << m[1] << ">\n";
json jtag = {
{"TITLE", (string)m[1]}
};
json jtag = {{"TITLE", (string)m[1]}};
setMeta(jtag);
}
}
@ -175,5 +170,3 @@ void SpotifyStream::onTimeout(const Watchdog* watchdog, size_t ms)
if (process_)
process_->kill();
}

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -28,7 +28,8 @@
* Implements EncoderListener to get the encoded data.
* Data is passed to the PcmListener
* usage:
* snapserver -s "spotify:///librespot?name=Spotify&username=<my username>&password=<my password>[&devicename=Snapcast][&bitrate=320][&volume=<volume in percent>][&cache=<cache dir>]"
* snapserver -s "spotify:///librespot?name=Spotify&username=<my username>&password=<my password>[&devicename=Snapcast][&bitrate=320][&volume=<volume in
* percent>][&cache=<cache dir>]"
*/
class SpotifyStream : public ProcessStream, WatchdogListener
{

View file

@ -1,6 +1,6 @@
/***
This file is part of snapcast
Copyright (C) 2014-2018 Johannes Pohl
Copyright (C) 2014-2019 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
@ -18,20 +18,21 @@
#include "streamManager.h"
#include "airplayStream.h"
#include "spotifyStream.h"
#include "processStream.h"
#include "pipeStream.h"
#include "fileStream.h"
#include "common/utils.h"
#include "common/strCompat.h"
#include "aixlog.hpp"
#include "common/snapException.h"
#include "common/strCompat.h"
#include "common/utils.h"
#include "fileStream.h"
#include "pipeStream.h"
#include "processStream.h"
#include "spotifyStream.h"
using namespace std;
StreamManager::StreamManager(PcmListener* pcmListener, const std::string& defaultSampleFormat, const std::string& defaultCodec, size_t defaultReadBufferMs) : pcmListener_(pcmListener), sampleFormat_(defaultSampleFormat), codec_(defaultCodec), readBufferMs_(defaultReadBufferMs)
StreamManager::StreamManager(PcmListener* pcmListener, const std::string& defaultSampleFormat, const std::string& defaultCodec, size_t defaultReadBufferMs)
: pcmListener_(pcmListener), sampleFormat_(defaultSampleFormat), codec_(defaultCodec), readBufferMs_(defaultReadBufferMs)
{
}
@ -142,5 +143,3 @@ json StreamManager::toJson() const
result.push_back(stream->toJson());
return result;
}

View file

@ -1,10 +1,10 @@
#ifndef PCM_READER_FACTORY_H
#define PCM_READER_FACTORY_H
#include "pcmStream.h"
#include <memory>
#include <string>
#include <vector>
#include <memory>
#include "pcmStream.h"
typedef std::shared_ptr<PcmStream> PcmStreamPtr;

Some files were not shown because too many files have changed in this diff Show more