1
0
mirror of https://github.com/clementine-player/Clementine synced 2024-12-18 04:19:55 +01:00

Some support for MediaStorageInterface.

This commit is contained in:
John Maguire 2011-03-13 18:20:37 +00:00
parent 002ae13817
commit e172765331
13 changed files with 347 additions and 2 deletions

View File

@ -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
)

View File

@ -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()

View File

@ -24,6 +24,7 @@ namespace xrme {
extern const char* kXmlnsXrme;
extern const char* kXmlnsXrmeMediaPlayer;
extern const char* kXmlnsXrmeMediaStorage;
extern const char* kXmlnsXrmeRemoteControl;
struct Metadata {

View File

@ -19,6 +19,7 @@
#include "connection.h"
#include "extensions.h"
#include "mediaplayerhandler.h"
#include "mediastoragehandler.h"
#include "remotecontrolhandler.h"
#include <QSocketNotifier>
@ -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<Handler*> 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.

View File

@ -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;

View File

@ -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']";
}

View File

@ -46,6 +46,12 @@ class MediaPlayerExtension : public XRMEExtension<MediaPlayerExtension> {
static const char* kFilterString;
};
class MediaStorageExtension : public XRMEExtension<MediaStorageExtension> {
public:
static const int kExtensionType = gloox::ExtUser + 3;
static const char* kFilterString;
};
template <typename T>
XRMEExtension<T>::XRMEExtension()
: StanzaExtension(T::kExtensionType),

View File

@ -0,0 +1,95 @@
/* This file is part of the XMPP Remote Media Extension.
Copyright 2010, David Sansome <me@davidsansome.com>
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 <http://www.gnu.org/licenses/>.
*/
#include "connection.h"
#include "extensions.h"
#include "mediastoragehandler.h"
#include "mediastorageinterface.h"
#include <QBuffer>
#include <QtDebug>
#include <gloox/client.h>
#include <gloox/disco.h>
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

50
3rdparty/libxrme/mediastoragehandler.h vendored Normal file
View File

@ -0,0 +1,50 @@
/* This file is part of the XMPP Remote Media Extension.
Copyright 2010, David Sansome <me@davidsansome.com>
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 <http://www.gnu.org/licenses/>.
*/
#ifndef LIBXRME_MEDIASTORAGEHANDLER_H
#define LIBXRME_MEDIASTORAGEHANDLER_H
#include "handler.h"
#include <gloox/iqhandler.h>
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

View File

@ -0,0 +1,44 @@
/* This file is part of the XMPP Remote Media Extension.
Copyright 2010, David Sansome <me@davidsansome.com>
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 <http://www.gnu.org/licenses/>.
*/
#include "mediastoragehandler.h"
#include "mediastorageinterface.h"
#include <QtDebug>
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

View File

@ -0,0 +1,49 @@
/* This file is part of the XMPP Remote Media Extension.
Copyright 2010, David Sansome <me@davidsansome.com>
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 <http://www.gnu.org/licenses/>.
*/
#ifndef LIBXRME_MEDIASTORAGEINTERFACE_H
#define LIBXRME_MEDIASTORAGEINTERFACE_H
#include <xrme/common.h>
#include <QImage>
#include <QScopedPointer>
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<Private> d;
};
} // namespace xrme
#endif // LIBXRME_MEDIASTORAGEINTERFACE_H

View File

@ -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<QTcpSocket*>(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<QTcpSocket*>(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;
}

View File

@ -25,12 +25,14 @@
#include <xrme/connection.h>
#include <xrme/mediaplayerinterface.h>
#include <xrme/mediastorageinterface.h>
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<QTcpSocket*, TomahawkConnection*> tomahawk_connections_;