diff --git a/CMakeLists.txt b/CMakeLists.txt
index 60b77d20e..69f6f6cfd 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,16 @@
PROJECT( tomahawk )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
+###
+### Tomahawk application info
+###
+SET( ORGANIZATION_NAME "Tomahawk" )
+SET( ORGANIZATION_DOMAIN "tomahawk-player.org" )
+SET( APPLICATION_NAME "Player" )
+SET( VERSION "0.0.0" )
+
+
+# set paths
SET( CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_SOURCE_DIR}/CMakeModules" )
SET( THIRDPARTY_DIR ${CMAKE_SOURCE_DIR}/thirdparty )
diff --git a/admin/mac/Info.plist b/admin/mac/Info.plist
index e1114d48c..ecf4c29fa 100644
--- a/admin/mac/Info.plist
+++ b/admin/mac/Info.plist
@@ -7,7 +7,7 @@
CFBundleExecutable
tomahawk
CFBundleIdentifier
- org.tomahawk.Tomahawk
+ org.tomahawk-player.org.Tomahawk
CFBundleInfoDictionaryVersion
6.0
CFBundlePackageType
diff --git a/admin/mac/deposx.sh b/admin/mac/deposx.sh
index 116c0ece4..3500895ce 100755
--- a/admin/mac/deposx.sh
+++ b/admin/mac/deposx.sh
@@ -62,7 +62,7 @@ function deposx_change
function deplib_change
{
install_name_tool -change /usr/local/Cellar/liblastfm/0.3.1/lib/liblastfm.0.dylib @executable_path/liblastfm.0.dylib $1
- install_name_tool -change libqjson.0.dylib @executable_path/libqjson.0.dylib $1
+ install_name_tool -change /usr/local/Cellar/qjson/0.7.1/lib/libqjson.0.dylib @executable_path/libqjson.0.dylib $1
install_name_tool -change /usr/local/lib/libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1
install_name_tool -change /usr/local/lib/libclucene-core.0.9.23.dylib @executable_path/libclucene-core.0.9.23.dylib $1
install_name_tool -change /usr/local/lib/libclucene-shared.0.9.23.dylib @executable_path/libclucene-shared.0.9.23.dylib $1
@@ -80,6 +80,11 @@ function deplib_change
install_name_tool -change $ORIGROOT/libsip_zeroconf.dylib @executable_path/libsip_zeroconf.dylib $1
install_name_tool -change $ORIGROOT/thirdparty/jdns/libtomahawk_jdns.dylib @executable_path/libtomahawk_jdns.dylib $1
install_name_tool -change $ORIGROOT/thirdparty/qtweetlib/libtomahawk_qtweetlib.dylib @executable_path/libtomahawk_qtweetlib.dylib $1
+
+ install_name_tool -change libqjson.0.dylib @executable_path/libqjson.0.dylib $1
+ install_name_tool -change libechonest.1.1.dylib @executable_path/libechonest.1.1.dylib $1
+ install_name_tool -change libclucene-core.0.9.23.dylib @executable_path/libclucene-core.0.9.23.dylib $1
+ install_name_tool -change libclucene-shared.0.9.23.dylib @executable_path/libclucene-shared.0.9.23.dylib $1
}
################################################################################
diff --git a/data/www/auth.html b/data/www/auth.html
index a8aac4c37..49358ef7c 100644
--- a/data/www/auth.html
+++ b/data/www/auth.html
@@ -44,7 +44,7 @@
diff --git a/data/www/tomahawk_banner_small.png b/data/www/tomahawk_banner_small.png
new file mode 100644
index 000000000..83a818d17
Binary files /dev/null and b/data/www/tomahawk_banner_small.png differ
diff --git a/resources.qrc b/resources.qrc
index fc3705795..231eb32b2 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -85,5 +85,6 @@
./data/icons/audio-x-generic-16x16.png
./data/www/auth.html
./data/www/auth.na.html
+
./data/www/tomahawk_banner_small.png
diff --git a/src/config.h.in b/src/config.h.in
index 8a8d1807d..59e6bc80e 100644
--- a/src/config.h.in
+++ b/src/config.h.in
@@ -1,6 +1,12 @@
#ifndef CONFIG_H_IN
#define CONFIG_H_IN
+#cmakedefine ORGANIZATION_NAME "${ORGANIZATION_NAME}"
+#cmakedefine ORGANIZATION_DOMAIN "${ORGANIZATION_DOMAIN}"
+#cmakedefine APPLICATION_NAME "${APPLICATION_NAME}"
+#cmakedefine VERSION "${VERSION}"
+
+
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#cmakedefine SNOW_LEOPARD
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index 90c3ec204..6373c1df1 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -43,6 +43,7 @@ set( libSources
database/databasecommand_allalbums.cpp
database/databasecommand_alltracks.cpp
database/databasecommand_addfiles.cpp
+ database/databasecommand_deletefiles.cpp
database/databasecommand_dirmtimes.cpp
database/databasecommand_loadfile.cpp
database/databasecommand_logplayback.cpp
@@ -181,6 +182,7 @@ set( libHeaders
database/databasecommand_allalbums.h
database/databasecommand_alltracks.h
database/databasecommand_addfiles.h
+ database/databasecommand_deletefiles.h
database/databasecommand_dirmtimes.h
database/databasecommand_loadfile.h
database/databasecommand_logplayback.h
diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp
index 1287d24a0..f002e23dc 100644
--- a/src/libtomahawk/audio/audioengine.cpp
+++ b/src/libtomahawk/audio/audioengine.cpp
@@ -252,7 +252,7 @@ AudioEngine::playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr&
{
qDebug() << Q_FUNC_INFO;
- m_playlist = playlist;
+ setPlaylist( playlist );
m_currentTrackPlaylist = playlist;
loadTrack( result );
@@ -298,6 +298,14 @@ AudioEngine::timerTriggered( qint64 time )
}
+void
+AudioEngine::setPlaylist( PlaylistInterface* playlist )
+{
+ m_playlist = playlist;
+ emit playlistChanged( playlist );
+}
+
+
void
AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
{
diff --git a/src/libtomahawk/audio/audioengine.h b/src/libtomahawk/audio/audioengine.h
index 840b3b821..7faf5a076 100644
--- a/src/libtomahawk/audio/audioengine.h
+++ b/src/libtomahawk/audio/audioengine.h
@@ -53,7 +53,7 @@ public slots:
void mute();
void playItem( PlaylistInterface* playlist, const Tomahawk::result_ptr& result );
- void setPlaylist( PlaylistInterface* playlist ) { m_playlist = playlist; }
+ void setPlaylist( PlaylistInterface* playlist );
void setQueue( PlaylistInterface* queue ) { m_queue = queue; }
void onTrackAboutToFinish();
@@ -72,6 +72,8 @@ signals:
void timerSeconds( unsigned int secondsElapsed );
void timerPercentage( unsigned int percentage );
+ void playlistChanged( PlaylistInterface* playlist );
+
void error( AudioErrorCode errorCode );
private slots:
diff --git a/src/libtomahawk/collection.cpp b/src/libtomahawk/collection.cpp
index b532a4c4a..7017257b9 100644
--- a/src/libtomahawk/collection.cpp
+++ b/src/libtomahawk/collection.cpp
@@ -153,10 +153,40 @@ Collection::setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& plist
void
-Collection::setTracks( const QList
& tracks, Tomahawk::collection_ptr collection )
+Collection::setTracks( const QList& tracks, const Tomahawk::collection_ptr& collection )
{
qDebug() << Q_FUNC_INFO << tracks.count() << collection->name();
m_tracks << tracks;
emit tracksAdded( tracks, collection );
}
+
+
+void
+Collection::delTracks( const QStringList& files, const Tomahawk::collection_ptr& collection )
+{
+ qDebug() << Q_FUNC_INFO << files.count() << collection->name();
+
+ QList tracks;
+
+ int i = 0;
+ foreach ( const query_ptr& query, m_tracks )
+ {
+ foreach ( QString file, files )
+ {
+ foreach ( const result_ptr& result, query->results() )
+ {
+ if ( file == result->url() )
+ {
+ qDebug() << Q_FUNC_INFO << "Found deleted result:" << file;
+ tracks << query;
+ m_tracks.removeAt( i );
+ }
+ }
+ }
+
+ i++;
+ }
+
+ emit tracksRemoved( tracks, collection );
+}
diff --git a/src/libtomahawk/collection.h b/src/libtomahawk/collection.h
index 1628f92de..4b467ee3f 100644
--- a/src/libtomahawk/collection.h
+++ b/src/libtomahawk/collection.h
@@ -9,6 +9,7 @@
#define TOMAHAWK_COLLECTION_H
#include
+#include
#include
#include
#include
@@ -56,7 +57,7 @@ public:
signals:
void tracksAdded( const QList& tracks, const Tomahawk::collection_ptr& );
- void tracksRemoved( const QList&, const Tomahawk::collection_ptr& );
+ void tracksRemoved( const QList& tracks, const Tomahawk::collection_ptr& );
void tracksFinished( const Tomahawk::collection_ptr& );
void playlistsAdded( const QList& );
@@ -66,12 +67,14 @@ signals:
void dynamicPlaylistsDeleted( const QList& );
public slots:
- virtual void addTracks( const QList &newitems ) = 0;
- virtual void removeTracks( const QList &olditems ) = 0;
+ virtual void addTracks( const QList& newitems ) = 0;
+ virtual void removeTracks( const QDir& dir ) = 0;
void setPlaylists( const QList& plists );
void setDynamicPlaylists( const QList< Tomahawk::dynplaylist_ptr >& dynplists );
- void setTracks( const QList& tracks, Tomahawk::collection_ptr collection );
+ void setTracks( const QList& tracks, const Tomahawk::collection_ptr& collection );
+
+ void delTracks( const QStringList& files, const Tomahawk::collection_ptr& collection );
protected:
QString m_name;
@@ -79,8 +82,8 @@ protected:
private:
source_ptr m_source;
- QList< Tomahawk::playlist_ptr > m_playlists;
QList< Tomahawk::query_ptr > m_tracks;
+ QList< Tomahawk::playlist_ptr > m_playlists;
QList< Tomahawk::dynplaylist_ptr > m_dynplaylists;
};
diff --git a/src/libtomahawk/database/databasecollection.cpp b/src/libtomahawk/database/databasecollection.cpp
index 55858c383..7d4a48e3a 100644
--- a/src/libtomahawk/database/databasecollection.cpp
+++ b/src/libtomahawk/database/databasecollection.cpp
@@ -3,6 +3,7 @@
#include "database/database.h"
#include "databasecommand_alltracks.h"
#include "databasecommand_addfiles.h"
+#include "databasecommand_deletefiles.h"
#include "databasecommand_loadallplaylists.h"
#include "databasecommand_loadalldynamicplaylists.h"
@@ -58,7 +59,7 @@ DatabaseCollection::loadTracks()
void
-DatabaseCollection::addTracks( const QList &newitems )
+DatabaseCollection::addTracks( const QList& newitems )
{
qDebug() << Q_FUNC_INFO << newitems.length();
DatabaseCommand_AddFiles* cmd = new DatabaseCommand_AddFiles( newitems, source() );
@@ -68,13 +69,12 @@ DatabaseCollection::addTracks( const QList &newitems )
void
-DatabaseCollection::removeTracks( const QList &olditems )
+DatabaseCollection::removeTracks( const QDir& dir )
{
- // FIXME
- Q_ASSERT( false );
-
- // TODO RemoveTracks cmd, probably builds a temp table of all the URLs in
- // olditems, then joins on that to batch-delete.
+ qDebug() << Q_FUNC_INFO << dir;
+ DatabaseCommand_DeleteFiles* cmd = new DatabaseCommand_DeleteFiles( dir, source() );
+
+ Database::instance()->enqueue( QSharedPointer( cmd ) );
}
diff --git a/src/libtomahawk/database/databasecollection.h b/src/libtomahawk/database/databasecollection.h
index 62b82eac6..cd5ea869f 100644
--- a/src/libtomahawk/database/databasecollection.h
+++ b/src/libtomahawk/database/databasecollection.h
@@ -1,6 +1,8 @@
#ifndef DATABASECOLLECTION_H
#define DATABASECOLLECTION_H
+#include
+
#include "collection.h"
#include "source.h"
#include "typedefs.h"
@@ -27,8 +29,8 @@ public:
virtual QList< Tomahawk::dynplaylist_ptr > dynamicPlaylists();
public slots:
- virtual void addTracks( const QList &newitems );
- virtual void removeTracks( const QList &olditems );
+ virtual void addTracks( const QList& newitems );
+ virtual void removeTracks( const QDir& dir );
private slots:
void dynamicPlaylistCreated( const Tomahawk::source_ptr& source, const QVariantList& data );
diff --git a/src/libtomahawk/database/databasecommand.cpp b/src/libtomahawk/database/databasecommand.cpp
index f1074954b..82e0c5cad 100644
--- a/src/libtomahawk/database/databasecommand.cpp
+++ b/src/libtomahawk/database/databasecommand.cpp
@@ -4,6 +4,7 @@
#include "databasecommand_addfiles.h"
#include "databasecommand_createplaylist.h"
+#include "databasecommand_deletefiles.h"
#include "databasecommand_deleteplaylist.h"
#include "databasecommand_logplayback.h"
#include "databasecommand_renameplaylist.h"
@@ -60,6 +61,13 @@ DatabaseCommand::factory( const QVariant& op, const source_ptr& source )
QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
return cmd;
}
+ else if( name == "deletefiles" )
+ {
+ DatabaseCommand_DeleteFiles * cmd = new DatabaseCommand_DeleteFiles;
+ cmd->setSource( source );
+ QJson::QObjectHelper::qvariant2qobject( op.toMap(), cmd );
+ return cmd;
+ }
else if( name == "createplaylist" )
{
DatabaseCommand_CreatePlaylist * cmd = new DatabaseCommand_CreatePlaylist;
diff --git a/src/libtomahawk/database/databasecommand_addfiles.cpp b/src/libtomahawk/database/databasecommand_addfiles.cpp
index 8eec10a93..0026c1f13 100644
--- a/src/libtomahawk/database/databasecommand_addfiles.cpp
+++ b/src/libtomahawk/database/databasecommand_addfiles.cpp
@@ -73,19 +73,14 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
TomahawkSqlQuery query_trackattr = dbi->newquery();
TomahawkSqlQuery query_file_del = dbi->newquery();
- query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) "
- "VALUES (?, ?, ?, ?, ?, ?, ?, ?)" );
- query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) "
- "VALUES (?,?,?,?,?)" );
- query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) "
- "VALUES (?,?,?)" );
+ query_file.prepare( "INSERT INTO file(source, url, size, mtime, md5, mimetype, duration, bitrate) VALUES (?, ?, ?, ?, ?, ?, ?, ?)" );
+ query_filejoin.prepare( "INSERT INTO file_join(file, artist, album, track, albumpos) VALUES (?, ?, ?, ?, ?)" );
+ query_trackattr.prepare( "INSERT INTO track_attributes(id, k, v) VALUES (?, ?, ?)" );
query_file_del.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" )
.arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
int added = 0;
- QVariant srcid = source()->isLocal() ?
- QVariant( QVariant::Int ) : source()->id();
-
+ QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
qDebug() << "Adding" << m_files.length() << "files to db for source" << srcid;
QList::iterator it;
@@ -94,18 +89,18 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
QVariant& v = *it;
QVariantMap m = v.toMap();
- QString url = m.value( "url" ).toString();
- int mtime = m.value( "mtime" ).toInt();
- int size = m.value( "size" ).toInt();
- QString hash = m.value( "hash" ).toString();
- QString mimetype = m.value( "mimetype" ).toString();
- int duration = m.value( "duration" ).toInt();
- int bitrate = m.value( "bitrate" ).toInt();
- QString artist = m.value( "artist" ).toString();
- QString album = m.value( "album" ).toString();
- QString track = m.value( "track" ).toString();
- int albumpos = m.value( "albumpos" ).toInt();
- int year = m.value( "year" ).toInt();
+ QString url = m.value( "url" ).toString();
+ int mtime = m.value( "mtime" ).toInt();
+ uint size = m.value( "size" ).toUInt();
+ QString hash = m.value( "hash" ).toString();
+ QString mimetype = m.value( "mimetype" ).toString();
+ uint duration = m.value( "duration" ).toUInt();
+ uint bitrate = m.value( "bitrate" ).toUInt();
+ QString artist = m.value( "artist" ).toString();
+ QString album = m.value( "album" ).toString();
+ QString track = m.value( "track" ).toString();
+ uint albumpos = m.value( "albumpos" ).toUInt();
+ int year = m.value( "year" ).toInt();
int fileid = 0, artistid = 0, albumid = 0, trackid = 0;
query_file_del.bindValue( 0, url );
@@ -139,9 +134,7 @@ DatabaseCommand_AddFiles::exec( DatabaseImpl* dbi )
v = m;
if( !source()->isLocal() )
- url = QString( "servent://%1\t%2" )
- .arg( source()->userName() )
- .arg( url );
+ url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( url );
bool isnew;
artistid = dbi->artistId( artist, isnew );
diff --git a/src/libtomahawk/database/databasecommand_addfiles.h b/src/libtomahawk/database/databasecommand_addfiles.h
index f1a79ca9a..8e8b5e11c 100644
--- a/src/libtomahawk/database/databasecommand_addfiles.h
+++ b/src/libtomahawk/database/databasecommand_addfiles.h
@@ -36,8 +36,8 @@ public:
void setFiles( const QVariantList& f ) { m_files = f; }
signals:
- void done( const QList&, Tomahawk::collection_ptr );
- void notify( const QList&, Tomahawk::collection_ptr );
+ void done( const QList&, const Tomahawk::collection_ptr& );
+ void notify( const QList&, const Tomahawk::collection_ptr& );
private:
QVariantList m_files;
diff --git a/src/libtomahawk/database/databasecommand_deletefiles.cpp b/src/libtomahawk/database/databasecommand_deletefiles.cpp
new file mode 100644
index 000000000..436bffcfc
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_deletefiles.cpp
@@ -0,0 +1,122 @@
+#include "databasecommand_deletefiles.h"
+
+#include
+
+#include "artist.h"
+#include "album.h"
+#include "collection.h"
+#include "database/database.h"
+#include "databasecommand_collectionstats.h"
+#include "databaseimpl.h"
+#include "network/controlconnection.h"
+
+using namespace Tomahawk;
+
+
+// After changing a collection, we need to tell other bits of the system:
+void
+DatabaseCommand_DeleteFiles::postCommitHook()
+{
+ qDebug() << Q_FUNC_INFO;
+
+ // make the collection object emit its tracksAdded signal, so the
+ // collection browser will update/fade in etc.
+ Collection* coll = source()->collection().data();
+
+ connect( this, SIGNAL( notify( QStringList, Tomahawk::collection_ptr ) ),
+ coll, SLOT( delTracks( QStringList, Tomahawk::collection_ptr ) ), Qt::QueuedConnection );
+
+ emit notify( m_files, source()->collection() );
+
+ // also re-calc the collection stats, to updates the "X tracks" in the sidebar etc:
+ DatabaseCommand_CollectionStats* cmd = new DatabaseCommand_CollectionStats( source() );
+ connect( cmd, SIGNAL( done( QVariantMap ) ),
+ source().data(), SLOT( setStats( QVariantMap ) ), Qt::QueuedConnection );
+ Database::instance()->enqueue( QSharedPointer( cmd ) );
+
+ if( source()->isLocal() )
+ Servent::instance()->triggerDBSync();
+}
+
+
+void
+DatabaseCommand_DeleteFiles::exec( DatabaseImpl* dbi )
+{
+ qDebug() << Q_FUNC_INFO;
+ Q_ASSERT( !source().isNull() );
+
+ int deleted = 0;
+ QVariant srcid = source()->isLocal() ? QVariant( QVariant::Int ) : source()->id();
+ TomahawkSqlQuery delquery = dbi->newquery();
+
+ if ( !m_dir.path().isEmpty() && source()->isLocal() )
+ {
+ qDebug() << "Deleting" << m_dir.path() << "from db for localsource" << srcid;
+ TomahawkSqlQuery dirquery = dbi->newquery();
+
+ dirquery.prepare( QString( "SELECT id, url FROM file WHERE source %1 AND url LIKE ?" )
+ .arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
+ delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND id = ?" )
+ .arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
+
+ dirquery.bindValue( 0, "file://" + m_dir.absolutePath() + "/%" );
+ dirquery.exec();
+
+ while ( dirquery.next() )
+ {
+ QFileInfo fi( dirquery.value( 1 ).toString().mid( 7 ) ); // remove file://
+ if ( fi.absolutePath() != m_dir.absolutePath() )
+ {
+ qDebug() << "Skipping subdir:" << fi.absolutePath();
+ continue;
+ }
+
+ m_ids << dirquery.value( 0 ).toUInt();
+ m_files << dirquery.value( 1 ).toString();
+ }
+
+ foreach ( const QVariant& id, m_ids )
+ {
+ delquery.bindValue( 0, id.toUInt() );
+ if( !delquery.exec() )
+ {
+ qDebug() << "Failed to delete file:"
+ << delquery.lastError().databaseText()
+ << delquery.lastError().driverText()
+ << delquery.boundValues();
+ continue;
+ }
+
+ deleted++;
+ }
+ }
+ else
+ {
+ delquery.prepare( QString( "DELETE FROM file WHERE source %1 AND url = ?" )
+ .arg( source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( source()->id() ) ) );
+
+ foreach( const QVariant& id, m_ids )
+ {
+ qDebug() << "Deleting" << id.toUInt() << "from db for source" << srcid;
+
+ const QString url = QString( "servent://%1\t%2" ).arg( source()->userName() ).arg( id.toString() );
+ m_files << url;
+
+ delquery.bindValue( 0, id.toUInt() );
+ if( !delquery.exec() )
+ {
+ qDebug() << "Failed to delete file:"
+ << delquery.lastError().databaseText()
+ << delquery.lastError().driverText()
+ << delquery.boundValues();
+ continue;
+ }
+
+ deleted++;
+ }
+ }
+
+ qDebug() << "Deleted" << deleted << m_ids << m_files;
+
+ emit done( m_files, source()->collection() );
+}
diff --git a/src/libtomahawk/database/databasecommand_deletefiles.h b/src/libtomahawk/database/databasecommand_deletefiles.h
new file mode 100644
index 000000000..d10fb98c7
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_deletefiles.h
@@ -0,0 +1,52 @@
+#ifndef DATABASECOMMAND_DELETEFILES_H
+#define DATABASECOMMAND_DELETEFILES_H
+
+#include
+#include
+#include
+
+#include "database/databasecommandloggable.h"
+#include "typedefs.h"
+#include "query.h"
+
+#include "dllmacro.h"
+
+class DLLEXPORT DatabaseCommand_DeleteFiles : public DatabaseCommandLoggable
+{
+Q_OBJECT
+Q_PROPERTY( QVariantList ids READ ids WRITE setIds )
+
+public:
+ explicit DatabaseCommand_DeleteFiles( QObject* parent = 0 )
+ : DatabaseCommandLoggable( parent )
+ {}
+
+ explicit DatabaseCommand_DeleteFiles( const QDir& dir, const Tomahawk::source_ptr& source, QObject* parent = 0 )
+ : DatabaseCommandLoggable( parent ), m_dir( dir )
+ {
+ setSource( source );
+ }
+
+ virtual QString commandname() const { return "deletefiles"; }
+
+ virtual void exec( DatabaseImpl* );
+ virtual bool doesMutates() const { return true; }
+ virtual void postCommitHook();
+
+ QStringList files() const { return m_files; }
+ void setFiles( const QStringList& f ) { m_files = f; }
+
+ QVariantList ids() const { return m_ids; }
+ void setIds( const QVariantList& i ) { m_ids = i; }
+
+signals:
+ void done( const QStringList&, const Tomahawk::collection_ptr& );
+ void notify( const QStringList&, const Tomahawk::collection_ptr& );
+
+private:
+ QDir m_dir;
+ QStringList m_files;
+ QVariantList m_ids;
+};
+
+#endif // DATABASECOMMAND_DELETEFILES_H
diff --git a/src/libtomahawk/database/databasecommand_dirmtimes.cpp b/src/libtomahawk/database/databasecommand_dirmtimes.cpp
index d8c11c799..42c7c7084 100644
--- a/src/libtomahawk/database/databasecommand_dirmtimes.cpp
+++ b/src/libtomahawk/database/databasecommand_dirmtimes.cpp
@@ -26,7 +26,7 @@ DatabaseCommand_DirMtimes::execSelect( DatabaseImpl* dbi )
{
query.prepare( QString( "SELECT name, mtime "
"FROM dirs_scanned "
- "WHERE name LIKE '%1%'" ).arg(m_prefix.replace( '\'',"''" ) ) );
+ "WHERE name LIKE '%1%'" ).arg( m_prefix.replace( '\'',"''" ) ) );
query.exec();
}
while( query.next() )
@@ -44,7 +44,7 @@ DatabaseCommand_DirMtimes::execUpdate( DatabaseImpl* dbi )
qDebug() << "Saving mtimes...";
TomahawkSqlQuery query = dbi->newquery();
query.exec( "DELETE FROM dirs_scanned" );
- query.prepare( "INSERT INTO dirs_scanned(name, mtime) VALUES(?,?)" );
+ query.prepare( "INSERT INTO dirs_scanned(name, mtime) VALUES(?, ?)" );
foreach( const QString& k, m_tosave.keys() )
{
diff --git a/src/libtomahawk/database/databasecommand_loadplaylistentries.cpp b/src/libtomahawk/database/databasecommand_loadplaylistentries.cpp
index 1f6a9a155..f81c03980 100644
--- a/src/libtomahawk/database/databasecommand_loadplaylistentries.cpp
+++ b/src/libtomahawk/database/databasecommand_loadplaylistentries.cpp
@@ -56,7 +56,7 @@ void DatabaseCommand_LoadPlaylistEntries::generateEntries( DatabaseImpl* dbi )
e->setLastmodified( 0 ); // TODO e->lastmodified = query.value(6).toInt();
e->setResultHint( query.value( 8 ).toString() );
- Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString(), false );
+ Tomahawk::query_ptr q = Tomahawk::Query::get( query.value( 2 ).toString(), query.value( 1 ).toString(), query.value( 3 ).toString() );
q->setResultHint( query.value( 8 ).toString() );
e->setQuery( q );
diff --git a/src/libtomahawk/database/databaseimpl.cpp b/src/libtomahawk/database/databaseimpl.cpp
index 006177647..2fd075625 100644
--- a/src/libtomahawk/database/databaseimpl.cpp
+++ b/src/libtomahawk/database/databaseimpl.cpp
@@ -19,7 +19,7 @@
*/
#include "schema.sql.h"
-#define CURRENT_SCHEMA_VERSION 21
+#define CURRENT_SCHEMA_VERSION 22
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
diff --git a/src/libtomahawk/database/schema.sql b/src/libtomahawk/database/schema.sql
index c30132ab9..e35973508 100644
--- a/src/libtomahawk/database/schema.sql
+++ b/src/libtomahawk/database/schema.sql
@@ -219,7 +219,7 @@ CREATE INDEX artist_tags_tag ON artist_tags(tag);
-- so that we can always do range queries.
CREATE TABLE IF NOT EXISTS track_attributes (
- id INTEGER NOT NULL, -- track id
+ id INTEGER REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, -- track id
k TEXT NOT NULL,
v TEXT NOT NULL
);
@@ -241,6 +241,8 @@ CREATE TABLE IF NOT EXISTS playback_log (
CREATE INDEX playback_log_source ON playback_log(source);
CREATE INDEX playback_log_track ON playback_log(track);
+
+
-- auth information for http clients
CREATE TABLE IF NOT EXISTS http_client_auth (
@@ -253,6 +255,7 @@ CREATE TABLE IF NOT EXISTS http_client_auth (
);
+
-- Schema version, and misc tomahawk settings relating to the collection db
CREATE TABLE IF NOT EXISTS settings (
@@ -260,4 +263,4 @@ CREATE TABLE IF NOT EXISTS settings (
v TEXT NOT NULL DEFAULT ''
);
-INSERT INTO settings(k,v) VALUES('schema_version', '21');
+INSERT INTO settings(k,v) VALUES('schema_version', '22');
diff --git a/src/libtomahawk/database/schema.sql.h b/src/libtomahawk/database/schema.sql.h
index 9283091f3..dfd468cf8 100644
--- a/src/libtomahawk/database/schema.sql.h
+++ b/src/libtomahawk/database/schema.sql.h
@@ -1,5 +1,5 @@
/*
- This file was automatically generated from schema.sql on Thu Feb 24 19:05:46 EST 2011.
+ This file was automatically generated from ./schema.sql on Wed Mar 2 01:40:39 CET 2011.
*/
static const char * tomahawk_schema_sql =
@@ -146,7 +146,7 @@ static const char * tomahawk_schema_sql =
");"
"CREATE INDEX artist_tags_tag ON artist_tags(tag);"
"CREATE TABLE IF NOT EXISTS track_attributes ("
-" id INTEGER NOT NULL, "
+" id INTEGER REFERENCES track(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED, "
" k TEXT NOT NULL,"
" v TEXT NOT NULL"
");"
@@ -173,7 +173,7 @@ static const char * tomahawk_schema_sql =
" k TEXT NOT NULL PRIMARY KEY,"
" v TEXT NOT NULL DEFAULT ''"
");"
-"INSERT INTO settings(k,v) VALUES('schema_version', '21');"
+"INSERT INTO settings(k,v) VALUES('schema_version', '22');"
;
const char * get_tomahawk_sql()
diff --git a/src/libtomahawk/network/controlconnection.cpp b/src/libtomahawk/network/controlconnection.cpp
index bfbff6550..0973b59ed 100644
--- a/src/libtomahawk/network/controlconnection.cpp
+++ b/src/libtomahawk/network/controlconnection.cpp
@@ -91,7 +91,7 @@ ControlConnection::setup()
void
ControlConnection::registerSource()
{
- qDebug() << Q_FUNC_INFO;
+ qDebug() << Q_FUNC_INFO << m_source->id();
Source* source = (Source*) sender();
Q_ASSERT( source == m_source.data() );
// .. but we'll use the shared pointer we've already made:
@@ -105,10 +105,11 @@ ControlConnection::registerSource()
void
ControlConnection::setupDbSyncConnection( bool ondemand )
{
+ qDebug() << Q_FUNC_INFO << ondemand << m_source->id() << ondemand << m_dbconnkey << m_dbsyncconn << m_registered;
+
if ( m_dbsyncconn || !m_registered )
return;
- qDebug() << Q_FUNC_INFO << ondemand << m_source->id();
Q_ASSERT( m_source->id() > 0 );
if( !m_dbconnkey.isEmpty() )
diff --git a/src/libtomahawk/network/remotecollection.cpp b/src/libtomahawk/network/remotecollection.cpp
index c4d52538a..757164456 100644
--- a/src/libtomahawk/network/remotecollection.cpp
+++ b/src/libtomahawk/network/remotecollection.cpp
@@ -11,14 +11,14 @@ RemoteCollection::RemoteCollection( source_ptr source, QObject* parent )
// adding/removing is done by dbsyncconnection, and the dbcmd objects that modify
// the database will make us emit the appropriate signals (tracksAdded etc.)
-void RemoteCollection::addTracks( const QList &newitems )
+void RemoteCollection::addTracks( const QList& newitems )
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT( false );
}
-void RemoteCollection::removeTracks( const QList &olditems )
+void RemoteCollection::removeTracks( const QDir& dir )
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT( false );
diff --git a/src/libtomahawk/network/remotecollection.h b/src/libtomahawk/network/remotecollection.h
index 63124d618..86d334f50 100644
--- a/src/libtomahawk/network/remotecollection.h
+++ b/src/libtomahawk/network/remotecollection.h
@@ -20,8 +20,8 @@ public:
}
public slots:
- virtual void addTracks( const QList &newitems );
- virtual void removeTracks( const QList &olditems );
+ virtual void addTracks( const QList& newitems );
+ virtual void removeTracks( const QDir& dir );
};
#endif // REMOTECOLLECTION_H
diff --git a/src/libtomahawk/pipeline.cpp b/src/libtomahawk/pipeline.cpp
index fa42cda84..805b2f723 100644
--- a/src/libtomahawk/pipeline.cpp
+++ b/src/libtomahawk/pipeline.cpp
@@ -152,7 +152,6 @@ Pipeline::reportResults( QID qid, const QList< result_ptr >& results )
}
state = m_qidsState.value( qid ) - 1;
-
if ( state )
{
qDebug() << Q_FUNC_INFO << "replacing" << qid << state;
diff --git a/src/libtomahawk/playlist.cpp b/src/libtomahawk/playlist.cpp
index 24e3d246b..00c644593 100644
--- a/src/libtomahawk/playlist.cpp
+++ b/src/libtomahawk/playlist.cpp
@@ -28,7 +28,7 @@ PlaylistEntry::setQueryVariant( const QVariant& v )
QString artist = m.value( "artist" ).toString();
QString album = m.value( "album" ).toString();
QString track = m.value( "track" ).toString();
- m_query = Tomahawk::Query::get( artist, track, album, false );
+ m_query = Tomahawk::Query::get( artist, track, album );
}
diff --git a/src/libtomahawk/playlist/collectionflatmodel.cpp b/src/libtomahawk/playlist/collectionflatmodel.cpp
index bfaa3d259..5edf161d5 100644
--- a/src/libtomahawk/playlist/collectionflatmodel.cpp
+++ b/src/libtomahawk/playlist/collectionflatmodel.cpp
@@ -60,7 +60,9 @@ CollectionFlatModel::addCollection( const collection_ptr& collection )
SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) );
connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
-
+ connect( collection.data(), SIGNAL( tracksRemoved( QList, Tomahawk::collection_ptr ) ),
+ SLOT( onTracksRemoved( QList, Tomahawk::collection_ptr ) ) );
+
if ( collection->source()->isLocal() )
setTitle( tr( "Your Collection" ) );
else
@@ -93,6 +95,8 @@ CollectionFlatModel::addFilteredCollection( const collection_ptr& collection, un
void
CollectionFlatModel::removeCollection( const collection_ptr& collection )
{
+ return; // FIXME
+
disconnect( collection.data(), SIGNAL( tracksAdded( QList, Tomahawk::collection_ptr ) ),
this, SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) );
disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
@@ -163,6 +167,8 @@ CollectionFlatModel::removeCollection( const collection_ptr& collection )
void
CollectionFlatModel::onTracksAdded( const QList& tracks, const Tomahawk::collection_ptr& collection )
{
+ qDebug() << Q_FUNC_INFO;
+
if ( !tracks.count() )
{
emit trackCountChanged( rowCount( QModelIndex() ) );
@@ -202,6 +208,39 @@ CollectionFlatModel::onTracksAddingFinished( const Tomahawk::collection_ptr& col
}
+void
+CollectionFlatModel::onTracksRemoved( const QList& tracks, const Tomahawk::collection_ptr& collection )
+{
+ QList t = tracks;
+ for ( int i = rowCount( QModelIndex() ); i >= 0 && t.count(); i-- )
+ {
+ PlItem* item = itemFromIndex( index( i, 0, QModelIndex() ) );
+ if ( !item )
+ continue;
+
+ int j = 0;
+ foreach ( const query_ptr& query, t )
+ {
+ if ( item->query().data() == query.data() )
+ {
+ qDebug() << "Removing row:" << i << query->toString();
+ emit beginRemoveRows( QModelIndex(), i, i );
+ delete item;
+ emit endRemoveRows();
+
+ t.removeAt( j );
+ break;
+ }
+
+ j++;
+ }
+ }
+
+ emit trackCountChanged( rowCount( QModelIndex() ) );
+ qDebug() << Q_FUNC_INFO << rowCount( QModelIndex() );
+}
+
+
void
CollectionFlatModel::onDataChanged()
{
diff --git a/src/libtomahawk/playlist/collectionflatmodel.h b/src/libtomahawk/playlist/collectionflatmodel.h
index a87e6a32d..95abdf1ac 100644
--- a/src/libtomahawk/playlist/collectionflatmodel.h
+++ b/src/libtomahawk/playlist/collectionflatmodel.h
@@ -54,6 +54,8 @@ private slots:
void onTracksAdded( const QList& tracks, const Tomahawk::collection_ptr& collection );
void onTracksAddingFinished( const Tomahawk::collection_ptr& collection );
+ void onTracksRemoved( const QList& tracks, const Tomahawk::collection_ptr& collection );
+
void onSourceOffline( const Tomahawk::source_ptr& src );
private:
diff --git a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp
index 3f55f924b..32d8448ab 100644
--- a/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp
+++ b/src/libtomahawk/playlist/dynamic/echonest/EchonestGenerator.cpp
@@ -18,7 +18,7 @@
#include "dynamic/echonest/EchonestControl.h"
#include "dynamic/echonest/EchonestSteerer.h"
#include "query.h"
-#include "tomahawk/tomahawkapp.h"
+#include "utils/tomahawkutils.h"
using namespace Tomahawk;
@@ -285,7 +285,7 @@ query_ptr
EchonestGenerator::queryFromSong(const Echonest::Song& song)
{
// track[ "album" ] = song.release(); // TODO should we include it? can be quite specific
- return Query::get( song.artistName(), song.title(), QString() );
+ return Query::get( song.artistName(), song.title(), QString(), uuid() );
}
QWidget*
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
index ee6763db8..e7829a6bb 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.cpp
@@ -92,6 +92,7 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
connect( PlaylistManager::instance(), SIGNAL( playClicked() ), this, SLOT( playPressed() ) );
connect( PlaylistManager::instance(), SIGNAL( pauseClicked() ), this, SLOT( pausePressed() ) );
+ connect( AudioEngine::instance(), SIGNAL( playlistChanged( PlaylistInterface* ) ), this, SLOT( playlistStopped( PlaylistInterface* ) ) );
}
DynamicWidget::~DynamicWidget()
@@ -207,18 +208,22 @@ DynamicWidget::layoutFloatingWidgets()
}
void
-DynamicWidget::hideEvent( QHideEvent* ev )
+DynamicWidget::playlistStopped( PlaylistInterface* pl )
{
+ if( pl == static_cast< PlaylistInterface* >( m_view->proxyModel() ) ) // same playlist, so don't stop
+ return;
+
+ // user started playing something somewhere else, so give it a rest
if( m_runningOnDemand ) {
stopStation( false );
+ m_model->clear();
}
- QWidget::hideEvent( ev );
}
void
DynamicWidget::showEvent(QShowEvent* )
{
- if( !m_playlist.isNull() ) {
+ if( !m_playlist.isNull() && !m_runningOnDemand ) {
m_setup->fadeIn();
}
}
diff --git a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
index e8653b2b7..78e133708 100644
--- a/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
+++ b/src/libtomahawk/playlist/dynamic/widgets/DynamicWidget.h
@@ -67,7 +67,6 @@ public:
virtual QSize sizeHint() const;
virtual void resizeEvent( QResizeEvent* );
- virtual void hideEvent(QHideEvent* );
virtual void showEvent(QShowEvent* );
static void paintRoundedFilledRect( QPainter& p, QPalette& pal, QRect& r, qreal opacity = .95 );
@@ -90,6 +89,8 @@ public slots:
void pausePressed();
void stationFailed( const QString& );
+ void playlistStopped( PlaylistInterface* );
+
private slots:
void generate( int = -1 );
void tracksGenerated( const QList< Tomahawk::query_ptr>& queries );
diff --git a/src/libtomahawk/source.cpp b/src/libtomahawk/source.cpp
index 0c24deb26..2f959141c 100644
--- a/src/libtomahawk/source.cpp
+++ b/src/libtomahawk/source.cpp
@@ -79,6 +79,10 @@ Source::friendlyName() const
if ( m_friendlyname.isEmpty() )
return m_username;
+ //TODO: this is a terrible assumption, help me clean this up, mighty muesli!
+ if ( m_friendlyname.contains( "@conference.") )
+ return QString(m_friendlyname).remove( 0, m_friendlyname.lastIndexOf( "/" )+1 ).append(" via MUC");
+
if ( m_friendlyname.contains( "/tomahawk" ) )
return m_friendlyname.left( m_friendlyname.indexOf( "/tomahawk" ) );
diff --git a/src/libtomahawk/utils/tomahawkutils.cpp b/src/libtomahawk/utils/tomahawkutils.cpp
index 1b5db86fe..03b7e9161 100644
--- a/src/libtomahawk/utils/tomahawkutils.cpp
+++ b/src/libtomahawk/utils/tomahawkutils.cpp
@@ -116,6 +116,17 @@ appDataDir()
}
+QDir
+appLogDir()
+{
+#ifndef Q_WS_MAC
+ return appDataDir();
+#else
+ return QDir( QDir::homePath() + "/Library/Logs" );
+#endif
+}
+
+
QString
timeToString( int seconds )
{
diff --git a/src/libtomahawk/utils/tomahawkutils.h b/src/libtomahawk/utils/tomahawkutils.h
index 1696dbd00..4161a8cde 100644
--- a/src/libtomahawk/utils/tomahawkutils.h
+++ b/src/libtomahawk/utils/tomahawkutils.h
@@ -26,15 +26,16 @@ namespace TomahawkUtils
//a non-static non-singleton normal utility class then.
class DLLEXPORT DNSResolver : public QObject
{
- Q_OBJECT
+ Q_OBJECT
+
public:
explicit DNSResolver();
~DNSResolver() {}
- void resolve( QString &host, QString type );
+ void resolve( QString& host, QString type );
signals:
- void result( QString &result );
+ void result( QString& result );
public slots:
void resultsReady();
@@ -47,23 +48,24 @@ namespace TomahawkUtils
class DLLEXPORT Sleep : public QThread
{
public:
- static void sleep(unsigned long secs)
+ static void sleep( unsigned long secs )
{
- QThread::sleep(secs);
+ QThread::sleep( secs );
}
- static void msleep(unsigned long msecs)
+ static void msleep( unsigned long msecs )
{
- QThread::msleep(msecs);
+ QThread::msleep( msecs );
}
- static void usleep(unsigned long usecs)
+ static void usleep( unsigned long usecs )
{
- QThread::usleep(usecs);
+ QThread::usleep( usecs );
}
};
DLLEXPORT QDir appConfigDir();
DLLEXPORT QDir appDataDir();
-
+ DLLEXPORT QDir appLogDir();
+
DLLEXPORT QString timeToString( int seconds );
DLLEXPORT QString ageToString( const QDateTime& time );
DLLEXPORT QString filesizeToString( unsigned int size );
diff --git a/src/libtomahawk/utils/xspfloader.cpp b/src/libtomahawk/utils/xspfloader.cpp
index 9b68b342c..ccdba5b9b 100644
--- a/src/libtomahawk/utils/xspfloader.cpp
+++ b/src/libtomahawk/utils/xspfloader.cpp
@@ -104,7 +104,7 @@ XSPFLoader::gotBody()
album = e.firstChildElement( "album" ).text();
track = e.firstChildElement( "title" ).text();
- p->setQuery( Tomahawk::Query::get( artist, track, album ) );
+ p->setQuery( Tomahawk::Query::get( artist, track, album, uuid() ) );
p->query()->setDuration( e.firstChildElement( "duration" ).text().toInt() / 1000 );
m_entries << p;
}
diff --git a/src/main.cpp b/src/main.cpp
index d755703d2..137172c69 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -1,13 +1,14 @@
#include "tomahawk/tomahawkapp.h"
#ifdef Q_WS_MAC
-#include "tomahawkapp_mac.h"
-#include
-static pascal OSErr appleEventHandler( const AppleEvent*, AppleEvent*, long );
+ #include "tomahawkapp_mac.h"
+ #include
+ static pascal OSErr appleEventHandler( const AppleEvent*, AppleEvent*, long );
#endif
#include
-int main( int argc, char *argv[] )
+int
+main( int argc, char *argv[] )
{
#ifdef Q_WS_MAC
// Do Mac specific startup to get media keys working.
@@ -19,21 +20,25 @@ int main( int argc, char *argv[] )
AEInstallEventHandler( 'GURL', 'GURL', h, 0, false );
#endif
- try {
+ try
+ {
TomahawkApp a( argc, argv );
return a.exec();
- } catch( const std::runtime_error& e ) {
+ }
+ catch( const std::runtime_error& e )
+ {
return 0;
}
}
#ifdef Q_WS_MAC
-static pascal OSErr appleEventHandler( const AppleEvent* e, AppleEvent*, long )
+static pascal OSErr
+appleEventHandler( const AppleEvent* e, AppleEvent*, long )
{
OSType id = typeWildCard;
- AEGetAttributePtr( e, keyEventIDAttr, typeType, 0, &id, sizeof(id), 0 );
+ AEGetAttributePtr( e, keyEventIDAttr, typeType, 0, &id, sizeof( id ), 0 );
- switch (id)
+ switch ( id )
{
case 'GURL':
{
diff --git a/src/musicscanner.cpp b/src/musicscanner.cpp
index 5bbe24c3b..c2a80210d 100644
--- a/src/musicscanner.cpp
+++ b/src/musicscanner.cpp
@@ -5,10 +5,19 @@
#include "database/database.h"
#include "database/databasecommand_dirmtimes.h"
#include "database/databasecommand_addfiles.h"
+#include "database/databasecommand_deletefiles.h"
using namespace Tomahawk;
+void
+DirLister::go()
+{
+ scanDir( m_dir, 0 );
+ emit finished( m_newdirmtimes );
+}
+
+
void
DirLister::scanDir( QDir dir, int depth )
{
@@ -16,13 +25,15 @@ DirLister::scanDir( QDir dir, int depth )
const uint mtime = QFileInfo( dir.absolutePath() ).lastModified().toUTC().toTime_t();
m_newdirmtimes.insert( dir.absolutePath(), mtime );
- if ( m_dirmtimes.contains( dir.absolutePath() ) &&
- mtime == m_dirmtimes.value( dir.absolutePath() ) )
+ if ( m_dirmtimes.contains( dir.absolutePath() ) && mtime == m_dirmtimes.value( dir.absolutePath() ) )
{
// dont scan this dir, unchanged since last time.
}
else
{
+ if ( m_dirmtimes.contains( dir.absolutePath() ) )
+ Database::instance()->enqueue( QSharedPointer( new DatabaseCommand_DeleteFiles( dir, SourceList::instance()->getLocal() ) ) );
+
dir.setFilter( QDir::Files | QDir::Readable | QDir::NoDotAndDotDot );
dir.setSorting( QDir::Name );
dirs = dir.entryInfoList();
@@ -138,6 +149,7 @@ void
MusicScanner::listerFinished( const QMap& newmtimes )
{
qDebug() << Q_FUNC_INFO;
+
// any remaining stuff that wasnt emitted as a batch:
if( m_scannedfiles.length() )
{
@@ -145,13 +157,23 @@ MusicScanner::listerFinished( const QMap& newmtimes )
commitBatch( m_scannedfiles );
}
+ // remove obsolete / stale files
+ foreach ( const QString& path, m_dirmtimes.keys() )
+ {
+ if ( !newmtimes.keys().contains( path ) )
+ {
+ qDebug() << "Removing stale dir:" << path;
+ Database::instance()->enqueue( QSharedPointer( new DatabaseCommand_DeleteFiles( path, SourceList::instance()->getLocal() ) ) );
+ }
+ }
+
// save mtimes, then quit thread
DatabaseCommand_DirMtimes* cmd = new DatabaseCommand_DirMtimes( newmtimes );
connect( cmd, SIGNAL( finished() ), SLOT( deleteLister() ) );
Database::instance()->enqueue( QSharedPointer(cmd) );
qDebug() << "Scanning complete, saving to database. "
- "(scanned" << m_scanned << "skipped" << m_skipped << ")";
+ "( scanned" << m_scanned << "skipped" << m_skipped << ")";
qDebug() << "Skipped the following files (no tags / no valid audio):";
foreach( const QString& s, m_skippedFiles )
@@ -222,7 +244,9 @@ MusicScanner::scanFile( const QFileInfo& fi )
QVariant
MusicScanner::readFile( const QFileInfo& fi )
{
- if ( ! m_ext2mime.contains( fi.suffix().toLower() ) )
+ const QString suffix = fi.suffix().toLower();
+
+ if ( ! m_ext2mime.contains( suffix ) )
{
m_skipped++;
return QVariantMap(); // invalid extension
@@ -235,7 +259,7 @@ MusicScanner::readFile( const QFileInfo& fi )
qDebug() << "SCAN" << m_scanned << fi.absoluteFilePath();
#ifdef COMPLEX_TAGLIB_FILENAME
- const wchar_t *encodedName = reinterpret_cast< const wchar_t *>(fi.absoluteFilePath().utf16());
+ const wchar_t *encodedName = reinterpret_cast< const wchar_t * >( fi.absoluteFilePath().utf16() );
#else
QByteArray fileName = QFile::encodeName( fi.absoluteFilePath() );
const char *encodedName = fileName.constData();
@@ -272,14 +296,13 @@ MusicScanner::readFile( const QFileInfo& fi )
return QVariantMap();
}
- QString mimetype = m_ext2mime.value( fi.suffix().toLower() );
+ QString mimetype = m_ext2mime.value( suffix );
QString url( "file://%1" );
QVariantMap m;
m["url"] = url.arg( fi.absoluteFilePath() );
m["mtime"] = fi.lastModified().toUTC().toTime_t();
m["size"] = (unsigned int)fi.size();
- m["hash"] = ""; // TODO
m["mimetype"] = mimetype;
m["duration"] = duration;
m["bitrate"] = bitrate;
@@ -288,7 +311,8 @@ MusicScanner::readFile( const QFileInfo& fi )
m["track"] = track;
m["albumpos"] = tag->track();
m["year"] = tag->year();
-
+ m["hash"] = ""; // TODO
+
m_scanned++;
return m;
}
diff --git a/src/musicscanner.h b/src/musicscanner.h
index d76c2d06d..86aedfbb7 100644
--- a/src/musicscanner.h
+++ b/src/musicscanner.h
@@ -36,12 +36,7 @@ signals:
void finished( const QMap& );
private slots:
- void go()
- {
- scanDir( m_dir, 0 );
- emit finished( m_newdirmtimes );
- }
-
+ void go();
void scanDir( QDir dir, int depth );
private:
@@ -87,7 +82,7 @@ private:
QMap m_dirmtimes;
QMap m_newdirmtimes;
-
+
QList m_scannedfiles;
quint32 m_batchsize;
diff --git a/src/settingsdialog.ui b/src/settingsdialog.ui
index 95f277025..282665429 100644
--- a/src/settingsdialog.ui
+++ b/src/settingsdialog.ui
@@ -23,7 +23,7 @@
-
- 0
+ 1
@@ -382,10 +382,10 @@
Qt::RightToLeft
- Playdar HTTP API - NO AUTH
+ Playdar HTTP API
- false
+ true
diff --git a/src/sip/SipHandler.cpp b/src/sip/SipHandler.cpp
index 12a2f3c10..061720a5e 100644
--- a/src/sip/SipHandler.cpp
+++ b/src/sip/SipHandler.cpp
@@ -27,6 +27,7 @@ SipHandler::~SipHandler()
disconnectPlugins();
}
+
QList< SipPlugin* >
SipHandler::plugins() const
{
@@ -189,7 +190,13 @@ SipHandler::onPeerOnline( const QString& jid )
ControlConnection* conn = new ControlConnection( Servent::instance() );
const QString& nodeid = Database::instance()->dbid();
- conn->setName( jid.left( jid.indexOf( "/" ) ) );
+
+ //TODO: this is a terrible assumption, help me clean this up, mighty muesli!
+ if ( jid.contains( "@conference.") )
+ conn->setName( jid );
+ else
+ conn->setName( jid.left( jid.indexOf( "/" ) ) );
+
conn->setId( nodeid );
Servent::instance()->registerOffer( key, conn );
diff --git a/src/sip/jreen/jabber_p.cpp b/src/sip/jreen/jabber_p.cpp
index 3e809404a..ef7a9a080 100644
--- a/src/sip/jreen/jabber_p.cpp
+++ b/src/sip/jreen/jabber_p.cpp
@@ -150,8 +150,9 @@ Jabber_p::addContact( const QString& jid, const QString& msg )
return;
}
- //FIXME: implement it when I dont suck that much :-)
- //handleSubscription(Subscription());
+ // Add contact to the Tomahawk group on the roster
+ m_roster->add( jid, jid, QStringList() << "Tomahawk" );
+
return;
}
@@ -175,45 +176,77 @@ Jabber_p::onConnect()
m_client->setPresence(jreen::Presence::Available, "Tomahawk-JREEN available", 1);
m_client->disco()->setSoftwareVersion( "Tomahawk JREEN", "0.0.0.0", "Foobar" );
m_client->setPingInterval(60000);
- jreen::AbstractRoster *roster = new jreen::AbstractRoster( m_client );
- roster->load();
+ m_roster = new jreen::SimpleRoster( m_client );
+ m_roster->load();
+
+ // join MUC with bare jid as nickname
+ //TODO: make the room a list of rooms and make that configurable
+ QString bare(m_jid.bare());
+ m_room = new jreen::MUCRoom(m_client, jreen::JID(QString("tomahawk@conference.qutim.org/").append(bare.replace("@", "-"))));
+ 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 )
{
- qDebug() << Q_FUNC_INFO << 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() << "Connection error msg:" << error;
+ qDebug() << "Disconnected from server:" << error;
+
+ if(reconnect)
+ QTimer::singleShot(reconnectInSeconds*1000, m_client, SLOT(connectToServer()));
emit disconnected();
}
diff --git a/src/sip/jreen/jabber_p.h b/src/sip/jreen/jabber_p.h
index 645e0d039..b69369b6e 100644
--- a/src/sip/jreen/jabber_p.h
+++ b/src/sip/jreen/jabber_p.h
@@ -31,6 +31,7 @@
#include "../sipdllmacro.h"
#include
+#include
class SIPDLLEXPORT Jabber_p :
public QObject
@@ -72,6 +73,8 @@ private slots:
private:
bool presenceMeansOnline( jreen::Presence::Type p );
jreen::Client *m_client;
+ jreen::MUCRoom *m_room;
+ jreen::SimpleRoster *m_roster;
jreen::JID m_jid;
QMap m_presences;
QMap m_peers;
diff --git a/src/sip/zeroconf/tomahawkzeroconf.h b/src/sip/zeroconf/tomahawkzeroconf.h
index 6630b865d..d80f1103a 100644
--- a/src/sip/zeroconf/tomahawkzeroconf.h
+++ b/src/sip/zeroconf/tomahawkzeroconf.h
@@ -61,10 +61,16 @@ public:
TomahawkZeroconf( int port, QObject* parent = 0 )
: QObject( parent ), m_sock( this ), m_port( port )
{
+ qDebug() << Q_FUNC_INFO;
m_sock.bind( ZCONF_PORT, QUdpSocket::ShareAddress );
connect( &m_sock, SIGNAL( readyRead() ), this, SLOT( readPacket() ) );
}
+ virtual ~TomahawkZeroconf()
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
+
public slots:
void advertise()
{
@@ -107,8 +113,8 @@ private slots:
{
qDebug() << "ADVERT received:" << sender << port;
Node *n = new Node( sender.toString(), parts.at( 2 ), port );
- connect( n, SIGNAL( tomahawkHostFound( const QString&, int, const QString&, const QString& ) ),
- this, SIGNAL( tomahawkHostFound( const QString&, int, const QString&, const QString& ) ) );
+ connect( n, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ),
+ this, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ) );
n->resolve();
}
}
diff --git a/src/sip/zeroconf/zeroconf.cpp b/src/sip/zeroconf/zeroconf.cpp
index 239cb33ce..3a567ea48 100644
--- a/src/sip/zeroconf/zeroconf.cpp
+++ b/src/sip/zeroconf/zeroconf.cpp
@@ -25,21 +25,20 @@ ZeroconfPlugin::connectPlugin( bool /*startup*/ )
{
delete m_zeroconf;
m_zeroconf = new TomahawkZeroconf( Servent::instance()->port(), this );
- QObject::connect( m_zeroconf, SIGNAL( tomahawkHostFound( const QString&, int, const QString&, const QString& ) ),
- SLOT( lanHostFound( const QString&, int, const QString&, const QString& ) ) );
+ QObject::connect( m_zeroconf, SIGNAL( tomahawkHostFound( QString, int, QString, QString ) ),
+ SLOT( lanHostFound( QString, int, QString, QString ) ) );
m_zeroconf->advertise();
-
m_isOnline = true;
-
+
foreach( QStringList *currNode, m_cachedNodes )
{
QStringList nodeSet = *currNode;
if ( !Servent::instance()->connectedToSession( nodeSet[3] ) )
Servent::instance()->connectToPeer( nodeSet[0], nodeSet[1].toInt(), "whitelist", nodeSet[2], nodeSet[3] );
+
delete currNode;
}
- m_cachedNodes.empty();
return true;
}
@@ -48,6 +47,7 @@ void
ZeroconfPlugin::disconnectPlugin()
{
m_isOnline = false;
+
delete m_zeroconf;
m_zeroconf = 0;
}
@@ -55,20 +55,24 @@ ZeroconfPlugin::disconnectPlugin()
void
ZeroconfPlugin::lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid )
{
+ if ( sender() != m_zeroconf )
+ return;
+
qDebug() << "Found LAN host:" << host << port << nodeid;
-
- //FIXME: This doesn't work...why? I never see Found LAN host in debug either, but somehow nodes are being connected...
+
if ( !m_isOnline )
{
- qDebug() << "Not online, so not connecting";
+ qDebug() << "Not online, so not connecting.";
QStringList *nodeSet = new QStringList();
*nodeSet << host << QString::number( port ) << name << nodeid;
m_cachedNodes.insert( nodeSet );
return;
}
-
+
if ( !Servent::instance()->connectedToSession( nodeid ) )
Servent::instance()->connectToPeer( host, port, "whitelist", name, nodeid );
+ else
+ qDebug() << "Already connected to" << host;
}
Q_EXPORT_PLUGIN2( sip, ZeroconfPlugin )
diff --git a/src/sip/zeroconf/zeroconf.h b/src/sip/zeroconf/zeroconf.h
index 79eee4101..aa4926908 100644
--- a/src/sip/zeroconf/zeroconf.h
+++ b/src/sip/zeroconf/zeroconf.h
@@ -18,9 +18,14 @@ public:
: m_zeroconf( 0 )
, m_isOnline( false )
, m_cachedNodes()
- {}
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
- virtual ~ZeroconfPlugin() {}
+ virtual ~ZeroconfPlugin()
+ {
+ qDebug() << Q_FUNC_INFO;
+ }
virtual bool isValid() { return true; }
virtual const QString name();
diff --git a/src/tomahawkapp.cpp b/src/tomahawkapp.cpp
index 62fb28086..be34d4564 100644
--- a/src/tomahawkapp.cpp
+++ b/src/tomahawkapp.cpp
@@ -51,7 +51,7 @@
#include
#include
-#define LOGFILE TomahawkUtils::appDataDir().filePath( "tomahawk.log" ).toLocal8Bit()
+#define LOGFILE TomahawkUtils::appLogDir().filePath( "Tomahawk.log" ).toLocal8Bit()
#define LOGFILE_SIZE 1024 * 512
using namespace std;
@@ -146,10 +146,10 @@ TomahawkApp::TomahawkApp( int& argc, char *argv[] )
#endif
qDebug() << "TomahawkApp thread:" << this->thread();
- setOrganizationName( "Tomahawk" );
- setOrganizationDomain( "tomahawk.org" );
- setApplicationName( "Player" );
- setApplicationVersion( "0.0.0" );
+ setOrganizationName( QLatin1String( ORGANIZATION_NAME ) );
+ setOrganizationDomain( QLatin1String( ORGANIZATION_DOMAIN ) );
+ setApplicationName( QLatin1String( APPLICATION_NAME ) );
+ setApplicationVersion( QLatin1String( VERSION ) );
registerMetaTypes();
setupLogfile();
diff --git a/src/web/api_v1.cpp b/src/web/api_v1.cpp
index c5e65472c..36c3587d3 100644
--- a/src/web/api_v1.cpp
+++ b/src/web/api_v1.cpp
@@ -165,7 +165,7 @@ Api_v1::stat( QxtWebRequestEvent* event )
if( event->url.hasQueryItem( "auth" ) )
{
// check for auth status
- DatabaseCommand_ClientAuthValid* dbcmd = new DatabaseCommand_ClientAuthValid( event->url.queryItemValue( "auth" ), this );
+ DatabaseCommand_ClientAuthValid* dbcmd = new DatabaseCommand_ClientAuthValid( event->url.queryItemValue( "auth" ) );
connect( dbcmd, SIGNAL( authValid( QString, QString, bool ) ), this, SLOT( statResult( QString, QString, bool ) ) );
Database::instance()->enqueue( QSharedPointer(dbcmd) );
}
@@ -215,11 +215,17 @@ Api_v1::resolve( QxtWebRequestEvent* event )
void
-Api_v1::staticdata( QxtWebRequestEvent* event )
+Api_v1::staticdata( QxtWebRequestEvent* event, const QString& str )
{
- if( event->url.path().contains( "playdar_auth_logo.gif" ) )
+ qDebug() << "STATIC request:" << event << str;
+ if( str.contains( "tomahawk_auth_logo.png" ) )
{
- // TODO handle
+ QFile f( RESPATH "www/tomahawk_banner_small.png" );
+ f.open( QIODevice::ReadOnly );
+ QByteArray data = f.readAll();
+ QxtWebPageEvent * e = new QxtWebPageEvent( event->sessionID, event->requestID, data );
+ e->contentType = "image/png";
+ postEvent( e );
}
}
diff --git a/src/web/api_v1.h b/src/web/api_v1.h
index 28b14678a..73f2c68b6 100644
--- a/src/web/api_v1.h
+++ b/src/web/api_v1.h
@@ -53,7 +53,7 @@ public slots:
void stat( QxtWebRequestEvent* event );
void statResult( const QString& clientToken, const QString& name, bool valid );
void resolve( QxtWebRequestEvent* event );
- void staticdata( QxtWebRequestEvent* event );
+ void staticdata( QxtWebRequestEvent* event,const QString& );
void get_results( QxtWebRequestEvent* event );
void sendJSON( const QVariantMap& m, QxtWebRequestEvent* event );
diff --git a/thirdparty/jreen b/thirdparty/jreen
index a997c4196..040ca3f3c 160000
--- a/thirdparty/jreen
+++ b/thirdparty/jreen
@@ -1 +1 @@
-Subproject commit a997c41967823907216255346e179569e4b1cfc9
+Subproject commit 040ca3f3cb9b30b4845fc23054c833fda4717460