diff --git a/3rdparty/libxrme/CMakeLists.txt b/3rdparty/libxrme/CMakeLists.txt index 8edef76b9..6b58192ad 100644 --- a/3rdparty/libxrme/CMakeLists.txt +++ b/3rdparty/libxrme/CMakeLists.txt @@ -7,6 +7,8 @@ set(SOURCES handler.cpp mediaplayerhandler.cpp mediaplayerinterface.cpp + mediastoragehandler.cpp + mediastorageinterface.cpp remotecontrolhandler.cpp remotecontrolinterface.cpp ) @@ -19,6 +21,7 @@ SET(PUBLIC_HEADERS connection.h common.h mediaplayerinterface.h + mediastorageinterface.h remotecontrolinterface.h ) diff --git a/3rdparty/libxrme/common.cpp b/3rdparty/libxrme/common.cpp index c43290476..c3da3b5cd 100644 --- a/3rdparty/libxrme/common.cpp +++ b/3rdparty/libxrme/common.cpp @@ -21,6 +21,7 @@ namespace xrme { const char* kXmlnsXrme = "http://purplehatstands.com/xmlns/xrme"; const char* kXmlnsXrmeMediaPlayer = "http://purplehatstands.com/xmlns/xrme/mediaplayer"; +const char* kXmlnsXrmeMediaStorage = "http://purplehatstands.com/xmlns/xrme/mediastorage"; const char* kXmlnsXrmeRemoteControl = "http://purplehatstands.com/xmlns/xrme/remotecontrol"; Metadata::Metadata() diff --git a/3rdparty/libxrme/common.h b/3rdparty/libxrme/common.h index f35b784e3..1279a2681 100644 --- a/3rdparty/libxrme/common.h +++ b/3rdparty/libxrme/common.h @@ -24,6 +24,7 @@ namespace xrme { extern const char* kXmlnsXrme; extern const char* kXmlnsXrmeMediaPlayer; +extern const char* kXmlnsXrmeMediaStorage; extern const char* kXmlnsXrmeRemoteControl; struct Metadata { diff --git a/3rdparty/libxrme/connection.cpp b/3rdparty/libxrme/connection.cpp index e815770f2..c99b1dfa7 100644 --- a/3rdparty/libxrme/connection.cpp +++ b/3rdparty/libxrme/connection.cpp @@ -19,6 +19,7 @@ #include "connection.h" #include "extensions.h" #include "mediaplayerhandler.h" +#include "mediastoragehandler.h" #include "remotecontrolhandler.h" #include @@ -55,6 +56,7 @@ struct Connection::Private : public gloox::ConnectionListener, verbose_(false), media_player_(NULL), remote_control_(NULL), + media_storage_(NULL), spontaneous_disconnect_(true), media_player_extension_(NULL), remote_control_extension_(NULL) {} @@ -77,6 +79,7 @@ struct Connection::Private : public gloox::ConnectionListener, // Interfaces MediaPlayerInterface* media_player_; RemoteControlInterface* remote_control_; + MediaStorageInterface* media_storage_; QList handlers_; // Stuff that is valid when we're connected. @@ -200,6 +203,22 @@ void Connection::SetRemoteControl(RemoteControlInterface* iface) { d->handlers_ << new RemoteControlHandler(iface); } +void Connection::SetMediaStorage(MediaStorageInterface* iface) { + if (d->media_storage_) { + qWarning() << "Connection::MediaStorageInterface: this connection already" + " has a RemoteControlInterface set"; + return; + } + + if (!iface) { + qWarning() << "Connection::SetMediaStorage called with NULL interface"; + return; + } + + d->media_storage_ = iface; + d->handlers_ << new MediaStorageHandler(iface); +} + bool Connection::is_connected() const { return (d->client_ && d->client_->state() == gloox::StateConnected); } @@ -267,6 +286,7 @@ bool Connection::Connect() { d->remote_control_extension_ = new RemoteControlExtension; d->client_->registerStanzaExtension(d->media_player_extension_); d->client_->registerStanzaExtension(d->remote_control_extension_); + d->client_->registerStanzaExtension(new MediaStorageExtension); // Initialise the handlers foreach (Handler* handler, d->handlers_) { @@ -400,6 +420,8 @@ void Connection::Private::handleSelfPresence( const std::string&) { QString resource = QString::fromUtf8(res.c_str()); + qDebug() << "Resource presence changed:" << resource << presence; + switch (presence) { case gloox::Presence::Error: case gloox::Presence::Invalid: @@ -513,6 +535,9 @@ void Connection::Private::handleDiscoInfo( if (feature_name == kXmlnsXrmeRemoteControl) { peer.caps_ |= Peer::RemoteControl; } + if (feature_name == kXmlnsXrmeMediaStorage) { + peer.caps_ |= Peer::MediaStorage; + } } // No recognised capabilities? Discard the peer. diff --git a/3rdparty/libxrme/connection.h b/3rdparty/libxrme/connection.h index 50d10a0fc..2c8da6fa0 100644 --- a/3rdparty/libxrme/connection.h +++ b/3rdparty/libxrme/connection.h @@ -26,6 +26,7 @@ namespace xrme { class MediaPlayerInterface; +class MediaStorageInterface; class RemoteControlInterface; class Connection : public QObject { @@ -101,6 +102,8 @@ public: // RemoteControlInterface MUST stay alive for as long as the connection. void SetRemoteControl(RemoteControlInterface* iface); + void SetMediaStorage(MediaStorageInterface* iface); + // Returns true after Connected() is emitted. bool is_connected() const; diff --git a/3rdparty/libxrme/extensions.cpp b/3rdparty/libxrme/extensions.cpp index f3e06e5ba..8a5c1e318 100644 --- a/3rdparty/libxrme/extensions.cpp +++ b/3rdparty/libxrme/extensions.cpp @@ -6,5 +6,7 @@ const char* MediaPlayerExtension::kFilterString = "/iq/xrme[@xmlns='http://purplehatstands.com/xmlns/xrme/mediaplayer']"; const char* RemoteControlExtension::kFilterString = "/iq/xrme[@xmlns='http://purplehatstands.com/xmlns/xrme/remotecontrol']"; +const char* MediaStorageExtension::kFilterString = + "/iq/xrme[@xmlns='http://purplehatstands.com/xmlns/xrme/mediastorage']"; } diff --git a/3rdparty/libxrme/extensions.h b/3rdparty/libxrme/extensions.h index db9d44f7e..f13eaa3a7 100644 --- a/3rdparty/libxrme/extensions.h +++ b/3rdparty/libxrme/extensions.h @@ -46,6 +46,12 @@ class MediaPlayerExtension : public XRMEExtension { static const char* kFilterString; }; +class MediaStorageExtension : public XRMEExtension { + public: + static const int kExtensionType = gloox::ExtUser + 3; + static const char* kFilterString; +}; + template XRMEExtension::XRMEExtension() : StanzaExtension(T::kExtensionType), diff --git a/3rdparty/libxrme/mediastoragehandler.cpp b/3rdparty/libxrme/mediastoragehandler.cpp new file mode 100644 index 000000000..1f12919ef --- /dev/null +++ b/3rdparty/libxrme/mediastoragehandler.cpp @@ -0,0 +1,95 @@ +/* This file is part of the XMPP Remote Media Extension. + Copyright 2010, David Sansome + + This library 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 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "connection.h" +#include "extensions.h" +#include "mediastoragehandler.h" +#include "mediastorageinterface.h" + +#include +#include + +#include +#include + +namespace xrme { + +MediaStorageHandler::MediaStorageHandler(MediaStorageInterface* iface) + : interface_(iface) { + interface_->Attach(this); +} + +void MediaStorageHandler::GetArtists() { + if (!connection_) { + return; + } + + foreach (const Connection::Peer& peer, connection_->peers(Connection::Peer::RemoteControl)) { + gloox::JID to(client_->jid().bareJID()); + to.setResource(peer.jid_resource_.toUtf8().constData()); + + gloox::IQ iq(gloox::IQ::Set, to, client_->getID()); + gloox::Tag* tag = iq.tag(); + gloox::Tag* c = new gloox::Tag(tag, "xrme"); + c->setXmlns(kXmlnsXrmeRemoteControl); + + gloox::Tag* artists = new gloox::Tag(c, "artists"); + gloox::Tag* artist = new gloox::Tag(artists, "artist"); + artist->addAttribute("name", "Muse"); + artist->addAttribute("songs", 42); + artist->addAttribute("albums", 6); + + gloox::Tag* artist2 = new gloox::Tag(artists, "artist"); + artist2->addAttribute("name", "Rage against the Machine"); + artist2->addAttribute("songs", 67); + artist2->addAttribute("albums", 8); + + client_->send(tag); + } +} + +void MediaStorageHandler::Init(Connection* connection, gloox::Client* client) { + Handler::Init(connection, client); + + qDebug() << "Registering for extension:" << MediaStorageExtension::kExtensionType; + client->registerIqHandler( + this, MediaStorageExtension::kExtensionType); + client->disco()->addFeature(kXmlnsXrmeMediaStorage); +} + +bool MediaStorageHandler::handleIq(const gloox::IQ& stanza) { + qDebug() << Q_FUNC_INFO << stanza.tag()->xml().c_str(); + // Ignore stanzas from anyone else + if (stanza.from().bareJID() != client_->jid().bareJID()) { + return false; + } + + gloox::Tag* xrme = stanza.tag()->findChild("xrme"); + + if (xrme->hasChild("get_artists")) { + GetArtists(); + } else { + qWarning() << "Unknown command received from" + << stanza.from().resource().c_str() + << stanza.tag()->xml().c_str(); + return false; + } + + return true; +} + +} // namespace xrme diff --git a/3rdparty/libxrme/mediastoragehandler.h b/3rdparty/libxrme/mediastoragehandler.h new file mode 100644 index 000000000..f5d4ae130 --- /dev/null +++ b/3rdparty/libxrme/mediastoragehandler.h @@ -0,0 +1,50 @@ +/* This file is part of the XMPP Remote Media Extension. + Copyright 2010, David Sansome + + This library 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 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef LIBXRME_MEDIASTORAGEHANDLER_H +#define LIBXRME_MEDIASTORAGEHANDLER_H + +#include "handler.h" + +#include + +namespace xrme { + +class MediaStorageInterface; + +class MediaStorageHandler : public Handler, + public gloox::IqHandler { +public: + MediaStorageHandler(MediaStorageInterface* interface); + + void GetArtists(); + + + // Handler + void Init(Connection* connection, gloox::Client* client); + + // gloox::IqHandler + bool handleIq(const gloox::IQ& stanza); + void handleIqID(const gloox::IQ&, int) {} + +private: + MediaStorageInterface* interface_; +}; + +} // namespace xrme + +#endif // LIBXRME_MEDIASTORAGEHANDLER_H diff --git a/3rdparty/libxrme/mediastorageinterface.cpp b/3rdparty/libxrme/mediastorageinterface.cpp new file mode 100644 index 000000000..1576657db --- /dev/null +++ b/3rdparty/libxrme/mediastorageinterface.cpp @@ -0,0 +1,44 @@ +/* This file is part of the XMPP Remote Media Extension. + Copyright 2010, David Sansome + + This library 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 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "mediastoragehandler.h" +#include "mediastorageinterface.h" + +#include + +namespace xrme { + +struct MediaStorageInterface::Private { + Private() + : handler_(NULL) {} + + MediaStorageHandler* handler_; +}; + + +MediaStorageInterface::MediaStorageInterface() + : d(new Private) { +} + +MediaStorageInterface::~MediaStorageInterface() { +} + +void MediaStorageInterface::Attach(MediaStorageHandler* handler) { + d->handler_ = handler; +} + +} // namespace xrme diff --git a/3rdparty/libxrme/mediastorageinterface.h b/3rdparty/libxrme/mediastorageinterface.h new file mode 100644 index 000000000..d6797ca92 --- /dev/null +++ b/3rdparty/libxrme/mediastorageinterface.h @@ -0,0 +1,49 @@ +/* This file is part of the XMPP Remote Media Extension. + Copyright 2010, David Sansome + + This library 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 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#ifndef LIBXRME_MEDIASTORAGEINTERFACE_H +#define LIBXRME_MEDIASTORAGEINTERFACE_H + +#include + +#include +#include + +namespace xrme { + +class MediaStorageHandler; + +class MediaStorageInterface { +public: + MediaStorageInterface(); + virtual ~MediaStorageInterface(); + + virtual QStringList GetArtists() const = 0; + +private: + Q_DISABLE_COPY(MediaStorageInterface); + friend class MediaStorageHandler; + + void Attach(MediaStorageHandler* handler); + + struct Private; + QScopedPointer d; +}; + +} // namespace xrme + +#endif // LIBXRME_MEDIASTORAGEINTERFACE_H diff --git a/src/remote/remote.cpp b/src/remote/remote.cpp index 3f3cc3fd8..2e253ba85 100644 --- a/src/remote/remote.cpp +++ b/src/remote/remote.cpp @@ -37,6 +37,7 @@ Remote::Remote(Player* player, QObject* parent) retry_count_(0) { connection_->SetMediaPlayer(this); + connection_->SetMediaStorage(this); connection_->set_verbose(true); connect(connection_, SIGNAL(Connected()), SLOT(Connected())); connect(connection_, SIGNAL(Disconnected(QString)), SLOT(Disconnected(QString))); @@ -164,6 +165,10 @@ QImage Remote::album_art() const { return last_image_; } +QStringList Remote::GetArtists() const { + return QStringList(); +} + void Remote::SetStateChanged() { StateChanged(); } @@ -298,6 +303,7 @@ void Remote::TomahawkReadyRead() { if (ok) { QVariantMap map = json.toMap(); QString method = map["method"].toString(); + QString conntype = map["conntype"].toString(); if (method == "dbsync-offer") { qDebug() << "DBSYNC!"; TomahawkConnection* db_connection = new TomahawkConnection; @@ -309,13 +315,25 @@ void Remote::TomahawkReadyRead() { connect(sync_socket, SIGNAL(disconnected()), SLOT(TomahawkDBDisconnected())); connect(sync_socket, SIGNAL(readyRead()), SLOT(TomahawkDBReadyRead())); tomahawk_connections_[sync_socket] = db_connection; + } else if (conntype == "request-offer") { + qDebug() << "File Transfer!"; + TomahawkConnection* file_transfer = new TomahawkConnection; + file_transfer->key = map["key"].toString(); + file_transfer->num_bytes = -1; + file_transfer->offer = map["offer"].toString(); + file_transfer->controlid = map["controlid"].toString(); + QTcpSocket* file_transfer_socket = new QTcpSocket(this); + file_transfer_socket->connectToHost(socket->peerAddress(), map["port"].toUInt()); + connect(file_transfer_socket, SIGNAL(connected()), SLOT(TomahawkTransferConnected())); + connect(file_transfer_socket, SIGNAL(disconnected()), SLOT(TomahawkTransferDisconnected())); + connect(file_transfer_socket, SIGNAL(readyRead()), SLOT(TomahawkTransferReadyRead())); + tomahawk_connections_[file_transfer_socket] = file_transfer; } } } } void Remote::TomahawkDBConnected() { - qDebug() << Q_FUNC_INFO; qDebug() << Q_FUNC_INFO; QTcpSocket* socket = qobject_cast(sender()); Q_ASSERT(socket); @@ -435,3 +453,40 @@ void Remote::TomahawkDisconnected() { void Remote::TomahawkError(QAbstractSocket::SocketError error) { qDebug() << Q_FUNC_INFO << error; } + +void Remote::TomahawkTransferConnected() { + qDebug() << Q_FUNC_INFO; + QTcpSocket* socket = qobject_cast(sender()); + Q_ASSERT(socket); + + TomahawkConnection* connection = tomahawk_connections_[socket]; + + { + QVariantMap request; + request["method"] = "accept-offer"; + request["key"] = connection->key; + + QJson::Serializer serialiser; + const QByteArray& json = serialiser.serialize(request); + + QDataStream stream(socket); + stream << (quint32)json.length(); + stream << (quint8)(2); + stream.writeRawData(json.constData(), json.length()); + } + + { + QDataStream stream(socket); + stream << (quint32)2; + stream << (quint8)(128 | 1); // SETUP | RAW + stream.writeRawData("ok", 2); + } +} + +void Remote::TomahawkTransferDisconnected() { + qDebug() << Q_FUNC_INFO; +} + +void Remote::TomahawkTransferReadyRead() { + qDebug() << Q_FUNC_INFO; +} diff --git a/src/remote/remote.h b/src/remote/remote.h index 5bf482cce..827b6b91f 100644 --- a/src/remote/remote.h +++ b/src/remote/remote.h @@ -25,12 +25,14 @@ #include #include +#include class ArtLoader; class Player; class Remote : public QObject, - protected xrme::MediaPlayerInterface { + protected xrme::MediaPlayerInterface, + protected xrme::MediaStorageInterface { Q_OBJECT public: @@ -54,6 +56,9 @@ protected: xrme::State state() const; QImage album_art() const; + // xrme::MediaStorageInterface + QStringList GetArtists() const; + private slots: void Connected(); void Disconnected(const QString& error); @@ -70,6 +75,10 @@ private slots: void TomahawkDBDisconnected(); void TomahawkDBReadyRead(); + void TomahawkTransferConnected(); + void TomahawkTransferDisconnected(); + void TomahawkTransferReadyRead(); + private: bool is_configured() const; @@ -84,6 +93,8 @@ private: QTcpSocket* socket; int num_bytes; quint8 flags; + QString offer; + QString controlid; }; QMap tomahawk_connections_;