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:
parent
b733f646ea
commit
b20add3815
105 changed files with 7773 additions and 7723 deletions
.clang-format
client
Makefile
browseZeroConf
clientConnection.cppclientConnection.hcontroller.cppcontroller.hdecoder
doubleBuffer.hmetadata.hplayer
alsaPlayer.cppalsaPlayer.hcoreAudioPlayer.cppcoreAudioPlayer.hopenslPlayer.cppopenslPlayer.hpcmDevice.hplayer.cppplayer.h
snapClient.cppstream.cppstream.htimeProvider.cpptimeProvider.hcmake
common
daemon.cppdaemon.h
message
queue.hsampleFormat.cppsampleFormat.hsignalHandler.hsnapException.hstrCompat.htimeDefs.hutils.hutils
doc
externals
server
Makefileconfig.cppconfig.hcontrolServer.cppcontrolServer.hcontrolSession.cppcontrolSession.h
encoder
encoder.hencoderFactory.cppencoderFactory.hflacEncoder.cppflacEncoder.hoggEncoder.cppoggEncoder.hpcmEncoder.cpppcmEncoder.h
publishZeroConf
snapServer.cppstreamServer.cppstreamServer.hstreamSession.cppstreamSession.hstreamreader
20
.clang-format
Normal file
20
.clang-format
Normal 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
|
||||
|
||||
...
|
|
@ -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
47
client/browseZeroConf/browseAvahi.cpp
Executable file → Normal 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
14
client/browseZeroConf/browseAvahi.h
Executable file → Normal 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
61
client/browseZeroConf/browseBonjour.cpp
Executable file → Normal 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
0
client/browseZeroConf/browseBonjour.h
Executable file → Normal file
0
client/browseZeroConf/browsemDNS.h
Executable file → Normal file
0
client/browseZeroConf/browsemDNS.h
Executable file → Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
*/
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
179
doc/snapcast_plain_icon.svg
Normal 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
2
externals/Makefile
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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
|
|||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef ENCODER_FACTORY_H
|
||||
#define ENCODER_FACTORY_H
|
||||
|
||||
#include <string>
|
||||
#include "encoder.h"
|
||||
#include <string>
|
||||
|
||||
class EncoderFactory
|
||||
{
|
||||
|
|
|
@ -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]));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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:;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
0
server/publishZeroConf/publishmDNS.h
Executable file → Normal 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue