mirror of
https://github.com/badaix/snapcast.git
synced 2025-05-31 01:46:16 +02:00
added Host, Snapcast and Config to Client json
This commit is contained in:
parent
d8e23fadac
commit
8ddf928b9a
3 changed files with 167 additions and 52 deletions
|
@ -84,7 +84,7 @@ ClientInfoPtr Config::getClientInfo(const std::string& macAddress, bool add)
|
||||||
|
|
||||||
for (auto client: clients)
|
for (auto client: clients)
|
||||||
{
|
{
|
||||||
if (client->macAddress == macAddress)
|
if (client->host.mac == macAddress)
|
||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
156
server/config.h
156
server/config.h
|
@ -24,6 +24,8 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "json/json.hpp"
|
#include "json/json.hpp"
|
||||||
|
#include "common/utils.h"
|
||||||
|
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
@ -67,9 +69,106 @@ struct Volume
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Host
|
||||||
|
{
|
||||||
|
Host(const std::string& _macAddress = "") : name(getHostName()), mac(_macAddress), os(getOS()), arch(getArch()), ip("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fromJson(const json& j)
|
||||||
|
{
|
||||||
|
name = trim_copy(jGet<std::string>(j, "name", ""));
|
||||||
|
mac = trim_copy(jGet<std::string>(j, "mac", ""));
|
||||||
|
os = trim_copy(jGet<std::string>(j, "os", ""));
|
||||||
|
arch = trim_copy(jGet<std::string>(j, "arch", ""));
|
||||||
|
ip = trim_copy(jGet<std::string>(j, "ip", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
json toJson()
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["name"] = name;
|
||||||
|
j["mac"] = mac;
|
||||||
|
j["os"] = os;
|
||||||
|
j["arch"] = arch;
|
||||||
|
j["ip"] = ip;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string mac;
|
||||||
|
std::string os;
|
||||||
|
std::string arch;
|
||||||
|
std::string ip;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct ClientConfig
|
||||||
|
{
|
||||||
|
ClientConfig() : name(""), volume(100), latency(0), streamId("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fromJson(const json& j)
|
||||||
|
{
|
||||||
|
name = trim_copy(jGet<std::string>(j, "name", ""));
|
||||||
|
volume.fromJson(j["volume"]);
|
||||||
|
latency = jGet<int32_t>(j, "latency", 0);
|
||||||
|
streamId = trim_copy(jGet<std::string>(j, "stream", ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
json toJson()
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["name"] = trim_copy(name);
|
||||||
|
j["volume"] = volume.toJson();
|
||||||
|
j["latency"] = latency;
|
||||||
|
j["stream"] = trim_copy(streamId);
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
Volume volume;
|
||||||
|
int32_t latency;
|
||||||
|
std::string streamId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Snapcast
|
||||||
|
{
|
||||||
|
Snapcast(const std::string& _name = "", const std::string& _version = "") : name(_name), version(_version), streamProtocolVersion(1), controlProtocolVersion(1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void fromJson(const json& j)
|
||||||
|
{
|
||||||
|
name = trim_copy(jGet<std::string>(j, "name", ""));
|
||||||
|
version = trim_copy(jGet<std::string>(j, "version", ""));
|
||||||
|
streamProtocolVersion = jGet<int>(j, "streamProtocolVersion", 1);
|
||||||
|
controlProtocolVersion = jGet<int>(j, "controlProtocolVersion", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
json toJson()
|
||||||
|
{
|
||||||
|
json j;
|
||||||
|
j["name"] = trim_copy(name);
|
||||||
|
j["version"] = trim_copy(version);
|
||||||
|
j["streamProtocolVersion"] = streamProtocolVersion;
|
||||||
|
j["controlProtocolVersion"] = controlProtocolVersion;
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name;
|
||||||
|
std::string version;
|
||||||
|
int streamProtocolVersion;
|
||||||
|
int controlProtocolVersion;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ClientInfo
|
struct ClientInfo
|
||||||
{
|
{
|
||||||
ClientInfo(const std::string& _macAddress = "") : macAddress(_macAddress), volume(100), connected(false), latency(0), streamId("")
|
ClientInfo(const std::string& _macAddress = "") : host(_macAddress), connected(false)
|
||||||
{
|
{
|
||||||
lastSeen.tv_sec = 0;
|
lastSeen.tv_sec = 0;
|
||||||
lastSeen.tv_usec = 0;
|
lastSeen.tv_usec = 0;
|
||||||
|
@ -77,47 +176,52 @@ struct ClientInfo
|
||||||
|
|
||||||
void fromJson(const json& j)
|
void fromJson(const json& j)
|
||||||
{
|
{
|
||||||
macAddress = jGet<std::string>(j, "MAC", "");
|
if (j.count("host") && !j["host"].is_string())
|
||||||
ipAddress = jGet<std::string>(j, "IP", "");
|
host.fromJson(j["host"]);
|
||||||
hostName = jGet<std::string>(j, "host", "");
|
else
|
||||||
version = jGet<std::string>(j, "version", "");
|
{
|
||||||
name = jGet<std::string>(j, "name", "");
|
host.ip = jGet<std::string>(j, "IP", "");
|
||||||
volume.fromJson(j["volume"]);
|
host.mac = jGet<std::string>(j, "MAC", "");
|
||||||
|
host.name = jGet<std::string>(j, "host", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (j.count("snapclient"))
|
||||||
|
snapclient.fromJson(j["snapclient"]);
|
||||||
|
else
|
||||||
|
snapclient.version = jGet<std::string>(j, "version", "");
|
||||||
|
|
||||||
|
if (j.count("config"))
|
||||||
|
host.fromJson(j["config"]);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
config.name = trim_copy(jGet<std::string>(j, "name", ""));
|
||||||
|
config.volume.fromJson(j["volume"]);
|
||||||
|
config.latency = jGet<int32_t>(j, "latency", 0);
|
||||||
|
config.streamId = trim_copy(jGet<std::string>(j, "stream", ""));
|
||||||
|
}
|
||||||
|
|
||||||
lastSeen.tv_sec = jGet<int32_t>(j["lastSeen"], "sec", 0);
|
lastSeen.tv_sec = jGet<int32_t>(j["lastSeen"], "sec", 0);
|
||||||
lastSeen.tv_usec = jGet<int32_t>(j["lastSeen"], "usec", 0);
|
lastSeen.tv_usec = jGet<int32_t>(j["lastSeen"], "usec", 0);
|
||||||
connected = jGet<bool>(j, "connected", true);
|
connected = jGet<bool>(j, "connected", true);
|
||||||
latency = jGet<int32_t>(j, "latency", 0);
|
|
||||||
streamId = jGet<std::string>(j, "stream", "");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
json toJson()
|
json toJson()
|
||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
j["MAC"] = macAddress;
|
j["host"] = host.toJson();
|
||||||
j["IP"] = ipAddress;
|
j["snapclient"] = snapclient.toJson();
|
||||||
j["host"] = hostName;
|
j["config"] = config.toJson();
|
||||||
j["version"] = version;
|
|
||||||
j["name"] = name;
|
|
||||||
j["volume"] = volume.toJson();
|
|
||||||
j["lastSeen"]["sec"] = lastSeen.tv_sec;
|
j["lastSeen"]["sec"] = lastSeen.tv_sec;
|
||||||
j["lastSeen"]["usec"] = lastSeen.tv_usec;
|
j["lastSeen"]["usec"] = lastSeen.tv_usec;
|
||||||
j["connected"] = connected;
|
j["connected"] = connected;
|
||||||
j["latency"] = latency;
|
|
||||||
j["stream"] = streamId;
|
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string macAddress;
|
Host host;
|
||||||
std::string ipAddress;
|
Snapcast snapclient;
|
||||||
std::string hostName;
|
ClientConfig config;
|
||||||
std::string version;
|
|
||||||
std::string name;
|
|
||||||
Volume volume;
|
|
||||||
bool muted;
|
|
||||||
timeval lastSeen;
|
timeval lastSeen;
|
||||||
bool connected;
|
bool connected;
|
||||||
int32_t latency;
|
|
||||||
std::string streamId;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::shared_ptr<ClientInfo> ClientInfoPtr;
|
typedef std::shared_ptr<ClientInfo> ClientInfoPtr;
|
||||||
|
|
|
@ -135,21 +135,25 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
||||||
else
|
else
|
||||||
jClient = Config::instance().getClientInfos();
|
jClient = Config::instance().getClientInfos();
|
||||||
|
|
||||||
|
Host host;
|
||||||
|
//TODO: Set MAC and IP
|
||||||
|
Snapcast snapserver("Snapserver", VERSION);
|
||||||
response = {
|
response = {
|
||||||
{"server", {
|
{"server", {
|
||||||
{"host", getHostName()},
|
{"host", host.toJson()},//getHostName()},
|
||||||
{"version", VERSION}
|
{"snapserver", snapserver.toJson()}
|
||||||
}},
|
}},
|
||||||
{"clients", jClient},
|
{"clients", jClient},
|
||||||
{"streams", streamManager_->toJson()}
|
{"streams", streamManager_->toJson()}
|
||||||
};
|
};
|
||||||
|
// cout << response.dump(4);
|
||||||
}
|
}
|
||||||
else if (request.method == "Server.DeleteClient")
|
else if (request.method == "Server.DeleteClient")
|
||||||
{
|
{
|
||||||
clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>(), false);
|
clientInfo = Config::instance().getClientInfo(request.getParam("client").get<string>(), false);
|
||||||
if (clientInfo == nullptr)
|
if (clientInfo == nullptr)
|
||||||
throw JsonInternalErrorException("Client not found", request.id);
|
throw JsonInternalErrorException("Client not found", request.id);
|
||||||
response = clientInfo->macAddress;
|
response = clientInfo->host.mac;
|
||||||
Config::instance().remove(clientInfo);
|
Config::instance().remove(clientInfo);
|
||||||
Config::instance().save();
|
Config::instance().save();
|
||||||
json notification = JsonNotification::getJson("Client.OnDelete", clientInfo->toJson());
|
json notification = JsonNotification::getJson("Client.OnDelete", clientInfo->toJson());
|
||||||
|
@ -158,13 +162,13 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
||||||
}
|
}
|
||||||
else if (request.method == "Client.SetVolume")
|
else if (request.method == "Client.SetVolume")
|
||||||
{
|
{
|
||||||
clientInfo->volume.percent = request.getParam<uint16_t>("volume", 0, 100);
|
clientInfo->config.volume.percent = request.getParam<uint16_t>("volume", 0, 100);
|
||||||
response = clientInfo->volume.percent;
|
response = clientInfo->config.volume.percent;
|
||||||
}
|
}
|
||||||
else if (request.method == "Client.SetMute")
|
else if (request.method == "Client.SetMute")
|
||||||
{
|
{
|
||||||
clientInfo->volume.muted = request.getParam<bool>("mute", false, true);
|
clientInfo->config.volume.muted = request.getParam<bool>("mute", false, true);
|
||||||
response = clientInfo->volume.muted;
|
response = clientInfo->config.volume.muted;
|
||||||
}
|
}
|
||||||
else if (request.method == "Client.SetStream")
|
else if (request.method == "Client.SetStream")
|
||||||
{
|
{
|
||||||
|
@ -173,8 +177,8 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
throw JsonInternalErrorException("Stream not found", request.id);
|
throw JsonInternalErrorException("Stream not found", request.id);
|
||||||
|
|
||||||
clientInfo->streamId = streamId;
|
clientInfo->config.streamId = streamId;
|
||||||
response = clientInfo->streamId;
|
response = clientInfo->config.streamId;
|
||||||
|
|
||||||
StreamSession* session = getStreamSession(request.getParam("client").get<string>());
|
StreamSession* session = getStreamSession(request.getParam("client").get<string>());
|
||||||
if (session != NULL)
|
if (session != NULL)
|
||||||
|
@ -185,22 +189,22 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std::
|
||||||
}
|
}
|
||||||
else if (request.method == "Client.SetLatency")
|
else if (request.method == "Client.SetLatency")
|
||||||
{
|
{
|
||||||
clientInfo->latency = request.getParam<int>("latency", -10000, settings_.bufferMs);
|
clientInfo->config.latency = request.getParam<int>("latency", -10000, settings_.bufferMs);
|
||||||
response = clientInfo->latency;
|
response = clientInfo->config.latency;
|
||||||
}
|
}
|
||||||
else if (request.method == "Client.SetName")
|
else if (request.method == "Client.SetName")
|
||||||
{
|
{
|
||||||
clientInfo->name = request.getParam("name").get<string>();
|
clientInfo->config.name = request.getParam("name").get<string>();
|
||||||
response = clientInfo->name;
|
response = clientInfo->config.name;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw JsonMethodNotFoundException(request.id);
|
throw JsonMethodNotFoundException(request.id);
|
||||||
|
|
||||||
if (clientInfo != nullptr)
|
if (clientInfo != nullptr)
|
||||||
{
|
{
|
||||||
serverSettings.volume = clientInfo->volume.percent;
|
serverSettings.volume = clientInfo->config.volume.percent;
|
||||||
serverSettings.muted = clientInfo->volume.muted;
|
serverSettings.muted = clientInfo->config.volume.muted;
|
||||||
serverSettings.latency = clientInfo->latency;
|
serverSettings.latency = clientInfo->config.latency;
|
||||||
|
|
||||||
StreamSession* session = getStreamSession(request.getParam("client").get<string>());
|
StreamSession* session = getStreamSession(request.getParam("client").get<string>());
|
||||||
if (session != NULL)
|
if (session != NULL)
|
||||||
|
@ -247,7 +251,9 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
||||||
msg::Hello helloMsg;
|
msg::Hello helloMsg;
|
||||||
helloMsg.deserialize(baseMessage, buffer);
|
helloMsg.deserialize(baseMessage, buffer);
|
||||||
connection->macAddress = helloMsg.getMacAddress();
|
connection->macAddress = helloMsg.getMacAddress();
|
||||||
logO << "Hello from " << connection->macAddress << ", host: " << helloMsg.getHostName() << ", v" << helloMsg.getVersion() << "\n";
|
logO << "Hello from " << connection->macAddress << ", host: " << helloMsg.getHostName() << ", v" << helloMsg.getVersion()
|
||||||
|
<< ", ClientName: " << helloMsg.getClientName() << ", OS: " << helloMsg.getOS() << ", Arch: " << helloMsg.getArch()
|
||||||
|
<< ", control version: " << helloMsg.getControlProtocolVersion() << ", Stream version: " << helloMsg.getStreamProtocolVersion() << "\n";
|
||||||
|
|
||||||
logD << "request kServerSettings: " << connection->macAddress << "\n";
|
logD << "request kServerSettings: " << connection->macAddress << "\n";
|
||||||
// std::lock_guard<std::mutex> mlock(mutex_);
|
// std::lock_guard<std::mutex> mlock(mutex_);
|
||||||
|
@ -260,27 +266,32 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM
|
||||||
{
|
{
|
||||||
logD << "request kServerSettings\n";
|
logD << "request kServerSettings\n";
|
||||||
msg::ServerSettings serverSettings;
|
msg::ServerSettings serverSettings;
|
||||||
serverSettings.volume = clientInfo->volume.percent;
|
serverSettings.volume = clientInfo->config.volume.percent;
|
||||||
serverSettings.muted = clientInfo->volume.muted;
|
serverSettings.muted = clientInfo->config.volume.muted;
|
||||||
serverSettings.latency = clientInfo->latency;
|
serverSettings.latency = clientInfo->config.latency;
|
||||||
serverSettings.refersTo = helloMsg.id;
|
serverSettings.refersTo = helloMsg.id;
|
||||||
serverSettings.bufferMs = settings_.bufferMs;
|
serverSettings.bufferMs = settings_.bufferMs;
|
||||||
connection->send(&serverSettings);
|
connection->send(&serverSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClientInfoPtr client = Config::instance().getClientInfo(connection->macAddress);
|
ClientInfoPtr client = Config::instance().getClientInfo(connection->macAddress);
|
||||||
client->ipAddress = connection->getIP();
|
client->host.ip = connection->getIP();
|
||||||
client->hostName = helloMsg.getHostName();
|
client->host.name = helloMsg.getHostName();
|
||||||
client->version = helloMsg.getVersion();
|
client->host.os = helloMsg.getOS();
|
||||||
|
client->host.arch = helloMsg.getArch();
|
||||||
|
client->snapclient.version = helloMsg.getVersion();
|
||||||
|
client->snapclient.name = helloMsg.getClientName();
|
||||||
|
client->snapclient.streamProtocolVersion = helloMsg.getStreamProtocolVersion();
|
||||||
|
client->snapclient.controlProtocolVersion = helloMsg.getControlProtocolVersion();
|
||||||
client->connected = true;
|
client->connected = true;
|
||||||
gettimeofday(&client->lastSeen, NULL);
|
gettimeofday(&client->lastSeen, NULL);
|
||||||
|
|
||||||
// Assign and update stream
|
// Assign and update stream
|
||||||
PcmReaderPtr stream = streamManager_->getStream(client->streamId);
|
PcmReaderPtr stream = streamManager_->getStream(client->config.streamId);
|
||||||
if (stream == nullptr)
|
if (stream == nullptr)
|
||||||
{
|
{
|
||||||
stream = streamManager_->getDefaultStream();
|
stream = streamManager_->getDefaultStream();
|
||||||
client->streamId = stream->getUri().id();
|
client->config.streamId = stream->getUri().id();
|
||||||
}
|
}
|
||||||
Config::instance().save();
|
Config::instance().save();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue