Added remote control for clementine
This commit is contained in:
parent
4fff9c3ca5
commit
f10292eb95
|
@ -212,6 +212,12 @@ set(SOURCES
|
|||
musicbrainz/musicbrainzclient.cpp
|
||||
musicbrainz/tagfetcher.cpp
|
||||
|
||||
networkremote/networkremotehelper.cpp
|
||||
networkremote/networkremote.cpp
|
||||
networkremote/incomingxmlparser.cpp
|
||||
networkremote/outgoingxmlcreator.cpp
|
||||
networkremote/remotexmltags.cpp
|
||||
|
||||
playlist/dynamicplaylistcontrols.cpp
|
||||
playlist/playlist.cpp
|
||||
playlist/playlistbackend.cpp
|
||||
|
@ -323,6 +329,7 @@ set(SOURCES
|
|||
ui/iconloader.cpp
|
||||
ui/mainwindow.cpp
|
||||
ui/networkproxysettingspage.cpp
|
||||
ui/networkremotesettingspage.cpp
|
||||
ui/notificationssettingspage.cpp
|
||||
ui/organisedialog.cpp
|
||||
ui/organiseerrordialog.cpp
|
||||
|
@ -484,6 +491,12 @@ set(HEADERS
|
|||
musicbrainz/musicbrainzclient.h
|
||||
musicbrainz/tagfetcher.h
|
||||
|
||||
networkremote/networkremotehelper.h
|
||||
networkremote/networkremote.h
|
||||
networkremote/incomingxmlparser.h
|
||||
networkremote/outgoingxmlcreator.h
|
||||
networkremote/remotexmltags.h
|
||||
|
||||
playlist/dynamicplaylistcontrols.h
|
||||
playlist/playlist.h
|
||||
playlist/playlistbackend.h
|
||||
|
@ -580,6 +593,7 @@ set(HEADERS
|
|||
ui/globalshortcutssettingspage.h
|
||||
ui/mainwindow.h
|
||||
ui/networkproxysettingspage.h
|
||||
ui/networkremotesettingspage.h
|
||||
ui/notificationssettingspage.h
|
||||
ui/organisedialog.h
|
||||
ui/organiseerrordialog.h
|
||||
|
@ -697,6 +711,7 @@ set(UI
|
|||
ui/globalshortcutssettingspage.ui
|
||||
ui/mainwindow.ui
|
||||
ui/networkproxysettingspage.ui
|
||||
ui/networkremotesettingspage.ui
|
||||
ui/notificationssettingspage.ui
|
||||
ui/organisedialog.ui
|
||||
ui/organiseerrordialog.ui
|
||||
|
|
|
@ -30,6 +30,8 @@
|
|||
#include "globalsearch/globalsearch.h"
|
||||
#include "library/library.h"
|
||||
#include "library/librarybackend.h"
|
||||
#include "networkremote/networkremote.h"
|
||||
#include "networkremote/networkremotehelper.h"
|
||||
#include "playlist/playlistbackend.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "podcasts/gpoddersync.h"
|
||||
|
@ -63,7 +65,9 @@ Application::Application(QObject* parent)
|
|||
podcast_downloader_(NULL),
|
||||
gpodder_sync_(NULL),
|
||||
moodbar_loader_(NULL),
|
||||
moodbar_controller_(NULL)
|
||||
moodbar_controller_(NULL),
|
||||
network_remote_(NULL),
|
||||
network_remote_helper_(NULL)
|
||||
{
|
||||
tag_reader_client_ = new TagReaderClient(this);
|
||||
MoveToNewThread(tag_reader_client_);
|
||||
|
@ -100,6 +104,13 @@ Application::Application(QObject* parent)
|
|||
moodbar_controller_ = new MoodbarController(this, this);
|
||||
#endif
|
||||
|
||||
// Network Remote
|
||||
network_remote_ = new NetworkRemote(this);
|
||||
MoveToNewThread(network_remote_);
|
||||
|
||||
network_remote_helper_ = new NetworkRemoteHelper(this);
|
||||
network_remote_helper_->StartServer();
|
||||
|
||||
library_->Init();
|
||||
|
||||
DoInAMinuteOrSo(database_, SLOT(DoBackup()));
|
||||
|
|
|
@ -36,6 +36,8 @@ class LibraryBackend;
|
|||
class LibraryModel;
|
||||
class MoodbarController;
|
||||
class MoodbarLoader;
|
||||
class NetworkRemote;
|
||||
class NetworkRemoteHelper;
|
||||
class Player;
|
||||
class PlaylistBackend;
|
||||
class PodcastDownloader;
|
||||
|
@ -73,6 +75,8 @@ public:
|
|||
GPodderSync* gpodder_sync() const { return gpodder_sync_; }
|
||||
MoodbarLoader* moodbar_loader() const { return moodbar_loader_; }
|
||||
MoodbarController* moodbar_controller() const { return moodbar_controller_; }
|
||||
NetworkRemote* network_remote() const { return network_remote_; }
|
||||
NetworkRemoteHelper* network_remote_helper() const { return network_remote_helper_; }
|
||||
|
||||
LibraryBackend* library_backend() const;
|
||||
LibraryModel* library_model() const;
|
||||
|
@ -111,6 +115,8 @@ private:
|
|||
GPodderSync* gpodder_sync_;
|
||||
MoodbarLoader* moodbar_loader_;
|
||||
MoodbarController* moodbar_controller_;
|
||||
NetworkRemote* network_remote_;
|
||||
NetworkRemoteHelper* network_remote_helper_;
|
||||
|
||||
QList<QObject*> objects_in_threads_;
|
||||
QList<QThread*> threads_;
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, Andreas Muttscheller <asfa194@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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::CloseConnection() {
|
||||
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 <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/;
|
||||
} 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);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef INCOMINGXMLPARSER_H
|
||||
#define PARSEINCOMINGXML_H
|
||||
|
||||
#include <QDomDocument>
|
||||
|
||||
#include "core/player.h"
|
||||
#include "core/application.h"
|
||||
|
||||
class IncomingXmlParser : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
IncomingXmlParser(Application* app);
|
||||
~IncomingXmlParser();
|
||||
|
||||
void Parse(QString* xml_data);
|
||||
bool close_connection();
|
||||
|
||||
signals:
|
||||
void SendClementineInfos();
|
||||
void SendFirstData();
|
||||
void SendAllPlaylists();
|
||||
void SendPlaylistSongs(int id);
|
||||
|
||||
void Play();
|
||||
void PlayPause();
|
||||
void Pause();
|
||||
void Stop();
|
||||
void Next();
|
||||
void Previous();
|
||||
void SetVolume(int volume);
|
||||
void PlayAt(int i, Engine::TrackChangeFlags change, bool reshuffle);
|
||||
void SetActivePlaylist(int id);
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
bool close_connection_;
|
||||
|
||||
void ChangeVolume(QDomNode& child);
|
||||
void GetPlaylistSongs(QDomNode& child);
|
||||
void ChangeSong(QDomNode& child);
|
||||
};
|
||||
|
||||
#endif // PARSEINCOMINGXML_H
|
|
@ -0,0 +1,149 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, Andreas Muttscheller <asfa194@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "covers/currentartloader.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
|
||||
#include "networkremote.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
const char* NetworkRemote::kSettingsGroup = "NetworkRemote";
|
||||
const int NetworkRemote::kDefaultServerPort = 5500;
|
||||
|
||||
NetworkRemote::NetworkRemote(Application* app)
|
||||
: app_(app)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
NetworkRemote::~NetworkRemote() {
|
||||
server_->close();
|
||||
delete incoming_xml_parser_;
|
||||
delete outgoing_xml_creator_;
|
||||
}
|
||||
|
||||
void NetworkRemote::ReadSettings() {
|
||||
QSettings s;
|
||||
|
||||
s.beginGroup(NetworkRemote::kSettingsGroup);
|
||||
use_remote_ = s.value("use_remote").toBool();
|
||||
port_ = s.value("port").toInt();
|
||||
if (port_ == 0) {
|
||||
port_ = kDefaultServerPort;
|
||||
}
|
||||
s.endGroup();
|
||||
}
|
||||
|
||||
void NetworkRemote::SetupServer() {
|
||||
server_ = new QTcpServer();
|
||||
incoming_xml_parser_ = new IncomingXmlParser(app_);
|
||||
outgoing_xml_creator_ = new OutgoingXmlCreator(app_);
|
||||
|
||||
connect(app_->current_art_loader(),
|
||||
SIGNAL(ArtLoaded(const Song&, const QString&, const QImage&)),
|
||||
outgoing_xml_creator_,
|
||||
SLOT(CurrentSongChanged(const Song&, const QString&, const QImage&)));
|
||||
}
|
||||
|
||||
void NetworkRemote::StartServer() {
|
||||
if (!app_) {
|
||||
qLog(Error) << "Start Server called before having an application!";
|
||||
return;
|
||||
}
|
||||
// Check if user desires to start a network remote server
|
||||
ReadSettings();
|
||||
if (!use_remote_) {
|
||||
qLog(Info) << "Network Remote deactivated";
|
||||
return;
|
||||
}
|
||||
|
||||
qLog(Info) << "Starting network remote";
|
||||
|
||||
clients_ = NULL;
|
||||
|
||||
connect(server_, SIGNAL(newConnection()), this, SLOT(AcceptConnection()));
|
||||
|
||||
server_->listen(QHostAddress::Any, port_);
|
||||
|
||||
qLog(Info) << "Listening on port " << port_;
|
||||
}
|
||||
|
||||
void NetworkRemote::StopServer() {
|
||||
if (server_->isListening()) {
|
||||
server_->close();
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkRemote::ReloadSettings() {
|
||||
if (server_->isListening()) {
|
||||
server_->close();
|
||||
}
|
||||
StartServer();
|
||||
}
|
||||
|
||||
void NetworkRemote::AcceptConnection() {
|
||||
if (!clients_) {
|
||||
// Create a new QList with clients
|
||||
clients_ = new QList<QTcpSocket*>();
|
||||
outgoing_xml_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(app_->playlist_manager(), SIGNAL(ActiveChanged(Playlist*)),
|
||||
outgoing_xml_creator_, SLOT(ActiveChanged(Playlist*)));
|
||||
connect(app_->playlist_manager(), SIGNAL(PlaylistChanged(Playlist*)),
|
||||
outgoing_xml_creator_, SLOT(ActiveChanged(Playlist*)));
|
||||
|
||||
connect(app_->player(), SIGNAL(VolumeChanged(int)), outgoing_xml_creator_,
|
||||
SLOT(VolumeChanged(int)));
|
||||
connect(app_->player()->engine(), SIGNAL(StateChanged(Engine::State)),
|
||||
outgoing_xml_creator_, SLOT(StateChanged(Engine::State)));
|
||||
|
||||
qLog(Info) << "Signals connected!";
|
||||
}
|
||||
QTcpSocket* client = server_->nextPendingConnection();
|
||||
|
||||
clients_->push_back(client);
|
||||
|
||||
// Connect to the slot IncomingData when receiving data
|
||||
connect(client, SIGNAL(readyRead()), this, SLOT(IncomingData()));
|
||||
}
|
||||
|
||||
void NetworkRemote::IncomingData() {
|
||||
QByteArray buf;
|
||||
QTcpSocket* client = static_cast<QTcpSocket*>(QObject::sender());
|
||||
|
||||
buf = client->read(client->bytesAvailable());
|
||||
|
||||
QString strbuf(buf);
|
||||
incoming_xml_parser_->Parse(&strbuf);
|
||||
|
||||
qLog(Debug) << "Data = " << buf << "Size = " << buf.size();
|
||||
if (incoming_xml_parser_->close_connection()) {
|
||||
client->close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#ifndef NETWORKREMOTE_H
|
||||
#define NETWORKREMOTE_H
|
||||
|
||||
#include <QtNetwork>
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include "core/player.h"
|
||||
#include "core/application.h"
|
||||
#include "incomingxmlparser.h"
|
||||
#include "outgoingxmlcreator.h"
|
||||
|
||||
class NetworkRemote : public QThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static const char* kSettingsGroup;
|
||||
static const int kDefaultServerPort;
|
||||
|
||||
NetworkRemote(Application* app);
|
||||
~NetworkRemote();
|
||||
|
||||
public slots:
|
||||
void SetupServer();
|
||||
void StartServer();
|
||||
void ReloadSettings();
|
||||
void AcceptConnection();
|
||||
void IncomingData();
|
||||
|
||||
private:
|
||||
QTcpServer* server_;
|
||||
QList<QTcpSocket*>* clients_;
|
||||
IncomingXmlParser* incoming_xml_parser_;
|
||||
OutgoingXmlCreator* outgoing_xml_creator_;
|
||||
int port_;
|
||||
bool use_remote_;
|
||||
Application* app_;
|
||||
|
||||
void StopServer();
|
||||
void ReadSettings();
|
||||
};
|
||||
|
||||
#endif // NETWORKREMOTE_H
|
|
@ -0,0 +1,58 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, Andreas Muttscheller <asfa194@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "core/logging.h"
|
||||
|
||||
#include "networkremote.h"
|
||||
#include "networkremotehelper.h"
|
||||
|
||||
NetworkRemoteHelper* NetworkRemoteHelper::sInstance = NULL;
|
||||
|
||||
NetworkRemoteHelper::NetworkRemoteHelper(Application* app)
|
||||
: app_(app)
|
||||
{
|
||||
app_ = app;
|
||||
connect(this, SIGNAL(ReloadSettingsSig()),
|
||||
app_->network_remote(), SLOT(ReloadSettings()));
|
||||
connect(this, SIGNAL(StartServerSig()),
|
||||
app_->network_remote(), SLOT(StartServer()));
|
||||
connect(this, SIGNAL(SetupServerSig()),
|
||||
app_->network_remote(), SLOT(SetupServer()));
|
||||
|
||||
sInstance = this;
|
||||
}
|
||||
|
||||
NetworkRemoteHelper::~NetworkRemoteHelper() {
|
||||
}
|
||||
|
||||
void NetworkRemoteHelper::StartServer() {
|
||||
emit SetupServerSig();
|
||||
emit StartServerSig();
|
||||
}
|
||||
|
||||
void NetworkRemoteHelper::ReloadSettings() {
|
||||
emit ReloadSettingsSig();
|
||||
}
|
||||
|
||||
// For using in Settingsdialog, we haven't the appication there
|
||||
NetworkRemoteHelper* NetworkRemoteHelper::Instance() {
|
||||
if (!sInstance) {
|
||||
// normally he shouldn't go here. Only for safety
|
||||
return NULL;
|
||||
}
|
||||
return sInstance;
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
#ifndef NETWORKREMOTEHELPER_H
|
||||
#define NETWORKREMOTEHELPER_H
|
||||
|
||||
#include <QThread>
|
||||
|
||||
#include "networkremote.h"
|
||||
|
||||
class NetworkRemoteHelper : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static NetworkRemoteHelper* Instance();
|
||||
|
||||
NetworkRemoteHelper(Application* app);
|
||||
~NetworkRemoteHelper();
|
||||
|
||||
void StartServer();
|
||||
void ReloadSettings();
|
||||
|
||||
signals:
|
||||
void SetupServerSig();
|
||||
void StartServerSig();
|
||||
void ReloadSettingsSig();
|
||||
|
||||
private:
|
||||
static NetworkRemoteHelper* sInstance;
|
||||
Application* app_;
|
||||
};
|
||||
|
||||
#endif // NETWORKREMOTEHELPER_H
|
|
@ -0,0 +1,309 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, Andreas Muttscheller <asfa194@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<QTcpSocket*>* 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<Playlist*> playlists = app_->playlist_manager()->GetAllPlaylists();
|
||||
QListIterator<Playlist*> 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<Song> 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());
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef OUTGOINGXMLCREATOR_H
|
||||
#define OUTGOINGXMLCREATOR_H
|
||||
|
||||
#include <QDomDocument>
|
||||
#include <QTcpSocket>
|
||||
#include <QImage>
|
||||
#include <QList>
|
||||
#include <QTimer>
|
||||
|
||||
#include "core/player.h"
|
||||
#include "core/application.h"
|
||||
#include "engines/enginebase.h"
|
||||
#include "engines/engine_fwd.h"
|
||||
#include "playlist/playlist.h"
|
||||
#include "playlist/playlistmanager.h"
|
||||
|
||||
class OutgoingXmlCreator : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
OutgoingXmlCreator(Application* app);
|
||||
~OutgoingXmlCreator();
|
||||
|
||||
void SetClients(QList<QTcpSocket*>* clients);
|
||||
|
||||
public slots:
|
||||
void SendClementineInfos();
|
||||
void SendAllPlaylists();
|
||||
void SendFirstData();
|
||||
void SendPlaylistSongs(int id);
|
||||
void VolumeChanged(int volume);
|
||||
void ActiveChanged(Playlist*);
|
||||
void CurrentSongChanged(const Song& song, const QString& uri, const QImage& img);
|
||||
void StateChanged(Engine::State);
|
||||
void SendKeepAlive();
|
||||
|
||||
private:
|
||||
Application* app_;
|
||||
QList<QTcpSocket*>* clients_;
|
||||
Song current_song_;
|
||||
QString current_uri_;
|
||||
QImage current_image_;
|
||||
Engine::State last_state_;
|
||||
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);
|
||||
};
|
||||
|
||||
#endif // OUTGOINGXMLCREATOR_H
|
|
@ -0,0 +1,77 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2012, Andreas Muttscheller <asfa194@gmail.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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() {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#ifndef REMOTEXMLTAGS_H
|
||||
#define REMOTEXMLTAGS_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
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
|
|
@ -0,0 +1,70 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "iconloader.h"
|
||||
#include "networkremotesettingspage.h"
|
||||
#include "ui_networkremotesettingspage.h"
|
||||
#include "networkremote/networkremote.h"
|
||||
#include "networkremote/networkremotehelper.h"
|
||||
|
||||
#include <QSettings>
|
||||
|
||||
|
||||
NetworkRemoteSettingsPage::NetworkRemoteSettingsPage(SettingsDialog* dialog)
|
||||
: SettingsPage(dialog),
|
||||
ui_(new Ui_NetworkRemoteSettingsPage)
|
||||
{
|
||||
ui_->setupUi(this);
|
||||
setWindowIcon(IconLoader::Load("ipodtouchicon"));
|
||||
}
|
||||
|
||||
NetworkRemoteSettingsPage::~NetworkRemoteSettingsPage() {
|
||||
delete ui_;
|
||||
}
|
||||
|
||||
void NetworkRemoteSettingsPage::Load() {
|
||||
QSettings s;
|
||||
int port;
|
||||
|
||||
s.beginGroup(NetworkRemote::kSettingsGroup);
|
||||
|
||||
port = s.value("port").toInt();
|
||||
if (port == 0) {
|
||||
ui_->remote_port->setValue(NetworkRemote::kDefaultServerPort);
|
||||
}
|
||||
else {
|
||||
ui_->remote_port->setValue(s.value("port").toInt());
|
||||
}
|
||||
|
||||
ui_->use_remote->setChecked(s.value("use_remote").toBool());
|
||||
|
||||
s.endGroup();
|
||||
}
|
||||
|
||||
void NetworkRemoteSettingsPage::Save() {
|
||||
QSettings s;
|
||||
|
||||
s.beginGroup(NetworkRemote::kSettingsGroup);
|
||||
s.setValue("port", ui_->remote_port->value());
|
||||
s.setValue("use_remote", ui_->use_remote->isChecked());
|
||||
|
||||
s.endGroup();
|
||||
|
||||
if (NetworkRemoteHelper::Instance()) {
|
||||
NetworkRemoteHelper::Instance()->ReloadSettings();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* This file is part of Clementine.
|
||||
Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
|
||||
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef NETWORKREMOTESETTINGSPAGE_H
|
||||
#define NETWORKREMOTESETTINGSPAGE_H
|
||||
|
||||
#include "settingspage.h"
|
||||
|
||||
class Ui_NetworkRemoteSettingsPage;
|
||||
|
||||
class NetworkRemoteSettingsPage : public SettingsPage {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NetworkRemoteSettingsPage(SettingsDialog* dialog);
|
||||
~NetworkRemoteSettingsPage();
|
||||
|
||||
void Load();
|
||||
void Save();
|
||||
|
||||
private:
|
||||
Ui_NetworkRemoteSettingsPage* ui_;
|
||||
};
|
||||
|
||||
#endif // NETWORKREMOTESETTINGSPAGE_H
|
|
@ -0,0 +1,103 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>NetworkRemoteSettingsPage</class>
|
||||
<widget class="QWidget" name="NetworkRemoteSettingsPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Network Remote</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="use_remote">
|
||||
<property name="text">
|
||||
<string>Use Remotecontrol</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="use_remote_container" native="true">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_15">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>171</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Port</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="remote_port">
|
||||
<property name="maximum">
|
||||
<number>65535</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>8080</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>use_remote</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>use_remote_container</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>199</x>
|
||||
<y>19</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>199</x>
|
||||
<y>60</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
|
@ -23,6 +23,7 @@
|
|||
#include "iconloader.h"
|
||||
#include "playbacksettingspage.h"
|
||||
#include "networkproxysettingspage.h"
|
||||
#include "networkremotesettingspage.h"
|
||||
#include "notificationssettingspage.h"
|
||||
#include "mainwindow.h"
|
||||
#include "settingsdialog.h"
|
||||
|
@ -130,6 +131,7 @@ SettingsDialog::SettingsDialog(Application* app, BackgroundStreams* streams, QWi
|
|||
AddPage(Page_Library, new LibrarySettingsPage(this), general);
|
||||
AddPage(Page_Proxy, new NetworkProxySettingsPage(this), general);
|
||||
AddPage(Page_Transcoding, new TranscoderSettingsPage(this), general);
|
||||
AddPage(Page_NetworkRemote, new NetworkRemoteSettingsPage(this), general);
|
||||
|
||||
#ifdef HAVE_WIIMOTEDEV
|
||||
AddPage(Page_Wiimotedev, new WiimoteSettingsPage(this), general);
|
||||
|
|
|
@ -63,6 +63,7 @@ public:
|
|||
Page_GlobalShortcuts,
|
||||
Page_GlobalSearch,
|
||||
Page_Appearance,
|
||||
Page_NetworkRemote,
|
||||
Page_Notifications,
|
||||
Page_Library,
|
||||
Page_Lastfm,
|
||||
|
|
Loading…
Reference in New Issue