/*** This file is part of snapcast Copyright (C) 2014-2017 Johannes Pohl This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ***/ #include "config.h" #include #include #include #include #include "common/snapException.h" #include "common/strCompat.h" #include "common/log.h" using namespace std; Config::Config() { string dir; if (getenv("HOME") == NULL) dir = "/var/lib/snapserver/"; else dir = getenv("HOME") + string("/.config/snapserver/"); int status = mkdirRecursive(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if ((status != 0) && (errno != EEXIST)) throw SnapException("failed to create settings directory: \"" + dir + "\": " + cpt::to_string(errno)); filename_ = dir + "server.json"; logO << "Settings file: " << filename_ << "\n"; try { ifstream ifs(filename_, std::ifstream::in); if (ifs.good()) { json j; ifs >> j; if (j.count("ConfigVersion")) { json jGroups = j["Groups"]; for (auto it = jGroups.begin(); it != jGroups.end(); ++it) { GroupPtr group = make_shared(); group->fromJson(*it); // if (client->id.empty() || getClientInfo(client->id)) // continue; groups.push_back(group); } } } } catch(const std::exception& e) { logE << "Error reading config: " << e.what() << "\n"; } } Config::~Config() { save(); } void Config::save() { std::ofstream ofs(filename_.c_str(), std::ofstream::out|std::ofstream::trunc); json clients = { {"ConfigVersion", 2}, {"Groups", getGroups()} }; ofs << std::setw(4) << clients; ofs.close(); } ClientInfoPtr Config::getClientInfo(const std::string& clientId) const { if (clientId.empty()) return nullptr; for (auto group: groups) { for (auto client: group->clients) { if (client->id == clientId) return client; } } return nullptr; } GroupPtr Config::addClientInfo(ClientInfoPtr client) { GroupPtr group = getGroupFromClient(client); if (!group) { group = std::make_shared(); group->addClient(client); groups.push_back(group); } return group; } GroupPtr Config::addClientInfo(const std::string& clientId) { ClientInfoPtr client = getClientInfo(clientId); if (!client) client = make_shared(clientId); return addClientInfo(client); } GroupPtr Config::getGroup(const std::string& groupId) const { for (auto group: groups) { if (group->id == groupId) return group; } return nullptr; } GroupPtr Config::getGroupFromClient(const std::string& clientId) { for (auto group: groups) { for (auto c: group->clients) { if (c->id == clientId) return group; } } return nullptr; } GroupPtr Config::getGroupFromClient(ClientInfoPtr client) { return getGroupFromClient(client->id); } json Config::getServerStatus(const json& streams) const { Host host; host.update(); //TODO: Set MAC and IP Snapserver snapserver("Snapserver", VERSION); json serverStatus = { {"server", { {"host", host.toJson()},//getHostName()}, {"snapserver", snapserver.toJson()} }}, {"groups", getGroups()}, {"streams", streams} }; return serverStatus; } json Config::getGroups() const { json result = json::array(); for (auto group: groups) result.push_back(group->toJson()); return result; } void Config::remove(ClientInfoPtr client) { auto group = getGroupFromClient(client); if (!group) return; group->removeClient(client); if (group->empty()) remove(group); } void Config::remove(GroupPtr group, bool force) { if (!group) return; if (group->empty() || force) groups.erase(std::remove(groups.begin(), groups.end(), group), groups.end()); } /* GroupPtr Config::removeFromGroup(const std::string& groupId, const std::string& clientId) { GroupPtr group = getGroup(groupId); if (!group || (group->id != groupId)) return group; auto client = getClientInfo(clientId); if (client) group->clients.erase(std::remove(group->clients.begin(), group->clients.end(), client), group->clients.end()); addClientInfo(clientId); return group; } GroupPtr Config::setGroupForClient(const std::string& groupId, const std::string& clientId) { GroupPtr oldGroup = getGroupFromClient(clientId); if (oldGroup && (oldGroup->id == groupId)) return oldGroup; GroupPtr newGroup = getGroup(groupId); if (!newGroup) return nullptr; auto client = getClientInfo(clientId); if (!client) return nullptr; if (oldGroup) removeFromGroup(oldGroup->id, clientId); newGroup->addClient(client); return newGroup; } */