diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6a929f306..cc5a74825 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,10 @@
PROJECT( tomahawk )
CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
+IF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
+ CMAKE_POLICY(SET CMP0017 NEW)
+ENDIF( ${CMAKE_VERSION} VERSION_GREATER 2.8.3 )
+
###
### Tomahawk application info
###
@@ -49,35 +53,39 @@ macro_log_feature(TAGLIB_FOUND "TagLib" "Audio Meta-Data Library" "http://develo
# we need pthreads too
find_package(Threads)
+find_package(KDE4)
+IF(KDE4_FOUND)
+ #KDE4 adds and removes some compiler flags that we don't like
+ STRING( REPLACE "-std=iso9899:1990" "" CLEAN_C_FLAGS ${CMAKE_C_FLAGS} )
+ SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexceptions" )
+ELSE()
+ SET( CLEAN_C_FLAGS ${CMAKE_C_FLAGS} )
+ENDIF()
+
include( CheckTagLibFileName )
check_taglib_filename( COMPLEX_TAGLIB_FILENAME )
# optional
macro_optional_find_package(Jreen)
IF( NOT LIBJREEN_FOUND )
+ SET( CMAKE_C_FLAGS ${CLEAN_C_FLAGS} )
ADD_SUBDIRECTORY( thirdparty/jreen )
SET( LIBJREEN_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/jreen/include )
IF( UNIX AND NOT APPLE )
SET( LIBJREEN_LIBRARY ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/jreen/libjreen.so )
ENDIF( UNIX AND NOT APPLE )
IF( WIN32 )
- SET( LIBJREEN_LIBRARY ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/jreen/libjreen.dll )
+ SET( LIBJREEN_LIBRARY ${CMAKE_CURRENT_BINARY_DIR}/thirdparty/jreen/libjreen.dll )
ENDIF( WIN32 )
SET( LIBJREEN_FOUND true )
MESSAGE(STATUS "Internal libjreen: ${LIBJREEN_INCLUDE_DIR}, ${LIBJREEN_LIBRARY}")
ENDIF( NOT LIBJREEN_FOUND )
+
IF( WIN32 )
find_library(QTSPARKLE_LIBRARIES qtsparkle)
ENDIF( WIN32 )
-macro_log_feature(JREEN_FOUND "Jreen" "Qt XMPP library" "http://gitorious.org/jreen" FALSE "" "Jreen is needed for the alternative/new Jabber SIP plugin. Built automatically inside Tomahawk, if not installed systemwide and ENABLE_JREEN is true")
-
-macro_optional_find_package(Gloox 1.0)
-IF( ENABLE_JREEN )
- set( GLOOX_FOUND false )
-ENDIF( ENABLE_JREEN)
-macro_log_feature(GLOOX_FOUND "Gloox" "A portable high-level Jabber/XMPP library for C++" "http://camaya.net/gloox" FALSE "" "Gloox is needed for the Jabber SIP plugin and the XMPP-Bot")
#show dep log
macro_display_feature_log()
MESSAGE("WARNING!")
@@ -94,9 +102,10 @@ CONFIGURE_FILE(
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
-ADD_CUSTOM_TARGET(uninstall
- "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
-
+# KDE4 defines an uninstall target for us automatically
+IF( NOT KDE4_FOUND )
+ ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+ENDIF()
IF( NOT APPLE )
# Make linking as strict on linux as it is on osx. Then we don't break linking on mac so often
diff --git a/ChangeLog b/ChangeLog
index 877b048fa..8393fc358 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12 +1,24 @@
Version 0.1.0:
+ * Resolvers can now be enabled and disabled, and some can be configured
+ directly in Tomahawk.
+ * Browse and play collections in our snappy tree-view, which also shows
+ images for artists and albums.
* Watch folders for changes and automatically update your collection. This
is on by default; you can turn it off on the Local Music tab in the
- settings dialog. Note that this triggers only on files or folders being
+ settings dialog. Note that this triggers only on files or folders being
added to or removed from folders; it is not watch individual files as
most OSes can't support enough file watches to handle a normal-sized
music collection.
+Version 0.0.4:
+ * Fixed crash that could occur when playing a track from a browser.
+ * Fixed a crash situation caused by sources going on- or offline.
+
Version 0.0.3:
+ * Show spinner while resolving playlists.
+ * Go back to previous page visible when deleting a playlist.
+ * Fixed issue where automatic playlists and station summaries were not
+ updated in the playlist header.
* Fixed an issue which caused duplicate items when rescanning.
* Revert change introduced in 0.0.2 causing Twitter protocol to not try
to reconnect to a peer if it couldn't connect the first time the plugin
@@ -17,9 +29,10 @@ Version 0.0.3:
* Don't automatically try to resolve all incoming playback logs. This
speeds up importing sources a lot.
* Faster painting of playlists with lots of unresolved tracks.
- * The tomahawk:// protocol handler works on Windows now.
- * Fixed launching Tomahawk from Windows installer with admin privileges.
* Prefer local results when results' score is equal.
+ * (Windows) The tomahawk:// protocol handler works on Windows now.
+ * (Windows) Fixed launching Tomahawk from Windows installer with admin privileges.
+ * (Windows) Prevent launching a second instance on Windows.
Version 0.0.2:
* Don't reconnect to Jabber if the settings dialog is closed successfully
@@ -35,7 +48,6 @@ Version 0.0.2:
the Tomahawk XMPP presence.
* Incompatible change: Twitter SIP protocol has changed slightly. 0.0.1
clients will not be able to talk to newer clients.
- * Hopefully fixed crashes during Twitter authentication.
* Don't let long playlist or summary names force a large Tomahawk window.
* Tomahawk now asks you to authorize new contacts.
diff --git a/README b/README
index f33c4f948..2483da2f6 100644
--- a/README
+++ b/README
@@ -1,82 +1,23 @@
-Quickstart on Ubuntu
---------------------
-
- $ sudo apt-get install build-essential cmake libtag1c2a libtag1-dev libqt4-dev libqt4-sql-sqlite \
- libvorbis-dev libmad0-dev libflac++-dev libasound2-dev libboost-dev zlib1g-dev \
- libgnutls-dev pkg-config
-
-
-Gloox 1.0 (XMPP library)
-------------------------
- On Ubuntu 10.10 (and higher):
- $ sudo apt-get install libgloox-dev
-
- Otherwise see: http://camaya.net/glooxdownload
- You need to build gloox 1.0 from source, Ubuntu 10.04 only packages version 0.9.
-
- Download and unpack tarball:
- $ ./configure --without-openssl --with-gnutls --without-libidn --with-zlib --without-examples --without-tests
- $ CXXFLAGS=-fPIC make
- $ sudo make install
-
-QJson (Qt JSON library)
------------------------
- On Ubuntu 10.04 (and higher):
- $ sudo apt-get install libqjson-dev
-
- Otherwise see: http://sourceforge.net/projects/qjson/files/ (developed using version 0.7.1)
-
- Download and unpack tarball:
- $ ./configure && make
- $ sudo make install
-
-libEchonest 1.1.4
----------------
- See: http://projects.kde.org/projects/playground/libs/libechonest/
-
- Download and unpack tarball:
- $ mkdir build && cd build
- $ cmake ..
- $ make
- $ sudo make install
-
-CLucene 0.9.23
----------------
- See: http://clucene.sourceforge.net/download.shtml
-
- Clone from git and build CLucene:
- $ git clone git://clucene.git.sourceforge.net/gitroot/clucene/clucene
- $ cd clucene && mkdir build && cd build
- $ cmake ..
- $ make
- $ sudo make install
-
-
-Quickstart on OS X
+Compiling Tomahawk
------------------
- Install homebrew
- $ ruby -e "$(curl -fsSL https://gist.github.com/raw/323731/install_homebrew.rb)"
- $ brew install cmake qt qjson gloox libmad libvorbis flac taglib boost
-
- Install libEchnoest & CLucene as per the above instructions.
-
- If liblastfm gives problems, do the below:
- $ brew edit liblastfm
- Change the url to https://github.com/davidsansome/liblastfm/tarball/0.3.1
- $ brew install liblastfm
- Copy the md5 hash it returns.
- $ brew edit liblastfm
- Replace the md5 hash with the new one you copied.
- $ brew install liblastfm
-
-
-Now compile Tomahawk
---------------------
$ mkdir build && cd build
$ cmake ..
$ make
+
+ Start the application on Linux:
$ ./tomahawk
+ Start the application on OS X:
+ $ open tomahawk.app
+
+
+Detailed building instructions for Ubuntu
+-----------------------------------------
+ See: http://wiki.tomahawk-player.org/mediawiki/index.php/Building_Ubuntu_Binary_on_Maverick_(10.10)
+
+Detailed building instructions for OS X
+---------------------------------------
+ See: http://wiki.tomahawk-player.org/mediawiki/index.php/Building_OS_X_Application_Bundle_on_Snow_Leopard_(10.6)
Dependencies
@@ -85,7 +26,7 @@ Dependencies
CMake 2.8.0 http://www.cmake.org/
Qt 4.7.0 http://qt.nokia.com/
QJson 0.7.1 http://qjson.sourceforge.net/
- Gloox 1.0 (0.9.x will fail) http://camaya.net/gloox/
+ Gloox 1.0 http://camaya.net/gloox/
SQLite 3.6.22 http://www.sqlite.org/
TagLib 1.6.2 http://developer.kde.org/~wheeler/taglib.html
Boost 1.3x http://www.boost.org/
@@ -102,23 +43,4 @@ Dependencies
MiniUPnP http://miniupnp.free.fr/
liblastfm 0.4.0 http://github.com/jonocole/liblastfm/
-
-To build the app:
------------------
- $ mkdir build && cd build
- $ cmake ..
- $ make
-
-To run the app:
----------------
- Only run the next two commands if you installed any of the dependencies from source on Linux.
- $ export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
- $ sudo ldconfig -v
-
- Start the application on Linux:
- $ ./tomahawk
-
- Start the application on OS X:
- $ open tomahawk.app
-
Enjoy!
diff --git a/admin/mac/Info.plist b/admin/mac/Info.plist
index 9acc67a0c..f4fd83c88 100644
--- a/admin/mac/Info.plist
+++ b/admin/mac/Info.plist
@@ -13,9 +13,9 @@
CFBundlePackageType
APPL
CFBundleVersion
- 0.0.2.0
+ TOMAHAWK_VERSION
CFBundleShortVersionString
- 0.0.2
+ TOMAHAWK_VERSION
CFBundleSignature
tomahawk
CFBundleIconFile
diff --git a/admin/unix/tomahawk.protocol b/admin/unix/tomahawk.protocol
index 3a393aa61..f342fb39c 100644
--- a/admin/unix/tomahawk.protocol
+++ b/admin/unix/tomahawk.protocol
@@ -1,5 +1,5 @@
[Protocol]
-exec=/home/leo/kde/tomahawk/build/tomahawk "%u"
+exec=/path/to/binary "%u"
protocol=tomahawk
input=none
output=none
diff --git a/admin/win/nsi/revision.txt b/admin/win/nsi/revision.txt
index 105d7d9ad..0fd0714a5 100644
--- a/admin/win/nsi/revision.txt
+++ b/admin/win/nsi/revision.txt
@@ -1 +1 @@
-100
\ No newline at end of file
+103
\ No newline at end of file
diff --git a/admin/win/nsi/tomahawk.nsi b/admin/win/nsi/tomahawk.nsi
index 416944114..11c2469ba 100644
--- a/admin/win/nsi/tomahawk.nsi
+++ b/admin/win/nsi/tomahawk.nsi
@@ -9,7 +9,7 @@
!define OPTION_SECTION_SC_DESKTOP
!define OPTION_SECTION_SC_QUICK_LAUNCH
!define OPTION_FINISHPAGE
-;!define OPTION_FINISHPAGE_LAUNCHER
+!define OPTION_FINISHPAGE_LAUNCHER
!define OPTION_FINISHPAGE_RELEASE_NOTES
;-----------------------------------------------------------------------------
diff --git a/data/images/configure.png b/data/images/configure.png
new file mode 100644
index 000000000..5ce478b1a
Binary files /dev/null and b/data/images/configure.png differ
diff --git a/data/sql/dbmigrate-22_to_23.sql b/data/sql/dbmigrate-22_to_23.sql
new file mode 100644
index 000000000..0ee92dd21
--- /dev/null
+++ b/data/sql/dbmigrate-22_to_23.sql
@@ -0,0 +1,11 @@
+-- Script to migate from db version 22 to 23.
+-- Only change in this version is that playlists gained a createdOn date.
+-- Set all playlists to created to now.
+--
+-- Separate each command with %%
+
+ALTER TABLE playlist ADD COLUMN createdOn INTEGER NOT NULL DEFAULT 0;
+
+UPDATE playlist SET createdOn = strftime( '%s','now' );
+
+UPDATE settings SET v = '23' WHERE k == 'schema_version';
diff --git a/include/tomahawk/tomahawkapp.h b/include/tomahawk/tomahawkapp.h
index 7775a6528..2d55f3a1b 100644
--- a/include/tomahawk/tomahawkapp.h
+++ b/include/tomahawk/tomahawkapp.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -44,6 +44,7 @@
class AudioEngine;
class Database;
+class ScanManager;
class SipHandler;
class TomahawkSettings;
class XMPPBot;
@@ -78,10 +79,10 @@ public:
TomahawkApp( int& argc, char *argv[] );
virtual ~TomahawkApp();
+ void init();
static TomahawkApp* instance();
SipHandler* sipHandler() { return m_sipHandler; }
- Tomahawk::InfoSystem::InfoSystem* infoSystem() { return m_infoSystem; }
XMPPBot* xmppBot() { return m_xmppBot; }
#ifndef TOMAHAWK_HEADLESS
@@ -89,8 +90,9 @@ public:
TomahawkWindow* mainWindow() const { return m_mainwindow; }
#endif
- void addScriptResolver( const QString& scriptPath );
- void removeScriptResolver( const QString& scriptPath );
+ void enableScriptResolver( const QString& scriptPath );
+ void disableScriptResolver( const QString& scriptPath );
+ Tomahawk::ExternalResolver* resolverForPath( const QString& scriptPath );
// PlatformInterface
virtual void activate();
@@ -98,10 +100,10 @@ public:
// because QApplication::arguments() is expensive
bool scrubFriendlyName() const { return m_scrubFriendlyName; }
-
+
public slots:
void instanceStarted( KDSingleApplicationGuard::Instance );
-
+
private slots:
void setupSIP();
@@ -115,30 +117,31 @@ private:
void startHTTP();
QList m_collections;
- QList m_scriptResolvers;
+ QHash m_scriptResolvers;
Database* m_database;
+ ScanManager *m_scanManager;
AudioEngine* m_audioEngine;
SipHandler* m_sipHandler;
Servent* m_servent;
+ Tomahawk::InfoSystem::InfoSystem* m_infoSystem;
XMPPBot* m_xmppBot;
Tomahawk::ShortcutHandler* m_shortcutHandler;
bool m_scrubFriendlyName;
-
+
#ifdef LIBLASTFM_FOUND
Scrobbler* m_scrobbler;
#endif
#ifndef TOMAHAWK_HEADLESS
TomahawkWindow* m_mainwindow;
-#endif
+#endif
bool m_headless;
- Tomahawk::InfoSystem::InfoSystem* m_infoSystem;
-
QxtHttpServerConnector m_connector;
QxtHttpSessionManager m_session;
};
#endif // TOMAHAWKAPP_H
+
diff --git a/resources.qrc b/resources.qrc
index ddbc46b96..7442790aa 100644
--- a/resources.qrc
+++ b/resources.qrc
@@ -74,6 +74,7 @@
./data/images/back.png
./data/images/forward.png
./data/images/music-icon.png
+./data/images/configure.png
./data/topbar-radiobuttons.css
./data/icons/tomahawk-icon-16x16.png
./data/icons/tomahawk-icon-32x32.png
@@ -87,5 +88,6 @@
./data/www/auth.html
./data/www/auth.na.html
./data/www/tomahawk_banner_small.png
+./data/sql/dbmigrate-22_to_23.sql
diff --git a/src/CMakeLists.osx.txt b/src/CMakeLists.osx.txt
index 6d3ded108..0488b2f71 100644
--- a/src/CMakeLists.osx.txt
+++ b/src/CMakeLists.osx.txt
@@ -35,15 +35,18 @@ if (APPLE)
# Use two different sparkle update tracks for debug and release
# We have to change the URL in the Info.plist file :-/
- IF( NOT CMAKE_BUILD_TYPE STREQUAL "Release" )
- FILE(READ ${CMAKE_SOURCE_DIR}/admin/mac/Info.plist plist)
- STRING( REPLACE "http://download.tomahawk-player.org/sparkle" # match this
- "http://download.tomahawk-player.org/sparkle-debug" #replace with debug url
+ FILE(READ ${CMAKE_SOURCE_DIR}/admin/mac/Info.plist plist)
+ STRING( REPLACE "TOMAHAWK_VERSION"
+ ${VERSION}
edited_plist # save in this variable
"${plist}" # from the contents of this var
)
- FILE( WRITE ${CMAKE_BINARY_DIR}/Info.plist "${edited_plist}" )
- ELSE() # Just copy the release one
- FILE( COPY ${CMAKE_SOURCE_DIR}/admin/mac/Info.plist DESTINATION ${CMAKE_BINARY_DIR} )
+ IF( NOT CMAKE_BUILD_TYPE STREQUAL "Release" )
+ STRING( REPLACE "http://download.tomahawk-player.org/sparkle" # match this
+ "http://download.tomahawk-player.org/sparkle-debug" #replace with debug url
+ edited_plist # save in this variable
+ "${edited_plist}" # from the contents of this var
+ )
ENDIF()
+ FILE( WRITE ${CMAKE_BINARY_DIR}/Info.plist "${edited_plist}" )
endif (APPLE)
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 69081156a..067558b19 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -34,12 +34,6 @@ ENDIF()
SET( tomahawkSources ${tomahawkSources}
sip/SipHandler.cpp
- infosystem/infosystemcache.cpp
- infosystem/infosystem.cpp
- infosystem/infoplugins/echonestplugin.cpp
- infosystem/infoplugins/lastfmplugin.cpp
- infosystem/infoplugins/musixmatchplugin.cpp
-
web/api_v1.cpp
resolvers/scriptresolver.cpp
@@ -69,20 +63,16 @@ SET( tomahawkSourcesGui ${tomahawkSourcesGui}
tomahawktrayicon.cpp
audiocontrols.cpp
settingsdialog.cpp
+ resolverconfigdelegate.cpp
+ resolversmodel.cpp
tomahawkwindow.cpp
)
SET( tomahawkHeaders ${tomahawkHeaders}
"${TOMAHAWK_INC_DIR}/tomahawk/tomahawkapp.h"
- "${TOMAHAWK_INC_DIR}/tomahawk/infosystem.h"
sip/SipHandler.h
- infosystem/infosystemcache.h
- infosystem/infoplugins/echonestplugin.h
- infosystem/infoplugins/lastfmplugin.h
- infosystem/infoplugins/musixmatchplugin.h
-
web/api_v1.h
resolvers/scriptresolver.h
@@ -111,6 +101,9 @@ SET( tomahawkHeadersGui ${tomahawkHeadersGui}
tomahawktrayicon.h
audiocontrols.h
settingsdialog.h
+ resolverconfigdelegate.h
+ resolversmodel.h
+ resolverconfigwrapper.h
tomahawkwindow.h
)
@@ -124,7 +117,7 @@ SET( tomahawkUI ${tomahawkUI}
)
INCLUDE_DIRECTORIES(
- .
+ .
${TOMAHAWK_INC_DIR}
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src
@@ -137,8 +130,6 @@ INCLUDE_DIRECTORIES(
topbar
utils
libtomahawk
- libtomahawk/utils
- infosystem
mac
${THIRDPARTY_DIR}/alsa-playback
@@ -245,4 +236,14 @@ ENDIF( APPLE )
INSTALL( TARGETS tomahawk BUNDLE DESTINATION . RUNTIME DESTINATION bin )
+IF(KDE4_FOUND) #install protocol file
+ FILE(READ ${CMAKE_SOURCE_DIR}/admin/unix/tomahawk.protocol protocol)
+ STRING( REPLACE "/path/to/binary" # match this
+ "${CMAKE_INSTALL_PREFIX}/bin/tomahawk" # this is linux (kde) so pretty safe I think
+ edited_protocol # save in this variable
+ "${protocol}" # from the contents of this var
+ )
+ FILE( WRITE ${CMAKE_BINARY_DIR}/tomahawk.protocol "${edited_protocol}" )
+ INSTALL( FILES ${CMAKE_BINARY_DIR}/tomahawk.protocol DESTINATION ${SERVICES_INSTALL_DIR} )
+ENDIF()
#INCLUDE( "CPack.txt" )
diff --git a/src/audiocontrols.cpp b/src/audiocontrols.cpp
index 8f4214ed8..d80efd846 100644
--- a/src/audiocontrols.cpp
+++ b/src/audiocontrols.cpp
@@ -21,7 +21,6 @@
#include
-#include "tomahawk/tomahawkapp.h"
#include "audio/audioengine.h"
#include "playlist/playlistmanager.h"
#include "utils/imagebutton.h"
@@ -29,9 +28,8 @@
#include "album.h"
-#define LASTFM_DEFAULT_COVER "http://cdn.last.fm/flatness/catalogue/noimage"
+static QString s_acInfoIdentifier = QString( "AUDIOCONTROLS" );
-static QString s_infoIdentifier = QString("AUDIOCONTROLS");
AudioControls::AudioControls( QWidget* parent )
: QWidget( parent )
@@ -45,11 +43,11 @@ AudioControls::AudioControls( QWidget* parent )
QFont font( ui->artistTrackLabel->font() );
font.setPixelSize( 12 );
-
+
#ifdef Q_WS_MAC
font.setPointSize( font.pointSize() - 2 );
#endif
-
+
ui->artistTrackLabel->setFont( font );
ui->artistTrackLabel->setElideMode( Qt::ElideMiddle );
ui->artistTrackLabel->setType( QueryLabel::ArtistAndTrack );
@@ -144,10 +142,10 @@ AudioControls::AudioControls( QWidget* parent )
connect( ui->volumeLowButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( lowerVolume() ) );
connect( ui->volumeHighButton, SIGNAL( clicked() ), AudioEngine::instance(), SLOT( raiseVolume() ) );
-
+
connect( ui->playPauseButton, SIGNAL( clicked() ), this, SIGNAL( playPressed() ) );
connect( ui->pauseButton, SIGNAL( clicked() ), this, SIGNAL( pausePressed() ) );
-
+
connect( ui->repeatButton, SIGNAL( clicked() ), SLOT( onRepeatClicked() ) );
connect( ui->shuffleButton, SIGNAL( clicked() ), SLOT( onShuffleClicked() ) );
@@ -167,11 +165,11 @@ AudioControls::AudioControls( QWidget* parent )
m_defaultCover = QPixmap( RESPATH "images/no-album-art-placeholder.png" )
.scaled( ui->coverImage->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation );
- connect( TomahawkApp::instance()->infoSystem(),
+ connect( Tomahawk::InfoSystem::InfoSystem::instance(),
SIGNAL( info( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
SLOT( infoSystemInfo( QString, Tomahawk::InfoSystem::InfoType, QVariant, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ) );
-
- connect( TomahawkApp::instance()->infoSystem(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
+
+ connect( Tomahawk::InfoSystem::InfoSystem::instance(), SIGNAL( finished( QString ) ), SLOT( infoSystemFinished( QString ) ) );
onPlaybackStopped(); // initial state
}
@@ -208,40 +206,6 @@ AudioControls::onVolumeChanged( int volume )
}
-void
-AudioControls::onCoverArtDownloaded()
-{
- if ( m_currentTrack.isNull() )
- return;
-
- QNetworkReply* reply = qobject_cast( sender() );
- QUrl redir = reply->attribute( QNetworkRequest::RedirectionTargetAttribute ).toUrl();
- if ( redir.isEmpty() )
- {
- const QByteArray ba = reply->readAll();
- if ( ba.length() )
- {
- QPixmap pm;
- pm.loadFromData( ba );
-
- if ( pm.isNull() || reply->url().toString().startsWith( LASTFM_DEFAULT_COVER ) )
- ui->coverImage->setPixmap( m_defaultCover );
- else
- ui->coverImage->setPixmap( pm.scaled( ui->coverImage->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
- }
- }
- else
- {
- // Follow HTTP redirect
- QNetworkRequest req( redir );
- QNetworkReply* reply = TomahawkUtils::nam()->get( req );
- connect( reply, SIGNAL( finished() ), SLOT( onCoverArtDownloaded() ) );
- }
-
- reply->deleteLater();
-}
-
-
void
AudioControls::onPlaybackStarted( const Tomahawk::result_ptr& result )
{
@@ -249,28 +213,29 @@ AudioControls::onPlaybackStarted( const Tomahawk::result_ptr& result )
onPlaybackLoading( result );
- QString artistName = result->artist()->name();
- QString albumName = result->album()->name();
-
Tomahawk::InfoSystem::InfoCustomData trackInfo;
-
trackInfo["artist"] = QVariant::fromValue< QString >( result->artist()->name() );
trackInfo["album"] = QVariant::fromValue< QString >( result->album()->name() );
- TomahawkApp::instance()->infoSystem()->getInfo(
- s_infoIdentifier, Tomahawk::InfoSystem::InfoAlbumCoverArt,
+
+ Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
+ s_acInfoIdentifier, Tomahawk::InfoSystem::InfoAlbumCoverArt,
QVariant::fromValue< Tomahawk::InfoSystem::InfoCustomData >( trackInfo ), Tomahawk::InfoSystem::InfoCustomData() );
}
+
void
AudioControls::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData )
{
- qDebug() << Q_FUNC_INFO;
- if ( caller != s_infoIdentifier || type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
+ Q_UNUSED( input );
+ Q_UNUSED( customData );
+
+ qDebug() << Q_FUNC_INFO << caller << type << s_acInfoIdentifier << Tomahawk::InfoSystem::InfoAlbumCoverArt;
+ if ( caller != s_acInfoIdentifier || type != Tomahawk::InfoSystem::InfoAlbumCoverArt )
{
- qDebug() << "info of wrong type or not with our identifier";
+ qDebug() << "Info of wrong type or not with our identifier";
return;
}
-
+
if ( m_currentTrack.isNull() )
{
qDebug() << "Current track is null when trying to apply fetched cover art";
@@ -281,7 +246,7 @@ AudioControls::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType ty
{
qDebug() << "Cannot convert fetched art from a QByteArray";
return;
- }
+ }
Tomahawk::InfoSystem::InfoCustomData returnedData = output.value< Tomahawk::InfoSystem::InfoCustomData >();
const QByteArray ba = returnedData["imgbytes"].toByteArray();
@@ -290,19 +255,22 @@ AudioControls::infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType ty
QPixmap pm;
pm.loadFromData( ba );
- if ( pm.isNull() || returnedData["url"].toString().startsWith( LASTFM_DEFAULT_COVER ) )
+ if ( pm.isNull() )
ui->coverImage->setPixmap( m_defaultCover );
else
ui->coverImage->setPixmap( pm.scaled( ui->coverImage->size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation ) );
}
}
-
+
+
void
AudioControls::infoSystemFinished( QString target )
{
+ Q_UNUSED( target );
qDebug() << Q_FUNC_INFO;
}
+
void
AudioControls::onPlaybackLoading( const Tomahawk::result_ptr& result )
{
@@ -356,7 +324,7 @@ AudioControls::onPlaybackResumed()
ui->pauseButton->setVisible( true );
ui->pauseButton->setEnabled( true );
ui->playPauseButton->setVisible( false );
- ui->playPauseButton->setEnabled( false );
+ ui->playPauseButton->setEnabled( false );
}
diff --git a/src/audiocontrols.h b/src/audiocontrols.h
index 3b90005d6..a2de2d35b 100644
--- a/src/audiocontrols.h
+++ b/src/audiocontrols.h
@@ -23,7 +23,7 @@
#include "result.h"
#include "playlistinterface.h"
-#include "tomahawk/infosystem.h"
+#include "infosystem/infosystem.h"
namespace Ui
{
@@ -41,12 +41,10 @@ public:
signals:
void playPressed();
void pausePressed();
-
+
public slots:
void onRepeatModeChanged( PlaylistInterface::RepeatMode mode );
void onShuffleModeChanged( bool enabled );
- void infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
- void infoSystemFinished( QString target );
protected:
void changeEvent( QEvent* e );
@@ -68,7 +66,8 @@ private slots:
void onAlbumClicked();
void onTrackClicked();
- void onCoverArtDownloaded();
+ void infoSystemInfo( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
+ void infoSystemFinished( QString target );
private:
Ui::AudioControls *ui;
diff --git a/src/infosystem/infosystemcache.cpp b/src/infosystem/infosystemcache.cpp
deleted file mode 100644
index 3a86c5634..000000000
--- a/src/infosystem/infosystemcache.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-/* === This file is part of Tomahawk Player - ===
- *
- * Copyright 2010-2011, Christian Muehlhaeuser
- *
- * Tomahawk is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tomahawk is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tomahawk. If not, see .
- */
-
-#include
-#include
-#include
-#include
-
-#include "infosystemcache.h"
-
-
-namespace Tomahawk
-{
-
-namespace InfoSystem
-{
-
-
-InfoSystemCache::InfoSystemCache( QObject* parent )
- : QObject(parent)
-{
- qDebug() << Q_FUNC_INFO;
- QString cacheBaseDir = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
- for( int i = 0; i <= InfoNoInfo; i++ )
- {
- InfoType type = (InfoType)(i);
- if( m_dirtySet.contains( type ) && m_dataCache.contains( type ) )
- {
- QString cacheDir = cacheBaseDir + QString::number( i );
- QDir dir( cacheDir );
- if( dir.exists() && QFile::exists( QString( cacheDir + '/' + QString::number( i ) ) ) )
- loadCache( type, QString( cacheDir + '/' + QString::number( i ) ) );
- }
- }
-}
-
-
-InfoSystemCache::~InfoSystemCache()
-{
- qDebug() << Q_FUNC_INFO;
- qDebug() << "Saving infosystemcache to disk";
- QString cacheBaseDir = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
- for( int i = 0; i <= InfoNoInfo; i++ )
- {
- InfoType type = (InfoType)(i);
- if( m_dirtySet.contains( type ) && m_dataCache.contains( type ) )
- {
- QString cacheDir = cacheBaseDir + QString::number( i );
- saveCache( type, cacheDir );
- }
- }
-}
-
-
-void
-InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData )
-{
- qDebug() << Q_FUNC_INFO;
- if( !m_dataCache.contains( type ) || !m_dataCache[type].contains( criteria ) )
- {
- emit notInCache( criteria, caller, type, input, customData );
- return;
- }
-
- emit info( caller, type, input, m_dataCache[type][criteria], customData );
-}
-
-
-void
-InfoSystemCache::updateCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, Tomahawk::InfoSystem::InfoType type, QVariant output )
-{
- qDebug() << Q_FUNC_INFO;
- QHash< InfoCacheCriteria, QVariant > typedatacache;
- QHash< InfoCacheCriteria, QDateTime > typetimecache;
- typedatacache[criteria] = output;
- typetimecache[criteria] = QDateTime::currentDateTimeUtc();
- m_dataCache[type] = typedatacache;
- m_timeCache[type] = typetimecache;
- m_dirtySet.insert( type );
-}
-
-
-void
-InfoSystemCache::loadCache( InfoType type, const QString &cacheDir )
-{
- qDebug() << Q_FUNC_INFO;
-}
-
-
-void
-InfoSystemCache::saveCache( InfoType type, const QString &cacheDir )
-{
- qDebug() << Q_FUNC_INFO;
- QDir dir( cacheDir );
- if( !dir.exists( cacheDir ) )
- {
- qDebug() << "Creating cache directory " << cacheDir;
- if( !dir.mkpath( cacheDir ) )
- {
- qDebug() << "Failed to create cache dir! Bailing...";
- return;
- }
- }
-
- QSettings cacheFile( QString( cacheDir + '/' + QString::number( (int)type ) ), QSettings::IniFormat );
-
- foreach( InfoCacheCriteria criteria, m_dataCache[type].keys() )
- {
- cacheFile.beginGroup( "type_" + QString::number( type ) );
- cacheFile.beginWriteArray( "criteria" );
- QStringList keys = criteria.keys();
- for( int i = 0; i < criteria.size(); i++ )
- {
- cacheFile.setArrayIndex( i );
- cacheFile.setValue( keys.at( i ), criteria[keys.at( i )] );
- }
- cacheFile.endArray();
- cacheFile.setValue( "data", m_dataCache[type][criteria] );
- cacheFile.setValue( "time", m_timeCache[type][criteria] );
- cacheFile.endGroup();
- }
-
- m_dirtySet.remove( type );
-}
-
-
-} //namespace InfoSystem
-
-} //namespace Tomahawk
\ No newline at end of file
diff --git a/src/libtomahawk/CMakeLists.txt b/src/libtomahawk/CMakeLists.txt
index 188f6c1b3..33aaff411 100644
--- a/src/libtomahawk/CMakeLists.txt
+++ b/src/libtomahawk/CMakeLists.txt
@@ -4,6 +4,7 @@ SET( QT_USE_QTGUI TRUE )
SET( QT_USE_QTSQL TRUE )
SET( QT_USE_QTNETWORK TRUE )
SET( QT_USE_QTXML TRUE )
+SET(QT_USE_QTUITOOLS TRUE)
include( ${QT_USE_FILE} )
@@ -21,6 +22,7 @@ set( libSources
album.cpp
collection.cpp
playlist.cpp
+ resolver.cpp
query.cpp
result.cpp
source.cpp
@@ -29,6 +31,7 @@ set( libSources
sip/SipPlugin.cpp
audio/madtranscode.cpp
+ audio/dummytranscode.cpp
audio/vorbistranscode.cpp
audio/flactranscode.cpp
audio/audioengine.cpp
@@ -42,6 +45,7 @@ set( libSources
database/databasecommand.cpp
database/databasecommandloggable.cpp
database/databasecommand_resolve.cpp
+ database/databasecommand_allartists.cpp
database/databasecommand_allalbums.cpp
database/databasecommand_alltracks.cpp
database/databasecommand_addfiles.cpp
@@ -73,7 +77,16 @@ set( libSources
database/databasecommand_clientauthvalid.cpp
database/database.cpp
- playlist/collectionmodel.cpp
+ infosystem/infosystemcache.cpp
+ infosystem/infosystem.cpp
+ infosystem/infoplugins/echonestplugin.cpp
+ infosystem/infoplugins/lastfmplugin.cpp
+ infosystem/infoplugins/musixmatchplugin.cpp
+
+ playlist/treemodel.cpp
+ playlist/treeproxymodel.cpp
+ playlist/treeheader.cpp
+ playlist/treeitemdelegate.cpp
playlist/collectionproxymodel.cpp
playlist/collectionflatmodel.cpp
playlist/collectionview.cpp
@@ -89,15 +102,17 @@ set( libSources
playlist/trackproxymodel.cpp
playlist/trackview.cpp
playlist/trackheader.cpp
+ playlist/treemodelitem.cpp
playlist/albumitem.cpp
playlist/albummodel.cpp
playlist/albumproxymodel.cpp
playlist/albumitemdelegate.cpp
playlist/albumview.cpp
+ playlist/artistview.cpp
playlist/topbar/topbar.cpp
- playlist/topbar/clearbutton.cpp
- playlist/topbar/searchlineedit.cpp
+ playlist/topbar/clearbutton.cpp
+ playlist/topbar/searchlineedit.cpp
playlist/topbar/lineedit.cpp
playlist/topbar/searchbutton.cpp
@@ -175,6 +190,7 @@ set( libHeaders
audio/transcodeinterface.h
audio/madtranscode.h
+ audio/dummytranscode.h
audio/vorbistranscode.h
audio/flactranscode.h
audio/audioengine.h
@@ -187,6 +203,7 @@ set( libHeaders
database/databasecommand.h
database/databasecommandloggable.h
database/databasecommand_resolve.h
+ database/databasecommand_allartists.h
database/databasecommand_allalbums.h
database/databasecommand_alltracks.h
database/databasecommand_addfiles.h
@@ -217,6 +234,12 @@ set( libHeaders
database/databasecommand_addclientauth.h
database/databasecommand_clientauthvalid.h
+ infosystem/infosystem.h
+ infosystem/infosystemcache.h
+ infosystem/infoplugins/echonestplugin.h
+ infosystem/infoplugins/lastfmplugin.h
+ infosystem/infoplugins/musixmatchplugin.h
+
network/bufferiodevice.h
network/msgprocessor.h
network/remotecollection.h
@@ -227,7 +250,10 @@ set( libHeaders
network/controlconnection.h
network/portfwdthread.h
- playlist/collectionmodel.h
+ playlist/treemodel.h
+ playlist/treeproxymodel.h
+ playlist/treeheader.h
+ playlist/treeitemdelegate.h
playlist/collectionproxymodel.h
playlist/collectionflatmodel.h
playlist/collectionview.h
@@ -243,15 +269,17 @@ set( libHeaders
playlist/trackproxymodel.h
playlist/trackview.h
playlist/trackheader.h
+ playlist/treemodelitem.h
playlist/albumitem.h
playlist/albummodel.h
playlist/albumproxymodel.h
playlist/albumitemdelegate.h
playlist/albumview.h
+ playlist/artistview.h
playlist/topbar/topbar.h
playlist/topbar/clearbutton.h
- playlist/topbar/searchlineedit.h
+ playlist/topbar/searchlineedit.h
playlist/topbar/lineedit.h
playlist/topbar/lineedit_p.h
playlist/topbar/searchbutton.h
@@ -297,8 +325,8 @@ set( libHeaders
kdsingleapplicationguard/kdlockedsharedmemorypointer.h
)
-set( libHeaders_NoMOC
- playlist/dynamic/GeneratorInterface.h
+set( libHeaders_NoMOC
+ playlist/dynamic/GeneratorInterface.h
)
set( libUI ${libUI}
widgets/newplaylistwidget.ui
@@ -316,9 +344,9 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
${LIBECHONEST_INCLUDE_DIR}/..
${CLUCENE_INCLUDE_DIR}
${CLUCENE_LIBRARY_DIR}
+ ${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src
../../include
- ../network
playlist
${THIRDPARTY_DIR}/libportfwd/include
@@ -329,6 +357,7 @@ include_directories( . ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/.
${THIRDPARTY_DIR}/jdns/jdns
${THIRDPARTY_DIR}/jdns/jdnsshared
${THIRDPARTY_DIR}/qtweetlib/qtweetlib/src
+ ${CMAKE_BINARY_DIR}/thirdparty/liblastfm2/src
)
@@ -379,6 +408,10 @@ IF( UNIX AND NOT APPLE )
)
ENDIF( UNIX AND NOT APPLE )
+IF(LIBLASTFM_FOUND)
+ SET(LINK_LIBRARIES ${LINK_LIBRARIES} tomahawk_lastfm2 )
+ENDIF(LIBLASTFM_FOUND)
+
qt4_wrap_ui( libUI_H ${libUI} )
qt4_wrap_cpp( libMoc ${libHeaders} )
@@ -407,6 +440,7 @@ target_link_libraries( tomahawklib
${QT_LIBRARIES}
${OS_SPECIFIC_LINK_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
+ ${LINK_LIBRARIES}
)
INSTALL( TARGETS tomahawklib DESTINATION lib${LIB_SUFFIX} )
diff --git a/src/libtomahawk/album.cpp b/src/libtomahawk/album.cpp
index 5fede95c5..425183174 100644
--- a/src/libtomahawk/album.cpp
+++ b/src/libtomahawk/album.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -93,7 +93,7 @@ Album::tracks()
cmd->setAlbum( this );
cmd->setSortOrder( DatabaseCommand_AllTracks::AlbumPosition );
- connect( cmd, SIGNAL( tracks( QList ) ),
+ connect( cmd, SIGNAL( tracks( QList, QVariant ) ),
SLOT( onTracksAdded( QList ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
diff --git a/src/libtomahawk/album.h b/src/libtomahawk/album.h
index df8009b27..a1497f490 100644
--- a/src/libtomahawk/album.h
+++ b/src/libtomahawk/album.h
@@ -58,7 +58,7 @@ public:
virtual void setRepeatMode( PlaylistInterface::RepeatMode ) {}
virtual void setShuffled( bool ) {}
- virtual void setFilter( const QString& pattern ) {}
+ virtual void setFilter( const QString& /*pattern*/ ) {}
signals:
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
diff --git a/src/libtomahawk/artist.cpp b/src/libtomahawk/artist.cpp
index bc130e55f..0d24772a4 100644
--- a/src/libtomahawk/artist.cpp
+++ b/src/libtomahawk/artist.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -95,7 +95,7 @@ Artist::tracks()
cmd->setArtist( this );
cmd->setSortOrder( DatabaseCommand_AllTracks::Album );
- connect( cmd, SIGNAL( tracks( QList ) ),
+ connect( cmd, SIGNAL( tracks( QList, QVariant ) ),
SLOT( onTracksAdded( QList ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
diff --git a/src/libtomahawk/artist.h b/src/libtomahawk/artist.h
index d7f5ac7ef..200e29c48 100644
--- a/src/libtomahawk/artist.h
+++ b/src/libtomahawk/artist.h
@@ -58,7 +58,7 @@ public:
virtual void setRepeatMode( PlaylistInterface::RepeatMode ) {}
virtual void setShuffled( bool ) {}
- virtual void setFilter( const QString& pattern ) {}
+ virtual void setFilter( const QString& /*pattern*/ ) {}
signals:
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
diff --git a/src/libtomahawk/audio/audioengine.cpp b/src/libtomahawk/audio/audioengine.cpp
index 07c5c3cc1..8b2987149 100644
--- a/src/libtomahawk/audio/audioengine.cpp
+++ b/src/libtomahawk/audio/audioengine.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -28,6 +28,7 @@
#include "network/servent.h"
#include "madtranscode.h"
+#include "dummytranscode.h"
#ifndef NO_OGG
#include "vorbistranscode.h"
#endif
@@ -228,12 +229,15 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
qDebug() << "Starting new song from url:" << m_currentTrack->url();
emit loading( m_currentTrack );
+ qDebug() << "input is:" << m_input.isNull();
if ( !m_input.isNull() )
{
m_input->close();
m_input.clear();
}
+ if( !m_lastTrack.isNull() ) qDebug() << "LAST TRACK:" << m_lastTrack->mimetype();
+ qDebug() << "LOADING SONG:" << m_currentTrack->mimetype();
if ( m_lastTrack.isNull() || ( m_currentTrack->mimetype() != m_lastTrack->mimetype() ) )
{
if ( !m_transcode.isNull() )
@@ -241,7 +245,10 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
m_transcode.clear();
}
- if ( m_currentTrack->mimetype() == "audio/mpeg" )
+ if ( m_currentTrack->mimetype() == "audio/basic" )
+ {
+ m_transcode = QSharedPointer(new DummyTranscode());
+ } else if ( m_currentTrack->mimetype() == "audio/mpeg" )
{
m_transcode = QSharedPointer(new MADTranscode());
}
@@ -428,8 +435,10 @@ AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
void
AudioEngine::onDownloadProgress( qint64 recv, qint64 total )
{
- if ( ( recv > 1024 * 32 ) || recv > total )
+ if ( ( recv > 1024 * 32 ) || recv > total )
m_readReady = true;
+
+// qDebug() << "Got onDownloadProgress from reading http stream, received enough?" << m_readReady << "(" << recv << "> 1024 * 32 and" << recv << "<" << total << ")";
}
@@ -454,28 +463,30 @@ void
AudioEngine::loop()
{
m_i++;
- //if( m_i % 500 == 0 ) qDebug() << Q_FUNC_INFO << thread();
+// if( m_i % 500 == 0 ) qDebug() << Q_FUNC_INFO << thread();
{
QMutexLocker lock( &m_mutex );
-/* if ( m_i % 200 == 0 )
- {
- if ( !m_input.isNull() )
- qDebug() << "Outer audio loop" << m_input->bytesAvailable() << m_audio->needData();
- }*/
+// if ( m_i % 200 == 0 )
+// {
+// if ( !m_input.isNull() )
+// qDebug() << "Outer audio loop" << m_input->bytesAvailable() << m_audio->needData();
+// }
if ( m_i % 10 == 0 && m_audio->isPlaying() )
m_audio->triggerTimers();
+// qDebug() << !m_transcode.isNull() << !m_input.isNull() << m_audio->needData() << !m_audio->isPaused();
+// if( !m_input.isNull() ) qDebug() << "INPUT has bytes:" << m_input->bytesAvailable();
if( !m_transcode.isNull() &&
!m_input.isNull() &&
m_input->bytesAvailable() &&
m_audio->needData() &&
!m_audio->isPaused() )
{
- //if ( m_i % 50 == 0 )
- // qDebug() << "Inner audio loop";
+// if ( m_i % 50 == 0 )
+// qDebug() << "Inner audio loop";
if ( m_transcode->needData() > 0 )
{
@@ -498,11 +509,12 @@ AudioEngine::loop()
// are we cleanly at the end of a track, and ready for the next one?
if ( !m_input.isNull() &&
m_input->atEnd() &&
- m_readReady &&
+ m_readReady &&
!m_input->bytesAvailable() &&
!m_audio->haveData() &&
!m_audio->isPaused() )
{
+ qDebug() << !m_input.isNull() << m_input->atEnd() << m_readReady << !m_input->bytesAvailable() << !m_audio->haveData() << !m_audio->isPaused();
qDebug() << "Starting next track then";
loadNextTrack();
// will need data immediately:
diff --git a/src/libtomahawk/audio/dummytranscode.cpp b/src/libtomahawk/audio/dummytranscode.cpp
new file mode 100644
index 000000000..92b5efc6e
--- /dev/null
+++ b/src/libtomahawk/audio/dummytranscode.cpp
@@ -0,0 +1,64 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#include "dummytranscode.h"
+
+#include
+
+DummyTranscode::DummyTranscode()
+ : m_init( false )
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+
+DummyTranscode::~DummyTranscode()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+
+void
+DummyTranscode::processData( const QByteArray &buffer, bool finish )
+{
+ Q_UNUSED( finish );
+ m_buffer.append( buffer );
+// qDebug() << "DUMMYTRANSCODING:" << buffer.size();
+
+ if( !m_init && m_buffer.size() >= 16364 ) {
+ m_init = true;
+ emit streamInitialized( 44100, 2 );
+ }
+}
+
+
+void
+DummyTranscode::onSeek( int seconds )
+{
+ Q_UNUSED( seconds );
+ m_buffer.clear();
+}
+
+
+void
+DummyTranscode::clearBuffers()
+{
+ m_buffer.clear();
+ m_init = false;
+}
+
diff --git a/src/libtomahawk/audio/dummytranscode.h b/src/libtomahawk/audio/dummytranscode.h
new file mode 100644
index 000000000..d38774ffd
--- /dev/null
+++ b/src/libtomahawk/audio/dummytranscode.h
@@ -0,0 +1,63 @@
+/*
+
+ Copyright (C) 2011 Leo Franchi
+
+ 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 3 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, see .
+*/
+
+
+#ifndef DUMMYTRANSCODE_H
+#define DUMMYTRANSCODE_H
+
+#include "audio/transcodeinterface.h"
+#include "dllmacro.h"
+
+#define _BUFFER_PREFERRED 32768
+
+class DLLEXPORT DummyTranscode : public TranscodeInterface
+{
+ Q_OBJECT
+
+public:
+ DummyTranscode();
+ virtual ~DummyTranscode();
+
+ const QStringList supportedTypes() const { QStringList l; l << "audio/basic"; return l; }
+
+ int needData() { return true; } // always eats data
+ bool haveData() { return !m_buffer.isEmpty(); }
+
+ unsigned int preferredDataSize() { return _BUFFER_PREFERRED; }
+
+ QByteArray data() { QByteArray b = m_buffer; m_buffer.clear(); return b; }
+
+ virtual void setBufferCapacity( int bytes ) { m_bufferCapacity = bytes; }
+ int bufferSize() { return m_buffer.size(); }
+
+public slots:
+ virtual void clearBuffers();
+ virtual void onSeek( int seconds );
+ virtual void processData( const QByteArray& data, bool finish );
+
+signals:
+ void streamInitialized( long sampleRate, int channels );
+ void timeChanged( int seconds );
+
+private:
+ QByteArray m_buffer;
+ int m_bufferCapacity;
+ bool m_init;
+};
+
+#endif // DUMMYTRANSCODE_H
diff --git a/src/libtomahawk/audio/flactranscode.cpp b/src/libtomahawk/audio/flactranscode.cpp
index aee7299d1..c66c5a557 100644
--- a/src/libtomahawk/audio/flactranscode.cpp
+++ b/src/libtomahawk/audio/flactranscode.cpp
@@ -39,6 +39,7 @@ FLACTranscode::~FLACTranscode()
void
FLACTranscode::onSeek( int seconds )
{
+ Q_UNUSED( seconds );
QMutexLocker locker( &m_mutex );
m_buffer.clear();
@@ -120,6 +121,7 @@ FLACTranscode::write_callback( const ::FLAC__Frame *frame, const FLAC__int32 *co
::FLAC__StreamDecoderSeekStatus
FLACTranscode::seek_callback(FLAC__uint64 absolute_byte_offset)
{
+ Q_UNUSED( absolute_byte_offset );
return FLAC__STREAM_DECODER_SEEK_STATUS_UNSUPPORTED;
}
diff --git a/src/libtomahawk/audio/vorbistranscode.cpp b/src/libtomahawk/audio/vorbistranscode.cpp
index 826c0f272..20403684c 100644
--- a/src/libtomahawk/audio/vorbistranscode.cpp
+++ b/src/libtomahawk/audio/vorbistranscode.cpp
@@ -39,6 +39,9 @@ vorbis_read( void* data_ptr, size_t byteSize, size_t sizeToRead, void* data_src
int
vorbis_seek( void* data_src, ogg_int64_t offset, int origin )
{
+ Q_UNUSED( data_src );
+ Q_UNUSED( offset );
+ Q_UNUSED( origin );
return -1;
}
@@ -46,6 +49,7 @@ vorbis_seek( void* data_src, ogg_int64_t offset, int origin )
int
vorbis_close( void* data_src )
{
+ Q_UNUSED( data_src );
// done ;-)
return 0;
}
@@ -54,6 +58,7 @@ vorbis_close( void* data_src )
long
vorbis_tell( void* data_src )
{
+ Q_UNUSED( data_src );
return -1;
}
@@ -74,6 +79,7 @@ VorbisTranscode::~VorbisTranscode()
void
VorbisTranscode::onSeek( int seconds )
{
+ Q_UNUSED( seconds );
QMutexLocker locker( &m_mutex );
m_buffer.clear();
diff --git a/src/libtomahawk/database/database.h b/src/libtomahawk/database/database.h
index a6890fbb6..df02ce2a0 100644
--- a/src/libtomahawk/database/database.h
+++ b/src/libtomahawk/database/database.h
@@ -49,7 +49,7 @@ public:
~Database();
QString dbid() const;
- const bool indexReady() const { return m_indexReady; }
+ bool indexReady() const { return m_indexReady; }
void loadIndex();
diff --git a/src/libtomahawk/database/databasecollection.cpp b/src/libtomahawk/database/databasecollection.cpp
index 564180398..bbcf6da79 100644
--- a/src/libtomahawk/database/databasecollection.cpp
+++ b/src/libtomahawk/database/databasecollection.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -52,10 +52,10 @@ DatabaseCollection::loadDynamicPlaylists()
{
qDebug() << Q_FUNC_INFO;
DatabaseCommand_LoadAllDynamicPlaylists* cmd = new DatabaseCommand_LoadAllDynamicPlaylists( source() );
-
+
connect( cmd, SIGNAL( playlistLoaded( Tomahawk::source_ptr, QVariantList ) ),
SLOT( dynamicPlaylistCreated( const Tomahawk::source_ptr&, const QVariantList& ) ) );
-
+
Database::instance()->enqueue( QSharedPointer( cmd ) );
}
@@ -68,7 +68,7 @@ DatabaseCollection::loadTracks()
setLoaded();
DatabaseCommand_AllTracks* cmd = new DatabaseCommand_AllTracks( source()->collection() );
- connect( cmd, SIGNAL( tracks( QList ) ),
+ connect( cmd, SIGNAL( tracks( QList, QVariant ) ),
SLOT( setTracks( QList ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
@@ -112,12 +112,12 @@ DatabaseCollection::playlists()
QList< dynplaylist_ptr > DatabaseCollection::dynamicPlaylists()
{
qDebug() << Q_FUNC_INFO;
-
+
if ( Collection::dynamicPlaylists().isEmpty() )
{
loadDynamicPlaylists();
}
-
+
return Collection::dynamicPlaylists();
}
@@ -143,11 +143,12 @@ void DatabaseCollection::dynamicPlaylistCreated( const source_ptr& source, const
data[1].toString(), //title
data[2].toString(), //info
data[3].toString(), //creator
- data[4].toString(), // dynamic type
- static_cast(data[5].toInt()), // dynamic mode
- data[6].toBool(), //shared
- data[7].toInt(), //lastmod
- data[8].toString() ) ); //GUID
+ data[4].toUInt(), // createdOn
+ data[5].toString(), // dynamic type
+ static_cast(data[6].toInt()), // dynamic mode
+ data[7].toBool(), //shared
+ data[8].toInt(), //lastmod
+ data[9].toString() ) ); //GUID
addDynamicPlaylist( p );
}
diff --git a/src/libtomahawk/database/databasecommand.h b/src/libtomahawk/database/databasecommand.h
index f18440ca7..3ce9b6873 100644
--- a/src/libtomahawk/database/databasecommand.h
+++ b/src/libtomahawk/database/databasecommand.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -48,6 +48,7 @@ public:
explicit DatabaseCommand( const Tomahawk::source_ptr& src, QObject* parent = 0 );
DatabaseCommand( const DatabaseCommand &other )
+ : QObject( other.parent() )
{
}
@@ -59,7 +60,7 @@ public:
// if i make this pure virtual, i get compile errors in qmetatype.h.
// we need Q_DECLARE_METATYPE to use in queued sig/slot connections.
- virtual void exec( DatabaseImpl* lib ) { Q_ASSERT( false ); }
+ virtual void exec( DatabaseImpl* /*lib*/ ) { Q_ASSERT( false ); }
void _exec( DatabaseImpl* lib );
@@ -75,6 +76,9 @@ public:
virtual bool singletonCmd() const { return false; }
virtual bool localOnly() const { return false; }
+ virtual QVariant data() const { return m_data; }
+ virtual void setData( const QVariant& data ) { m_data = data; }
+
QString guid() const
{
if( m_guid.isEmpty() )
@@ -97,6 +101,8 @@ private:
State m_state;
Tomahawk::source_ptr m_source;
mutable QString m_guid;
+
+ QVariant m_data;
};
Q_DECLARE_METATYPE( DatabaseCommand )
diff --git a/src/libtomahawk/database/databasecommand_allalbums.cpp b/src/libtomahawk/database/databasecommand_allalbums.cpp
index 99af75aff..55b2b7139 100644
--- a/src/libtomahawk/database/databasecommand_allalbums.cpp
+++ b/src/libtomahawk/database/databasecommand_allalbums.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -22,14 +22,13 @@
#include "databaseimpl.h"
-void
-DatabaseCommand_AllAlbums::exec( DatabaseImpl* dbi )
-{
- Q_ASSERT( !m_collection->source().isNull() );
+void
+DatabaseCommand_AllAlbums::execForArtist( DatabaseImpl* dbi )
+{
TomahawkSqlQuery query = dbi->newquery();
QList al;
- QString m_orderToken;
+ QString orderToken, sourceToken;
switch ( m_sortOrder )
{
@@ -37,22 +36,78 @@ DatabaseCommand_AllAlbums::exec( DatabaseImpl* dbi )
break;
case ModificationTime:
- m_orderToken = "file.mtime";
+ orderToken = "file.mtime";
+ }
+
+ if ( !m_collection.isNull() )
+ sourceToken = QString( "AND file.source %1 " ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) );
+
+ QString sql = QString(
+ "SELECT DISTINCT album.id, album.name "
+ "FROM file, file_join "
+ "LEFT OUTER JOIN album "
+ "ON file_join.album = album.id "
+ "WHERE file.id = file_join.file "
+ "AND file_join.artist = %1 "
+ "%2 "
+ "%3 %4 %5"
+ ).arg( m_artist->id() )
+ .arg( sourceToken )
+ .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
+ .arg( m_sortDescending ? "DESC" : QString() )
+ .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
+
+ query.prepare( sql );
+ query.exec();
+
+ while( query.next() )
+ {
+ unsigned int albumId = query.value( 0 ).toUInt();
+ QString albumName = query.value( 1 ).toString();
+ if ( query.value( 0 ).isNull() )
+ {
+ albumName = tr( "Unknown" );
+ }
+
+ Tomahawk::album_ptr album = Tomahawk::Album::get( albumId, albumName, m_artist );
+ al << album;
+ }
+
+ if ( al.count() )
+ emit albums( al, data() );
+ emit done();
+}
+
+
+void
+DatabaseCommand_AllAlbums::execForCollection( DatabaseImpl* dbi )
+{
+ TomahawkSqlQuery query = dbi->newquery();
+ QList al;
+ QString orderToken;
+
+ switch ( m_sortOrder )
+ {
+ case 0:
+ break;
+
+ case ModificationTime:
+ orderToken = "file.mtime";
}
QString sql = QString(
- "SELECT DISTINCT album.id, album.name, album.artist, artist.name "
- "FROM album, file, file_join "
- "LEFT OUTER JOIN artist "
- "ON album.artist = artist.id "
- "WHERE file.id = file_join.file "
- "AND file_join.album = album.id "
- "AND file.source %1 "
- "%2 %3 %4"
- ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) )
- .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( m_orderToken ) : QString() )
- .arg( m_sortDescending ? "DESC" : QString() )
- .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
+ "SELECT DISTINCT album.id, album.name, album.artist, artist.name "
+ "FROM album, file, file_join "
+ "LEFT OUTER JOIN artist "
+ "ON album.artist = artist.id "
+ "WHERE file.id = file_join.file "
+ "AND file_join.album = album.id "
+ "AND file.source %1 "
+ "%2 %3 %4"
+ ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) )
+ .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
+ .arg( m_sortDescending ? "DESC" : QString() )
+ .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
query.prepare( sql );
query.exec();
@@ -66,6 +121,20 @@ DatabaseCommand_AllAlbums::exec( DatabaseImpl* dbi )
}
if ( al.count() )
- emit albums( al, m_collection );
- emit done( m_collection );
+ emit albums( al, data() );
+ emit done();
+}
+
+
+void
+DatabaseCommand_AllAlbums::exec( DatabaseImpl* dbi )
+{
+ if ( !m_artist.isNull() )
+ {
+ execForArtist( dbi );
+ }
+ else
+ {
+ execForCollection( dbi );
+ }
}
diff --git a/src/libtomahawk/database/databasecommand_allalbums.h b/src/libtomahawk/database/databasecommand_allalbums.h
index 501e9ae5e..8520e0d07 100644
--- a/src/libtomahawk/database/databasecommand_allalbums.h
+++ b/src/libtomahawk/database/databasecommand_allalbums.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -38,9 +38,10 @@ public:
ModificationTime = 1
};
- explicit DatabaseCommand_AllAlbums( const Tomahawk::collection_ptr& collection, QObject* parent = 0 )
+ explicit DatabaseCommand_AllAlbums( const Tomahawk::collection_ptr& collection, const Tomahawk::artist_ptr& artist = Tomahawk::artist_ptr(), QObject* parent = 0 )
: DatabaseCommand( parent )
, m_collection( collection )
+ , m_artist( artist )
, m_amount( 0 )
, m_sortOrder( DatabaseCommand_AllAlbums::None )
, m_sortDescending( false )
@@ -51,16 +52,21 @@ public:
virtual bool doesMutates() const { return false; }
virtual QString commandname() const { return "allalbums"; }
+ void execForCollection( DatabaseImpl* );
+ void execForArtist( DatabaseImpl* );
+
void setLimit( unsigned int amount ) { m_amount = amount; }
void setSortOrder( DatabaseCommand_AllAlbums::SortOrder order ) { m_sortOrder = order; }
void setSortDescending( bool descending ) { m_sortDescending = descending; }
signals:
- void albums( const QList&, const Tomahawk::collection_ptr& );
- void done( const Tomahawk::collection_ptr& );
+ void albums( const QList&, const QVariant& data );
+ void done();
private:
Tomahawk::collection_ptr m_collection;
+ Tomahawk::artist_ptr m_artist;
+
unsigned int m_amount;
DatabaseCommand_AllAlbums::SortOrder m_sortOrder;
bool m_sortDescending;
diff --git a/src/libtomahawk/database/databasecommand_allartists.cpp b/src/libtomahawk/database/databasecommand_allartists.cpp
new file mode 100644
index 000000000..41b7e3079
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_allartists.cpp
@@ -0,0 +1,68 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#include "databasecommand_allartists.h"
+
+#include
+
+#include "databaseimpl.h"
+
+void
+DatabaseCommand_AllArtists::exec( DatabaseImpl* dbi )
+{
+ TomahawkSqlQuery query = dbi->newquery();
+ QList al;
+ QString orderToken, sourceToken;
+
+ switch ( m_sortOrder )
+ {
+ case 0:
+ break;
+
+ case ModificationTime:
+ orderToken = "file.mtime";
+ }
+
+ if ( !m_collection.isNull() )
+ sourceToken = QString( "AND file.source %1 " ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) );
+
+ QString sql = QString(
+ "SELECT DISTINCT artist.id, artist.name "
+ "FROM artist, file, file_join "
+ "WHERE file.id = file_join.file "
+ "AND file_join.artist = artist.id "
+ "%1 %2 %3 %4"
+ ).arg( sourceToken )
+ .arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( orderToken ) : QString() )
+ .arg( m_sortDescending ? "DESC" : QString() )
+ .arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
+
+ query.prepare( sql );
+ query.exec();
+
+ while( query.next() )
+ {
+ Tomahawk::artist_ptr artist = Tomahawk::Artist::get( query.value( 0 ).toUInt(), query.value( 1 ).toString() );
+
+ al << artist;
+ }
+
+ if ( al.count() )
+ emit artists( al );
+ emit done();
+}
diff --git a/src/libtomahawk/database/databasecommand_allartists.h b/src/libtomahawk/database/databasecommand_allartists.h
new file mode 100644
index 000000000..6d13a107c
--- /dev/null
+++ b/src/libtomahawk/database/databasecommand_allartists.h
@@ -0,0 +1,69 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#ifndef DATABASECOMMAND_ALLARTISTS_H
+#define DATABASECOMMAND_ALLARTISTS_H
+
+#include
+#include
+
+#include "databasecommand.h"
+#include "album.h"
+#include "collection.h"
+#include "typedefs.h"
+
+#include "dllmacro.h"
+
+class DLLEXPORT DatabaseCommand_AllArtists : public DatabaseCommand
+{
+Q_OBJECT
+public:
+ enum SortOrder {
+ None = 0,
+ ModificationTime = 1
+ };
+
+ explicit DatabaseCommand_AllArtists( const Tomahawk::collection_ptr& collection = Tomahawk::collection_ptr(), QObject* parent = 0 )
+ : DatabaseCommand( parent )
+ , m_collection( collection )
+ , m_amount( 0 )
+ , m_sortOrder( DatabaseCommand_AllArtists::None )
+ , m_sortDescending( false )
+ {}
+
+ virtual void exec( DatabaseImpl* );
+
+ virtual bool doesMutates() const { return false; }
+ virtual QString commandname() const { return "allartists"; }
+
+ void setLimit( unsigned int amount ) { m_amount = amount; }
+ void setSortOrder( DatabaseCommand_AllArtists::SortOrder order ) { m_sortOrder = order; }
+ void setSortDescending( bool descending ) { m_sortDescending = descending; }
+
+signals:
+ void artists( const QList& );
+ void done();
+
+private:
+ Tomahawk::collection_ptr m_collection;
+ unsigned int m_amount;
+ DatabaseCommand_AllArtists::SortOrder m_sortOrder;
+ bool m_sortDescending;
+};
+
+#endif // DATABASECOMMAND_ALLARTISTS_H
diff --git a/src/libtomahawk/database/databasecommand_alltracks.cpp b/src/libtomahawk/database/databasecommand_alltracks.cpp
index 07072db4b..01117751c 100644
--- a/src/libtomahawk/database/databasecommand_alltracks.cpp
+++ b/src/libtomahawk/database/databasecommand_alltracks.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -51,10 +51,21 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
break;
}
-
if ( !m_collection.isNull() )
sourceToken = QString( "AND file.source %1" ).arg( m_collection->source()->isLocal() ? "IS NULL" : QString( "= %1" ).arg( m_collection->source()->id() ) );
+ QString albumToken;
+ if ( m_album )
+ {
+ if ( m_album->id() == 0 )
+ {
+ m_artist = m_album->artist().data();
+ albumToken = QString( "AND album.id IS NULL" );
+ }
+ else
+ albumToken = QString( "AND album.id = %1" ).arg( m_album->id() );
+ }
+
QString sql = QString(
"SELECT file.id, artist.name, album.name, track.name, file.size, "
"file.duration, file.bitrate, file.url, file.source, file.mtime, file.mimetype, file_join.albumpos, artist.id, album.id, track.id "
@@ -69,7 +80,7 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
"%4 %5 %6"
).arg( sourceToken )
.arg( !m_artist ? QString() : QString( "AND artist.id = %1" ).arg( m_artist->id() ) )
- .arg( !m_album ? QString() : QString( "AND album.id = %1" ).arg( m_album->id() ) )
+ .arg( !m_album ? QString() : albumToken )
.arg( m_sortOrder > 0 ? QString( "ORDER BY %1" ).arg( m_orderToken ) : QString() )
.arg( m_sortDescending ? "DESC" : QString() )
.arg( m_amount > 0 ? QString( "LIMIT 0, %1" ).arg( m_amount ) : QString() );
@@ -77,7 +88,6 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
query.prepare( sql );
query.exec();
- int i = 0;
while( query.next() )
{
Tomahawk::result_ptr result = Tomahawk::result_ptr( new Tomahawk::Result() );
@@ -139,12 +149,12 @@ DatabaseCommand_AllTracks::exec( DatabaseImpl* dbi )
results << result;
qry->addResults( results );
qry->setResolveFinished( true );
-
+
ql << qry;
}
qDebug() << Q_FUNC_INFO << ql.length();
- emit tracks( ql );
+ emit tracks( ql, data() );
emit done( m_collection );
}
diff --git a/src/libtomahawk/database/databasecommand_alltracks.h b/src/libtomahawk/database/databasecommand_alltracks.h
index 5b8981aed..335c11585 100644
--- a/src/libtomahawk/database/databasecommand_alltracks.h
+++ b/src/libtomahawk/database/databasecommand_alltracks.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -63,7 +63,7 @@ public:
void setSortDescending( bool descending ) { m_sortDescending = descending; }
signals:
- void tracks( const QList& );
+ void tracks( const QList&, const QVariant& data );
void done( const Tomahawk::collection_ptr& );
private:
diff --git a/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp b/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp
index f432f3a25..31b675119 100644
--- a/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp
+++ b/src/libtomahawk/database/databasecommand_createdynamicplaylist.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -53,15 +53,15 @@ DatabaseCommand_CreateDynamicPlaylist::exec( DatabaseImpl* lib )
qDebug() << Q_FUNC_INFO;
Q_ASSERT( !( m_playlist.isNull() && m_v.isNull() ) );
Q_ASSERT( !source().isNull() );
-
+
DatabaseCommand_CreatePlaylist::createPlaylist( lib, true );
qDebug() << "Created normal playlist, now creating additional dynamic info!";
-
+
TomahawkSqlQuery cre = lib->newquery();
cre.prepare( "INSERT INTO dynamic_playlist( guid, pltype, plmode ) "
"VALUES( ?, ?, ? )" );
-
+
if( m_playlist.isNull() ) {
QVariantMap m = m_v.toMap();
cre.addBindValue( m.value( "guid" ) );
@@ -73,22 +73,6 @@ DatabaseCommand_CreateDynamicPlaylist::exec( DatabaseImpl* lib )
cre.addBindValue( m_playlist->mode() );
}
cre.exec();
-
- // save the controls -- wait, no controls in a new playlist :P
-// cre = lib->newquery();
-// cre.prepare( "INSERT INTO dynamic_playlist_controls( id, selectedType, match, input) "
-// "VALUES( :id, :selectedType, :match, :input )" );
-// foreach( const dyncontrol_ptr& control, m_playlist->generator()->controls() ) {
-//
-// cre.bindValue( ":id", control->id() );
-// cre.bindValue( ":selectedType", control->selectedType() );
-// cre.bindValue( ":match", control->match() );
-// cre.bindValue( ":input", control->input() );
-//
-// qDebug() << "CREATE DYNPLAYLIST CONTROL:" << cre.boundValues();
-//
-// cre.exec();
-// }
}
@@ -101,10 +85,10 @@ DatabaseCommand_CreateDynamicPlaylist::postCommitHook()
qDebug() << "Source has gone offline, not emitting to GUI.";
return;
}
-
+
if( report() == false )
return;
-
+
qDebug() << Q_FUNC_INFO << "..reporting..";
if( m_playlist.isNull() ) {
source_ptr src = source();
diff --git a/src/libtomahawk/database/databasecommand_createplaylist.cpp b/src/libtomahawk/database/databasecommand_createplaylist.cpp
index b5bd2ccc2..9a9f32697 100644
--- a/src/libtomahawk/database/databasecommand_createplaylist.cpp
+++ b/src/libtomahawk/database/databasecommand_createplaylist.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -75,25 +75,37 @@ DatabaseCommand_CreatePlaylist::postCommitHook()
} else {
m_playlist->reportCreated( m_playlist );
}
-
+
if( source()->isLocal() )
Servent::instance()->triggerDBSync();
}
-void
+void
DatabaseCommand_CreatePlaylist::createPlaylist( DatabaseImpl* lib, bool dynamic)
{
qDebug() << Q_FUNC_INFO;
Q_ASSERT( !( m_playlist.isNull() && m_v.isNull() ) );
Q_ASSERT( !source().isNull() );
-
+
+ uint now = 0;
+ if( m_playlist.isNull() )
+ {
+ now = m_v.toMap()[ "createdon" ].toUInt();
+ }
+ else
+ {
+ now = QDateTime::currentDateTime().toTime_t();
+ m_playlist->setCreatedOn( now );
+ }
+
TomahawkSqlQuery cre = lib->newquery();
- cre.prepare( "INSERT INTO playlist( guid, source, shared, title, info, creator, lastmodified, dynplaylist) "
- "VALUES( :guid, :source, :shared, :title, :info, :creator, :lastmodified, :dynplaylist )" );
-
+ cre.prepare( "INSERT INTO playlist( guid, source, shared, title, info, creator, lastmodified, dynplaylist, createdOn) "
+ "VALUES( :guid, :source, :shared, :title, :info, :creator, :lastmodified, :dynplaylist, :createdOn )" );
+
cre.bindValue( ":source", source()->isLocal() ? QVariant(QVariant::Int) : source()->id() );
cre.bindValue( ":dynplaylist", dynamic );
+ cre.bindValue( ":createdOn", now );
if( !m_playlist.isNull() ) {
cre.bindValue( ":guid", m_playlist->guid() );
cre.bindValue( ":shared", m_playlist->shared() );
@@ -111,6 +123,6 @@ DatabaseCommand_CreatePlaylist::createPlaylist( DatabaseImpl* lib, bool dynamic)
cre.bindValue( ":lastmodified", m.value( "lastmodified", 0 ) );
}
qDebug() << "CREATE PLAYLIST:" << cre.boundValues();
-
+
cre.exec();
}
diff --git a/src/libtomahawk/database/databasecommand_deletefiles.cpp b/src/libtomahawk/database/databasecommand_deletefiles.cpp
index 503d3887b..f3675369f 100644
--- a/src/libtomahawk/database/databasecommand_deletefiles.cpp
+++ b/src/libtomahawk/database/databasecommand_deletefiles.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -78,18 +78,18 @@ DatabaseCommand_DeleteFiles::exec( DatabaseImpl* dbi )
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.bindValue( 0, "file://" + m_dir.canonicalPath() + "/%" );
dirquery.exec();
while ( dirquery.next() )
{
QFileInfo fi( dirquery.value( 1 ).toString().mid( 7 ) ); // remove file://
- if ( fi.absolutePath() != m_dir.absolutePath() )
+ if ( fi.canonicalPath() != m_dir.canonicalPath() )
{
- if ( lastPath != fi.absolutePath() )
- qDebug() << "Skipping subdir:" << fi.absolutePath();
+ if ( lastPath != fi.canonicalPath() )
+ qDebug() << "Skipping subdir:" << fi.canonicalPath();
- lastPath = fi.absolutePath();
+ lastPath = fi.canonicalPath();
continue;
}
@@ -133,11 +133,11 @@ DatabaseCommand_DeleteFiles::exec( DatabaseImpl* dbi )
<< delquery.boundValues();
continue;
}
-
+
deleted++;
}
}
-
+
qDebug() << "Deleted" << deleted << m_ids << m_files;
emit done( m_files, source()->collection() );
diff --git a/src/libtomahawk/database/databasecommand_dirmtimes.cpp b/src/libtomahawk/database/databasecommand_dirmtimes.cpp
index 07fbad637..c0ef4ffc5 100644
--- a/src/libtomahawk/database/databasecommand_dirmtimes.cpp
+++ b/src/libtomahawk/database/databasecommand_dirmtimes.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -60,7 +60,7 @@ DatabaseCommand_DirMtimes::execSelectPath( DatabaseImpl *dbi, const QDir& path,
"FROM dirs_scanned "
"WHERE name LIKE :prefix" ) );
- query.bindValue( ":prefix", path.absolutePath() + "%" );
+ query.bindValue( ":prefix", path.canonicalPath() + "%" );
query.exec();
while( query.next() )
diff --git a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp b/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp
index 333b596fd..8c5a1bd27 100644
--- a/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp
+++ b/src/libtomahawk/database/databasecommand_loadalldynamicplaylists.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -29,28 +29,29 @@ using namespace Tomahawk;
void DatabaseCommand_LoadAllDynamicPlaylists::exec( DatabaseImpl* dbi )
{
TomahawkSqlQuery query = dbi->newquery();
-
- query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode "
+
+ query.exec( QString( "SELECT playlist.guid as guid, title, info, creator, createdOn, lastmodified, shared, currentrevision, dynamic_playlist.pltype, dynamic_playlist.plmode "
"FROM playlist, dynamic_playlist WHERE source %1 AND dynplaylist = 'true' AND playlist.guid = dynamic_playlist.guid" )
.arg( source()->isLocal() ? "IS NULL" :
QString( "=%1" ).arg( source()->id() )
) );
-
+
QList plists;
while ( query.next() )
{
- QVariantList data = QVariantList() << query.value(6).toString() //current rev
+ QVariantList data = QVariantList() << query.value(7).toString() //current rev
<< query.value(1).toString() //title
<< query.value(2).toString() //info
<< query.value(3).toString() //creator
- << query.value(7).toString() // dynamic type
- << static_cast(query.value(8).toInt()) // dynamic mode
- << query.value(5).toBool() //shared
- << query.value(4).toInt() //lastmod
+ << query.value(4).toString() //createdOn
+ << query.value(8).toString() // dynamic type
+ << static_cast(query.value(9).toInt()) // dynamic mode
+ << query.value(6).toBool() //shared
+ << query.value(5).toInt() //lastmod
<< query.value(0).toString(); //GUID
emit playlistLoaded( source(), data );
}
-
+
emit done();
}
diff --git a/src/libtomahawk/database/databasecommand_loadallplaylists.cpp b/src/libtomahawk/database/databasecommand_loadallplaylists.cpp
index db7865767..c2f0782bc 100644
--- a/src/libtomahawk/database/databasecommand_loadallplaylists.cpp
+++ b/src/libtomahawk/database/databasecommand_loadallplaylists.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -30,7 +30,7 @@ void DatabaseCommand_LoadAllPlaylists::exec( DatabaseImpl* dbi )
{
TomahawkSqlQuery query = dbi->newquery();
- query.exec( QString( "SELECT guid, title, info, creator, lastmodified, shared, currentrevision "
+ query.exec( QString( "SELECT guid, title, info, creator, lastmodified, shared, currentrevision, createdOn "
"FROM playlist WHERE source %1 AND dynplaylist = 'false'" )
.arg( source()->isLocal() ? "IS NULL" :
QString( "= %1" ).arg( source()->id() )
@@ -44,6 +44,7 @@ void DatabaseCommand_LoadAllPlaylists::exec( DatabaseImpl* dbi )
query.value(1).toString(), //title
query.value(2).toString(), //info
query.value(3).toString(), //creator
+ query.value(7).toInt(), //lastmod
query.value(5).toBool(), //shared
query.value(4).toInt(), //lastmod
query.value(0).toString() //GUID
diff --git a/src/libtomahawk/database/databasecommand_loadops.h b/src/libtomahawk/database/databasecommand_loadops.h
index 6a3580f42..06c8cb56f 100644
--- a/src/libtomahawk/database/databasecommand_loadops.h
+++ b/src/libtomahawk/database/databasecommand_loadops.h
@@ -32,7 +32,9 @@ Q_OBJECT
public:
explicit DatabaseCommand_loadOps( const Tomahawk::source_ptr& src, QString since, QObject* parent = 0 )
: DatabaseCommand( src ), m_since( since )
- {}
+ {
+ Q_UNUSED( parent );
+ }
virtual void exec( DatabaseImpl* db );
virtual bool doesMutates() const { return false; }
diff --git a/src/libtomahawk/database/databasecommand_loadplaylistentries.h b/src/libtomahawk/database/databasecommand_loadplaylistentries.h
index ec597ef67..255c9a017 100644
--- a/src/libtomahawk/database/databasecommand_loadplaylistentries.h
+++ b/src/libtomahawk/database/databasecommand_loadplaylistentries.h
@@ -33,7 +33,7 @@ Q_OBJECT
public:
explicit DatabaseCommand_LoadPlaylistEntries( QString revision_guid, QObject* parent = 0 )
- : DatabaseCommand( parent ), m_revguid( revision_guid ), m_islatest( true )
+ : DatabaseCommand( parent ), m_islatest( true ), m_revguid( revision_guid )
{}
virtual void exec( DatabaseImpl* );
diff --git a/src/libtomahawk/database/databasecommand_modifyplaylist.cpp b/src/libtomahawk/database/databasecommand_modifyplaylist.cpp
index 640fe8a3c..1d60da687 100644
--- a/src/libtomahawk/database/databasecommand_modifyplaylist.cpp
+++ b/src/libtomahawk/database/databasecommand_modifyplaylist.cpp
@@ -32,4 +32,5 @@ DatabaseCommand_ModifyPlaylist::DatabaseCommand_ModifyPlaylist( Playlist* playli
void DatabaseCommand_ModifyPlaylist::exec( DatabaseImpl* lib )
{
+ Q_UNUSED( lib );
}
diff --git a/src/libtomahawk/database/databaseimpl.cpp b/src/libtomahawk/database/databaseimpl.cpp
index ff96c3d7d..e052368f0 100644
--- a/src/libtomahawk/database/databaseimpl.cpp
+++ b/src/libtomahawk/database/databaseimpl.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -30,6 +30,7 @@
#include "result.h"
#include "artist.h"
#include "album.h"
+#include "utils/tomahawkutils.h"
/* !!!! You need to manually generate schema.sql.h when the schema changes:
cd src/libtomahawk/database
@@ -37,7 +38,7 @@
*/
#include "schema.sql.h"
-#define CURRENT_SCHEMA_VERSION 22
+#define CURRENT_SCHEMA_VERSION 23
DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
@@ -63,21 +64,22 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
int v = qry.value( 0 ).toInt();
qDebug() << "Current schema is" << v << this->thread();
if ( v != CURRENT_SCHEMA_VERSION )
- {
+ {
QString newname = QString("%1.v%2").arg(dbname).arg(v);
qDebug() << endl << "****************************" << endl;
qDebug() << "Schema version too old: " << v << ". Current version is:" << CURRENT_SCHEMA_VERSION;
qDebug() << "Moving" << dbname << newname;
+ qDebug() << "If the migration fails, you can recover your DB by copying" << newname << "back to" << dbname;
qDebug() << endl << "****************************" << endl;
qry.clear();
qry.finish();
-
+
db.close();
db.removeDatabase( "tomahawk" );
- if( QFile::rename( dbname, newname ) )
+ if( QFile::copy( dbname, newname ) )
{
db = QSqlDatabase::addDatabase( "QSQLITE", "tomahawk" );
db.setDatabaseName( dbname );
@@ -87,6 +89,13 @@ DatabaseImpl::DatabaseImpl( const QString& dbname, Database* parent )
TomahawkSqlQuery query = newquery();
query.exec( "PRAGMA auto_vacuum = FULL" );
schemaUpdated = updateSchema( v );
+
+ if( !schemaUpdated )
+ {
+ Q_ASSERT( false );
+ QTimer::singleShot( 0, qApp, SLOT( quit() ) );
+ }
+
}
else
{
@@ -149,26 +158,73 @@ DatabaseImpl::updateSearchIndex()
bool
-DatabaseImpl::updateSchema( int currentver )
+DatabaseImpl::updateSchema( int oldVersion )
{
- qDebug() << "Create tables... old version is" << currentver;
- QString sql( get_tomahawk_sql() );
- QStringList statements = sql.split( ";", QString::SkipEmptyParts );
- db.transaction();
-
- foreach( const QString& sl, statements )
+ // we are called here with the old database. we must migrate it to the CURRENT_SCHEMA_VERSION from the oldVersion
+ if ( oldVersion == 0 ) // empty database, so create our tables and stuff
{
- QString s( sl.trimmed() );
- if( s.length() == 0 )
- continue;
+ qDebug() << "Create tables... old version is" << oldVersion;
+ QString sql( get_tomahawk_sql() );
+ QStringList statements = sql.split( ";", QString::SkipEmptyParts );
+ db.transaction();
- qDebug() << "Executing:" << s;
- TomahawkSqlQuery query = newquery();
- query.exec( s );
+ foreach( const QString& sl, statements )
+ {
+ QString s( sl.trimmed() );
+ if( s.length() == 0 )
+ continue;
+
+ qDebug() << "Executing:" << s;
+ TomahawkSqlQuery query = newquery();
+ query.exec( s );
+ }
+
+ db.commit();
+ return true;
}
+ else // update in place! run the proper upgrade script
+ {
+ int cur = oldVersion;
+ db.transaction();
+ while ( cur < CURRENT_SCHEMA_VERSION )
+ {
+ cur++;
- db.commit();
- return true;
+ QString path = QString( RESPATH "sql/dbmigrate-%1_to_%2.sql" ).arg( cur - 1 ).arg( cur );
+ QFile script( path );
+ if( !script.exists() || !script.open( QIODevice::ReadOnly ) )
+ {
+ qWarning() << "Failed to find or open upgrade script from" << (cur-1) << "to" << cur << " (" << path << ")! Aborting upgrade..";
+ return false;
+ }
+
+ QString sql = QString::fromUtf8( script.readAll() ).trimmed();
+ QStringList statements = sql.split( ";", QString::SkipEmptyParts );
+ foreach( const QString& sql, statements )
+ {
+ QString clean = cleanSql( sql ).trimmed();
+ if( clean.isEmpty() )
+ continue;
+
+ qDebug() << "Executing upgrade statement:" << clean;
+ TomahawkSqlQuery q = newquery();
+ q.exec( clean );
+ }
+ }
+ db.commit();
+ qDebug() << "DB Upgrade successful!";
+ return true;
+ }
+}
+
+
+QString
+DatabaseImpl::cleanSql( const QString& sql )
+{
+ QString fixed = sql;
+ QRegExp r( "--[^\\n]*" );
+ fixed.replace( r, QString() );
+ return fixed.trimmed();
}
@@ -369,6 +425,7 @@ DatabaseImpl::albumId( int artistid, const QString& name_orig, bool& isnew )
QList< int >
DatabaseImpl::searchTable( const QString& table, const QString& name, uint limit )
{
+ Q_UNUSED( limit );
QList< int > results;
if( table != "artist" && table != "track" && table != "album" )
return results;
diff --git a/src/libtomahawk/database/databaseimpl.h b/src/libtomahawk/database/databaseimpl.h
index e2965f553..f3551b634 100644
--- a/src/libtomahawk/database/databaseimpl.h
+++ b/src/libtomahawk/database/databaseimpl.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -84,9 +84,11 @@ signals:
public slots:
private:
+ QString cleanSql( const QString& sql );
+
bool m_ready;
-
- bool updateSchema( int currentver );
+
+ bool updateSchema( int oldVersion );
QSqlDatabase db;
diff --git a/src/libtomahawk/database/databaseworker.cpp b/src/libtomahawk/database/databaseworker.cpp
index 791888e80..e0d1f7be7 100644
--- a/src/libtomahawk/database/databaseworker.cpp
+++ b/src/libtomahawk/database/databaseworker.cpp
@@ -32,6 +32,9 @@ DatabaseWorker::DatabaseWorker( DatabaseImpl* lib, Database* db, bool mutates )
, m_abort( false )
, m_outstanding( 0 )
{
+ Q_UNUSED( db );
+ Q_UNUSED( mutates );
+
moveToThread( this );
qDebug() << "CTOR DatabaseWorker" << this->thread();
diff --git a/src/libtomahawk/database/fuzzyindex.cpp b/src/libtomahawk/database/fuzzyindex.cpp
index 25719317c..31d4f5754 100644
--- a/src/libtomahawk/database/fuzzyindex.cpp
+++ b/src/libtomahawk/database/fuzzyindex.cpp
@@ -179,7 +179,7 @@ FuzzyIndex::search( const QString& table, const QString& name )
FuzzyQuery* qry = _CLNEW FuzzyQuery( _CLNEW Term( table.toStdWString().c_str(), DatabaseImpl::sortname( name ).toStdWString().c_str() ) );
hits = m_luceneSearcher->search( qry );
- for ( int i = 0; i < hits->length(); i++ )
+ for ( uint i = 0; i < hits->length(); i++ )
{
Document* d = &hits->doc( i );
diff --git a/src/libtomahawk/database/schema.sql b/src/libtomahawk/database/schema.sql
index e35973508..e2f6ce90d 100644
--- a/src/libtomahawk/database/schema.sql
+++ b/src/libtomahawk/database/schema.sql
@@ -67,13 +67,14 @@ CREATE TABLE IF NOT EXISTS playlist (
creator TEXT,
lastmodified INTEGER NOT NULL DEFAULT 0,
currentrevision TEXT REFERENCES playlist_revision(guid) DEFERRABLE INITIALLY DEFERRED,
- dynplaylist BOOLEAN DEFAULT false
+ dynplaylist BOOLEAN DEFAULT false,
+ createdOn INTEGER NOT NULL DEFAULT 0
);
---INSERT INTO playlist(guid, title, info, currentrevision, dynplaylist)
+--INSERT INTO playlist(guid, title, info, currentrevision, dynplaylist)
--VALUES('dynamic_playlist-guid-1','Test Dynamic Playlist Dynamic','this playlist automatically created and used for testing','revisionguid-1', 1);
---INSERT INTO playlist(guid, title, info, currentrevision, dynplaylist)
+--INSERT INTO playlist(guid, title, info, currentrevision, dynplaylist)
--VALUES('dynamic_playlist-guid-2','Test Dynamic Playlist Static','this playlist automatically created and used for testing','revisionguid-11', 1);
CREATE TABLE IF NOT EXISTS playlist_item (
@@ -129,8 +130,8 @@ CREATE TABLE IF NOT EXISTS dynamic_playlist_controls (
--INSERT INTO dynamic_playlist_controls(id, playlist, selectedType, match, input)
-- VALUES('controlid-2', 'dynamic_playlist-guid-11', "artist", 0, "FooArtist" );
-
-
+
+
CREATE TABLE IF NOT EXISTS dynamic_playlist_revision (
guid TEXT PRIMARY KEY NOT NULL REFERENCES playlist_revision(guid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
controls TEXT, -- qlist( id, id, id )
@@ -148,7 +149,7 @@ CREATE TABLE IF NOT EXISTS dynamic_playlist_revision (
-- if source=null, file is local to this machine
CREATE TABLE IF NOT EXISTS file (
- id INTEGER PRIMARY KEY AUTOINCREMENT,
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
source INTEGER REFERENCES source(id) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
url TEXT NOT NULL, -- file:///music/foo/bar.mp3,
size INTEGER NOT NULL, -- in bytes
@@ -212,7 +213,7 @@ CREATE TABLE IF NOT EXISTS artist_tags (
);
CREATE INDEX artist_tags_tag ON artist_tags(tag);
--- all other attributes.
+-- all other attributes.
-- like tags that have a value, eg:
-- BPM=120, releaseyear=1980, key=Dminor, composer=Someone
-- NB: since all values are text, numeric values should be zero-padded to a set amount
@@ -263,4 +264,4 @@ CREATE TABLE IF NOT EXISTS settings (
v TEXT NOT NULL DEFAULT ''
);
-INSERT INTO settings(k,v) VALUES('schema_version', '22');
+INSERT INTO settings(k,v) VALUES('schema_version', '23');
diff --git a/src/libtomahawk/database/schema.sql.h b/src/libtomahawk/database/schema.sql.h
index dfd468cf8..864766dc6 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 Wed Mar 2 01:40:39 CET 2011.
+ This file was automatically generated from schema.sql on Fri Apr 15 15:55:52 EDT 2011.
*/
static const char * tomahawk_schema_sql =
@@ -51,7 +51,8 @@ static const char * tomahawk_schema_sql =
" creator TEXT,"
" lastmodified INTEGER NOT NULL DEFAULT 0,"
" currentrevision TEXT REFERENCES playlist_revision(guid) DEFERRABLE INITIALLY DEFERRED,"
-" dynplaylist BOOLEAN DEFAULT false"
+" dynplaylist BOOLEAN DEFAULT false,"
+" createdOn INTEGER NOT NULL DEFAULT 0"
");"
"CREATE TABLE IF NOT EXISTS playlist_item ("
" guid TEXT PRIMARY KEY,"
@@ -86,8 +87,6 @@ static const char * tomahawk_schema_sql =
" match TEXT,"
" input TEXT"
");"
-""
-""
"CREATE TABLE IF NOT EXISTS dynamic_playlist_revision ("
" guid TEXT PRIMARY KEY NOT NULL REFERENCES playlist_revision(guid) ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,"
" controls TEXT, "
@@ -173,7 +172,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', '22');"
+"INSERT INTO settings(k,v) VALUES('schema_version', '23');"
;
const char * get_tomahawk_sql()
diff --git a/src/libtomahawk/functimeout.h b/src/libtomahawk/functimeout.h
index c66134311..bbb632f59 100644
--- a/src/libtomahawk/functimeout.h
+++ b/src/libtomahawk/functimeout.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -22,6 +22,7 @@
#include
#include
#include
+#include
#include "boost/function.hpp"
#include "boost/bind.hpp"
@@ -43,8 +44,9 @@ class DLLEXPORT FuncTimeout : public QObject
Q_OBJECT
public:
- FuncTimeout( int ms, boost::function func )
+ FuncTimeout( int ms, boost::function func, QObject* besafe )
: m_func( func )
+ , m_watch( QWeakPointer< QObject >( besafe ) )
{
//qDebug() << Q_FUNC_INFO;
QTimer::singleShot( ms, this, SLOT( exec() ) );
@@ -58,12 +60,14 @@ public:
public slots:
void exec()
{
- m_func();
+ if( !m_watch.isNull() )
+ m_func();
this->deleteLater();
};
private:
boost::function m_func;
+ QWeakPointer< QObject > m_watch;
};
}; // ns
diff --git a/src/infosystem/infoplugins/echonestplugin.cpp b/src/libtomahawk/infosystem/infoplugins/echonestplugin.cpp
similarity index 98%
rename from src/infosystem/infoplugins/echonestplugin.cpp
rename to src/libtomahawk/infosystem/infoplugins/echonestplugin.cpp
index 38f64ed4c..73dd3b7b2 100644
--- a/src/infosystem/infoplugins/echonestplugin.cpp
+++ b/src/libtomahawk/infosystem/infoplugins/echonestplugin.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -16,8 +16,6 @@
* along with Tomahawk. If not, see .
*/
-#include "tomahawk/infosystem.h"
-#include "tomahawk/tomahawkapp.h"
#include "echonestplugin.h"
#include
#include
@@ -68,13 +66,14 @@ void EchoNestPlugin::getInfo(const QString &caller, const InfoType type, const Q
void EchoNestPlugin::getSongProfile(const QString &caller, const QVariant& data, InfoCustomData &customData, const QString &item)
{
//WARNING: Totally not implemented yet
+ Q_UNUSED( item );
if( !isValidTrackData( caller, data, customData ) )
return;
-
+
// Track track( data.toString() );
// Artist artist( customData.data()->property("artistName").toString() );
-// reply->setProperty("artist", QVariant::fromValue(artist));
+// reply->setProperty("artist", QVariant::fromValue(artist));
// reply->setProperty( "data", data );
// m_replyMap[reply] = customData;
// connect(reply, SIGNAL(finished()), SLOT(getArtistBiographySlot()));
@@ -84,7 +83,7 @@ void EchoNestPlugin::getArtistBiography(const QString &caller, const QVariant& d
{
if( !isValidArtistData( caller, data, customData ) )
return;
-
+
Echonest::Artist artist( data.toString() );
QNetworkReply *reply = artist.fetchBiographies();
reply->setProperty("artist", QVariant::fromValue(artist));
@@ -98,7 +97,7 @@ void EchoNestPlugin::getArtistFamiliarity(const QString &caller, const QVariant&
{
if( !isValidArtistData( caller, data, customData ) )
return;
-
+
qDebug() << "Fetching artist familiarity!" << data;
Echonest::Artist artist( data.toString() );
QNetworkReply* reply = artist.fetchFamiliarity();
@@ -106,14 +105,14 @@ void EchoNestPlugin::getArtistFamiliarity(const QString &caller, const QVariant&
reply->setProperty( "data", data );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
- connect(reply, SIGNAL(finished()), SLOT(getArtistFamiliaritySlot()));
+ connect(reply, SIGNAL(finished()), SLOT(getArtistFamiliaritySlot()));
}
void EchoNestPlugin::getArtistHotttnesss(const QString &caller, const QVariant& data, InfoCustomData &customData)
{
if( !isValidArtistData( caller, data, customData ) )
return;
-
+
Echonest::Artist artist( data.toString() );
QNetworkReply* reply = artist.fetchHotttnesss();
reply->setProperty( "artist", QVariant::fromValue(artist));
@@ -127,7 +126,7 @@ void EchoNestPlugin::getArtistTerms(const QString &caller, const QVariant& data,
{
if( !isValidArtistData( caller, data, customData ) )
return;
-
+
Echonest::Artist artist( data.toString() );
QNetworkReply* reply = artist.fetchTerms( Echonest::Artist::Weight );
reply->setProperty( "artist", QVariant::fromValue(artist));
@@ -139,6 +138,7 @@ void EchoNestPlugin::getArtistTerms(const QString &caller, const QVariant& data,
void EchoNestPlugin::getMiscTopTerms(const QString &caller, const QVariant& data, InfoCustomData& customData)
{
+ Q_UNUSED( data );
QNetworkReply* reply = Echonest::Artist::topTerms( 20 );
m_replyMap[reply] = customData;
m_callerMap[reply] = caller;
@@ -160,7 +160,7 @@ void EchoNestPlugin::getArtistBiographySlot()
biographyMap[biography.site()]["attribution"] = biography.license().attribution;
biographyMap[biography.site()]["licensetype"] = biography.license().type;
biographyMap[biography.site()]["attribution"] = biography.license().url.toString();
-
+
}
emit info( m_callerMap[reply], Tomahawk::InfoSystem::InfoArtistBiography, reply->property( "data" ), QVariant::fromValue(biographyMap), m_replyMap[reply] );
m_replyMap.remove(reply);
@@ -254,7 +254,7 @@ bool EchoNestPlugin::isValidTrackData(const QString &caller, const QVariant& dat
emit info(caller, Tomahawk::InfoSystem::InfoNoInfo, QVariant(), QVariant(), customData);
return false;
}
- if (!customData.contains("artistName") ||
+ if (!customData.contains("artistName") ||
customData["artistName"].toString().isEmpty())
return false;
return true;
diff --git a/src/infosystem/infoplugins/echonestplugin.h b/src/libtomahawk/infosystem/infoplugins/echonestplugin.h
similarity index 97%
rename from src/infosystem/infoplugins/echonestplugin.h
rename to src/libtomahawk/infosystem/infoplugins/echonestplugin.h
index d4a4db367..25276c373 100644
--- a/src/infosystem/infoplugins/echonestplugin.h
+++ b/src/libtomahawk/infosystem/infoplugins/echonestplugin.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -19,7 +19,7 @@
#ifndef ECHONESTPLUGIN_H
#define ECHONESTPLUGIN_H
-#include "tomahawk/infosystem.h"
+#include "infosystem/infosystem.h"
#include
@@ -37,13 +37,13 @@ namespace InfoSystem
class EchoNestPlugin : public InfoPlugin
{
Q_OBJECT
-
+
public:
EchoNestPlugin(QObject *parent);
virtual ~EchoNestPlugin();
-
+
void getInfo( const QString &caller, const InfoType type, const QVariant &data, InfoCustomData customData );
-
+
private:
void getSongProfile( const QString &caller, const QVariant &data, InfoCustomData &customData, const QString &item = QString() );
void getArtistBiography ( const QString &caller, const QVariant &data, InfoCustomData &customData );
@@ -55,14 +55,14 @@ private:
bool isValidArtistData( const QString &caller, const QVariant& data, InfoCustomData& customData );
bool isValidTrackData( const QString &caller, const QVariant& data, InfoCustomData& customData );
Echonest::Artist artistFromReply( QNetworkReply* );
-
+
private slots:
void getArtistBiographySlot();
void getArtistFamiliaritySlot();
void getArtistHotttnesssSlot();
void getArtistTermsSlot();
void getMiscTopSlot();
-
+
private:
QHash< QNetworkReply*, InfoCustomData > m_replyMap;
QHash< QNetworkReply*, QString > m_callerMap;
diff --git a/src/infosystem/infoplugins/lastfmplugin.cpp b/src/libtomahawk/infosystem/infoplugins/lastfmplugin.cpp
similarity index 64%
rename from src/infosystem/infoplugins/lastfmplugin.cpp
rename to src/libtomahawk/infosystem/infoplugins/lastfmplugin.cpp
index 652d87414..407031f1e 100644
--- a/src/infosystem/infoplugins/lastfmplugin.cpp
+++ b/src/libtomahawk/infosystem/infoplugins/lastfmplugin.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -26,7 +26,7 @@
#include "typedefs.h"
#include "audio/audioengine.h"
#include "tomahawksettings.h"
-#include "tomahawk/tomahawkapp.h"
+#include "utils/tomahawkutils.h"
#include
#include
@@ -47,9 +47,9 @@ LastFmPlugin::LastFmPlugin( QObject* parent )
, m_authJob( 0 )
{
QSet< InfoType > supportedTypes;
- supportedTypes << InfoMiscSubmitScrobble << InfoMiscSubmitNowPlaying << InfoAlbumCoverArt;
+ supportedTypes << InfoMiscSubmitScrobble << InfoMiscSubmitNowPlaying << InfoAlbumCoverArt << InfoArtistImages;
qobject_cast< InfoSystem* >(parent)->registerInfoTypes(this, supportedTypes);
-
+
/*
Your API Key is 7194b85b6d1f424fe1668173a78c0c4a
Your secret is ba80f1df6d27ae63e9cb1d33ccf2052f
@@ -61,14 +61,14 @@ LastFmPlugin::LastFmPlugin( QObject* parent )
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
lastfm::ws::Username = TomahawkSettings::instance()->lastFmUsername();
-
+
m_pw = TomahawkSettings::instance()->lastFmPassword();
-
+
if( TomahawkSettings::instance()->scrobblingEnabled() && !lastfm::ws::Username.isEmpty() )
{
createScrobbler();
}
-
+
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
// tries to write the track cache, it fails silently. until we have a fixed version, do this
// code taken from Amarok (src/services/lastfm/ScrobblerAdapter.cpp)
@@ -81,6 +81,8 @@ LastFmPlugin::LastFmPlugin( QObject* parent )
}
#endif
+ m_badUrls << QUrl( "http://cdn.last.fm/flatness/catalogue/noimage" );
+
connect( TomahawkSettings::instance(), SIGNAL( changed() ),
SLOT( settingsChanged() ), Qt::QueuedConnection );
}
@@ -91,6 +93,7 @@ LastFmPlugin::~LastFmPlugin()
delete m_scrobbler;
}
+
void
LastFmPlugin::dataError( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData )
{
@@ -98,20 +101,36 @@ LastFmPlugin::dataError( const QString &caller, const InfoType type, const QVari
return;
}
+
void
LastFmPlugin::getInfo( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData customData )
{
qDebug() << Q_FUNC_INFO;
- if ( type == InfoMiscSubmitNowPlaying )
- nowPlaying( caller, type, data, customData );
- else if ( type == InfoMiscSubmitScrobble )
- scrobble( caller, type, data, customData );
- else if ( type == InfoAlbumCoverArt )
- fetchCoverArt( caller, type, data, customData );
- else
- dataError( caller, type, data, customData );
+
+ switch ( type )
+ {
+ case InfoMiscSubmitNowPlaying:
+ nowPlaying( caller, type, data, customData );
+ break;
+
+ case InfoMiscSubmitScrobble:
+ scrobble( caller, type, data, customData );
+ break;
+
+ case InfoArtistImages:
+ fetchArtistImages( caller, type, data, customData );
+ break;
+
+ case InfoAlbumCoverArt:
+ fetchCoverArt( caller, type, data, customData );
+ break;
+
+ default:
+ dataError( caller, type, data, customData );
+ }
}
+
void
LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData )
{
@@ -126,7 +145,7 @@ LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVar
dataError( caller, type, data, customData );
return;
}
-
+
m_track = lastfm::MutableTrack();
m_track.stamp();
@@ -140,6 +159,7 @@ LastFmPlugin::nowPlaying( const QString &caller, const InfoType type, const QVar
emit info( caller, type, data, QVariant(), customData );
}
+
void
LastFmPlugin::scrobble( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData )
{
@@ -154,10 +174,11 @@ LastFmPlugin::scrobble( const QString &caller, const InfoType type, const QVaria
qDebug() << Q_FUNC_INFO << m_track.toString();
m_scrobbler->cache( m_track );
m_scrobbler->submit();
-
+
emit info( caller, type, data, QVariant(), customData );
}
+
void
LastFmPlugin::fetchCoverArt( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData )
{
@@ -173,38 +194,84 @@ LastFmPlugin::fetchCoverArt( const QString &caller, const InfoType type, const Q
dataError( caller, type, data, customData );
return;
}
-
+
Tomahawk::InfoSystem::InfoCacheCriteria criteria;
criteria["artist"] = hash["artist"].toString();
criteria["album"] = hash["album"].toString();
-
- emit getCachedInfo( criteria, caller, type, data, customData );
+
+ emit getCachedInfo( criteria, 2419200000, caller, type, data, customData );
}
+
+void
+LastFmPlugin::fetchArtistImages( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData )
+{
+ qDebug() << Q_FUNC_INFO;
+ if ( !data.canConvert< Tomahawk::InfoSystem::InfoCustomData >() )
+ {
+ dataError( caller, type, data, customData );
+ return;
+ }
+ InfoCustomData hash = data.value< Tomahawk::InfoSystem::InfoCustomData >();
+ if ( !hash.contains( "artist" ) )
+ {
+ dataError( caller, type, data, customData );
+ return;
+ }
+
+ Tomahawk::InfoSystem::InfoCacheCriteria criteria;
+ criteria["artist"] = hash["artist"].toString();
+
+ emit getCachedInfo( criteria, 2419200000, caller, type, data, customData );
+}
+
+
void
LastFmPlugin::notInCacheSlot( QHash criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData )
{
qDebug() << Q_FUNC_INFO;
- if ( type == InfoAlbumCoverArt )
+
+ switch ( type )
{
- QString artistName = criteria["artist"];
- QString albumName = criteria["album"];
+ case InfoAlbumCoverArt:
+ {
+ QString artistName = criteria["artist"];
+ QString albumName = criteria["album"];
- QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=album.imageredirect&artist=%1&album=%2&size=medium&api_key=7a90f6672a04b809ee309af169f34b8b";
- QNetworkRequest req( imgurl.arg( artistName ).arg( albumName ) );
- QNetworkReply* reply = TomahawkUtils::nam()->get( req );
- reply->setProperty( "customData", QVariant::fromValue( customData ) );
- reply->setProperty( "origData", input );
- reply->setProperty( "caller", caller );
- reply->setProperty( "type", (uint)(type) );
+ QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=album.imageredirect&artist=%1&album=%2&autocorrect=1&size=medium&api_key=7a90f6672a04b809ee309af169f34b8b";
+ QNetworkRequest req( imgurl.arg( artistName ).arg( albumName ) );
+ QNetworkReply* reply = TomahawkUtils::nam()->get( req );
+ reply->setProperty( "customData", QVariant::fromValue( customData ) );
+ reply->setProperty( "origData", input );
+ reply->setProperty( "caller", caller );
+ reply->setProperty( "type", (uint)(type) );
- connect( reply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
- return;
+ connect( reply, SIGNAL( finished() ), SLOT( coverArtReturned() ) );
+ return;
+ }
+
+ case InfoArtistImages:
+ {
+ QString artistName = criteria["artist"];
+
+ QString imgurl = "http://ws.audioscrobbler.com/2.0/?method=artist.imageredirect&artist=%1&autocorrect=1&size=medium&api_key=7a90f6672a04b809ee309af169f34b8b";
+ QNetworkRequest req( imgurl.arg( artistName ) );
+ QNetworkReply* reply = TomahawkUtils::nam()->get( req );
+ reply->setProperty( "customData", QVariant::fromValue( customData ) );
+ reply->setProperty( "origData", input );
+ reply->setProperty( "caller", caller );
+ reply->setProperty( "type", (uint)(type) );
+
+ connect( reply, SIGNAL( finished() ), SLOT( artistImagesReturned() ) );
+ return;
+ }
+
+ default:
+ qDebug() << "Couldn't figure out what to do with this type of request after cache miss";
}
- else
- qDebug() << "Couldn't figure out what to do with this type of request after cache miss";
}
+
void
LastFmPlugin::coverArtReturned()
{
@@ -213,11 +280,17 @@ LastFmPlugin::coverArtReturned()
QUrl redir = reply->attribute( QNetworkRequest::RedirectionTargetAttribute ).toUrl();
if ( redir.isEmpty() )
{
- const QByteArray ba = reply->readAll();
+ QByteArray ba = reply->readAll();
+ foreach ( const QUrl& url, m_badUrls )
+ {
+ if ( reply->url().toString().startsWith( url.toString() ) )
+ ba = QByteArray();
+ }
+
InfoCustomData returnedData;
returnedData["imgbytes"] = ba;
returnedData["url"] = reply->url().toString();
-
+
InfoCustomData customData = reply->property( "customData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
InfoType type = (Tomahawk::InfoSystem::InfoType)(reply->property( "type" ).toUInt());
emit info(
@@ -227,12 +300,12 @@ LastFmPlugin::coverArtReturned()
returnedData,
customData
);
-
+
InfoCustomData origData = reply->property( "origData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
Tomahawk::InfoSystem::InfoCacheCriteria criteria;
criteria["artist"] = origData["artist"].toString();
criteria["album"] = origData["album"].toString();
- emit updateCache( criteria, type, returnedData );
+ emit updateCache( criteria, 2419200000, type, returnedData );
}
else
{
@@ -249,6 +322,57 @@ LastFmPlugin::coverArtReturned()
reply->deleteLater();
}
+
+void
+LastFmPlugin::artistImagesReturned()
+{
+ qDebug() << Q_FUNC_INFO;
+ QNetworkReply* reply = qobject_cast( sender() );
+ QUrl redir = reply->attribute( QNetworkRequest::RedirectionTargetAttribute ).toUrl();
+ if ( redir.isEmpty() )
+ {
+ QByteArray ba = reply->readAll();
+ foreach ( const QUrl& url, m_badUrls )
+ {
+ if ( reply->url().toString().startsWith( url.toString() ) )
+ ba = QByteArray();
+ }
+
+ InfoCustomData returnedData;
+ returnedData["imgbytes"] = ba;
+ returnedData["url"] = reply->url().toString();
+
+ InfoCustomData customData = reply->property( "customData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
+ InfoType type = (Tomahawk::InfoSystem::InfoType)(reply->property( "type" ).toUInt());
+ emit info(
+ reply->property( "caller" ).toString(),
+ type,
+ reply->property( "origData" ),
+ returnedData,
+ customData
+ );
+
+ InfoCustomData origData = reply->property( "origData" ).value< Tomahawk::InfoSystem::InfoCustomData >();
+ Tomahawk::InfoSystem::InfoCacheCriteria criteria;
+ criteria["artist"] = origData["artist"].toString();
+ emit updateCache( criteria, 2419200000, type, returnedData );
+ }
+ else
+ {
+ // Follow HTTP redirect
+ QNetworkRequest req( redir );
+ QNetworkReply* newReply = TomahawkUtils::nam()->get( req );
+ newReply->setProperty( "origData", reply->property( "origData" ) );
+ newReply->setProperty( "customData", reply->property( "customData" ) );
+ newReply->setProperty( "caller", reply->property( "caller" ) );
+ newReply->setProperty( "type", reply->property( "type" ) );
+ connect( newReply, SIGNAL( finished() ), SLOT( artistImagesReturned() ) );
+ }
+
+ reply->deleteLater();
+}
+
+
void
LastFmPlugin::settingsChanged()
{
@@ -280,12 +404,12 @@ LastFmPlugin::settingsChanged()
void
LastFmPlugin::onAuthenticated()
{
- if( !m_authJob )
+ if( !m_authJob )
{
qDebug() << Q_FUNC_INFO << "Help! No longer got a last.fm auth job!";
return;
}
-
+
if( m_authJob->error() == QNetworkReply::NoError )
{
lastfm::XmlQuery lfm = lastfm::XmlQuery( m_authJob->readAll() );
@@ -294,7 +418,7 @@ LastFmPlugin::onAuthenticated()
{
qDebug() << "Error from authenticating with Last.fm service:" << lfm.text();
TomahawkSettings::instance()->setLastFmSessionKey( QByteArray() );
-
+
}
else
{
@@ -310,7 +434,7 @@ LastFmPlugin::onAuthenticated()
{
qDebug() << "Got error in Last.fm authentication job:" << m_authJob->errorString();
}
-
+
m_authJob->deleteLater();
}
@@ -321,19 +445,19 @@ LastFmPlugin::createScrobbler()
if( TomahawkSettings::instance()->lastFmSessionKey().isEmpty() ) // no session key, so get one
{
QString authToken = md5( ( lastfm::ws::Username.toLower() + md5( m_pw.toUtf8() ) ).toUtf8() );
-
+
QMap query;
query[ "method" ] = "auth.getMobileSession";
query[ "username" ] = lastfm::ws::Username;
query[ "authToken" ] = authToken;
m_authJob = lastfm::ws::post( query );
-
+
connect( m_authJob, SIGNAL( finished() ), SLOT( onAuthenticated() ) );
}
else
{
lastfm::ws::SessionKey = TomahawkSettings::instance()->lastFmSessionKey();
-
+
m_scrobbler = new lastfm::Audioscrobbler( "thk" );
m_scrobbler->moveToThread( thread() );
}
diff --git a/src/infosystem/infoplugins/lastfmplugin.h b/src/libtomahawk/infosystem/infoplugins/lastfmplugin.h
similarity index 89%
rename from src/infosystem/infoplugins/lastfmplugin.h
rename to src/libtomahawk/infosystem/infoplugins/lastfmplugin.h
index 589d40db1..1b97b0e0c 100644
--- a/src/infosystem/infoplugins/lastfmplugin.h
+++ b/src/libtomahawk/infosystem/infoplugins/lastfmplugin.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -18,7 +18,7 @@
#ifndef LASTFMPLUGIN_H
#define LASTFMPLUGIN_H
-#include "tomahawk/infosystem.h"
+#include "infosystem/infosystem.h"
#include "result.h"
#include
@@ -38,30 +38,38 @@ namespace InfoSystem
class LastFmPlugin : public InfoPlugin
{
Q_OBJECT
-
+
public:
LastFmPlugin( QObject *parent );
virtual ~LastFmPlugin();
-
+
void getInfo( const QString &caller, const InfoType type, const QVariant &data, InfoCustomData customData );
-
+
public slots:
void settingsChanged();
+
void onAuthenticated();
void coverArtReturned();
+ void artistImagesReturned();
+
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
-
+
private:
void fetchCoverArt( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData );
- void scrobble( const QString &caller, const InfoType type, const QVariant& data, InfoCustomData &customData );
+ void fetchArtistImages( const QString &caller, const InfoType type, const QVariant& data, Tomahawk::InfoSystem::InfoCustomData &customData );
+
void createScrobbler();
+ void scrobble( const QString &caller, const InfoType type, const QVariant& data, InfoCustomData &customData );
void nowPlaying( const QString &caller, const InfoType type, const QVariant& data, InfoCustomData &customData );
+
void dataError( const QString &caller, const InfoType type, const QVariant& data, InfoCustomData &customData );
-
+
lastfm::MutableTrack m_track;
lastfm::Audioscrobbler* m_scrobbler;
QString m_pw;
-
+
+ QList< QUrl > m_badUrls;
+
QNetworkReply* m_authJob;
};
diff --git a/src/infosystem/infoplugins/musixmatchplugin.cpp b/src/libtomahawk/infosystem/infoplugins/musixmatchplugin.cpp
similarity index 98%
rename from src/infosystem/infoplugins/musixmatchplugin.cpp
rename to src/libtomahawk/infosystem/infoplugins/musixmatchplugin.cpp
index 128085ca6..914a29e27 100644
--- a/src/infosystem/infoplugins/musixmatchplugin.cpp
+++ b/src/libtomahawk/infosystem/infoplugins/musixmatchplugin.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -16,10 +16,10 @@
* along with Tomahawk. If not, see .
*/
-#include "tomahawk/infosystem.h"
-#include "tomahawk/tomahawkapp.h"
#include "musixmatchplugin.h"
+#include "utils/tomahawkutils.h"
+
#include
#include
@@ -65,7 +65,7 @@ void MusixMatchPlugin::getInfo(const QString &caller, const InfoType type, const
reply->setProperty("customData", QVariant::fromValue(customData));
reply->setProperty("origData", data);
reply->setProperty("caller", caller);
-
+
connect(reply, SIGNAL(finished()), SLOT(trackSearchSlot()));
}
diff --git a/src/infosystem/infoplugins/musixmatchplugin.h b/src/libtomahawk/infosystem/infoplugins/musixmatchplugin.h
similarity index 96%
rename from src/infosystem/infoplugins/musixmatchplugin.h
rename to src/libtomahawk/infosystem/infoplugins/musixmatchplugin.h
index 255ebd53d..3fcb1ded7 100644
--- a/src/infosystem/infoplugins/musixmatchplugin.h
+++ b/src/libtomahawk/infosystem/infoplugins/musixmatchplugin.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -18,7 +18,8 @@
#ifndef MUSIXMATCHPLUGIN_H
#define MUSIXMATCHPLUGIN_H
-#include "tomahawk/infosystem.h"
+
+#include "infosystem/infosystem.h"
class QNetworkReply;
@@ -31,16 +32,16 @@ namespace InfoSystem
class MusixMatchPlugin : public InfoPlugin
{
Q_OBJECT
-
+
public:
MusixMatchPlugin(QObject *parent);
virtual ~MusixMatchPlugin();
-
+
void getInfo(const QString &caller, const InfoType type, const QVariant &data, InfoCustomData customData);
-
+
private:
bool isValidTrackData( const QString &caller, const QVariant& data, InfoCustomData &customData );
-
+
public slots:
void trackSearchSlot();
void trackLyricsSlot();
diff --git a/src/infosystem/infosystem.cpp b/src/libtomahawk/infosystem/infosystem.cpp
similarity index 92%
rename from src/infosystem/infosystem.cpp
rename to src/libtomahawk/infosystem/infosystem.cpp
index 7fd6158c6..6c8357ed6 100644
--- a/src/infosystem/infosystem.cpp
+++ b/src/libtomahawk/infosystem/infosystem.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -18,8 +18,8 @@
#include
-#include "tomahawk/infosystem.h"
-#include "tomahawkutils.h"
+#include "infosystem.h"
+#include "utils/tomahawkutils.h"
#include "infosystemcache.h"
#include "infoplugins/echonestplugin.h"
#include "infoplugins/musixmatchplugin.h"
@@ -27,7 +27,7 @@
namespace Tomahawk
{
-
+
namespace InfoSystem
{
@@ -40,9 +40,9 @@ InfoPlugin::InfoPlugin(QObject *parent)
{
QObject::connect(
this,
- SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCacheCriteria, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
+ SIGNAL( getCachedInfo( Tomahawk::InfoSystem::InfoCacheCriteria, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) ),
system->getCache(),
- SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCacheCriteria, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
+ SLOT( getCachedInfoSlot( Tomahawk::InfoSystem::InfoCacheCriteria, qint64, QString, Tomahawk::InfoSystem::InfoType, QVariant, Tomahawk::InfoSystem::InfoCustomData ) )
);
QObject::connect(
system->getCache(),
@@ -52,35 +52,45 @@ InfoPlugin::InfoPlugin(QObject *parent)
);
QObject::connect(
this,
- SIGNAL( updateCache( Tomahawk::InfoSystem::InfoCacheCriteria, Tomahawk::InfoSystem::InfoType, QVariant ) ),
+ SIGNAL( updateCache( Tomahawk::InfoSystem::InfoCacheCriteria, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) ),
system->getCache(),
- SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria, Tomahawk::InfoSystem::InfoType, QVariant ) )
+ SLOT( updateCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria, qint64, Tomahawk::InfoSystem::InfoType, QVariant ) )
);
}
}
+InfoSystem* InfoSystem::s_instance = 0;
+
+InfoSystem*
+InfoSystem::instance()
+{
+ return s_instance;
+}
+
InfoSystem::InfoSystem(QObject *parent)
: QObject(parent)
{
+ s_instance = this;
+
qDebug() << Q_FUNC_INFO;
qRegisterMetaType< QMap< QString, QMap< QString, QString > > >( "Tomahawk::InfoSystem::InfoGenericMap" );
qRegisterMetaType< QHash< QString, QVariant > >( "Tomahawk::InfoSystem::InfoCustomData" );
qRegisterMetaType< QHash< QString, QString > >( "Tomahawk::InfoSystem::InfoCacheCriteria" );
qRegisterMetaType< Tomahawk::InfoSystem::InfoType >( "Tomahawk::InfoSystem::InfoType" );
-
+
m_infoSystemCacheThreadController = new QThread( this );
m_cache = new InfoSystemCache();
m_cache->moveToThread( m_infoSystemCacheThreadController );
m_infoSystemCacheThreadController->start( QThread::IdlePriority );
-
+
InfoPluginPtr enptr( new EchoNestPlugin( this ) );
m_plugins.append( enptr );
InfoPluginPtr mmptr( new MusixMatchPlugin( this ) );
m_plugins.append( mmptr );
InfoPluginPtr lfmptr( new LastFmPlugin( this ) );
m_plugins.append( lfmptr );
-
+
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
{
connect(
@@ -107,19 +117,19 @@ InfoSystem::~InfoSystem()
if( m_infoSystemCacheThreadController )
{
m_infoSystemCacheThreadController->quit();
-
+
while( !m_infoSystemCacheThreadController->isFinished() )
{
QCoreApplication::processEvents( QEventLoop::AllEvents, 200 );
TomahawkUtils::Sleep::msleep( 100 );
}
-
+
if( m_cache )
{
delete m_cache;
m_cache = 0;
}
-
+
delete m_infoSystemCacheThreadController;
m_infoSystemCacheThreadController = 0;
}
@@ -152,7 +162,7 @@ void InfoSystem::getInfo(const QString &caller, const InfoType type, const QVari
emit finished(caller);
return;
}
-
+
InfoPluginPtr ptr = providers.first();
if (!ptr)
{
@@ -160,7 +170,7 @@ void InfoSystem::getInfo(const QString &caller, const InfoType type, const QVari
emit finished(caller);
return;
}
-
+
m_dataTracker[caller][type] = m_dataTracker[caller][type] + 1;
qDebug() << "current count in dataTracker for type" << type << "is" << m_dataTracker[caller][type];
ptr.data()->getInfo(caller, type, data, customData);
@@ -182,7 +192,7 @@ void InfoSystem::infoSlot(QString target, InfoType type, QVariant input, QVarian
return;
}
emit info(target, type, input, output, customData);
-
+
m_dataTracker[target][type] = m_dataTracker[target][type] - 1;
qDebug() << "current count in dataTracker is " << m_dataTracker[target][type];
Q_FOREACH(InfoType testtype, m_dataTracker[target].keys())
diff --git a/include/tomahawk/infosystem.h b/src/libtomahawk/infosystem/infosystem.h
similarity index 90%
rename from include/tomahawk/infosystem.h
rename to src/libtomahawk/infosystem/infosystem.h
index 1409dabf9..75e674f49 100644
--- a/include/tomahawk/infosystem.h
+++ b/src/libtomahawk/infosystem/infosystem.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -29,12 +29,14 @@
#include
#include
+#include "dllmacro.h"
+
namespace Tomahawk {
namespace InfoSystem {
class InfoSystemCache;
-
+
enum InfoType {
InfoTrackID = 0,
InfoTrackArtist,
@@ -58,7 +60,7 @@ enum InfoType {
InfoTrackDanceability,
InfoTrackTempo,
InfoTrackLoudness,
-
+
InfoArtistID,
InfoArtistName,
InfoArtistBiography,
@@ -74,7 +76,7 @@ enum InfoType {
InfoArtistTerms,
InfoArtistLinks,
InfoArtistVideos,
-
+
InfoAlbumID,
InfoAlbumName,
InfoAlbumArtist,
@@ -85,10 +87,10 @@ enum InfoType {
InfoMiscTopHotttness,
InfoMiscTopTerms,
-
+
InfoMiscSubmitNowPlaying,
InfoMiscSubmitScrobble,
-
+
InfoNoInfo
};
@@ -97,10 +99,10 @@ typedef QMap< QString, QMap< QString, QString > > InfoGenericMap;
typedef QHash< QString, QVariant > InfoCustomData;
typedef QHash< QString, QString > InfoCacheCriteria;
-class InfoPlugin : public QObject
+class DLLEXPORT InfoPlugin : public QObject
{
Q_OBJECT
-
+
public:
InfoPlugin( QObject *parent );
@@ -108,62 +110,70 @@ public:
{
qDebug() << Q_FUNC_INFO;
}
-
+
virtual void getInfo( const QString &caller, const InfoType type, const QVariant &data, InfoCustomData customData ) = 0;
-
+
signals:
- void getCachedInfo( Tomahawk::InfoSystem::InfoCacheCriteria criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
- void updateCache( Tomahawk::InfoSystem::InfoCacheCriteria criteria, Tomahawk::InfoSystem::InfoType type, QVariant output );
+ void getCachedInfo( Tomahawk::InfoSystem::InfoCacheCriteria criteria, qint64 newMaxAge, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
+ void updateCache( Tomahawk::InfoSystem::InfoCacheCriteria criteria, qint64, Tomahawk::InfoSystem::InfoType type, QVariant output );
void info( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void finished( QString, Tomahawk::InfoSystem::InfoType );
-
+
public slots:
//FIXME: Make pure virtual when everything supports it
virtual void notInCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData )
{
+ Q_UNUSED( criteria );
+ Q_UNUSED( caller );
+ Q_UNUSED( type );
+ Q_UNUSED( input );
+ Q_UNUSED( customData );
}
-
+
protected:
InfoType m_type;
};
typedef QWeakPointer< InfoPlugin > InfoPluginPtr;
-class InfoSystem : public QObject
+class DLLEXPORT InfoSystem : public QObject
{
Q_OBJECT
-
+
public:
-
+ static InfoSystem* instance();
+
InfoSystem( QObject *parent );
~InfoSystem();
-
+
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &types );
-
+
void getInfo( const QString &caller, const InfoType type, const QVariant &data, InfoCustomData customData );
void getInfo( const QString &caller, const InfoMap &input, InfoCustomData customData );
-
+
InfoSystemCache* getCache() { return m_cache; }
signals:
void info( QString caller, Tomahawk::InfoSystem::InfoType, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
void finished( QString target );
-
+
public slots:
void infoSlot( QString target, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
-
+
private:
QLinkedList< InfoPluginPtr > determineOrderedMatches( const InfoType type ) const;
-
+
QMap< InfoType, QLinkedList< InfoPluginPtr > > m_infoMap;
-
+
// For now, statically instantiate plugins; this is just somewhere to keep them
QLinkedList< InfoPluginPtr > m_plugins;
-
+
QHash< QString, QHash< InfoType, int > > m_dataTracker;
-
+
InfoSystemCache* m_cache;
QThread* m_infoSystemCacheThreadController;
+
+ static InfoSystem* s_instance;
};
}
@@ -177,14 +187,14 @@ inline uint qHash( Tomahawk::InfoSystem::InfoCacheCriteria hash )
md5.addData( key.toUtf8() );
foreach( QString value, hash.values() )
md5.addData( value.toUtf8() );
-
+
QString hexData = md5.result();
-
+
uint returnval = 0;
-
+
foreach( uint val, hexData.toUcs4() )
returnval += val;
-
+
return returnval;
}
diff --git a/src/libtomahawk/infosystem/infosystemcache.cpp b/src/libtomahawk/infosystem/infosystemcache.cpp
new file mode 100644
index 000000000..7b89539c1
--- /dev/null
+++ b/src/libtomahawk/infosystem/infosystemcache.cpp
@@ -0,0 +1,216 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#include
+#include
+#include
+#include
+
+#include "infosystemcache.h"
+
+
+namespace Tomahawk
+{
+
+namespace InfoSystem
+{
+
+
+InfoSystemCache::InfoSystemCache( QObject* parent )
+ : QObject(parent)
+ , m_cacheRemainingToLoad( 0 )
+{
+ qDebug() << Q_FUNC_INFO;
+ QString cacheBaseDir = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
+ for( int i = 0; i <= InfoNoInfo; i++ )
+ {
+ InfoType type = (InfoType)(i);
+ QString cacheDir = cacheBaseDir + "/InfoSystemCache/" + QString::number( i );
+ QString cacheFile = cacheDir + '/' + QString::number( i );
+ QDir dir( cacheDir );
+ if( dir.exists() && QFile::exists( cacheFile ) )
+ {
+ m_cacheRemainingToLoad++;
+ QMetaObject::invokeMethod( this, "loadCache", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( QString, cacheFile ) );
+ }
+ }
+}
+
+
+InfoSystemCache::~InfoSystemCache()
+{
+ qDebug() << Q_FUNC_INFO;
+ qDebug() << "Saving infosystemcache to disk";
+ QString cacheBaseDir = QDesktopServices::storageLocation( QDesktopServices::CacheLocation );
+ for ( int i = 0; i <= InfoNoInfo; i++ )
+ {
+ InfoType type = (InfoType)(i);
+ if ( m_dirtySet.contains( type ) && m_dataCache.contains( type ) )
+ {
+ QString cacheDir = cacheBaseDir + "/InfoSystemCache/" + QString::number( i );
+ saveCache( type, cacheDir );
+ }
+ }
+}
+
+
+void
+InfoSystemCache::getCachedInfoSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, qint64 newMaxAge, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData )
+{
+ qDebug() << Q_FUNC_INFO;
+ if ( !m_dataCache.contains( type ) || !m_dataCache[type].contains( criteria ) )
+ {
+ emit notInCache( criteria, caller, type, input, customData );
+ return;
+ }
+
+ if ( m_cacheRemainingToLoad > 0 )
+ {
+ qDebug() << "Cache not fully loaded, punting request for a bit";
+ QMetaObject::invokeMethod( this, "getCachedInfoSlot", Qt::QueuedConnection, Q_ARG( Tomahawk::InfoSystem::InfoCacheCriteria, criteria ), Q_ARG( qint64, newMaxAge ), Q_ARG( QString, caller ), Q_ARG( Tomahawk::InfoSystem::InfoType, type ), Q_ARG( Tomahawk::InfoSystem::InfoCustomData, customData ) );
+ return;
+ }
+
+ QHash< InfoCacheCriteria, QDateTime > typemaxtimecache = m_maxTimeCache[type];
+
+ if ( typemaxtimecache[criteria].toMSecsSinceEpoch() < QDateTime::currentMSecsSinceEpoch() )
+ {
+ QHash< InfoCacheCriteria, QVariant > typedatacache = m_dataCache[type];
+ QHash< InfoCacheCriteria, QDateTime > typeinserttimecache = m_insertTimeCache[type];
+ typemaxtimecache.remove( criteria );
+ m_maxTimeCache[type] = typemaxtimecache;
+ typedatacache.remove( criteria );
+ m_dataCache[type] = typedatacache;
+ typeinserttimecache.remove( criteria );
+ m_insertTimeCache[type] = typeinserttimecache;
+ m_dirtySet.insert( type );
+ emit notInCache( criteria, caller, type, input, customData );
+ return;
+ }
+
+ if ( newMaxAge > 0 )
+ {
+ QHash< InfoCacheCriteria, QDateTime > typemaxtimecache = m_maxTimeCache[type];
+ typemaxtimecache[criteria] = QDateTime::fromMSecsSinceEpoch( QDateTime::currentMSecsSinceEpoch() + newMaxAge );
+ m_maxTimeCache[type] = typemaxtimecache;
+ m_dirtySet.insert( type );
+ }
+
+ emit info( caller, type, input, m_dataCache[type][criteria], customData );
+}
+
+
+void
+InfoSystemCache::updateCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output )
+{
+ qDebug() << Q_FUNC_INFO;
+ QHash< InfoCacheCriteria, QVariant > typedatacache = m_dataCache[type];
+ QHash< InfoCacheCriteria, QDateTime > typeinserttimecache = m_insertTimeCache[type];
+ QHash< InfoCacheCriteria, QDateTime > typemaxtimecache = m_maxTimeCache[type];
+ typedatacache[criteria] = output;
+ typeinserttimecache[criteria] = QDateTime::currentDateTimeUtc();
+ typemaxtimecache[criteria] = QDateTime::fromMSecsSinceEpoch( QDateTime::currentMSecsSinceEpoch() + maxAge );
+ m_dataCache[type] = typedatacache;
+ m_insertTimeCache[type] = typeinserttimecache;
+ m_maxTimeCache[type] = typemaxtimecache;
+ m_dirtySet.insert( type );
+}
+
+
+void
+InfoSystemCache::loadCache( Tomahawk::InfoSystem::InfoType type, const QString &cacheFile )
+{
+ qDebug() << Q_FUNC_INFO;
+ QSettings cachedSettings( cacheFile, QSettings::IniFormat );
+
+ foreach ( QString group, cachedSettings.childGroups() )
+ {
+ cachedSettings.beginGroup( group );
+ if ( cachedSettings.value( "maxtime" ).toDateTime().toMSecsSinceEpoch() < QDateTime::currentMSecsSinceEpoch() )
+ continue;
+ QHash< InfoCacheCriteria, QVariant > dataHash = m_dataCache[type];
+ QHash< InfoCacheCriteria, QDateTime > insertDateHash = m_insertTimeCache[type];
+ QHash< InfoCacheCriteria, QDateTime > maxDateHash = m_maxTimeCache[type];
+ InfoCacheCriteria criteria;
+ int numCriteria = cachedSettings.beginReadArray( "criteria" );
+ for ( int i = 0; i < numCriteria; i++ )
+ {
+ cachedSettings.setArrayIndex( i );
+ QStringList criteriaValues = cachedSettings.value( QString::number( i ) ).toStringList();
+ for ( int j = 0; j < criteriaValues.length(); j += 2 )
+ criteria[criteriaValues.at( j )] = criteriaValues.at( j + 1 );
+ }
+ cachedSettings.endArray();
+ dataHash[criteria] = cachedSettings.value( "data" );
+ insertDateHash[criteria] = cachedSettings.value( "inserttime" ).toDateTime();
+ maxDateHash[criteria] = cachedSettings.value( "maxtime" ).toDateTime();
+ cachedSettings.endGroup();
+ m_dataCache[type] = dataHash;
+ m_insertTimeCache[type] = insertDateHash;
+ m_maxTimeCache[type] = maxDateHash;
+ }
+ m_cacheRemainingToLoad--;
+}
+
+
+void
+InfoSystemCache::saveCache( Tomahawk::InfoSystem::InfoType type, const QString &cacheDir )
+{
+ qDebug() << Q_FUNC_INFO;
+ QDir dir( cacheDir );
+ if( !dir.exists( cacheDir ) )
+ {
+ qDebug() << "Creating cache directory " << cacheDir;
+ if( !dir.mkpath( cacheDir ) )
+ {
+ qDebug() << "Failed to create cache dir! Bailing...";
+ return;
+ }
+ }
+
+ QSettings cachedSettings( QString( cacheDir + '/' + QString::number( (int)type ) ), QSettings::IniFormat );
+
+ int criteriaNumber = 0;
+
+ foreach( InfoCacheCriteria criteria, m_dataCache[type].keys() )
+ {
+ cachedSettings.beginGroup( "group_" + QString::number( criteriaNumber ) );
+ cachedSettings.beginWriteArray( "criteria" );
+ QStringList keys = criteria.keys();
+ for( int i = 0; i < criteria.size(); i++ )
+ {
+ cachedSettings.setArrayIndex( i );
+ QStringList critVal;
+ critVal << keys.at( i ) << criteria[keys.at( i )];
+ cachedSettings.setValue( QString::number( i ), critVal );
+ }
+ cachedSettings.endArray();
+ cachedSettings.setValue( "data", m_dataCache[type][criteria] );
+ cachedSettings.setValue( "inserttime", m_insertTimeCache[type][criteria] );
+ cachedSettings.setValue( "maxtime", m_maxTimeCache[type][criteria] );
+ cachedSettings.endGroup();
+ ++criteriaNumber;
+ }
+
+ m_dirtySet.remove( type );
+}
+
+
+} //namespace InfoSystem
+
+} //namespace Tomahawk
diff --git a/src/infosystem/infosystemcache.h b/src/libtomahawk/infosystem/infosystemcache.h
similarity index 72%
rename from src/infosystem/infosystemcache.h
rename to src/libtomahawk/infosystem/infosystemcache.h
index b74cf8a40..bf712c8d0 100644
--- a/src/infosystem/infosystemcache.h
+++ b/src/libtomahawk/infosystem/infosystemcache.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -23,11 +23,11 @@
#include
#include
-#include "tomahawk/infosystem.h"
+#include "infosystem.h"
namespace Tomahawk
{
-
+
namespace InfoSystem
{
@@ -37,7 +37,7 @@ Q_OBJECT
public:
InfoSystemCache( QObject *parent = 0 );
-
+
virtual ~InfoSystemCache();
signals:
@@ -45,20 +45,23 @@ signals:
void info( QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, QVariant output, Tomahawk::InfoSystem::InfoCustomData customData );
public slots:
- void getCachedInfoSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
- void updateCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, Tomahawk::InfoSystem::InfoType type, QVariant output );
-
+ void getCachedInfoSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, qint64 newMaxAge, QString caller, Tomahawk::InfoSystem::InfoType type, QVariant input, Tomahawk::InfoSystem::InfoCustomData customData );
+ void updateCacheSlot( Tomahawk::InfoSystem::InfoCacheCriteria criteria, qint64 maxAge, Tomahawk::InfoSystem::InfoType type, QVariant output );
+
+private slots:
+ void loadCache( Tomahawk::InfoSystem::InfoType type, const QString &cacheFile );
+ void saveCache( Tomahawk::InfoSystem::InfoType type, const QString &cacheDir );
+
private:
- void loadCache( InfoType type, const QString &cache );
- void saveCache( InfoType type, const QString &cache );
-
QHash< InfoType, QHash< InfoCacheCriteria, QVariant > > m_dataCache;
- QHash< InfoType, QHash< InfoCacheCriteria, QDateTime > > m_timeCache;
+ QHash< InfoType, QHash< InfoCacheCriteria, QDateTime > > m_insertTimeCache;
+ QHash< InfoType, QHash< InfoCacheCriteria, QDateTime > > m_maxTimeCache;
QSet< InfoType > m_dirtySet;
+ int m_cacheRemainingToLoad;
};
} //namespace InfoSystem
} //namespace Tomahawk
-#endif //TOMAHAWK_INFOSYSTEMCACHE_H
\ No newline at end of file
+#endif //TOMAHAWK_INFOSYSTEMCACHE_H
diff --git a/src/libtomahawk/kdsingleapplicationguard/kdsingleapplicationguard.cpp b/src/libtomahawk/kdsingleapplicationguard/kdsingleapplicationguard.cpp
index 63893dbde..6ccfe4e39 100644
--- a/src/libtomahawk/kdsingleapplicationguard/kdsingleapplicationguard.cpp
+++ b/src/libtomahawk/kdsingleapplicationguard/kdsingleapplicationguard.cpp
@@ -8,11 +8,11 @@
#define KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE 1024
#endif
-
+
KDSingleApplicationGuard::Instance::Instance( const QStringList& args, qint64 p )
- : arguments( args ),
- pid( p )
+: arguments( args ),
+pid( p )
{
}
@@ -61,31 +61,31 @@ void KDSingleApplicationGuard::timerEvent( QTimerEvent* )
using namespace kdtools;
/*!
- \class KDSingleApplicationGuard KDSingleApplicationGuard
- \brief A guard to protect an application from having several instances.
-
- KDSingleApplicationGuard can be used to make sure only one instance of an
- application is running at the same time.
-
- \note As KDSingleApplicationGuard uses QSharedMemory Qt 4.4 or later is required
+ * \class KDSingleApplicationGuard KDSingleApplicationGuard
+ * \brief A guard to protect an application from having several instances.
+ *
+ * KDSingleApplicationGuard can be used to make sure only one instance of an
+ * application is running at the same time.
+ *
+ * \note As KDSingleApplicationGuard uses QSharedMemory Qt 4.4 or later is required
*/
/*!
- \fn void KDSingleApplicationGuard::instanceStarted()
- This signal is emitted by the primary instance when ever one other
- instance was started.
+ * \fn void KDSingleApplicationGuard::instanceStarted()
+ * This signal is emitted by the primary instance when ever one other
+ * instance was started.
*/
/*!
- \fn void KDSingleApplicationGuard::instanceExited()
- This signal is emitted by the primary instance when ever one other
- instance was exited.
+ * \fn void KDSingleApplicationGuard::instanceExited()
+ * This signal is emitted by the primary instance when ever one other
+ * instance was exited.
*/
-
+
/*!
- \fn void KDSingleApplicationGuard::becamePrimaryInstance()
- This signal is emitted, when the current running application gets the new
- primary application. The old primary application has quit.
+ * \fn void KDSingleApplicationGuard::becamePrimaryInstance()
+ * This signal is emitted, when the current running application gets the new
+ * primary application. The old primary application has quit.
*/
enum Command
@@ -105,8 +105,8 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( Commands )
struct ProcessInfo
{
explicit ProcessInfo( Command c = FreeInstance, const QStringList& arguments = QStringList(), qint64 p = -1 )
- : command( c ),
- pid( p )
+ : command( c ),
+ pid( p )
{
std::fill_n( commandline, KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE, '\0' );
@@ -149,7 +149,7 @@ struct ProcessInfo
bool operator==( const ProcessInfo& lhs, const ProcessInfo& rhs )
{
return lhs.command == rhs.command &&
- ::memcmp( lhs.commandline, rhs.commandline, KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE ) == 0;
+ ::memcmp( lhs.commandline, rhs.commandline, KDSINGLEAPPLICATIONGUARD_MAX_COMMAND_LINE ) == 0;
}
bool operator!=( const ProcessInfo& lhs, const ProcessInfo& rhs )
@@ -158,21 +158,21 @@ bool operator!=( const ProcessInfo& lhs, const ProcessInfo& rhs )
}
/*!
- This struct contains information about the managed process system.
- \internal
+ * This struct contains information about the managed process system.
+ * \internal
*/
struct InstanceRegister
{
InstanceRegister( KDSingleApplicationGuard::Policy policy = KDSingleApplicationGuard::NoPolicy )
- : policy( policy )
+ : policy( policy )
{
std::fill_n( info, KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES, ProcessInfo() );
::memcpy( magicCookie, "kdsingleapp", 12 );
}
/*!
- Returns wheter this register was properly initialized by the first instance.
- */
+ * Returns wheter this register was properly initialized by the first instance.
+ */
bool isValid() const
{
return ::strcmp( magicCookie, "kdsingleapp" ) == 0;
@@ -192,18 +192,18 @@ bool operator==( const InstanceRegister& lhs, const InstanceRegister& rhs )
if( lhs.info[ i ] != rhs.info[ i ] )
return false;
- return true;
+ return true;
}
/*!
- \internal
+ * \internal
*/
class KDSingleApplicationGuard::Private
{
public:
Private( KDSingleApplicationGuard* qq )
- : q( qq ),
- id( -1 )
+ : q( qq ),
+ id( -1 )
{
if( primaryInstance == 0 )
primaryInstance = q;
@@ -258,28 +258,28 @@ void SIGINT_handler( int sig )
#endif
/*!
- Creates a new KDSingleApplicationGuard guarding \a parent from mulitply instances.
- If \a policy is AutoKillOtherInstances (the default), all instances, which try to start,
- are killed automatically and instanceStarted() is emitted.
- If \a policy is NoPolicy, the other instance will run and instanceStarted() is emitted.
+ * Creates a new KDSingleApplicationGuard guarding \a parent from mulitply instances.
+ * If \a policy is AutoKillOtherInstances (the default), all instances, which try to start,
+ * are killed automatically and instanceStarted() is emitted.
+ * If \a policy is NoPolicy, the other instance will run and instanceStarted() is emitted.
*/
KDSingleApplicationGuard::KDSingleApplicationGuard( QCoreApplication* parent, Policy policy )
- : QObject( parent ),
- d( new Private( this ) )
+: QObject( parent ),
+d( new Private( this ) )
{
const QString name = parent->applicationName();
Q_ASSERT_X( !name.isEmpty(), "KDSingleApplicationGuard::KDSingleApplicationGuard", "applicationName must not be emty" );
d->mem.setKey( name );
-
+
// if another instance crashed, the shared memory segment is still there on Unix
// the following lines trigger deletion in that case
-#ifndef Q_WS_WIN
+ #ifndef Q_WS_WIN
d->mem.attach();
d->mem.detach();
-#endif
-
+ #endif
+
d->policy = policy;
-
+
const bool created = d->mem.create( sizeof( InstanceRegister ) );
if( !created )
{
@@ -288,7 +288,7 @@ KDSingleApplicationGuard::KDSingleApplicationGuard( QCoreApplication* parent, Po
qWarning( "KDSingleApplicationGuard: Could neither create nor attach to shared memory segment." );
return;
}
-
+
// lets wait till the other instance initialized the register
bool initialized = false;
while( !initialized )
@@ -298,52 +298,57 @@ KDSingleApplicationGuard::KDSingleApplicationGuard( QCoreApplication* parent, Po
}
}
-
- KDLockedSharedMemoryPointer< InstanceRegister > instances( &d->mem );
-
- if( !created )
+ bool killMyself = false;
{
- // we're _not_ the first instance
- // but the
- bool killOurSelf = false;
-
- // find a new slot...
- d->id = std::find( instances->info, instances->info + KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES, ProcessInfo() ) - instances->info;
- ProcessInfo& info = instances->info[ d->id ];
- info = ProcessInfo( NewInstance, parent->arguments(), QCoreApplication::applicationPid() );
- killOurSelf = instances->policy == AutoKillOtherInstances;
- d->policy = instances->policy;
+ KDLockedSharedMemoryPointer< InstanceRegister > instances( &d->mem );
- // but the signal that we tried to start was sent to the primary application
- if( killOurSelf )
+ if( !created )
{
- info.command |= ExitedInstance;
- exit( 1 );
+ // we're _not_ the first instance
+ // but the
+ bool killOurSelf = false;
+
+ // find a new slot...
+ d->id = std::find( instances->info, instances->info + KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES, ProcessInfo() ) - instances->info;
+ ProcessInfo& info = instances->info[ d->id ];
+ info = ProcessInfo( NewInstance, parent->arguments(), QCoreApplication::applicationPid() );
+ killOurSelf = instances->policy == AutoKillOtherInstances;
+ d->policy = instances->policy;
+
+ // but the signal that we tried to start was sent to the primary application
+ if( killOurSelf )
+ {
+ info.command |= ExitedInstance;
+ killMyself = true;
+ }
+ }
+ else
+ {
+ // ok.... we are the first instance
+ InstanceRegister reg( policy ); // create a new list
+ d->id = 0; // our id = 0
+ // and we've no command
+ reg.info[ 0 ] = ProcessInfo( NoCommand, parent->arguments(), QCoreApplication::applicationPid() );
+ *instances = reg; // push this is the process list into shared memory
}
}
- else
- {
- // ok.... we are the first instance
- InstanceRegister reg( policy ); // create a new list
- d->id = 0; // our id = 0
- // and we've no command
- reg.info[ 0 ] = ProcessInfo( NoCommand, parent->arguments(), QCoreApplication::applicationPid() );
- *instances = reg; // push this is the process list into shared memory
- }
+ // call exit after we let the locker release our memory, as exit() is not guaranteed to clean up objects on the stack
+ if ( killMyself )
+ exit( 1 );
-#ifndef Q_WS_WIN
- ::signal( SIGINT, SIGINT_handler );
-#endif
+ #ifndef Q_WS_WIN
+ ::signal( SIGINT, SIGINT_handler );
+ #endif
- // now listen for commands
- startTimer( 250 );
+ // now listen for commands
+ startTimer( 250 );
}
/*!
- Destroys this SingleApplicationGuard.
- If this instance has been the primary instance and no other instance is existing anymore,
- the application is shut down completely. Otherwise the destructor selects another instance to
- be the primary instances.
+ * Destroys this SingleApplicationGuard.
+ * If this instance has been the primary instance and no other instance is existing anymore,
+ * the application is shut down completely. Otherwise the destructor selects another instance to
+ * be the primary instances.
*/
KDSingleApplicationGuard::~KDSingleApplicationGuard()
{
@@ -352,16 +357,16 @@ KDSingleApplicationGuard::~KDSingleApplicationGuard()
d->shutdownInstance();
}
-
-/*!
- \property KDSingleApplicationGuard::primaryInstance
- Determines wheter this instance is the primary instance.
- The primary instance is the first instance which was started or an instance which
- got selected by KDSingleApplicationGuard's destructor, when the primary instance was
- shut down.
- Get this property's value using %isPrimaryInstance(), and monitor changes to it
- using becamePrimaryInstance().
+/*!
+ * \property KDSingleApplicationGuard::primaryInstance
+ * Determines wheter this instance is the primary instance.
+ * The primary instance is the first instance which was started or an instance which
+ * got selected by KDSingleApplicationGuard's destructor, when the primary instance was
+ * shut down.
+ *
+ * Get this property's value using %isPrimaryInstance(), and monitor changes to it
+ * using becamePrimaryInstance().
*/
bool KDSingleApplicationGuard::isPrimaryInstance() const
{
@@ -369,12 +374,12 @@ bool KDSingleApplicationGuard::isPrimaryInstance() const
}
/*!
- \property KDSingleApplicationGuard::Policy
- Specifies the policy KDSingleApplicationGuard is using when new instances are started.
- This can only be set in the primary instance.
-
- Get this property's value using %policy(), set it using %setPolicy(), and monitor changes
- to it using policyChanged().
+ * \property KDSingleApplicationGuard::Policy
+ * Specifies the policy KDSingleApplicationGuard is using when new instances are started.
+ * This can only be set in the primary instance.
+ *
+ * Get this property's value using %policy(), set it using %setPolicy(), and monitor changes
+ * to it using policyChanged().
*/
KDSingleApplicationGuard::Policy KDSingleApplicationGuard::policy() const
{
@@ -394,7 +399,7 @@ void KDSingleApplicationGuard::setPolicy( Policy policy )
}
/*!
- Returns a list of all currently running instances.
+ * Returns a list of all currently running instances.
*/
QList< KDSingleApplicationGuard::Instance > KDSingleApplicationGuard::instances() const
{
@@ -409,10 +414,10 @@ QList< KDSingleApplicationGuard::Instance > KDSingleApplicationGuard::instances(
return result;
}
-/*!
- Shuts down all other instances. This can only be called from the
- the primary instance.
- Shut down is done gracefully via QCoreApplication::quit().
+/*!
+ * Shuts down all other instances. This can only be called from the
+ * the primary instance.
+ * Shut down is done gracefully via QCoreApplication::quit().
*/
void KDSingleApplicationGuard::shutdownOtherInstances()
{
@@ -426,9 +431,9 @@ void KDSingleApplicationGuard::shutdownOtherInstances()
}
/*!
- Kills all other instances. This can only be called from the
- the primary instance.
- Killing is done via exit(1)
+ * Kills all other instances. This can only be called from the
+ * the primary instance.
+ * Killing is done via exit(1)
*/
void KDSingleApplicationGuard::killOtherInstances()
{
@@ -442,7 +447,7 @@ void KDSingleApplicationGuard::killOtherInstances()
}
/*!
- \reimp
+ * \reimp
*/
void KDSingleApplicationGuard::timerEvent( QTimerEvent* event )
{
@@ -456,11 +461,11 @@ void KDSingleApplicationGuard::timerEvent( QTimerEvent* event )
{
KDLockedSharedMemoryPointer< InstanceRegister > instances( &d->mem );
-
+
for( int i = 1; i < KDSINGLEAPPLICATIONGUARD_NUMBER_OF_PROCESSES; ++i )
{
ProcessInfo& info = instances->info[ i ];
- if( info.command & NewInstance )
+ if( info.command & NewInstance )
{
startedInstances.push_back( Instance( info.arguments(), info.pid ) );
info.command &= ~NewInstance; // clear NewInstance flag
@@ -472,7 +477,7 @@ void KDSingleApplicationGuard::timerEvent( QTimerEvent* event )
}
}
}
-
+
// one signal for every new instance - _after_ the memory segment was unlocked again
for( QList< Instance >::const_iterator it = startedInstances.begin(); it != startedInstances.end(); ++it )
emit instanceStarted( *it );
@@ -495,7 +500,7 @@ void KDSingleApplicationGuard::timerEvent( QTimerEvent* event )
if( instances->info[ d->id ].command & BecomePrimaryCommand )
{
// we became primary!
- instances->info[ 0 ] = instances->info[ d->id ];
+ instances->info[ 0 ] = instances->info[ d->id ];
instances->info[ d->id ] = ProcessInfo(); // change our id to 0 and declare the old slot as free
d->id = 0;
emit becamePrimaryInstance();
@@ -510,7 +515,7 @@ void KDSingleApplicationGuard::timerEvent( QTimerEvent* event )
d->id = -1; // becauso our d'tor won't be called anymore
}
}
-
+
if( killOurSelf ) // kill our self takes precedence
exit( 1 );
else if( shutDownOurSelf )
@@ -590,14 +595,14 @@ KDAB_UNITTEST_SIMPLE( KDSingleApplicationGuard, "kdcoretools" ) {
spy3 = new QSignalSpy( guard3, SIGNAL( becamePrimaryInstance() ) );
assertFalse( guard3->isPrimaryInstance() );
}
-
+
wait( 1000 );
assertEqual( spy3->count(), 1 );
assertEqual( guard3->instances().count(), 1 );
assertTrue( guard3->isPrimaryInstance() );
assertEqual( guard3->instances().first().arguments, qApp->arguments() );
-
+
QSignalSpy spyStarted( guard3, SIGNAL( instanceStarted( KDSingleApplicationGuard::Instance ) ) );
QSignalSpy spyExited( guard3, SIGNAL( instanceExited( KDSingleApplicationGuard::Instance ) ) );
@@ -609,13 +614,13 @@ KDAB_UNITTEST_SIMPLE( KDSingleApplicationGuard, "kdcoretools" ) {
assertEqual( spyStarted.count(), 2 );
}
-
+
wait( 1000 );
assertEqual( spyExited.count(), 2 );
delete spy3;
delete guard3;
- }
+}
#endif // KDTOOLSCORE_UNITTESTS
diff --git a/src/libtomahawk/network/bufferiodevice.cpp b/src/libtomahawk/network/bufferiodevice.cpp
index 435a2b2cd..bceca0745 100644
--- a/src/libtomahawk/network/bufferiodevice.cpp
+++ b/src/libtomahawk/network/bufferiodevice.cpp
@@ -38,6 +38,7 @@ BufferIODevice::BufferIODevice( unsigned int size, QObject* parent )
bool
BufferIODevice::open( OpenMode mode )
{
+ Q_UNUSED( mode );
QMutexLocker lock( &m_mut );
qDebug() << Q_FUNC_INFO;
@@ -148,6 +149,8 @@ BufferIODevice::readData( char* data, qint64 maxSize )
qint64
BufferIODevice::writeData( const char* data, qint64 maxSize )
{
+ Q_UNUSED( data );
+ Q_UNUSED( maxSize );
// call addData instead
Q_ASSERT( false );
return 0;
diff --git a/src/libtomahawk/network/controlconnection.cpp b/src/libtomahawk/network/controlconnection.cpp
index 24cc6af6d..b1c7a0b50 100644
--- a/src/libtomahawk/network/controlconnection.cpp
+++ b/src/libtomahawk/network/controlconnection.cpp
@@ -118,6 +118,7 @@ ControlConnection::registerSource()
{
qDebug() << Q_FUNC_INFO << m_source->id();
Source* source = (Source*) sender();
+ Q_UNUSED( source )
Q_ASSERT( source == m_source.data() );
// .. but we'll use the shared pointer we've already made:
diff --git a/src/libtomahawk/network/remotecollection.cpp b/src/libtomahawk/network/remotecollection.cpp
index 8bfdfd3a2..e73966cac 100644
--- a/src/libtomahawk/network/remotecollection.cpp
+++ b/src/libtomahawk/network/remotecollection.cpp
@@ -31,6 +31,7 @@ RemoteCollection::RemoteCollection( source_ptr source, QObject* parent )
// the database will make us emit the appropriate signals (tracksAdded etc.)
void RemoteCollection::addTracks( const QList& newitems )
{
+ Q_UNUSED( newitems );
qDebug() << Q_FUNC_INFO;
Q_ASSERT( false );
}
@@ -38,6 +39,7 @@ void RemoteCollection::addTracks( const QList& newitems )
void RemoteCollection::removeTracks( const QDir& dir )
{
+ Q_UNUSED( dir );
qDebug() << Q_FUNC_INFO;
Q_ASSERT( false );
}
diff --git a/src/libtomahawk/network/servent.cpp b/src/libtomahawk/network/servent.cpp
index 083e67d92..a1ddff6a2 100644
--- a/src/libtomahawk/network/servent.cpp
+++ b/src/libtomahawk/network/servent.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include
#include "result.h"
@@ -41,7 +42,6 @@
#include "tomahawksettings.h"
#include "utils/tomahawkutils.h"
#include
-#include
using namespace Tomahawk;
@@ -62,7 +62,7 @@ Servent::Servent( QObject* parent )
, m_portfwd( 0 )
{
s_instance = this;
-
+
new ACLSystem( this );
setProxy( QNetworkProxy::NoProxy );
@@ -126,7 +126,7 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
// --lanhack means to advertise your LAN IP over jabber as if it were externallyVisible
qDebug() << "Address mode = " << (int)(TomahawkSettings::instance()->externalAddressMode());
qDebug() << "Static host/port preferred ? = " << ( TomahawkSettings::instance()->preferStaticHostPort() ? "true" : "false" );
-
+
if( TomahawkSettings::instance()->preferStaticHostPort() )
{
qDebug() << "Forcing static preferred host and port";
@@ -136,8 +136,12 @@ Servent::startListening( QHostAddress ha, bool upnp, int port )
emit ready();
return true;
}
-
- switch( TomahawkSettings::instance()->externalAddressMode() )
+
+ TomahawkSettings::ExternalAddressMode mode = TomahawkSettings::instance()->externalAddressMode();
+ if ( mode == TomahawkSettings::Upnp && !upnp )
+ mode = TomahawkSettings::Lan;
+
+ switch( mode )
{
case TomahawkSettings::Lan:
foreach( QHostAddress ha, QNetworkInterface::allAddresses() )
@@ -318,7 +322,7 @@ Servent::readyRead()
pport = m.value( "port" ).toInt();
nodeid = m.value( "nodeid" ).toString();
controlid = m.value( "controlid" ).toString();
-
+
qDebug() << "Incoming connection details: " << m;
if( !nodeid.isEmpty() ) // only control connections send nodeid
@@ -367,7 +371,7 @@ Servent::readyRead()
{
qDebug() << "Invalid or unhandled conntype";
}
-
+
// fallthru to cleanup:
closeconnection:
qDebug() << "Closing incoming connection, something was wrong.";
@@ -562,7 +566,7 @@ Connection*
Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString &key, const QHostAddress peer )
{
qDebug() << Q_FUNC_INFO;
-
+
bool noauth = qApp->arguments().contains( "--noauth" );
// magic key for stream connections:
@@ -629,9 +633,9 @@ Servent::claimOffer( ControlConnection* cc, const QString &nodeid, const QString
return NULL;
}
}
-
+
qDebug() << "ACL has allowed the connection";
-
+
if( conn->onceOnly() )
{
m_offers.remove( key );
@@ -672,7 +676,7 @@ Servent::checkACL( const Connection* conn, const QString &nodeid, bool showDialo
{
if( !showDialog )
return false;
-
+
qDebug() << "ACL for this node not found";
QMessageBox msgBox;
msgBox.setIcon( QMessageBox::Question );
@@ -682,7 +686,7 @@ Servent::checkACL( const Connection* conn, const QString &nodeid, bool showDialo
QPushButton *alwaysDenyButton = msgBox.addButton( tr( "Always Deny" ), QMessageBox::YesRole );
QPushButton *allowButton = msgBox.addButton( tr( "Allow" ), QMessageBox::NoRole );
QPushButton *alwaysAllowButton = msgBox.addButton( tr( "Always Allow" ), QMessageBox::ActionRole );
-
+
msgBox.setDefaultButton( denyButton );
msgBox.setEscapeButton( denyButton );
@@ -696,12 +700,21 @@ Servent::checkACL( const Connection* conn, const QString &nodeid, bool showDialo
return false;
}
else if( msgBox.clickedButton() == alwaysAllowButton )
+ {
aclSystem->authorizeUser( nodeid, ACLSystem::Allow );
+ return true;
+ }
+ else if( msgBox.clickedButton() == allowButton )
+ return true;
+
+ //How could we get here?
+ qDebug() << "Somehow no button matched";
+ return false;
}
#endif
return true;
-}
+}
QSharedPointer
Servent::remoteIODeviceFactory( const result_ptr& result )
@@ -832,7 +845,6 @@ Servent::registerIODeviceFactory( const QString &proto, boost::function
Servent::getIODeviceForUrl( const Tomahawk::result_ptr& result )
{
@@ -845,9 +857,9 @@ Servent::getIODeviceForUrl( const Tomahawk::result_ptr& result )
const QString proto = rx.cap( 1 );
//const QString urlpart = rx.cap( 2 );
+ qDebug() << "Getting IODevice for URL:" << proto << m_iofactories.contains( proto );
if ( !m_iofactories.contains( proto ) )
return sp;
-
return m_iofactories.value( proto )( result );
}
@@ -870,5 +882,5 @@ Servent::httpIODeviceFactory( const Tomahawk::result_ptr& result )
qDebug() << Q_FUNC_INFO << result->url();
QNetworkRequest req( result->url() );
QNetworkReply* reply = TomahawkUtils::nam()->get( req );
- return QSharedPointer( reply );
+ return QSharedPointer( reply, &QObject::deleteLater );
}
diff --git a/src/libtomahawk/network/streamconnection.cpp b/src/libtomahawk/network/streamconnection.cpp
index 224ab7d7f..e33ed6196 100644
--- a/src/libtomahawk/network/streamconnection.cpp
+++ b/src/libtomahawk/network/streamconnection.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -46,7 +46,7 @@ StreamConnection::StreamConnection( Servent* s, ControlConnection* cc, QString f
qDebug() << Q_FUNC_INFO;
BufferIODevice* bio = new BufferIODevice( result->size() );
- m_iodev = QSharedPointer( bio ); // device audio data gets written to
+ m_iodev = QSharedPointer( bio, &QObject::deleteLater ); // device audio data gets written to
m_iodev->open( QIODevice::ReadWrite );
Servent::instance()->registerStreamConnection( this );
@@ -108,7 +108,7 @@ StreamConnection::id() const
}
-Tomahawk::source_ptr
+Tomahawk::source_ptr
StreamConnection::source() const
{
return m_source;
diff --git a/src/libtomahawk/pipeline.cpp b/src/libtomahawk/pipeline.cpp
index b7d538a37..c3bab44d6 100644
--- a/src/libtomahawk/pipeline.cpp
+++ b/src/libtomahawk/pipeline.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -134,7 +134,7 @@ Pipeline::resolve( const query_ptr& q, bool prioritized )
{
if ( q.isNull() )
return;
-
+
QList< query_ptr > qlist;
qlist << q;
resolve( qlist, prioritized );
@@ -292,7 +292,7 @@ Pipeline::shunt( const query_ptr& q )
{
incQIDState( q );
// qDebug() << "Shunting in" << lasttimeout << "ms, q:" << q->toString();
- new FuncTimeout( lasttimeout, boost::bind( &Pipeline::shunt, this, q ) );
+ new FuncTimeout( lasttimeout, boost::bind( &Pipeline::shunt, this, q ), this );
}
}
else
@@ -311,8 +311,8 @@ Pipeline::shunt( const query_ptr& q )
bool
Pipeline::resolverSorter( const Resolver* left, const Resolver* right )
{
- if( left->weight() == right->weight() )
- return left->preference() > right->preference();
+ if( left->weight() == right->weight() ) // TODO dispatch in parallel
+ return left;
else
return left->weight() > right->weight();
}
diff --git a/src/libtomahawk/playlist.cpp b/src/libtomahawk/playlist.cpp
index 9d35c0fe6..4281f7265 100644
--- a/src/libtomahawk/playlist.cpp
+++ b/src/libtomahawk/playlist.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -57,28 +57,28 @@ PlaylistEntry::queryVariant() const
}
-void
+void
PlaylistEntry::setQuery( const Tomahawk::query_ptr& q )
{
m_query = q;
}
-const Tomahawk::query_ptr&
+const Tomahawk::query_ptr&
PlaylistEntry::query() const
{
return m_query;
}
-source_ptr
+source_ptr
PlaylistEntry::lastSource() const
{
return m_lastsource;
}
-void
+void
PlaylistEntry::setLastSource( source_ptr s )
{
m_lastsource = s;
@@ -99,6 +99,7 @@ Playlist::Playlist( const source_ptr& src,
const QString& title,
const QString& info,
const QString& creator,
+ uint createdOn,
bool shared,
int lastmod,
const QString& guid )
@@ -109,6 +110,7 @@ Playlist::Playlist( const source_ptr& src,
, m_title( title )
, m_info( info )
, m_creator( creator )
+ , m_createdOn( createdOn )
, m_lastmodified( lastmod )
, m_shared( shared )
{
@@ -129,6 +131,7 @@ Playlist::Playlist( const source_ptr& author,
, m_title( title )
, m_info ( info )
, m_creator( creator )
+ , m_createdOn( 0 ) // will be set by db command
, m_lastmodified( 0 )
, m_shared( shared )
{
@@ -141,7 +144,7 @@ void
Playlist::init()
{
m_locallyChanged = false;
- connect( Pipeline::instance(), SIGNAL( idle() ), SLOT( onResolvingFinished() ) );
+ connect( Pipeline::instance(), SIGNAL( idle() ), SLOT( onResolvingFinished() ) );
}
@@ -229,7 +232,7 @@ Playlist::reportDeleted( const Tomahawk::playlist_ptr& self )
qDebug() << Q_FUNC_INFO;
Q_ASSERT( self.data() == this );
m_source->collection()->deletePlaylist( self );
-
+
emit deleted( self );
}
@@ -310,24 +313,24 @@ Playlist::setRevision( const QString& rev,
);
return;
}
-
+
PlaylistRevision pr = setNewRevision( rev, neworderedguids, oldorderedguids, is_newest_rev, addedmap );
-
+
if( applied )
m_currentrevision = rev;
pr.applied = applied;
-
+
foreach( const plentry_ptr& entry, m_entries )
{
connect( entry->query().data(), SIGNAL( resultsAdded( QList ) ),
SLOT( onResultsFound( QList ) ), Qt::UniqueConnection );
-
+
}
emit revisionLoaded( pr );
}
-PlaylistRevision
+PlaylistRevision
Playlist::setNewRevision( const QString& rev,
const QList& neworderedguids,
const QList& oldorderedguids,
@@ -340,10 +343,10 @@ Playlist::setNewRevision( const QString& rev,
QMap entriesmap;
foreach( const plentry_ptr& p, m_entries )
entriesmap.insert( p->guid(), p );
-
-
+
+
QList entries;
-
+
foreach( const QString& id, neworderedguids )
{
//qDebug() << "id:" << id;
@@ -351,7 +354,7 @@ Playlist::setNewRevision( const QString& rev,
//qDebug() << "entriesmap:" << entriesmap.count() << entriesmap;
//qDebug() << "addedmap:" << addedmap.count() << addedmap;
//qDebug() << "m_entries" << m_entries;
-
+
if( entriesmap.contains( id ) )
{
entries.append( entriesmap.value( id ) );
@@ -367,13 +370,13 @@ Playlist::setNewRevision( const QString& rev,
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 removedguids = oldorderedguids.toSet().subtract( neworderedguids.toSet() );
//qDebug() << "Removedguids:" << removedguids << "oldorederedguids" << oldorderedguids << "newog" << neworderedguids;
@@ -399,10 +402,10 @@ Playlist::setNewRevision( const QString& rev,
}
}
}
-
+
pr.added = addedmap.values();
-
-
+
+
pr.newlist = entries;
return pr;
}
@@ -410,12 +413,12 @@ Playlist::setNewRevision( const QString& rev,
source_ptr
Playlist::author() const
-{
- return m_source;
+{
+ return m_source;
}
-void
+void
Playlist::resolve()
{
QList< query_ptr > qlist;
@@ -431,6 +434,7 @@ Playlist::resolve()
void
Playlist::onResultsFound( const QList& results )
{
+ Q_UNUSED( results );
m_locallyChanged = true;
}
@@ -461,7 +465,7 @@ void
Playlist::addEntries( const QList& queries, const QString& oldrev )
{
//qDebug() << Q_FUNC_INFO;
-
+
QList el = addEntriesInternal( queries );
QString newrev = uuid();
@@ -469,7 +473,7 @@ Playlist::addEntries( const QList& queries, const QString& oldrev )
}
-QList
+QList
Playlist::addEntriesInternal( const QList& queries )
{
QList el = entries();
@@ -477,16 +481,16 @@ Playlist::addEntriesInternal( const QList& queries )
{
plentry_ptr e( new PlaylistEntry() );
e->setGuid( uuid() );
-
+
if ( query->results().count() )
e->setDuration( query->results().at( 0 )->duration() );
else
e->setDuration( 0 );
-
+
e->setLastmodified( 0 );
e->setAnnotation( "" ); // FIXME
e->setQuery( query );
-
+
el << e;
}
return el;
@@ -499,14 +503,14 @@ Playlist::newEntries( const QList< plentry_ptr >& entries )
QSet currentguids;
foreach( const plentry_ptr& p, m_entries )
currentguids.insert( p->guid() ); // could be cached as member?
-
+
// calc list of newly added entries:
QList added;
foreach( const plentry_ptr& p, entries )
{
if( !currentguids.contains( p->guid() ) )
added << p;
- }
+ }
return added;
}
diff --git a/src/libtomahawk/playlist.h b/src/libtomahawk/playlist.h
index d0a4ee490..e905517b2 100644
--- a/src/libtomahawk/playlist.h
+++ b/src/libtomahawk/playlist.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -77,6 +77,7 @@ public:
source_ptr lastSource() const;
void setLastSource( source_ptr s );
+
private:
QString m_guid;
Tomahawk::query_ptr m_query;
@@ -107,6 +108,7 @@ Q_PROPERTY( QString currentrevision READ currentrevision WRITE setCurrentrevi
Q_PROPERTY( QString title READ title WRITE setTitle )
Q_PROPERTY( QString info READ info WRITE setInfo )
Q_PROPERTY( QString creator READ creator WRITE setCreator )
+Q_PROPERTY( unsigned int createdon READ createdOn WRITE setCreatedOn )
Q_PROPERTY( bool shared READ shared WRITE setShared )
friend class ::DatabaseCommand_LoadAllPlaylists;
@@ -139,6 +141,7 @@ public:
QString guid() const { return m_guid; }
bool shared() const { return m_shared; }
unsigned int lastmodified() const { return m_lastmodified; }
+ uint createdOn() const { return m_createdOn; }
const QList< plentry_ptr >& entries() { return m_entries; }
virtual void addEntry( const Tomahawk::query_ptr& query, const QString& oldrev );
@@ -155,6 +158,7 @@ public:
void setCreator( const QString& s ) { m_creator = s; }
void setGuid( const QString& s ) { m_guid = s; }
void setShared( bool b ) { m_shared = b; }
+ void setCreatedOn( uint createdOn ) { m_createdOn = createdOn; }
//
virtual QList tracks();
@@ -162,7 +166,7 @@ public:
virtual int unfilteredTrackCount() const { return m_entries.count(); }
virtual int trackCount() const { return m_entries.count(); }
- virtual Tomahawk::result_ptr siblingItem( int itemsAway ) { return result_ptr(); }
+ virtual Tomahawk::result_ptr siblingItem( int /*itemsAway*/ ) { return result_ptr(); }
virtual PlaylistInterface::RepeatMode repeatMode() const { return PlaylistInterface::NoRepeat; }
virtual bool shuffled() const { return false; }
@@ -170,7 +174,7 @@ public:
virtual void setRepeatMode( PlaylistInterface::RepeatMode ) {}
virtual void setShuffled( bool ) {}
- virtual void setFilter( const QString& pattern ) {}
+ virtual void setFilter( const QString& /*pattern*/ ) {}
signals:
/// emitted when the playlist revision changes (whenever the playlist changes)
@@ -184,7 +188,7 @@ signals:
/// was deleted, eh?
void deleted( const Tomahawk::playlist_ptr& pl );
-
+
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
void shuffleModeChanged( bool enabled );
@@ -214,6 +218,7 @@ protected:
const QString& title,
const QString& info,
const QString& creator,
+ uint createdOn,
bool shared,
int lastmod,
const QString& guid = "" ); // populate db
@@ -247,6 +252,7 @@ private:
QString m_currentrevision;
QString m_guid, m_title, m_info, m_creator;
unsigned int m_lastmodified;
+ unsigned int m_createdOn;
bool m_shared;
QList< plentry_ptr > m_entries;
diff --git a/src/libtomahawk/playlist/albummodel.cpp b/src/libtomahawk/playlist/albummodel.cpp
index a60610e36..7e28d655d 100644
--- a/src/libtomahawk/playlist/albummodel.cpp
+++ b/src/libtomahawk/playlist/albummodel.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -81,6 +81,7 @@ AlbumModel::rowCount( const QModelIndex& parent ) const
int
AlbumModel::columnCount( const QModelIndex& parent ) const
{
+ Q_UNUSED( parent );
return 1;
}
@@ -239,8 +240,8 @@ AlbumModel::addCollection( const collection_ptr& collection )
DatabaseCommand_AllAlbums* cmd = new DatabaseCommand_AllAlbums( collection );
- connect( cmd, SIGNAL( albums( QList, Tomahawk::collection_ptr ) ),
- SLOT( onAlbumsAdded( QList, Tomahawk::collection_ptr ) ) );
+ connect( cmd, SIGNAL( albums( QList, QVariant ) ),
+ SLOT( onAlbumsAdded( QList ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
@@ -261,8 +262,8 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in
cmd->setSortOrder( order );
cmd->setSortDescending( true );
- connect( cmd, SIGNAL( albums( QList, Tomahawk::collection_ptr ) ),
- SLOT( onAlbumsAdded( QList, Tomahawk::collection_ptr ) ) );
+ connect( cmd, SIGNAL( albums( QList, QVariant ) ),
+ SLOT( onAlbumsAdded( QList ) ) );
Database::instance()->enqueue( QSharedPointer( cmd ) );
@@ -271,7 +272,7 @@ AlbumModel::addFilteredCollection( const collection_ptr& collection, unsigned in
void
-AlbumModel::onAlbumsAdded( const QList& albums, const Tomahawk::collection_ptr& collection )
+AlbumModel::onAlbumsAdded( const QList& albums )
{
if ( !albums.count() )
return;
diff --git a/src/libtomahawk/playlist/albummodel.h b/src/libtomahawk/playlist/albummodel.h
index dc080a84c..ae8658e19 100644
--- a/src/libtomahawk/playlist/albummodel.h
+++ b/src/libtomahawk/playlist/albummodel.h
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -69,7 +69,7 @@ public:
virtual QString description() const { return m_description; }
virtual void setTitle( const QString& title ) { m_title = title; }
virtual void setDescription( const QString& description ) { m_description = description; }
-
+
AlbumItem* itemFromIndex( const QModelIndex& index ) const
{
if ( index.isValid() )
@@ -81,8 +81,8 @@ public:
}
public slots:
- virtual void setRepeatMode( PlaylistInterface::RepeatMode mode ) {}
- virtual void setShuffled( bool shuffled ) {}
+ virtual void setRepeatMode( PlaylistInterface::RepeatMode /*mode*/ ) {}
+ virtual void setShuffled( bool /*shuffled*/ ) {}
signals:
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
@@ -93,7 +93,7 @@ signals:
protected:
private slots:
- void onAlbumsAdded( const QList& albums, const Tomahawk::collection_ptr& collection );
+ void onAlbumsAdded( const QList& albums );
void onCoverArtDownloaded();
void onDataChanged();
diff --git a/src/libtomahawk/playlist/albumproxymodel.cpp b/src/libtomahawk/playlist/albumproxymodel.cpp
index 8a9f66493..95a764e15 100644
--- a/src/libtomahawk/playlist/albumproxymodel.cpp
+++ b/src/libtomahawk/playlist/albumproxymodel.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -22,7 +22,6 @@
#include
#include "query.h"
-#include "collectionmodel.h"
AlbumProxyModel::AlbumProxyModel( QObject* parent )
@@ -38,12 +37,19 @@ AlbumProxyModel::AlbumProxyModel( QObject* parent )
setSortCaseSensitivity( Qt::CaseInsensitive );
setDynamicSortFilter( true );
- setSourceModel( 0 );
+ setSourceAlbumModel( 0 );
}
+void
+AlbumProxyModel::setSourceModel( QAbstractItemModel* sourceModel )
+{
+ Q_UNUSED( sourceModel );
+ qDebug() << "Explicitly use setSourceAlbumModel instead";
+ Q_ASSERT( false );
+}
void
-AlbumProxyModel::setSourceModel( AlbumModel* sourceModel )
+AlbumProxyModel::setSourceAlbumModel( AlbumModel* sourceModel )
{
m_model = sourceModel;
@@ -141,6 +147,7 @@ AlbumProxyModel::removeIndexes( const QList& indexes )
Tomahawk::result_ptr
AlbumProxyModel::siblingItem( int itemsAway )
{
+ Q_UNUSED( itemsAway );
qDebug() << Q_FUNC_INFO;
return Tomahawk::result_ptr( 0 );
}
diff --git a/src/libtomahawk/playlist/albumproxymodel.h b/src/libtomahawk/playlist/albumproxymodel.h
index 151ba51c8..7427cc85f 100644
--- a/src/libtomahawk/playlist/albumproxymodel.h
+++ b/src/libtomahawk/playlist/albumproxymodel.h
@@ -34,7 +34,8 @@ public:
explicit AlbumProxyModel( QObject* parent = 0 );
virtual AlbumModel* sourceModel() const { return m_model; }
- virtual void setSourceModel( AlbumModel* sourceModel );
+ virtual void setSourceAlbumModel( AlbumModel* sourceModel );
+ virtual void setSourceModel( QAbstractItemModel* sourceModel );
virtual QList tracks() { Q_ASSERT( FALSE ); QList queries; return queries; }
diff --git a/src/libtomahawk/playlist/albumview.cpp b/src/libtomahawk/playlist/albumview.cpp
index 1f8affea7..351fd8ea2 100644
--- a/src/libtomahawk/playlist/albumview.cpp
+++ b/src/libtomahawk/playlist/albumview.cpp
@@ -72,13 +72,22 @@ AlbumView::setProxyModel( AlbumProxyModel* model )
void
-AlbumView::setModel( AlbumModel* model )
+AlbumView::setModel( QAbstractItemModel* model )
+{
+ Q_UNUSED( model );
+ qDebug() << "Explicitly use setAlbumModel instead";
+ Q_ASSERT( false );
+}
+
+
+void
+AlbumView::setAlbumModel( AlbumModel* model )
{
m_model = model;
if ( m_proxyModel )
{
- m_proxyModel->setSourceModel( model );
+ m_proxyModel->setSourceAlbumModel( m_model );
m_proxyModel->sort( 0 );
}
@@ -142,6 +151,7 @@ AlbumView::onFilterChanged( const QString& )
void
AlbumView::startDrag( Qt::DropActions supportedActions )
{
+ Q_UNUSED( supportedActions );
}
@@ -149,5 +159,6 @@ AlbumView::startDrag( Qt::DropActions supportedActions )
QPixmap
AlbumView::createDragPixmap( int itemCount ) const
{
+ Q_UNUSED( itemCount );
return QPixmap();
}
diff --git a/src/libtomahawk/playlist/albumview.h b/src/libtomahawk/playlist/albumview.h
index 953863ab2..194eab8d7 100644
--- a/src/libtomahawk/playlist/albumview.h
+++ b/src/libtomahawk/playlist/albumview.h
@@ -42,7 +42,8 @@ public:
AlbumProxyModel* proxyModel() const { return m_proxyModel; }
// PlaylistItemDelegate* delegate() { return m_delegate; }
- void setModel( AlbumModel* model );
+ void setAlbumModel( AlbumModel* model );
+ void setModel( QAbstractItemModel* model );
virtual QWidget* widget() { return this; }
virtual PlaylistInterface* playlistInterface() const { return proxyModel(); }
diff --git a/src/libtomahawk/playlist/artistview.cpp b/src/libtomahawk/playlist/artistview.cpp
new file mode 100644
index 000000000..126f99ecd
--- /dev/null
+++ b/src/libtomahawk/playlist/artistview.cpp
@@ -0,0 +1,234 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#include "artistview.h"
+
+#include
+#include
+#include
+#include
+#include
+
+#include "audio/audioengine.h"
+
+#include "tomahawksettings.h"
+#include "treeheader.h"
+#include "treeitemdelegate.h"
+#include "playlistmanager.h"
+
+static QString s_tmInfoIdentifier = QString( "TREEMODEL" );
+
+#define SCROLL_TIMEOUT 280
+
+using namespace Tomahawk;
+
+
+ArtistView::ArtistView( QWidget* parent )
+ : QTreeView( parent )
+ , m_header( new TreeHeader( this ) )
+ , m_model( 0 )
+ , m_proxyModel( 0 )
+// , m_delegate( 0 )
+{
+ setAlternatingRowColors( true );
+ setDragEnabled( true );
+ setDropIndicatorShown( false );
+ setDragDropOverwriteMode( false );
+ setUniformRowHeights( false );
+ setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
+ setRootIsDecorated( true );
+ setAnimated( false );
+ setAllColumnsShowFocus( true );
+ setSelectionMode( QAbstractItemView::ExtendedSelection );
+ setSelectionBehavior( QAbstractItemView::SelectRows );
+
+ setHeader( m_header );
+ setProxyModel( new TreeProxyModel( this ) );
+
+ #ifndef Q_WS_WIN
+ QFont f = font();
+ f.setPointSize( f.pointSize() - 1 );
+ setFont( f );
+ #endif
+
+ #ifdef Q_WS_MAC
+ f.setPointSize( f.pointSize() - 2 );
+ setFont( f );
+ #endif
+
+ m_timer.setInterval( SCROLL_TIMEOUT );
+
+ connect( verticalScrollBar(), SIGNAL( rangeChanged( int, int ) ), SLOT( onViewChanged() ) );
+ connect( verticalScrollBar(), SIGNAL( valueChanged( int ) ), SLOT( onViewChanged() ) );
+ connect( &m_timer, SIGNAL( timeout() ), SLOT( onScrollTimeout() ) );
+
+ connect( this, SIGNAL( doubleClicked( QModelIndex ) ), SLOT( onItemActivated( QModelIndex ) ) );
+}
+
+
+ArtistView::~ArtistView()
+{
+ qDebug() << Q_FUNC_INFO;
+}
+
+
+void
+ArtistView::setProxyModel( TreeProxyModel* model )
+{
+ m_proxyModel = model;
+ setItemDelegate( new TreeItemDelegate( this, m_proxyModel ) );
+
+ QTreeView::setModel( m_proxyModel );
+}
+
+
+void
+ArtistView::setModel( TreeModel* model )
+{
+ m_model = model;
+
+ if ( m_proxyModel )
+ {
+ m_proxyModel->setSourceModel( model );
+ m_proxyModel->sort( 0 );
+ }
+
+ connect( m_proxyModel, SIGNAL( filterChanged( QString ) ), SLOT( onFilterChanged( QString ) ) );
+
+ setAcceptDrops( false );
+}
+
+
+void
+ArtistView::onItemActivated( const QModelIndex& index )
+{
+ TreeModelItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( index ) );
+ if ( item )
+ {
+ if ( !item->artist().isNull() )
+ PlaylistManager::instance()->show( item->artist() );
+ else if ( !item->album().isNull() )
+ PlaylistManager::instance()->show( item->album() );
+ else if ( !item->result().isNull() )
+ AudioEngine::instance()->playItem( 0, item->result() );
+ }
+}
+
+
+void
+ArtistView::dragEnterEvent( QDragEnterEvent* event )
+{
+ qDebug() << Q_FUNC_INFO;
+ QTreeView::dragEnterEvent( event );
+}
+
+
+void
+ArtistView::dragMoveEvent( QDragMoveEvent* event )
+{
+ QTreeView::dragMoveEvent( event );
+}
+
+
+void
+ArtistView::dropEvent( QDropEvent* event )
+{
+ QTreeView::dropEvent( event );
+}
+
+
+void
+ArtistView::paintEvent( QPaintEvent* event )
+{
+ QTreeView::paintEvent( event );
+}
+
+
+void
+ArtistView::resizeEvent( QResizeEvent* event )
+{
+ QTreeView::resizeEvent( event );
+ m_header->checkState();
+}
+
+
+void
+ArtistView::onFilterChanged( const QString& )
+{
+ if ( selectedIndexes().count() )
+ scrollTo( selectedIndexes().at( 0 ), QAbstractItemView::PositionAtCenter );
+}
+
+
+void
+ArtistView::startDrag( Qt::DropActions supportedActions )
+{
+ Q_UNUSED( supportedActions );
+}
+
+
+QPixmap
+ArtistView::createDragPixmap( int itemCount ) const
+{
+ Q_UNUSED( itemCount );
+ return QPixmap();
+}
+
+
+void
+ArtistView::onViewChanged()
+{
+ if ( m_timer.isActive() )
+ m_timer.stop();
+
+ m_timer.start();
+}
+
+
+void
+ArtistView::onScrollTimeout()
+{
+ qDebug() << Q_FUNC_INFO;
+ if ( m_timer.isActive() )
+ m_timer.stop();
+
+ QModelIndex left = indexAt( viewport()->rect().topLeft() );
+ while ( left.isValid() && left.parent().isValid() )
+ left = left.parent();
+
+ QModelIndex right = indexAt( viewport()->rect().bottomLeft() );
+ while ( right.isValid() && right.parent().isValid() )
+ right = right.parent();
+
+ int max = m_proxyModel->trackCount();
+ if ( right.isValid() )
+ max = right.row() + 1;
+
+ for ( int i = left.row(); i < max; i++ )
+ {
+ TreeModelItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( m_proxyModel->index( i, 0 ) ) );
+
+ Tomahawk::InfoSystem::InfoCustomData trackInfo;
+ trackInfo["artist"] = QVariant::fromValue< QString >( item->artist()->name() );
+ trackInfo["pptr"] = QVariant::fromValue< qlonglong >( (qlonglong)item );
+
+ Tomahawk::InfoSystem::InfoSystem::instance()->getInfo(
+ s_tmInfoIdentifier, Tomahawk::InfoSystem::InfoArtistImages,
+ QVariant::fromValue< Tomahawk::InfoSystem::InfoCustomData >( trackInfo ), Tomahawk::InfoSystem::InfoCustomData() );
+ }
+}
diff --git a/src/libtomahawk/playlist/artistview.h b/src/libtomahawk/playlist/artistview.h
new file mode 100644
index 000000000..e02107cbb
--- /dev/null
+++ b/src/libtomahawk/playlist/artistview.h
@@ -0,0 +1,90 @@
+/* === This file is part of Tomahawk Player - ===
+ *
+ * Copyright 2010-2011, Christian Muehlhaeuser
+ *
+ * Tomahawk is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Tomahawk is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Tomahawk. If not, see .
+ */
+
+#ifndef ARTISTVIEW_H
+#define ARTISTVIEW_H
+
+#include
+#include
+
+#include "treemodel.h"
+#include "treeproxymodel.h"
+#include "viewpage.h"
+
+#include "dllmacro.h"
+
+class TreeHeader;
+
+class DLLEXPORT ArtistView : public QTreeView, public Tomahawk::ViewPage
+{
+Q_OBJECT
+
+public:
+ explicit ArtistView( QWidget* parent = 0 );
+ ~ArtistView();
+
+ void setProxyModel( TreeProxyModel* model );
+
+ TreeModel* model() const { return m_model; }
+ TreeProxyModel* proxyModel() const { return m_proxyModel; }
+// PlaylistItemDelegate* delegate() { return m_delegate; }
+
+ void setModel( TreeModel* model );
+
+ virtual QWidget* widget() { return this; }
+ virtual PlaylistInterface* playlistInterface() const { return proxyModel(); }
+
+ virtual QString title() const { return m_model->title(); }
+ virtual QString description() const { return m_model->description(); }
+
+ virtual bool showStatsBar() const { return false; }
+ virtual bool showModes() const { return true; }
+
+ virtual bool jumpToCurrentTrack() { return false; }
+
+ QString guid() const { return QString( "ArtistView" ); }
+
+public slots:
+ void onItemActivated( const QModelIndex& index );
+
+protected:
+ virtual void startDrag( Qt::DropActions supportedActions );
+ virtual void dragEnterEvent( QDragEnterEvent* event );
+ virtual void dragMoveEvent( QDragMoveEvent* event );
+ virtual void dropEvent( QDropEvent* event );
+ virtual void resizeEvent( QResizeEvent* event );
+
+ void paintEvent( QPaintEvent* event );
+
+private slots:
+ void onFilterChanged( const QString& filter );
+ void onViewChanged();
+ void onScrollTimeout();
+
+private:
+ QPixmap createDragPixmap( int itemCount ) const;
+
+ TreeHeader* m_header;
+ TreeModel* m_model;
+ TreeProxyModel* m_proxyModel;
+// PlaylistItemDelegate* m_delegate;
+
+ QTimer m_timer;
+};
+
+#endif // ARTISTVIEW_H
diff --git a/src/libtomahawk/playlist/collectionflatmodel.cpp b/src/libtomahawk/playlist/collectionflatmodel.cpp
index aa7cae7e6..2090b6cba 100644
--- a/src/libtomahawk/playlist/collectionflatmodel.cpp
+++ b/src/libtomahawk/playlist/collectionflatmodel.cpp
@@ -102,8 +102,8 @@ CollectionFlatModel::addFilteredCollection( const collection_ptr& collection, un
cmd->setSortOrder( order );
cmd->setSortDescending( true );
- connect( cmd, SIGNAL( tracks( QList, Tomahawk::collection_ptr ) ),
- SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ), Qt::QueuedConnection );
+ connect( cmd, SIGNAL( tracks( QList, QVariant ) ),
+ SLOT( onTracksAdded( QList ) ), Qt::QueuedConnection );
Database::instance()->enqueue( QSharedPointer( cmd ) );
}
diff --git a/src/libtomahawk/playlist/collectionflatmodel.h b/src/libtomahawk/playlist/collectionflatmodel.h
index fee195376..65e1489a0 100644
--- a/src/libtomahawk/playlist/collectionflatmodel.h
+++ b/src/libtomahawk/playlist/collectionflatmodel.h
@@ -54,7 +54,7 @@ public:
void addFilteredCollection( const Tomahawk::collection_ptr& collection, unsigned int amount, DatabaseCommand_AllTracks::SortOrder order );
- virtual void append( const Tomahawk::query_ptr& query ) {}
+ virtual void append( const Tomahawk::query_ptr& /*query*/ ) {}
signals:
void repeatModeChanged( PlaylistInterface::RepeatMode mode );
diff --git a/src/libtomahawk/playlist/collectionmodel.cpp b/src/libtomahawk/playlist/collectionmodel.cpp
deleted file mode 100644
index ac0a5dc18..000000000
--- a/src/libtomahawk/playlist/collectionmodel.cpp
+++ /dev/null
@@ -1,286 +0,0 @@
-/* === This file is part of Tomahawk Player - ===
- *
- * Copyright 2010-2011, Christian Muehlhaeuser
- *
- * Tomahawk is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tomahawk is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tomahawk. If not, see .
- */
-
-#include "collectionmodel.h"
-
-#include
-#include
-#include
-
-#include "sourcelist.h"
-#include "utils/tomahawkutils.h"
-
-using namespace Tomahawk;
-
-
-CollectionModel::CollectionModel( QObject* parent )
- : QAbstractItemModel( parent )
- , m_rootItem( 0 )
-{
- qDebug() << Q_FUNC_INFO;
-
- connect( SourceList::instance(), SIGNAL( sourceRemoved( Tomahawk::source_ptr ) ), SLOT( onSourceOffline( Tomahawk::source_ptr ) ) );
-}
-
-
-CollectionModel::~CollectionModel()
-{
-}
-
-
-QModelIndex
-CollectionModel::index( int row, int column, const QModelIndex& parent ) const
-{
- if ( !m_rootItem || row < 0 || column < 0 )
- return QModelIndex();
-
- TrackModelItem* parentItem = itemFromIndex( parent );
- TrackModelItem* childItem = parentItem->children.value( row );
- if ( !childItem )
- return QModelIndex();
-
- return createIndex( row, column, childItem );
-}
-
-
-int
-CollectionModel::rowCount( const QModelIndex& parent ) const
-{
- if ( parent.column() > 0 )
- return 0;
-
- TrackModelItem* parentItem = itemFromIndex( parent );
- if ( !parentItem )
- return 0;
-
- return parentItem->children.count();
-}
-
-
-int
-CollectionModel::columnCount( const QModelIndex& parent ) const
-{
- return 4;
-}
-
-
-QModelIndex
-CollectionModel::parent( const QModelIndex& child ) const
-{
- TrackModelItem* entry = itemFromIndex( child );
- if ( !entry )
- return QModelIndex();
-
- TrackModelItem* parentEntry = entry->parent;
- if ( !parentEntry )
- return QModelIndex();
-
- TrackModelItem* grandparentEntry = parentEntry->parent;
- if ( !grandparentEntry )
- return QModelIndex();
-
- int row = grandparentEntry->children.indexOf( parentEntry );
- return createIndex( row, 0, parentEntry );
-}
-
-
-QVariant
-CollectionModel::data( const QModelIndex& index, int role ) const
-{
- if ( role != Qt::DisplayRole )
- return QVariant();
-
- TrackModelItem* entry = itemFromIndex( index );
- if ( !entry )
- return QVariant();
-
- const query_ptr& query = entry->query();
- if ( query.isNull() )
- {
- if ( !index.column() )
- {
- return entry->caption.isEmpty() ? "Unknown" : entry->caption;
- }
-
- if ( index.column() == 1 )
- {
- return entry->childCount;
- }
-
- return QVariant( "" );
- }
-
- if ( !query->numResults() )
- {
- switch( index.column() )
- {
- case 0:
- return query->track();
- break;
- }
- }
- else
- {
- switch( index.column() )
- {
- case 0:
- return query->results().first()->track();
- break;
-
- case 1:
- return QVariant();
- break;
-
- case 2:
- return TomahawkUtils::timeToString( query->results().first()->duration() );
- break;
-
- case 3:
- return query->results().first()->collection()->source()->friendlyName();
- break;
- }
- }
-
- return QVariant();
-}
-
-
-QVariant
-CollectionModel::headerData( int section, Qt::Orientation orientation, int role ) const
-{
- QStringList headers;
- headers << tr( "Name" ) << tr( "Tracks" ) << tr( "Duration" ) << tr( "Origin" );
- if ( orientation == Qt::Horizontal && role == Qt::DisplayRole && section >= 0 )
- {
- return headers.at( section );
- }
-
- return QVariant();
-}
-
-
-void
-CollectionModel::addCollection( const collection_ptr& collection )
-{
- qDebug() << Q_FUNC_INFO << collection->name()
- << collection->source()->id()
- << collection->source()->userName();
-
- emit loadingStarts();
-
- connect( collection.data(), SIGNAL( tracksAdded( QList, Tomahawk::collection_ptr ) ),
- SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) );
- connect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
- SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
-}
-
-
-void
-CollectionModel::removeCollection( const collection_ptr& collection )
-{
- disconnect( collection.data(), SIGNAL( tracksAdded( QList, Tomahawk::collection_ptr ) ),
- this, SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) );
- disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
- this, SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
-
- QList plitems = m_collectionIndex.values( collection );
-
- m_collectionIndex.remove( collection );
-}
-
-
-void
-CollectionModel::onTracksAdded( const QList& tracks, const collection_ptr& collection )
-{
-// int c = rowCount( QModelIndex() );
-
- TrackModelItem* plitem;
- foreach( const Tomahawk::query_ptr& query, tracks )
- {
- TrackModelItem* parent = m_rootItem;
- if ( parent->hash.contains( query->artist() ) )
- {
- parent = parent->hash.value( query->artist() );
- }
- else
- {
- parent = new TrackModelItem( query->artist(), m_rootItem );
- m_rootItem->hash.insert( query->artist(), parent );
- }
-
- if ( parent->hash.contains( query->album() ) )
- {
- parent->childCount++;
- parent = parent->hash.value( query->album() );
- parent->childCount++;
- }
- else
- {
- TrackModelItem* subitem = new TrackModelItem( query->album(), parent );
- parent->hash.insert( query->album(), subitem );
- parent->childCount++;
- subitem->childCount++;
- parent = subitem;
- }
-
- plitem = new TrackModelItem( query, parent );
- m_collectionIndex.insertMulti( collection, plitem );
- }
-
- reset();
-
- qDebug() << rowCount( QModelIndex() );
-}
-
-
-void
-CollectionModel::onTracksAddingFinished( const Tomahawk::collection_ptr& collection )
-{
- qDebug() << "Finished loading tracks" << collection->source()->friendlyName();
-
- disconnect( collection.data(), SIGNAL( tracksAdded( QList, Tomahawk::collection_ptr ) ),
- this, SLOT( onTracksAdded( QList, Tomahawk::collection_ptr ) ) );
- disconnect( collection.data(), SIGNAL( tracksFinished( Tomahawk::collection_ptr ) ),
- this, SLOT( onTracksAddingFinished( Tomahawk::collection_ptr ) ) );
-
- emit loadingFinished();
-}
-
-
-void
-CollectionModel::onSourceOffline( Tomahawk::source_ptr src )
-{
- qDebug() << Q_FUNC_INFO;
-
- if ( m_collectionIndex.contains( src->collection() ) )
- {
- removeCollection( src->collection() );
- }
-}
-
-
-TrackModelItem*
-CollectionModel::itemFromIndex( const QModelIndex& index ) const
-{
- if ( index.isValid() )
- return static_cast( index.internalPointer() );
- else
- {
- return m_rootItem;
- }
-}
diff --git a/src/libtomahawk/playlist/collectionmodel.h b/src/libtomahawk/playlist/collectionmodel.h
deleted file mode 100644
index d6563922f..000000000
--- a/src/libtomahawk/playlist/collectionmodel.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* === This file is part of Tomahawk Player - ===
- *
- * Copyright 2010-2011, Christian Muehlhaeuser
- *
- * Tomahawk is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Tomahawk is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Tomahawk. If not, see .
- */
-
-#ifndef COLLECTIONMODEL_H
-#define COLLECTIONMODEL_H
-
-#include
-#include
-#include
-
-#include "trackmodelitem.h"
-#include "collection.h"
-#include "query.h"
-#include "typedefs.h"
-#include "playlist.h"
-#include "playlistinterface.h"
-
-#include "dllmacro.h"
-
-class QMetaData;
-
-class DLLEXPORT CollectionModel : public QAbstractItemModel
-{
-Q_OBJECT
-
-public:
- explicit CollectionModel( QObject* parent = 0 );
- ~CollectionModel();
-
- QModelIndex index( int row, int column, const QModelIndex& parent ) const;
- QModelIndex parent( const QModelIndex& child ) const;
-
- int trackCount() const { return rowCount( QModelIndex() ); }
-
- int rowCount( const QModelIndex& parent ) const;
- int columnCount( const QModelIndex& parent ) const;
-
- QVariant data( const QModelIndex& index, int role ) const;
- QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
-
- void addCollection( const Tomahawk::collection_ptr& collection );
- void removeCollection( const Tomahawk::collection_ptr& collection );
-
- virtual PlaylistInterface::RepeatMode repeatMode() const { return PlaylistInterface::NoRepeat; }
- virtual bool shuffled() const { return false; }
-
- virtual void setRepeatMode( PlaylistInterface::RepeatMode mode ) {}
- virtual void setShuffled( bool shuffled ) {}
-
- TrackModelItem* itemFromIndex( const QModelIndex& index ) const;
-
-signals:
- void repeatModeChanged( PlaylistInterface::RepeatMode mode );
- void shuffleModeChanged( bool enabled );
-
- void loadingStarts();
- void loadingFinished();
- void trackCountChanged( unsigned int tracks );
-
-private slots:
- void onTracksAdded( const QList& tracks, const Tomahawk::collection_ptr& collection );
- void onTracksAddingFinished( const Tomahawk::collection_ptr& collection );
-
- void onSourceOffline( Tomahawk::source_ptr src );
-
-private:
- TrackModelItem* m_rootItem;
- QMap< Tomahawk::collection_ptr, TrackModelItem* > m_collectionIndex;
-};
-
-#endif // COLLECTIONMODEL_H
diff --git a/src/libtomahawk/playlist/collectionproxymodel.cpp b/src/libtomahawk/playlist/collectionproxymodel.cpp
index f6c5dd7b5..4f602e5db 100644
--- a/src/libtomahawk/playlist/collectionproxymodel.cpp
+++ b/src/libtomahawk/playlist/collectionproxymodel.cpp
@@ -23,7 +23,6 @@
#include "album.h"
#include "query.h"
-#include "collectionmodel.h"
CollectionProxyModel::CollectionProxyModel( QObject* parent )
@@ -46,11 +45,6 @@ CollectionProxyModel::lessThan( const QModelIndex& left, const QModelIndex& righ
const Tomahawk::query_ptr& q1 = p1->query();
const Tomahawk::query_ptr& q2 = p2->query();
- if ( q1.isNull() || q2.isNull() )
- {
- return QString::localeAwareCompare( p1->caption, p2->caption ) < 0;
- }
-
QString artist1 = q1->artist();
QString artist2 = q2->artist();
QString album1 = q1->album();
diff --git a/src/libtomahawk/playlist/collectionview.cpp b/src/libtomahawk/playlist/collectionview.cpp
index d67b02535..6d93742f6 100644
--- a/src/libtomahawk/playlist/collectionview.cpp
+++ b/src/libtomahawk/playlist/collectionview.cpp
@@ -51,9 +51,18 @@ CollectionView::~CollectionView()
void
-CollectionView::setModel( TrackModel* model )
+CollectionView::setModel( QAbstractItemModel* model )
{
- TrackView::setModel( model );
+ Q_UNUSED( model );
+ qDebug() << "Explicitly use setTrackModel instead";
+ Q_ASSERT( false );
+}
+
+
+void
+CollectionView::setTrackModel( TrackModel* model )
+{
+ TrackView::setTrackModel( model );
setGuid( "collectionview" );
connect( model, SIGNAL( trackCountChanged( unsigned int ) ), SLOT( onTrackCountChanged( unsigned int ) ) );
diff --git a/src/libtomahawk/playlist/collectionview.h b/src/libtomahawk/playlist/collectionview.h
index ea26fc5af..1fe261646 100644
--- a/src/libtomahawk/playlist/collectionview.h
+++ b/src/libtomahawk/playlist/collectionview.h
@@ -36,7 +36,8 @@ public:
explicit CollectionView( QWidget* parent = 0 );
~CollectionView();
- virtual void setModel( TrackModel* model );
+ virtual void setTrackModel( TrackModel* model );
+ virtual void setModel( QAbstractItemModel* model );
virtual QWidget* widget() { return this; }
virtual PlaylistInterface* playlistInterface() const { return proxyModel(); }
diff --git a/src/libtomahawk/playlist/dynamic/DynamicControl.h b/src/libtomahawk/playlist/dynamic/DynamicControl.h
index 42b62d07d..c03d386fd 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicControl.h
+++ b/src/libtomahawk/playlist/dynamic/DynamicControl.h
@@ -79,8 +79,8 @@ public:
virtual QString summary() const { Q_ASSERT( false ); return QString(); }
// used by JSON serialization
- virtual void setMatch( const QString& match ) { Q_ASSERT( false ); }
- virtual void setInput( const QString& input ) { Q_ASSERT( false ); }
+ virtual void setMatch( const QString& /*match*/ ) { Q_ASSERT( false ); }
+ virtual void setInput( const QString& /*input*/ ) { Q_ASSERT( false ); }
/// All the potential type selectors for this control
QStringList typeSelectors() const { return m_typeSelectors; }
diff --git a/src/libtomahawk/playlist/dynamic/DynamicModel.cpp b/src/libtomahawk/playlist/dynamic/DynamicModel.cpp
index 43fceeaac..689af3bca 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicModel.cpp
+++ b/src/libtomahawk/playlist/dynamic/DynamicModel.cpp
@@ -42,8 +42,10 @@ DynamicModel::~DynamicModel()
}
void
-DynamicModel::loadPlaylist( const Tomahawk::dynplaylist_ptr& playlist )
+DynamicModel::loadPlaylist( const Tomahawk::dynplaylist_ptr& playlist, bool loadEntries )
{
+ Q_UNUSED( loadEntries );
+
if( !m_playlist.isNull() ) {
disconnect( m_playlist->generator().data(), SIGNAL( nextTrackGenerated( Tomahawk::query_ptr ) ), this, SLOT( newTrackGenerated( Tomahawk::query_ptr ) ) );
}
@@ -108,6 +110,8 @@ DynamicModel::changeStation()
void
DynamicModel::trackResolveFinished( bool success )
{
+ Q_UNUSED( success );
+
Query* q = qobject_cast(sender());
if( !q->playable() ) {
diff --git a/src/libtomahawk/playlist/dynamic/DynamicModel.h b/src/libtomahawk/playlist/dynamic/DynamicModel.h
index a3cdc5f65..23aa93e68 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicModel.h
+++ b/src/libtomahawk/playlist/dynamic/DynamicModel.h
@@ -44,7 +44,7 @@ public:
virtual QString description() const;
- void loadPlaylist( const dynplaylist_ptr& playlist );
+ void loadPlaylist( const dynplaylist_ptr& playlist, bool loadEntries = true );
virtual void removeIndex( const QModelIndex& index, bool moreToCome = false );
diff --git a/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp b/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp
index 6186024ee..d81c27324 100644
--- a/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp
+++ b/src/libtomahawk/playlist/dynamic/DynamicPlaylist.cpp
@@ -1,5 +1,5 @@
/* === This file is part of Tomahawk Player - ===
- *
+ *
* Copyright 2010-2011, Christian Muehlhaeuser
*
* Tomahawk is free software: you can redistribute it and/or modify
@@ -43,17 +43,18 @@ DynamicPlaylist::~DynamicPlaylist()
}
// Called by loadAllPlaylists command
-DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
+DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
const QString& currentrevision,
- const QString& title,
- const QString& info,
- const QString& creator,
- const QString& type,
+ const QString& title,
+ const QString& info,
+ const QString& creator,
+ uint createdOn,
+ const QString& type,
GeneratorMode mode,
- bool shared,
- int lastmod,
+ bool shared,
+ int lastmod,
const QString& guid )
- : Playlist( src, currentrevision, title, info, creator, shared, lastmod, guid )
+ : Playlist( src, currentrevision, title, info, creator, createdOn, shared, lastmod, guid )
{
qDebug() << "Creating Dynamic Playlist 1";
// TODO instantiate generator
@@ -63,12 +64,12 @@ DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& src,
// 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,
+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 )
{
@@ -76,31 +77,31 @@ DynamicPlaylist::DynamicPlaylist ( const Tomahawk::source_ptr& author,
m_generator = geninterface_ptr( GeneratorFactory::create( type ) );
}
-geninterface_ptr
+geninterface_ptr
DynamicPlaylist::generator() const
{
return m_generator;
}
-int
+int
DynamicPlaylist::mode() const
{
return m_generator->mode();
}
-void
+void
DynamicPlaylist::setGenerator(const Tomahawk::geninterface_ptr& gen_ptr)
{
m_generator = gen_ptr;
}
-QString
+QString
DynamicPlaylist::type() const
{
return m_generator->type();
}
-void
+void
DynamicPlaylist::setMode( int mode )
{
m_generator->setMode( (GeneratorMode)mode );
@@ -108,27 +109,27 @@ 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,
+dynplaylist_ptr
+DynamicPlaylist::create( const Tomahawk::source_ptr& author,
+ const QString& guid,
+ const QString& title,
+ const QString& info,
+ const QString& creator,
bool shared )
{
// default generator
QString type = "";
dynplaylist_ptr dynplaylist = 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()) );
Database::instance()->enqueue( QSharedPointer