1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-03-25 02:09:48 +01:00

Allow url result-hints, load them from XSPFs too.

Add support for various tomahawk:// links
This commit is contained in:
Leo Franchi 2011-05-01 01:27:34 -04:00
parent 4768f9acd7
commit ab2e91fdd6
20 changed files with 737 additions and 109 deletions

View File

@ -39,6 +39,7 @@ SET( tomahawkSources ${tomahawkSources}
musicscanner.cpp
shortcuthandler.cpp
globalactionmanager.cpp
scanmanager.cpp
tomahawkapp.cpp
main.cpp
@ -81,6 +82,7 @@ SET( tomahawkHeaders ${tomahawkHeaders}
musicscanner.h
scanmanager.h
shortcuthandler.h
globalactionmanager.h
)
IF(LIBLASTFM_FOUND)

341
src/globalactionmanager.cpp Normal file
View File

@ -0,0 +1,341 @@
/*
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 "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 <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 );
if( track.isLocalFile() ) { // 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 ) ) );
} else {
doBookmark( bookmarkpl, q );
}
return true;
}
return false;
}
void
GlobalActionManager::bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl )
{
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;
m_waitingToBookmark.clear();
// if nothing is playing, lets start this
// TODO
// if( !AudioEngine::instance()->isPlaying() )
}
void
GlobalActionManager::showPlaylist()
{
if( m_toShow.isNull() )
return;
ViewManager::instance()->show( m_toShow );
m_toShow.clear();
}

59
src/globalactionmanager.h Normal file
View File

@ -0,0 +1,59 @@
/*
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 );
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::query_ptr m_waitingToBookmark;
Tomahawk::playlist_ptr m_toShow;
static GlobalActionManager* s_instance;
};
#endif // GLOBALACTIONMANAGER_H

View File

@ -21,6 +21,7 @@ set( libSources
artist.cpp
album.cpp
collection.cpp
webcollection.cpp
playlist.cpp
resolver.cpp
query.cpp
@ -37,6 +38,7 @@ set( libSources
database/database.cpp
database/fuzzyindex.cpp
database/databasecollection.cpp
database/localcollection.cpp
database/databaseworker.cpp
database/databaseimpl.cpp
database/databaseresolver.cpp
@ -65,7 +67,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
@ -174,6 +175,7 @@ set( libHeaders
aclsystem.h
collection.h
webcollection.h
query.h
resolver.h
result.h
@ -222,6 +224,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

View File

@ -1,5 +1,5 @@
/* === 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
@ -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;

View File

@ -1,5 +1,5 @@
/* === 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
@ -60,7 +60,7 @@ DatabaseCommand_SetPlaylistRevision::postCommitHook()
qDebug() << "Source has gone offline, not emitting to GUI.";
return;
}
if ( m_localOnly )
return;
@ -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 );

View File

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

View File

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

View File

@ -0,0 +1,54 @@
/*
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>
#define MAGIC_BOOKMARK_GUID "_bookmarkplaylist"
LocalCollection::LocalCollection( const Tomahawk::source_ptr& source, QObject* parent )
: DatabaseCollection( source, parent )
{
}
Tomahawk::playlist_ptr
LocalCollection::bookmarksPlaylist()
{
return playlist( MAGIC_BOOKMARK_GUID );
}
void
LocalCollection::createBookmarksPlaylist()
{
if( bookmarksPlaylist().isNull() ) {
Tomahawk::playlist_ptr p = Tomahawk::Playlist::create( SourceList::instance()->getLocal(), MAGIC_BOOKMARK_GUID, tr( "Bookmarks" ), tr( "Saved tracks" ), QString(), false );
// connect( p.data(), SIGNAL( revisionLoaded( Tomahawk::PlaylistRevision ) ), this, SLOT( loaded( Tomahawk::PlaylistRevision ) ), Qt::QueuedConnection );
connect( p.data(), SIGNAL( created() ), this, SLOT( created() ), Qt::QueuedConnection );
// p->createNewRevision( uuid(), p->currentrevision(), QList< Tomahawk::plentry_ptr >() );
}
}
void
LocalCollection::created()
{
emit bookmarkPlaylistCreated( bookmarksPlaylist() );
}

View 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

View File

@ -30,7 +30,7 @@
using namespace Tomahawk;
DynamicPlaylist::DynamicPlaylist(const Tomahawk::source_ptr& author, const QString& type )
: Playlist(author)
: Playlist(author)
{
qDebug() << Q_FUNC_INFO << "JSON";
m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
@ -54,7 +54,7 @@ DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
bool shared,
int lastmod,
const QString& guid )
: Playlist( src, currentrevision, title, info, creator, createdOn, shared, lastmod, guid )
: Playlist( src, currentrevision, title, info, creator, createdOn, shared, lastmod, guid )
{
qDebug() << "Creating Dynamic Playlist 1";
// TODO instantiate generator
@ -72,7 +72,7 @@ DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author,
const QString& type,
GeneratorMode mode,
bool shared )
: Playlist ( author, guid, title, info, creator, shared )
: Playlist ( author, guid, title, info, creator, shared )
{
qDebug() << "Creating Dynamic Playlist 2";
m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
@ -113,15 +113,15 @@ DynamicPlaylist::setMode( int mode )
dynplaylist_ptr
DynamicPlaylist::create( const Tomahawk::source_ptr& author,
const QString& guid,
const QString& title,
const QString& info,
const QString& creator,
GeneratorMode mode,
bool shared )
const QString& guid,
const QString& title,
const QString& info,
const QString& creator,
GeneratorMode mode,
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 );
@ -148,10 +148,10 @@ DynamicPlaylist::createNewRevision( const QString& newUuid )
// create a new revision that will be a static playlist, as it has entries
void
DynamicPlaylist::createNewRevision( const QString& newrev,
const QString& oldrev,
const QString& type,
const QList< dyncontrol_ptr>& controls,
const QList< plentry_ptr >& entries )
const QString& oldrev,
const QString& type,
const QList< dyncontrol_ptr>& controls,
const QList< plentry_ptr >& entries )
{
// get the newly added tracks
QList< plentry_ptr > added = newEntries( entries );
@ -162,29 +162,29 @@ DynamicPlaylist::createNewRevision( const QString& newrev,
// no conflict resolution or partial updating for controls. all or nothing baby
// source making the change (local user in this case)
source_ptr author = SourceList::instance()->getLocal();
// command writes new rev to DB and calls setRevision, which emits our signal
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
new DatabaseCommand_SetDynamicPlaylistRevision( author,
guid(),
newrev,
oldrev,
orderedguids,
added,
entries,
type,
Static,
controls );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
// source making the change (local user in this case)
source_ptr author = SourceList::instance()->getLocal();
// command writes new rev to DB and calls setRevision, which emits our signal
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
new DatabaseCommand_SetDynamicPlaylistRevision( author,
guid(),
newrev,
oldrev,
orderedguids,
added,
entries,
type,
Static,
controls );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
// create a new revision that will be an ondemand playlist, as it has no entries
void
DynamicPlaylist::createNewRevision( const QString& newrev,
const QString& oldrev,
const QString& type,
const QList< dyncontrol_ptr>& controls )
const QString& oldrev,
const QString& type,
const QList< dyncontrol_ptr>& controls )
{
// can skip the entry stuff. just overwrite with new info
source_ptr author = SourceList::instance()->getLocal();
@ -237,7 +237,7 @@ DynamicPlaylist::loadRevision( const QString& rev )
bool ) ) );
}
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
Database::instance()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
}
bool
@ -257,8 +257,8 @@ DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self )
Q_ASSERT( !author().isNull() );
Q_ASSERT( !author()->collection().isNull() );
// will emit Collection::playlistCreated(...)
// qDebug() << "Creating dynplaylist belonging to:" << author().data() << author().isNull();
// qDebug() << "REPORTING DYNAMIC PLAYLIST CREATED:" << this << author()->friendlyName();
// qDebug() << "Creating dynplaylist belonging to:" << author().data() << author().isNull();
// qDebug() << "REPORTING DYNAMIC PLAYLIST CREATED:" << this << author()->friendlyName();
if( self->mode() == Static )
author()->collection()->addAutoPlaylist( self );
else
@ -339,33 +339,33 @@ void DynamicPlaylist::setRevision( const QString& rev,
setCurrentrevision( rev );
}
// qDebug() << "EMITTING REVISION LOADED 1!";
emit dynamicRevisionLoaded( dpr );
emit dynamicRevisionLoaded( dpr );
}
void
DynamicPlaylist::setRevision( const QString& rev,
const QList< QString >& neworderedguids,
const QList< QString >& oldorderedguids,
const QString& type,
const QList< QVariantMap>& controlsV,
bool is_newest_rev,
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
bool applied )
const QList< QString >& neworderedguids,
const QList< QString >& oldorderedguids,
const QString& type,
const QList< QVariantMap>& controlsV,
bool is_newest_rev,
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
bool applied )
{
if( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this,
"setRevision",
Qt::BlockingQueuedConnection,
Q_ARG( QString, rev ),
Q_ARG( QList<QString> , neworderedguids ),
Q_ARG( QList<QString> , oldorderedguids ),
Q_ARG( QString , type ),
QGenericArgument( "QList< QVariantMap > " , (const void*)&controlsV ),
Q_ARG( bool, is_newest_rev ),
QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr > " , (const void*)&addedmap ),
Q_ARG( bool, applied ) );
"setRevision",
Qt::BlockingQueuedConnection,
Q_ARG( QString, rev ),
Q_ARG( QList<QString> , neworderedguids ),
Q_ARG( QList<QString> , oldorderedguids ),
Q_ARG( QString , type ),
QGenericArgument( "QList< QVariantMap > " , (const void*)&controlsV ),
Q_ARG( bool, is_newest_rev ),
QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr > " , (const void*)&addedmap ),
Q_ARG( bool, applied ) );
return;
}
@ -416,10 +416,10 @@ void DynamicPlaylist::setRevision( const QString& rev,
void
DynamicPlaylist::setRevision( const QString& rev,
bool is_newest_rev,
const QString& type,
const QList< QVariantMap >& controlsV,
bool applied )
bool is_newest_rev,
const QString& type,
const QList< QVariantMap >& controlsV,
bool applied )
{
if( QThread::currentThread() != thread() )
{

View File

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

View File

@ -1,5 +1,5 @@
/* === 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
@ -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()

View File

@ -1,5 +1,5 @@
/* === 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
@ -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;
@ -57,7 +60,7 @@ signals:
private slots:
void setSources( const QList<Tomahawk::source_ptr>& sources );
void sourceSynced();
private:
void loadSources();
void add( const Tomahawk::source_ptr& source );
@ -66,8 +69,9 @@ 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;
};

View File

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

View File

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

View File

@ -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; }
@ -127,6 +120,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 );

View 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()
{
}

View 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

View File

@ -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"
@ -147,7 +150,6 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
, m_database( 0 )
, m_scanManager( 0 )
, m_audioEngine( 0 )
, m_sipHandler( 0 )
, m_servent( 0 )
, m_shortcutHandler( 0 )
, m_mainwindow( 0 )
@ -166,13 +168,13 @@ TomahawkApp::init()
{
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );
#ifdef TOMAHAWK_HEADLESS
#ifdef TOMAHAWK_HEADLESS
m_headless = true;
#else
#else
m_mainwindow = 0;
m_headless = arguments().contains( "--headless" );
setWindowIcon( QIcon( RESPATH "icons/tomahawk-icon-128x128.png" ) );
#endif
#endif
registerMetaTypes();
@ -193,12 +195,12 @@ TomahawkApp::init()
GeneratorFactory::registerFactory( "echonest", new EchonestFactory );
// Register shortcut handler for this platform
#ifdef Q_WS_MAC
#ifdef Q_WS_MAC
m_shortcutHandler = new MacShortcutHandler( this );
Tomahawk::setShortcutHandler( static_cast<MacShortcutHandler*>( m_shortcutHandler) );
Tomahawk::setApplicationHandler( this );
#endif
#endif
// Connect up shortcuts
if ( m_shortcutHandler )
@ -252,7 +254,7 @@ TomahawkApp::init()
qDebug() << "Init SIP system.";
m_sipHandler = new SipHandler( this );
#ifndef TOMAHAWK_HEADLESS
#ifndef TOMAHAWK_HEADLESS
if ( !m_headless )
{
qDebug() << "Init MainWindow.";
@ -260,7 +262,7 @@ TomahawkApp::init()
m_mainwindow->setWindowTitle( "Tomahawk" );
m_mainwindow->show();
}
#endif
#endif
qDebug() << "Init Local Collection.";
initLocalCollection();
@ -295,7 +297,6 @@ TomahawkApp::~TomahawkApp()
}
m_scriptResolvers.clear();
delete m_sipHandler;
delete m_servent;
delete m_scanManager;
#ifndef TOMAHAWK_HEADLESS
@ -322,7 +323,6 @@ TomahawkApp::audioControls()
}
#endif
void
TomahawkApp::registerMetaTypes()
{
@ -460,12 +460,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 );
@ -495,13 +502,14 @@ TomahawkApp::setupSIP()
//FIXME: jabber autoconnect is really more, now that there is sip -- should be renamed and/or split out of jabber-specific settings
if( !arguments().contains( "--nosip" ) && TomahawkSettings::instance()->jabberAutoConnect() )
{
#ifdef GLOOX_FOUND
#ifdef GLOOX_FOUND
m_xmppBot = new XMPPBot( this );
#endif
#endif
qDebug() << "Connecting SIP classes";
m_sipHandler->connectPlugins( true );
// m_sipHandler->setProxy( *TomahawkUtils::proxy() );
}
}
@ -518,28 +526,22 @@ 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 true;
return false;
}
@ -553,6 +555,7 @@ TomahawkApp::instanceStarted( KDSingleApplicationGuard::Instance instance )
return;
}
loadUrl( instance.arguments.at( 1 ) );
QString arg1 = instance.arguments[ 1 ];
loadUrl( arg1 );
}