From d87398c47aee5e2b56b072d9084a803c3efa1d2a Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 20 Apr 2011 00:26:13 +0200 Subject: [PATCH 1/8] First shitty implementation of loading avatars --- src/sip/jreen/jabber_p.cpp | 42 ++++++++++++++++++++++++++++++++++++-- src/sip/jreen/jabber_p.h | 9 ++++++-- 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/sip/jreen/jabber_p.cpp b/src/sip/jreen/jabber_p.cpp index 5c849f40c..93efa5a06 100644 --- a/src/sip/jreen/jabber_p.cpp +++ b/src/sip/jreen/jabber_p.cpp @@ -25,6 +25,8 @@ #include "utils/tomahawkutils.h" #include +#include +#include #include #include @@ -37,6 +39,14 @@ #include #include #include +#include +#include +#include +#include + +//remove +#include +#include #define TOMAHAWK_FEATURE QLatin1String( "tomahawk:sip:v1" ) @@ -57,6 +67,12 @@ Jabber_p::Jabber_p( const QString& jid, const QString& password, const QString& m_client->registerStanzaExtension(new TomahawkSipMessageFactory); m_client->setResource( QString( "tomahawk%1" ).arg( QString::number( qrand() % 10000 ) ) ); + // add VCardUpdate extension to own presence + m_client->presence().addExtension( new Jreen::VCardUpdate() ); + + // read cached avatars + m_photoHashes = QDir("/home/domme/jreen/").entryList(); + // setup disco m_client->disco()->setSoftwareVersion( "Tomahawk Player", TOMAHAWK_VERSION, CMAKE_SYSTEM ); m_client->disco()->addIdentity( Jreen::Disco::Identity( "client", "type", "tomahawk", "en" ) ); @@ -210,6 +226,9 @@ Jabber_p::onConnect() // set presence to least valid value m_client->setPresence(Jreen::Presence::XA, "Got Tomahawk? http://gettomahawk.com", -127); + // request own vcard + fetchVCard( m_jid.bare() ); + // set ping timeout to 15 secs (TODO: verify if this works) m_client->setPingInterval(15000); @@ -329,8 +348,19 @@ void Jabber_p::onNewPresence( const Jreen::Presence& presence) Jreen::JID jid = presence.from(); QString fulljid( jid.full() ); + qDebug() << Q_FUNC_INFO << "* New presence: " << fulljid << presence.subtype(); + Jreen::VCardUpdate::Ptr update = presence.findExtension(); + if(update) + { + qDebug() << "vcard: found update for " << fulljid; + if(!m_photoHashes.contains(update->photoHash())) + { + fetchVCard( jid.bare() ); + } + } + if( jid == m_jid ) return; @@ -411,11 +441,18 @@ Jabber_p::onNewIq( const Jreen::IQ &iq, int context ) { qDebug() << "Sent SipMessage... what now?!"; } + /*else if(context == RequestedVCard ) + { + qDebug() << "Requested VCard... what now?!"; + }*/ else { + TomahawkSipMessage *sipMessage = iq.findExtension().data(); if(sipMessage) { + iq.accept(); + qDebug() << Q_FUNC_INFO << "Got SipMessage ..."; qDebug() << "ip" << sipMessage->ip(); qDebug() << "port" << sipMessage->port(); @@ -466,8 +503,10 @@ Jabber_p::presenceMeansOnline( Jreen::Presence::Type p ) } void -Jabber_p::handlePeerStatus( const QString& fulljid, Jreen::Presence::Type presenceType ) +Jabber_p::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type presenceType ) { + QString fulljid = jid.full(); + // "going offline" event if ( !presenceMeansOnline( presenceType ) && ( !m_peers.contains( fulljid ) || @@ -504,4 +543,3 @@ Jabber_p::handlePeerStatus( const QString& fulljid, Jreen::Presence::Type presen //qDebug() << "Updating presence data for" << fulljid; m_peers[ fulljid ] = presenceType; } - diff --git a/src/sip/jreen/jabber_p.h b/src/sip/jreen/jabber_p.h index ae00f1329..0fd354467 100644 --- a/src/sip/jreen/jabber_p.h +++ b/src/sip/jreen/jabber_p.h @@ -85,7 +85,7 @@ private slots: private: bool presenceMeansOnline( Jreen::Presence::Type p ); - void handlePeerStatus( const QString &fulljid, Jreen::Presence::Type presenceType ); + void handlePeerStatus( const Jreen::JID &jid, Jreen::Presence::Type presenceType ); Jreen::Client *m_client; Jreen::MUCRoom *m_room; @@ -95,9 +95,14 @@ private: QMap m_peers; QString m_server; - enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent }; + enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard }; QStringList m_legacy_peers; + + + //sort out + //QHash m_contactsPhotoHashes; + QStringList m_photoHashes; }; #endif // JABBER_H From def3e3d868ff532366ee6879a4b01fd9aa847cb5 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 20 Apr 2011 20:22:06 +0200 Subject: [PATCH 2/8] Move SipHandler from application to library --- src/CMakeLists.txt | 3 - src/libtomahawk/CMakeLists.txt | 2 + src/{ => libtomahawk}/sip/SipHandler.cpp | 71 +++++++++++++++++++++++- src/{ => libtomahawk}/sip/SipHandler.h | 16 +++++- 4 files changed, 84 insertions(+), 8 deletions(-) rename src/{ => libtomahawk}/sip/SipHandler.cpp (83%) rename src/{ => libtomahawk}/sip/SipHandler.h (85%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 067558b19..1c3f3a8e7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -32,8 +32,6 @@ ENDIF() #ENDFOREACH( moddir ) SET( tomahawkSources ${tomahawkSources} - sip/SipHandler.cpp - web/api_v1.cpp resolvers/scriptresolver.cpp @@ -71,7 +69,6 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui} SET( tomahawkHeaders ${tomahawkHeaders} "${TOMAHAWK_INC_DIR}/tomahawk/tomahawkapp.h" - sip/SipHandler.h web/api_v1.h diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt index 33aaff411..01a18a12a 100644 --- a/src/libtomahawk/CMakeLists.txt +++ b/src/libtomahawk/CMakeLists.txt @@ -29,6 +29,7 @@ set( libSources viewpage.cpp sip/SipPlugin.cpp + sip/SipHandler.cpp audio/madtranscode.cpp audio/dummytranscode.cpp @@ -187,6 +188,7 @@ set( libHeaders playlist.h sip/SipPlugin.h + sip/SipHandler.h audio/transcodeinterface.h audio/madtranscode.h diff --git a/src/sip/SipHandler.cpp b/src/libtomahawk/sip/SipHandler.cpp similarity index 83% rename from src/sip/SipHandler.cpp rename to src/libtomahawk/sip/SipHandler.cpp index 59aa8ea12..0170bdf64 100644 --- a/src/sip/SipHandler.cpp +++ b/src/libtomahawk/sip/SipHandler.cpp @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -24,19 +24,33 @@ #include #include +#include "functimeout.h" + #include "database/database.h" #include "network/controlconnection.h" #include "sourcelist.h" #include "tomahawksettings.h" -#include "tomahawk/tomahawkapp.h" +//#include "tomahawk/tomahawkapp.h" #include "config.h" +//remove +#include + +SipHandler* SipHandler::s_instance = 0; + +SipHandler* SipHandler::instance() +{ + return s_instance; +} + SipHandler::SipHandler( QObject* parent ) : QObject( parent ) , m_connected( false ) { + s_instance = this; + loadPlugins( findPlugins() ); connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( onSettingsChanged() ) ); @@ -55,6 +69,23 @@ SipHandler::plugins() const return m_plugins; } +const QPixmap SipHandler::avatar( const QString& name ) const +{ + qDebug() << Q_FUNC_INFO << "Getting avatar" << name << m_usernameAvatars.keys(); + if( m_usernameAvatars.keys().contains( name ) ) + { + qDebug() << Q_FUNC_INFO << "Getting avatar and avatar != null "; + Q_ASSERT(!m_usernameAvatars.value( name ).isNull()); + return m_usernameAvatars.value( name ); + } + else + { + qDebug() << Q_FUNC_INFO << "Getting avatar and avatar == null, GAAAAAH "; + return QPixmap(); + } +} + + void SipHandler::onSettingsChanged() @@ -147,6 +178,7 @@ SipHandler::loadPlugin( const QString& path ) QObject::connect( sip, SIGNAL( disconnected() ), SIGNAL( disconnected() ) ); QObject::connect( sip, SIGNAL( error( int, QString ) ), SLOT( onError( int, QString ) ) ); + QObject::connect( sip, SIGNAL( avatarReceived( QString, QPixmap ) ), SLOT( onAvatarReceived( QString, QPixmap ) ) ); m_plugins << sip; } } @@ -182,7 +214,8 @@ SipHandler::connectPlugins( bool startup, const QString &pluginName ) if ( !TomahawkSettings::instance()->acceptedLegalWarning() ) { int result = QMessageBox::question( - TomahawkApp::instance()->mainWindow(), tr( "Legal Warning" ), + //TomahawkApp::instance()->mainWindow(), + 0, tr( "Legal Warning" ), tr( "By pressing OK below, you agree that your use of Tomahawk will be in accordance with any applicable laws, including copyright and intellectual property laws, in effect in your country of residence, and indemnify the Tomahawk developers and project from liability should you choose to break those laws.\n\nFor more information, please see http://gettomahawk.com/legal" ), tr( "I Do Not Agree" ), tr( "I Agree" ) ); @@ -346,3 +379,35 @@ SipHandler::onError( int code, const QString& msg ) QTimer::singleShot( 10000, sip, SLOT( connectPlugin() ) ); } } + +void SipHandler::onAvatarReceived( const QString& from, const QPixmap& avatar ) +{ + qDebug() << Q_FUNC_INFO << "Set avatar on source for " << from; + Q_ASSERT(!avatar.isNull()); + + m_usernameAvatars.insert( from, avatar ); + + // + + //Tomahawk::source_ptr source = ->source(); + ControlConnection *conn = Servent::instance()->lookupControlConnection( from ); + if( conn ) + { + qDebug() << Q_FUNC_INFO << from << "got control connection"; + Tomahawk::source_ptr source = conn->source(); + if( source ) + { + + qDebug() << Q_FUNC_INFO << from << "got source, setting avatar"; + source->setAvatar( avatar ); + } + else + { + qDebug() << Q_FUNC_INFO << from << "no source found, not setting avatar"; + } + } + else + { + qDebug() << Q_FUNC_INFO << from << "no control connection setup yet"; + } +} diff --git a/src/sip/SipHandler.h b/src/libtomahawk/sip/SipHandler.h similarity index 85% rename from src/sip/SipHandler.h rename to src/libtomahawk/sip/SipHandler.h index 0d3dcfa63..d394ea5d1 100644 --- a/src/sip/SipHandler.h +++ b/src/libtomahawk/sip/SipHandler.h @@ -1,5 +1,5 @@ /* === This file is part of Tomahawk Player - === - * + * * Copyright 2010-2011, Christian Muehlhaeuser * * Tomahawk is free software: you can redistribute it and/or modify @@ -23,19 +23,24 @@ #include #include +#include +#include +#include class SipHandler : public QObject { Q_OBJECT public: -// static SipHandler* instance() { return s_instance ? s_instance : new SipHandler(); } + static SipHandler* instance(); SipHandler( QObject* parent ); ~SipHandler(); QList< SipPlugin* > plugins() const; + const QPixmap avatar( const QString& name ) const; + public slots: void addContact( const QString& id ) { qDebug() << Q_FUNC_INFO << id; } @@ -57,7 +62,11 @@ private slots: void onSettingsChanged(); + void onAvatarReceived( const QString& from, const QPixmap& avatar = QPixmap()); + private: + static SipHandler *s_instance; + QStringList findPlugins(); bool pluginLoaded( const QString& name ) const; @@ -66,6 +75,9 @@ private: QList< SipPlugin* > m_plugins; bool m_connected; + + + QHash m_usernameAvatars; }; #endif From 47fd7b82859ce812c8744ba173d0e721ceb07bea Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 20 Apr 2011 20:30:04 +0200 Subject: [PATCH 3/8] Add avatar support to controlconnection, source and sourcetreeview. --- src/libtomahawk/network/controlconnection.cpp | 5 +++++ src/libtomahawk/network/controlconnection.h | 2 ++ src/libtomahawk/sip/SipPlugin.h | 4 +++- src/libtomahawk/source.cpp | 10 ++++++++++ src/libtomahawk/source.h | 4 ++++ src/sourcetree/sourcetreeview.cpp | 7 +++++-- 6 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/libtomahawk/network/controlconnection.cpp b/src/libtomahawk/network/controlconnection.cpp index b1c7a0b50..1982ee8d7 100644 --- a/src/libtomahawk/network/controlconnection.cpp +++ b/src/libtomahawk/network/controlconnection.cpp @@ -23,6 +23,7 @@ #include "database/databasecommand_collectionstats.h" #include "dbsyncconnection.h" #include "sourcelist.h" +#include #define TCP_TIMEOUT 600 @@ -120,6 +121,10 @@ ControlConnection::registerSource() Source* source = (Source*) sender(); Q_UNUSED( source ) Q_ASSERT( source == m_source.data() ); + + qDebug() << Q_FUNC_INFO << "Setting avatar ... " << name() << !SipHandler::instance()->avatar( name() ).isNull(); + source->setAvatar( SipHandler::instance()->avatar( name() ) ); + // .. but we'll use the shared pointer we've already made: m_registered = true; diff --git a/src/libtomahawk/network/controlconnection.h b/src/libtomahawk/network/controlconnection.h index d23c91f43..f0f2b105b 100644 --- a/src/libtomahawk/network/controlconnection.h +++ b/src/libtomahawk/network/controlconnection.h @@ -44,6 +44,8 @@ public: DBSyncConnection* dbSyncConnection(); + Tomahawk::source_ptr source() const { return m_source; } + protected: virtual void setup(); diff --git a/src/libtomahawk/sip/SipPlugin.h b/src/libtomahawk/sip/SipPlugin.h index 47af2fcf3..28e19ffb2 100644 --- a/src/libtomahawk/sip/SipPlugin.h +++ b/src/libtomahawk/sip/SipPlugin.h @@ -57,7 +57,9 @@ signals: void peerOnline( const QString& ); void peerOffline( const QString& ); void msgReceived( const QString& from, const QString& msg ); - + + void avatarReceived ( const QString& from, const QPixmap& avatar); + void addMenu( QMenu* menu ); void removeMenu( QMenu* menu ); }; diff --git a/src/libtomahawk/source.cpp b/src/libtomahawk/source.cpp index d825a7724..3e729d8f8 100644 --- a/src/libtomahawk/source.cpp +++ b/src/libtomahawk/source.cpp @@ -107,6 +107,16 @@ Source::friendlyName() const return m_friendlyname; } +void Source::setAvatar(const QPixmap& avatar) +{ + m_avatar = avatar; +} + +const QPixmap Source::avatar() const +{ + return m_avatar; +} + void Source::addCollection( const collection_ptr& c ) diff --git a/src/libtomahawk/source.h b/src/libtomahawk/source.h index ed48dfd1b..51d2dcdc7 100644 --- a/src/libtomahawk/source.h +++ b/src/libtomahawk/source.h @@ -54,6 +54,8 @@ public: QString userName() const { return m_username; } QString friendlyName() const; void setFriendlyName( const QString& fname ) { m_friendlyname = fname; } + void setAvatar(const QPixmap &avatar); + const QPixmap avatar() const; collection_ptr collection() const; void addCollection( const Tomahawk::collection_ptr& c ); @@ -116,6 +118,8 @@ private: QString m_textStatus; ControlConnection* m_cc; + + QPixmap m_avatar; }; }; diff --git a/src/sourcetree/sourcetreeview.cpp b/src/sourcetree/sourcetreeview.cpp index 6693bd106..716d2cd18 100644 --- a/src/sourcetree/sourcetreeview.cpp +++ b/src/sourcetree/sourcetreeview.cpp @@ -537,17 +537,20 @@ SourceDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option, co SourceTreeItem* sti = SourcesModel::indexToTreeItem( index ); bool status = !( !sti || sti->source().isNull() || !sti->source()->isOnline() ); + QPixmap avatar( RESPATH "images/user-avatar.png" ); QString tracks; int figWidth = 0; - if ( status ) + if ( status && sti && !sti->source().isNull() ) { tracks = QString::number( sti->source()->trackCount() ); figWidth = painter->fontMetrics().width( tracks ); + if ( !sti->source()->avatar().isNull() ) + avatar = sti->source()->avatar(); } QRect iconRect = option.rect.adjusted( 4, 6, -option.rect.width() + option.rect.height() - 12 + 4, -6 ); - painter->drawPixmap( iconRect, QPixmap( RESPATH "images/user-avatar.png" ).scaledToHeight( iconRect.height(), Qt::SmoothTransformation ) ); + painter->drawPixmap( iconRect, avatar.scaledToHeight( iconRect.height(), Qt::SmoothTransformation ) ); if ( ( option.state & QStyle::State_Selected ) == QStyle::State_Selected ) { From ddb7e012df29295b56233208ae99ba2968880721 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 20 Apr 2011 21:12:04 +0200 Subject: [PATCH 4/8] sipjreen: Add AvatarManager class --- src/sip/jreen/CMakeLists.txt | 2 + src/sip/jreen/avatarmanager.cpp | 171 ++++++++++++++++++++++++++++++++ src/sip/jreen/avatarmanager.h | 43 ++++++++ 3 files changed, 216 insertions(+) create mode 100644 src/sip/jreen/avatarmanager.cpp create mode 100644 src/sip/jreen/avatarmanager.h diff --git a/src/sip/jreen/CMakeLists.txt b/src/sip/jreen/CMakeLists.txt index 7cf3d3dd2..e0aa1b0d0 100644 --- a/src/sip/jreen/CMakeLists.txt +++ b/src/sip/jreen/CMakeLists.txt @@ -11,6 +11,7 @@ set( jabberSources jabber_p.cpp tomahawksipmessage.cpp tomahawksipmessagefactory.cpp + avatarmanager.cpp ) set( jabberHeaders @@ -18,6 +19,7 @@ set( jabberHeaders jabber_p.h tomahawksipmessage.h tomahawksipmessagefactory.h + avatarmanager.h ) include_directories( . ${CMAKE_CURRENT_BINARY_DIR} .. diff --git a/src/sip/jreen/avatarmanager.cpp b/src/sip/jreen/avatarmanager.cpp new file mode 100644 index 000000000..366d805e1 --- /dev/null +++ b/src/sip/jreen/avatarmanager.cpp @@ -0,0 +1,171 @@ +#include "avatarmanager.h" + + +#include "utils/tomahawkutils.h" + +#include +#include +#include + +#include +#include +#include +#include + +AvatarManager::AvatarManager(Jreen::Client *client) : + m_cacheDir(TomahawkUtils::appDataDir().absolutePath().append("/jreen/")) +{ + m_client = client; + + m_cachedAvatars = m_cacheDir.entryList(); + + connect(m_client, SIGNAL(serverFeaturesReceived(QSet)), SLOT(onNewConnection())); + connect(m_client, SIGNAL(newPresence(Jreen::Presence)), SLOT(onNewPresence(Jreen::Presence))); + connect(m_client, SIGNAL(newIQ(Jreen::IQ)), SLOT(onNewIq(Jreen::IQ))); + + connect(this, SIGNAL(newAvatar(QString)), SLOT(onNewAvatar(QString))); +} + +AvatarManager::~AvatarManager() +{ +} + +void AvatarManager::onNewConnection() +{ + fetchVCard( m_client->jid().bare() ); +} + + +void AvatarManager::fetchVCard(const QString &jid) +{ + qDebug() << Q_FUNC_INFO; + + Jreen::IQ iq(Jreen::IQ::Get, jid ); + iq.addExtension(new Jreen::VCard()); + m_client->send( iq, this, SLOT( onNewIq( Jreen::IQ, int ) ), 0 ); +} + +void AvatarManager::onNewPresence(const Jreen::Presence& presence) +{ + Jreen::VCardUpdate::Ptr update = presence.findExtension(); + if(update) + { + qDebug() << "vcard: found update for " << presence.from().full(); + if(!isCached(update->photoHash())) + { + qDebug() << presence.from().full() << "vcard: photo not cached, starting request..." << update->photoHash(); + fetchVCard( presence.from().bare() ); + } + else + { + qDebug() << presence.from().full() << "vcard: photo already cached no request necessary " << update->photoHash(); + m_JidsAvatarHashes.insert( update->photoHash(), presence.from().bare() ); + + Q_ASSERT(!this->avatar(presence.from().bare()).isNull()); + emit newAvatar(presence.from().bare()); + } + } + else + { + qDebug() << Q_FUNC_INFO << presence.from().full() << "got no statusupdateextension"; + + //TODO: do we want this? might fetch avatars for broken clients + fetchVCard( presence.from().bare() ); + } +} + +void AvatarManager::onNewIq(const Jreen::IQ& iq, int context) +{ + Jreen::VCard *vcard = iq.findExtension().data(); + if(vcard) + { + iq.accept(); + + qDebug() << Q_FUNC_INFO << "Got vcard from " << iq.from().full(); + + QString id = iq.from().full(); + QString avatarHash; + + const Jreen::VCard::Photo &photo = vcard->photo(); + if (!photo.data().isEmpty()) { + qDebug() << "vcard: got photo data" << id; + + avatarHash = QCryptographicHash::hash(photo.data(), QCryptographicHash::Sha1).toHex(); + + if (!m_cacheDir.exists()) + m_cacheDir.mkpath( avatarDir( avatarHash ).absolutePath() ); + + + QFile file(avatarPath(avatarHash)); + if (file.open(QIODevice::WriteOnly)) { + file.write(photo.data()); + file.close(); + } + + m_cachedAvatars.append(avatarHash); + m_JidsAvatarHashes.insert( avatarHash, iq.from().bare() ); + + Q_ASSERT(!this->avatar(iq.from().bare()).isNull()); + emit newAvatar(iq.from().bare()); + } + else + { + qDebug() << "vcard: got no photo data" << id; + } + + // got own presence + if ( m_client->jid().bare() == id ) + { + qDebug() << Q_FUNC_INFO << "got own vcard"; + + Jreen::Presence presence = m_client->presence(); + Jreen::VCardUpdate::Ptr update = presence.findExtension(); + if (update->photoHash() != avatarHash) + { + qDebug() << Q_FUNC_INFO << "Updating own presence..."; + + update->setPhotoHash(avatarHash); + m_client->send(presence); + } + } + } +} + +QPixmap AvatarManager::avatar(const QString &jid) const +{ + if( isCached( avatarHash( jid ) ) ) + { + return QPixmap( avatarPath( avatarHash( jid ) ) ); + } + else + { + return QPixmap(); + } +} + +QString AvatarManager::avatarHash(const QString &jid) const +{ + //qDebug() << Q_FUNC_INFO << jid << m_JidsAvatarHashes.key(jid); + return m_JidsAvatarHashes.key(jid); +} + +QDir AvatarManager::avatarDir(const QString &avatarHash) const +{ + return m_cacheDir; +} + +QString AvatarManager::avatarPath(const QString &avatarHash) const +{ + Q_ASSERT(!avatarHash.contains("@")); + return avatarDir(avatarHash).absoluteFilePath(avatarHash); +} + +bool AvatarManager::isCached(const QString &avatarHash) const +{ + return m_cachedAvatars.contains( avatarHash ); +} + +void AvatarManager::onNewAvatar(const QString& jid) +{ + qDebug() << Q_FUNC_INFO << "Found new Avatar..." << jid; +} diff --git a/src/sip/jreen/avatarmanager.h b/src/sip/jreen/avatarmanager.h new file mode 100644 index 000000000..71852285c --- /dev/null +++ b/src/sip/jreen/avatarmanager.h @@ -0,0 +1,43 @@ +#ifndef AVATARMANAGER_H +#define AVATARMANAGER_H + +#include + +#include +#include + + +class AvatarManager : public QObject +{ +Q_OBJECT + +public: + AvatarManager(Jreen::Client *client); + virtual ~AvatarManager(); + + QPixmap avatar(const QString &jid) const; + +signals: + void newAvatar( const QString &jid ); + +private slots: + void onNewPresence( const Jreen::Presence& presence ); + void onNewIq(const Jreen::IQ &iq, int context = 0 ); + void onNewConnection(); + void onNewAvatar( const QString &jid ); + +private: + void fetchVCard( const QString &jid); + QString avatarHash(const QString &jid) const; + QString avatarPath(const QString &avatarHash) const; + + QDir avatarDir(const QString &avatarHash) const; + bool isCached(const QString &avatarHash) const; + + Jreen::Client *m_client; + QStringList m_cachedAvatars; + QDir m_cacheDir; + QMap m_JidsAvatarHashes; +}; + +#endif // AVATARMANAGER_H From d9a4b71414c86264d3ca8639f5ebf104b09b9c32 Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 20 Apr 2011 21:26:16 +0200 Subject: [PATCH 5/8] Use the AvatarManager and show avatars in the MainWindow. --- src/sip/jreen/jabber.cpp | 1 + src/sip/jreen/jabber_p.cpp | 42 ++++++++++++++++++++++++-------------- src/sip/jreen/jabber_p.h | 9 ++++---- 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/sip/jreen/jabber.cpp b/src/sip/jreen/jabber.cpp index a4b0f1aab..e6982857b 100644 --- a/src/sip/jreen/jabber.cpp +++ b/src/sip/jreen/jabber.cpp @@ -110,6 +110,7 @@ JabberPlugin::connectPlugin( bool startup ) QObject::connect( p, SIGNAL( disconnected() ), SLOT( onDisconnected() ) ); QObject::connect( p, SIGNAL( authError( int, QString ) ), SLOT( onAuthError( int, QString ) ) ); + QObject::connect( p, SIGNAL( avatarReceived( QString, QPixmap ) ), SIGNAL( avatarReceived( QString, QPixmap ) ) ); return true; } diff --git a/src/sip/jreen/jabber_p.cpp b/src/sip/jreen/jabber_p.cpp index 93efa5a06..ea5add54a 100644 --- a/src/sip/jreen/jabber_p.cpp +++ b/src/sip/jreen/jabber_p.cpp @@ -70,8 +70,8 @@ Jabber_p::Jabber_p( const QString& jid, const QString& password, const QString& // add VCardUpdate extension to own presence m_client->presence().addExtension( new Jreen::VCardUpdate() ); - // read cached avatars - m_photoHashes = QDir("/home/domme/jreen/").entryList(); + // initialize the AvatarManager + m_avatarManager = new AvatarManager(m_client); // setup disco m_client->disco()->setSoftwareVersion( "Tomahawk Player", TOMAHAWK_VERSION, CMAKE_SYSTEM ); @@ -96,6 +96,8 @@ Jabber_p::Jabber_p( const QString& jid, const QString& password, const QString& connect(m_client, SIGNAL(newPresence(Jreen::Presence)), SLOT(onNewPresence(Jreen::Presence))); connect(m_client, SIGNAL(newIQ(Jreen::IQ)), SLOT(onNewIq(Jreen::IQ))); + connect(m_avatarManager, SIGNAL(newAvatar(QString)), SLOT(onNewAvatar(QString))); + // connect qDebug() << "Connecting to the XMPP server..."; @@ -226,9 +228,6 @@ Jabber_p::onConnect() // set presence to least valid value m_client->setPresence(Jreen::Presence::XA, "Got Tomahawk? http://gettomahawk.com", -127); - // request own vcard - fetchVCard( m_jid.bare() ); - // set ping timeout to 15 secs (TODO: verify if this works) m_client->setPingInterval(15000); @@ -351,16 +350,6 @@ void Jabber_p::onNewPresence( const Jreen::Presence& presence) qDebug() << Q_FUNC_INFO << "* New presence: " << fulljid << presence.subtype(); - Jreen::VCardUpdate::Ptr update = presence.findExtension(); - if(update) - { - qDebug() << "vcard: found update for " << fulljid; - if(!m_photoHashes.contains(update->photoHash())) - { - fetchVCard( jid.bare() ); - } - } - if( jid == m_jid ) return; @@ -536,10 +525,33 @@ Jabber_p::handlePeerStatus( const Jreen::JID& jid, Jreen::Presence::Type presenc { m_peers[ fulljid ] = presenceType; qDebug() << Q_FUNC_INFO << "* Peer goes online:" << fulljid; + emit peerOnline( fulljid ); + + if(!m_avatarManager->avatar(jid.bare()).isNull()) + onNewAvatar( jid.bare() ); + return; } //qDebug() << "Updating presence data for" << fulljid; m_peers[ fulljid ] = presenceType; } + +void Jabber_p::onNewAvatar(const QString& jid) +{ + qDebug() << Q_FUNC_INFO << jid; + Q_ASSERT(!m_avatarManager->avatar( jid ).isNull()); + + // find peers for the jid + QStringList peers = m_peers.keys(); + foreach(const QString &peer, peers) + { + if( peer.startsWith(jid) ) + { + emit avatarReceived ( peer, m_avatarManager->avatar( jid ) ); + } + } + + emit avatarReceived ( jid, m_avatarManager->avatar( jid ) ); +} diff --git a/src/sip/jreen/jabber_p.h b/src/sip/jreen/jabber_p.h index 0fd354467..2d138b788 100644 --- a/src/sip/jreen/jabber_p.h +++ b/src/sip/jreen/jabber_p.h @@ -22,6 +22,8 @@ #include "../sipdllmacro.h" +#include "avatarmanager.h" + #include #include #include @@ -63,6 +65,7 @@ signals: void connected(); void disconnected(); void jidChanged( const QString& ); + void avatarReceived( const QString&, const QPixmap& avatar ); void authError( int, const QString& ); public slots: @@ -82,6 +85,7 @@ private slots: qDebug() << e; } virtual void onNewIq( const Jreen::IQ &iq, int context = NoContext ); + virtual void onNewAvatar( const QString &jid ); private: bool presenceMeansOnline( Jreen::Presence::Type p ); @@ -99,10 +103,7 @@ private: QStringList m_legacy_peers; - - //sort out - //QHash m_contactsPhotoHashes; - QStringList m_photoHashes; + AvatarManager *m_avatarManager; }; #endif // JABBER_H From 84019e5d115a480ba33217f414fc41b892a137bd Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Wed, 20 Apr 2011 21:43:14 +0200 Subject: [PATCH 6/8] Add DLLEXPORT macro to SipHandler --- src/libtomahawk/sip/SipHandler.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libtomahawk/sip/SipHandler.h b/src/libtomahawk/sip/SipHandler.h index d394ea5d1..cbef72f5d 100644 --- a/src/libtomahawk/sip/SipHandler.h +++ b/src/libtomahawk/sip/SipHandler.h @@ -20,6 +20,7 @@ #define SIPHANDLER_H #include "sip/SipPlugin.h" +#include "dllmacro.h" #include #include @@ -27,7 +28,7 @@ #include #include -class SipHandler : public QObject +class DLLEXPORT SipHandler : public QObject { Q_OBJECT From 3182a294d7749b79f0d8722bc5af28d0c5575a07 Mon Sep 17 00:00:00 2001 From: Frank Osterfeld Date: Wed, 20 Apr 2011 23:30:44 +0200 Subject: [PATCH 7/8] Do not truncate FLAC playback. If "finish" is set, play until the buffer is empty. --- src/libtomahawk/audio/flactranscode.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libtomahawk/audio/flactranscode.cpp b/src/libtomahawk/audio/flactranscode.cpp index c66c5a557..22f339c49 100644 --- a/src/libtomahawk/audio/flactranscode.cpp +++ b/src/libtomahawk/audio/flactranscode.cpp @@ -70,7 +70,7 @@ FLACTranscode::processData( const QByteArray& data, bool finish ) m_buffer.append( data ); m_mutex.unlock(); - while ( m_buffer.size() >= FLAC_BUFFER ) + while ( m_buffer.size() >= FLAC_BUFFER || ( finish && !m_buffer.isEmpty() ) ) { process_single(); } From 3e20fd1f6a3e6bec4fdffb050d2112176e7306ed Mon Sep 17 00:00:00 2001 From: Dominik Schmidt Date: Thu, 21 Apr 2011 13:42:16 +0200 Subject: [PATCH 8/8] Let SipHandler set the avatar for MyCollection --- src/libtomahawk/sip/SipHandler.cpp | 7 +++++++ src/libtomahawk/sip/SipHandler.h | 7 ++++++- src/libtomahawk/sip/SipPlugin.h | 5 +++++ src/sip/jreen/jabber.cpp | 1 + src/sip/jreen/jabber_p.cpp | 7 ++++++- src/sip/jreen/jabber_p.h | 1 + 6 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/libtomahawk/sip/SipHandler.cpp b/src/libtomahawk/sip/SipHandler.cpp index 0170bdf64..a3b7b0375 100644 --- a/src/libtomahawk/sip/SipHandler.cpp +++ b/src/libtomahawk/sip/SipHandler.cpp @@ -179,6 +179,7 @@ SipHandler::loadPlugin( const QString& path ) QObject::connect( sip, SIGNAL( error( int, QString ) ), SLOT( onError( int, QString ) ) ); QObject::connect( sip, SIGNAL( avatarReceived( QString, QPixmap ) ), SLOT( onAvatarReceived( QString, QPixmap ) ) ); + QObject::connect( sip, SIGNAL( avatarReceived( QPixmap ) ), SLOT( onAvatarReceived( QPixmap ) ) ); m_plugins << sip; } } @@ -411,3 +412,9 @@ void SipHandler::onAvatarReceived( const QString& from, const QPixmap& avatar ) qDebug() << Q_FUNC_INFO << from << "no control connection setup yet"; } } + +void SipHandler::onAvatarReceived( const QPixmap& avatar ) +{ + qDebug() << Q_FUNC_INFO << "Set own avatar on MyCollection"; + SourceList::instance()->getLocal()->setAvatar( avatar ); +} diff --git a/src/libtomahawk/sip/SipHandler.h b/src/libtomahawk/sip/SipHandler.h index cbef72f5d..1c1c6f5bc 100644 --- a/src/libtomahawk/sip/SipHandler.h +++ b/src/libtomahawk/sip/SipHandler.h @@ -63,7 +63,12 @@ private slots: void onSettingsChanged(); - void onAvatarReceived( const QString& from, const QPixmap& avatar = QPixmap()); + // set data for local source + void onAvatarReceived( const QPixmap& avatar ); + + // set data for other sources + void onAvatarReceived( const QString& from, const QPixmap& avatar ); + private: static SipHandler *s_instance; diff --git a/src/libtomahawk/sip/SipPlugin.h b/src/libtomahawk/sip/SipPlugin.h index 28e19ffb2..4bd55fc31 100644 --- a/src/libtomahawk/sip/SipPlugin.h +++ b/src/libtomahawk/sip/SipPlugin.h @@ -58,8 +58,13 @@ signals: void peerOffline( const QString& ); void msgReceived( const QString& from, const QString& msg ); + // new data for own source + void avatarReceived ( const QPixmap& avatar ); + + // new data for other sources; void avatarReceived ( const QString& from, const QPixmap& avatar); + void addMenu( QMenu* menu ); void removeMenu( QMenu* menu ); }; diff --git a/src/sip/jreen/jabber.cpp b/src/sip/jreen/jabber.cpp index e6982857b..7e0b1235e 100644 --- a/src/sip/jreen/jabber.cpp +++ b/src/sip/jreen/jabber.cpp @@ -111,6 +111,7 @@ JabberPlugin::connectPlugin( bool startup ) QObject::connect( p, SIGNAL( authError( int, QString ) ), SLOT( onAuthError( int, QString ) ) ); QObject::connect( p, SIGNAL( avatarReceived( QString, QPixmap ) ), SIGNAL( avatarReceived( QString, QPixmap ) ) ); + QObject::connect( p, SIGNAL( avatarReceived( QPixmap ) ), SIGNAL( avatarReceived( QPixmap) ) ); return true; } diff --git a/src/sip/jreen/jabber_p.cpp b/src/sip/jreen/jabber_p.cpp index ea5add54a..100ae908c 100644 --- a/src/sip/jreen/jabber_p.cpp +++ b/src/sip/jreen/jabber_p.cpp @@ -553,5 +553,10 @@ void Jabber_p::onNewAvatar(const QString& jid) } } - emit avatarReceived ( jid, m_avatarManager->avatar( jid ) ); + if( jid == m_client->jid().bare() ) + // own avatar + emit avatarReceived ( m_avatarManager->avatar( jid ) ); + else + // someone else's avatar + emit avatarReceived ( jid, m_avatarManager->avatar( jid ) ); } diff --git a/src/sip/jreen/jabber_p.h b/src/sip/jreen/jabber_p.h index 2d138b788..243e255a9 100644 --- a/src/sip/jreen/jabber_p.h +++ b/src/sip/jreen/jabber_p.h @@ -65,6 +65,7 @@ signals: void connected(); void disconnected(); void jidChanged( const QString& ); + void avatarReceived( const QPixmap& avatar ); void avatarReceived( const QString&, const QPixmap& avatar ); void authError( int, const QString& );