diff --git a/server/config.cpp b/server/config.cpp index 7f0e0392..377b1736 100644 --- a/server/config.cpp +++ b/server/config.cpp @@ -84,7 +84,7 @@ ClientInfoPtr Config::getClientInfo(const std::string& macAddress, bool add) for (auto client: clients) { - if (client->macAddress == macAddress) + if (client->host.mac == macAddress) return client; } diff --git a/server/config.h b/server/config.h index 24ca24e5..9d7e29cd 100644 --- a/server/config.h +++ b/server/config.h @@ -24,6 +24,8 @@ #include #include #include "json/json.hpp" +#include "common/utils.h" + 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(j, "name", "")); + mac = trim_copy(jGet(j, "mac", "")); + os = trim_copy(jGet(j, "os", "")); + arch = trim_copy(jGet(j, "arch", "")); + ip = trim_copy(jGet(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(j, "name", "")); + volume.fromJson(j["volume"]); + latency = jGet(j, "latency", 0); + streamId = trim_copy(jGet(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(j, "name", "")); + version = trim_copy(jGet(j, "version", "")); + streamProtocolVersion = jGet(j, "streamProtocolVersion", 1); + controlProtocolVersion = jGet(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 { - 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_usec = 0; @@ -77,47 +176,52 @@ struct ClientInfo void fromJson(const json& j) { - macAddress = jGet(j, "MAC", ""); - ipAddress = jGet(j, "IP", ""); - hostName = jGet(j, "host", ""); - version = jGet(j, "version", ""); - name = jGet(j, "name", ""); - volume.fromJson(j["volume"]); + if (j.count("host") && !j["host"].is_string()) + host.fromJson(j["host"]); + else + { + host.ip = jGet(j, "IP", ""); + host.mac = jGet(j, "MAC", ""); + host.name = jGet(j, "host", ""); + } + + if (j.count("snapclient")) + snapclient.fromJson(j["snapclient"]); + else + snapclient.version = jGet(j, "version", ""); + + if (j.count("config")) + host.fromJson(j["config"]); + else + { + config.name = trim_copy(jGet(j, "name", "")); + config.volume.fromJson(j["volume"]); + config.latency = jGet(j, "latency", 0); + config.streamId = trim_copy(jGet(j, "stream", "")); + } + lastSeen.tv_sec = jGet(j["lastSeen"], "sec", 0); lastSeen.tv_usec = jGet(j["lastSeen"], "usec", 0); connected = jGet(j, "connected", true); - latency = jGet(j, "latency", 0); - streamId = jGet(j, "stream", ""); } json toJson() { json j; - j["MAC"] = macAddress; - j["IP"] = ipAddress; - j["host"] = hostName; - j["version"] = version; - j["name"] = name; - j["volume"] = volume.toJson(); + j["host"] = host.toJson(); + j["snapclient"] = snapclient.toJson(); + j["config"] = config.toJson(); j["lastSeen"]["sec"] = lastSeen.tv_sec; j["lastSeen"]["usec"] = lastSeen.tv_usec; j["connected"] = connected; - j["latency"] = latency; - j["stream"] = streamId; return j; } - std::string macAddress; - std::string ipAddress; - std::string hostName; - std::string version; - std::string name; - Volume volume; - bool muted; + Host host; + Snapcast snapclient; + ClientConfig config; timeval lastSeen; bool connected; - int32_t latency; - std::string streamId; }; typedef std::shared_ptr ClientInfoPtr; diff --git a/server/streamServer.cpp b/server/streamServer.cpp index b0ae62f7..163172d2 100644 --- a/server/streamServer.cpp +++ b/server/streamServer.cpp @@ -135,21 +135,25 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std:: else jClient = Config::instance().getClientInfos(); + Host host; + //TODO: Set MAC and IP + Snapcast snapserver("Snapserver", VERSION); response = { {"server", { - {"host", getHostName()}, - {"version", VERSION} + {"host", host.toJson()},//getHostName()}, + {"snapserver", snapserver.toJson()} }}, {"clients", jClient}, {"streams", streamManager_->toJson()} }; +// cout << response.dump(4); } else if (request.method == "Server.DeleteClient") { clientInfo = Config::instance().getClientInfo(request.getParam("client").get(), false); if (clientInfo == nullptr) throw JsonInternalErrorException("Client not found", request.id); - response = clientInfo->macAddress; + response = clientInfo->host.mac; Config::instance().remove(clientInfo); Config::instance().save(); 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") { - clientInfo->volume.percent = request.getParam("volume", 0, 100); - response = clientInfo->volume.percent; + clientInfo->config.volume.percent = request.getParam("volume", 0, 100); + response = clientInfo->config.volume.percent; } else if (request.method == "Client.SetMute") { - clientInfo->volume.muted = request.getParam("mute", false, true); - response = clientInfo->volume.muted; + clientInfo->config.volume.muted = request.getParam("mute", false, true); + response = clientInfo->config.volume.muted; } else if (request.method == "Client.SetStream") { @@ -173,8 +177,8 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std:: if (stream == nullptr) throw JsonInternalErrorException("Stream not found", request.id); - clientInfo->streamId = streamId; - response = clientInfo->streamId; + clientInfo->config.streamId = streamId; + response = clientInfo->config.streamId; StreamSession* session = getStreamSession(request.getParam("client").get()); if (session != NULL) @@ -185,22 +189,22 @@ void StreamServer::onMessageReceived(ControlSession* controlSession, const std:: } else if (request.method == "Client.SetLatency") { - clientInfo->latency = request.getParam("latency", -10000, settings_.bufferMs); - response = clientInfo->latency; + clientInfo->config.latency = request.getParam("latency", -10000, settings_.bufferMs); + response = clientInfo->config.latency; } else if (request.method == "Client.SetName") { - clientInfo->name = request.getParam("name").get(); - response = clientInfo->name; + clientInfo->config.name = request.getParam("name").get(); + response = clientInfo->config.name; } else throw JsonMethodNotFoundException(request.id); if (clientInfo != nullptr) { - serverSettings.volume = clientInfo->volume.percent; - serverSettings.muted = clientInfo->volume.muted; - serverSettings.latency = clientInfo->latency; + serverSettings.volume = clientInfo->config.volume.percent; + serverSettings.muted = clientInfo->config.volume.muted; + serverSettings.latency = clientInfo->config.latency; StreamSession* session = getStreamSession(request.getParam("client").get()); if (session != NULL) @@ -247,7 +251,9 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM msg::Hello helloMsg; helloMsg.deserialize(baseMessage, buffer); 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"; // std::lock_guard mlock(mutex_); @@ -260,27 +266,32 @@ void StreamServer::onMessageReceived(StreamSession* connection, const msg::BaseM { logD << "request kServerSettings\n"; msg::ServerSettings serverSettings; - serverSettings.volume = clientInfo->volume.percent; - serverSettings.muted = clientInfo->volume.muted; - serverSettings.latency = clientInfo->latency; + serverSettings.volume = clientInfo->config.volume.percent; + serverSettings.muted = clientInfo->config.volume.muted; + serverSettings.latency = clientInfo->config.latency; serverSettings.refersTo = helloMsg.id; serverSettings.bufferMs = settings_.bufferMs; connection->send(&serverSettings); } ClientInfoPtr client = Config::instance().getClientInfo(connection->macAddress); - client->ipAddress = connection->getIP(); - client->hostName = helloMsg.getHostName(); - client->version = helloMsg.getVersion(); + client->host.ip = connection->getIP(); + client->host.name = helloMsg.getHostName(); + 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; gettimeofday(&client->lastSeen, NULL); // Assign and update stream - PcmReaderPtr stream = streamManager_->getStream(client->streamId); + PcmReaderPtr stream = streamManager_->getStream(client->config.streamId); if (stream == nullptr) { stream = streamManager_->getDefaultStream(); - client->streamId = stream->getUri().id(); + client->config.streamId = stream->getUri().id(); } Config::instance().save();