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
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
|
# 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
|
# 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
|
# 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 "browseAvahi.h"
|
||||||
#include <stdio.h>
|
#include "aixlog.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <iostream>
|
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "aixlog.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
static AvahiSimplePoll* simple_poll = NULL;
|
static AvahiSimplePoll* simple_poll = NULL;
|
||||||
|
@ -57,19 +57,9 @@ void BrowseAvahi::cleanUp()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BrowseAvahi::resolve_callback(
|
void BrowseAvahi::resolve_callback(AvahiServiceResolver* r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol,
|
||||||
AvahiServiceResolver *r,
|
AvahiResolverEvent event, const char* name, const char* type, const char* domain, const char* host_name,
|
||||||
AVAHI_GCC_UNUSED AvahiIfIndex interface,
|
const AvahiAddress* address, uint16_t port, AvahiStringList* txt, AvahiLookupResultFlags flags,
|
||||||
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)
|
AVAHI_GCC_UNUSED void* userdata)
|
||||||
{
|
{
|
||||||
BrowseAvahi* browseAvahi = static_cast<BrowseAvahi*>(userdata);
|
BrowseAvahi* browseAvahi = static_cast<BrowseAvahi*>(userdata);
|
||||||
|
@ -80,7 +70,8 @@ void BrowseAvahi::resolve_callback(
|
||||||
switch (event)
|
switch (event)
|
||||||
{
|
{
|
||||||
case AVAHI_RESOLVER_FAILURE:
|
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;
|
break;
|
||||||
|
|
||||||
case AVAHI_RESOLVER_FOUND:
|
case AVAHI_RESOLVER_FOUND:
|
||||||
|
@ -116,16 +107,8 @@ void BrowseAvahi::resolve_callback(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void BrowseAvahi::browse_callback(
|
void BrowseAvahi::browse_callback(AvahiServiceBrowser* b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char* name,
|
||||||
AvahiServiceBrowser *b,
|
const char* type, const char* domain, AVAHI_GCC_UNUSED AvahiLookupResultFlags flags, void* userdata)
|
||||||
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;
|
// AvahiClient* client = (AvahiClient*)userdata;
|
||||||
|
@ -149,7 +132,8 @@ void BrowseAvahi::browse_callback(
|
||||||
the callback function is called the server will free
|
the callback function is called the server will free
|
||||||
the resolver for us. */
|
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";
|
LOG(ERROR) << "Failed to resolve service '" << name << "': " << avahi_strerror(avahi_client_errno(browseAvahi->client_)) << "\n";
|
||||||
|
|
||||||
break;
|
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)));
|
throw SnapException("BrowseAvahi - Failed to create client: " + std::string(avahi_strerror(error)));
|
||||||
|
|
||||||
/* Create the service browser */
|
/* 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_))));
|
throw SnapException("BrowseAvahi - Failed to create service browser: " + std::string(avahi_strerror(avahi_client_errno(client_))));
|
||||||
|
|
||||||
result_.valid = false;
|
result_.valid = false;
|
||||||
|
@ -220,5 +205,3 @@ bool BrowseAvahi::browse(const std::string& serviceName, mDNSResult& result, int
|
||||||
throw;
|
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
|
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
|
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
|
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/client.h>
|
||||||
#include <avahi-client/lookup.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/error.h>
|
||||||
|
#include <avahi-common/malloc.h>
|
||||||
|
#include <avahi-common/simple-watch.h>
|
||||||
|
|
||||||
class BrowseAvahi;
|
class BrowseAvahi;
|
||||||
|
|
||||||
|
@ -38,8 +38,12 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void cleanUp();
|
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 resolve_callback(AvahiServiceResolver* r, AVAHI_GCC_UNUSED AvahiIfIndex interface, AVAHI_GCC_UNUSED AvahiProtocol protocol,
|
||||||
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);
|
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);
|
static void client_callback(AvahiClient* c, AvahiClientState state, AVAHI_GCC_UNUSED void* userdata);
|
||||||
AvahiClient* client_;
|
AvahiClient* client_;
|
||||||
mDNSResult result_;
|
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 "browseBonjour.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <iostream>
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
#ifdef WINDOWS
|
#ifdef WINDOWS
|
||||||
#include <WinSock2.h>
|
#include <WinSock2.h>
|
||||||
#include <Ws2tcpip.h>
|
#include <Ws2tcpip.h>
|
||||||
#else
|
#else
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
@ -141,7 +141,9 @@ struct mDNSResolve
|
||||||
uint16_t port;
|
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)
|
void runService(const DNSServiceHandle& service)
|
||||||
{
|
{
|
||||||
|
@ -173,20 +175,14 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
|
||||||
{
|
{
|
||||||
DNSServiceHandle service(new DNSServiceRef(NULL));
|
DNSServiceHandle service(new DNSServiceRef(NULL));
|
||||||
CHECKED(DNSServiceBrowse(service.get(), 0, 0, serviceName.c_str(), "local.",
|
CHECKED(DNSServiceBrowse(service.get(), 0, 0, serviceName.c_str(), "local.",
|
||||||
[](DNSServiceRef service,
|
[](DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
|
||||||
DNSServiceFlags flags,
|
const char* serviceName, const char* regtype, const char* replyDomain, void* context) {
|
||||||
uint32_t interfaceIndex,
|
|
||||||
DNSServiceErrorType errorCode,
|
|
||||||
const char* serviceName,
|
|
||||||
const char* regtype,
|
|
||||||
const char* replyDomain,
|
|
||||||
void* context)
|
|
||||||
{
|
|
||||||
auto replyCollection = static_cast<deque<mDNSReply>*>(context);
|
auto replyCollection = static_cast<deque<mDNSReply>*>(context);
|
||||||
|
|
||||||
CHECKED(errorCode);
|
CHECKED(errorCode);
|
||||||
replyCollection->push_back(mDNSReply{string(serviceName), string(regtype), string(replyDomain)});
|
replyCollection->push_back(mDNSReply{string(serviceName), string(regtype), string(replyDomain)});
|
||||||
}, &replyCollection));
|
},
|
||||||
|
&replyCollection));
|
||||||
|
|
||||||
runService(service);
|
runService(service);
|
||||||
}
|
}
|
||||||
|
@ -196,23 +192,16 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
|
||||||
{
|
{
|
||||||
DNSServiceHandle service(new DNSServiceRef(NULL));
|
DNSServiceHandle service(new DNSServiceRef(NULL));
|
||||||
for (auto& reply : replyCollection)
|
for (auto& reply : replyCollection)
|
||||||
CHECKED(DNSServiceResolve(service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
|
CHECKED(
|
||||||
[](DNSServiceRef service,
|
DNSServiceResolve(service.get(), 0, 0, reply.name.c_str(), reply.regtype.c_str(), reply.domain.c_str(),
|
||||||
DNSServiceFlags flags,
|
[](DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode, const char* fullName,
|
||||||
uint32_t interfaceIndex,
|
const char* hosttarget, uint16_t port, uint16_t txtLen, const unsigned char* txtRecord, void* context) {
|
||||||
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);
|
auto resultCollection = static_cast<deque<mDNSResolve>*>(context);
|
||||||
|
|
||||||
CHECKED(errorCode);
|
CHECKED(errorCode);
|
||||||
resultCollection->push_back(mDNSResolve{string(hosttarget), ntohs(port)});
|
resultCollection->push_back(mDNSResolve{string(hosttarget), ntohs(port)});
|
||||||
}, &resolveCollection));
|
},
|
||||||
|
&resolveCollection));
|
||||||
|
|
||||||
runService(service);
|
runService(service);
|
||||||
}
|
}
|
||||||
|
@ -226,15 +215,8 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
|
||||||
{
|
{
|
||||||
resultCollection[i].port = resolve.port;
|
resultCollection[i].port = resolve.port;
|
||||||
CHECKED(DNSServiceGetAddrInfo(service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
|
CHECKED(DNSServiceGetAddrInfo(service.get(), kDNSServiceFlagsLongLivedQuery, 0, kDNSServiceProtocol_IPv4, resolve.fullName.c_str(),
|
||||||
[](DNSServiceRef service,
|
[](DNSServiceRef service, DNSServiceFlags flags, uint32_t interfaceIndex, DNSServiceErrorType errorCode,
|
||||||
DNSServiceFlags flags,
|
const char* hostname, const sockaddr* address, uint32_t ttl, void* context) {
|
||||||
uint32_t interfaceIndex,
|
|
||||||
DNSServiceErrorType errorCode,
|
|
||||||
const char* hostname,
|
|
||||||
const sockaddr* address,
|
|
||||||
uint32_t ttl,
|
|
||||||
void* context)
|
|
||||||
{
|
|
||||||
auto result = static_cast<mDNSResult*>(context);
|
auto result = static_cast<mDNSResult*>(context);
|
||||||
|
|
||||||
result->host = string(hostname);
|
result->host = string(hostname);
|
||||||
|
@ -243,15 +225,14 @@ bool BrowseBonjour::browse(const string& serviceName, mDNSResult& result, int ti
|
||||||
|
|
||||||
char hostIP[NI_MAXHOST];
|
char hostIP[NI_MAXHOST];
|
||||||
char hostService[NI_MAXSERV];
|
char hostService[NI_MAXSERV];
|
||||||
if (getnameinfo(address, sizeof(*address),
|
if (getnameinfo(address, sizeof(*address), hostIP, sizeof(hostIP), hostService, sizeof(hostService),
|
||||||
hostIP, sizeof(hostIP),
|
|
||||||
hostService, sizeof(hostService),
|
|
||||||
NI_NUMERICHOST | NI_NUMERICSERV) == 0)
|
NI_NUMERICHOST | NI_NUMERICSERV) == 0)
|
||||||
result->ip = string(hostIP);
|
result->ip = string(hostIP);
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
result->valid = true;
|
result->valid = true;
|
||||||
}, &resultCollection[i++]));
|
},
|
||||||
|
&resultCollection[i++]));
|
||||||
}
|
}
|
||||||
runService(service);
|
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
|
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
|
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
|
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/>.
|
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 <iostream>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "clientConnection.h"
|
|
||||||
#include "common/strCompat.h"
|
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "message/hello.h"
|
|
||||||
#include "aixlog.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
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));
|
len += socket_->read_some(asio::buffer((char*)_to + len, toRead));
|
||||||
// cout << "len: " << len << ", error: " << error << endl;
|
// cout << "len: " << len << ", error: " << error << endl;
|
||||||
toRead = _bytes - len;
|
toRead = _bytes - len;
|
||||||
}
|
} while (toRead > 0);
|
||||||
while (toRead > 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,9 +100,11 @@ void ClientConnection::stop()
|
||||||
if (socket_)
|
if (socket_)
|
||||||
{
|
{
|
||||||
socket_->shutdown(asio::ip::tcp::socket::shutdown_both, ec);
|
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);
|
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_)
|
if (readerThread_)
|
||||||
{
|
{
|
||||||
|
@ -174,7 +177,8 @@ void ClientConnection::getNextMessage()
|
||||||
vector<char> buffer(baseMsgSize);
|
vector<char> buffer(baseMsgSize);
|
||||||
socketRead(&buffer[0], baseMsgSize);
|
socketRead(&buffer[0], baseMsgSize);
|
||||||
baseMessage.deserialize(&buffer[0]);
|
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())
|
if (baseMessage.size > buffer.size())
|
||||||
buffer.resize(baseMessage.size);
|
buffer.resize(baseMessage.size);
|
||||||
// {
|
// {
|
||||||
|
@ -186,7 +190,8 @@ void ClientConnection::getNextMessage()
|
||||||
|
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> lock(pendingRequestsMutex_);
|
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_)
|
for (auto req : pendingRequests_)
|
||||||
{
|
{
|
||||||
|
@ -230,7 +235,3 @@ void ClientConnection::reader()
|
||||||
connected_ = false;
|
connected_ = false;
|
||||||
active_ = false;
|
active_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,16 +19,16 @@
|
||||||
#ifndef CLIENT_CONNECTION_H
|
#ifndef CLIENT_CONNECTION_H
|
||||||
#define 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 <string>
|
||||||
#include <thread>
|
#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;
|
using asio::ip::tcp;
|
||||||
|
@ -130,7 +130,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include "controller.h"
|
#include "controller.h"
|
||||||
#include "decoder/pcmDecoder.h"
|
#include "decoder/pcmDecoder.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#if defined(HAS_OGG) && (defined(HAS_TREMOR) || defined(HAS_VORBIS))
|
#if defined(HAS_OGG) && (defined(HAS_TREMOR) || defined(HAS_VORBIS))
|
||||||
#include "decoder/oggDecoder.h"
|
#include "decoder/oggDecoder.h"
|
||||||
#endif
|
#endif
|
||||||
#if defined(HAS_FLAC)
|
#if defined(HAS_FLAC)
|
||||||
#include "decoder/flacDecoder.h"
|
#include "decoder/flacDecoder.h"
|
||||||
#endif
|
#endif
|
||||||
#include "timeProvider.h"
|
|
||||||
#include "message/time.h"
|
|
||||||
#include "message/hello.h"
|
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include "message/hello.h"
|
||||||
|
#include "message/time.h"
|
||||||
|
#include "timeProvider.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
Controller::Controller(const std::string& hostId, size_t instance, std::shared_ptr<MetadataAdapter> meta) : MessageReceiver(),
|
Controller::Controller(const std::string& hostId, size_t instance, std::shared_ptr<MetadataAdapter> meta)
|
||||||
hostId_(hostId),
|
: MessageReceiver(), hostId_(hostId), instance_(instance), active_(false), latency_(0), stream_(nullptr), decoder_(nullptr), player_(nullptr), meta_(meta),
|
||||||
instance_(instance),
|
serverSettings_(nullptr), async_exception_(nullptr)
|
||||||
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?
|
// TODO: do decoding in thread?
|
||||||
stream_->addChunk(pcmChunk);
|
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
|
else
|
||||||
delete pcmChunk;
|
delete pcmChunk;
|
||||||
|
@ -88,7 +81,8 @@ void Controller::onMessageReceived(ClientConnection* connection, const msg::Base
|
||||||
{
|
{
|
||||||
serverSettings_.reset(new msg::ServerSettings());
|
serverSettings_.reset(new msg::ServerSettings());
|
||||||
serverSettings_->deserialize(baseMessage, buffer);
|
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_)
|
if (stream_ && player_)
|
||||||
{
|
{
|
||||||
player_->setVolume(serverSettings_->getVolume() / 100.);
|
player_->setVolume(serverSettings_->getVolume() / 100.);
|
||||||
|
@ -254,6 +248,3 @@ void Controller::worker()
|
||||||
}
|
}
|
||||||
LOG(DEBUG) << "Thread stopped\n";
|
LOG(DEBUG) << "Thread stopped\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,13 +19,13 @@
|
||||||
#ifndef CONTROLLER_H
|
#ifndef CONTROLLER_H
|
||||||
#define CONTROLLER_H
|
#define CONTROLLER_H
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
#include <atomic>
|
|
||||||
#include "decoder/decoder.h"
|
#include "decoder/decoder.h"
|
||||||
#include "message/message.h"
|
#include "message/message.h"
|
||||||
#include "message/serverSettings.h"
|
#include "message/serverSettings.h"
|
||||||
#include "message/streamTags.h"
|
#include "message/streamTags.h"
|
||||||
#include "player/pcmDevice.h"
|
#include "player/pcmDevice.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <thread>
|
||||||
#ifdef HAS_ALSA
|
#ifdef HAS_ALSA
|
||||||
#include "player/alsaPlayer.h"
|
#include "player/alsaPlayer.h"
|
||||||
#elif HAS_OPENSL
|
#elif HAS_OPENSL
|
||||||
|
@ -34,8 +34,8 @@
|
||||||
#include "player/coreAudioPlayer.h"
|
#include "player/coreAudioPlayer.h"
|
||||||
#endif
|
#endif
|
||||||
#include "clientConnection.h"
|
#include "clientConnection.h"
|
||||||
#include "stream.h"
|
|
||||||
#include "metadata.h"
|
#include "metadata.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
|
||||||
/// Forwards PCM data to the audio player
|
/// Forwards PCM data to the audio player
|
||||||
|
@ -86,4 +86,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
#ifndef DECODER_H
|
#ifndef DECODER_H
|
||||||
#define DECODER_H
|
#define DECODER_H
|
||||||
#include <mutex>
|
|
||||||
#include "message/pcmChunk.h"
|
|
||||||
#include "message/codecHeader.h"
|
|
||||||
#include "common/sampleFormat.h"
|
#include "common/sampleFormat.h"
|
||||||
|
#include "message/codecHeader.h"
|
||||||
|
#include "message/pcmChunk.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
|
||||||
class Decoder
|
class Decoder
|
||||||
|
@ -38,5 +38,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cmath>
|
|
||||||
#include "flacDecoder.h"
|
#include "flacDecoder.h"
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "common/endian.hpp"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "common/endian.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
static FLAC__StreamDecoderReadStatus read_callback(const FLAC__StreamDecoder* decoder, FLAC__byte buffer[], size_t* bytes, void* client_data);
|
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 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);
|
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;
|
(void)decoder;
|
||||||
|
|
||||||
|
@ -199,10 +201,7 @@ void metadata_callback(const FLAC__StreamDecoder *decoder, const FLAC__StreamMet
|
||||||
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
|
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
|
||||||
{
|
{
|
||||||
static_cast<FlacDecoder*>(client_data)->cacheInfo_.sampleRate_ = metadata->data.stream_info.sample_rate;
|
static_cast<FlacDecoder*>(client_data)->cacheInfo_.sampleRate_ = metadata->data.stream_info.sample_rate;
|
||||||
sampleFormat.setFormat(
|
sampleFormat.setFormat(metadata->data.stream_info.sample_rate, metadata->data.stream_info.bits_per_sample, metadata->data.stream_info.channels);
|
||||||
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_UNPARSEABLE_STREAM
|
||||||
// Oct 27 17:47:13 kitchen snapclient[869]: Got error callback: FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC
|
// 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
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -60,5 +60,3 @@ public:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "oggDecoder.h"
|
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "common/endian.hpp"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "common/endian.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include "oggDecoder.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -229,7 +229,8 @@ SampleFormat OggDecoder::setHeader(msg::CodecHeader* chunk)
|
||||||
std::string comment(*ptr);
|
std::string comment(*ptr);
|
||||||
if (comment.find("SAMPLE_FORMAT=") == 0)
|
if (comment.find("SAMPLE_FORMAT=") == 0)
|
||||||
sampleFormat_.setFormat(comment.substr(comment.find("=") + 1));
|
sampleFormat_.setFormat(comment.substr(comment.find("=") + 1));
|
||||||
LOG(INFO) << "comment: " << comment << "\n";;
|
LOG(INFO) << "comment: " << comment << "\n";
|
||||||
|
;
|
||||||
++ptr;
|
++ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,6 +238,3 @@ SampleFormat OggDecoder::setHeader(msg::CodecHeader* chunk)
|
||||||
|
|
||||||
return sampleFormat_;
|
return sampleFormat_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -39,8 +39,10 @@ private:
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T clip(const T& value, const T& lower, const T& upper) const
|
T clip(const T& value, const T& lower, const T& upper) const
|
||||||
{
|
{
|
||||||
if (value > upper) return upper;
|
if (value > upper)
|
||||||
if (value < lower) return lower;
|
return upper;
|
||||||
|
if (value < lower)
|
||||||
|
return lower;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,5 +61,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
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 "pcmDecoder.h"
|
||||||
|
#include "aixlog.hpp"
|
||||||
|
#include "common/endian.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
|
||||||
|
|
||||||
#define ID_RIFF 0x46464952
|
#define ID_RIFF 0x46464952
|
||||||
|
@ -108,21 +108,13 @@ SampleFormat PcmDecoder::setHeader(msg::CodecHeader* chunk)
|
||||||
/// Unknown chunk, skip bytes
|
/// Unknown chunk, skip bytes
|
||||||
pos += SWAP_32(chunk_header.sz);
|
pos += SWAP_32(chunk_header.sz);
|
||||||
}
|
}
|
||||||
}
|
} while (moreChunks);
|
||||||
while (moreChunks);
|
|
||||||
|
|
||||||
|
|
||||||
if (SWAP_32(chunk_fmt.sample_rate) == 0)
|
if (SWAP_32(chunk_fmt.sample_rate) == 0)
|
||||||
throw SnapException("Sample format not found");
|
throw SnapException("Sample format not found");
|
||||||
|
|
||||||
SampleFormat sampleFormat(
|
SampleFormat sampleFormat(SWAP_32(chunk_fmt.sample_rate), SWAP_16(chunk_fmt.bits_per_sample), SWAP_16(chunk_fmt.num_channels));
|
||||||
SWAP_32(chunk_fmt.sample_rate),
|
|
||||||
SWAP_16(chunk_fmt.bits_per_sample),
|
|
||||||
SWAP_16(chunk_fmt.num_channels));
|
|
||||||
|
|
||||||
return sampleFormat;
|
return sampleFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -31,5 +31,3 @@ public:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
#ifndef DOUBLE_BUFFER_H
|
#ifndef DOUBLE_BUFFER_H
|
||||||
#define DOUBLE_BUFFER_H
|
#define DOUBLE_BUFFER_H
|
||||||
|
|
||||||
#include<deque>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <deque>
|
||||||
|
|
||||||
|
|
||||||
/// Size limited queue
|
/// Size limited queue
|
||||||
|
@ -126,11 +126,8 @@ public:
|
||||||
private:
|
private:
|
||||||
size_t bufferSize;
|
size_t bufferSize;
|
||||||
std::deque<T> buffer;
|
std::deque<T> buffer;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -98,7 +98,6 @@ public:
|
||||||
std::cerr << serialize() << "\n";
|
std::cerr << serialize() << "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -26,8 +26,7 @@
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
AlsaPlayer::AlsaPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
|
AlsaPlayer::AlsaPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) : Player(pcmDevice, stream), handle_(NULL), buff_(NULL)
|
||||||
Player(pcmDevice, stream), handle_(NULL), buff_(NULL)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,9 +272,12 @@ vector<PcmDevice> AlsaPlayer::pcm_list(void)
|
||||||
if (io != NULL && strcmp(io, "Output") != 0)
|
if (io != NULL && strcmp(io, "Output") != 0)
|
||||||
goto __end;
|
goto __end;
|
||||||
pcmDevice.name = name;
|
pcmDevice.name = name;
|
||||||
if(descr == NULL) {
|
if (descr == NULL)
|
||||||
|
{
|
||||||
pcmDevice.description = "";
|
pcmDevice.description = "";
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
pcmDevice.description = descr;
|
pcmDevice.description = descr;
|
||||||
}
|
}
|
||||||
pcmDevice.idx = idx++;
|
pcmDevice.idx = idx++;
|
||||||
|
@ -293,4 +295,3 @@ __end:
|
||||||
snd_device_name_free_hint(hints);
|
snd_device_name_free_hint(hints);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -54,4 +54,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,8 +17,8 @@
|
||||||
***/
|
***/
|
||||||
|
|
||||||
//#include <CoreServices/CoreServices.h>
|
//#include <CoreServices/CoreServices.h>
|
||||||
#include <CoreAudio/CoreAudio.h>
|
|
||||||
#include "coreAudioPlayer.h"
|
#include "coreAudioPlayer.h"
|
||||||
|
#include <CoreAudio/CoreAudio.h>
|
||||||
|
|
||||||
#define NUM_BUFFERS 2
|
#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) :
|
CoreAudioPlayer::CoreAudioPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) : Player(pcmDevice, stream), ms_(100), pubStream_(stream)
|
||||||
Player(pcmDevice, stream),
|
|
||||||
ms_(100),
|
|
||||||
pubStream_(stream)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,9 +48,7 @@ std::vector<PcmDevice> CoreAudioPlayer::pcm_list(void)
|
||||||
{
|
{
|
||||||
UInt32 propsize;
|
UInt32 propsize;
|
||||||
|
|
||||||
AudioObjectPropertyAddress theAddress = { kAudioHardwarePropertyDevices,
|
AudioObjectPropertyAddress theAddress = {kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster};
|
||||||
kAudioObjectPropertyScopeGlobal,
|
|
||||||
kAudioObjectPropertyElementMaster };
|
|
||||||
|
|
||||||
AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &theAddress, 0, NULL, &propsize);
|
AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &theAddress, 0, NULL, &propsize);
|
||||||
int nDevices = propsize / sizeof(AudioDeviceID);
|
int nDevices = propsize / sizeof(AudioDeviceID);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -58,4 +58,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,10 +19,10 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "openslPlayer.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
|
#include "openslPlayer.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -43,19 +43,9 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
OpenslPlayer::OpenslPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
|
OpenslPlayer::OpenslPlayer(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream)
|
||||||
Player(pcmDevice, stream),
|
: Player(pcmDevice, stream), engineObject(NULL), engineEngine(NULL), outputMixObject(NULL), bqPlayerObject(NULL), bqPlayerPlay(NULL),
|
||||||
engineObject(NULL),
|
bqPlayerBufferQueue(NULL), bqPlayerVolume(NULL), curBuffer(0), ms_(50), buff_size(0), pubStream_(stream)
|
||||||
engineEngine(NULL),
|
|
||||||
outputMixObject(NULL),
|
|
||||||
bqPlayerObject(NULL),
|
|
||||||
bqPlayerPlay(NULL),
|
|
||||||
bqPlayerBufferQueue(NULL),
|
|
||||||
bqPlayerVolume(NULL),
|
|
||||||
curBuffer(0),
|
|
||||||
ms_(50),
|
|
||||||
buff_size(0),
|
|
||||||
pubStream_(stream)
|
|
||||||
{
|
{
|
||||||
initOpensl();
|
initOpensl();
|
||||||
}
|
}
|
||||||
|
@ -200,10 +190,7 @@ void OpenslPlayer::initOpensl()
|
||||||
|
|
||||||
SLresult result;
|
SLresult result;
|
||||||
// create engine
|
// create engine
|
||||||
SLEngineOption engineOption[] =
|
SLEngineOption engineOption[] = {{(SLuint32)SL_ENGINEOPTION_THREADSAFE, (SLuint32)SL_BOOLEAN_TRUE}};
|
||||||
{
|
|
||||||
{(SLuint32) SL_ENGINEOPTION_THREADSAFE, (SLuint32) SL_BOOLEAN_TRUE}
|
|
||||||
};
|
|
||||||
result = slCreateEngine(&engineObject, 1, engineOption, 0, NULL, NULL);
|
result = slCreateEngine(&engineObject, 1, engineOption, 0, NULL, NULL);
|
||||||
throwUnsuccess("slCreateEngine", result);
|
throwUnsuccess("slCreateEngine", result);
|
||||||
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
|
||||||
|
@ -284,16 +271,9 @@ void OpenslPlayer::initOpensl()
|
||||||
|
|
||||||
|
|
||||||
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
|
||||||
SLDataFormat_PCM format_pcm =
|
SLDataFormat_PCM format_pcm = {
|
||||||
{
|
SL_DATAFORMAT_PCM, format.channels, samplesPerSec, bitsPerSample, containerSize, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
|
||||||
SL_DATAFORMAT_PCM,
|
SL_BYTEORDER_LITTLEENDIAN};
|
||||||
format.channels,
|
|
||||||
samplesPerSec,
|
|
||||||
bitsPerSample,
|
|
||||||
containerSize,
|
|
||||||
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
|
|
||||||
SL_BYTEORDER_LITTLEENDIAN
|
|
||||||
};
|
|
||||||
|
|
||||||
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
|
||||||
|
|
||||||
|
@ -413,4 +393,3 @@ void OpenslPlayer::stop()
|
||||||
void OpenslPlayer::worker()
|
void OpenslPlayer::worker()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -74,4 +74,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -24,15 +24,9 @@
|
||||||
|
|
||||||
struct PcmDevice
|
struct PcmDevice
|
||||||
{
|
{
|
||||||
PcmDevice() :
|
PcmDevice() : idx(-1), name("default"){};
|
||||||
idx(-1), name("default")
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
PcmDevice(int idx, const std::string& name, const std::string& description = "") :
|
PcmDevice(int idx, const std::string& name, const std::string& description = "") : idx(idx), name(name), description(description){};
|
||||||
idx(idx), name(name), description(description)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
int idx;
|
int idx;
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -41,4 +35,3 @@ struct PcmDevice
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "player.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
Player::Player(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream) :
|
Player::Player(const PcmDevice& pcmDevice, std::shared_ptr<Stream> stream)
|
||||||
active_(false),
|
: active_(false), stream_(stream), pcmDevice_(pcmDevice), volume_(1.0), muted_(false), volCorrection_(1.0)
|
||||||
stream_(stream),
|
|
||||||
pcmDevice_(pcmDevice),
|
|
||||||
volume_(1.0),
|
|
||||||
muted_(false),
|
|
||||||
volCorrection_(1.0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,5 +108,3 @@ void Player::setMute(bool mute)
|
||||||
{
|
{
|
||||||
muted_ = mute;
|
muted_ = mute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,14 +19,14 @@
|
||||||
#ifndef PLAYER_H
|
#ifndef PLAYER_H
|
||||||
#define PLAYER_H
|
#define PLAYER_H
|
||||||
|
|
||||||
|
#include "aixlog.hpp"
|
||||||
|
#include "common/endian.hpp"
|
||||||
|
#include "pcmDevice.h"
|
||||||
|
#include "stream.h"
|
||||||
|
#include <atomic>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "stream.h"
|
|
||||||
#include "pcmDevice.h"
|
|
||||||
#include "common/endian.hpp"
|
|
||||||
#include "aixlog.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
/// Audio Player
|
/// Audio Player
|
||||||
|
@ -72,4 +72,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include "popl.hpp"
|
|
||||||
#include "controller.h"
|
|
||||||
#include "browseZeroConf/browsemDNS.h"
|
#include "browseZeroConf/browsemDNS.h"
|
||||||
|
#include "controller.h"
|
||||||
|
#include "popl.hpp"
|
||||||
|
|
||||||
#ifdef HAS_ALSA
|
#ifdef HAS_ALSA
|
||||||
#include "player/alsaPlayer.h"
|
#include "player/alsaPlayer.h"
|
||||||
|
@ -131,8 +131,7 @@ int main (int argc, char **argv)
|
||||||
vector<PcmDevice> pcmDevices = AlsaPlayer::pcm_list();
|
vector<PcmDevice> pcmDevices = AlsaPlayer::pcm_list();
|
||||||
for (auto dev : pcmDevices)
|
for (auto dev : pcmDevices)
|
||||||
{
|
{
|
||||||
cout << dev.idx << ": " << dev.name << "\n"
|
cout << dev.idx << ": " << dev.name << "\n" << dev.description << "\n\n";
|
||||||
<< dev.description << "\n\n";
|
|
||||||
}
|
}
|
||||||
exit(EXIT_SUCCESS);
|
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)");
|
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())
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -268,5 +268,3 @@ int main (int argc, char **argv)
|
||||||
SLOG(NOTICE) << "daemon terminated." << endl;
|
SLOG(NOTICE) << "daemon terminated." << endl;
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,18 +17,19 @@
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include "stream.h"
|
#include "stream.h"
|
||||||
|
#include "aixlog.hpp"
|
||||||
|
#include "timeProvider.h"
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "aixlog.hpp"
|
|
||||||
#include "timeProvider.h"
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
// using namespace chronos;
|
// using namespace chronos;
|
||||||
namespace cs = 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);
|
buffer_.setSize(500);
|
||||||
shortBuffer_.setSize(100);
|
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 << ", ";
|
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
|
// 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";
|
LOG(INFO) << "sleep: " << cs::duration<cs::msec>(sleep_) << "\n";
|
||||||
if (sleep_ < -bufferDuration / 2)
|
if (sleep_ < -bufferDuration / 2)
|
||||||
return true;
|
return true;
|
||||||
|
@ -253,7 +255,9 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
// We're late: discard oldest chunks
|
// We're late: discard oldest chunks
|
||||||
while (sleep_ > chunk_->duration<cs::usec>())
|
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);
|
sleep_ = std::chrono::duration_cast<cs::usec>(TimeProvider::serverNow() - chunk_->start() - bufferMs_ + outputBufferDacTime);
|
||||||
if (!chunks_.try_pop(chunk_, outputBufferDacTime))
|
if (!chunks_.try_pop(chunk_, outputBufferDacTime))
|
||||||
{
|
{
|
||||||
|
@ -294,7 +298,9 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
playedFrames_ -= abs(correctAfterXFrames_);
|
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);
|
setRealSampleRate(format_.rate);
|
||||||
if (sleep_.count() == 0)
|
if (sleep_.count() == 0)
|
||||||
|
@ -341,7 +347,8 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
if (lastAge != msAge)
|
if (lastAge != msAge)
|
||||||
{
|
{
|
||||||
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())
|
else if (shortBuffer_.full())
|
||||||
|
@ -361,8 +368,10 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
lastUpdate_ = now;
|
lastUpdate_ = now;
|
||||||
median_ = buffer_.median();
|
median_ = buffer_.median();
|
||||||
shortMedian_ = shortBuffer_.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() / 100 << "\t" << miniBuffer_.median() / 100 << "\t" << shortMedian_ / 100 << "\t" << median_ / 100 << "\t"
|
||||||
// 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";
|
<< 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);
|
return (abs(cs::duration<cs::msec>(age)) < 500);
|
||||||
}
|
}
|
||||||
|
@ -372,6 +381,3 @@ bool Stream::getPlayerChunk(void* outputBuffer, const cs::usec& outputBufferDacT
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -25,13 +25,13 @@
|
||||||
//#include <chrono>
|
//#include <chrono>
|
||||||
//#include "common/timeUtils.h"
|
//#include "common/timeUtils.h"
|
||||||
|
|
||||||
#include <deque>
|
#include "common/queue.h"
|
||||||
#include <memory>
|
#include "common/sampleFormat.h"
|
||||||
#include "doubleBuffer.h"
|
#include "doubleBuffer.h"
|
||||||
#include "message/message.h"
|
#include "message/message.h"
|
||||||
#include "message/pcmChunk.h"
|
#include "message/pcmChunk.h"
|
||||||
#include "common/sampleFormat.h"
|
#include <deque>
|
||||||
#include "common/queue.h"
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
/// Time synchronized audio stream
|
/// Time synchronized audio stream
|
||||||
|
@ -94,5 +94,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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);
|
return diffBuffer.percentile(percentile);
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,11 +19,11 @@
|
||||||
#ifndef TIME_PROVIDER_H
|
#ifndef TIME_PROVIDER_H
|
||||||
#define TIME_PROVIDER_H
|
#define TIME_PROVIDER_H
|
||||||
|
|
||||||
#include <atomic>
|
#include "common/timeDefs.h"
|
||||||
#include <chrono>
|
|
||||||
#include "doubleBuffer.h"
|
#include "doubleBuffer.h"
|
||||||
#include "message/message.h"
|
#include "message/message.h"
|
||||||
#include "common/timeDefs.h"
|
#include <atomic>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
|
||||||
/// Provides local and server time
|
/// Provides local and server time
|
||||||
|
@ -87,5 +87,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# This file is part of snapcast
|
# 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
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,27 +18,24 @@
|
||||||
|
|
||||||
#include "daemon.h"
|
#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/snapException.h"
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
#include "common/utils/file_utils.h"
|
|
||||||
#include "common/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) :
|
Daemon::Daemon(const std::string& user, const std::string& group, const std::string& pidfile)
|
||||||
pidFilehandle_(-1),
|
: pidFilehandle_(-1), user_(user), group_(group), pidfile_(pidfile)
|
||||||
user_(user),
|
|
||||||
group_(group),
|
|
||||||
pidfile_(pidfile)
|
|
||||||
{
|
{
|
||||||
if (pidfile.empty() || pidfile.find('/') == std::string::npos)
|
if (pidfile.empty() || pidfile.find('/') == std::string::npos)
|
||||||
throw SnapException("invalid pid file \"" + pidfile + "\"");
|
throw SnapException("invalid pid file \"" + pidfile + "\"");
|
||||||
|
@ -166,6 +163,3 @@ void Daemon::daemonize()
|
||||||
close(STDOUT_FILENO);
|
close(STDOUT_FILENO);
|
||||||
close(STDERR_FILENO);
|
close(STDERR_FILENO);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -62,10 +62,7 @@ protected:
|
||||||
writeVal(stream, payload, payloadSize);
|
writeVal(stream, payload, payloadSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
#ifndef HELLO_MSG_H
|
#ifndef HELLO_MSG_H
|
||||||
#define HELLO_MSG_H
|
#define HELLO_MSG_H
|
||||||
|
|
||||||
#include "jsonMessage.h"
|
|
||||||
#include "common/utils.h"
|
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
|
#include "common/utils.h"
|
||||||
|
#include "jsonMessage.h"
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
@ -108,10 +108,7 @@ public:
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
#ifndef JSON_MESSAGE_H
|
#ifndef JSON_MESSAGE_H
|
||||||
#define JSON_MESSAGE_H
|
#define JSON_MESSAGE_H
|
||||||
|
|
||||||
#include "message.h"
|
|
||||||
#include "common/json.hpp"
|
#include "common/json.hpp"
|
||||||
|
#include "message.h"
|
||||||
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
@ -76,10 +76,7 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,14 +19,14 @@
|
||||||
#ifndef MESSAGE_H
|
#ifndef MESSAGE_H
|
||||||
#define MESSAGE_H
|
#define MESSAGE_H
|
||||||
|
|
||||||
|
#include "common/endian.hpp"
|
||||||
|
#include "common/timeDefs.h"
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
#include <vector>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "common/endian.hpp"
|
#include <vector>
|
||||||
#include "common/timeDefs.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
template<typename CharT, typename TraitsT = std::char_traits<CharT> >
|
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;
|
BaseMessage message;
|
||||||
char* buffer;
|
char* buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,10 +19,10 @@
|
||||||
#ifndef PCM_CHUNK_H
|
#ifndef PCM_CHUNK_H
|
||||||
#define PCM_CHUNK_H
|
#define PCM_CHUNK_H
|
||||||
|
|
||||||
#include <chrono>
|
#include "common/sampleFormat.h"
|
||||||
#include "message.h"
|
#include "message.h"
|
||||||
#include "wireChunk.h"
|
#include "wireChunk.h"
|
||||||
#include "common/sampleFormat.h"
|
#include <chrono>
|
||||||
|
|
||||||
|
|
||||||
namespace msg
|
namespace msg
|
||||||
|
@ -36,17 +36,11 @@ namespace msg
|
||||||
class PcmChunk : public WireChunk
|
class PcmChunk : public WireChunk
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PcmChunk(const SampleFormat& sampleFormat, size_t ms) :
|
PcmChunk(const SampleFormat& sampleFormat, size_t ms) : WireChunk(sampleFormat.rate * sampleFormat.frameSize * ms / 1000), format(sampleFormat), idx_(0)
|
||||||
WireChunk(sampleFormat.rate*sampleFormat.frameSize*ms / 1000),
|
|
||||||
format(sampleFormat),
|
|
||||||
idx_(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PcmChunk(const PcmChunk& pcmChunk) :
|
PcmChunk(const PcmChunk& pcmChunk) : WireChunk(pcmChunk), format(pcmChunk.format), idx_(0)
|
||||||
WireChunk(pcmChunk),
|
|
||||||
format(pcmChunk.format),
|
|
||||||
idx_(0)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,7 +64,8 @@ public:
|
||||||
memcpy((char*)outputBuffer, (char*)(payload) + format.frameSize * idx_, format.frameSize * result);
|
memcpy((char*)outputBuffer, (char*)(payload) + format.frameSize * idx_, format.frameSize * result);
|
||||||
|
|
||||||
idx_ += 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,11 +84,8 @@ public:
|
||||||
|
|
||||||
virtual chronos::time_point_clk start() const
|
virtual chronos::time_point_clk start() const
|
||||||
{
|
{
|
||||||
return chronos::time_point_clk(
|
return chronos::time_point_clk(chronos::sec(timestamp.sec) + chronos::usec(timestamp.usec) +
|
||||||
chronos::sec(timestamp.sec) +
|
chronos::usec((chronos::usec::rep)(1000000. * ((double)idx_ / (double)format.rate))));
|
||||||
chronos::usec(timestamp.usec) +
|
|
||||||
chronos::usec((chronos::usec::rep)(1000000. * ((double)idx_ / (double)format.rate)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline chronos::time_point_clk end() const
|
inline chronos::time_point_clk end() const
|
||||||
|
@ -133,9 +125,6 @@ public:
|
||||||
private:
|
private:
|
||||||
uint32_t idx_;
|
uint32_t idx_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -82,10 +82,7 @@ public:
|
||||||
msg["muted"] = muted;
|
msg["muted"] = muted;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -69,10 +69,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -55,10 +55,7 @@ protected:
|
||||||
writeVal(stream, latency.usec);
|
writeVal(stream, latency.usec);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,14 +19,14 @@
|
||||||
#ifndef WIRE_CHUNK_H
|
#ifndef WIRE_CHUNK_H
|
||||||
#define WIRE_CHUNK_H
|
#define WIRE_CHUNK_H
|
||||||
|
|
||||||
|
#include "common/timeDefs.h"
|
||||||
|
#include "message.h"
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "message.h"
|
|
||||||
#include "common/timeDefs.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace msg
|
namespace msg
|
||||||
|
@ -84,10 +84,7 @@ protected:
|
||||||
writeVal(stream, payload, payloadSize);
|
writeVal(stream, payload, payloadSize);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,17 +19,16 @@
|
||||||
#ifndef QUEUE_H
|
#ifndef QUEUE_H
|
||||||
#define QUEUE_H
|
#define QUEUE_H
|
||||||
|
|
||||||
#include <deque>
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <thread>
|
|
||||||
#include <mutex>
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <deque>
|
||||||
|
#include <mutex>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
class Queue
|
class Queue
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
T pop()
|
T pop()
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> mlock(mutex_);
|
std::unique_lock<std::mutex> mlock(mutex_);
|
||||||
|
@ -161,5 +160,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#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 "aixlog.hpp"
|
||||||
|
#include "common/strCompat.h"
|
||||||
|
#include "common/utils.h"
|
||||||
|
#include "common/utils/string_utils.h"
|
||||||
|
#include "sampleFormat.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -60,10 +60,7 @@ void SampleFormat::setFormat(const std::string& format)
|
||||||
std::vector<std::string> strs;
|
std::vector<std::string> strs;
|
||||||
strs = utils::string::split(format, ':');
|
strs = utils::string::split(format, ':');
|
||||||
if (strs.size() == 3)
|
if (strs.size() == 3)
|
||||||
setFormat(
|
setFormat(cpt::stoul(strs[0]), cpt::stoul(strs[1]), cpt::stoul(strs[2]));
|
||||||
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;
|
frameSize = channels * sampleSize;
|
||||||
// LOG(DEBUG) << "SampleFormat: " << rate << ":" << bits << ":" << channels << "\n";
|
// LOG(DEBUG) << "SampleFormat: " << rate << ":" << bits << ":" << channels << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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 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)
|
* 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:
|
* 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
|
class SampleFormat
|
||||||
{
|
{
|
||||||
|
@ -73,4 +74,3 @@ public:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -47,5 +47,3 @@ void signal_handler(int sig)
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,13 +19,15 @@
|
||||||
#ifndef SNAP_EXCEPTION_H
|
#ifndef SNAP_EXCEPTION_H
|
||||||
#define SNAP_EXCEPTION_H
|
#define SNAP_EXCEPTION_H
|
||||||
|
|
||||||
|
#include <cstring> // std::strlen, std::strcpy
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cstring> // std::strlen, std::strcpy
|
|
||||||
|
|
||||||
// text_exception uses a dynamically-allocated internal c-string for what():
|
// text_exception uses a dynamically-allocated internal c-string for what():
|
||||||
class SnapException : public std::exception {
|
class SnapException : public std::exception
|
||||||
|
{
|
||||||
char* text_;
|
char* text_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SnapException(const char* text)
|
SnapException(const char* text)
|
||||||
{
|
{
|
||||||
|
@ -78,5 +80,3 @@ public:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
#define COMPAT_H
|
#define COMPAT_H
|
||||||
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <clocale>
|
#include <clocale>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#ifdef NO_CPP11_STRING
|
#ifdef NO_CPP11_STRING
|
||||||
#include <sstream>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cmath>
|
|
||||||
#include <climits>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <climits>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <sstream>
|
||||||
|
#include <stdexcept>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
@ -103,4 +103,3 @@ namespace cpt
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
#define TIME_DEFS_H
|
#define TIME_DEFS_H
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <thread>
|
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <thread>
|
||||||
#ifdef MACOS
|
#ifdef MACOS
|
||||||
#include <mach/clock.h>
|
#include <mach/clock.h>
|
||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
|
@ -119,5 +119,3 @@ namespace chronos
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -22,34 +22,34 @@
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
#include "common/utils/string_utils.h"
|
#include "common/utils/string_utils.h"
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <locale>
|
|
||||||
#include <string>
|
|
||||||
#include <cstring>
|
|
||||||
#include <vector>
|
|
||||||
#include <fstream>
|
|
||||||
#include <sstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <memory>
|
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iomanip>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <sys/ioctl.h>
|
#include <locale>
|
||||||
|
#include <memory>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <sys/types.h>
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <iomanip>
|
#include <vector>
|
||||||
#ifndef FREEBSD
|
#ifndef FREEBSD
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#endif
|
#endif
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#ifdef MACOS
|
#ifdef MACOS
|
||||||
#include <ifaddrs.h>
|
|
||||||
#include <net/if_dl.h>
|
|
||||||
#include <IOKit/IOCFPlugIn.h>
|
#include <IOKit/IOCFPlugIn.h>
|
||||||
#include <IOKit/IOTypes.h>
|
#include <IOKit/IOTypes.h>
|
||||||
|
#include <ifaddrs.h>
|
||||||
|
#include <net/if_dl.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
#include <sys/system_properties.h>
|
#include <sys/system_properties.h>
|
||||||
|
@ -186,12 +186,9 @@ static std::string generateUUID()
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << std::setfill('0') << std::hex
|
ss << std::setfill('0') << std::hex << std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff) << "-" << std::setw(4)
|
||||||
<< std::setw(4) << (std::rand() % 0xffff) << std::setw(4) << (std::rand() % 0xffff)
|
<< (std::rand() % 0xffff) << "-" << std::setw(4) << (std::rand() % 0xffff) << "-" << std::setw(4) << (std::rand() % 0xffff) << "-" << std::setw(4)
|
||||||
<< "-" << std::setw(4) << (std::rand() % 0xffff)
|
<< (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();
|
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);
|
it = (struct ifreq*)((char*)it + len);
|
||||||
i += len;
|
i += len;
|
||||||
|
@ -289,13 +288,13 @@ static std::string getMacAddress(int sock)
|
||||||
|
|
||||||
char mac[19];
|
char mac[19];
|
||||||
#ifndef FREEBSD
|
#ifndef FREEBSD
|
||||||
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
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[0], (unsigned char)ifr.ifr_hwaddr.sa_data[1], (unsigned char)ifr.ifr_hwaddr.sa_data[2],
|
(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[3], (unsigned char)ifr.ifr_hwaddr.sa_data[4], (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
|
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
|
||||||
#else
|
#else
|
||||||
sprintf(mac, "%02x:%02x:%02x:%02x:%02x:%02x",
|
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[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[2], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[3],
|
||||||
(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]);
|
(unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[4], (unsigned char)ifr.ifr_ifru.ifru_addr.sa_data[5]);
|
||||||
#endif
|
#endif
|
||||||
return mac;
|
return mac;
|
||||||
}
|
}
|
||||||
|
@ -343,5 +342,3 @@ static std::string getHostId(const std::string defaultId = "")
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,12 +19,12 @@
|
||||||
#ifndef FILE_UTILS_H
|
#ifndef FILE_UTILS_H
|
||||||
#define FILE_UTILS_H
|
#define FILE_UTILS_H
|
||||||
|
|
||||||
|
#include "string_utils.h"
|
||||||
|
#include <fstream>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <fstream>
|
|
||||||
#include "string_utils.h"
|
|
||||||
|
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
|
@ -93,4 +93,3 @@ static int mkdirRecursive(const char *path, mode_t mode)
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,10 +19,10 @@
|
||||||
#ifndef STRING_UTILS_H
|
#ifndef STRING_UTILS_H
|
||||||
#define STRING_UTILS_H
|
#define STRING_UTILS_H
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <string>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
|
@ -72,7 +72,8 @@ static inline std::string trim_copy(const std::string &s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// decode %xx to char
|
// decode %xx to char
|
||||||
static std::string uriDecode(const std::string& src) {
|
static std::string uriDecode(const std::string& src)
|
||||||
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
char ch;
|
char ch;
|
||||||
for (size_t i = 0; i < src.length(); i++)
|
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
|
} // namespace utils
|
||||||
|
|
||||||
#endif
|
#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 Width: | Height: | Size: 7.2 KiB |
2
externals/Makefile
vendored
2
externals/Makefile
vendored
|
@ -1,5 +1,5 @@
|
||||||
# This file is part of snapcast
|
# 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
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
# This file is part of snapcast
|
# 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
|
# 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
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,15 +17,15 @@
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include <sys/types.h>
|
#include "aixlog.hpp"
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <fstream>
|
|
||||||
#include <cerrno>
|
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
#include "common/utils/file_utils.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;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -120,10 +120,7 @@ void Config::save()
|
||||||
if (filename_.empty())
|
if (filename_.empty())
|
||||||
init();
|
init();
|
||||||
std::ofstream ofs(filename_.c_str(), std::ofstream::out | std::ofstream::trunc);
|
std::ofstream ofs(filename_.c_str(), std::ofstream::out | std::ofstream::trunc);
|
||||||
json clients = {
|
json clients = {{"ConfigVersion", 2}, {"Groups", getGroups()}};
|
||||||
{"ConfigVersion", 2},
|
|
||||||
{"Groups", getGroups()}
|
|
||||||
};
|
|
||||||
ofs << std::setw(4) << clients;
|
ofs << std::setw(4) << clients;
|
||||||
ofs.close();
|
ofs.close();
|
||||||
}
|
}
|
||||||
|
@ -207,14 +204,11 @@ json Config::getServerStatus(const json& streams) const
|
||||||
host.update();
|
host.update();
|
||||||
// TODO: Set MAC and IP
|
// TODO: Set MAC and IP
|
||||||
Snapserver snapserver("Snapserver", VERSION);
|
Snapserver snapserver("Snapserver", VERSION);
|
||||||
json serverStatus = {
|
json serverStatus = {{"server",
|
||||||
{"server", {
|
{{"host", host.toJson()}, // getHostName()},
|
||||||
{"host", host.toJson()},//getHostName()},
|
{"snapserver", snapserver.toJson()}}},
|
||||||
{"snapserver", snapserver.toJson()}
|
|
||||||
}},
|
|
||||||
{"groups", getGroups()},
|
{"groups", getGroups()},
|
||||||
{"streams", streams}
|
{"streams", streams}};
|
||||||
};
|
|
||||||
|
|
||||||
return serverStatus;
|
return serverStatus;
|
||||||
}
|
}
|
||||||
|
@ -287,5 +281,3 @@ GroupPtr Config::setGroupForClient(const std::string& groupId, const std::string
|
||||||
return newGroup;
|
return newGroup;
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,14 +19,14 @@
|
||||||
#ifndef CONFIG_H
|
#ifndef CONFIG_H
|
||||||
#define CONFIG_H
|
#define CONFIG_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <string>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "common/json.hpp"
|
#include "common/json.hpp"
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
|
#include "common/utils/string_utils.h"
|
||||||
|
|
||||||
|
|
||||||
namespace strutils = utils::string;
|
namespace strutils = utils::string;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include "jsonrpcpp.hpp"
|
|
||||||
#include "controlServer.h"
|
#include "controlServer.h"
|
||||||
#include "message/time.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
#include "common/utils.h"
|
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
|
#include "common/utils.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "jsonrpcpp.hpp"
|
||||||
|
#include "message/time.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -30,12 +30,8 @@ using namespace std;
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
ControlServer::ControlServer(asio::io_service* io_service, size_t port, ControlMessageReceiver* controlMessageReceiver) :
|
ControlServer::ControlServer(asio::io_service* io_service, size_t port, ControlMessageReceiver* controlMessageReceiver)
|
||||||
acceptor_v4_(nullptr),
|
: acceptor_v4_(nullptr), acceptor_v6_(nullptr), io_service_(io_service), port_(port), controlMessageReceiver_(controlMessageReceiver)
|
||||||
acceptor_v6_(nullptr),
|
|
||||||
io_service_(io_service),
|
|
||||||
port_(port),
|
|
||||||
controlMessageReceiver_(controlMessageReceiver)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,4 +195,3 @@ void ControlServer::stop()
|
||||||
for (auto s : sessions_)
|
for (auto s : sessions_)
|
||||||
s->stop();
|
s->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,18 +20,18 @@
|
||||||
#define CONTROL_SERVER_H
|
#define CONTROL_SERVER_H
|
||||||
|
|
||||||
#include <asio.hpp>
|
#include <asio.hpp>
|
||||||
#include <vector>
|
|
||||||
#include <thread>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <mutex>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "controlSession.h"
|
|
||||||
#include "common/queue.h"
|
#include "common/queue.h"
|
||||||
#include "common/sampleFormat.h"
|
#include "common/sampleFormat.h"
|
||||||
#include "message/message.h"
|
#include "controlSession.h"
|
||||||
#include "message/codecHeader.h"
|
#include "message/codecHeader.h"
|
||||||
|
#include "message/message.h"
|
||||||
#include "message/serverSettings.h"
|
#include "message/serverSettings.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,5 +77,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <mutex>
|
|
||||||
#include "controlSession.h"
|
#include "controlSession.h"
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
#include "message/pcmChunk.h"
|
#include "message/pcmChunk.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ControlSession::ControlSession(ControlMessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) :
|
ControlSession::ControlSession(ControlMessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) : active_(false), messageReceiver_(receiver)
|
||||||
active_(false), messageReceiver_(receiver)
|
|
||||||
{
|
{
|
||||||
socket_ = socket;
|
socket_ = socket;
|
||||||
}
|
}
|
||||||
|
@ -62,9 +61,11 @@ void ControlSession::stop()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::recursive_mutex> socketLock(socketMutex_);
|
std::lock_guard<std::recursive_mutex> socketLock(socketMutex_);
|
||||||
socket_->shutdown(asio::ip::tcp::socket::shutdown_both, ec);
|
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);
|
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())
|
if (readerThread_.joinable())
|
||||||
{
|
{
|
||||||
|
@ -170,5 +171,3 @@ void ControlSession::writer()
|
||||||
}
|
}
|
||||||
active_ = false;
|
active_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,16 +19,16 @@
|
||||||
#ifndef CONTROL_SESSION_H
|
#ifndef CONTROL_SESSION_H
|
||||||
#define 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 <string>
|
||||||
#include <thread>
|
#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;
|
using asio::ip::tcp;
|
||||||
|
@ -87,9 +87,4 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,12 +19,12 @@
|
||||||
#ifndef ENCODER_H
|
#ifndef ENCODER_H
|
||||||
#define ENCODER_H
|
#define ENCODER_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "message/pcmChunk.h"
|
|
||||||
#include "message/codecHeader.h"
|
|
||||||
#include "common/sampleFormat.h"
|
#include "common/sampleFormat.h"
|
||||||
|
#include "message/codecHeader.h"
|
||||||
|
#include "message/pcmChunk.h"
|
||||||
|
|
||||||
|
|
||||||
class Encoder;
|
class Encoder;
|
||||||
|
@ -100,5 +100,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -24,9 +24,9 @@
|
||||||
#if defined(HAS_FLAC)
|
#if defined(HAS_FLAC)
|
||||||
#include "flacEncoder.h"
|
#include "flacEncoder.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include "common/utils/string_utils.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -69,6 +69,3 @@ Encoder* EncoderFactory::createEncoder(const std::string& codecSettings) const
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#ifndef ENCODER_FACTORY_H
|
#ifndef ENCODER_FACTORY_H
|
||||||
#define ENCODER_FACTORY_H
|
#define ENCODER_FACTORY_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class EncoderFactory
|
class EncoderFactory
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,10 +18,10 @@
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "flacEncoder.h"
|
|
||||||
#include "common/strCompat.h"
|
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include "common/strCompat.h"
|
||||||
|
#include "flacEncoder.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -71,7 +71,8 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
{
|
{
|
||||||
int samples = chunk->getSampleCount();
|
int samples = chunk->getSampleCount();
|
||||||
int frames = chunk->getFrameCount();
|
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)
|
if (pcmBufferSize_ < samples)
|
||||||
{
|
{
|
||||||
|
@ -112,10 +113,7 @@ void FlacEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEncoder *encoder,
|
FLAC__StreamEncoderWriteStatus FlacEncoder::write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
|
||||||
const FLAC__byte buffer[],
|
|
||||||
size_t bytes,
|
|
||||||
unsigned samples,
|
|
||||||
unsigned current_frame)
|
unsigned current_frame)
|
||||||
{
|
{
|
||||||
// LOG(INFO) << "write_callback: " << bytes << ", " << samples << ", " << current_frame << "\n";
|
// 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,
|
FLAC__StreamEncoderWriteStatus write_callback(const FLAC__StreamEncoder* encoder, const FLAC__byte buffer[], size_t bytes, unsigned samples,
|
||||||
const FLAC__byte buffer[],
|
unsigned current_frame, void* client_data)
|
||||||
size_t bytes,
|
|
||||||
unsigned samples,
|
|
||||||
unsigned current_frame,
|
|
||||||
void *client_data)
|
|
||||||
{
|
{
|
||||||
FlacEncoder* flacEncoder = (FlacEncoder*)client_data;
|
FlacEncoder* flacEncoder = (FlacEncoder*)client_data;
|
||||||
return flacEncoder->write_callback(encoder, buffer, bytes, samples, current_frame);
|
return flacEncoder->write_callback(encoder, buffer, bytes, samples, current_frame);
|
||||||
|
@ -187,15 +181,13 @@ void FlacEncoder::initEncoder()
|
||||||
throw SnapException("error setting up encoder");
|
throw SnapException("error setting up encoder");
|
||||||
|
|
||||||
// now add some metadata; we'll add some tags and a padding block
|
// now add some metadata; we'll add some tags and a padding block
|
||||||
if (
|
if ((metadata_[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
|
||||||
(metadata_[0] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_VORBIS_COMMENT)) == NULL ||
|
|
||||||
(metadata_[1] = FLAC__metadata_object_new(FLAC__METADATA_TYPE_PADDING)) == 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:
|
// 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_entry_from_name_value_pair(&entry, "TITLE", "SnapStream") ||
|
||||||
!FLAC__metadata_object_vorbiscomment_append_comment(metadata_[0], entry, false) ||
|
!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_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");
|
throw SnapException("out of memory or tag error");
|
||||||
|
|
||||||
metadata_[1]->length = 1234; // set the padding length
|
metadata_[1]->length = 1234; // set the padding length
|
||||||
|
@ -208,4 +200,3 @@ void FlacEncoder::initEncoder()
|
||||||
if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
|
if (init_status != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
|
||||||
throw SnapException("ERROR: initializing encoder: " + string(FLAC__StreamEncoderInitStatusString[init_status]));
|
throw SnapException("ERROR: initializing encoder: " + string(FLAC__StreamEncoderInitStatusString[init_status]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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 getDefaultOptions() const;
|
||||||
virtual std::string name() 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:
|
protected:
|
||||||
virtual void initEncoder();
|
virtual void initEncoder();
|
||||||
|
@ -54,5 +55,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "oggEncoder.h"
|
#include "aixlog.hpp"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/utils.h"
|
#include "common/utils.h"
|
||||||
#include "aixlog.hpp"
|
#include "common/utils/string_utils.h"
|
||||||
|
#include "oggEncoder.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -55,7 +55,8 @@ std::string OggEncoder::name() const
|
||||||
void OggEncoder::encode(const msg::PcmChunk* chunk)
|
void OggEncoder::encode(const msg::PcmChunk* chunk)
|
||||||
{
|
{
|
||||||
double res = 0;
|
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();
|
int frames = chunk->getFrameCount();
|
||||||
float** buffer = vorbis_analysis_buffer(&vd_, frames);
|
float** buffer = vorbis_analysis_buffer(&vd_, frames);
|
||||||
|
|
||||||
|
@ -256,5 +257,3 @@ void OggEncoder::initEncoder()
|
||||||
pos += og_.body_len;
|
pos += og_.body_len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,8 +19,8 @@
|
||||||
#ifndef OGG_ENCODER_H
|
#ifndef OGG_ENCODER_H
|
||||||
#define OGG_ENCODER_H
|
#define OGG_ENCODER_H
|
||||||
#include "encoder.h"
|
#include "encoder.h"
|
||||||
#include <vorbis/vorbisenc.h>
|
|
||||||
#include <ogg/ogg.h>
|
#include <ogg/ogg.h>
|
||||||
|
#include <vorbis/vorbisenc.h>
|
||||||
|
|
||||||
class OggEncoder : public Encoder
|
class OggEncoder : public Encoder
|
||||||
{
|
{
|
||||||
|
@ -50,5 +50,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include "common/endian.hpp"
|
|
||||||
#include "pcmEncoder.h"
|
#include "pcmEncoder.h"
|
||||||
|
#include "common/endian.hpp"
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
|
||||||
#define ID_RIFF 0x46464952
|
#define ID_RIFF 0x46464952
|
||||||
|
@ -65,5 +65,3 @@ std::string PcmEncoder::name() const
|
||||||
{
|
{
|
||||||
return "pcm";
|
return "pcm";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -41,5 +41,3 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -17,18 +17,17 @@
|
||||||
USA.
|
USA.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <cstdio>
|
|
||||||
#include <cstdlib>
|
|
||||||
#include "publishAvahi.h"
|
#include "publishAvahi.h"
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
static AvahiEntryGroup* group;
|
static AvahiEntryGroup* group;
|
||||||
static AvahiSimplePoll* simple_poll;
|
static AvahiSimplePoll* simple_poll;
|
||||||
static char* name;
|
static char* name;
|
||||||
|
|
||||||
PublishAvahi::PublishAvahi(const std::string& serviceName) : PublishmDNS(serviceName),
|
PublishAvahi::PublishAvahi(const std::string& serviceName) : PublishmDNS(serviceName), client_(NULL), active_(false)
|
||||||
client_(NULL), active_(false)
|
|
||||||
{
|
{
|
||||||
group = NULL;
|
group = NULL;
|
||||||
simple_poll = NULL;
|
simple_poll = NULL;
|
||||||
|
@ -64,7 +63,8 @@ void PublishAvahi::publish(const std::vector<mDNSService>& services)
|
||||||
|
|
||||||
void PublishAvahi::worker()
|
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;
|
break;
|
||||||
|
|
||||||
case AVAHI_ENTRY_GROUP_UNCOMMITED:
|
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
|
/// We will now add two services and one subtype to the entry group
|
||||||
for (const auto& service : services_)
|
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)
|
if (ret == AVAHI_ERR_COLLISION)
|
||||||
goto collision;
|
goto collision;
|
||||||
|
@ -161,7 +161,8 @@ void PublishAvahi::create_services(AvahiClient *c)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add an additional (hypothetic) subtype
|
/// 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));
|
fprintf(stderr, "Failed to add subtype _magic._sub._printer._tcp: %s\n", avahi_strerror(ret));
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -229,10 +230,6 @@ void PublishAvahi::client_callback(AvahiClient *c, AvahiClientState state, AVAHI
|
||||||
avahi_entry_group_reset(group);
|
avahi_entry_group_reset(group);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_CLIENT_CONNECTING:
|
case AVAHI_CLIENT_CONNECTING:;
|
||||||
;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/client.h>
|
||||||
#include <avahi-client/publish.h>
|
#include <avahi-client/publish.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <avahi-common/alternative.h>
|
#include <avahi-common/alternative.h>
|
||||||
#include <avahi-common/simple-watch.h>
|
|
||||||
#include <avahi-common/malloc.h>
|
|
||||||
#include <avahi-common/error.h>
|
#include <avahi-common/error.h>
|
||||||
|
#include <avahi-common/malloc.h>
|
||||||
|
#include <avahi-common/simple-watch.h>
|
||||||
#include <avahi-common/timeval.h>
|
#include <avahi-common/timeval.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <atomic>
|
#include <vector>
|
||||||
|
|
||||||
class PublishAvahi;
|
class PublishAvahi;
|
||||||
|
|
||||||
|
@ -57,5 +57,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,10 +19,13 @@
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
#include "publishBonjour.h"
|
|
||||||
#include "aixlog.hpp"
|
#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)
|
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)sdref; // Unused
|
||||||
(void)flags; // Unused
|
(void)flags; // Unused
|
||||||
|
@ -146,14 +150,12 @@ void PublishBonjour::publish(const std::vector<mDNSService>& services)
|
||||||
DNSServiceFlags flags = 0;
|
DNSServiceFlags flags = 0;
|
||||||
Opaque16 registerPort = {{static_cast<unsigned char>(service.port_ >> 8), static_cast<unsigned char>(service.port_ & 0xFF)}};
|
Opaque16 registerPort = {{static_cast<unsigned char>(service.port_ >> 8), static_cast<unsigned char>(service.port_ & 0xFF)}};
|
||||||
DNSServiceRef client = NULL;
|
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,
|
||||||
DNSServiceRegister(&client, flags, kDNSServiceInterfaceIndexAny, serviceName_.c_str(), service.name_.c_str(), NULL, NULL, registerPort.NotAnInteger, 0, NULL, reg_reply, this);
|
//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);
|
clients.push_back(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
pollThread_ = std::thread(&PublishBonjour::worker, this);
|
pollThread_ = std::thread(&PublishBonjour::worker, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,8 +20,8 @@
|
||||||
#ifndef PUBLISH_BONJOUR_H
|
#ifndef PUBLISH_BONJOUR_H
|
||||||
#define PUBLISH_BONJOUR_H
|
#define PUBLISH_BONJOUR_H
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <dns_sd.h>
|
#include <dns_sd.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
class PublishBonjour;
|
class PublishBonjour;
|
||||||
|
|
||||||
|
@ -43,5 +43,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#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
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -24,19 +24,19 @@
|
||||||
#ifdef HAS_DAEMON
|
#ifdef HAS_DAEMON
|
||||||
#include "common/daemon.h"
|
#include "common/daemon.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/timeDefs.h"
|
#include "common/sampleFormat.h"
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/signalHandler.h"
|
#include "common/signalHandler.h"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/sampleFormat.h"
|
#include "common/timeDefs.h"
|
||||||
#include "message/message.h"
|
#include "common/utils/string_utils.h"
|
||||||
#include "encoder/encoderFactory.h"
|
#include "encoder/encoderFactory.h"
|
||||||
|
#include "message/message.h"
|
||||||
#include "streamServer.h"
|
#include "streamServer.h"
|
||||||
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
|
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
|
||||||
#include "publishZeroConf/publishmDNS.h"
|
#include "publishZeroConf/publishmDNS.h"
|
||||||
#endif
|
#endif
|
||||||
#include "config.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
volatile sig_atomic_t g_terminated = false;
|
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 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 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 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 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 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 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);
|
/*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)");
|
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())
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -190,11 +194,8 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
|
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
|
||||||
PublishZeroConf publishZeroConfg("Snapcast");
|
PublishZeroConf publishZeroConfg("Snapcast");
|
||||||
publishZeroConfg.publish({
|
publishZeroConfg.publish({mDNSService("_snapcast._tcp", settings.port), mDNSService("_snapcast-jsonrpc._tcp", settings.controlPort),
|
||||||
mDNSService("_snapcast._tcp", settings.port),
|
mDNSService("_snapcastjsonrpc._tcp", settings.controlPort)});
|
||||||
mDNSService("_snapcast-jsonrpc._tcp", settings.controlPort),
|
|
||||||
mDNSService("_snapcastjsonrpc._tcp", settings.controlPort)
|
|
||||||
});
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (settings.bufferMs < 400)
|
if (settings.bufferMs < 400)
|
||||||
|
@ -226,4 +227,3 @@ int main(int argc, char* argv[])
|
||||||
SLOG(NOTICE) << "daemon terminated." << endl;
|
SLOG(NOTICE) << "daemon terminated." << endl;
|
||||||
exit(exitcode);
|
exit(exitcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,11 +17,11 @@
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include "streamServer.h"
|
#include "streamServer.h"
|
||||||
#include "message/time.h"
|
|
||||||
#include "message/hello.h"
|
|
||||||
#include "message/streamTags.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "message/hello.h"
|
||||||
|
#include "message/streamTags.h"
|
||||||
|
#include "message/time.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -29,11 +29,8 @@ using namespace std;
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
|
||||||
StreamServer::StreamServer(asio::io_service* io_service, const StreamServerSettings& streamServerSettings) :
|
StreamServer::StreamServer(asio::io_service* io_service, const StreamServerSettings& streamServerSettings)
|
||||||
io_service_(io_service),
|
: io_service_(io_service), acceptor_v4_(nullptr), acceptor_v6_(nullptr), settings_(streamServerSettings)
|
||||||
acceptor_v4_(nullptr),
|
|
||||||
acceptor_v6_(nullptr),
|
|
||||||
settings_(streamServerSettings)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +42,8 @@ StreamServer::~StreamServer()
|
||||||
|
|
||||||
void StreamServer::onMetaChanged(const PcmStream* pcmStream)
|
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
|
// Send meta to all connected clients
|
||||||
const auto meta = pcmStream->getMeta();
|
const auto meta = pcmStream->getMeta();
|
||||||
|
@ -65,7 +63,9 @@ void StreamServer::onMetaChanged(const PcmStream* pcmStream)
|
||||||
|
|
||||||
void StreamServer::onStateChanged(const PcmStream* pcmStream, const ReaderState& state)
|
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) << "onStateChanged (" << pcmStream->getName() << "): " << state << "\n";
|
||||||
// LOG(INFO) << pcmStream->toJson().dump(4);
|
// LOG(INFO) << pcmStream->toJson().dump(4);
|
||||||
json notification = jsonrpcpp::Notification("Stream.OnUpdate", jsonrpcpp::Parameter("id", pcmStream->getId(), "stream", pcmStream->toJson())).to_json();
|
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
|
/// in case of a duplicate client id
|
||||||
if (getStreamSession(clientInfo->id) == nullptr)
|
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"}}
|
/// Notification:
|
||||||
json notification = jsonrpcpp::Notification("Client.OnDisconnect", jsonrpcpp::Parameter("id", clientInfo->id, "client", clientInfo->toJson())).to_json();
|
/// {"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());
|
controlServer_->send(notification.dump());
|
||||||
////cout << "Notification: " << notification.dump() << "\n";
|
////cout << "Notification: " << notification.dump() << "\n";
|
||||||
}
|
}
|
||||||
|
@ -169,7 +173,10 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
|
||||||
if (request->method() == "Client.GetStatus")
|
if (request->method() == "Client.GetStatus")
|
||||||
{
|
{
|
||||||
/// Request: {"id":8,"jsonrpc":"2.0","method":"Client.GetStatus","params":{"id":"00:21:6a:7d:74:fc"}}
|
/// 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();
|
result["client"] = clientInfo->toJson();
|
||||||
}
|
}
|
||||||
else if (request->method() == "Client.SetVolume")
|
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}}}
|
/// 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"));
|
clientInfo->config.volume.fromJson(request->params().get("volume"));
|
||||||
result["volume"] = clientInfo->config.volume.toJson();
|
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")
|
else if (request->method() == "Client.SetLatency")
|
||||||
{
|
{
|
||||||
|
@ -193,7 +201,8 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
|
||||||
latency = settings_.bufferMs;
|
latency = settings_.bufferMs;
|
||||||
clientInfo->config.latency = latency; //, -10000, settings_.bufferMs);
|
clientInfo->config.latency = latency; //, -10000, settings_.bufferMs);
|
||||||
result["latency"] = clientInfo->config.latency;
|
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")
|
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"}}
|
/// 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");
|
clientInfo->config.name = request->params().get<std::string>("name");
|
||||||
result["name"] = clientInfo->config.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
|
else
|
||||||
throw jsonrpcpp::MethodNotFoundException(request->id());
|
throw jsonrpcpp::MethodNotFoundException(request->id());
|
||||||
|
@ -233,7 +243,13 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
|
||||||
if (request->method() == "Group.GetStatus")
|
if (request->method() == "Group.GetStatus")
|
||||||
{
|
{
|
||||||
/// Request: {"id":5,"jsonrpc":"2.0","method":"Group.GetStatus","params":{"id":"4dcc4e3b-c699-a04b-7f0c-8260d23c43e1"}}
|
/// 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();
|
result["group"] = group->toJson();
|
||||||
}
|
}
|
||||||
else if (request->method() == "Group.SetMute")
|
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")
|
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"}}
|
/// 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");
|
string streamId = request->params().get<std::string>("stream_id");
|
||||||
PcmStreamPtr stream = streamManager_->getStream(streamId);
|
PcmStreamPtr stream = streamManager_->getStream(streamId);
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
|
@ -293,9 +311,33 @@ void StreamServer::ProcessRequest(const jsonrpcpp::request_ptr request, jsonrpcp
|
||||||
}
|
}
|
||||||
else if (request->method() == "Group.SetClients")
|
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"}}
|
/// Request:
|
||||||
/// 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"}}]}}}
|
/// {"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"}}
|
||||||
/// 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"}}]}}}
|
/// 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");
|
vector<string> clients = request->params().get("clients");
|
||||||
/// Remove clients from group
|
/// Remove clients from group
|
||||||
for (auto iter = group->clients.begin(); iter != group->clients.end();)
|
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")
|
else if (request->method() == "Server.GetStatus")
|
||||||
{
|
{
|
||||||
/// Request: {"id":1,"jsonrpc":"2.0","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());
|
result["server"] = Config::instance().getServerStatus(streamManager_->toJson());
|
||||||
}
|
}
|
||||||
else if (request->method() == "Server.DeleteClient")
|
else if (request->method() == "Server.DeleteClient")
|
||||||
{
|
{
|
||||||
/// Request: {"id":2,"jsonrpc":"2.0","method":"Server.DeleteClient","params":{"id":"00:21:6a:7d:74:fc"}}
|
/// 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"}}]}}}
|
/// Response: {"id":2,"jsonrpc":"2.0","result":{"server":{"groups":[{"clients":[{"config":{"instance":2,"latency":6,"name":"123
|
||||||
/// 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"}}]}}}
|
/// 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"));
|
ClientInfoPtr clientInfo = Config::instance().getClientInfo(request->params().get<std::string>("id"));
|
||||||
if (clientInfo == nullptr)
|
if (clientInfo == nullptr)
|
||||||
throw jsonrpcpp::InternalErrorException("Client not found", request->id());
|
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)
|
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)
|
if (baseMessage.type == message_type::kTime)
|
||||||
{
|
{
|
||||||
auto timeMsg = make_shared<msg::Time>();
|
auto timeMsg = make_shared<msg::Time>();
|
||||||
timeMsg->deserialize(baseMessage, buffer);
|
timeMsg->deserialize(baseMessage, buffer);
|
||||||
timeMsg->refersTo = timeMsg->id;
|
timeMsg->refersTo = timeMsg->id;
|
||||||
timeMsg->latency = timeMsg->received - timeMsg->sent;
|
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);
|
streamSession->sendAsync(timeMsg);
|
||||||
|
|
||||||
// refresh streamSession state
|
// refresh streamSession state
|
||||||
|
@ -583,7 +658,20 @@ void StreamServer::onMessageReceived(StreamSession* streamSession, const msg::Ba
|
||||||
|
|
||||||
if (newGroup)
|
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 server = Config::instance().getServerStatus(streamManager_->toJson());
|
||||||
json notification = jsonrpcpp::Notification("Server.OnUpdate", jsonrpcpp::Parameter("server", server)).to_json();
|
json notification = jsonrpcpp::Notification("Server.OnUpdate", jsonrpcpp::Parameter("server", server)).to_json();
|
||||||
controlServer_->send(notification.dump());
|
controlServer_->send(notification.dump());
|
||||||
|
@ -591,7 +679,10 @@ void StreamServer::onMessageReceived(StreamSession* streamSession, const msg::Ba
|
||||||
}
|
}
|
||||||
else
|
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();
|
json notification = jsonrpcpp::Notification("Client.OnConnect", jsonrpcpp::Parameter("id", client->id, "client", client->toJson())).to_json();
|
||||||
controlServer_->send(notification.dump());
|
controlServer_->send(notification.dump());
|
||||||
////cout << "Notification: " << notification.dump() << "\n";
|
////cout << "Notification: " << notification.dump() << "\n";
|
||||||
|
@ -769,4 +860,3 @@ void StreamServer::stop()
|
||||||
acceptor_v6_ = nullptr;
|
acceptor_v6_ = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -20,22 +20,22 @@
|
||||||
#define STREAM_SERVER_H
|
#define STREAM_SERVER_H
|
||||||
|
|
||||||
#include <asio.hpp>
|
#include <asio.hpp>
|
||||||
#include <vector>
|
|
||||||
#include <thread>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <mutex>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "jsonrpcpp.hpp"
|
|
||||||
#include "streamSession.h"
|
|
||||||
#include "streamreader/streamManager.h"
|
|
||||||
#include "common/queue.h"
|
#include "common/queue.h"
|
||||||
#include "common/sampleFormat.h"
|
#include "common/sampleFormat.h"
|
||||||
#include "message/message.h"
|
|
||||||
#include "message/codecHeader.h"
|
|
||||||
#include "message/serverSettings.h"
|
|
||||||
#include "controlServer.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;
|
using asio::ip::tcp;
|
||||||
|
@ -44,14 +44,8 @@ typedef std::shared_ptr<StreamSession> session_ptr;
|
||||||
|
|
||||||
struct StreamServerSettings
|
struct StreamServerSettings
|
||||||
{
|
{
|
||||||
StreamServerSettings() :
|
StreamServerSettings()
|
||||||
port(1704),
|
: port(1704), controlPort(1705), codec("flac"), bufferMs(1000), sampleFormat("48000:16:2"), streamReadMs(20), sendAudioToMutedClients(false)
|
||||||
controlPort(1705),
|
|
||||||
codec("flac"),
|
|
||||||
bufferMs(1000),
|
|
||||||
sampleFormat("48000:16:2"),
|
|
||||||
streamReadMs(20),
|
|
||||||
sendAudioToMutedClients(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
size_t port;
|
size_t port;
|
||||||
|
@ -118,5 +112,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,17 +18,17 @@
|
||||||
|
|
||||||
#include "streamSession.h"
|
#include "streamSession.h"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <mutex>
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
#include "message/pcmChunk.h"
|
#include "message/pcmChunk.h"
|
||||||
|
#include <iostream>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StreamSession::StreamSession(MessageReceiver* receiver, std::shared_ptr<tcp::socket> socket) :
|
StreamSession::StreamSession(MessageReceiver* receiver, std::shared_ptr<tcp::socket> socket)
|
||||||
active_(false), readerThread_(nullptr), writerThread_(nullptr), messageReceiver_(receiver), pcmStream_(nullptr)
|
: active_(false), readerThread_(nullptr), writerThread_(nullptr), messageReceiver_(receiver), pcmStream_(nullptr)
|
||||||
{
|
{
|
||||||
socket_ = socket;
|
socket_ = socket;
|
||||||
}
|
}
|
||||||
|
@ -80,9 +80,11 @@ void StreamSession::stop()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> socketLock(socketMutex_);
|
std::lock_guard<std::mutex> socketLock(socketMutex_);
|
||||||
socket_->shutdown(asio::ip::tcp::socket::shutdown_both, ec);
|
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);
|
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())
|
if (readerThread_ && readerThread_->joinable())
|
||||||
{
|
{
|
||||||
|
@ -113,8 +115,7 @@ void StreamSession::socketRead(void* _to, size_t _bytes)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
read += socket_->read_some(asio::buffer((char*)_to + read, _bytes - read));
|
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());
|
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())
|
if (baseMessage.size > buffer.size())
|
||||||
buffer.resize(baseMessage.size);
|
buffer.resize(baseMessage.size);
|
||||||
// {
|
// {
|
||||||
|
@ -259,5 +261,3 @@ void StreamSession::writer()
|
||||||
if (active_ && (messageReceiver_ != NULL))
|
if (active_ && (messageReceiver_ != NULL))
|
||||||
messageReceiver_->onDisconnect(this);
|
messageReceiver_->onDisconnect(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,17 +19,17 @@
|
||||||
#ifndef STREAM_SESSION_H
|
#ifndef STREAM_SESSION_H
|
||||||
#define 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 <string>
|
||||||
#include <thread>
|
#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;
|
using asio::ip::tcp;
|
||||||
|
@ -104,9 +104,4 @@ protected:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -17,11 +17,11 @@
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include "airplayStream.h"
|
#include "airplayStream.h"
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/utils.h"
|
|
||||||
#include "base64.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "base64.h"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include "common/utils.h"
|
||||||
|
#include "common/utils/string_utils.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -106,11 +106,15 @@ void AirplayStream::push()
|
||||||
if (entry_->type == "ssnc" && entry_->code == "mdst")
|
if (entry_->type == "ssnc" && entry_->code == "mdst")
|
||||||
jtag_ = json();
|
jtag_ = json();
|
||||||
|
|
||||||
if(entry_->code == "asal") jtag_["ALBUM"] = data;
|
if (entry_->code == "asal")
|
||||||
if(entry_->code == "asar") jtag_["ARTIST"] = data;
|
jtag_["ALBUM"] = data;
|
||||||
if(entry_->code == "minm") jtag_["TITLE"] = 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";
|
// LOG(INFO) << "metadata=" << jtag_.dump(4) << "\n";
|
||||||
setMeta(jtag_);
|
setMeta(jtag_);
|
||||||
}
|
}
|
||||||
|
@ -127,10 +131,12 @@ void AirplayStream::pipeReader()
|
||||||
{
|
{
|
||||||
ifstream pipe(pipePath_);
|
ifstream pipe(pipePath_);
|
||||||
|
|
||||||
if(pipe){
|
if (pipe)
|
||||||
|
{
|
||||||
string line;
|
string line;
|
||||||
|
|
||||||
while(getline(pipe, line)){
|
while (getline(pipe, line))
|
||||||
|
{
|
||||||
#ifdef HAS_EXPAT
|
#ifdef HAS_EXPAT
|
||||||
parse(line);
|
parse(line);
|
||||||
#endif
|
#endif
|
||||||
|
@ -187,9 +193,11 @@ void XMLCALL AirplayStream::element_start(void *userdata, const char *element_na
|
||||||
string name(element_name);
|
string name(element_name);
|
||||||
|
|
||||||
self->buf_.assign("");
|
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 name(attr[i]);
|
||||||
string value(attr[i + 1]);
|
string value(attr[i + 1]);
|
||||||
if (name == "encoding")
|
if (name == "encoding")
|
||||||
|
@ -217,8 +225,10 @@ void XMLCALL AirplayStream::element_end(void *userdata, const char *element_name
|
||||||
else if (name == "item")
|
else if (name == "item")
|
||||||
self->push();
|
self->push();
|
||||||
|
|
||||||
else if(name == "metatags") ;
|
else if (name == "metatags")
|
||||||
else cout << "Unknown tag <" << name << ">\n";
|
;
|
||||||
|
else
|
||||||
|
cout << "Unknown tag <" << name << ">\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
void XMLCALL AirplayStream::data(void* userdata, const char* content, int length)
|
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);
|
self->buf_.append(value);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -32,7 +32,9 @@
|
||||||
class TageEntry
|
class TageEntry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TageEntry(): isBase64(false), length(0) {}
|
TageEntry() : isBase64(false), length(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
std::string code;
|
std::string code;
|
||||||
std::string type;
|
std::string type;
|
||||||
|
|
|
@ -26,26 +26,29 @@
|
||||||
*/
|
*/
|
||||||
#include "base64.h"
|
#include "base64.h"
|
||||||
|
|
||||||
static const std::string base64_chars =
|
static const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
"abcdefghijklmnopqrstuvwxyz"
|
||||||
"0123456789+/";
|
"0123456789+/";
|
||||||
|
|
||||||
|
|
||||||
static inline bool is_base64(unsigned char c) {
|
static inline bool is_base64(unsigned char c)
|
||||||
|
{
|
||||||
return (isalnum(c) || (c == '+') || (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;
|
std::string ret;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 0;
|
int j = 0;
|
||||||
unsigned char char_array_3[3];
|
unsigned char char_array_3[3];
|
||||||
unsigned char char_array_4[4];
|
unsigned char char_array_4[4];
|
||||||
|
|
||||||
while (in_len--) {
|
while (in_len--)
|
||||||
|
{
|
||||||
char_array_3[i++] = *(bytes_to_encode++);
|
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[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[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);
|
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))
|
while ((i++ < 3))
|
||||||
ret += '=';
|
ret += '=';
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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 in_len = encoded_string.size();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j = 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];
|
unsigned char char_array_4[4], char_array_3[3];
|
||||||
std::string ret;
|
std::string ret;
|
||||||
|
|
||||||
while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) {
|
while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_]))
|
||||||
char_array_4[i++] = encoded_string[in_]; in_++;
|
{
|
||||||
if (i ==4) {
|
char_array_4[i++] = encoded_string[in_];
|
||||||
|
in_++;
|
||||||
|
if (i == 4)
|
||||||
|
{
|
||||||
for (i = 0; i < 4; i++)
|
for (i = 0; i < 4; i++)
|
||||||
char_array_4[i] = base64_chars.find(char_array_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++)
|
for (j = i; j < 4; j++)
|
||||||
char_array_4[j] = 0;
|
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[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];
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "fileStream.h"
|
|
||||||
#include "encoder/encoderFactory.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
|
#include "encoder/encoderFactory.h"
|
||||||
|
#include "fileStream.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FileStream::FileStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri)
|
FileStream::FileStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri)
|
||||||
{
|
{
|
||||||
ifs.open(uri_.path.c_str(), std::ifstream::in | std::ifstream::binary);
|
ifs.open(uri_.path.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||||
|
@ -84,7 +83,8 @@ void FileStream::worker()
|
||||||
ifs.read(chunk->payload + count, toRead - count);
|
ifs.read(chunk->payload + count, toRead - count);
|
||||||
|
|
||||||
encoder_->encode(chunk.get());
|
encoder_->encode(chunk.get());
|
||||||
if (!active_) break;
|
if (!active_)
|
||||||
|
break;
|
||||||
nextTick += pcmReadMs_;
|
nextTick += pcmReadMs_;
|
||||||
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
|
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
|
||||||
long currentTick = chronos::getTickCount();
|
long currentTick = chronos::getTickCount();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "encoder/encoderFactory.h"
|
#include "aixlog.hpp"
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
|
#include "encoder/encoderFactory.h"
|
||||||
#include "pcmStream.h"
|
#include "pcmStream.h"
|
||||||
#include "aixlog.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) :
|
PcmStream::PcmStream(PcmListener* pcmListener, const StreamUri& uri) : active_(false), pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
|
||||||
active_(false), pcmListener_(pcmListener), uri_(uri), pcmReadMs_(20), state_(kIdle)
|
|
||||||
{
|
{
|
||||||
EncoderFactory encoderFactory;
|
EncoderFactory encoderFactory;
|
||||||
if (uri_.query.find("codec") == uri_.query.end())
|
if (uri_.query.find("codec") == uri_.query.end())
|
||||||
|
@ -170,9 +169,7 @@ json PcmStream::toJson() const
|
||||||
state = "disabled";
|
state = "disabled";
|
||||||
|
|
||||||
json j = {
|
json j = {
|
||||||
{"uri", uri_.toJson()},
|
{"uri", uri_.toJson()}, {"id", getId()}, {"status", state},
|
||||||
{"id", getId()},
|
|
||||||
{"status", state},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (meta_)
|
if (meta_)
|
||||||
|
@ -196,4 +193,3 @@ void PcmStream::setMeta(json jtag)
|
||||||
if (pcmListener_)
|
if (pcmListener_)
|
||||||
pcmListener_->onMetaChanged(this);
|
pcmListener_->onMetaChanged(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,18 +19,18 @@
|
||||||
#ifndef PCM_STREAM_H
|
#ifndef PCM_STREAM_H
|
||||||
#define 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/json.hpp"
|
||||||
|
#include "common/sampleFormat.h"
|
||||||
|
#include "encoder/encoder.h"
|
||||||
#include "message/codecHeader.h"
|
#include "message/codecHeader.h"
|
||||||
#include "message/streamTags.h"
|
#include "message/streamTags.h"
|
||||||
|
#include "streamUri.h"
|
||||||
|
#include <atomic>
|
||||||
|
#include <condition_variable>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
|
||||||
class PcmStream;
|
class PcmStream;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
#include <cerrno>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <cerrno>
|
|
||||||
|
|
||||||
#include "pipeStream.h"
|
#include "aixlog.hpp"
|
||||||
#include "encoder/encoderFactory.h"
|
|
||||||
#include "common/snapException.h"
|
#include "common/snapException.h"
|
||||||
#include "common/strCompat.h"
|
#include "common/strCompat.h"
|
||||||
#include "aixlog.hpp"
|
#include "encoder/encoderFactory.h"
|
||||||
|
#include "pipeStream.h"
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
PipeStream::PipeStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), fd_(-1)
|
PipeStream::PipeStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), fd_(-1)
|
||||||
{
|
{
|
||||||
umask(0);
|
umask(0);
|
||||||
|
@ -108,15 +107,16 @@ void PipeStream::worker()
|
||||||
len += count;
|
len += count;
|
||||||
idleBytes = 0;
|
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
|
/// TODO: use less raw pointers, make this encoding more transparent
|
||||||
encoder_->encode(chunk.get());
|
encoder_->encode(chunk.get());
|
||||||
|
|
||||||
if (!active_) break;
|
if (!active_)
|
||||||
|
break;
|
||||||
|
|
||||||
nextTick += pcmReadMs_;
|
nextTick += pcmReadMs_;
|
||||||
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
|
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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 "processStream.h"
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/utils.h"
|
|
||||||
#include "aixlog.hpp"
|
#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;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ProcessStream::ProcessStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), path_(""), process_(nullptr)
|
ProcessStream::ProcessStream(PcmListener* pcmListener, const StreamUri& uri) : PcmStream(pcmListener, uri), path_(""), process_(nullptr)
|
||||||
{
|
{
|
||||||
params_ = uri_.getQuery("params");
|
params_ = uri_.getQuery("params");
|
||||||
|
@ -191,14 +190,15 @@ void ProcessStream::worker()
|
||||||
len += count;
|
len += count;
|
||||||
idleBytes = 0;
|
idleBytes = 0;
|
||||||
}
|
}
|
||||||
}
|
} while ((len < toRead) && active_);
|
||||||
while ((len < toRead) && active_);
|
|
||||||
|
|
||||||
if (!active_) break;
|
if (!active_)
|
||||||
|
break;
|
||||||
|
|
||||||
encoder_->encode(chunk.get());
|
encoder_->encode(chunk.get());
|
||||||
|
|
||||||
if (!active_) break;
|
if (!active_)
|
||||||
|
break;
|
||||||
|
|
||||||
nextTick += pcmReadMs_;
|
nextTick += pcmReadMs_;
|
||||||
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
|
chronos::addUs(tvChunk, pcmReadMs_ * 1000);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
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/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
#include <regex>
|
|
||||||
#include "spotifyStream.h"
|
#include "spotifyStream.h"
|
||||||
#include "common/snapException.h"
|
|
||||||
#include "common/utils/string_utils.h"
|
|
||||||
#include "common/utils.h"
|
|
||||||
#include "aixlog.hpp"
|
#include "aixlog.hpp"
|
||||||
|
#include "common/snapException.h"
|
||||||
|
#include "common/utils.h"
|
||||||
|
#include "common/utils/string_utils.h"
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SpotifyStream::SpotifyStream(PcmListener* pcmListener, const StreamUri& uri) : ProcessStream(pcmListener, uri)
|
SpotifyStream::SpotifyStream(PcmListener* pcmListener, const StreamUri& uri) : ProcessStream(pcmListener, uri)
|
||||||
{
|
{
|
||||||
sampleFormat_ = SampleFormat("44100:16:2");
|
sampleFormat_ = SampleFormat("44100:16:2");
|
||||||
|
@ -119,9 +118,7 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
|
||||||
watchdog_->trigger();
|
watchdog_->trigger();
|
||||||
string logmsg = utils::string::trim_copy(string(buffer, n));
|
string logmsg = utils::string::trim_copy(string(buffer, n));
|
||||||
|
|
||||||
if ((logmsg.find("allocated stream") == string::npos) &&
|
if ((logmsg.find("allocated stream") == string::npos) && (logmsg.find("Got channel") == string::npos) && (logmsg.find('\0') == string::npos) &&
|
||||||
(logmsg.find("Got channel") == string::npos) &&
|
|
||||||
(logmsg.find('\0') == string::npos) &&
|
|
||||||
(logmsg.size() > 4))
|
(logmsg.size() > 4))
|
||||||
{
|
{
|
||||||
LOG(INFO) << "(" << getName() << ") " << logmsg << "\n";
|
LOG(INFO) << "(" << getName() << ") " << logmsg << "\n";
|
||||||
|
@ -141,9 +138,7 @@ void SpotifyStream::onStderrMsg(const char* buffer, size_t n)
|
||||||
{
|
{
|
||||||
LOG(INFO) << "metadata: <" << m[1] << ">\n";
|
LOG(INFO) << "metadata: <" << m[1] << ">\n";
|
||||||
|
|
||||||
json jtag = {
|
json jtag = {{"TITLE", (string)m[1]}};
|
||||||
{"TITLE", (string)m[1]}
|
|
||||||
};
|
|
||||||
setMeta(jtag);
|
setMeta(jtag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,5 +170,3 @@ void SpotifyStream::onTimeout(const Watchdog* watchdog, size_t ms)
|
||||||
if (process_)
|
if (process_)
|
||||||
process_->kill();
|
process_->kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -28,7 +28,8 @@
|
||||||
* Implements EncoderListener to get the encoded data.
|
* Implements EncoderListener to get the encoded data.
|
||||||
* Data is passed to the PcmListener
|
* Data is passed to the PcmListener
|
||||||
* usage:
|
* 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
|
class SpotifyStream : public ProcessStream, WatchdogListener
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/***
|
/***
|
||||||
This file is part of snapcast
|
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
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,20 +18,21 @@
|
||||||
|
|
||||||
#include "streamManager.h"
|
#include "streamManager.h"
|
||||||
#include "airplayStream.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 "aixlog.hpp"
|
||||||
#include "common/snapException.h"
|
#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;
|
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());
|
result.push_back(stream->toJson());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#ifndef PCM_READER_FACTORY_H
|
#ifndef PCM_READER_FACTORY_H
|
||||||
#define PCM_READER_FACTORY_H
|
#define PCM_READER_FACTORY_H
|
||||||
|
|
||||||
|
#include "pcmStream.h"
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <memory>
|
|
||||||
#include "pcmStream.h"
|
|
||||||
|
|
||||||
typedef std::shared_ptr<PcmStream> PcmStreamPtr;
|
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