mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-21 21:25:52 +02:00
Merge branch 'master' of github.com:tomahawk-player/tomahawk
Conflicts: src/libtomahawk/tomahawksettings.cpp src/libtomahawk/tomahawksettings.h src/sip/jreen/jabber.cpp src/sip/jreen/jabber.h src/tomahawkapp.cpp src/tomahawkwindow.h thirdparty/jreen
This commit is contained in:
@@ -39,6 +39,11 @@ INCLUDE( MacroLogFeature )
|
||||
set(LIBLASTFM_FOUND true)
|
||||
|
||||
find_package(Phonon REQUIRED)
|
||||
if(PHONON_VERSION STRLESS "4.5.0")
|
||||
message(FATAL_ERROR "Phonon version 4.5.0 or higher is required, you have version ${PHONON_VERSION}")
|
||||
else()
|
||||
message(STATUS "Phonon found; ensure that phonon-vlc is at least 0.4")
|
||||
endif()
|
||||
|
||||
macro_optional_find_package(LibEchonest 1.1.1)
|
||||
macro_log_feature(LIBECHONEST_FOUND "Echonest" "Qt library for communicating with The Echo Nest" "http://projects.kde.org/libechonest" TRUE "" "libechonest is needed for dynamic playlists and the infosystem")
|
||||
|
@@ -31,11 +31,11 @@ else(PHONON_FOUND)
|
||||
endif(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
|
||||
# As discussed on kde-buildsystem: first look at CMAKE_PREFIX_PATH, then at the suggested PATHS (kde4 install dir)
|
||||
find_library(PHONON_LIBRARY NAMES phonon phonon4 PATHS ${KDE4_LIB_INSTALL_DIR} ${QT_LIBRARY_DIR} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
|
||||
find_library(PHONON_LIBRARY NAMES phonon phonon4 PATHS ${KDE4_LIB_INSTALL_DIR} ${QT_LIBRARY_DIR})
|
||||
# then at the default system locations (CMAKE_SYSTEM_PREFIX_PATH, i.e. /usr etc.)
|
||||
find_library(PHONON_LIBRARY NAMES phonon phonon4)
|
||||
|
||||
find_path(PHONON_INCLUDE_DIR NAMES phonon/phonon_export.h PATHS ${KDE4_INCLUDE_INSTALL_DIR} ${QT_INCLUDE_DIR} ${INCLUDE_INSTALL_DIR} ${QT_LIBRARY_DIR} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH)
|
||||
find_path(PHONON_INCLUDE_DIR NAMES phonon/phonon_export.h PATHS ${KDE4_INCLUDE_INSTALL_DIR} ${QT_INCLUDE_DIR} ${INCLUDE_INSTALL_DIR} ${QT_LIBRARY_DIR})
|
||||
find_path(PHONON_INCLUDE_DIR NAMES phonon/phonon_export.h)
|
||||
|
||||
if(PHONON_INCLUDE_DIR AND PHONON_LIBRARY)
|
||||
|
@@ -39,6 +39,7 @@ SET( tomahawkSources ${tomahawkSources}
|
||||
|
||||
musicscanner.cpp
|
||||
shortcuthandler.cpp
|
||||
globalactionmanager.cpp
|
||||
scanmanager.cpp
|
||||
tomahawkapp.cpp
|
||||
main.cpp
|
||||
@@ -83,6 +84,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
||||
musicscanner.h
|
||||
scanmanager.h
|
||||
shortcuthandler.h
|
||||
globalactionmanager.h
|
||||
)
|
||||
|
||||
IF(LIBLASTFM_FOUND)
|
||||
|
360
src/globalactionmanager.cpp
Normal file
360
src/globalactionmanager.cpp
Normal file
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include "globalactionmanager.h"
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "utils/xspfloader.h"
|
||||
#include "sourcelist.h"
|
||||
#include "playlist/dynamic/GeneratorInterface.h"
|
||||
#include "viewmanager.h"
|
||||
#include "playlist/topbar/topbar.h"
|
||||
#include "pipeline.h"
|
||||
#include "database/localcollection.h"
|
||||
#include "playlist/playlistview.h"
|
||||
#include "echonest/Playlist.h"
|
||||
|
||||
#include <QUrl>
|
||||
#include <Playlist.h>
|
||||
|
||||
GlobalActionManager* GlobalActionManager::s_instance = 0;
|
||||
|
||||
GlobalActionManager*
|
||||
GlobalActionManager::instance()
|
||||
{
|
||||
if( !s_instance )
|
||||
s_instance = new GlobalActionManager;
|
||||
|
||||
return s_instance;
|
||||
}
|
||||
|
||||
|
||||
GlobalActionManager::GlobalActionManager( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
GlobalActionManager::~GlobalActionManager()
|
||||
{}
|
||||
|
||||
bool
|
||||
GlobalActionManager::parseTomahawkLink( const QString& url )
|
||||
{
|
||||
if( url.contains( "tomahawk://" ) ) {
|
||||
QString cmd = url.mid( 11 );
|
||||
qDebug() << "Parsing tomahawk link command" << cmd;
|
||||
|
||||
QString cmdType = cmd.split( "/" ).first();
|
||||
QUrl u( cmd );
|
||||
|
||||
// for backwards compatibility
|
||||
if( cmdType == "load" ) {
|
||||
if( u.hasQueryItem( "xspf" ) ) {
|
||||
QUrl xspf = QUrl::fromUserInput( u.queryItemValue( "xspf" ) );
|
||||
XSPFLoader* l = new XSPFLoader( true, this );
|
||||
qDebug() << "Loading spiff:" << xspf.toString();
|
||||
l->load( xspf );
|
||||
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), ViewManager::instance(), SLOT( show( Tomahawk::playlist_ptr ) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if( cmdType == "playlist" ) {
|
||||
return handlePlaylistCommand( u );
|
||||
} else if( cmdType == "collection" ) {
|
||||
return handleCollectionCommand( u );
|
||||
} else if( cmdType == "queue" ) {
|
||||
return handleQueueCommand( u );
|
||||
} else if( cmdType == "station" ) {
|
||||
return handleStationCommand( u );
|
||||
} else if( cmdType == "search" ) {
|
||||
return handleSearchCommand( u );
|
||||
} else if( cmdType == "play" ) {
|
||||
return handlePlayCommand( u );
|
||||
} else {
|
||||
qDebug() << "Tomahawk link not supported, command not known!" << cmdType << u.path();
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Not a tomahawk:// link!";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handlePlaylistCommand( const QUrl& url )
|
||||
{
|
||||
QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command
|
||||
if( parts.isEmpty() ) {
|
||||
qDebug() << "No specific playlist command:" << url.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parts[ 0 ] == "import" ) {
|
||||
if( !url.hasQueryItem( "xspf" ) ) {
|
||||
qDebug() << "No xspf to load..";
|
||||
return false;
|
||||
}
|
||||
QUrl xspf = QUrl( url.queryItemValue( "xspf" ) );
|
||||
QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString();
|
||||
XSPFLoader* l= new XSPFLoader( true, this );
|
||||
l->setOverrideTitle( title );
|
||||
l->load( xspf );
|
||||
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), ViewManager::instance(), SLOT( show( Tomahawk::playlist_ptr ) ) );
|
||||
|
||||
} else if( parts [ 0 ] == "new" ) {
|
||||
if( !url.hasQueryItem( "title" ) ) {
|
||||
qDebug() << "New playlist command needs a title...";
|
||||
return false;
|
||||
}
|
||||
Tomahawk::playlist_ptr pl = Tomahawk::Playlist::create( SourceList::instance()->getLocal(), uuid(), url.queryItemValue( "title" ), QString(), QString(), false );
|
||||
pl->createNewRevision( uuid(), pl->currentrevision(), QList< Tomahawk::plentry_ptr >() );
|
||||
ViewManager::instance()->show( pl );
|
||||
} else if( parts[ 0 ] == "add" ) {
|
||||
if( !url.hasQueryItem( "playlistid" ) || !url.hasQueryItem( "track" ) || !url.hasQueryItem( "artist" ) ) {
|
||||
qDebug() << "Add to playlist command needs playlistid, track, and artist..." << url.toString();
|
||||
return false;
|
||||
}
|
||||
// TODO implement. Let the user select what playlist to add to
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleCollectionCommand( const QUrl& url )
|
||||
{
|
||||
QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command
|
||||
if( parts.isEmpty() ) {
|
||||
qDebug() << "No specific collection command:" << url.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parts[ 0 ] == "add" ) {
|
||||
// TODO implement
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleQueueCommand( const QUrl& url )
|
||||
{
|
||||
QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command
|
||||
if( parts.isEmpty() ) {
|
||||
qDebug() << "No specific queue command:" << url.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parts[ 0 ] == "add" ) {
|
||||
if( parts.size() > 1 && parts[ 1 ] == "track" ) {
|
||||
QPair< QString, QString > pair;
|
||||
foreach( pair, url.queryItems() ) {
|
||||
if( pair.first != "url" )
|
||||
continue;
|
||||
QUrl track = QUrl::fromUserInput( pair.second );
|
||||
//FIXME: isLocalFile is Qt 4.8
|
||||
if( track.toString().startsWith( "file://" ) ) { // it's local, so we see if it's in the DB and load it if so
|
||||
// TODO
|
||||
} else { // give it a web result hint
|
||||
// TODO actually read the tags
|
||||
QFileInfo info( track.path() );
|
||||
Tomahawk::query_ptr q = Tomahawk::Query::get( QString(), info.baseName(), QString() );
|
||||
q->setResultHint( track.toString() );
|
||||
Tomahawk::Pipeline::instance()->resolve( q, true );
|
||||
|
||||
ViewManager::instance()->queue()->model()->append( q );
|
||||
ViewManager::instance()->showQueue();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Only queue/add/track is support at the moment, got:" << parts;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleSearchCommand( const QUrl& url )
|
||||
{
|
||||
// open the super collection and set this as the search filter
|
||||
QStringList query;
|
||||
if( url.hasQueryItem( "artist" ) )
|
||||
query << url.queryItemValue( "artist" );
|
||||
if( url.hasQueryItem( "album" ) )
|
||||
query << url.queryItemValue( "album" );
|
||||
if( url.hasQueryItem( "track" ) )
|
||||
query << url.queryItemValue( "track" );
|
||||
QString queryStr = query.join( " " );
|
||||
|
||||
if( queryStr.isEmpty() )
|
||||
return false;
|
||||
|
||||
ViewManager::instance()->showSuperCollection();
|
||||
ViewManager::instance()->topbar()->setFilter( queryStr );
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handleStationCommand( const QUrl& url )
|
||||
{
|
||||
QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command
|
||||
if( parts.isEmpty() ) {
|
||||
qDebug() << "No specific station command:" << url.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parts[ 0 ] == "create" ) {
|
||||
if( !url.hasQueryItem( "title" ) || !url.hasQueryItem( "type" ) ) {
|
||||
qDebug() << "Station create command needs title and type..." << url.toString();
|
||||
return false;
|
||||
}
|
||||
QString title = url.queryItemValue( "title" );
|
||||
QString type = url.queryItemValue( "type" );
|
||||
Tomahawk::dynplaylist_ptr pl = Tomahawk::DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), title, QString(), QString(), Tomahawk::OnDemand, false, type );
|
||||
QList< Tomahawk::dyncontrol_ptr > controls;
|
||||
QPair< QString, QString > param;
|
||||
foreach( param, url.queryItems() ) {
|
||||
if( param.first == "artist" ) {
|
||||
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist" );
|
||||
c->setInput( param.second );
|
||||
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistRadioType ) );
|
||||
controls << c;
|
||||
} /*else if( param.first == "hotttnesss" ) { TODO
|
||||
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist" );
|
||||
c->setInput( param.second );
|
||||
c->setMatch( 0 );
|
||||
controls << c;
|
||||
} */
|
||||
}
|
||||
pl->createNewRevision( uuid(), pl->currentrevision(), type, controls );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
GlobalActionManager::handlePlayCommand( const QUrl& url )
|
||||
{
|
||||
QStringList parts = url.path().split( "/" ).mid( 1 ); // get the rest of the command
|
||||
if( parts.isEmpty() ) {
|
||||
qDebug() << "No specific play command:" << url.toString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if( parts[ 0 ] == "track" ) {
|
||||
QPair< QString, QString > pair;
|
||||
QString title, artist, album, urlStr;
|
||||
foreach( pair, url.queryItems() ) {
|
||||
if( pair.first == "track" )
|
||||
title = pair.second;
|
||||
else if( pair.first == "artist" )
|
||||
artist = pair.second;
|
||||
else if( pair.first == "album" )
|
||||
album = pair.second;
|
||||
else if( pair.first == "url" )
|
||||
urlStr = pair.second;
|
||||
}
|
||||
Tomahawk::query_ptr q = Tomahawk::Query::get( artist, title, album );
|
||||
if( !urlStr.isEmpty() )
|
||||
q->setResultHint( urlStr );
|
||||
Tomahawk::Pipeline::instance()->resolve( q, true );
|
||||
|
||||
// now we add it to the special "bookmarks" playlist, creating it if it doesn't exist. if nothing is playing, start playing the track
|
||||
QSharedPointer< LocalCollection > col = SourceList::instance()->getLocal()->collection().dynamicCast< LocalCollection >();
|
||||
Tomahawk::playlist_ptr bookmarkpl = col->bookmarksPlaylist();
|
||||
if( bookmarkpl.isNull() ) { // create it and do the deed then
|
||||
m_waitingToBookmark = q;
|
||||
col->createBookmarksPlaylist();
|
||||
connect( col.data(), SIGNAL( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), this, SLOT( bookmarkPlaylistCreated( Tomahawk::playlist_ptr ) ), Qt::UniqueConnection );
|
||||
} else {
|
||||
doBookmark( bookmarkpl, q );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl )
|
||||
{
|
||||
Q_ASSERT( !m_waitingToBookmark.isNull() );
|
||||
doBookmark( pl, m_waitingToBookmark );
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q )
|
||||
{
|
||||
Tomahawk::plentry_ptr e( new Tomahawk::PlaylistEntry );
|
||||
e->setGuid( uuid() );
|
||||
|
||||
if ( q->results().count() )
|
||||
e->setDuration( q->results().at( 0 )->duration() );
|
||||
else
|
||||
e->setDuration( 0 );
|
||||
|
||||
e->setLastmodified( 0 );
|
||||
e->setAnnotation( "" ); // FIXME
|
||||
e->setQuery( q );
|
||||
|
||||
pl->createNewRevision( uuid(), pl->currentrevision(), QList< Tomahawk::plentry_ptr >( pl->entries() ) << e );
|
||||
connect( pl.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( showPlaylist() ) );
|
||||
|
||||
m_toShow = pl;
|
||||
|
||||
// if nothing is playing, lets start this
|
||||
// TODO
|
||||
if( !AudioEngine::instance()->isPlaying() ) {
|
||||
connect( q.data(), SIGNAL( resolvingFinished( bool ) ), this, SLOT( waitingForResolved( bool ) ) );
|
||||
m_waitingToPlay = q;
|
||||
}
|
||||
|
||||
m_waitingToBookmark.clear();
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::showPlaylist()
|
||||
{
|
||||
if( m_toShow.isNull() )
|
||||
return;
|
||||
|
||||
ViewManager::instance()->show( m_toShow );
|
||||
|
||||
m_toShow.clear();
|
||||
}
|
||||
|
||||
void
|
||||
GlobalActionManager::waitingForResolved( bool success )
|
||||
{
|
||||
if( success && !m_waitingToPlay.isNull() && !m_waitingToPlay->results().isEmpty() ) { // play it!
|
||||
AudioEngine::instance()->playItem( AudioEngine::instance()->playlist(), m_waitingToPlay->results().first() );
|
||||
}
|
||||
|
||||
m_waitingToPlay.clear();
|
||||
}
|
||||
|
||||
|
61
src/globalactionmanager.h
Normal file
61
src/globalactionmanager.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GLOBALACTIONMANAGER_H
|
||||
#define GLOBALACTIONMANAGER_H
|
||||
|
||||
#include "playlist.h"
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
class GlobalActionManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
static GlobalActionManager* instance();
|
||||
virtual ~GlobalActionManager();
|
||||
|
||||
public slots:
|
||||
bool parseTomahawkLink( const QString& link );
|
||||
void waitingForResolved( bool );
|
||||
|
||||
private slots:
|
||||
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl );
|
||||
void showPlaylist();
|
||||
|
||||
private:
|
||||
explicit GlobalActionManager( QObject* parent = 0 );
|
||||
void doBookmark( const Tomahawk::playlist_ptr& pl, const Tomahawk::query_ptr& q );
|
||||
|
||||
bool handlePlaylistCommand( const QUrl& url );
|
||||
bool handleCollectionCommand(const QUrl& url );
|
||||
bool handleQueueCommand(const QUrl& url );
|
||||
bool handleStationCommand(const QUrl& url );
|
||||
bool handleSearchCommand(const QUrl& url );
|
||||
bool handlePlayCommand(const QUrl& url );
|
||||
|
||||
Tomahawk::playlist_ptr m_toShow;
|
||||
Tomahawk::query_ptr m_waitingToBookmark;
|
||||
Tomahawk::query_ptr m_waitingToPlay;
|
||||
|
||||
static GlobalActionManager* s_instance;
|
||||
};
|
||||
|
||||
#endif // GLOBALACTIONMANAGER_H
|
@@ -21,6 +21,7 @@ set( libSources
|
||||
artist.cpp
|
||||
album.cpp
|
||||
collection.cpp
|
||||
webcollection.cpp
|
||||
playlist.cpp
|
||||
resolver.cpp
|
||||
query.cpp
|
||||
@@ -38,6 +39,7 @@ set( libSources
|
||||
database/database.cpp
|
||||
database/fuzzyindex.cpp
|
||||
database/databasecollection.cpp
|
||||
database/localcollection.cpp
|
||||
database/databaseworker.cpp
|
||||
database/databaseimpl.cpp
|
||||
database/databaseresolver.cpp
|
||||
@@ -66,7 +68,6 @@ set( libSources
|
||||
database/databasecommand_renameplaylist.cpp
|
||||
database/databasecommand_loadops.cpp
|
||||
database/databasecommand_updatesearchindex.cpp
|
||||
database/databasecollection.cpp
|
||||
database/databasecommand_setdynamicplaylistrevision.cpp
|
||||
database/databasecommand_createdynamicplaylist.cpp
|
||||
database/databasecommand_loaddynamicplaylist.cpp
|
||||
@@ -79,6 +80,7 @@ set( libSources
|
||||
|
||||
infosystem/infosystemcache.cpp
|
||||
infosystem/infosystem.cpp
|
||||
infosystem/infosystemworker.cpp
|
||||
infosystem/infoplugins/echonestplugin.cpp
|
||||
infosystem/infoplugins/lastfmplugin.cpp
|
||||
infosystem/infoplugins/musixmatchplugin.cpp
|
||||
@@ -174,6 +176,7 @@ set( libHeaders
|
||||
|
||||
aclsystem.h
|
||||
collection.h
|
||||
webcollection.h
|
||||
query.h
|
||||
resolver.h
|
||||
result.h
|
||||
@@ -223,6 +226,7 @@ set( libHeaders
|
||||
database/databasecommand_loadops.h
|
||||
database/databasecommand_updatesearchindex.h
|
||||
database/databasecollection.h
|
||||
database/localcollection.h
|
||||
database/databasecommand_setdynamicplaylistrevision.h
|
||||
database/databasecommand_createdynamicplaylist.h
|
||||
database/databasecommand_loaddynamicplaylist.h
|
||||
@@ -233,6 +237,7 @@ set( libHeaders
|
||||
database/databasecommand_clientauthvalid.h
|
||||
|
||||
infosystem/infosystem.h
|
||||
infosystem/infosystemworker.h
|
||||
infosystem/infosystemcache.h
|
||||
infosystem/infoplugins/echonestplugin.h
|
||||
infosystem/infoplugins/lastfmplugin.h
|
||||
|
@@ -113,12 +113,6 @@ AudioEngine::stop()
|
||||
m_expectStop = true;
|
||||
m_mediaObject->stop();
|
||||
|
||||
if ( !m_input.isNull() )
|
||||
{
|
||||
m_input->close();
|
||||
m_input.clear();
|
||||
}
|
||||
|
||||
setCurrentTrack( Tomahawk::result_ptr() );
|
||||
emit stopped();
|
||||
}
|
||||
@@ -198,8 +192,6 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
m_expectStop = true;
|
||||
}
|
||||
|
||||
m_input = io;
|
||||
|
||||
if ( !m_currentTrack->url().startsWith( "http://" ) )
|
||||
{
|
||||
m_mediaObject->setCurrentSource( io.data() );
|
||||
@@ -215,6 +207,9 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
}
|
||||
m_mediaObject->setCurrentSource( furl );
|
||||
}
|
||||
|
||||
m_input = io;
|
||||
|
||||
m_mediaObject->currentSource().setAutoDelete( true );
|
||||
m_mediaObject->play();
|
||||
|
||||
|
@@ -41,7 +41,7 @@ DatabaseCommand_Resolve::exec( DatabaseImpl* lib )
|
||||
{
|
||||
qDebug() << "Using result-hint to speed up resolving:" << m_query->resultHint();
|
||||
|
||||
Tomahawk::result_ptr result = lib->result( m_query->resultHint() );
|
||||
Tomahawk::result_ptr result = lib->resultFromHint( m_query );
|
||||
if ( !result.isNull() && result->collection()->source()->isOnline() )
|
||||
{
|
||||
res << result;
|
||||
@@ -119,7 +119,7 @@ DatabaseCommand_Resolve::exec( DatabaseImpl* lib )
|
||||
s = SourceList::instance()->get( files_query.value( 13 ).toUInt() );
|
||||
if( s.isNull() )
|
||||
{
|
||||
Q_ASSERT( false );
|
||||
qDebug() << "WTF: Could not find source" << files_query.value( 13 ).toUInt();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -149,6 +149,8 @@ DatabaseCommand_SetPlaylistRevision::exec( DatabaseImpl* lib )
|
||||
QString resultHint;
|
||||
if ( !e->query()->results().isEmpty() )
|
||||
resultHint = e->query()->results().first()->url();
|
||||
else if ( !e->query()->resultHint().isEmpty() )
|
||||
resultHint = e->query()->resultHint();
|
||||
|
||||
adde.bindValue( 0, e->guid() );
|
||||
adde.bindValue( 1, m_playlistguid );
|
||||
|
@@ -528,8 +528,9 @@ DatabaseImpl::album( int id )
|
||||
|
||||
|
||||
Tomahawk::result_ptr
|
||||
DatabaseImpl::result( const QString& url )
|
||||
DatabaseImpl::resultFromHint( const Tomahawk::query_ptr& origquery )
|
||||
{
|
||||
QString url = origquery->resultHint();
|
||||
TomahawkSqlQuery query = newquery();
|
||||
Tomahawk::source_ptr s;
|
||||
Tomahawk::result_ptr res;
|
||||
@@ -552,7 +553,18 @@ DatabaseImpl::result( const QString& url )
|
||||
else
|
||||
{
|
||||
// Q_ASSERT( false );
|
||||
qDebug() << "We don't support non-servent / non-file result-hints yet.";
|
||||
// qDebug() << "We don't support non-servent / non-file result-hints yet.";
|
||||
res = Tomahawk::result_ptr( new Tomahawk::Result() );
|
||||
s = SourceList::instance()->webSource();
|
||||
res->setUrl( url );
|
||||
res->setCollection( s->collection() );
|
||||
res->setRID( uuid() );
|
||||
res->setScore( 1.0 );
|
||||
res->setArtist( Tomahawk::artist_ptr( new Tomahawk::Artist( 0, origquery->artist() ) ) );
|
||||
res->setAlbum( Tomahawk::album_ptr( new Tomahawk::Album( 0, origquery->album(), res->artist() ) ) );
|
||||
res->setTrack( origquery->track() );
|
||||
res->setDuration( origquery->duration() );
|
||||
res->setFriendlySource( url );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@@ -64,7 +64,7 @@ public:
|
||||
QVariantMap album( int id );
|
||||
QVariantMap track( int id );
|
||||
Tomahawk::result_ptr file( int fid );
|
||||
Tomahawk::result_ptr result( const QString& url );
|
||||
Tomahawk::result_ptr resultFromHint( const Tomahawk::query_ptr& query );
|
||||
|
||||
static bool scorepairSorter( const QPair<int,float>& left, const QPair<int,float>& right )
|
||||
{
|
||||
|
61
src/libtomahawk/database/localcollection.cpp
Normal file
61
src/libtomahawk/database/localcollection.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
|
||||
This program 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "localcollection.h"
|
||||
|
||||
#include "sourcelist.h"
|
||||
#include "viewmanager.h"
|
||||
#include <tomahawksettings.h>
|
||||
|
||||
LocalCollection::LocalCollection( const Tomahawk::source_ptr& source, QObject* parent )
|
||||
: DatabaseCollection( source, parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Tomahawk::playlist_ptr
|
||||
LocalCollection::bookmarksPlaylist()
|
||||
{
|
||||
if( TomahawkSettings::instance()->bookmarkPlaylist().isEmpty() )
|
||||
return Tomahawk::playlist_ptr();
|
||||
|
||||
return playlist( TomahawkSettings::instance()->bookmarkPlaylist() );
|
||||
}
|
||||
|
||||
void
|
||||
LocalCollection::createBookmarksPlaylist()
|
||||
{
|
||||
if( bookmarksPlaylist().isNull() ) {
|
||||
QString guid = uuid();
|
||||
Tomahawk::playlist_ptr p = Tomahawk::Playlist::create( SourceList::instance()->getLocal(), guid, tr( "Bookmarks" ), tr( "Saved tracks" ), QString(), false );
|
||||
ViewManager::instance()->createPageForPlaylist( p );
|
||||
// connect( p.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( loaded( Tomahawk::PlaylistRevision ) ), Qt::QueuedConnection );
|
||||
connect( p.data(), SIGNAL( created() ), this, SLOT( created() ) );
|
||||
|
||||
TomahawkSettings::instance()->setBookmarkPlaylist( guid );
|
||||
// p->createNewRevision( uuid(), p->currentrevision(), QList< Tomahawk::plentry_ptr >() );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LocalCollection::created()
|
||||
{
|
||||
emit bookmarkPlaylistCreated( bookmarksPlaylist() );
|
||||
}
|
46
src/libtomahawk/database/localcollection.h
Normal file
46
src/libtomahawk/database/localcollection.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LOCALCOLLECTION_H
|
||||
#define LOCALCOLLECTION_H
|
||||
|
||||
#include "databasecollection.h"
|
||||
#include "dllmacro.h"
|
||||
#include "playlist.h"
|
||||
|
||||
class DLLEXPORT LocalCollection : public DatabaseCollection
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit LocalCollection( const Tomahawk::source_ptr& source, QObject* parent = 0 );
|
||||
|
||||
// gets the playlist used for storing stuff from the web, if it already exists. if the returned playlist
|
||||
// is invalid ask to create and listen to the signal
|
||||
Tomahawk::playlist_ptr bookmarksPlaylist();
|
||||
void createBookmarksPlaylist();
|
||||
|
||||
signals:
|
||||
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& p );
|
||||
|
||||
private slots:
|
||||
void created();
|
||||
|
||||
};
|
||||
|
||||
#endif // LOCALCOLLECTION_H
|
@@ -25,13 +25,16 @@ using namespace Echonest;
|
||||
|
||||
// for internal neatness
|
||||
|
||||
EchoNestPlugin::EchoNestPlugin(QObject *parent)
|
||||
EchoNestPlugin::EchoNestPlugin(InfoSystemWorker *parent)
|
||||
: InfoPlugin(parent)
|
||||
, m_infoSystemWorker( parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QSet< InfoType > supportedTypes;
|
||||
supportedTypes << Tomahawk::InfoSystem::InfoArtistBiography << Tomahawk::InfoSystem::InfoArtistFamiliarity << Tomahawk::InfoSystem::InfoArtistHotttness << Tomahawk::InfoSystem::InfoArtistTerms << Tomahawk::InfoSystem::InfoMiscTopTerms;
|
||||
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
|
||||
parent->registerInfoTypes( this, supportedTypes, QSet< InfoType>() );
|
||||
|
||||
connect( parent, SIGNAL( namChanged() ), SLOT( namChangedSlot() ) );
|
||||
}
|
||||
|
||||
EchoNestPlugin::~EchoNestPlugin()
|
||||
@@ -39,6 +42,13 @@ EchoNestPlugin::~EchoNestPlugin()
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::namChangedSlot()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Echonest::Config::instance()->setNetworkAccessManager( m_infoSystemWorker->nam() );
|
||||
}
|
||||
|
||||
void
|
||||
EchoNestPlugin::getInfo(const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData)
|
||||
{
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#define ECHONESTPLUGIN_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "infosystem/infosystemworker.h"
|
||||
|
||||
#include <QObject>
|
||||
|
||||
@@ -39,12 +40,31 @@ class EchoNestPlugin : public InfoPlugin
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EchoNestPlugin(QObject *parent);
|
||||
EchoNestPlugin( InfoSystemWorker *parent );
|
||||
virtual ~EchoNestPlugin();
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
|
||||
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data )
|
||||
{
|
||||
Q_UNUSED( caller );
|
||||
Q_UNUSED( type );
|
||||
Q_UNUSED( data );
|
||||
}
|
||||
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
|
||||
{
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( caller );
|
||||
Q_UNUSED( type );
|
||||
Q_UNUSED( input );
|
||||
Q_UNUSED( customData );
|
||||
}
|
||||
|
||||
public slots:
|
||||
void namChangedSlot();
|
||||
|
||||
private:
|
||||
void getSongProfile( const QString &caller, const QVariant &input, const InfoCustomData &customData, const QString &item = QString() );
|
||||
void getArtistBiography ( const QString &caller, const QVariant &input, const InfoCustomData &customData );
|
||||
@@ -67,6 +87,7 @@ private slots:
|
||||
private:
|
||||
QHash< QNetworkReply*, InfoCustomData > m_replyMap;
|
||||
QHash< QNetworkReply*, QString > m_callerMap;
|
||||
InfoSystemWorker* m_infoSystemWorker;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -41,14 +41,18 @@ md5( const QByteArray& src )
|
||||
}
|
||||
|
||||
|
||||
LastFmPlugin::LastFmPlugin( QObject* parent )
|
||||
LastFmPlugin::LastFmPlugin( InfoSystemWorker* parent )
|
||||
: InfoPlugin(parent)
|
||||
, m_scrobbler( 0 )
|
||||
, m_authJob( 0 )
|
||||
, m_infoSystemWorker( parent )
|
||||
{
|
||||
QSet< InfoType > supportedTypes;
|
||||
supportedTypes << InfoMiscSubmitScrobble << InfoMiscSubmitNowPlaying << InfoAlbumCoverArt << InfoArtistImages;
|
||||
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
|
||||
QSet< InfoType > supportedGetTypes, supportedPushTypes;
|
||||
supportedGetTypes << InfoAlbumCoverArt << InfoArtistImages;
|
||||
supportedPushTypes << InfoSubmitScrobble << InfoSubmitNowPlaying;
|
||||
parent->registerInfoTypes( this, supportedGetTypes, supportedPushTypes );
|
||||
|
||||
connect( parent, SIGNAL( namChanged() ), SLOT( namChangedSlot() ) );
|
||||
|
||||
/*
|
||||
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
|
||||
@@ -94,6 +98,14 @@ LastFmPlugin::~LastFmPlugin()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::namChangedSlot()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
lastfm::setNetworkAccessManager( m_infoSystemWorker->nam() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::dataError( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
|
||||
{
|
||||
@@ -109,14 +121,6 @@ LastFmPlugin::getInfo( const QString caller, const Tomahawk::InfoSystem::InfoTyp
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case InfoMiscSubmitNowPlaying:
|
||||
nowPlaying( caller, type, input, customData );
|
||||
break;
|
||||
|
||||
case InfoMiscSubmitScrobble:
|
||||
scrobble( caller, type, input, customData );
|
||||
break;
|
||||
|
||||
case InfoArtistImages:
|
||||
fetchArtistImages( caller, type, input, customData );
|
||||
break;
|
||||
@@ -132,19 +136,34 @@ LastFmPlugin::getInfo( const QString caller, const Tomahawk::InfoSystem::InfoTyp
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
|
||||
LastFmPlugin::pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
switch ( type )
|
||||
{
|
||||
case InfoSubmitNowPlaying:
|
||||
nowPlaying( caller, type, input );
|
||||
break;
|
||||
|
||||
case InfoSubmitScrobble:
|
||||
scrobble( caller, type, input );
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVariant &input )
|
||||
{
|
||||
if ( !input.canConvert< Tomahawk::InfoSystem::InfoCriteriaHash >() || !m_scrobbler )
|
||||
{
|
||||
dataError( caller, type, input, customData );
|
||||
return;
|
||||
}
|
||||
|
||||
InfoCriteriaHash hash = input.value< Tomahawk::InfoSystem::InfoCriteriaHash >();
|
||||
if ( !hash.contains( "title" ) || !hash.contains( "artist" ) || !hash.contains( "album" ) || !hash.contains( "duration" ) )
|
||||
{
|
||||
dataError( caller, type, input, customData );
|
||||
return;
|
||||
}
|
||||
|
||||
m_track = lastfm::MutableTrack();
|
||||
m_track.stamp();
|
||||
@@ -157,26 +176,20 @@ LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVar
|
||||
m_track.setSource( lastfm::Track::Player );
|
||||
|
||||
m_scrobbler->nowPlaying( m_track );
|
||||
emit info( caller, type, input, QVariant(), customData );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
LastFmPlugin::scrobble( const QString &caller, const InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData )
|
||||
LastFmPlugin::scrobble( const QString &caller, const InfoType type, const QVariant &input )
|
||||
{
|
||||
Q_ASSERT( QThread::currentThread() == thread() );
|
||||
|
||||
if ( !m_scrobbler || m_track.isNull() )
|
||||
{
|
||||
dataError( caller, type, input, customData );
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << m_track.toString();
|
||||
m_scrobbler->cache( m_track );
|
||||
m_scrobbler->submit();
|
||||
|
||||
emit info( caller, type, input, QVariant(), customData );
|
||||
}
|
||||
|
||||
|
||||
@@ -241,7 +254,7 @@ LastFmPlugin::notInCacheSlot( const QHash<QString, QString> criteria, const QStr
|
||||
|
||||
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=album.imageredirect&artist=%1&album=%2&autocorrect=1&size=medium&api_key=7a90f6672a04b809ee309af169f34b8b";
|
||||
QNetworkRequest req( imgurl.arg( artistName ).arg( albumName ) );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
|
||||
QNetworkReply* reply = m_infoSystemWorker->nam()->get( req );
|
||||
reply->setProperty( "customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomData>( customData ) );
|
||||
reply->setProperty( "origData", input );
|
||||
reply->setProperty( "caller", caller );
|
||||
@@ -257,7 +270,7 @@ LastFmPlugin::notInCacheSlot( const QHash<QString, QString> criteria, const QStr
|
||||
|
||||
QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=artist.imageredirect&artist=%1&autocorrect=1&size=medium&api_key=7a90f6672a04b809ee309af169f34b8b";
|
||||
QNetworkRequest req( imgurl.arg( artistName ) );
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
|
||||
QNetworkReply* reply = m_infoSystemWorker->nam()->get( req );
|
||||
reply->setProperty( "customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomData>( customData ) );
|
||||
reply->setProperty( "origData", input );
|
||||
reply->setProperty( "caller", caller );
|
||||
@@ -312,7 +325,7 @@ LastFmPlugin::coverArtReturned()
|
||||
{
|
||||
// Follow HTTP redirect
|
||||
QNetworkRequest req( redir );
|
||||
QNetworkReply* newReply = TomahawkUtils::nam()->get( req );
|
||||
QNetworkReply* newReply = m_infoSystemWorker->nam()->get( req );
|
||||
newReply->setProperty( "origData", reply->property( "origData" ) );
|
||||
newReply->setProperty( "customData", reply->property( "customData" ) );
|
||||
newReply->setProperty( "caller", reply->property( "caller" ) );
|
||||
@@ -362,7 +375,7 @@ LastFmPlugin::artistImagesReturned()
|
||||
{
|
||||
// Follow HTTP redirect
|
||||
QNetworkRequest req( redir );
|
||||
QNetworkReply* newReply = TomahawkUtils::nam()->get( req );
|
||||
QNetworkReply* newReply = m_infoSystemWorker->nam()->get( req );
|
||||
newReply->setProperty( "origData", reply->property( "origData" ) );
|
||||
newReply->setProperty( "customData", reply->property( "customData" ) );
|
||||
newReply->setProperty( "caller", reply->property( "caller" ) );
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#ifndef LASTFMPLUGIN_H
|
||||
#define LASTFMPLUGIN_H
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "infosystem/infosystemworker.h"
|
||||
#include "result.h"
|
||||
|
||||
#include <lastfm/Track>
|
||||
@@ -40,7 +41,7 @@ class LastFmPlugin : public InfoPlugin
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
LastFmPlugin( QObject *parent );
|
||||
LastFmPlugin( InfoSystemWorker *parent );
|
||||
virtual ~LastFmPlugin();
|
||||
|
||||
public slots:
|
||||
@@ -50,17 +51,21 @@ public slots:
|
||||
void coverArtReturned();
|
||||
void artistImagesReturned();
|
||||
|
||||
void namChangedSlot();
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
|
||||
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data );
|
||||
|
||||
private:
|
||||
void fetchCoverArt( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
|
||||
void fetchArtistImages( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
|
||||
|
||||
void createScrobbler();
|
||||
void scrobble( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
|
||||
void nowPlaying( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
|
||||
void scrobble( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input );
|
||||
void nowPlaying( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input );
|
||||
|
||||
void dataError( const QString &caller, const Tomahawk::InfoSystem::InfoType type, const QVariant &input, const Tomahawk::InfoSystem::InfoCustomData &customData );
|
||||
|
||||
@@ -71,6 +76,8 @@ private:
|
||||
QList< QUrl > m_badUrls;
|
||||
|
||||
QNetworkReply* m_authJob;
|
||||
|
||||
InfoSystemWorker* m_infoSystemWorker;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -27,14 +27,15 @@ using namespace Tomahawk::InfoSystem;
|
||||
|
||||
// for internal neatness
|
||||
|
||||
MusixMatchPlugin::MusixMatchPlugin(QObject *parent)
|
||||
MusixMatchPlugin::MusixMatchPlugin(InfoSystemWorker *parent)
|
||||
: InfoPlugin(parent)
|
||||
, m_apiKey("61be4ea5aea7dd942d52b2f1311dd9fe")
|
||||
, m_infoSystemWorker( parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QSet< InfoType > supportedTypes;
|
||||
supportedTypes << Tomahawk::InfoSystem::InfoTrackLyrics;
|
||||
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
|
||||
parent->registerInfoTypes( this, supportedTypes, QSet< InfoType>() );
|
||||
}
|
||||
|
||||
MusixMatchPlugin::~MusixMatchPlugin()
|
||||
@@ -62,7 +63,7 @@ MusixMatchPlugin::getInfo( const QString caller, const Tomahawk::InfoSystem::Inf
|
||||
url.addQueryItem("apikey", m_apiKey);
|
||||
url.addQueryItem("q_artist", artist);
|
||||
url.addQueryItem("q_track", track);
|
||||
QNetworkReply* reply = TomahawkUtils::nam()->get(QNetworkRequest(url));
|
||||
QNetworkReply* reply = m_infoSystemWorker->nam()->get(QNetworkRequest(url));
|
||||
reply->setProperty("customData", QVariant::fromValue<Tomahawk::InfoSystem::InfoCustomData>(customData));
|
||||
reply->setProperty("origData", input);
|
||||
reply->setProperty("caller", caller);
|
||||
@@ -120,7 +121,7 @@ MusixMatchPlugin::trackSearchSlot()
|
||||
QUrl url(requestString);
|
||||
url.addQueryItem("apikey", m_apiKey);
|
||||
url.addQueryItem("track_id", track_id);
|
||||
QNetworkReply* newReply = TomahawkUtils::nam()->get(QNetworkRequest(url));
|
||||
QNetworkReply* newReply = m_infoSystemWorker->nam()->get(QNetworkRequest(url));
|
||||
newReply->setProperty("origData", oldReply->property("origData"));
|
||||
newReply->setProperty("customData", oldReply->property("customData"));
|
||||
newReply->setProperty("caller", oldReply->property("caller"));
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#define MUSIXMATCHPLUGIN_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
#include "infosystem/infosystemworker.h"
|
||||
|
||||
class QNetworkReply;
|
||||
|
||||
@@ -34,7 +35,7 @@ class MusixMatchPlugin : public InfoPlugin
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MusixMatchPlugin( QObject *parent );
|
||||
MusixMatchPlugin( InfoSystemWorker *parent );
|
||||
virtual ~MusixMatchPlugin();
|
||||
|
||||
public slots:
|
||||
@@ -44,10 +45,28 @@ public slots:
|
||||
protected slots:
|
||||
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
|
||||
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data )
|
||||
{
|
||||
Q_UNUSED( caller );
|
||||
Q_UNUSED( type );
|
||||
Q_UNUSED( data );
|
||||
}
|
||||
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
|
||||
{
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( caller );
|
||||
Q_UNUSED( type );
|
||||
Q_UNUSED( input );
|
||||
Q_UNUSED( customData );
|
||||
}
|
||||
|
||||
private:
|
||||
bool isValidTrackData( const QString &caller, const QVariant &input, const InfoCustomData &customData );
|
||||
|
||||
QString m_apiKey;
|
||||
|
||||
InfoSystemWorker* m_infoSystemWorker;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "infosystem.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "infosystemcache.h"
|
||||
#include "infoplugins/echonestplugin.h"
|
||||
@@ -31,7 +32,7 @@ namespace Tomahawk
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
InfoPlugin::InfoPlugin(QObject *parent)
|
||||
InfoPlugin::InfoPlugin( InfoSystemWorker *parent )
|
||||
:QObject( parent )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
@@ -59,59 +60,33 @@ InfoSystem::InfoSystem(QObject *parent)
|
||||
m_cache->moveToThread( m_infoSystemCacheThreadController );
|
||||
m_infoSystemCacheThreadController->start( QThread::IdlePriority );
|
||||
|
||||
InfoPluginPtr enptr( new EchoNestPlugin( this ) );
|
||||
m_plugins.append( enptr );
|
||||
InfoPluginPtr mmptr( new MusixMatchPlugin( this ) );
|
||||
m_plugins.append( mmptr );
|
||||
InfoPluginPtr lfmptr( new LastFmPlugin( this ) );
|
||||
m_plugins.append( lfmptr );
|
||||
m_infoSystemWorkerThreadController = new QThread( this );
|
||||
m_worker = new InfoSystemWorker();
|
||||
m_worker->moveToThread( m_infoSystemWorkerThreadController );
|
||||
m_infoSystemWorkerThreadController->start();
|
||||
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
this,
|
||||
SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
Qt::UniqueConnection
|
||||
);
|
||||
QMetaObject::invokeMethod( m_worker, "init", Qt::QueuedConnection );
|
||||
|
||||
connect( TomahawkSettings::instance(), SIGNAL( changed() ), SLOT( newNam() ) );
|
||||
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
m_cache,
|
||||
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
|
||||
);
|
||||
connect(
|
||||
m_cache,
|
||||
SIGNAL( notInCache( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
plugin.data(),
|
||||
SLOT( notInCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
|
||||
);
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
|
||||
m_cache,
|
||||
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
|
||||
);
|
||||
}
|
||||
connect( m_cache, SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection );
|
||||
|
||||
connect( m_worker, SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
this, SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ), Qt::UniqueConnection );
|
||||
}
|
||||
|
||||
InfoSystem::~InfoSystem()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
if( plugin )
|
||||
delete plugin.data();
|
||||
}
|
||||
|
||||
if ( m_infoSystemCacheThreadController )
|
||||
m_infoSystemCacheThreadController->quit();
|
||||
if ( m_infoSystemWorkerThreadController )
|
||||
m_infoSystemWorkerThreadController->quit();
|
||||
|
||||
if( m_infoSystemCacheThreadController )
|
||||
{
|
||||
m_infoSystemCacheThreadController->quit();
|
||||
|
||||
while( !m_infoSystemCacheThreadController->isFinished() )
|
||||
{
|
||||
QCoreApplication::processEvents( QEventLoop::AllEvents, 200 );
|
||||
@@ -127,56 +102,73 @@ InfoSystem::~InfoSystem()
|
||||
delete m_infoSystemCacheThreadController;
|
||||
m_infoSystemCacheThreadController = 0;
|
||||
}
|
||||
|
||||
if( m_infoSystemWorkerThreadController )
|
||||
{
|
||||
while( !m_infoSystemWorkerThreadController->isFinished() )
|
||||
{
|
||||
QCoreApplication::processEvents( QEventLoop::AllEvents, 200 );
|
||||
TomahawkUtils::Sleep::msleep( 100 );
|
||||
}
|
||||
|
||||
void InfoSystem::registerInfoTypes(const InfoPluginPtr &plugin, const QSet< InfoType >& types)
|
||||
if( m_worker )
|
||||
{
|
||||
delete m_worker;
|
||||
m_worker = 0;
|
||||
}
|
||||
|
||||
delete m_infoSystemWorkerThreadController;
|
||||
m_infoSystemWorkerThreadController = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::newNam() const
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_FOREACH(InfoType type, types)
|
||||
m_infoMap[type].append(plugin);
|
||||
QMetaObject::invokeMethod( m_worker, "newNam", Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
QLinkedList< InfoPluginPtr > InfoSystem::determineOrderedMatches(const InfoType type) const
|
||||
{
|
||||
//Dummy function for now that returns the various items in the QSet; at some point this will
|
||||
//probably need to support ordering based on the data source
|
||||
QLinkedList< InfoPluginPtr > providers;
|
||||
Q_FOREACH(InfoPluginPtr ptr, m_infoMap[type])
|
||||
providers << ptr;
|
||||
return providers;
|
||||
}
|
||||
|
||||
void InfoSystem::getInfo(const QString &caller, const InfoType type, const QVariant& input, InfoCustomData customData)
|
||||
void
|
||||
InfoSystem::getInfo( const QString &caller, const InfoType type, const QVariant& input, InfoCustomData customData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches(type);
|
||||
if (providers.isEmpty())
|
||||
{
|
||||
emit info(caller, InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
emit finished(caller);
|
||||
return;
|
||||
}
|
||||
|
||||
InfoPluginPtr ptr = providers.first();
|
||||
if (!ptr)
|
||||
{
|
||||
emit info(caller, InfoNoInfo, QVariant(), QVariant(), customData);
|
||||
emit finished(caller);
|
||||
return;
|
||||
}
|
||||
|
||||
m_dataTracker[caller][type] = m_dataTracker[caller][type] + 1;
|
||||
qDebug() << "current count in dataTracker for type" << type << "is" << m_dataTracker[caller][type];
|
||||
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
|
||||
QMetaObject::invokeMethod( m_worker, "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
|
||||
}
|
||||
|
||||
void InfoSystem::getInfo(const QString &caller, const InfoMap &input, InfoCustomData customData)
|
||||
|
||||
void
|
||||
InfoSystem::getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData )
|
||||
{
|
||||
Q_FOREACH( InfoType type, input.keys() )
|
||||
getInfo( caller, type, input[type], customData );
|
||||
}
|
||||
|
||||
void InfoSystem::infoSlot(QString target, InfoType type, QVariant input, QVariant output, InfoCustomData customData)
|
||||
|
||||
void
|
||||
InfoSystem::pushInfo( const QString &caller, const InfoType type, const QVariant& input )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
QMetaObject::invokeMethod( m_worker, "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::pushInfo( const QString &caller, const InfoMap &input )
|
||||
{
|
||||
Q_FOREACH( InfoType type, input.keys() )
|
||||
pushInfo( caller, type, input[type] );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystem::infoSlot( QString target, InfoType type, QVariant input, QVariant output, InfoCustomData customData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qDebug() << "current count in dataTracker is " << m_dataTracker[target][type];
|
||||
|
@@ -36,62 +36,63 @@ namespace Tomahawk {
|
||||
namespace InfoSystem {
|
||||
|
||||
class InfoSystemCache;
|
||||
class InfoSystemWorker;
|
||||
|
||||
enum InfoType {
|
||||
enum InfoType { // as items are saved in cache, mark them here to not change them
|
||||
InfoTrackID = 0,
|
||||
InfoTrackArtist,
|
||||
InfoTrackAlbum,
|
||||
InfoTrackGenre,
|
||||
InfoTrackComposer,
|
||||
InfoTrackDate,
|
||||
InfoTrackNumber,
|
||||
InfoTrackDiscNumber,
|
||||
InfoTrackBitRate,
|
||||
InfoTrackLength,
|
||||
InfoTrackSampleRate,
|
||||
InfoTrackFileSize,
|
||||
InfoTrackBPM,
|
||||
InfoTrackReplayGain,
|
||||
InfoTrackReplayPeakGain,
|
||||
InfoTrackLyrics,
|
||||
InfoTrackLocation,
|
||||
InfoTrackProfile,
|
||||
InfoTrackEnergy,
|
||||
InfoTrackDanceability,
|
||||
InfoTrackTempo,
|
||||
InfoTrackLoudness,
|
||||
InfoTrackArtist = 1,
|
||||
InfoTrackAlbum = 2,
|
||||
InfoTrackGenre = 3,
|
||||
InfoTrackComposer = 4,
|
||||
InfoTrackDate = 5,
|
||||
InfoTrackNumber = 6,
|
||||
InfoTrackDiscNumber = 7,
|
||||
InfoTrackBitRate = 8,
|
||||
InfoTrackLength = 9,
|
||||
InfoTrackSampleRate = 10,
|
||||
InfoTrackFileSize = 11,
|
||||
InfoTrackBPM = 12,
|
||||
InfoTrackReplayGain = 13,
|
||||
InfoTrackReplayPeakGain = 14,
|
||||
InfoTrackLyrics = 15,
|
||||
InfoTrackLocation = 16,
|
||||
InfoTrackProfile = 17,
|
||||
InfoTrackEnergy = 18,
|
||||
InfoTrackDanceability = 19,
|
||||
InfoTrackTempo = 20,
|
||||
InfoTrackLoudness = 21,
|
||||
|
||||
InfoArtistID,
|
||||
InfoArtistName,
|
||||
InfoArtistBiography,
|
||||
InfoArtistBlog,
|
||||
InfoArtistFamiliarity,
|
||||
InfoArtistHotttness,
|
||||
InfoArtistImages,
|
||||
InfoArtistNews,
|
||||
InfoArtistProfile,
|
||||
InfoArtistReviews,
|
||||
InfoArtistSongs,
|
||||
InfoArtistSimilars,
|
||||
InfoArtistTerms,
|
||||
InfoArtistLinks,
|
||||
InfoArtistVideos,
|
||||
InfoArtistID = 22,
|
||||
InfoArtistName = 23,
|
||||
InfoArtistBiography = 24,
|
||||
InfoArtistBlog = 25,
|
||||
InfoArtistFamiliarity = 26,
|
||||
InfoArtistHotttness = 27,
|
||||
InfoArtistImages = 28,
|
||||
InfoArtistNews = 29,
|
||||
InfoArtistProfile = 30,
|
||||
InfoArtistReviews = 31,
|
||||
InfoArtistSongs = 32,
|
||||
InfoArtistSimilars = 33,
|
||||
InfoArtistTerms = 34,
|
||||
InfoArtistLinks = 35,
|
||||
InfoArtistVideos = 36,
|
||||
|
||||
InfoAlbumID,
|
||||
InfoAlbumName,
|
||||
InfoAlbumArtist,
|
||||
InfoAlbumDate,
|
||||
InfoAlbumGenre,
|
||||
InfoAlbumComposer,
|
||||
InfoAlbumCoverArt,
|
||||
InfoAlbumID = 37,
|
||||
InfoAlbumName = 38,
|
||||
InfoAlbumArtist = 39,
|
||||
InfoAlbumDate = 40,
|
||||
InfoAlbumGenre = 41,
|
||||
InfoAlbumComposer = 42,
|
||||
InfoAlbumCoverArt = 43, //cached -- do not change
|
||||
|
||||
InfoMiscTopHotttness,
|
||||
InfoMiscTopTerms,
|
||||
InfoMiscTopHotttness = 44,
|
||||
InfoMiscTopTerms = 45,
|
||||
|
||||
InfoMiscSubmitNowPlaying,
|
||||
InfoMiscSubmitScrobble,
|
||||
InfoSubmitNowPlaying = 46,
|
||||
InfoSubmitScrobble = 47,
|
||||
|
||||
InfoNoInfo
|
||||
InfoNoInfo = 48
|
||||
};
|
||||
|
||||
typedef QMap< InfoType, QVariant > InfoMap;
|
||||
@@ -104,12 +105,9 @@ class DLLEXPORT InfoPlugin : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InfoPlugin( QObject *parent );
|
||||
InfoPlugin( InfoSystemWorker *parent );
|
||||
|
||||
virtual ~InfoPlugin()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
virtual ~InfoPlugin() {}
|
||||
|
||||
signals:
|
||||
void getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash criteria, qint64 newMaxAge, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
@@ -119,16 +117,8 @@ signals:
|
||||
|
||||
protected slots:
|
||||
virtual void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data, const Tomahawk::InfoSystem::InfoCustomData customData ) = 0;
|
||||
|
||||
//FIXME: Make pure virtual when everything supports it
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData )
|
||||
{
|
||||
Q_UNUSED( criteria );
|
||||
Q_UNUSED( caller );
|
||||
Q_UNUSED( type );
|
||||
Q_UNUSED( input );
|
||||
Q_UNUSED( customData );
|
||||
}
|
||||
virtual void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant data ) = 0;
|
||||
virtual void notInCacheSlot( const Tomahawk::InfoSystem::InfoCriteriaHash criteria, const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData ) = 0;
|
||||
|
||||
protected:
|
||||
InfoType m_type;
|
||||
@@ -139,13 +129,6 @@ private:
|
||||
|
||||
typedef QWeakPointer< InfoPlugin > InfoPluginPtr;
|
||||
|
||||
class DLLEXPORT InfoSystemWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
InfoSystemWorker() {};
|
||||
~InfoSystemWorker() {};
|
||||
};
|
||||
|
||||
class DLLEXPORT InfoSystem : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -156,12 +139,12 @@ public:
|
||||
InfoSystem( QObject *parent );
|
||||
~InfoSystem();
|
||||
|
||||
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &types );
|
||||
|
||||
void getInfo( const QString &caller, const InfoType type, const QVariant &input, InfoCustomData customData );
|
||||
void getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData );
|
||||
void pushInfo( const QString &caller, const InfoType type, const QVariant &input );
|
||||
void pushInfo( const QString &caller, const InfoMap &input );
|
||||
|
||||
InfoSystemCache* getCache() { return m_cache; }
|
||||
InfoSystemCache* getCache() const { return m_cache; }
|
||||
|
||||
signals:
|
||||
void info( QString caller, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
@@ -170,14 +153,9 @@ signals:
|
||||
public slots:
|
||||
void infoSlot( const QString target, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const QVariant output, const Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
|
||||
void newNam() const;
|
||||
|
||||
private:
|
||||
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
|
||||
|
||||
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoMap;
|
||||
|
||||
// For now, statically instantiate plugins; this is just somewhere to keep them
|
||||
QLinkedList< InfoPluginPtr > m_plugins;
|
||||
|
||||
QHash< QString, QHash< InfoType, int > > m_dataTracker;
|
||||
|
||||
InfoSystemCache* m_cache;
|
||||
|
190
src/libtomahawk/infosystem/infosystemworker.cpp
Normal file
190
src/libtomahawk/infosystem/infosystemworker.cpp
Normal file
@@ -0,0 +1,190 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk 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.
|
||||
*
|
||||
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QNetworkConfiguration>
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#include "infosystemworker.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
#include "infosystemcache.h"
|
||||
#include "infoplugins/echonestplugin.h"
|
||||
#include "infoplugins/musixmatchplugin.h"
|
||||
#include "infoplugins/lastfmplugin.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
namespace InfoSystem
|
||||
{
|
||||
|
||||
InfoSystemWorker::InfoSystemWorker()
|
||||
: m_nam( 0 )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
|
||||
|
||||
InfoSystemWorker::~InfoSystemWorker()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
if( plugin )
|
||||
delete plugin.data();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void InfoSystemWorker::init()
|
||||
{
|
||||
InfoPluginPtr enptr( new EchoNestPlugin( this ) );
|
||||
m_plugins.append( enptr );
|
||||
InfoPluginPtr mmptr( new MusixMatchPlugin( this ) );
|
||||
m_plugins.append( mmptr );
|
||||
InfoPluginPtr lfmptr( new LastFmPlugin( this ) );
|
||||
m_plugins.append( lfmptr );
|
||||
|
||||
InfoSystemCache *cache = InfoSystem::instance()->getCache();
|
||||
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
InfoSystem::instance(),
|
||||
SLOT( infoSlot( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
Qt::UniqueConnection
|
||||
);
|
||||
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
cache,
|
||||
SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
|
||||
);
|
||||
connect(
|
||||
cache,
|
||||
SIGNAL( notInCache( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
|
||||
plugin.data(),
|
||||
SLOT( notInCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
|
||||
);
|
||||
connect(
|
||||
plugin.data(),
|
||||
SIGNAL( updateCache( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
|
||||
cache,
|
||||
SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoCriteriaHash, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
|
||||
);
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod( this, "newNam" );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType >& getTypes, const QSet< InfoType >& pushTypes )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
Q_FOREACH( InfoType type, getTypes )
|
||||
m_infoGetMap[type].append( plugin );
|
||||
Q_FOREACH( InfoType type, pushTypes )
|
||||
m_infoPushMap[type].append( plugin );
|
||||
}
|
||||
|
||||
|
||||
QLinkedList< InfoPluginPtr >
|
||||
InfoSystemWorker::determineOrderedMatches( const InfoType type ) const
|
||||
{
|
||||
//Dummy function for now that returns the various items in the QSet; at some point this will
|
||||
//probably need to support ordering based on the data source
|
||||
QLinkedList< InfoPluginPtr > providers;
|
||||
Q_FOREACH( InfoPluginPtr ptr, m_infoGetMap[type] )
|
||||
providers << ptr;
|
||||
return providers;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::getInfo( QString caller, InfoType type, QVariant input, InfoCustomData customData )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QLinkedList< InfoPluginPtr > providers = determineOrderedMatches(type);
|
||||
if ( providers.isEmpty() )
|
||||
{
|
||||
emit info( caller, type, QVariant(), QVariant(), customData );
|
||||
return;
|
||||
}
|
||||
|
||||
InfoPluginPtr ptr = providers.first();
|
||||
if ( !ptr )
|
||||
{
|
||||
emit info( caller, type, QVariant(), QVariant(), customData );
|
||||
return;
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod( ptr.data(), "getInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::pushInfo( const QString caller, const InfoType type, const QVariant input )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
Q_FOREACH( InfoPluginPtr ptr, m_infoPushMap[type] )
|
||||
{
|
||||
if( ptr )
|
||||
QMetaObject::invokeMethod( ptr.data(), "pushInfo", Qt::QueuedConnection, Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QVariant, input ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QNetworkAccessManager*
|
||||
InfoSystemWorker::nam() const
|
||||
{
|
||||
return m_nam;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::newNam()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
QNetworkAccessManager *newNam = new QNetworkAccessManager();
|
||||
if ( m_nam )
|
||||
{
|
||||
delete m_nam;
|
||||
}
|
||||
QNetworkAccessManager *oldNam = TomahawkUtils::nam();
|
||||
if ( !oldNam )
|
||||
{
|
||||
m_nam = newNam;
|
||||
return;
|
||||
}
|
||||
newNam->setConfiguration( oldNam->configuration() );
|
||||
newNam->setNetworkAccessible( oldNam->networkAccessible() );
|
||||
newNam->setProxy( oldNam->proxy() );
|
||||
m_nam = newNam;
|
||||
|
||||
emit namChanged();
|
||||
}
|
||||
|
||||
|
||||
} //namespace InfoSystem
|
||||
|
||||
} //namespace Tomahawk
|
76
src/libtomahawk/infosystem/infosystemworker.h
Normal file
76
src/libtomahawk/infosystem/infosystemworker.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk 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.
|
||||
*
|
||||
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TOMAHAWK_INFOSYSTEMWORKER_H
|
||||
#define TOMAHAWK_INFOSYSTEMWORKER_H
|
||||
|
||||
#include "infosystem/infosystem.h"
|
||||
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QtDebug>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QWeakPointer>
|
||||
#include <QtCore/QSet>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QtCore/QVariant>
|
||||
|
||||
#include "dllmacro.h"
|
||||
|
||||
namespace Tomahawk {
|
||||
|
||||
namespace InfoSystem {
|
||||
|
||||
class DLLEXPORT InfoSystemWorker : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
InfoSystemWorker();
|
||||
~InfoSystemWorker();
|
||||
|
||||
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
|
||||
QNetworkAccessManager* nam() const;
|
||||
|
||||
signals:
|
||||
void info( QString target, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
void namChanged();
|
||||
|
||||
public slots:
|
||||
void init();
|
||||
void getInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input, const Tomahawk::InfoSystem::InfoCustomData customData );
|
||||
void pushInfo( const QString caller, const Tomahawk::InfoSystem::InfoType type, const QVariant input );
|
||||
void newNam();
|
||||
|
||||
private:
|
||||
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
|
||||
|
||||
// For now, statically instantiate plugins; this is just somewhere to keep them
|
||||
QLinkedList< InfoPluginPtr > m_plugins;
|
||||
|
||||
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoGetMap;
|
||||
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoPushMap;
|
||||
|
||||
QNetworkAccessManager *m_nam;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // TOMAHAWK_INFOSYSTEMWORKER_H
|
@@ -496,13 +496,13 @@ Servent::connectToPeer( const QString& ha, int port, const QString &key, const Q
|
||||
void
|
||||
Servent::connectToPeer( const QString& ha, int port, const QString &key, Connection* conn )
|
||||
{
|
||||
qDebug() << "Servent::connectToPeer:" << ha << ":" << port
|
||||
<< thread() << QThread::currentThread();
|
||||
|
||||
Q_ASSERT( port > 0 );
|
||||
Q_ASSERT( conn );
|
||||
// Q_ASSERT( this->thread() == QThread::currentThread() );
|
||||
|
||||
qDebug() << "Servent::connectToPeer:" << ha << ":" << port
|
||||
<< thread() << QThread::currentThread();
|
||||
|
||||
if ( ( ha == m_externalAddress.toString() || ha == m_externalHostname ) &&
|
||||
( port == m_externalPort ) )
|
||||
{
|
||||
|
@@ -118,10 +118,10 @@ DynamicPlaylist::create( const Tomahawk::source_ptr& author,
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
GeneratorMode mode,
|
||||
bool shared )
|
||||
bool shared,
|
||||
const QString& type
|
||||
)
|
||||
{
|
||||
// default generator
|
||||
QString type = "";
|
||||
dynplaylist_ptr dynplaylist = dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, mode, shared ) );
|
||||
|
||||
DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist );
|
||||
|
@@ -82,7 +82,8 @@ public:
|
||||
const QString& info,
|
||||
const QString& creator,
|
||||
GeneratorMode mode,
|
||||
bool shared
|
||||
bool shared,
|
||||
const QString& type = QString()
|
||||
);
|
||||
static bool remove( const dynplaylist_ptr& playlist );
|
||||
|
||||
|
@@ -55,6 +55,18 @@ SourceList::getLocal()
|
||||
return m_local;
|
||||
}
|
||||
|
||||
void
|
||||
SourceList::setWebSource( const source_ptr& websrc )
|
||||
{
|
||||
m_dummy = websrc;
|
||||
}
|
||||
|
||||
const
|
||||
source_ptr SourceList::webSource() const
|
||||
{
|
||||
return m_dummy;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SourceList::loadSources()
|
||||
|
@@ -40,6 +40,9 @@ public:
|
||||
const Tomahawk::source_ptr& getLocal();
|
||||
void setLocal( const Tomahawk::source_ptr& localSrc );
|
||||
|
||||
void setWebSource( const Tomahawk::source_ptr& websrc );
|
||||
const Tomahawk::source_ptr webSource() const;
|
||||
|
||||
void removeAllRemote();
|
||||
|
||||
QList<Tomahawk::source_ptr> sources( bool onlyOnline = false ) const;
|
||||
@@ -66,6 +69,7 @@ private:
|
||||
QMap< int, QString > m_sources_id2name;
|
||||
|
||||
Tomahawk::source_ptr m_local;
|
||||
Tomahawk::source_ptr m_dummy;
|
||||
mutable QMutex m_mut; // mutable so const methods can use a lock
|
||||
|
||||
static SourceList* s_instance;
|
||||
|
@@ -377,6 +377,18 @@ TomahawkSettings::appendRecentlyPlayedPlaylist( const Tomahawk::playlist_ptr& pl
|
||||
setValue( "playlists/recentlyPlayed", playlist_guids );
|
||||
}
|
||||
|
||||
QString
|
||||
TomahawkSettings::bookmarkPlaylist() const
|
||||
{
|
||||
return value( "playlists/bookmark", QString() ).toString();
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkSettings::setBookmarkPlaylist( const QString& guid )
|
||||
{
|
||||
setValue( "playlists/bookmark", guid );
|
||||
}
|
||||
|
||||
QStringList
|
||||
TomahawkSettings::sipPlugins() const
|
||||
{
|
||||
|
@@ -73,6 +73,9 @@ public:
|
||||
void setSipPlugins( const QStringList& plugins );
|
||||
QStringList sipPlugins() const;
|
||||
|
||||
void setBookmarkPlaylist( const QString& guid );
|
||||
QString bookmarkPlaylist() const;
|
||||
|
||||
// just the enabled sip plugins.
|
||||
void setEnabledSipPlugins( const QStringList& list );
|
||||
QStringList enabledSipPlugins() const;
|
||||
|
@@ -29,6 +29,12 @@
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
void
|
||||
XSPFLoader::setOverrideTitle( const QString& newTitle )
|
||||
{
|
||||
m_overrideTitle = newTitle;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
XSPFLoader::load( const QUrl& url )
|
||||
@@ -116,13 +122,15 @@ XSPFLoader::gotBody()
|
||||
m_title = origTitle;
|
||||
if ( m_title.isEmpty() )
|
||||
m_title = tr( "New Playlist" );
|
||||
if( !m_overrideTitle.isEmpty() )
|
||||
m_title = m_overrideTitle;
|
||||
|
||||
bool shownError = false;
|
||||
for ( unsigned int i = 0; i < tracklist.length(); i++ )
|
||||
{
|
||||
QDomNode e = tracklist.at( i );
|
||||
|
||||
QString artist, album, track, duration, annotation;
|
||||
QString artist, album, track, duration, annotation, url;
|
||||
QDomElement n = e.firstChildElement();
|
||||
for ( ; !n.isNull(); n = n.nextSiblingElement() ) {
|
||||
if (n.namespaceURI() == m_NS && n.localName() == "duration") {
|
||||
@@ -135,6 +143,8 @@ XSPFLoader::gotBody()
|
||||
album = n.text();
|
||||
} else if (n.namespaceURI() == m_NS && n.localName() == "title") {
|
||||
track = n.text();
|
||||
} else if (n.namespaceURI() == m_NS && n.localName() == "url") {
|
||||
url = n.text();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,6 +164,8 @@ XSPFLoader::gotBody()
|
||||
|
||||
p->setQuery( Tomahawk::Query::get( artist, track, album, uuid() ) );
|
||||
p->query()->setDuration( duration.toInt() / 1000 );
|
||||
if( !url.isEmpty() )
|
||||
p->query()->setResultHint( url );
|
||||
m_entries << p;
|
||||
}
|
||||
|
||||
|
@@ -53,6 +53,7 @@ public:
|
||||
|
||||
QList< Tomahawk::plentry_ptr > entries() const { return m_entries; }
|
||||
|
||||
void setOverrideTitle( const QString& newTitle );
|
||||
signals:
|
||||
void failed();
|
||||
void ok( const Tomahawk::playlist_ptr& );
|
||||
@@ -70,7 +71,7 @@ private:
|
||||
void gotBody();
|
||||
|
||||
bool m_autoCreate;
|
||||
QString m_NS;
|
||||
QString m_NS,m_overrideTitle;
|
||||
QList< Tomahawk::plentry_ptr > m_entries;
|
||||
QString m_title, m_info, m_creator;
|
||||
|
||||
|
@@ -149,6 +149,22 @@ ViewManager::queue() const
|
||||
return m_queueView->queue();
|
||||
}
|
||||
|
||||
PlaylistView*
|
||||
ViewManager::createPageForPlaylist( const playlist_ptr& pl )
|
||||
{
|
||||
PlaylistView* view = new PlaylistView();
|
||||
|
||||
PlaylistModel* model = new PlaylistModel();
|
||||
view->setPlaylistModel( model );
|
||||
view->setFrameShape( QFrame::NoFrame );
|
||||
view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
|
||||
model->loadPlaylist( pl );
|
||||
pl->resolve();
|
||||
|
||||
m_playlistViews.insert( pl, view );
|
||||
return view;
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::ViewPage*
|
||||
ViewManager::show( const Tomahawk::playlist_ptr& playlist )
|
||||
@@ -156,15 +172,7 @@ ViewManager::show( const Tomahawk::playlist_ptr& playlist )
|
||||
PlaylistView* view;
|
||||
if ( !m_playlistViews.contains( playlist ) )
|
||||
{
|
||||
view = new PlaylistView();
|
||||
PlaylistModel* model = new PlaylistModel();
|
||||
view->setPlaylistModel( model );
|
||||
view->setFrameShape( QFrame::NoFrame );
|
||||
view->setAttribute( Qt::WA_MacShowFocusRect, 0 );
|
||||
model->loadPlaylist( playlist );
|
||||
playlist->resolve();
|
||||
|
||||
m_playlistViews.insert( playlist, view );
|
||||
view = createPageForPlaylist( playlist );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@@ -67,6 +67,7 @@ public:
|
||||
|
||||
QWidget* widget() const { return m_widget; }
|
||||
PlaylistView* queue() const;
|
||||
TopBar* topbar() const { return m_topbar; }
|
||||
|
||||
bool isSuperCollectionVisible() const;
|
||||
bool isNewPlaylistPageVisible() const;
|
||||
@@ -76,14 +77,6 @@ public:
|
||||
Tomahawk::ViewPage* pageForInterface( PlaylistInterface* interface ) const;
|
||||
int positionInHistory( Tomahawk::ViewPage* page ) const;
|
||||
|
||||
// Returns the shown viewpage
|
||||
Tomahawk::ViewPage* show( const Tomahawk::playlist_ptr& playlist );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::dynplaylist_ptr& playlist );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::artist_ptr& artist );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::album_ptr& album );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::collection_ptr& collection );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::source_ptr& source );
|
||||
|
||||
Tomahawk::ViewPage* show( Tomahawk::ViewPage* page );
|
||||
|
||||
Tomahawk::ViewPage* welcomeWidget() const { return m_welcomeWidget; }
|
||||
@@ -94,6 +87,9 @@ public:
|
||||
Tomahawk::ViewPage* pageForDynPlaylist( const Tomahawk::dynplaylist_ptr& pl ) const;
|
||||
Tomahawk::ViewPage* pageForCollection( const Tomahawk::collection_ptr& pl ) const;
|
||||
|
||||
// only use this is you need to create a playlist and show it directly and want it to be
|
||||
// linked to the sidebar. call it right after creating the playlist
|
||||
PlaylistView* createPageForPlaylist( const Tomahawk::playlist_ptr& pl );
|
||||
signals:
|
||||
void numSourcesChanged( unsigned int sources );
|
||||
void numTracksChanged( unsigned int tracks );
|
||||
@@ -127,6 +123,14 @@ public slots:
|
||||
Tomahawk::ViewPage* showWelcomePage();
|
||||
void showCurrentTrack();
|
||||
|
||||
// Returns the shown viewpage
|
||||
Tomahawk::ViewPage* show( const Tomahawk::playlist_ptr& playlist );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::dynplaylist_ptr& playlist );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::artist_ptr& artist );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::album_ptr& album );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::collection_ptr& collection );
|
||||
Tomahawk::ViewPage* show( const Tomahawk::source_ptr& source );
|
||||
|
||||
void historyBack();
|
||||
void historyForward();
|
||||
void showHistory( int historyPosition );
|
||||
|
32
src/libtomahawk/webcollection.cpp
Normal file
32
src/libtomahawk/webcollection.cpp
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "webcollection.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
WebCollection::WebCollection( const source_ptr& source, const QString& name, QObject* parent )
|
||||
: Collection( source, name, parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
WebCollection::~WebCollection()
|
||||
{
|
||||
}
|
43
src/libtomahawk/webcollection.h
Normal file
43
src/libtomahawk/webcollection.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program 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, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef WEBCOLLECTION_H
|
||||
#define WEBCOLLECTION_H
|
||||
|
||||
#include "collection.h"
|
||||
#include "dllmacro.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT WebCollection : public Collection
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
WebCollection( const source_ptr& source, const QString& name = QString(), QObject* parent = 0 );
|
||||
virtual ~WebCollection();
|
||||
|
||||
virtual void removeTracks( const QDir& ) {}
|
||||
virtual void addTracks( const QList< QVariant >& ) {}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // WEBCOLLECTION_H
|
@@ -80,9 +80,9 @@ Scrobbler::trackStarted( const Tomahawk::result_ptr& track )
|
||||
trackInfo["artist"] = track->artist()->name();
|
||||
trackInfo["album"] = track->album()->name();
|
||||
trackInfo["duration"] = QString::number( track->duration() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
|
||||
s_scInfoIdentifier, Tomahawk::InfoSystem::InfoMiscSubmitNowPlaying,
|
||||
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ), Tomahawk::InfoSystem::InfoCustomData() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
|
||||
s_scInfoIdentifier, Tomahawk::InfoSystem::InfoSubmitNowPlaying,
|
||||
QVariant::fromValue< Tomahawk::InfoSystem::InfoCriteriaHash >( trackInfo ) );
|
||||
|
||||
m_scrobblePoint = ScrobblePoint( track->duration() / 2 );
|
||||
}
|
||||
@@ -128,9 +128,9 @@ Scrobbler::scrobble()
|
||||
{
|
||||
Q_ASSERT( QThread::currentThread() == thread() );
|
||||
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
|
||||
s_scInfoIdentifier, Tomahawk::InfoSystem::InfoMiscSubmitScrobble,
|
||||
QVariant(), Tomahawk::InfoSystem::InfoCustomData() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo(
|
||||
s_scInfoIdentifier, Tomahawk::InfoSystem::InfoSubmitScrobble,
|
||||
QVariant() );
|
||||
}
|
||||
|
||||
|
||||
@@ -141,13 +141,7 @@ Scrobbler::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type,
|
||||
Q_UNUSED( output );
|
||||
Q_UNUSED( customData );
|
||||
if ( caller == s_scInfoIdentifier )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
if ( type == Tomahawk::InfoSystem::InfoMiscSubmitNowPlaying )
|
||||
qDebug() << "Scrobbler received now playing response from InfoSystem";
|
||||
else if ( type == Tomahawk::InfoSystem::InfoMiscSubmitScrobble )
|
||||
qDebug() << "Scrobbler received scrobble response from InfoSystem";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -8,7 +8,6 @@ add_definitions( -DSIPDLLEXPORT_PRO )
|
||||
|
||||
set( jabberSources
|
||||
jabber.cpp
|
||||
jabber_p.cpp
|
||||
tomahawksipmessage.cpp
|
||||
tomahawksipmessagefactory.cpp
|
||||
avatarmanager.cpp
|
||||
@@ -16,7 +15,6 @@ set( jabberSources
|
||||
|
||||
set( jabberHeaders
|
||||
jabber.h
|
||||
jabber_p.h
|
||||
tomahawksipmessage.h
|
||||
tomahawksipmessagefactory.h
|
||||
avatarmanager.h
|
||||
|
@@ -10,7 +10,6 @@ set( googleHeaders
|
||||
|
||||
set( googleSources
|
||||
../jabber.cpp
|
||||
../jabber_p.cpp
|
||||
../tomahawksipmessage.cpp
|
||||
../tomahawksipmessagefactory.cpp
|
||||
../avatarmanager.cpp
|
||||
|
@@ -19,13 +19,27 @@
|
||||
|
||||
#include "jabber.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "tomahawksettings.h"
|
||||
#include "tomahawksipmessage.h"
|
||||
#include "tomahawksipmessagefactory.h"
|
||||
|
||||
#include <jreen/jid.h>
|
||||
#include <jreen/capabilities.h>
|
||||
#include <jreen/vcardupdate.h>
|
||||
#include <jreen/vcard.h>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
#include <qjson/serializer.h>
|
||||
|
||||
#include <QtPlugin>
|
||||
#include <QStringList>
|
||||
#include <QInputDialog>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QDateTime>
|
||||
#include <QTimer>
|
||||
|
||||
#include "ui_configwidget.h"
|
||||
|
||||
@@ -41,14 +55,16 @@ JabberFactory::icon() const
|
||||
return QIcon( ":/jabber-icon.png" );
|
||||
}
|
||||
|
||||
|
||||
JabberPlugin::JabberPlugin( const QString& pluginId )
|
||||
: SipPlugin( pluginId )
|
||||
, p( 0 )
|
||||
, m_menu( 0 )
|
||||
, m_addFriendAction( 0 )
|
||||
, m_state( Disconnected )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||
|
||||
m_configWidget = QWeakPointer< QWidget >( new QWidget );
|
||||
m_ui = new Ui_JabberConfig;
|
||||
m_ui->setupUi( m_configWidget.data() );
|
||||
@@ -60,17 +76,56 @@ JabberPlugin::JabberPlugin( const QString& pluginId )
|
||||
m_ui->jabberServer->setText( readServer() );
|
||||
m_ui->jabberPort->setValue( readPort() );
|
||||
|
||||
// setup JID object
|
||||
Jreen::JID jid = Jreen::JID( accountName() );
|
||||
|
||||
// general client setup
|
||||
m_client = new Jreen::Client( jid, m_currentPassword );
|
||||
m_client->registerStanzaExtension(new TomahawkSipMessageFactory);
|
||||
m_currentResource = QString::fromAscii( "tomahawk%1" ).arg( QString::number( qrand() % 10000 ) );
|
||||
m_client->setResource( m_currentResource );
|
||||
|
||||
// add VCardUpdate extension to own presence
|
||||
m_client->presence().addExtension( new Jreen::VCardUpdate() );
|
||||
|
||||
// initialize the AvatarManager
|
||||
m_avatarManager = new AvatarManager( m_client );
|
||||
|
||||
// setup disco
|
||||
m_client->disco()->setSoftwareVersion( "Tomahawk Player", TOMAHAWK_VERSION, CMAKE_SYSTEM );
|
||||
m_client->disco()->addIdentity( Jreen::Disco::Identity( "client", "type", "tomahawk", "en" ) );
|
||||
m_client->disco()->addFeature( TOMAHAWK_FEATURE );
|
||||
|
||||
// setup caps node, legacy peer detection - used before 0.1
|
||||
Jreen::Capabilities::Ptr caps = m_client->presence().findExtension<Jreen::Capabilities>();
|
||||
caps->setNode( TOMAHAWK_CAP_NODE_NAME );
|
||||
//FIXME: caps->setVersion( TOMAHAWK_VERSION );
|
||||
|
||||
// print connection parameters
|
||||
qDebug() << "Our JID set to:" << m_client->jid().full();
|
||||
qDebug() << "Our Server set to:" << m_client->server();
|
||||
qDebug() << "Our Port set to" << m_client->port();
|
||||
|
||||
// setup slots
|
||||
connect(m_client->connection(), SIGNAL(error(SocketError)), SLOT(onError(SocketError)));
|
||||
connect(m_client, SIGNAL(serverFeaturesReceived(QSet<QString>)), SLOT(onConnect()));
|
||||
connect(m_client, SIGNAL(disconnected(Jreen::Client::DisconnectReason)), SLOT(onDisconnect(Jreen::Client::DisconnectReason)));
|
||||
connect(m_client, SIGNAL(newMessage(Jreen::Message)), SLOT(onNewMessage(Jreen::Message)));
|
||||
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)));
|
||||
}
|
||||
|
||||
JabberPlugin::~JabberPlugin()
|
||||
{
|
||||
delete p;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::setProxy( QNetworkProxy* proxy )
|
||||
{
|
||||
p->setProxy( proxy );
|
||||
qDebug() << Q_FUNC_INFO << "Not implemented";
|
||||
}
|
||||
|
||||
|
||||
@@ -124,32 +179,13 @@ JabberPlugin::connectPlugin( bool startup )
|
||||
QString password = m_currentPassword = readPassword();
|
||||
unsigned int port = m_currentPort = readPort();
|
||||
|
||||
QStringList splitJid = jid.split( '@', QString::SkipEmptyParts );
|
||||
if ( splitJid.size() < 2 )
|
||||
{
|
||||
qDebug() << "JID did not have an @ in it, could not find a server part";
|
||||
return false;
|
||||
}
|
||||
qDebug() << "Connecting to the XMPP server..." << (m_state == Connected);
|
||||
qDebug() << m_client->jid().full();
|
||||
//m_client->setServer( m_client->jid().domain() );
|
||||
qDebug() << m_client->server() << m_client->port();
|
||||
|
||||
if ( port < 1 || port > 65535 || jid.isEmpty() || password.isEmpty() )
|
||||
{
|
||||
qDebug() << "Jabber credentials look wrong, not connecting";
|
||||
return false;
|
||||
}
|
||||
|
||||
delete p;
|
||||
p = new Jabber_p( jid, password, ( server.isEmpty() ? QString() : server ), port );
|
||||
|
||||
QObject::connect( p, SIGNAL( peerOnline( QString ) ), SIGNAL( peerOnline( QString ) ) );
|
||||
QObject::connect( p, SIGNAL( peerOffline( QString ) ), SIGNAL( peerOffline( QString ) ) );
|
||||
QObject::connect( p, SIGNAL( msgReceived( QString, QString ) ), SIGNAL( msgReceived( QString, QString ) ) );
|
||||
|
||||
QObject::connect( p, SIGNAL( connected() ), SLOT( onConnected() ) );
|
||||
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 ) ) );
|
||||
QObject::connect( p, SIGNAL( avatarReceived( QPixmap ) ), SIGNAL( avatarReceived( QPixmap) ) );
|
||||
QTimer::singleShot(1000, m_client, SLOT( connectToServer() ) );
|
||||
//m_client->connectToServer();
|
||||
|
||||
m_state = Connecting;
|
||||
emit stateChanged( m_state );
|
||||
@@ -159,58 +195,131 @@ JabberPlugin::connectPlugin( bool startup )
|
||||
void
|
||||
JabberPlugin::disconnectPlugin()
|
||||
{
|
||||
onDisconnected();
|
||||
qDebug() << Q_FUNC_INFO << (m_state == Connected);
|
||||
|
||||
if ( p )
|
||||
p->disconnect();
|
||||
if( m_state == Disconnected )
|
||||
return;
|
||||
|
||||
delete p;
|
||||
p = 0;
|
||||
foreach(const Jreen::JID &peer, m_peers.keys())
|
||||
{
|
||||
handlePeerStatus(peer, Jreen::Presence::Unavailable);
|
||||
}
|
||||
|
||||
|
||||
//m_roster->deleteLater();
|
||||
//m_roster = 0;
|
||||
//m_room->deleteLater();
|
||||
//m_room = 0;
|
||||
|
||||
m_peers.clear();
|
||||
m_legacy_peers.clear();
|
||||
|
||||
m_client->disconnectFromServer(true);
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::onConnected()
|
||||
JabberPlugin::onConnect()
|
||||
{
|
||||
if( !m_menu ) {
|
||||
m_menu = new QMenu( QString( "JREEN (" ).append( accountName() ).append(")" ) );
|
||||
m_addFriendAction = m_menu->addAction( "Add Friend..." );
|
||||
QAction *connectAction = m_menu->addAction( "Connect" );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
connect( m_addFriendAction, SIGNAL(triggered() ),
|
||||
this, SLOT( showAddFriendDialog() ) );
|
||||
connect( connectAction, SIGNAL( triggered() ), SLOT( connectPlugin() ) );
|
||||
|
||||
emit addMenu( m_menu );
|
||||
// update jid resource, servers like gtalk use resource binding and may
|
||||
// have changed our requested /resource
|
||||
if ( m_client->jid().resource() != m_currentResource )
|
||||
{
|
||||
m_currentResource = m_client->jid().resource();
|
||||
emit jidChanged( m_client->jid().full() );
|
||||
}
|
||||
|
||||
qDebug() << "Connected as:" << m_client->jid().full();
|
||||
|
||||
// set presence to least valid value
|
||||
m_client->setPresence(Jreen::Presence::XA, "Got Tomahawk? http://gettomahawk.com", -127);
|
||||
|
||||
// set ping timeout to 15 secs (TODO: verify if this works)
|
||||
m_client->setPingInterval(1000);
|
||||
|
||||
// load roster
|
||||
m_roster = new Jreen::SimpleRoster( m_client );
|
||||
m_roster->load();
|
||||
|
||||
//FIXME: this implementation is totally broken atm, so it's disabled to avoid harm :P
|
||||
// join MUC with bare jid as nickname
|
||||
//TODO: make the room a list of rooms and make that configurable
|
||||
QString mucNickname = QString( "tomahawk@conference.qutim.org/" ).append( QString( m_client->jid().bare() ).replace( "@", "-" ) );
|
||||
//m_room = new Jreen::MUCRoom(m_client, Jreen::JID( mucNickname ) );
|
||||
//m_room->setHistorySeconds(0);
|
||||
//m_room->join();
|
||||
|
||||
// treat muc participiants like contacts
|
||||
//connect( m_room, SIGNAL( messageReceived( Jreen::Message, bool ) ), this, SLOT( onNewMessage( Jreen::Message ) ) );
|
||||
//connect( m_room, SIGNAL( presenceReceived( Jreen::Presence, const Jreen::MUCRoom::Participant* ) ), this, SLOT( onNewPresence( Jreen::Presence ) ) );
|
||||
|
||||
m_state = Connected;
|
||||
|
||||
emit stateChanged( m_state );
|
||||
|
||||
addMenuHelper();
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::onDisconnected()
|
||||
JabberPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
{
|
||||
if( m_menu && m_addFriendAction ) {
|
||||
emit removeMenu( m_menu );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
delete m_menu;
|
||||
m_menu = 0;
|
||||
m_addFriendAction = 0; // deleted by menu
|
||||
}
|
||||
QString errorMessage;
|
||||
bool reconnect = false;
|
||||
int reconnectInSeconds = 0;
|
||||
|
||||
m_state = Disconnected;
|
||||
|
||||
emit stateChanged( m_state );
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::onAuthError( int code, const QString& msg )
|
||||
{
|
||||
switch( code )
|
||||
switch( reason )
|
||||
{
|
||||
case Jreen::Client::User:
|
||||
errorMessage = "User Interaction";
|
||||
break;
|
||||
case Jreen::Client::HostUnknown:
|
||||
errorMessage = "Host is unknown";
|
||||
break;
|
||||
case Jreen::Client::ItemNotFound:
|
||||
errorMessage = "Item not found";
|
||||
break;
|
||||
case Jreen::Client::AuthorizationError:
|
||||
emit error( SipPlugin::AuthError, msg );
|
||||
errorMessage = "Authorization Error";
|
||||
break;
|
||||
case Jreen::Client::RemoteStreamError:
|
||||
errorMessage = "Remote Stream Error";
|
||||
reconnect = true;
|
||||
break;
|
||||
case Jreen::Client::RemoteConnectionFailed:
|
||||
errorMessage = "Remote Connection failed";
|
||||
break;
|
||||
case Jreen::Client::InternalServerError:
|
||||
errorMessage = "Internal Server Error";
|
||||
reconnect = true;
|
||||
break;
|
||||
case Jreen::Client::SystemShutdown:
|
||||
errorMessage = "System shutdown";
|
||||
reconnect = true;
|
||||
reconnectInSeconds = 60;
|
||||
break;
|
||||
case Jreen::Client::Conflict:
|
||||
errorMessage = "Conflict";
|
||||
break;
|
||||
|
||||
case Jreen::Client::Unknown:
|
||||
errorMessage = "Unknown";
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug() << "Not all Client::DisconnectReasons checked";
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
switch( reason )
|
||||
{
|
||||
case Jreen::Client::User:
|
||||
break;
|
||||
|
||||
case Jreen::Client::AuthorizationError:
|
||||
emit error( SipPlugin::AuthError, errorMessage );
|
||||
break;
|
||||
|
||||
case Jreen::Client::HostUnknown:
|
||||
@@ -221,7 +330,7 @@ JabberPlugin::onAuthError( int code, const QString& msg )
|
||||
case Jreen::Client::SystemShutdown:
|
||||
case Jreen::Client::Conflict:
|
||||
case Jreen::Client::Unknown:
|
||||
emit error( SipPlugin::ConnectionError, msg );
|
||||
emit error( SipPlugin::ConnectionError, errorMessage );
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -230,29 +339,97 @@ JabberPlugin::onAuthError( int code, const QString& msg )
|
||||
break;
|
||||
}
|
||||
m_state = Disconnected;
|
||||
|
||||
emit stateChanged( m_state );
|
||||
|
||||
removeMenuHelper();
|
||||
|
||||
if(reconnect)
|
||||
QTimer::singleShot(reconnectInSeconds*1000, this, SLOT(connectPlugin()));
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::onAuthError( int code, const QString& msg )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::sendMsg(const QString& to, const QString& msg)
|
||||
{
|
||||
if ( p )
|
||||
p->sendMsg( to, msg );
|
||||
qDebug() << Q_FUNC_INFO << to << msg;
|
||||
|
||||
if ( !m_client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_legacy_peers.contains( to ) )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << to << "Send legacy message" << msg;
|
||||
Jreen::Message m( Jreen::Message::Chat, Jreen::JID(to), msg);
|
||||
m_client->send( m );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************
|
||||
* Obsolete this by a SipMessage class
|
||||
*/
|
||||
QJson::Parser parser;
|
||||
bool ok;
|
||||
QVariant v = parser.parse( msg.toAscii(), &ok );
|
||||
if ( !ok || v.type() != QVariant::Map )
|
||||
{
|
||||
qDebug() << "Invalid JSON in XMPP msg";
|
||||
return;
|
||||
}
|
||||
QVariantMap m = v.toMap();
|
||||
/*******************************************************/
|
||||
|
||||
TomahawkSipMessage *sipMessage;
|
||||
if(m["visible"].toBool())
|
||||
{
|
||||
sipMessage = new TomahawkSipMessage(m["ip"].toString(),
|
||||
m["port"].toInt(),
|
||||
m["uniqname"].toString(),
|
||||
m["key"].toString(),
|
||||
m["visible"].toBool()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
sipMessage = new TomahawkSipMessage();
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "Send sip messsage to " << to;
|
||||
Jreen::IQ iq( Jreen::IQ::Set, to );
|
||||
iq.addExtension( sipMessage );
|
||||
|
||||
m_client->send( iq, this, SLOT( onNewIq( Jreen::IQ, int ) ), SipMessageSent );
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::broadcastMsg(const QString& msg)
|
||||
{
|
||||
if ( p )
|
||||
p->broadcastMsg( msg );
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( !m_client )
|
||||
return;
|
||||
|
||||
foreach( const Jreen::JID& jid, m_peers.keys() )
|
||||
{
|
||||
sendMsg( jid.full(), msg );
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JabberPlugin::addContact(const QString& jid, const QString& msg)
|
||||
{
|
||||
if ( p )
|
||||
p->addContact( jid, msg );
|
||||
// Add contact to the Tomahawk group on the roster
|
||||
m_roster->subscribe( jid, msg, jid, QStringList() << "Tomahawk" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -287,13 +464,299 @@ JabberPlugin::checkSettings()
|
||||
m_currentServer = readServer();
|
||||
m_currentPort = readPort();
|
||||
|
||||
if ( reconnect && ( p || readAutoConnect() ) )
|
||||
if ( reconnect )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Reconnecting jreen plugin...";
|
||||
disconnectPlugin();
|
||||
|
||||
m_currentUsername = accountName();
|
||||
m_currentPassword = readPassword();
|
||||
m_currentServer = readServer();
|
||||
m_currentPort = readPort();
|
||||
|
||||
Jreen::JID jid = Jreen::JID( accountName() );
|
||||
m_client->setJID( jid );
|
||||
m_client->setPassword( m_currentPassword );
|
||||
m_client->setServer( m_currentServer );
|
||||
m_client->setPort( m_currentPort );
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Updated settings";
|
||||
connectPlugin( false );
|
||||
}
|
||||
}
|
||||
|
||||
void JabberPlugin::addMenuHelper()
|
||||
{
|
||||
if( !m_menu )
|
||||
{
|
||||
m_menu = new QMenu( QString( "JREEN (" ).append( accountName() ).append(")" ) );
|
||||
m_addFriendAction = m_menu->addAction( "Add Friend..." );
|
||||
|
||||
connect( m_addFriendAction, SIGNAL( triggered() ), this, SLOT( showAddFriendDialog() ) );
|
||||
|
||||
emit addMenu( m_menu );
|
||||
}
|
||||
}
|
||||
|
||||
void JabberPlugin::removeMenuHelper()
|
||||
{
|
||||
if( m_menu && m_addFriendAction )
|
||||
{
|
||||
emit removeMenu( m_menu );
|
||||
|
||||
delete m_menu;
|
||||
m_menu = 0;
|
||||
m_addFriendAction = 0; // deleted by menu
|
||||
}
|
||||
}
|
||||
|
||||
void JabberPlugin::onNewMessage(const Jreen::Message& message)
|
||||
{
|
||||
QString from = message.from().full();
|
||||
QString msg = message.body();
|
||||
|
||||
if ( msg.isEmpty() )
|
||||
return;
|
||||
|
||||
QJson::Parser parser;
|
||||
bool ok;
|
||||
QVariant v = parser.parse( msg.toAscii(), &ok );
|
||||
if ( !ok || v.type() != QVariant::Map )
|
||||
{
|
||||
QString to = from;
|
||||
QString response = QString( tr("I'm sorry -- I'm just an automatic presence used by Tomahawk Player"
|
||||
" (http://gettomahawk.com). If you are getting this message, the person you"
|
||||
" are trying to reach is probably not signed on, so please try again later!") );
|
||||
|
||||
// this is not a sip message, so we send it directly through the client
|
||||
m_client->send( Jreen::Message ( Jreen::Message::Chat, Jreen::JID(to), response) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "From:" << message.from().full() << ":" << message.body();
|
||||
emit msgReceived( from, msg );
|
||||
}
|
||||
|
||||
|
||||
void JabberPlugin::onNewPresence( const Jreen::Presence& presence)
|
||||
{
|
||||
Jreen::JID jid = presence.from();
|
||||
QString fulljid( jid.full() );
|
||||
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "* New presence: " << fulljid << presence.subtype();
|
||||
|
||||
if( jid == m_client->jid() )
|
||||
return;
|
||||
|
||||
if ( presence.error() ) {
|
||||
//qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: no" << "presence error";
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore anyone not Running tomahawk:
|
||||
Jreen::Capabilities::Ptr caps = presence.findExtension<Jreen::Capabilities>();
|
||||
if ( caps && ( caps->node() == TOMAHAWK_CAP_NODE_NAME ) )
|
||||
{
|
||||
// must be a jreen resource, implementation in gloox was broken
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: yes" << "caps " << caps->node();
|
||||
handlePeerStatus( jid, presence.subtype() );
|
||||
}
|
||||
else if( caps )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: maybe" << "caps " << caps->node()
|
||||
<< "requesting disco..";
|
||||
|
||||
// request disco features
|
||||
QString node = caps->node() + '#' + caps->ver();
|
||||
|
||||
Jreen::IQ iq( Jreen::IQ::Get, jid );
|
||||
iq.addExtension( new Jreen::Disco::Info( node ) );
|
||||
|
||||
m_client->send( iq, this, SLOT( onNewIq( Jreen::IQ, int ) ), RequestDisco );
|
||||
}
|
||||
else if( !caps )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Running tomahawk: no" << "no caps";
|
||||
}
|
||||
}
|
||||
|
||||
void JabberPlugin::onNewIq(const Jreen::IQ& iq, int context)
|
||||
{
|
||||
if( context == RequestDisco )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Received disco IQ...";
|
||||
Jreen::Disco::Info *discoInfo = iq.findExtension<Jreen::Disco::Info>().data();
|
||||
if(!discoInfo)
|
||||
return;
|
||||
iq.accept();
|
||||
|
||||
Jreen::JID jid = iq.from();
|
||||
|
||||
Jreen::DataForm::Ptr form = discoInfo->form();
|
||||
|
||||
if(discoInfo->features().contains( TOMAHAWK_FEATURE ))
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << jid.full() << "Running tomahawk/feature enabled: yes";
|
||||
|
||||
// the actual presence doesn't matter, it just needs to be "online"
|
||||
handlePeerStatus( jid, Jreen::Presence::Available );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << jid.full() << "Running tomahawk/feature enabled: no";
|
||||
|
||||
//LEGACY: accept resources starting with tomahawk too
|
||||
if( jid.resource().startsWith("tomahawk") )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << jid.full() << "Detected legacy tomahawk..";
|
||||
|
||||
// add to legacy peers, so we can send text messages instead of iqs
|
||||
m_legacy_peers.append( jid );
|
||||
|
||||
handlePeerStatus( jid, Jreen::Presence::Available );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(context == RequestedDisco)
|
||||
{
|
||||
qDebug() << "Sent IQ(Set), what should be happening here?";
|
||||
}
|
||||
else if(context == SipMessageSent )
|
||||
{
|
||||
qDebug() << "Sent SipMessage... what now?!";
|
||||
}
|
||||
/*else if(context == RequestedVCard )
|
||||
{
|
||||
qDebug() << "Requested VCard... what now?!";
|
||||
}*/
|
||||
else
|
||||
{
|
||||
|
||||
TomahawkSipMessage *sipMessage = iq.findExtension<TomahawkSipMessage>().data();
|
||||
if(sipMessage)
|
||||
{
|
||||
iq.accept();
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Got SipMessage ...";
|
||||
qDebug() << "ip" << sipMessage->ip();
|
||||
qDebug() << "port" << sipMessage->port();
|
||||
qDebug() << "uniqname" << sipMessage->uniqname();
|
||||
qDebug() << "key" << sipMessage->key();
|
||||
qDebug() << "visible" << sipMessage->visible();
|
||||
|
||||
|
||||
QVariantMap m;
|
||||
if( sipMessage->visible() )
|
||||
{
|
||||
m["visible"] = true;
|
||||
m["ip"] = sipMessage->ip();
|
||||
m["port"] = sipMessage->port();
|
||||
m["key"] = sipMessage->key();
|
||||
m["uniqname"] = sipMessage->uniqname();
|
||||
}
|
||||
else
|
||||
{
|
||||
m["visible"] = false;
|
||||
}
|
||||
|
||||
|
||||
QJson::Serializer ser;
|
||||
QByteArray ba = ser.serialize( m );
|
||||
QString msg = QString::fromAscii( ba );
|
||||
|
||||
QString from = iq.from().full();
|
||||
qDebug() << Q_FUNC_INFO << "From:" << from << ":" << msg;
|
||||
emit msgReceived( from, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool JabberPlugin::presenceMeansOnline(Jreen::Presence::Type p)
|
||||
{
|
||||
switch(p)
|
||||
{
|
||||
case Jreen::Presence::Invalid:
|
||||
case Jreen::Presence::Unavailable:
|
||||
case Jreen::Presence::Error:
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void JabberPlugin::handlePeerStatus(const Jreen::JID& jid, Jreen::Presence::Type presenceType)
|
||||
{
|
||||
QString fulljid = jid.full();
|
||||
|
||||
// "going offline" event
|
||||
if ( !presenceMeansOnline( presenceType ) &&
|
||||
( !m_peers.contains( jid ) ||
|
||||
presenceMeansOnline( m_peers.value( jid ) )
|
||||
)
|
||||
)
|
||||
{
|
||||
m_peers[ jid ] = presenceType;
|
||||
qDebug() << Q_FUNC_INFO << "* Peer goes offline:" << fulljid;
|
||||
|
||||
// remove peer from legacy peers
|
||||
if( m_legacy_peers.contains( jid ) )
|
||||
{
|
||||
m_legacy_peers.removeAll( jid );
|
||||
}
|
||||
|
||||
emit peerOffline( fulljid );
|
||||
return;
|
||||
}
|
||||
|
||||
// "coming online" event
|
||||
if( presenceMeansOnline( presenceType ) &&
|
||||
( !m_peers.contains( jid ) ||
|
||||
!presenceMeansOnline( m_peers.value( jid ) )
|
||||
)
|
||||
)
|
||||
{
|
||||
m_peers[ jid ] = 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[ jid ] = presenceType;
|
||||
}
|
||||
|
||||
void JabberPlugin::onNewAvatar(const QString& jid)
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << jid;
|
||||
Q_ASSERT(!m_avatarManager->avatar( jid ).isNull());
|
||||
|
||||
// find peers for the jid
|
||||
QList<Jreen::JID> peers = m_peers.keys();
|
||||
foreach(const Jreen::JID &peer, peers)
|
||||
{
|
||||
if( peer.bare() == jid )
|
||||
{
|
||||
emit avatarReceived ( peer.full(), 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 ) );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JabberPlugin::readPassword()
|
||||
{
|
||||
|
@@ -21,11 +21,29 @@
|
||||
#define JABBER_H
|
||||
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "jabber_p.h"
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
#include "avatarmanager.h"
|
||||
|
||||
#include <jreen/client.h>
|
||||
#include <jreen/disco.h>
|
||||
#include <jreen/message.h>
|
||||
#include <jreen/messagesession.h>
|
||||
#include <jreen/stanza.h>
|
||||
#include <jreen/jreen.h>
|
||||
#include <jreen/error.h>
|
||||
#include <jreen/presence.h>
|
||||
#include <jreen/vcard.h>
|
||||
#include <jreen/abstractroster.h>
|
||||
#include <jreen/connection.h>
|
||||
#include <jreen/mucroom.h>
|
||||
|
||||
#include <QNetworkProxy>
|
||||
|
||||
#define MYNAME "SIPJREEN"
|
||||
#define TOMAHAWK_FEATURE QLatin1String( "tomahawk:sip:v1" )
|
||||
#define TOMAHAWK_CAP_NODE_NAME QLatin1String( "http://tomahawk-player.org/" )
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
|
||||
class Ui_JabberConfig;
|
||||
|
||||
@@ -64,6 +82,8 @@ public:
|
||||
virtual void saveConfig();
|
||||
|
||||
void setProxy( QNetworkProxy* proxy );
|
||||
signals:
|
||||
void jidChanged( const QString& );
|
||||
|
||||
public slots:
|
||||
virtual bool connectPlugin( bool startup );
|
||||
@@ -78,17 +98,31 @@ protected:
|
||||
|
||||
private slots:
|
||||
void showAddFriendDialog();
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
void onConnect();
|
||||
void onDisconnect(Jreen::Client::DisconnectReason reason);
|
||||
void onAuthError(int code, const QString &msg);
|
||||
|
||||
void onNewPresence( const Jreen::Presence& presence );
|
||||
void onNewMessage( const Jreen::Message& message );
|
||||
void onError( const Jreen::Connection::SocketError& e )
|
||||
{
|
||||
qDebug() << e;
|
||||
}
|
||||
void onNewIq( const Jreen::IQ &iq, int context = NoContext );
|
||||
void onNewAvatar( const QString &jid );
|
||||
|
||||
private:
|
||||
QString readPassword();
|
||||
QString readServer();
|
||||
bool readAutoConnect();
|
||||
int readPort();
|
||||
|
||||
Jabber_p* p;
|
||||
void addMenuHelper();
|
||||
void removeMenuHelper();
|
||||
|
||||
bool presenceMeansOnline( Jreen::Presence::Type p );
|
||||
void handlePeerStatus( const Jreen::JID &jid, Jreen::Presence::Type presenceType );
|
||||
|
||||
QMenu* m_menu;
|
||||
QAction* m_addFriendAction;
|
||||
|
||||
@@ -99,6 +133,18 @@ private:
|
||||
ConnectionState m_state;
|
||||
|
||||
QWeakPointer< QWidget > m_configWidget;
|
||||
|
||||
QString m_currentResource;
|
||||
|
||||
// sort out
|
||||
Jreen::Client *m_client;
|
||||
|
||||
Jreen::MUCRoom *m_room;
|
||||
Jreen::SimpleRoster *m_roster;
|
||||
QHash<Jreen::JID, Jreen::Presence::Type> m_peers;
|
||||
enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard };
|
||||
QStringList m_legacy_peers;
|
||||
AvatarManager *m_avatarManager;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -1,576 +0,0 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Dominik Schmidt <dev@dominik-schmidt.de>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk 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.
|
||||
*
|
||||
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "jabber_p.h"
|
||||
#include "tomahawksipmessage.h"
|
||||
#include "tomahawksipmessagefactory.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "utils/tomahawkutils.h"
|
||||
|
||||
#include <jreen/capabilities.h>
|
||||
#include <jreen/tcpconnection.h>
|
||||
#include <jreen/vcardupdate.h>
|
||||
#include <jreen/vcard.h>
|
||||
|
||||
#include <qjson/parser.h>
|
||||
#include <qjson/serializer.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTime>
|
||||
#include <QTimer>
|
||||
#include <QString>
|
||||
#include <QRegExp>
|
||||
#include <QThread>
|
||||
#include <QVariant>
|
||||
#include <QMap>
|
||||
#include <QCryptographicHash>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QPixmap>
|
||||
|
||||
//remove
|
||||
#include <QLabel>
|
||||
#include <QtGui/QLabel>
|
||||
|
||||
#define TOMAHAWK_FEATURE QLatin1String( "tomahawk:sip:v1" )
|
||||
|
||||
#define TOMAHAWK_CAP_NODE_NAME QLatin1String( "http://tomahawk-player.org/" )
|
||||
|
||||
Jabber_p::Jabber_p( const QString& jid, const QString& password, const QString& server, const int port )
|
||||
: QObject()
|
||||
, m_server()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||
|
||||
// setup JID object
|
||||
m_jid = Jreen::JID( jid );
|
||||
|
||||
// general client setup
|
||||
m_client = new Jreen::Client( jid, password );
|
||||
if ( !server.isEmpty() )
|
||||
{
|
||||
m_client->setServer( server );
|
||||
m_client->setPort( port );
|
||||
}
|
||||
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() );
|
||||
|
||||
// initialize the AvatarManager
|
||||
m_avatarManager = new AvatarManager(m_client);
|
||||
|
||||
// setup disco
|
||||
m_client->disco()->setSoftwareVersion( "Tomahawk Player", TOMAHAWK_VERSION, CMAKE_SYSTEM );
|
||||
m_client->disco()->addIdentity( Jreen::Disco::Identity( "client", "type", "tomahawk", "en" ) );
|
||||
m_client->disco()->addFeature( TOMAHAWK_FEATURE );
|
||||
|
||||
// setup caps node, legacy peer detection - used before 0.1
|
||||
Jreen::Capabilities::Ptr caps = m_client->presence().findExtension<Jreen::Capabilities>();
|
||||
caps->setNode( TOMAHAWK_CAP_NODE_NAME );
|
||||
|
||||
// print connection parameters
|
||||
qDebug() << "Our JID set to:" << m_client->jid().full();
|
||||
qDebug() << "Our Server set to:" << m_client->server();
|
||||
qDebug() << "Our Port set to" << m_client->port();
|
||||
|
||||
m_client->setConnectionImpl( new Jreen::TcpConnection( m_client->server(), m_client->port() ) );
|
||||
|
||||
// setup slots
|
||||
connect(qobject_cast<Jreen::Connection*>(m_client->connection()), SIGNAL(error(const Jreen::Connection::SocketError&)), SLOT(onError(const Jreen::Connection::SocketError&)));
|
||||
connect(m_client, SIGNAL(serverFeaturesReceived(QSet<QString>)), SLOT(onConnect()));
|
||||
connect(m_client, SIGNAL(disconnected(Jreen::Client::DisconnectReason)), SLOT(onDisconnect(Jreen::Client::DisconnectReason)));
|
||||
connect(m_client, SIGNAL(destroyed(QObject*)), this, SLOT(onDestroy(QObject*)));
|
||||
connect(m_client, SIGNAL(newMessage(Jreen::Message)), SLOT(onNewMessage(Jreen::Message)));
|
||||
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...";
|
||||
m_client->connectToServer();
|
||||
}
|
||||
|
||||
|
||||
Jabber_p::~Jabber_p()
|
||||
{
|
||||
delete m_client;
|
||||
}
|
||||
|
||||
void
|
||||
Jabber_p::setProxy( QNetworkProxy* proxy )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "NOT IMPLEMENTED";
|
||||
}
|
||||
|
||||
void
|
||||
Jabber_p::disconnect()
|
||||
{
|
||||
if ( m_client )
|
||||
{
|
||||
m_client->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::sendMsg( const QString& to, const QString& msg )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << to << msg;
|
||||
|
||||
if ( !m_client ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if( m_legacy_peers.contains( to ) )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << to << "Send legacy message" << msg;
|
||||
Jreen::Message m( Jreen::Message::Chat, Jreen::JID(to), msg);
|
||||
m_client->send( m );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************
|
||||
* Obsolete this by a SipMessage class
|
||||
*/
|
||||
QJson::Parser parser;
|
||||
bool ok;
|
||||
QVariant v = parser.parse( msg.toAscii(), &ok );
|
||||
if ( !ok || v.type() != QVariant::Map )
|
||||
{
|
||||
qDebug() << "Invalid JSON in XMPP msg";
|
||||
return;
|
||||
}
|
||||
QVariantMap m = v.toMap();
|
||||
/*******************************************************/
|
||||
|
||||
TomahawkSipMessage *sipMessage;
|
||||
if(m["visible"].toBool())
|
||||
{
|
||||
sipMessage = new TomahawkSipMessage(m["ip"].toString(),
|
||||
m["port"].toInt(),
|
||||
m["uniqname"].toString(),
|
||||
m["key"].toString(),
|
||||
m["visible"].toBool()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
sipMessage = new TomahawkSipMessage();
|
||||
}
|
||||
|
||||
|
||||
qDebug() << "Send sip messsage to " << to;
|
||||
Jreen::IQ iq( Jreen::IQ::Set, to );
|
||||
iq.addExtension( sipMessage );
|
||||
|
||||
m_client->send( iq, this, SLOT( onNewIq( Jreen::IQ, int ) ), SipMessageSent );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::broadcastMsg( const QString &msg )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( !m_client )
|
||||
return;
|
||||
|
||||
foreach( const QString& jidstr, m_peers.keys() )
|
||||
{
|
||||
sendMsg( jidstr, msg );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::addContact( const QString& jid, const QString& msg )
|
||||
{
|
||||
// Add contact to the Tomahawk group on the roster
|
||||
m_roster->add( jid, jid, QStringList() << "Tomahawk" );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
Jabber_p::onConnect()
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
|
||||
// update jid resource, servers like gtalk use resource binding and may
|
||||
// have changed our requested /resource
|
||||
if ( m_client->jid().resource() != m_jid.resource() )
|
||||
{
|
||||
// TODO: check if this is still neccessary with jreen
|
||||
m_jid.setResource( m_client->jid().resource() );
|
||||
QString jidstr( m_jid.full() );
|
||||
emit jidChanged( jidstr );
|
||||
}
|
||||
|
||||
emit connected();
|
||||
qDebug() << "Connected as:" << m_jid.full();
|
||||
|
||||
// set presence to least valid value
|
||||
m_client->setPresence(Jreen::Presence::XA, "Got Tomahawk? http://gettomahawk.com", -127);
|
||||
|
||||
// set ping timeout to 15 secs (TODO: verify if this works)
|
||||
m_client->setPingInterval(15000);
|
||||
|
||||
// load roster
|
||||
m_roster = new Jreen::SimpleRoster( m_client );
|
||||
m_roster->load();
|
||||
|
||||
//FIXME: this implementation is totally broken atm, so it's disabled to avoid harm :P
|
||||
// join MUC with bare jid as nickname
|
||||
//TODO: make the room a list of rooms and make that configurable
|
||||
QString mucNickname = QString( "tomahawk@conference.qutim.org/" ).append( QString( m_jid.bare() ).replace( "@", "-" ) );
|
||||
m_room = new Jreen::MUCRoom(m_client, Jreen::JID( mucNickname ) );
|
||||
//m_room->setHistorySeconds(0);
|
||||
//m_room->join();
|
||||
|
||||
// treat muc participiants like contacts
|
||||
connect( m_room, SIGNAL( messageReceived( Jreen::Message, bool ) ), this, SLOT( onNewMessage( Jreen::Message ) ) );
|
||||
connect( m_room, SIGNAL( presenceReceived( Jreen::Presence, const Jreen::MUCRoom::Participant* ) ), this, SLOT( onNewPresence( Jreen::Presence ) ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Jabber_p::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
{
|
||||
QString error;
|
||||
bool reconnect = false;
|
||||
int reconnectInSeconds = 0;
|
||||
|
||||
switch( reason )
|
||||
{
|
||||
case Jreen::Client::User:
|
||||
error = "User Interaction";
|
||||
break;
|
||||
case Jreen::Client::HostUnknown:
|
||||
error = "Host is unknown";
|
||||
break;
|
||||
case Jreen::Client::ItemNotFound:
|
||||
error = "Item not found";
|
||||
break;
|
||||
case Jreen::Client::AuthorizationError:
|
||||
error = "Authorization Error";
|
||||
break;
|
||||
case Jreen::Client::RemoteStreamError:
|
||||
error = "Remote Stream Error";
|
||||
reconnect = true;
|
||||
break;
|
||||
case Jreen::Client::RemoteConnectionFailed:
|
||||
error = "Remote Connection failed";
|
||||
break;
|
||||
case Jreen::Client::InternalServerError:
|
||||
error = "Internal Server Error";
|
||||
reconnect = true;
|
||||
break;
|
||||
case Jreen::Client::SystemShutdown:
|
||||
error = "System shutdown";
|
||||
reconnect = true;
|
||||
reconnectInSeconds = 60;
|
||||
break;
|
||||
case Jreen::Client::Conflict:
|
||||
error = "Conflict";
|
||||
break;
|
||||
|
||||
case Jreen::Client::Unknown:
|
||||
error = "Unknown";
|
||||
break;
|
||||
|
||||
default:
|
||||
qDebug() << "Not all Client::DisconnectReasons checked";
|
||||
Q_ASSERT(false);
|
||||
break;
|
||||
}
|
||||
|
||||
qDebug() << "Disconnected from server:" << error;
|
||||
if( reason != Jreen::Client::User )
|
||||
{
|
||||
emit authError( reason, error );
|
||||
}
|
||||
|
||||
if(reconnect)
|
||||
QTimer::singleShot(reconnectInSeconds*1000, m_client, SLOT(connectToServer()));
|
||||
|
||||
emit disconnected();
|
||||
}
|
||||
|
||||
void
|
||||
Jabber_p::onNewMessage( const Jreen::Message& m )
|
||||
{
|
||||
QString from = m.from().full();
|
||||
QString msg = m.body();
|
||||
|
||||
if ( msg.isEmpty() )
|
||||
return;
|
||||
|
||||
QJson::Parser parser;
|
||||
bool ok;
|
||||
QVariant v = parser.parse( msg.toAscii(), &ok );
|
||||
if ( !ok || v.type() != QVariant::Map )
|
||||
{
|
||||
if ( m.from().domain().contains( "googlemail." )
|
||||
|| m.from().domain().contains( "gmail." )
|
||||
|| m.from().domain().contains( "gtalk." )
|
||||
)
|
||||
return;
|
||||
|
||||
QString to = from;
|
||||
QString response = QString( tr("I'm sorry -- I'm just an automatic presence used by Tomahawk Player"
|
||||
" (http://gettomahawk.com). If you are getting this message, the person you"
|
||||
" are trying to reach is probably not signed on, so please try again later!") );
|
||||
|
||||
// this is not a sip message, so we send it directly through the client
|
||||
m_client->send( Jreen::Message ( Jreen::Message::Chat, Jreen::JID(to), response) );
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "From:" << m.from().full() << ":" << m.body();
|
||||
emit msgReceived( from, msg );
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
||||
if( jid == m_jid )
|
||||
return;
|
||||
|
||||
if ( presence.error() ) {
|
||||
//qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: no" << "presence error";
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore anyone not Running tomahawk:
|
||||
Jreen::Capabilities::Ptr caps = presence.findExtension<Jreen::Capabilities>();
|
||||
if ( caps && ( caps->node() == TOMAHAWK_CAP_NODE_NAME ) )
|
||||
{
|
||||
// must be a jreen resource, implementation in gloox was broken
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: yes" << "caps " << caps->node();
|
||||
handlePeerStatus( fulljid, presence.subtype() );
|
||||
}
|
||||
else if( caps )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk: maybe" << "caps " << caps->node()
|
||||
<< "requesting disco..";
|
||||
|
||||
// request disco features
|
||||
QString node = caps->node() + '#' + caps->ver();
|
||||
|
||||
Jreen::IQ iq( Jreen::IQ::Get, jid );
|
||||
iq.addExtension( new Jreen::Disco::Info( node ) );
|
||||
|
||||
m_client->send( iq, this, SLOT( onNewIq( Jreen::IQ, int ) ), RequestDisco );
|
||||
}
|
||||
else if( !caps )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Running tomahawk: no" << "no caps";
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Jabber_p::onNewIq( const Jreen::IQ &iq, int context )
|
||||
{
|
||||
if( context == RequestDisco )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << "Received disco IQ...";
|
||||
Jreen::Disco::Info *discoInfo = iq.findExtension<Jreen::Disco::Info>().data();
|
||||
if(!discoInfo)
|
||||
return;
|
||||
iq.accept();
|
||||
|
||||
QString fulljid = iq.from().full();
|
||||
Jreen::DataForm::Ptr form = discoInfo->form();
|
||||
|
||||
if(discoInfo->features().contains( TOMAHAWK_FEATURE ))
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk/feature enabled: yes";
|
||||
|
||||
// the actual presence doesn't matter, it just needs to be "online"
|
||||
handlePeerStatus( fulljid, Jreen::Presence::Available );
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Running tomahawk/feature enabled: no";
|
||||
|
||||
//LEGACY: accept resources starting with tomahawk too
|
||||
if( iq.from().resource().startsWith("tomahawk") )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO << fulljid << "Detected legacy tomahawk..";
|
||||
|
||||
// add to legacy peers, so we can send text messages instead of iqs
|
||||
m_legacy_peers.append( fulljid );
|
||||
|
||||
handlePeerStatus( fulljid, Jreen::Presence::Available );
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(context == RequestedDisco)
|
||||
{
|
||||
qDebug() << "Sent IQ(Set), what should be happening here?";
|
||||
}
|
||||
else if(context == SipMessageSent )
|
||||
{
|
||||
qDebug() << "Sent SipMessage... what now?!";
|
||||
}
|
||||
/*else if(context == RequestedVCard )
|
||||
{
|
||||
qDebug() << "Requested VCard... what now?!";
|
||||
}*/
|
||||
else
|
||||
{
|
||||
|
||||
TomahawkSipMessage *sipMessage = iq.findExtension<TomahawkSipMessage>().data();
|
||||
if(sipMessage)
|
||||
{
|
||||
iq.accept();
|
||||
|
||||
qDebug() << Q_FUNC_INFO << "Got SipMessage ...";
|
||||
qDebug() << "ip" << sipMessage->ip();
|
||||
qDebug() << "port" << sipMessage->port();
|
||||
qDebug() << "uniqname" << sipMessage->uniqname();
|
||||
qDebug() << "key" << sipMessage->key();
|
||||
qDebug() << "visible" << sipMessage->visible();
|
||||
|
||||
|
||||
QVariantMap m;
|
||||
if( sipMessage->visible() )
|
||||
{
|
||||
m["visible"] = true;
|
||||
m["ip"] = sipMessage->ip();
|
||||
m["port"] = sipMessage->port();
|
||||
m["key"] = sipMessage->key();
|
||||
m["uniqname"] = sipMessage->uniqname();
|
||||
}
|
||||
else
|
||||
{
|
||||
m["visible"] = false;
|
||||
}
|
||||
|
||||
|
||||
QJson::Serializer ser;
|
||||
QByteArray ba = ser.serialize( m );
|
||||
QString msg = QString::fromAscii( ba );
|
||||
|
||||
QString from = iq.from().full();
|
||||
qDebug() << Q_FUNC_INFO << "From:" << from << ":" << msg;
|
||||
emit msgReceived( from, msg );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Jabber_p::presenceMeansOnline( Jreen::Presence::Type p )
|
||||
{
|
||||
switch(p)
|
||||
{
|
||||
case Jreen::Presence::Invalid:
|
||||
case Jreen::Presence::Unavailable:
|
||||
case Jreen::Presence::Error:
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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 ) ||
|
||||
presenceMeansOnline( m_peers.value( fulljid ) )
|
||||
)
|
||||
)
|
||||
{
|
||||
m_peers[ fulljid ] = presenceType;
|
||||
qDebug() << Q_FUNC_INFO << "* Peer goes offline:" << fulljid;
|
||||
|
||||
// remove peer from legacy peers
|
||||
if( m_legacy_peers.contains( fulljid ) )
|
||||
{
|
||||
m_legacy_peers.removeAll( fulljid );
|
||||
}
|
||||
|
||||
emit peerOffline( fulljid );
|
||||
return;
|
||||
}
|
||||
|
||||
// "coming online" event
|
||||
if( presenceMeansOnline( presenceType ) &&
|
||||
( !m_peers.contains( fulljid ) ||
|
||||
!presenceMeansOnline( m_peers.value( fulljid ) )
|
||||
)
|
||||
)
|
||||
{
|
||||
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 ) );
|
||||
}
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
@@ -1,114 +0,0 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2011, Dominik Schmidt <dev@dominik-schmidt.de>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk 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.
|
||||
*
|
||||
* Tomahawk 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 Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef JABBER_P_H
|
||||
#define JABBER_P_H
|
||||
|
||||
#include "../sipdllmacro.h"
|
||||
|
||||
#include "avatarmanager.h"
|
||||
|
||||
#include <jreen/client.h>
|
||||
#include <jreen/disco.h>
|
||||
#include <jreen/message.h>
|
||||
#include <jreen/messagesession.h>
|
||||
#include <jreen/stanza.h>
|
||||
#include <jreen/jreen.h>
|
||||
#include <jreen/error.h>
|
||||
#include <jreen/presence.h>
|
||||
#include <jreen/vcard.h>
|
||||
#include <jreen/abstractroster.h>
|
||||
#include <jreen/connection.h>
|
||||
#include <jreen/mucroom.h>
|
||||
|
||||
#include <QObject>
|
||||
#include <QSharedPointer>
|
||||
#include <QMap>
|
||||
#include <QNetworkProxy>
|
||||
|
||||
|
||||
#if defined( WIN32 ) || defined( _WIN32 )
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
class SIPDLLEXPORT Jabber_p :
|
||||
public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Jabber_p( const QString& jid, const QString& password, const QString& server = "", const int port = -1 );
|
||||
virtual ~Jabber_p();
|
||||
|
||||
void setProxy( QNetworkProxy* proxy );
|
||||
|
||||
signals:
|
||||
void msgReceived( const QString&, const QString& ); //from, msg
|
||||
void peerOnline( const QString& );
|
||||
void peerOffline( const QString& );
|
||||
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& );
|
||||
|
||||
public slots:
|
||||
void sendMsg( const QString& to, const QString& msg );
|
||||
void broadcastMsg( const QString& msg );
|
||||
void addContact( const QString& jid, const QString& msg = QString() );
|
||||
void disconnect();
|
||||
|
||||
void onDisconnect(Jreen::Client::DisconnectReason reason);
|
||||
void onConnect();
|
||||
|
||||
private slots:
|
||||
virtual void onNewPresence( const Jreen::Presence& presence );
|
||||
virtual void onNewMessage( const Jreen::Message& msg );
|
||||
virtual void onError( const Jreen::Connection::SocketError& e )
|
||||
{
|
||||
qDebug() << e;
|
||||
}
|
||||
virtual void onDestroy( QObject */*object*/ )
|
||||
{
|
||||
qDebug() << Q_FUNC_INFO;
|
||||
}
|
||||
virtual void onNewIq( const Jreen::IQ &iq, int context = NoContext );
|
||||
virtual void onNewAvatar( const QString &jid );
|
||||
|
||||
private:
|
||||
bool presenceMeansOnline( Jreen::Presence::Type p );
|
||||
void handlePeerStatus( const Jreen::JID &jid, Jreen::Presence::Type presenceType );
|
||||
|
||||
Jreen::Client *m_client;
|
||||
Jreen::MUCRoom *m_room;
|
||||
Jreen::SimpleRoster *m_roster;
|
||||
Jreen::JID m_jid;
|
||||
QMap<Jreen::Presence::Type, QString> m_presences;
|
||||
QMap<QString, Jreen::Presence::Type> m_peers;
|
||||
QString m_server;
|
||||
|
||||
enum IqContext { NoContext, RequestDisco, RequestedDisco, SipMessageSent, RequestedVCard };
|
||||
|
||||
QStringList m_legacy_peers;
|
||||
|
||||
AvatarManager *m_avatarManager;
|
||||
};
|
||||
|
||||
#endif // JABBER_H
|
@@ -48,6 +48,9 @@
|
||||
#include "shortcuthandler.h"
|
||||
#include "scanmanager.h"
|
||||
#include "tomahawksettings.h"
|
||||
#include "globalactionmanager.h"
|
||||
#include "webcollection.h"
|
||||
#include "database/localcollection.h"
|
||||
|
||||
#include "audio/audioengine.h"
|
||||
#include "utils/xspfloader.h"
|
||||
@@ -223,7 +226,7 @@ TomahawkApp::init()
|
||||
|
||||
#else
|
||||
qDebug() << "Setting NAM.";
|
||||
TomahawkUtils::setNam( new QNetworkAccessManager );
|
||||
TomahawkUtils::setNam( new QNetworkAccessManager() );
|
||||
#endif
|
||||
|
||||
// Set up proxy
|
||||
@@ -241,7 +244,6 @@ TomahawkApp::init()
|
||||
else
|
||||
TomahawkUtils::setProxy( new QNetworkProxy( QNetworkProxy::NoProxy ) );
|
||||
|
||||
|
||||
Echonest::Config::instance()->setAPIKey( "JRIHWEP6GPOER2QQ6" );
|
||||
Echonest::Config::instance()->setNetworkAccessManager( TomahawkUtils::nam() );
|
||||
|
||||
@@ -249,7 +251,6 @@ TomahawkApp::init()
|
||||
|
||||
qDebug() << "Init SIP system.";
|
||||
|
||||
|
||||
#ifndef TOMAHAWK_HEADLESS
|
||||
if ( !m_headless )
|
||||
{
|
||||
@@ -462,12 +463,19 @@ void
|
||||
TomahawkApp::initLocalCollection()
|
||||
{
|
||||
source_ptr src( new Source( 0, "My Collection" ) );
|
||||
collection_ptr coll( new DatabaseCollection( src ) );
|
||||
collection_ptr coll( new LocalCollection( src ) );
|
||||
|
||||
src->addCollection( coll );
|
||||
SourceList::instance()->setLocal( src );
|
||||
// src->collection()->tracks();
|
||||
|
||||
// dummy source/collection for web-based result-hints.
|
||||
source_ptr dummy( new Source( -1, "" ) );
|
||||
dummy->setOnline();
|
||||
collection_ptr dummycol( new WebCollection( dummy ) );
|
||||
dummy->addCollection( dummycol );
|
||||
SourceList::instance()->setWebSource( dummy );
|
||||
|
||||
// to make the stats signal be emitted by our local source
|
||||
// this will update the sidebar, etc.
|
||||
DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( src );
|
||||
@@ -503,7 +511,9 @@ TomahawkApp::setupSIP()
|
||||
|
||||
qDebug() << "Connecting SIP classes";
|
||||
SipHandler::instance()->loadFromConfig( true );
|
||||
// SipHandler::instance()->setProxy( *TomahawkUtils::proxy() );
|
||||
|
||||
// m_sipHandler->setProxy( *TomahawkUtils::proxy() );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -520,29 +530,23 @@ TomahawkApp::activate()
|
||||
bool
|
||||
TomahawkApp::loadUrl( const QString& url )
|
||||
{
|
||||
if( url.contains( "tomahawk://" ) ) {
|
||||
QString cmd = url.mid( 11 );
|
||||
qDebug() << "tomahawk!s" << cmd;
|
||||
if( cmd.startsWith( "load/?" ) ) {
|
||||
cmd = cmd.mid( 6 );
|
||||
qDebug() << "loading.." << cmd;
|
||||
if( cmd.startsWith( "xspf=" ) ) {
|
||||
XSPFLoader* l = new XSPFLoader( true, this );
|
||||
qDebug() << "Loading spiff:" << cmd.mid( 5 );
|
||||
l->load( QUrl( cmd.mid( 5 ) ) );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if( url.startsWith( "tomahawk://" ) )
|
||||
return GlobalActionManager::instance()->parseTomahawkLink( url );
|
||||
else
|
||||
{
|
||||
QFile f( url );
|
||||
QFileInfo info( f );
|
||||
if( f.exists() && info.suffix() == "xspf" ) {
|
||||
XSPFLoader* l = new XSPFLoader( true, this );
|
||||
qDebug() << "Loading spiff:" << url;
|
||||
l->load( QUrl::fromUserInput( url ) );
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
@@ -555,6 +559,7 @@ TomahawkApp::instanceStarted( KDSingleApplicationGuard::Instance instance )
|
||||
return;
|
||||
}
|
||||
|
||||
loadUrl( instance.arguments.at( 1 ) );
|
||||
QString arg1 = instance.arguments[ 1 ];
|
||||
loadUrl( arg1 );
|
||||
}
|
||||
|
||||
|
@@ -21,6 +21,8 @@
|
||||
|
||||
#include <QAction>
|
||||
#include <QCloseEvent>
|
||||
#include <QShowEvent>
|
||||
#include <QHideEvent>
|
||||
#include <QInputDialog>
|
||||
#include <QPixmap>
|
||||
#include <QPropertyAnimation>
|
||||
@@ -161,7 +163,7 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
|
||||
qtsparkle::Updater* updater = new qtsparkle::Updater( updaterUrl, this );
|
||||
updater->SetNetworkAccessManager( TomahawkUtils::nam() );
|
||||
updater->SetVersion( VERSION );
|
||||
updater->SetVersion( TOMAHAWK_VERSION );
|
||||
|
||||
ui->menu_Help->addSeparator();
|
||||
QAction* checkForUpdates = ui->menu_Help->addAction( tr( "Check For Updates...") );
|
||||
@@ -267,6 +269,13 @@ TomahawkWindow::setupSignals()
|
||||
connect( ui->actionCreate_New_Station, SIGNAL( triggered() ), SLOT( createStation() ));
|
||||
connect( ui->actionAboutTomahawk, SIGNAL( triggered() ), SLOT( showAboutTomahawk() ) );
|
||||
connect( ui->actionExit, SIGNAL( triggered() ), APP, SLOT( quit() ) );
|
||||
#if defined( Q_OS_DARWIN )
|
||||
connect( ui->actionMinimize, SIGNAL( triggered() ), SLOT( minimize() ) );
|
||||
connect( ui->actionZoom, SIGNAL( triggered() ), SLOT( maximize() ) );
|
||||
#else
|
||||
ui->menuWindow->clear();
|
||||
ui->menuWindow->menuAction()->setVisible( false );
|
||||
#endif
|
||||
|
||||
// <SipHandler>
|
||||
connect( APP->sipHandler(), SIGNAL( connected() ), SLOT( onSipConnected() ) );
|
||||
@@ -294,7 +303,6 @@ TomahawkWindow::changeEvent( QEvent* e )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkWindow::closeEvent( QCloseEvent* e )
|
||||
{
|
||||
@@ -310,6 +318,27 @@ TomahawkWindow::closeEvent( QCloseEvent* e )
|
||||
e->accept();
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::showEvent( QShowEvent* e )
|
||||
{
|
||||
QMainWindow::showEvent( e );
|
||||
|
||||
#if defined( Q_OS_DARWIN )
|
||||
ui->actionMinimize->setDisabled( false );
|
||||
ui->actionZoom->setDisabled( false );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::hideEvent( QHideEvent* e )
|
||||
{
|
||||
QMainWindow::hideEvent( e );
|
||||
|
||||
#if defined( Q_OS_DARWIN )
|
||||
ui->actionMinimize->setDisabled( true );
|
||||
ui->actionZoom->setDisabled( true );
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::showSettingsDialog()
|
||||
@@ -530,3 +559,25 @@ TomahawkWindow::checkForUpdates()
|
||||
Tomahawk::checkForUpdates();
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::minimize()
|
||||
{
|
||||
if ( isMinimized() )
|
||||
{
|
||||
showNormal();
|
||||
} else {
|
||||
showMinimized();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::maximize()
|
||||
{
|
||||
if ( isMaximized() )
|
||||
{
|
||||
showNormal();
|
||||
} else {
|
||||
showMaximized();
|
||||
}
|
||||
}
|
||||
|
@@ -57,6 +57,8 @@ public:
|
||||
protected:
|
||||
void changeEvent( QEvent* e );
|
||||
void closeEvent( QCloseEvent* e );
|
||||
void showEvent( QShowEvent* e );
|
||||
void hideEvent( QHideEvent* e );
|
||||
|
||||
public slots:
|
||||
void createAutomaticPlaylist();
|
||||
@@ -84,6 +86,10 @@ private slots:
|
||||
|
||||
void onSipPluginAdded( SipPlugin* p );
|
||||
void onSipPluginRemoved( SipPlugin* p );
|
||||
|
||||
void minimize();
|
||||
void maximize();
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
void saveSettings();
|
||||
|
@@ -72,6 +72,13 @@
|
||||
<addaction name="actionToggleConnect"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuWindow">
|
||||
<property name="title">
|
||||
<string>&Window</string>
|
||||
</property>
|
||||
<addaction name="actionMinimize"/>
|
||||
<addaction name="actionZoom"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
@@ -82,6 +89,7 @@
|
||||
<addaction name="menuPlaylist"/>
|
||||
<addaction name="menuNetwork"/>
|
||||
<addaction name="menuSettings"/>
|
||||
<addaction name="menuWindow"/>
|
||||
<addaction name="menu_Help"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
@@ -157,6 +165,22 @@
|
||||
<string>Hide Offline Sources</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionMinimize">
|
||||
<property name="text">
|
||||
<string>Minimize</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+M</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoom">
|
||||
<property name="text">
|
||||
<string>Zoom</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Meta+Ctrl+Z</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
2
thirdparty/jreen
vendored
2
thirdparty/jreen
vendored
Submodule thirdparty/jreen updated: 040ca3f3cb...40fd6b0a3d
3
thirdparty/liblastfm2/src/CMakeLists.txt
vendored
3
thirdparty/liblastfm2/src/CMakeLists.txt
vendored
@@ -78,7 +78,7 @@ if(UNIX)
|
||||
endif(APPLE)
|
||||
endif(UNIX)
|
||||
if(WIN32)
|
||||
set(SOURCES ${SOURCES} ws/win/WNetworkConnectionMonitor_win.cpp)
|
||||
set(SOURCES ${SOURCES} ws/win/WNetworkConnectionMonitor_win.cpp ws/win/Pac.cpp ws/win/NdisEvents.cpp )
|
||||
set(MOC_HEADERS ${MOC_HEADERS} ws/win/WNetworkConnectionMonitor.h)
|
||||
endif(WIN32)
|
||||
|
||||
@@ -100,6 +100,7 @@ ENDIF()
|
||||
target_link_libraries(tomahawk_lastfm2
|
||||
${QT_LIBRARIES}
|
||||
${QT_QTDBUS_LIBRARY}
|
||||
|
||||
)
|
||||
|
||||
set_target_properties(tomahawk_lastfm2 PROPERTIES COMPILE_FLAGS "-DLASTFM_OHAI_QMAKE" )
|
||||
|
@@ -50,7 +50,7 @@ static struct NetworkAccessManagerInit
|
||||
// at two seconds, so that hangs startup
|
||||
if (!s.fAutoDetect && s.lpszProxy)
|
||||
{
|
||||
QUrl url( QString::fromUtf16(s.lpszProxy) );
|
||||
QUrl url( QString::fromUtf16((const unsigned short*)s.lpszProxy) );
|
||||
QNetworkProxy proxy( QNetworkProxy::HttpProxy );
|
||||
proxy.setHostName( url.host() );
|
||||
proxy.setPort( url.port() );
|
||||
|
17
thirdparty/liblastfm2/src/ws/win/ComSetup.h
vendored
17
thirdparty/liblastfm2/src/ws/win/ComSetup.h
vendored
@@ -23,9 +23,10 @@
|
||||
#endif
|
||||
|
||||
#include <objbase.h>
|
||||
#include <atlbase.h>
|
||||
#include <atlcom.h>
|
||||
|
||||
//#include <boost/range/atl.hpp>
|
||||
//#include <atlbase.h>
|
||||
//#include <atlcom.h>
|
||||
#include <winable.h>
|
||||
|
||||
/** @brief WsConnectionMonitor needs Com to work as early as possible so we do this
|
||||
* @author <doug@last.fm>
|
||||
@@ -37,7 +38,7 @@ public:
|
||||
{
|
||||
HRESULT hr = CoInitialize(0);
|
||||
m_bComInitialised = SUCCEEDED(hr);
|
||||
_ASSERT(m_bComInitialised);
|
||||
//_ASSERT(m_bComInitialised);
|
||||
if (m_bComInitialised) {
|
||||
setupSecurity();
|
||||
}
|
||||
@@ -45,10 +46,10 @@ public:
|
||||
|
||||
void setupSecurity()
|
||||
{
|
||||
CSecurityDescriptor sd;
|
||||
sd.InitializeFromThreadToken();
|
||||
HRESULT hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
|
||||
_ASSERT(SUCCEEDED(hr));
|
||||
//CSecurityDescriptor sd;
|
||||
//sd.InitializeFromThreadToken();
|
||||
//HRESULT hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
|
||||
//_ASSERT(SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
~ComSetup()
|
||||
|
@@ -26,6 +26,7 @@
|
||||
*/
|
||||
struct IeSettings : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
|
||||
{
|
||||
#ifndef WIN32
|
||||
IeSettings()
|
||||
{
|
||||
if (!WinHttpGetIEProxyConfigForCurrentUser(this)) {
|
||||
@@ -33,6 +34,7 @@ struct IeSettings : WINHTTP_CURRENT_USER_IE_PROXY_CONFIG
|
||||
lpszAutoConfigUrl = lpszProxy = lpszProxyBypass = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
~IeSettings()
|
||||
{
|
||||
|
20
thirdparty/liblastfm2/src/ws/win/NdisEvents.cpp
vendored
20
thirdparty/liblastfm2/src/ws/win/NdisEvents.cpp
vendored
@@ -32,22 +32,24 @@ NdisEvents::NdisEvents()
|
||||
|
||||
NdisEvents::~NdisEvents()
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (m_pSink)
|
||||
m_pSink->disconnect();
|
||||
if (m_pServices && m_pSink)
|
||||
m_pServices->CancelAsyncCall(m_pSink);
|
||||
#endif
|
||||
//if (m_pServices && m_pSink)
|
||||
//m_pServices->CancelAsyncCall(m_pSink);
|
||||
// and reference counting will take care of the WmiSink object
|
||||
}
|
||||
|
||||
HRESULT
|
||||
NdisEvents::registerForNdisEvents()
|
||||
{
|
||||
HRESULT hr = m_pLocator.CoCreateInstance(CLSID_WbemLocator);
|
||||
HRESULT hr = 0; //m_pLocator.CoCreateInstance(CLSID_WbemLocator);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
// Connect to the root\wmi namespace with the current user.
|
||||
hr = m_pLocator->ConnectServer(CComBSTR("ROOT\\WMI"), // strNetworkResource
|
||||
hr = 0; /*m_pLocator->ConnectServer(CComBSTR("ROOT\\WMI"), // strNetworkResource
|
||||
NULL, // strUser
|
||||
NULL, // strPassword
|
||||
NULL, // strLocale
|
||||
@@ -55,12 +57,12 @@ NdisEvents::registerForNdisEvents()
|
||||
CComBSTR(""), // strAuthority
|
||||
NULL, // pCtx
|
||||
&m_pServices
|
||||
);
|
||||
);*/
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
#ifndef WIN32
|
||||
m_pSink = new WmiSink(this);
|
||||
|
||||
#endif
|
||||
//////////////////////////
|
||||
|
||||
// other notifications we're not interested in right now include...
|
||||
@@ -75,12 +77,12 @@ NdisEvents::registerForNdisEvents()
|
||||
// MSNdis_StatusProtocolUnbind
|
||||
// MSNdis_StatusMediaSpecificIndication
|
||||
|
||||
CComBSTR wql("WQL");
|
||||
/*CComBSTR wql("WQL");
|
||||
CComBSTR query("SELECT * FROM MSNdis_StatusMediaDisconnect");
|
||||
hr = m_pServices->ExecNotificationQueryAsync(wql, query, 0, 0, m_pSink);
|
||||
|
||||
query = "SELECT * FROM MSNdis_StatusMediaConnect";
|
||||
hr = m_pServices->ExecNotificationQueryAsync(wql, query, 0, 0, m_pSink);
|
||||
hr = m_pServices->ExecNotificationQueryAsync(wql, query, 0, 0, m_pSink);*/
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@@ -21,8 +21,8 @@
|
||||
#define NDIS_EVENTS_H
|
||||
|
||||
#include <windows.h>
|
||||
#include <atlbase.h>
|
||||
#include <WbemCli.h>
|
||||
//#include <atlbase.h>
|
||||
//#include <WbemCli.h>
|
||||
|
||||
class NdisEvents
|
||||
{
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
virtual void onConnectionDown(BSTR name) = 0;
|
||||
|
||||
private:
|
||||
CComPtr<IWbemLocator> m_pLocator;
|
||||
CComPtr<IWbemServices> m_pServices;
|
||||
//CComPtr<IWbemLocator> m_pLocator;
|
||||
//CComPtr<IWbemServices> m_pServices;
|
||||
class WmiSink *m_pSink;
|
||||
};
|
||||
|
||||
|
30
thirdparty/liblastfm2/src/ws/win/Pac.cpp
vendored
30
thirdparty/liblastfm2/src/ws/win/Pac.cpp
vendored
@@ -21,8 +21,9 @@
|
||||
#include <QNetworkRequest>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <atlbase.h>
|
||||
#include <atlconv.h>
|
||||
//#include <atlbase.h>
|
||||
//#include <atlconv.h>
|
||||
#include <winhttp.h>
|
||||
|
||||
|
||||
static bool
|
||||
@@ -73,8 +74,10 @@ lastfm::Pac::Pac()
|
||||
|
||||
lastfm::Pac::~Pac()
|
||||
{
|
||||
#ifndef WIN32
|
||||
if (m_hSession)
|
||||
WinHttpCloseHandle(m_hSession);
|
||||
#endif
|
||||
}
|
||||
|
||||
QNetworkProxy
|
||||
@@ -86,7 +89,7 @@ lastfm::Pac::resolve(const QNetworkRequest &request, const wchar_t* pacUrl)
|
||||
if (!m_hSession)
|
||||
{
|
||||
QByteArray user_agent = request.rawHeader("user-agent");
|
||||
m_hSession = WinHttpOpen(CA2W(user_agent), WINHTTP_ACCESS_TYPE_NO_PROXY, 0, 0, WINHTTP_FLAG_ASYNC);
|
||||
//m_hSession = WinHttpOpen(CA2W(user_agent), WINHTTP_ACCESS_TYPE_NO_PROXY, 0, 0, WINHTTP_FLAG_ASYNC);
|
||||
}
|
||||
if (m_hSession)
|
||||
{
|
||||
@@ -95,33 +98,36 @@ lastfm::Pac::resolve(const QNetworkRequest &request, const wchar_t* pacUrl)
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
if (pacUrl)
|
||||
{
|
||||
opts.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
|
||||
opts.lpszAutoConfigUrl = pacUrl;
|
||||
//opts.dwFlags = WINHTTP_AUTOPROXY_CONFIG_URL;
|
||||
//opts.lpszAutoConfigUrl = pacUrl;
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
|
||||
opts.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
|
||||
//opts.dwFlags = WINHTTP_AUTOPROXY_AUTO_DETECT;
|
||||
//opts.dwAutoDetectFlags = WINHTTP_AUTO_DETECT_TYPE_DHCP | WINHTTP_AUTO_DETECT_TYPE_DNS_A;
|
||||
}
|
||||
opts.fAutoLogonIfChallenged = TRUE;
|
||||
|
||||
if (WinHttpGetProxyForUrl(m_hSession, request.url().toString().utf16(), &opts, &info)) {
|
||||
#ifndef WIN32
|
||||
if (WinHttpGetProxyForUrl(m_hSession, (const WCHAR*)(request.url().toString().utf16()), &opts, &info)) {
|
||||
if (info.lpszProxy)
|
||||
{
|
||||
QList<QNetworkProxy> proxies = parsePacResult(QString::fromUtf16(info.lpszProxy));
|
||||
QList<QNetworkProxy> proxies = parsePacResult(QString::fromUtf16((const ushort*)info.lpszProxy));
|
||||
if (!proxies.empty())
|
||||
{
|
||||
out = proxies.at(0);
|
||||
}
|
||||
GlobalFree(info.lpszProxy);
|
||||
// pay attention! casting away constness
|
||||
GlobalFree((void*)info.lpszProxy);
|
||||
}
|
||||
if (info.lpszProxyBypass)
|
||||
{
|
||||
GlobalFree(info.lpszProxyBypass);
|
||||
// pay attention! casting away constness
|
||||
GlobalFree((void*)info.lpszProxyBypass);
|
||||
}
|
||||
} else {
|
||||
m_bFailed = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return out;
|
||||
|
2
thirdparty/liblastfm2/src/ws/win/WmiSink.h
vendored
2
thirdparty/liblastfm2/src/ws/win/WmiSink.h
vendored
@@ -20,7 +20,7 @@
|
||||
#ifndef WMISINK_WIN_H
|
||||
#define WMISINK_WIN_H
|
||||
|
||||
#include "WbemCli.h"
|
||||
#include "wbemcli.h"
|
||||
|
||||
// Sink object for WMI NDIS notifications
|
||||
class WmiSink : public IWbemObjectSink
|
||||
|
32
thirdparty/liblastfm2/src/ws/ws.cpp
vendored
32
thirdparty/liblastfm2/src/ws/ws.cpp
vendored
@@ -25,9 +25,13 @@
|
||||
#include <QDomElement>
|
||||
#include <QLocale>
|
||||
#include <QStringList>
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QUrl>
|
||||
static QNetworkAccessManager* nam = 0;
|
||||
|
||||
static QMap< QThread*, QNetworkAccessManager* > threadNamHash;
|
||||
static QMap< QThread*, bool > ourNamHash;
|
||||
static QMutex namAccessMutex;
|
||||
|
||||
QString
|
||||
lastfm::ws::host()
|
||||
@@ -192,17 +196,33 @@ lastfm::ws::parse( QNetworkReply* reply ) throw( ParseError )
|
||||
QNetworkAccessManager*
|
||||
lastfm::nam()
|
||||
{
|
||||
if (!::nam) ::nam = new NetworkAccessManager( qApp );
|
||||
return ::nam;
|
||||
QMutexLocker l( &namAccessMutex );
|
||||
QThread* thread = QThread::currentThread();
|
||||
if ( !threadNamHash.contains( thread ) )
|
||||
{
|
||||
NetworkAccessManager* newNam = new NetworkAccessManager();
|
||||
threadNamHash[thread] = newNam;
|
||||
ourNamHash[thread] = true;
|
||||
return newNam;
|
||||
}
|
||||
|
||||
return threadNamHash[thread];
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lastfm::setNetworkAccessManager( QNetworkAccessManager* nam )
|
||||
{
|
||||
delete ::nam;
|
||||
::nam = nam;
|
||||
nam->setParent( qApp ); // ensure it isn't deleted out from under us
|
||||
if ( !nam )
|
||||
return;
|
||||
|
||||
QMutexLocker l( &namAccessMutex );
|
||||
QThread* thread = QThread::currentThread();
|
||||
if ( threadNamHash.contains( thread ) && ourNamHash.contains( thread ) && ourNamHash[thread] )
|
||||
delete threadNamHash[thread];
|
||||
|
||||
threadNamHash[thread] = nam;
|
||||
ourNamHash[thread] = false;
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user