diff --git a/CMakeLists.txt b/CMakeLists.txt index 7097ccea4..d0fc439c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -423,6 +423,7 @@ add_subdirectory(tools/ultimate_lyrics_parser) add_subdirectory(ext/libclementine-common) add_subdirectory(ext/libclementine-tagreader) add_subdirectory(ext/clementine-tagreader) +add_subdirectory(ext/libclementine-remote) option(WITH_DEBIAN OFF) if(WITH_DEBIAN) diff --git a/ext/libclementine-remote/CMakeLists.txt b/ext/libclementine-remote/CMakeLists.txt new file mode 100644 index 000000000..f6fc7685a --- /dev/null +++ b/ext/libclementine-remote/CMakeLists.txt @@ -0,0 +1,16 @@ +include_directories(${PROTOBUF_INCLUDE_DIRS}) + +set(MESSAGES + remotecontrolmessages.proto +) + +protobuf_generate_cpp(PROTO_SOURCES PROTO_HEADERS ${MESSAGES}) + +add_library(libclementine-remote STATIC + ${PROTO_SOURCES} +) + +target_link_libraries(libclementine-remote + libclementine-common +) + diff --git a/ext/libclementine-remote/remotecontrolmessages.proto b/ext/libclementine-remote/remotecontrolmessages.proto new file mode 100644 index 000000000..5a700a3ee --- /dev/null +++ b/ext/libclementine-remote/remotecontrolmessages.proto @@ -0,0 +1,73 @@ +package pb.remote; + +enum MsgType { + // Messages generally send from client to server + CONNECT = 0; + DISCONNECT = 1; + REQUEST_PLAYLISTS = 2; + REQUEST_PLAYLIST_SONGS = 3; + CHANGE_SONG = 4; + SET_VOLUME = 5; + + // Messages send by both + PLAY = 20; + PLAYPAUSE = 21; + PAUSE = 22; + STOP = 23; + NEXT = 24; + PREV = 25; + + // Messages send from server to client + INFOS = 40; + CURRENT_METAINFOS = 41; + PLAYLISTS = 42; + PLAYLIST_SONGS = 43; + KEEP_ALIVE = 44; +} + +enum EngineState { + Empty = 0; + Idle = 1; + Playing = 2; + Paused = 3; +} + +message Message { + required MsgType msgType = 1; + + optional EngineState state = 2; + optional ClementineInfos infos = 3; + optional SongMetadata currentSong = 4; + optional int32 volume = 5; + repeated Playlist playlists = 6; +} + +message ClementineInfos { + optional string version = 1; +} + +message SongMetadata { + optional int32 id = 1; + optional int32 index = 2; + optional string title = 3; + optional string album = 4; + optional string artist = 5; + optional string albumartist = 6; + optional int32 track = 7; + optional int32 disc = 8; + optional string pretty_year = 9; + optional string genre = 10; + optional int32 playcount = 11; + optional string pretty_length = 12; + optional string art = 13; +} + +message Playlist { + optional int32 id = 1; + optional string name = 2; + optional int32 item_count = 3; + optional bool active = 4; + + repeated SongMetadata songs = 10; +} + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4102d832e..8d35283b5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -62,6 +62,8 @@ endif(HAVE_BREAKPAD) include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-common) include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-tagreader) include_directories(${CMAKE_BINARY_DIR}/ext/libclementine-tagreader) +include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-remote) +include_directories(${CMAKE_BINARY_DIR}/ext/libclementine-remote) cmake_policy(SET CMP0011 NEW) include(../cmake/ParseArguments.cmake) @@ -214,9 +216,8 @@ set(SOURCES networkremote/networkremotehelper.cpp networkremote/networkremote.cpp - networkremote/incomingxmlparser.cpp - networkremote/outgoingxmlcreator.cpp - networkremote/remotexmltags.cpp + networkremote/incomingdataparser.cpp + networkremote/outgoingdatacreator.cpp playlist/dynamicplaylistcontrols.cpp playlist/playlist.cpp @@ -493,9 +494,8 @@ set(HEADERS networkremote/networkremotehelper.h networkremote/networkremote.h - networkremote/incomingxmlparser.h - networkremote/outgoingxmlcreator.h - networkremote/remotexmltags.h + networkremote/incomingdataparser.h + networkremote/outgoingdatacreator.h playlist/dynamicplaylistcontrols.h playlist/playlist.h @@ -1140,6 +1140,7 @@ add_dependencies(clementine_lib pot) target_link_libraries(clementine_lib libclementine-common libclementine-tagreader + libclementine-remote ${SHA2_LIBRARIES} ${TAGLIB_LIBRARIES} ${MYGPOQT_LIBRARIES} diff --git a/src/networkremote/incomingdataparser.cpp b/src/networkremote/incomingdataparser.cpp new file mode 100644 index 000000000..3bd41f121 --- /dev/null +++ b/src/networkremote/incomingdataparser.cpp @@ -0,0 +1,130 @@ +/* This file is part of Clementine. + Copyright 2012, Andreas Muttscheller + + Clementine 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. + + Clementine 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 Clementine. If not, see . +*/ + +#include "incomingdataparser.h" +#include "core/logging.h" +#include "engines/enginebase.h" +#include "playlist/playlistmanager.h" + +IncomingDataParser::IncomingDataParser(Application* app) + :app_(app) +{ + // Connect all the signals + // due the player is in a different thread, we cannot access these functions directly + connect(this, SIGNAL(Play()), + app_->player(), SLOT(Play())); + connect(this, SIGNAL(PlayPause()), + app_->player(), SLOT(PlayPause())); + connect(this, SIGNAL(Pause()), + app_->player(), SLOT(Pause())); + connect(this, SIGNAL(Stop()), + app_->player(), SLOT(Stop())); + connect(this, SIGNAL(Next()), + app_->player(), SLOT(Next())); + connect(this, SIGNAL(Previous()), + app_->player(), SLOT(Previous())); + connect(this, SIGNAL(SetVolume(int)), + app_->player(), SLOT(SetVolume(int))); + connect(this, SIGNAL(PlayAt(int,Engine::TrackChangeFlags,bool)), + app_->player(), SLOT(PlayAt(int,Engine::TrackChangeFlags,bool))); + connect(this, SIGNAL(SetActivePlaylist(int)), + app_->playlist_manager(), SLOT(SetActivePlaylist(int))); +} + +IncomingDataParser::~IncomingDataParser() { +} + +bool IncomingDataParser::close_connection() { + return close_connection_; +} + +void IncomingDataParser::Parse(const QByteArray& b64_data) { + close_connection_ = false; + QByteArray pb_data = QByteArray::fromBase64(b64_data); + + // Parse the incoming data + pb::remote::Message msg; + if (!msg.ParseFromArray(pb_data.constData(), pb_data.size())) { + qLog(Info) << "Couldn't parse data"; + return; + } + + // Now check what's to do + switch (msg.msgtype()) { + case pb::remote::CONNECT: emit SendClementineInfos(); + emit SendFirstData(); + break; + case pb::remote::DISCONNECT: close_connection_ = true; + break; + case pb::remote::REQUEST_PLAYLISTS: emit SendAllPlaylists(); + break; + case pb::remote::REQUEST_PLAYLIST_SONGS: GetPlaylistSongs(&msg); + break; + case pb::remote::SET_VOLUME: emit SetVolume(msg.volume()); + break; + case pb::remote::PLAY: emit Play(); + break; + case pb::remote::PLAYPAUSE: emit PlayPause(); + break; + case pb::remote::PAUSE: emit Pause(); + break; + case pb::remote::STOP: emit Stop(); + break; + case pb::remote::NEXT: emit Next(); + break; + case pb::remote::PREV: emit Previous(); + break; + case pb::remote::CHANGE_SONG: ChangeSong(&msg); + break; + default: break; + } +} + +void IncomingDataParser::GetPlaylistSongs(pb::remote::Message* msg) { + // Check if we got a playlist + if (msg->playlists_size() == 0) + { + return; + } + + // Get the first entry and send the songs + pb::remote::Playlist playlist = msg->playlists(0); + emit SendPlaylistSongs(playlist.id()); +} + +void IncomingDataParser::ChangeSong(pb::remote::Message* msg) { + // Check if we got a song + if (msg->playlists_size() == 0) { + return; + } + + // Get the first entry and check if there is a song + pb::remote::Playlist playlist = msg->playlists(0); + if (playlist.songs_size() == 0) { + return; + } + + pb::remote::SongMetadata song = playlist.songs(0); + + // Check if we need to change the playlist + if (playlist.id() != app_->playlist_manager()->active_id()) { + emit SetActivePlaylist(playlist.id()); + } + + // Play the selected song + emit PlayAt(song.index(), Engine::Manual, false); +} diff --git a/src/networkremote/incomingxmlparser.h b/src/networkremote/incomingdataparser.h similarity index 58% rename from src/networkremote/incomingxmlparser.h rename to src/networkremote/incomingdataparser.h index cc44b6330..b9c80571c 100644 --- a/src/networkremote/incomingxmlparser.h +++ b/src/networkremote/incomingdataparser.h @@ -1,18 +1,17 @@ -#ifndef INCOMINGXMLPARSER_H -#define PARSEINCOMINGXML_H - -#include +#ifndef INCOMINGDATAPARSER_H +#define INCOMINGDATAPARSER_H #include "core/player.h" #include "core/application.h" +#include "remotecontrolmessages.pb.h" -class IncomingXmlParser : public QObject { +class IncomingDataParser : public QObject { Q_OBJECT public: - IncomingXmlParser(Application* app); - ~IncomingXmlParser(); + IncomingDataParser(Application* app); + ~IncomingDataParser(); - void Parse(QString* xml_data); + void Parse(const QByteArray& pb_data); bool close_connection(); signals: @@ -35,9 +34,8 @@ private: Application* app_; bool close_connection_; - void ChangeVolume(QDomNode& child); - void GetPlaylistSongs(QDomNode& child); - void ChangeSong(QDomNode& child); + void GetPlaylistSongs(pb::remote::Message* msg); + void ChangeSong(pb::remote::Message* msg); }; -#endif // PARSEINCOMINGXML_H +#endif // INCOMINGDATAPARSER_H diff --git a/src/networkremote/incomingxmlparser.cpp b/src/networkremote/incomingxmlparser.cpp deleted file mode 100644 index be9b70bdb..000000000 --- a/src/networkremote/incomingxmlparser.cpp +++ /dev/null @@ -1,172 +0,0 @@ -/* This file is part of Clementine. - Copyright 2012, Andreas Muttscheller - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#include "incomingxmlparser.h" -#include "remotexmltags.h" -#include "core/logging.h" -#include "engines/enginebase.h" -#include "playlist/playlistmanager.h" - -IncomingXmlParser::IncomingXmlParser(Application* app) - :app_(app) -{ - // Connect all the signals - // due the player is in a different thread, we cannot access these functions directly - connect(this, SIGNAL(Play()), - app_->player(), SLOT(Play())); - connect(this, SIGNAL(PlayPause()), - app_->player(), SLOT(PlayPause())); - connect(this, SIGNAL(Pause()), - app_->player(), SLOT(Pause())); - connect(this, SIGNAL(Stop()), - app_->player(), SLOT(Stop())); - connect(this, SIGNAL(Next()), - app_->player(), SLOT(Next())); - connect(this, SIGNAL(Previous()), - app_->player(), SLOT(Previous())); - connect(this, SIGNAL(SetVolume(int)), - app_->player(), SLOT(SetVolume(int))); - connect(this, SIGNAL(PlayAt(int,Engine::TrackChangeFlags,bool)), - app_->player(), SLOT(PlayAt(int,Engine::TrackChangeFlags,bool))); - connect(this, SIGNAL(SetActivePlaylist(int)), - app_->playlist_manager(), SLOT(SetActivePlaylist(int))); -} - -IncomingXmlParser::~IncomingXmlParser() { -} - -bool IncomingXmlParser::close_connection() { - return close_connection_; -} - -void IncomingXmlParser::Parse(QString *xml_data) { - close_connection_ = false; - - // Load the xml data - QDomDocument doc; - doc.setContent(*xml_data); - - QDomElement root = doc.documentElement(); - if (root.tagName() != RemoteXmlTags::ROOT) { - qLog(Info) << "Received invalid XML data"; - qLog(Debug) << xml_data; - return; - } - - // The first child must be "action". It tells us what to do now - QDomNode child = root.firstChild(); - if (child.toElement().tagName() != RemoteXmlTags::ACTION) { - qLog(Info) << "First node is not action! (" << - child.toElement().tagName() << ")"; - return; - } - - // Now check what's to do - QString action = child.toElement().text(); - qLog(Debug) << "Action = " << action; - if (action == RemoteXmlTags::CLIENT_CONNTECTED) { - emit SendClementineInfos(); - emit SendFirstData()/* This file is part of Clementine. - Copyright 2012, David Sansome - - Clementine 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. - - Clementine 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 Clementine. If not, see . - */; - } else if (action == RemoteXmlTags::CLIENT_DISCONNECT) { - close_connection_ = true; - } else if (action == RemoteXmlTags::REQUEST_PLAYLISTS) { - emit SendAllPlaylists(); - } else if (action == RemoteXmlTags::REQUEST_PLAYLIST_SONGS) { - GetPlaylistSongs(child); - } else if (action == RemoteXmlTags::SET_VOLUME) { - ChangeVolume(child); - } else if (action == RemoteXmlTags::PLAY) { - emit Play(); - } else if (action == RemoteXmlTags::PLAYPAUSE) { - emit PlayPause(); - } else if (action == RemoteXmlTags::PAUSE) { - emit Pause(); - } else if (action == RemoteXmlTags::STOP) { - emit Stop(); - } else if (action == RemoteXmlTags::NEXT) { - emit Next(); - } else if (action == RemoteXmlTags::PREV) { - emit Previous(); - } else if (action == RemoteXmlTags::CHANGE_SONG) { - ChangeSong(child); - } -} - -void IncomingXmlParser::GetPlaylistSongs(QDomNode &child) { - QDomNode c = child; - // Get the Playlist Tag - while (!c.isNull() && c.toElement().tagName() != RemoteXmlTags::PLAYLIST) { - c = c.nextSibling(); - } - - // If the node was found, send a signal to the outgoingXmlCreator to create the songlist - if (!c.isNull()) { - QDomElement p = c.toElement(); - - qLog(Debug) << "Element c = " << p.tagName() << - " Attribute: " << c.toElement().attribute(RemoteXmlTags::ID); - int id = c.toElement().attribute(RemoteXmlTags::ID).toInt(); - emit SendPlaylistSongs(id); - } -} - -void IncomingXmlParser::ChangeVolume(QDomNode& child) { - QDomNode c = child; - // Get the Volume Tag - while (!c.isNull() && c.toElement().tagName() != RemoteXmlTags::VOLUME) { - c = c.nextSibling(); - } - - // If we found it, the change the volume - if (!c.isNull()) { - emit SetVolume(c.toElement().text().toInt()); - } -} - -void IncomingXmlParser::ChangeSong(QDomNode& child) { - QDomNode c = child; - // Get the Volume Tag - while (!c.isNull() && c.toElement().tagName() != RemoteXmlTags::SONG) { - c = c.nextSibling(); - } - - // If we found it, the change the volume - if (!c.isNull()) { - // first check if we need to change the active Playlist - int selectedPlaylist = c.toElement().attribute(RemoteXmlTags::PLAYLIST).toInt(); - int selectedSong = c.toElement().attribute(RemoteXmlTags::INDEX).toInt(); - if (selectedPlaylist != app_->playlist_manager()->active_id()) { - emit SetActivePlaylist(selectedPlaylist); - } - emit PlayAt(selectedSong, Engine::Manual, false); - } -} diff --git a/src/networkremote/networkremote.cpp b/src/networkremote/networkremote.cpp index ab29f0888..abb20938c 100644 --- a/src/networkremote/networkremote.cpp +++ b/src/networkremote/networkremote.cpp @@ -21,6 +21,7 @@ #include "networkremote.h" +#include #include const char* NetworkRemote::kSettingsGroup = "NetworkRemote"; @@ -34,8 +35,8 @@ NetworkRemote::NetworkRemote(Application* app) NetworkRemote::~NetworkRemote() { server_->close(); - delete incoming_xml_parser_; - delete outgoing_xml_creator_; + delete incoming_data_parser_; + delete outgoing_data_creator_; } void NetworkRemote::ReadSettings() { @@ -52,18 +53,18 @@ void NetworkRemote::ReadSettings() { void NetworkRemote::SetupServer() { server_ = new QTcpServer(); - incoming_xml_parser_ = new IncomingXmlParser(app_); - outgoing_xml_creator_ = new OutgoingXmlCreator(app_); + incoming_data_parser_ = new IncomingDataParser(app_); + outgoing_data_creator_ = new OutgoingDataCreator(app_); connect(app_->current_art_loader(), SIGNAL(ArtLoaded(const Song&, const QString&, const QImage&)), - outgoing_xml_creator_, + outgoing_data_creator_, SLOT(CurrentSongChanged(const Song&, const QString&, const QImage&))); } void NetworkRemote::StartServer() { if (!app_) { - qLog(Error) << "Start Server called before having an application!"; + qLog(Error) << "Start Server called without having an application!"; return; } // Check if user desires to start a network remote server @@ -91,9 +92,7 @@ void NetworkRemote::StopServer() { } void NetworkRemote::ReloadSettings() { - if (server_->isListening()) { - server_->close(); - } + StopServer(); StartServer(); } @@ -101,29 +100,27 @@ void NetworkRemote::AcceptConnection() { if (!clients_) { // Create a new QList with clients clients_ = new QList(); - outgoing_xml_creator_->SetClients(clients_); + outgoing_data_creator_->SetClients(clients_); // Setting up the signals, but only once - connect(incoming_xml_parser_, SIGNAL(SendClementineInfos()), - outgoing_xml_creator_, SLOT(SendClementineInfos())); - connect(incoming_xml_parser_, SIGNAL(SendFirstData()), - outgoing_xml_creator_, SLOT(SendFirstData())); - connect(incoming_xml_parser_, SIGNAL(SendAllPlaylists()), - outgoing_xml_creator_, SLOT(SendAllPlaylists())); - connect(incoming_xml_parser_, SIGNAL(SendPlaylistSongs(int)), - outgoing_xml_creator_, SLOT(SendPlaylistSongs(int))); + connect(incoming_data_parser_, SIGNAL(SendClementineInfos()), + outgoing_data_creator_, SLOT(SendClementineInfos())); + connect(incoming_data_parser_, SIGNAL(SendFirstData()), + outgoing_data_creator_, SLOT(SendFirstData())); + connect(incoming_data_parser_, SIGNAL(SendAllPlaylists()), + outgoing_data_creator_, SLOT(SendAllPlaylists())); + connect(incoming_data_parser_, SIGNAL(SendPlaylistSongs(int)), + outgoing_data_creator_, SLOT(SendPlaylistSongs(int))); connect(app_->playlist_manager(), SIGNAL(ActiveChanged(Playlist*)), - outgoing_xml_creator_, SLOT(ActiveChanged(Playlist*))); + outgoing_data_creator_, SLOT(ActiveChanged(Playlist*))); connect(app_->playlist_manager(), SIGNAL(PlaylistChanged(Playlist*)), - outgoing_xml_creator_, SLOT(ActiveChanged(Playlist*))); + outgoing_data_creator_, SLOT(PlaylistChanged(Playlist*))); - connect(app_->player(), SIGNAL(VolumeChanged(int)), outgoing_xml_creator_, + connect(app_->player(), SIGNAL(VolumeChanged(int)), outgoing_data_creator_, SLOT(VolumeChanged(int))); connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)), - outgoing_xml_creator_, SLOT(StateChanged(Engine::State))); - - qLog(Info) << "Signals connected!"; + outgoing_data_creator_, SLOT(StateChanged(Engine::State))); } QTcpSocket* client = server_->nextPendingConnection(); @@ -134,16 +131,14 @@ void NetworkRemote::AcceptConnection() { } void NetworkRemote::IncomingData() { - QByteArray buf; QTcpSocket* client = static_cast(QObject::sender()); - buf = client->read(client->bytesAvailable()); + // Now read all the data from the socket + QByteArray data; + data = client->readAll(); + incoming_data_parser_->Parse(data); - QString strbuf(buf); - incoming_xml_parser_->Parse(&strbuf); - - qLog(Debug) << "Data = " << buf << "Size = " << buf.size(); - if (incoming_xml_parser_->close_connection()) { + if (incoming_data_parser_->close_connection()) { client->close(); } } diff --git a/src/networkremote/networkremote.h b/src/networkremote/networkremote.h index a763e0902..381e2a1ad 100644 --- a/src/networkremote/networkremote.h +++ b/src/networkremote/networkremote.h @@ -7,8 +7,8 @@ #include "core/player.h" #include "core/application.h" -#include "incomingxmlparser.h" -#include "outgoingxmlcreator.h" +#include "incomingdataparser.h" +#include "outgoingdatacreator.h" class NetworkRemote : public QThread { Q_OBJECT @@ -29,8 +29,8 @@ public slots: private: QTcpServer* server_; QList* clients_; - IncomingXmlParser* incoming_xml_parser_; - OutgoingXmlCreator* outgoing_xml_creator_; + IncomingDataParser* incoming_data_parser_; + OutgoingDataCreator* outgoing_data_creator_; int port_; bool use_remote_; Application* app_; diff --git a/src/networkremote/outgoingdatacreator.cpp b/src/networkremote/outgoingdatacreator.cpp new file mode 100644 index 000000000..fa5ac4599 --- /dev/null +++ b/src/networkremote/outgoingdatacreator.cpp @@ -0,0 +1,268 @@ +/* This file is part of Clementine. + Copyright 2012, Andreas Muttscheller + + Clementine 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. + + Clementine 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 Clementine. If not, see . +*/ + +#include "outgoingdatacreator.h" +#include "core/logging.h" + +OutgoingDataCreator::OutgoingDataCreator(Application* app) + : app_(app), + clients_(NULL) +{ + // Create Keep Alive Timer + keep_alive_timer_ = new QTimer(this); + connect(keep_alive_timer_, SIGNAL(timeout()), this, SLOT(SendKeepAlive())); + keep_alive_timeout_ = 10000; +} + +OutgoingDataCreator::~OutgoingDataCreator() { +} + +void OutgoingDataCreator::SetClients(QList* clients) { + clients_ = clients; + // After we got some clients, start the keep alive timer + // Default: every 10 seconds + keep_alive_timer_->start(keep_alive_timeout_); +} + +void OutgoingDataCreator::SendDataToClients(pb::remote::Message* msg) { + // Check if we have clients to send data to + if (!clients_ || clients_->size() == 0) { + return; + } + + QTcpSocket* sock; + foreach(sock, *clients_) { + // Check if the client is still active + if (sock->state() == QTcpSocket::ConnectedState) { + std::string data = msg->SerializeAsString(); + QByteArray b64_data = QByteArray::fromRawData(data.data(), data.length()); + sock->write(b64_data.toBase64()); + sock->write("\n"); + sock->flush(); + } else { + clients_->removeAt(clients_->indexOf(sock)); + } + } +} + +void OutgoingDataCreator::SendClementineInfos() { + // Create the general message and set the message type + pb::remote::Message msg; + msg.set_msgtype(pb::remote::INFOS); + + // Now add the message specific data + SetEngineState(&msg); + + QString version = QString("%1 %2").arg(QCoreApplication::applicationName(), + QCoreApplication::applicationVersion()); + pb::remote::ClementineInfos *infos = msg.mutable_infos(); + infos->set_version(version.toAscii()); + + SendDataToClients(&msg); +} + +void OutgoingDataCreator::SetEngineState(pb::remote::Message *msg) { + switch(app_->player()->GetState()) { + case Engine::Idle: msg->set_state(pb::remote::Idle); + break; + case Engine::Empty: msg->set_state(pb::remote::Empty); + break; + case Engine::Playing: msg->set_state(pb::remote::Playing); + break; + case Engine::Paused: msg->set_state(pb::remote::Paused); + break; + } +} + +void OutgoingDataCreator::SendAllPlaylists() { + // Get all Playlists + QList playlists = app_->playlist_manager()->GetAllPlaylists(); + QListIterator i(playlists); + int active_playlist = app_->playlist_manager()->active_id(); + + // Create message + pb::remote::Message msg; + msg.set_msgtype(pb::remote::PLAYLISTS); + + while(i.hasNext()) { + // Get the next Playlist + Playlist* p = i.next(); + QString playlist_name = app_->playlist_manager()->GetPlaylistName(p->id()); + + // Create a new playlist + pb::remote::Playlist* playlist = msg.add_playlists(); + playlist->set_name(playlist_name.toStdString()); + playlist->set_id(p->id()); + playlist->set_item_count(p->GetAllSongs().size()); + playlist->set_active((p->id() == active_playlist)); + } + + SendDataToClients(&msg); +} + +void OutgoingDataCreator::ActiveChanged(Playlist *) { + // When a playlist was changed, send the new list + SendAllPlaylists(); +} + +void OutgoingDataCreator::SendFirstData() { + // First Send the current song + PlaylistItemPtr item = app_->player()->GetCurrentItem(); + if (!item) { + qLog(Info) << "No current item found!"; + } + + CurrentSongChanged(current_song_, current_uri_, current_image_); + + // then the current volume + VolumeChanged(app_->player()->GetVolume()); +} + +void OutgoingDataCreator::CurrentSongChanged(const Song& song, const QString& uri, const QImage& img) { + current_song_ = song; + current_uri_ = uri; + current_image_ = img; + + if (clients_) { + // Create the message + pb::remote::Message msg; + msg.set_msgtype(pb::remote::CURRENT_METAINFOS); + + // If there is no song, create an empty node, otherwise fill it with data + int i = app_->playlist_manager()->active()->current_row(); + CreateSong(msg.mutable_currentsong(), ¤t_song_, &uri, i); + + SendDataToClients(&msg); + } +} + +void OutgoingDataCreator::CreateSong(pb::remote::SongMetadata* song_metadata, + Song* song, const QString* artUri, int index) { + if (song->is_valid()) { + song_metadata->set_id(song->id()); + song_metadata->set_index(index); + song_metadata->set_title( DataCommaSizeFromQString(song->PrettyTitle())); + song_metadata->set_artist(DataCommaSizeFromQString(song->artist())); + song_metadata->set_album( DataCommaSizeFromQString(song->album())); + song_metadata->set_albumartist(DataCommaSizeFromQString(song->albumartist())); + song_metadata->set_pretty_length(DataCommaSizeFromQString(song->PrettyLength())); + song_metadata->set_genre(DataCommaSizeFromQString(song->genre())); + song_metadata->set_pretty_year(DataCommaSizeFromQString(song->PrettyYear())); + song_metadata->set_track(song->track()); + song_metadata->set_disc(song->disc()); + song_metadata->set_playcount(song->playcount()); + + // Append coverart + if (!artUri->isEmpty()) { + QImage orig(QUrl(*artUri).toLocalFile()); + QImage small; + // Check if we resize the image + if (orig.width() > 1000) { + small = orig.scaled(1000, 1000, Qt::KeepAspectRatio); + } else { + small = orig; + } + + // Read the image in a buffer and compress it + QByteArray data; + QBuffer buf(&data); + buf.open(QIODevice::WriteOnly); + small.save(&buf, "JPG"); + + // Append the Data in the protocol buffer + song_metadata->set_art(data.toBase64()); + + buf.close(); + } + } +} + + +void OutgoingDataCreator::VolumeChanged(int volume) { + // Create the message + pb::remote::Message msg; + msg.set_msgtype(pb::remote::SET_VOLUME); + msg.set_volume(volume); + SendDataToClients(&msg); +} + +void OutgoingDataCreator::SendPlaylistSongs(int id) { + // Get the PlaylistQByteArray(data.data(), data.size() + Playlist* playlist = app_->playlist_manager()->playlist(id); + if(!playlist) { + qLog(Info) << "Could not find playlist with id = " << id; + return; + } + + SongList song_list = playlist->GetAllSongs(); + QListIterator i(song_list); + + // Create the message and the playlist + pb::remote::Message msg; + msg.set_msgtype(pb::remote::PLAYLIST_SONGS); + // Create a new playlist + pb::remote::Playlist* pb_playlist = msg.add_playlists(); + pb_playlist->set_id(id); + pb_playlist->set_item_count(playlist->GetAllSongs().size()); + + // Send all songs + int index = 0; + while(i.hasNext()) { + Song song = i.next(); + QString art = song.art_automatic(); + pb::remote::SongMetadata* pb_song = pb_playlist->add_songs(); + CreateSong(pb_song, &song, &art, index); + ++index; + } + SendDataToClients(&msg); +} + +void OutgoingDataCreator::PlaylistChanged(Playlist* playlist) { + // If a playlist changed, then send the new songs to the client + SendPlaylistSongs(playlist->id()); +} + +void OutgoingDataCreator::StateChanged(Engine::State state) { + // Send state only if it changed + // When selecting next song, StateChanged is emitted, but we already know + // that we are playing + if (state == last_state_) { + return; + } + last_state_ = state; + + pb::remote::Message msg; + + switch (state) { + case Engine::Playing: msg.set_msgtype(pb::remote::PLAY); + break; + case Engine::Paused: msg.set_msgtype(pb::remote::PAUSE); + break; + case Engine::Empty: msg.set_msgtype(pb::remote::STOP); // Empty is called when player stopped + break; + default: msg.set_msgtype(pb::remote::STOP); + break; + }; + + SendDataToClients(&msg); +} + +void OutgoingDataCreator::SendKeepAlive() { + pb::remote::Message msg; + msg.set_msgtype(pb::remote::KEEP_ALIVE); + SendDataToClients(&msg); +} diff --git a/src/networkremote/outgoingxmlcreator.h b/src/networkremote/outgoingdatacreator.h similarity index 64% rename from src/networkremote/outgoingxmlcreator.h rename to src/networkremote/outgoingdatacreator.h index 36a5ae7c9..7a3a8277d 100644 --- a/src/networkremote/outgoingxmlcreator.h +++ b/src/networkremote/outgoingdatacreator.h @@ -1,7 +1,6 @@ -#ifndef OUTGOINGXMLCREATOR_H -#define OUTGOINGXMLCREATOR_H +#ifndef OUTGOINGDATACREATOR_H +#define OUTGOINGDATACREATOR_H -#include #include #include #include @@ -13,12 +12,13 @@ #include "engines/engine_fwd.h" #include "playlist/playlist.h" #include "playlist/playlistmanager.h" +#include "remotecontrolmessages.pb.h" -class OutgoingXmlCreator : public QObject { +class OutgoingDataCreator : public QObject { Q_OBJECT public: - OutgoingXmlCreator(Application* app); - ~OutgoingXmlCreator(); + OutgoingDataCreator(Application* app); + ~OutgoingDataCreator(); void SetClients(QList* clients); @@ -27,6 +27,7 @@ public slots: void SendAllPlaylists(); void SendFirstData(); void SendPlaylistSongs(int id); + void PlaylistChanged(Playlist*); void VolumeChanged(int volume); void ActiveChanged(Playlist*); void CurrentSongChanged(const Song& song, const QString& uri, const QImage& img); @@ -43,10 +44,9 @@ private: QTimer* keep_alive_timer_; int keep_alive_timeout_; - void SendDataToClients(QByteArray data); - void CreateXmlHeader(QDomDocument* doc, QString action); - QDomElement CreateSong(QDomDocument* doc, Song* song, const QString* art_uri, int index); - QDomElement CreateSongTag(QDomDocument* doc, QString tag, QString text); + void SendDataToClients(pb::remote::Message* msg); + void SetEngineState(pb::remote::Message* msg); + void CreateSong(pb::remote::SongMetadata* song_metadata, Song* song, const QString* art_uri, int index); }; -#endif // OUTGOINGXMLCREATOR_H +#endif // OUTGOINGDATACREATOR_H diff --git a/src/networkremote/outgoingxmlcreator.cpp b/src/networkremote/outgoingxmlcreator.cpp deleted file mode 100644 index 69639a487..000000000 --- a/src/networkremote/outgoingxmlcreator.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/* This file is part of Clementine. - Copyright 2012, Andreas Muttscheller - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#include "outgoingxmlcreator.h" -#include "remotexmltags.h" -#include "core/logging.h" - -OutgoingXmlCreator::OutgoingXmlCreator(Application* app) - : app_(app), - clients_(NULL) -{ - // Create Keep Alive Timer - keep_alive_timer_ = new QTimer(this); - connect(keep_alive_timer_, SIGNAL(timeout()), this, SLOT(SendKeepAlive())); - keep_alive_timeout_ = 10000; -} - -OutgoingXmlCreator::~OutgoingXmlCreator() { -} - -void OutgoingXmlCreator::SetClients(QList* clients) { - clients_ = clients; - // After we got some clients, start the keep alive timer - // Default: every 10 seconds - keep_alive_timer_->start(keep_alive_timeout_); -} - -void OutgoingXmlCreator::SendDataToClients(QByteArray data) { - // Check if we have clients to send data to - if (!clients_) { - return; - } - - QTcpSocket* sock; - foreach(sock, *clients_) { - // Check if the client is still active - if (sock->state() == QTcpSocket::ConnectedState) { - sock->write(data); - } else { - clients_->removeAt(clients_->indexOf(sock)); - } - } -} - -void OutgoingXmlCreator::SendClementineInfos() { - // Create the xml and header - QDomDocument doc; - CreateXmlHeader(&doc, RemoteXmlTags::SEND_INFOS); - QDomElement root = doc.documentElement(); - QDomElement info = doc.createElement(RemoteXmlTags::INFOS); - QDomElement tag_version = doc.createElement(RemoteXmlTags::VERSION); - QDomText version_text = doc.createTextNode(QString("%1 %2").arg( - QCoreApplication::applicationName(), - QCoreApplication::applicationVersion())); - - tag_version.appendChild(version_text); - info.appendChild(tag_version); - root.appendChild(info); - - SendDataToClients(doc.toByteArray()); -} - -void OutgoingXmlCreator::SendAllPlaylists() { - // Get all Playlists - QList playlists = app_->playlist_manager()->GetAllPlaylists(); - QListIterator i(playlists); - int active_playlist = app_->playlist_manager()->active_id(); - - // Create the xml and header - QDomDocument doc; - CreateXmlHeader(&doc, RemoteXmlTags::SEND_PLAYLISTS); - QDomElement root = doc.documentElement(); - - while(i.hasNext()) { - Playlist* p = i.next(); - - // Append the id - QDomElement node_playlist = doc.createElement(RemoteXmlTags::PLAYLIST); - node_playlist.setAttribute(RemoteXmlTags::ID, p->id()); - node_playlist.setAttribute(RemoteXmlTags::CURRENT_ROW, p->current_row()); - - // get the name of the playlist - QDomElement playlist_elem = doc.createElement(RemoteXmlTags::PLAYLIST_NAME); - QString playlist_name = app_->playlist_manager()->GetPlaylistName(p->id()); - QDomText playlist_text = doc.createTextNode(playlist_name); - - // Add it to the playlist node - playlist_elem.appendChild(playlist_text); - node_playlist.appendChild(playlist_elem); - - // get the item count - QDomElement playlist_count = doc.createElement(RemoteXmlTags::PLAYLIST_ITEMS); - QDomText item_count = doc.createTextNode(QString::number(p->GetAllSongs().size())); - playlist_count.appendChild(item_count); - node_playlist.appendChild(playlist_count); - - // Check if the Playlist is active - QDomElement playlist_active_elem = doc.createElement(RemoteXmlTags::PLAYLIST_ACTIVE); - QDomText text_active = doc.createTextNode( QString::number( (p->id() == active_playlist) ) ); - playlist_active_elem.appendChild(text_active); - node_playlist.appendChild(playlist_active_elem); - - // Append it to the root node - root.appendChild(node_playlist); - } - - SendDataToClients(doc.toByteArray()); -} - -void OutgoingXmlCreator::ActiveChanged(Playlist *) { - // When a playlist was changed, send the new list - SendAllPlaylists(); -} - -void OutgoingXmlCreator::SendFirstData() { - // First Send the current song - PlaylistItemPtr item = app_->player()->GetCurrentItem(); - if (!item) { - qLog(Info) << "No current item found!"; - } - - CurrentSongChanged(current_song_, current_uri_, current_image_); - - // then the current volume - VolumeChanged(app_->player()->GetVolume()); -} - -void OutgoingXmlCreator::CurrentSongChanged(const Song& song, const QString& uri, const QImage& img) { - current_song_ = song; - current_uri_ = uri; - current_image_ = img; - - if (clients_) { - // Create the xml and header - QDomDocument doc; - CreateXmlHeader(&doc, RemoteXmlTags::SEND_METAINFOS); - QDomElement root = doc.documentElement(); - - // If there is no song, create an empty node, otherwise fill it with data - int i = app_->playlist_manager()->active()->current_row(); - root.appendChild(CreateSong(&doc, ¤t_song_, &uri, i)); - - SendDataToClients(doc.toByteArray()); - } -} - -QDomElement OutgoingXmlCreator::CreateSong(QDomDocument* doc, Song* song, const QString* artUri, int index) { - QDomElement nodeSong = doc->createElement(RemoteXmlTags::SONG); - if (song->is_valid()) { - QString pretty_length = song->PrettyLength(); - QString pretty_year = song->PrettyYear(); - nodeSong.setAttribute(RemoteXmlTags::ID, song->id()); - nodeSong.setAttribute(RemoteXmlTags::INDEX, index); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_TITLE, song->PrettyTitle() )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_ARTIST, song->artist() )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_ALBUM, song->album() )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_ALBUMARTIST, song->albumartist() )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_LENGTH, pretty_length )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_GENRE, song->genre() )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_YEAR, pretty_year )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_TRACK, QString::number(song->track()) )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_DISC, QString::number(song->disc()) )); - nodeSong.appendChild(CreateSongTag(doc, RemoteXmlTags::SONG_PLAYCOUNT, QString::number(song->playcount()) )); - // Append coverart - if (!artUri->isEmpty()) { - QImage orig(QUrl(*artUri).toLocalFile()); - QImage small; - // Check if we resize the image - if (orig.width() > 1000) { - small = orig.scaled(1000, 1000, Qt::KeepAspectRatio); - } else { - small = orig; - } - - // Read the image in a buffer and compress it - QByteArray data; - QBuffer buf(&data); - buf.open(QIODevice::WriteOnly); - small.save(&buf, "JPG"); - - // Append the Data in the xml file - QDomElement art = doc->createElement(RemoteXmlTags::SONG_ART); - // Art must be sent in Base64 encoding, because the raw data escapes QString and - // not all data is transfered - QDomText art_content = doc->createTextNode(data.toBase64()); - art.appendChild(art_content); - nodeSong.appendChild(art); - buf.close(); - } - } - - return nodeSong; -} - -QDomElement OutgoingXmlCreator::CreateSongTag(QDomDocument* doc, QString tag, QString text) { - QDomElement elem = doc->createElement(tag); - QDomText elem_text = doc->createTextNode(text); - elem.appendChild(elem_text); - return elem; -} - -void OutgoingXmlCreator::VolumeChanged(int volume) { - // Create the xml and header - QDomDocument doc; - CreateXmlHeader(&doc, RemoteXmlTags::VOLUME); - QDomElement root = doc.documentElement(); - - QDomElement volume_elem = doc.createElement(RemoteXmlTags::VOLUME); - QDomText volume_text = doc.createTextNode(QString::number(volume)); - volume_elem.appendChild(volume_text); - root.appendChild(volume_elem); - - SendDataToClients(doc.toByteArray()); -} - -void OutgoingXmlCreator::SendPlaylistSongs(int id) { - // Get the Playlist - Playlist* playlist = app_->playlist_manager()->playlist(id); - if(!playlist) { - qLog(Info) << "Could not find playlist with id = " << id; - return; - } - - SongList song_list = playlist->GetAllSongs(); - QListIterator i(song_list); - - // Create the xml and header - QDomDocument doc; - CreateXmlHeader(&doc, RemoteXmlTags::SEND_PLAYLIST_SONGS); - QDomElement root = doc.documentElement(); - - QDomElement playlist_elem = doc.createElement(RemoteXmlTags::PLAYLIST); - playlist_elem.setAttribute(RemoteXmlTags::ID, id); - - // Send all songs - int index = 0; - while(i.hasNext()) { - Song song = i.next(); - QString art = song.art_automatic(); - playlist_elem.appendChild(CreateSong(&doc, &song, &art, index)); - ++index; - } - - root.appendChild(playlist_elem); - - SendDataToClients(doc.toByteArray()); -} - -void OutgoingXmlCreator::StateChanged(Engine::State state) { - // Send state only if it changed - // When selecting next song, StateChanged is emitted, but we already know - // that we are playing - if (state == last_state_) { - return; - } - last_state_ = state; - - QDomDocument doc; - QString action; - - switch (state) { - case Engine::Playing: action = RemoteXmlTags::PLAY; - break; - case Engine::Paused: action = RemoteXmlTags::PAUSE; - break; - case Engine::Empty: action = RemoteXmlTags::STOP; // Empty is called when player stopped - break; - default: break; - }; - - CreateXmlHeader(&doc, action); - SendDataToClients(doc.toByteArray()); -} - -void OutgoingXmlCreator::CreateXmlHeader(QDomDocument *doc, QString action) -{ - // Create the header - QDomProcessingInstruction xml_header = doc->createProcessingInstruction("xml", "version=\"1.0\""); - doc->appendChild(xml_header); - // Create the root - QDomElement root = doc->createElement(RemoteXmlTags::ROOT); - doc->appendChild(root); - - // Append the action - QDomElement xml_action = doc->createElement(RemoteXmlTags::ACTION); - QDomText text_action = doc->createTextNode(action); - xml_action.appendChild(text_action); - root.appendChild(xml_action); -} - -void OutgoingXmlCreator::SendKeepAlive() { - QDomDocument doc; - CreateXmlHeader(&doc, RemoteXmlTags::KEEP_ALIVE); - SendDataToClients(doc.toByteArray()); -} diff --git a/src/networkremote/remotexmltags.cpp b/src/networkremote/remotexmltags.cpp deleted file mode 100644 index 0231b9d1e..000000000 --- a/src/networkremote/remotexmltags.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* This file is part of Clementine. - Copyright 2012, Andreas Muttscheller - - Clementine 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. - - Clementine 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 Clementine. If not, see . -*/ - -#include "remotexmltags.h" - -// Nodes -const QString RemoteXmlTags::ROOT = "ClementineRemote"; // The root node of every xml -const QString RemoteXmlTags::ACTION = "Action"; // The Node where the action is specified -const QString RemoteXmlTags::SONG = "Song"; // The Node for song metadata -const QString RemoteXmlTags::INFOS = "Infos"; -const QString RemoteXmlTags::VERSION = "Version"; - -// Playlist -const QString RemoteXmlTags::PLAYLIST = "Playlist"; -const QString RemoteXmlTags::PLAYLIST_NAME = "name"; -const QString RemoteXmlTags::PLAYLIST_ITEMS = "items"; -const QString RemoteXmlTags::PLAYLIST_ACTIVE = "active"; - -// Attributes -const QString RemoteXmlTags::ID = "id"; -const QString RemoteXmlTags::INDEX = "index"; -const QString RemoteXmlTags::CURRENT_ROW = "currentRow"; - -// Actions -const QString RemoteXmlTags::CLIENT_CONNTECTED = "Connect"; // A client wants to connect -const QString RemoteXmlTags::CLIENT_DISCONNECT = "Disconnect"; // A Client wants to disconnect -const QString RemoteXmlTags::SEND_INFOS = "Info"; -const QString RemoteXmlTags::SEND_METAINFOS = "CurrentMetainfos"; // Sends the metainfos of the current song -const QString RemoteXmlTags::SEND_PLAYLISTS = "Playlists"; -const QString RemoteXmlTags::SEND_PLAYLIST_SONGS = "PlaylistSongs"; -const QString RemoteXmlTags::REQUEST_PLAYLISTS = "GetPlaylists"; -const QString RemoteXmlTags::REQUEST_PLAYLIST_SONGS = "GetPlaylistSongs"; -const QString RemoteXmlTags::PLAY = "Play"; -const QString RemoteXmlTags::PLAYPAUSE = "PlayPause"; -const QString RemoteXmlTags::PAUSE = "Pause"; -const QString RemoteXmlTags::STOP = "Stop"; -const QString RemoteXmlTags::NEXT = "Next"; -const QString RemoteXmlTags::PREV = "Prev"; -const QString RemoteXmlTags::CHANGE_SONG = "ChangeSong"; -const QString RemoteXmlTags::SET_VOLUME = "SetVolume"; -const QString RemoteXmlTags::KEEP_ALIVE = "KeepAlive"; - -// Tags in Song -const QString RemoteXmlTags::SONG_TITLE = "Title"; -const QString RemoteXmlTags::SONG_ARTIST = "Artist"; -const QString RemoteXmlTags::SONG_ALBUM = "Album"; -const QString RemoteXmlTags::SONG_ALBUMARTIST = "AlbumArtist"; -const QString RemoteXmlTags::SONG_LENGTH = "Length"; -const QString RemoteXmlTags::SONG_GENRE = "Genre"; -const QString RemoteXmlTags::SONG_YEAR = "Year"; -const QString RemoteXmlTags::SONG_TRACK = "Track"; -const QString RemoteXmlTags::SONG_DISC = "Disc"; -const QString RemoteXmlTags::SONG_PLAYCOUNT = "Playcount"; -const QString RemoteXmlTags::SONG_ART = "Art"; -const QString RemoteXmlTags::VOLUME = "Volume"; - -RemoteXmlTags::RemoteXmlTags() { -} - -RemoteXmlTags::~RemoteXmlTags() { - -} - diff --git a/src/networkremote/remotexmltags.h b/src/networkremote/remotexmltags.h deleted file mode 100644 index f0128b774..000000000 --- a/src/networkremote/remotexmltags.h +++ /dev/null @@ -1,65 +0,0 @@ -#ifndef REMOTEXMLTAGS_H -#define REMOTEXMLTAGS_H - -#include - -class RemoteXmlTags { -public: - RemoteXmlTags(); - ~RemoteXmlTags(); - - // Nodes - const static QString ROOT; // The root node of every xml - const static QString ACTION; // The Node where the action is specified - const static QString SONG; // The Node for song metadata - const static QString INFOS; // Info Node - const static QString VERSION; // Holds the Version of Clementine - - // Playlist - const static QString PLAYLIST; // Node for Playlist - const static QString PLAYLIST_NAME; - const static QString PLAYLIST_ITEMS; // How may items are in the playlist? - const static QString PLAYLIST_ACTIVE; // Is the playlist active? - - // Attributes - const static QString ID; - const static QString INDEX; // Index on the Playlist - const static QString CURRENT_ROW; - - // Actions - const static QString CLIENT_CONNTECTED; // A client wants to connect - const static QString CLIENT_DISCONNECT; // A Client wants to disconnect - const static QString SEND_INFOS; // Sending general Infos to client (e.g. Version) - const static QString SEND_METAINFOS; // Sends the metainfos of the current song - const static QString SEND_PLAYLISTS; // Send the List of Playlists to client - const static QString SEND_PLAYLIST_SONGS; // Send the list of Songs to client - const static QString REQUEST_PLAYLISTS; // A client request for playlists - const static QString REQUEST_PLAYLIST_SONGS; // A clients wants to get all the songs in a playlist - const static QString SET_VOLUME; - const static QString PLAY; - const static QString PLAYPAUSE; - const static QString PAUSE; - const static QString STOP; - const static QString NEXT; - const static QString PREV; - const static QString CHANGE_SONG; - const static QString KEEP_ALIVE; - - - // Tags in Song - const static QString SONG_TITLE; - const static QString SONG_ARTIST; - const static QString SONG_ALBUM; - const static QString SONG_ALBUMARTIST; - const static QString SONG_LENGTH; - const static QString SONG_GENRE; - const static QString SONG_YEAR; - const static QString SONG_TRACK; - const static QString SONG_DISC; - const static QString SONG_PLAYCOUNT; - const static QString SONG_ART; - const static QString VOLUME; - -}; - -#endif // REMOTEXMLTAGS_H