mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 03:10:12 +02:00
first saving non-working commit
This commit is contained in:
@@ -118,7 +118,7 @@ public:
|
|||||||
// these need to exist and be public for the json serialization stuff
|
// these need to exist and be public for the json serialization stuff
|
||||||
// you SHOULD NOT call them. They are used for an alternate CTOR method from json.
|
// you SHOULD NOT call them. They are used for an alternate CTOR method from json.
|
||||||
// maybe friend QObjectHelper and make them private?
|
// maybe friend QObjectHelper and make them private?
|
||||||
Playlist( const source_ptr& author )
|
explicit Playlist( const source_ptr& author )
|
||||||
: m_source( author )
|
: m_source( author )
|
||||||
, m_lastmodified( 0 )
|
, m_lastmodified( 0 )
|
||||||
{
|
{
|
||||||
@@ -155,7 +155,7 @@ public slots:
|
|||||||
|
|
||||||
void resolve();
|
void resolve();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// called from loadAllPlaylists DB cmd:
|
// called from loadAllPlaylists DB cmd:
|
||||||
explicit Playlist( const source_ptr& src,
|
explicit Playlist( const source_ptr& src,
|
||||||
const QString& currentrevision,
|
const QString& currentrevision,
|
||||||
@@ -173,9 +173,14 @@ private:
|
|||||||
const QString& info,
|
const QString& info,
|
||||||
const QString& creator,
|
const QString& creator,
|
||||||
bool shared );
|
bool shared );
|
||||||
|
|
||||||
void rundb();
|
QList<plentry_ptr> newEntries( const QList< plentry_ptr >& entries );
|
||||||
|
PlaylistRevision setNewRevision( const QString& rev,
|
||||||
|
const QList<QString>& neworderedguids,
|
||||||
|
const QList<QString>& oldorderedguids,
|
||||||
|
bool is_newest_rev,
|
||||||
|
const QMap< QString, Tomahawk::plentry_ptr >& addedmap );
|
||||||
|
private:
|
||||||
source_ptr m_source;
|
source_ptr m_source;
|
||||||
QString m_currentrevision;
|
QString m_currentrevision;
|
||||||
QString m_guid, m_title, m_info, m_creator;
|
QString m_guid, m_title, m_info, m_creator;
|
||||||
|
@@ -11,6 +11,7 @@ namespace Tomahawk
|
|||||||
class Collection;
|
class Collection;
|
||||||
class Playlist;
|
class Playlist;
|
||||||
class PlaylistEntry;
|
class PlaylistEntry;
|
||||||
|
class DynamicPlaylist;
|
||||||
class Query;
|
class Query;
|
||||||
class Result;
|
class Result;
|
||||||
class Source;
|
class Source;
|
||||||
@@ -18,6 +19,7 @@ namespace Tomahawk
|
|||||||
typedef QSharedPointer<Collection> collection_ptr;
|
typedef QSharedPointer<Collection> collection_ptr;
|
||||||
typedef QSharedPointer<Playlist> playlist_ptr;
|
typedef QSharedPointer<Playlist> playlist_ptr;
|
||||||
typedef QSharedPointer<PlaylistEntry> plentry_ptr;
|
typedef QSharedPointer<PlaylistEntry> plentry_ptr;
|
||||||
|
typedef QSharedPointer<DynamicPlaylist> dynplaylist_ptr;
|
||||||
typedef QSharedPointer<Query> query_ptr;
|
typedef QSharedPointer<Query> query_ptr;
|
||||||
typedef QSharedPointer<Result> result_ptr;
|
typedef QSharedPointer<Result> result_ptr;
|
||||||
typedef QSharedPointer<Source> source_ptr;
|
typedef QSharedPointer<Source> source_ptr;
|
||||||
|
@@ -91,6 +91,10 @@ SET( tomahawkSources ${tomahawkSources}
|
|||||||
database/databasecommand_updatesearchindex.cpp
|
database/databasecommand_updatesearchindex.cpp
|
||||||
database/databasecollection.cpp
|
database/databasecollection.cpp
|
||||||
|
|
||||||
|
dynamic/dynamicplaylist.cpp
|
||||||
|
dynamic/dynamiccontrol.cpp
|
||||||
|
dynamic/generatorfactory.cpp
|
||||||
|
|
||||||
scrobbler.cpp
|
scrobbler.cpp
|
||||||
xmppbot/xmppbot.cpp
|
xmppbot/xmppbot.cpp
|
||||||
web/api_v1.cpp
|
web/api_v1.cpp
|
||||||
@@ -222,6 +226,11 @@ SET( tomahawkHeaders ${tomahawkHeaders}
|
|||||||
network/filetransferconnection.h
|
network/filetransferconnection.h
|
||||||
network/dbsyncconnection.h
|
network/dbsyncconnection.h
|
||||||
|
|
||||||
|
dynamic/dynamicplaylist.h
|
||||||
|
dynamic/dynamiccontrol.h
|
||||||
|
dynamic/generatorfactory.h
|
||||||
|
dynamic/generatorinterface.h
|
||||||
|
|
||||||
musicscanner.h
|
musicscanner.h
|
||||||
scriptresolver.h
|
scriptresolver.h
|
||||||
tomahawksettings.h
|
tomahawksettings.h
|
||||||
@@ -308,6 +317,7 @@ INCLUDE_DIRECTORIES(
|
|||||||
sourcetree
|
sourcetree
|
||||||
topbar
|
topbar
|
||||||
utils
|
utils
|
||||||
|
dynamic
|
||||||
|
|
||||||
../rtaudio
|
../rtaudio
|
||||||
../alsa-playback
|
../alsa-playback
|
||||||
|
0
src/dynamic/dynamiccontrol.cpp
Normal file
0
src/dynamic/dynamiccontrol.cpp
Normal file
6
src/dynamic/dynamiccontrol.h
Normal file
6
src/dynamic/dynamiccontrol.h
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef DYNAMIC_PLAYLIST_CONTROL
|
||||||
|
#define DYNAMIC_PLAYLIST_CONTROL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
238
src/dynamic/dynamicplaylist.cpp
Normal file
238
src/dynamic/dynamicplaylist.cpp
Normal file
@@ -0,0 +1,238 @@
|
|||||||
|
#include "dynamicplaylist.h"
|
||||||
|
|
||||||
|
#include "tomahawk/tomahawkapp.h"
|
||||||
|
|
||||||
|
using namespace Tomahawk;
|
||||||
|
|
||||||
|
// Called by loadAllPlaylists command
|
||||||
|
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
|
||||||
|
const QString& currentrevision,
|
||||||
|
const QString& title,
|
||||||
|
const QString& info,
|
||||||
|
const QString& creator,
|
||||||
|
const QString& type,
|
||||||
|
bool shared,
|
||||||
|
int lastmod,
|
||||||
|
const QString& guid )
|
||||||
|
: Playlist( src, currentrevision, title, info, creator, shared, lastmod, guid )
|
||||||
|
{
|
||||||
|
qDebug() << "Creating Dynamic Playlist 1";
|
||||||
|
// TODO instantiate generator
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// called when a new playlist is created (no currentrevision, new guid)
|
||||||
|
DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author,
|
||||||
|
const QString& guid,
|
||||||
|
const QString& title,
|
||||||
|
const QString& info,
|
||||||
|
const QString& creator,
|
||||||
|
const QString& type,
|
||||||
|
bool shared )
|
||||||
|
: Playlist ( author, guid, title, info, creator, shared )
|
||||||
|
{
|
||||||
|
qDebug() << "Creating Dynamic Playlist 2";
|
||||||
|
// TODO instantiate generator
|
||||||
|
}
|
||||||
|
|
||||||
|
dynplaylist_ptr DynamicPlaylist::create( const Tomahawk::source_ptr& author,
|
||||||
|
const QString& guid,
|
||||||
|
const QString& title,
|
||||||
|
const QString& info,
|
||||||
|
const QString& creator,
|
||||||
|
bool shared )
|
||||||
|
{
|
||||||
|
// TODO default generator?
|
||||||
|
QString type = "default_generator";
|
||||||
|
dynplaylist_ptr dynplaylist = new dynplaylist_ptr( new DynamicPlaylist( author, guid, title, info, creator, type, shared ) );
|
||||||
|
|
||||||
|
DatabaseCommand_CreateDynamicPlaylist* cmd = new DatabaseCommand_CreateDynamicPlaylist( author, dynplaylist );
|
||||||
|
connect( cmd, SIGNAL(finished()), dynplaylist.data(), SIGNAL(created()) );
|
||||||
|
APP->database()->enqueue( QSharedPointer<DatabaseCommand>(cmd) );
|
||||||
|
dynplaylist->reportCreated( dynplaylist );
|
||||||
|
return dynplaylist;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 )
|
||||||
|
{
|
||||||
|
// get the newly added tracks
|
||||||
|
QList< plentry_ptr > added = newEntries( entries );
|
||||||
|
|
||||||
|
QStringList orderedguids;
|
||||||
|
foreach( plentry_ptr p, entries )
|
||||||
|
orderedguids << p->guid();
|
||||||
|
|
||||||
|
// no conflict resolution or partial updating for controls. all or nothing baby
|
||||||
|
|
||||||
|
// source making the change (localy user in this case)
|
||||||
|
source_ptr author = APP->sourcelist().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,
|
||||||
|
type,
|
||||||
|
STATIC,
|
||||||
|
controls );
|
||||||
|
APP->database()->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 )
|
||||||
|
{
|
||||||
|
// can skip the entry stuff. just overwrite with new info
|
||||||
|
source_ptr author = APP->sourcelist().getLocal();
|
||||||
|
// command writes new rev to DB and calls setRevision, which emits our signal
|
||||||
|
DatabaseCommand_SetDynamicPlaylistRevision* cmd =
|
||||||
|
new DatabaseCommand_SetDynamicPlaylistRevision( author,
|
||||||
|
guid(),
|
||||||
|
newrev,
|
||||||
|
oldrev,
|
||||||
|
type,
|
||||||
|
STATIC,
|
||||||
|
controls );
|
||||||
|
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicPlaylist::loadRevision( const QString& rev )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
|
||||||
|
DatabaseCommand_LoadDynamicPlaylist* cmd =
|
||||||
|
new DatabaseCommand_LoadDynamicPlaylist( rev.isEmpty() ? currentrevision() : rev, m_generator->mode() );
|
||||||
|
|
||||||
|
if( m_generator->mode() == ONDEMAND ) {
|
||||||
|
connect( cmd, SIGNAL( done( QString,
|
||||||
|
bool,
|
||||||
|
const QString,
|
||||||
|
QList< dyncontrol_ptr>,
|
||||||
|
bool ) ),
|
||||||
|
SLOT( setRevision( QString,
|
||||||
|
bool,
|
||||||
|
const QString,
|
||||||
|
QList< dyncontrol_ptr>,
|
||||||
|
bool) ) );
|
||||||
|
} else if( m_generator->mode() == STATIC ) {
|
||||||
|
connect( cmd, SIGNAL( done( QString,
|
||||||
|
QList< QString >,
|
||||||
|
QList< QString >,
|
||||||
|
QString,
|
||||||
|
QList< dyncontrol_ptr>,
|
||||||
|
bool,
|
||||||
|
const QMap< QString, Tomahawk::plentry_ptr >,
|
||||||
|
bool ) ),
|
||||||
|
SLOT( setRevision( QString,
|
||||||
|
QList< QString >,
|
||||||
|
QList< QString >,
|
||||||
|
QString,
|
||||||
|
QList< dyncontrol_ptr>,
|
||||||
|
bool,
|
||||||
|
const QMap< QString, Tomahawk::plentry_ptr >,
|
||||||
|
bool ) ) );
|
||||||
|
|
||||||
|
}
|
||||||
|
APP->database()->enqueue( QSharedPointer<DatabaseCommand>( cmd ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicPlaylist::remove( const Tomahawk::dynplaylist_ptr& playlist )
|
||||||
|
{
|
||||||
|
return remove( playlist.staticCast<Tomahawk::playlist_ptr>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicPlaylist::reportCreated( const Tomahawk::dynplaylist_ptr& self )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
Q_ASSERT( self.data() == this );
|
||||||
|
// will emit Collection::playlistCreated(...)
|
||||||
|
m_source->collection()->addPlaylist( self.staticCast<Tomahawk::playlist_ptr>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicPlaylist::reportDeleted( const Tomahawk::dynplaylist_ptr& self )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO;
|
||||||
|
Q_ASSERT( self.data() == this );
|
||||||
|
// will emit Collection::playlistCreated(...)
|
||||||
|
m_source->collection()->deletePlaylist( self.staticCast<Tomahawk::playlist_ptr>() );
|
||||||
|
}
|
||||||
|
|
||||||
|
// static version
|
||||||
|
void DynamicPlaylist::setRevision( const QString& rev,
|
||||||
|
const QList< QString >& neworderedguids,
|
||||||
|
const QList< QString >& oldorderedguids,
|
||||||
|
const QString& type,
|
||||||
|
const QList< dyncontrol_ptr>& controls,
|
||||||
|
bool is_newest_rev,
|
||||||
|
const QMap< QString, plentry_ptr >& addedmap,
|
||||||
|
bool applied )
|
||||||
|
{
|
||||||
|
// we're probably being called by a database worker thread
|
||||||
|
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< dyncontrol_ptr >" , (const void*)&controls ),
|
||||||
|
Q_ARG( bool, is_newest_rev ),
|
||||||
|
QGenericArgument( "QMap< QString,Tomahawk::plentry_ptr >" , (const void*)&addedmap ),
|
||||||
|
Q_ARG( bool, applied ) );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( m_generator->type() != type ) { // new generator needed
|
||||||
|
m_generator = generatorinterface_ptr( GeneratorFactory::create( type ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_generator->setControls( controls );
|
||||||
|
m_generator->setMode( ONDEMAND )
|
||||||
|
|
||||||
|
DynamicPlaylistRevision pr = DynamicPlaylistRevision( setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap ) );
|
||||||
|
pr.controls = controls;
|
||||||
|
pr.type = type;
|
||||||
|
pr.mode = STATIC;
|
||||||
|
|
||||||
|
if( applied )
|
||||||
|
setCurrentRevision( rev );
|
||||||
|
pr.applied = applied;
|
||||||
|
|
||||||
|
emit revisionLoaded( pr );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ondemand version
|
||||||
|
void DynamicPlaylist::setRevision( const QString& rev,
|
||||||
|
bool is_newest_rev,
|
||||||
|
const QString& type,
|
||||||
|
const QList< dyncontrol_ptr>& controls,
|
||||||
|
bool applied )
|
||||||
|
{
|
||||||
|
if( m_generator->type() != type ) { // new generator needed
|
||||||
|
m_generator = generatorinterface_ptr( GeneratorFactory::create( type ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
m_generator->setControls( controls );
|
||||||
|
m_generator->setMode( ONDEMAND )
|
||||||
|
|
||||||
|
DynamicPlaylistRevision pr;
|
||||||
|
pr.oldrevisionguid = m_currentrevision;
|
||||||
|
pr.revisionguid = rev;
|
||||||
|
pr.controls = controls;
|
||||||
|
pr.type = type;
|
||||||
|
pr.mode = ONDEMAND;
|
||||||
|
|
||||||
|
emit revisionLoaded( pr );
|
||||||
|
}
|
||||||
|
|
120
src/dynamic/dynamicplaylist.h
Normal file
120
src/dynamic/dynamicplaylist.h
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
#ifndef DYNAMIC_PLAYLIST_H
|
||||||
|
#define DYNAMIC_PLAYLIST_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QList>
|
||||||
|
#include <QSharedPointer>
|
||||||
|
|
||||||
|
#include "tomahawk/playlist.h"
|
||||||
|
#include "dynamic/generatorinterface.h"
|
||||||
|
|
||||||
|
namespace Tomahawk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subclass of playlist that adds the information needed to store a dynamic playlist.
|
||||||
|
* It uses normal PlaylistEntries but also has a mode, a generator, and a list of controls
|
||||||
|
*/
|
||||||
|
|
||||||
|
class DynamicPlaylist : public Playlist
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
Q_PROPERTY( GeneratorMode mode WRITE setMode READ mode )
|
||||||
|
Q_PROPERTY( QString type WRITE setType READ type )
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum DynamicPlaylistMode {
|
||||||
|
OnDemand = 0,
|
||||||
|
StaticPlaylist
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Generate an empty dynamic playlist with default generator
|
||||||
|
static Tomahawk::dynplaylist_ptr create( const source_ptr& author,
|
||||||
|
const QString& guid,
|
||||||
|
const QString& title,
|
||||||
|
const QString& info,
|
||||||
|
const QString& creator,
|
||||||
|
bool shared
|
||||||
|
);
|
||||||
|
static bool remove( const dynplaylist_ptr& playlist );
|
||||||
|
|
||||||
|
virtual void loadRevision( const QString& rev = "" );
|
||||||
|
|
||||||
|
GeneratorMode mode() const { return m_generator->mode(); }
|
||||||
|
QString type() const { return m_generator->type(); }
|
||||||
|
generatorinterface_ptr generator() const { return m_generator; }
|
||||||
|
|
||||||
|
// <IGNORE hack="true">
|
||||||
|
// these need to exist and be public for the json serialization stuff
|
||||||
|
// you SHOULD NOT call them. They are used for an alternate CTOR method from json.
|
||||||
|
// maybe friend QObjectHelper and make them private?
|
||||||
|
explicit DynamicPlaylist( const source_ptr& author )
|
||||||
|
: Playlist( author )
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "JSON";
|
||||||
|
}
|
||||||
|
void setMode( GeneratorMode mode ) { m_generator->setMode( mode ); }
|
||||||
|
void setType( const QString& type ) { /** TODO */; }
|
||||||
|
void setGenerator( const generatorinterface_ptr& gen_ptr ) { m_generator = gen_ptr; }
|
||||||
|
// </IGNORE>
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/// emitted when the playlist revision changes (whenever the playlist changes)
|
||||||
|
void revisionLoaded( Tomahawk::DynamicPlaylistRevision );
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
// want to update the playlist from the model?
|
||||||
|
// generate a newrev using uuid() and call this:
|
||||||
|
// if this is a static playlist, pass it a new list of entries. implicitly sets mode to static
|
||||||
|
void createNewRevision( const QString& newrev, const QString& oldrev, const QString& type, const QList< dyncontrol_ptr>& controls, const QList< plentry_ptr >& entries );
|
||||||
|
// if it is ondemand, no entries are needed implicitly sets mode to ondemand
|
||||||
|
void createNewRevision( const QString& newrev, const QString& oldrev, const QString& type, const QList< dyncontrol_ptr>& controls );
|
||||||
|
|
||||||
|
void reportCreated( const Tomahawk::dynplaylist_ptr& self );
|
||||||
|
void reportDeleted( const Tomahawk::dynplaylist_ptr& self );
|
||||||
|
|
||||||
|
// called from setdynamicplaylistrevision db cmd
|
||||||
|
// static version
|
||||||
|
void setRevision( const QString& rev,
|
||||||
|
const QList<QString>& neworderedguids,
|
||||||
|
const QList<QString>& oldorderedguids,
|
||||||
|
const QString& type,
|
||||||
|
const QList< dyncontrol_ptr>& controls,
|
||||||
|
bool is_newest_rev,
|
||||||
|
const QMap< QString, Tomahawk::plentry_ptr >& addedmap,
|
||||||
|
bool applied );
|
||||||
|
|
||||||
|
// ondemand version
|
||||||
|
void setRevision( const QString& rev,
|
||||||
|
bool is_newest_rev,
|
||||||
|
const QString& type,
|
||||||
|
const QList< dyncontrol_ptr>& controls,
|
||||||
|
bool applied );
|
||||||
|
private:
|
||||||
|
// called from loadAllPlaylists DB cmd:
|
||||||
|
explicit DynamicPlaylist( const source_ptr& src,
|
||||||
|
const QString& currentrevision,
|
||||||
|
const QString& title,
|
||||||
|
const QString& info,
|
||||||
|
const QString& creator,
|
||||||
|
const QString& type,
|
||||||
|
bool shared,
|
||||||
|
int lastmod,
|
||||||
|
const QString& guid = "" ); // populate db
|
||||||
|
|
||||||
|
// called when creating new playlist
|
||||||
|
explicit DynamicPlaylist( const source_ptr& author,
|
||||||
|
const QString& guid,
|
||||||
|
const QString& title,
|
||||||
|
const QString& info,
|
||||||
|
const QString& creator,
|
||||||
|
const QString& type,
|
||||||
|
bool shared );
|
||||||
|
|
||||||
|
private:
|
||||||
|
generatorinterface_ptr m_generator;
|
||||||
|
};
|
||||||
|
|
||||||
|
}; // namespace
|
||||||
|
|
||||||
|
#endif
|
23
src/dynamic/generatorfactory.cpp
Normal file
23
src/dynamic/generatorfactory.cpp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
#include "generatorfactory.h"
|
||||||
|
|
||||||
|
Tomahawk::GeneratorFactory::GeneratorFactory()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Tomahawk::GeneratorFactory::~GeneratorFactory()
|
||||||
|
{
|
||||||
|
qDeleteAll( m_factories.values() );
|
||||||
|
}
|
||||||
|
|
||||||
|
generatorinterface_ptr Tomahawk::GeneratorFactory::create ( const QString& type )
|
||||||
|
{
|
||||||
|
if( !m_factories.contains( type ) )
|
||||||
|
return generatorinterface_ptr();
|
||||||
|
|
||||||
|
return generatorinterface_ptr( m_factories.value( type )->create() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tomahawk::GeneratorFactory::registerFactory ( const QString& type, Tomahawk::GeneratorFactoryInterface* interface )
|
||||||
|
{
|
||||||
|
m_factories.insert( type, interface );
|
||||||
|
}
|
39
src/dynamic/generatorfactory.h
Normal file
39
src/dynamic/generatorfactory.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#ifndef GENERATOR_FACTORY_H
|
||||||
|
#define GENERATOR_FACTORY_H
|
||||||
|
|
||||||
|
#include <QHash>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Tomahawk {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generators should subclass this and have it create the custom Generator
|
||||||
|
*/
|
||||||
|
class GeneratorFactoryInterface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GeneratorInterface* create() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple factory that generates Generators from string type descriptors
|
||||||
|
*/
|
||||||
|
class GeneratorFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GeneratorFactory();
|
||||||
|
~GeneratorFactory();
|
||||||
|
|
||||||
|
generatorinterface_ptr create( const QString& type );
|
||||||
|
|
||||||
|
void registerFactory( const QString& type, GeneratorFactoryInterface* interface );
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<QString, GeneratorFactoryInterface*> m_factories;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
52
src/dynamic/generatorinterface.h
Normal file
52
src/dynamic/generatorinterface.h
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#ifndef GENERATOR_INTERFACE_H
|
||||||
|
#define GENERATOR_INTERFACE_H
|
||||||
|
|
||||||
|
#include <QtCore/QObject>
|
||||||
|
|
||||||
|
namespace Tomahawk {
|
||||||
|
|
||||||
|
enum GeneratorMode {
|
||||||
|
OnDemand = 0,
|
||||||
|
Static
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The abstract interface for Dynamic Playlist Generators. Generators have the following features:
|
||||||
|
* - They create new DynamicControls that are appropriate for the generator
|
||||||
|
* - They expose a list of controls that this generator currently is operating on
|
||||||
|
* - They have a state of OnDemand or Static
|
||||||
|
*/
|
||||||
|
class GeneratorInterface : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY( QString type READ type )
|
||||||
|
Q_PROPERTY( GeneratorMode mode READ mode WRITE setMode );
|
||||||
|
Q_ENUMS( GeneratorMode )
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit GeneratorInterface() {}
|
||||||
|
virtual ~GeneratorInterface() {}
|
||||||
|
|
||||||
|
// Can't make it pure otherwise we can't shove it in QVariants :-/
|
||||||
|
virtual dyncontrol_ptr createControl() const {}
|
||||||
|
|
||||||
|
/// The type of this generator
|
||||||
|
virtual QString type() const { return m_type; }
|
||||||
|
|
||||||
|
virtual GeneratorMode mode() const { return m_mode; }
|
||||||
|
virtual void setMode( GeneratorMode mode ) { m_mode = mode; }
|
||||||
|
|
||||||
|
// control functions
|
||||||
|
virtual QList< dyncontrol_ptr > controls() const { return m_controls; }
|
||||||
|
virtual void addControl( const dyncontrol_ptr& control ) { m_controls << control; }
|
||||||
|
virtual void clearControls() { m_controls.clear(); }
|
||||||
|
virtual void setControls( const QList< dyncontrol_ptr>& controls ) { m_controls = controls; }
|
||||||
|
private:
|
||||||
|
QString m_type;
|
||||||
|
GeneratorMode m_mode;
|
||||||
|
QList< dyncontrol_ptr > m_controls;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
201
src/playlist.cpp
201
src/playlist.cpp
@@ -168,21 +168,11 @@ void
|
|||||||
Playlist::createNewRevision( const QString& newrev, const QString& oldrev, const QList< plentry_ptr >& entries )
|
Playlist::createNewRevision( const QString& newrev, const QString& oldrev, const QList< plentry_ptr >& entries )
|
||||||
{
|
{
|
||||||
// qDebug() << "m_entries guids:";
|
// qDebug() << "m_entries guids:";
|
||||||
// foreach( plentry_ptr pp, m_entries ) qDebug() << pp->guid();
|
|
||||||
|
|
||||||
QSet<QString> currentguids;
|
|
||||||
foreach( plentry_ptr p, m_entries )
|
|
||||||
currentguids.insert( p->guid() ); // could be cached as member?
|
|
||||||
|
|
||||||
// calc list of newly added entries:
|
// calc list of newly added entries:
|
||||||
QList<plentry_ptr> added;
|
QList<plentry_ptr> added = newEntries( entries );
|
||||||
QStringList orderedguids;
|
QStringList orderedguids;
|
||||||
foreach( plentry_ptr p, entries )
|
foreach( plentry_ptr p, entries )
|
||||||
{
|
|
||||||
orderedguids << p->guid();
|
orderedguids << p->guid();
|
||||||
if( !currentguids.contains(p->guid()) )
|
|
||||||
added << p;
|
|
||||||
}
|
|
||||||
|
|
||||||
// source making the change (localy user in this case)
|
// source making the change (localy user in this case)
|
||||||
source_ptr author = APP->sourcelist().getLocal();
|
source_ptr author = APP->sourcelist().getLocal();
|
||||||
@@ -225,87 +215,9 @@ Playlist::setRevision( const QString& rev,
|
|||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//qDebug() << Q_FUNC_INFO << (qlonglong)this
|
|
||||||
// << rev << neworderedguids << oldorderedguids
|
PlaylistRevision pr = setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap );
|
||||||
// << "isnewest:" << is_newest_rev << addedmap << applied << m_entries
|
|
||||||
// ;
|
|
||||||
|
|
||||||
// build up correctly ordered new list of plentry_ptrs from
|
|
||||||
// existing ones, and the ones that have been added
|
|
||||||
QMap<QString, plentry_ptr> entriesmap;
|
|
||||||
foreach( const plentry_ptr& p, m_entries )
|
|
||||||
entriesmap.insert( p->guid(), p );
|
|
||||||
|
|
||||||
//qDebug() << "Entries map:" << entriesmap;
|
|
||||||
|
|
||||||
QList<plentry_ptr> entries;
|
|
||||||
//qDebug() << "m_entries:" << m_entries.count() << m_entries;
|
|
||||||
|
|
||||||
//qDebug() << "counters:" << neworderedguids.count() << entriesmap.count() << addedmap.count();
|
|
||||||
foreach( const QString& id, neworderedguids )
|
|
||||||
{
|
|
||||||
//qDebug() << "id:" << id;
|
|
||||||
//qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
|
||||||
//qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
|
||||||
//qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
|
||||||
//qDebug() << "m_entries" << m_entries;
|
|
||||||
|
|
||||||
if( entriesmap.contains( id ) )
|
|
||||||
{
|
|
||||||
entries.append( entriesmap.value( id ) );
|
|
||||||
}
|
|
||||||
else if( addedmap.contains( id ) )
|
|
||||||
{
|
|
||||||
entries.append( addedmap.value( id ) );
|
|
||||||
if( is_newest_rev ) m_entries.append( addedmap.value( id ) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Q_ASSERT( false ); // XXX
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//qDebug() << Q_FUNC_INFO << rev << entries.length() << applied;
|
|
||||||
|
|
||||||
PlaylistRevision pr;
|
|
||||||
pr.oldrevisionguid = m_currentrevision;
|
|
||||||
pr.revisionguid = rev;
|
|
||||||
|
|
||||||
// entries that have been removed:
|
|
||||||
QSet<QString> removedguids = oldorderedguids.toSet().subtract( neworderedguids.toSet() );
|
|
||||||
//qDebug() << "Removedguids:" << removedguids << "oldorederedguids" << oldorderedguids << "newog" << neworderedguids;
|
|
||||||
foreach( QString remid, removedguids )
|
|
||||||
{
|
|
||||||
// NB: entriesmap will contain old/removed entries only if the removal was done
|
|
||||||
// in the same session - after a restart, history is not in memory.
|
|
||||||
if( entriesmap.contains( remid ) )
|
|
||||||
{
|
|
||||||
pr.removed << entriesmap.value( remid );
|
|
||||||
if( is_newest_rev )
|
|
||||||
{
|
|
||||||
//qDebug() << "Removing from m_entries" << remid;
|
|
||||||
for( int k = 0 ; k<m_entries.length(); ++k )
|
|
||||||
{
|
|
||||||
if( m_entries.at(k)->guid() == remid )
|
|
||||||
{
|
|
||||||
//qDebug() << "removed at " << k;
|
|
||||||
m_entries.removeAt(k);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pr.added = addedmap.values();
|
|
||||||
|
|
||||||
//qDebug() << "Revision set:" << rev
|
|
||||||
// << "added" << pr.added.size()
|
|
||||||
// << "removed" << pr.removed.size()
|
|
||||||
// << "total entries" << m_entries.size();
|
|
||||||
|
|
||||||
pr.newlist = entries;
|
|
||||||
|
|
||||||
if( applied )
|
if( applied )
|
||||||
m_currentrevision = rev;
|
m_currentrevision = rev;
|
||||||
pr.applied = applied;
|
pr.applied = applied;
|
||||||
@@ -313,6 +225,94 @@ Playlist::setRevision( const QString& rev,
|
|||||||
emit revisionLoaded( pr );
|
emit revisionLoaded( pr );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PlaylistRevision
|
||||||
|
Playlist::setNewRevision( const QString& rev,
|
||||||
|
const QList<QString>& neworderedguids,
|
||||||
|
const QList<QString>& oldorderedguids,
|
||||||
|
bool is_newest_rev,
|
||||||
|
const QMap< QString, Tomahawk::plentry_ptr >& addedmap )
|
||||||
|
{
|
||||||
|
//qDebug() << Q_FUNC_INFO << (qlonglong)this
|
||||||
|
// << rev << neworderedguids << oldorderedguids
|
||||||
|
// << "isnewest:" << is_newest_rev << addedmap << applied << m_entries
|
||||||
|
// ;
|
||||||
|
|
||||||
|
// build up correctly ordered new list of plentry_ptrs from
|
||||||
|
// existing ones, and the ones that have been added
|
||||||
|
QMap<QString, plentry_ptr> entriesmap;
|
||||||
|
foreach( const plentry_ptr& p, m_entries )
|
||||||
|
entriesmap.insert( p->guid(), p );
|
||||||
|
|
||||||
|
//qDebug() << "Entries map:" << entriesmap;
|
||||||
|
|
||||||
|
QList<plentry_ptr> entries;
|
||||||
|
//qDebug() << "m_entries:" << m_entries.count() << m_entries;
|
||||||
|
|
||||||
|
//qDebug() << "counters:" << neworderedguids.count() << entriesmap.count() << addedmap.count();
|
||||||
|
foreach( const QString& id, neworderedguids )
|
||||||
|
{
|
||||||
|
//qDebug() << "id:" << id;
|
||||||
|
//qDebug() << "newordered:" << neworderedguids.count() << neworderedguids;
|
||||||
|
//qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
|
||||||
|
//qDebug() << "addedmap:" << addedmap.count() << addedmap;
|
||||||
|
//qDebug() << "m_entries" << m_entries;
|
||||||
|
|
||||||
|
if( entriesmap.contains( id ) )
|
||||||
|
{
|
||||||
|
entries.append( entriesmap.value( id ) );
|
||||||
|
}
|
||||||
|
else if( addedmap.contains( id ) )
|
||||||
|
{
|
||||||
|
entries.append( addedmap.value( id ) );
|
||||||
|
if( is_newest_rev ) m_entries.append( addedmap.value( id ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Q_ASSERT( false ); // XXX
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//qDebug() << Q_FUNC_INFO << rev << entries.length() << applied;
|
||||||
|
|
||||||
|
PlaylistRevision pr;
|
||||||
|
pr.oldrevisionguid = m_currentrevision;
|
||||||
|
pr.revisionguid = rev;
|
||||||
|
|
||||||
|
// entries that have been removed:
|
||||||
|
QSet<QString> removedguids = oldorderedguids.toSet().subtract( neworderedguids.toSet() );
|
||||||
|
//qDebug() << "Removedguids:" << removedguids << "oldorederedguids" << oldorderedguids << "newog" << neworderedguids;
|
||||||
|
foreach( QString remid, removedguids )
|
||||||
|
{
|
||||||
|
// NB: entriesmap will contain old/removed entries only if the removal was done
|
||||||
|
// in the same session - after a restart, history is not in memory.
|
||||||
|
if( entriesmap.contains( remid ) )
|
||||||
|
{
|
||||||
|
pr.removed << entriesmap.value( remid );
|
||||||
|
if( is_newest_rev )
|
||||||
|
{
|
||||||
|
//qDebug() << "Removing from m_entries" << remid;
|
||||||
|
for( int k = 0 ; k<m_entries.length(); ++k )
|
||||||
|
{
|
||||||
|
if( m_entries.at(k)->guid() == remid )
|
||||||
|
{
|
||||||
|
//qDebug() << "removed at " << k;
|
||||||
|
m_entries.removeAt(k);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pr.added = addedmap.values();
|
||||||
|
|
||||||
|
//qDebug() << "Revision set:" << rev
|
||||||
|
// << "added" << pr.added.size()
|
||||||
|
// << "removed" << pr.removed.size()
|
||||||
|
// << "total entries" << m_entries.size();
|
||||||
|
|
||||||
|
pr.newlist = entries;
|
||||||
|
}
|
||||||
|
|
||||||
void Playlist::resolve()
|
void Playlist::resolve()
|
||||||
{
|
{
|
||||||
@@ -361,3 +361,20 @@ Playlist::addEntries( const QList<query_ptr>& queries, const QString& oldrev )
|
|||||||
QString newrev = uuid();
|
QString newrev = uuid();
|
||||||
createNewRevision( newrev, oldrev, el );
|
createNewRevision( newrev, oldrev, el );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList< plentry_ptr >
|
||||||
|
Playlist::newEntries( const QList< plentry_ptr > entries )
|
||||||
|
{
|
||||||
|
QSet<QString> currentguids;
|
||||||
|
foreach( plentry_ptr p, m_entries )
|
||||||
|
currentguids.insert( p->guid() ); // could be cached as member?
|
||||||
|
|
||||||
|
// calc list of newly added entries:
|
||||||
|
QList<plentry_ptr> added;
|
||||||
|
foreach( plentry_ptr p, entries )
|
||||||
|
{
|
||||||
|
if( !currentguids.contains(p->guid()) )
|
||||||
|
added << p;
|
||||||
|
}
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user