1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-09-09 21:50:58 +02:00

Compare commits

..

47 Commits

Author SHA1 Message Date
Anton Romanov
9a5750c6f4 Precache next track to play when reaching end of current song 2016-12-14 15:17:13 -08:00
Anton Romanov
3b6ba36e83 Streamline special char filtering out and add ´ to that list 2016-12-06 17:24:35 -08:00
Anton Romanov
cf6a37ae45 Only start playing preferred result if it is from the currently playing Query 2016-12-02 16:07:18 -08:00
Dominik Schmidt
690a87f1eb Merge pull request #577 from tomahawk-player/scriptcollectionweight
Allow to specify weight for collection (matters only as last resort for sorting results)
2016-11-30 22:12:10 +01:00
Anton Romanov
6842da7240 Fix possible issue with accessing parent resolver in collection(in case it doesn't have one) 2016-11-30 12:17:38 -08:00
Anton Romanov
6910e5dd3b Allow to specify weight for collection (matters only as last resort for sorting results) 2016-11-30 12:13:50 -08:00
Anton Romanov
584aa76582 Give script collection weight of 100 to fix prefered sorting 2016-11-30 11:44:40 -08:00
Anton Romanov
7e96285132 Merge pull request #573 from tomahawk-player/cacheSimilarity
Cache track similarity in Query to speed up result insertion/removal
2016-11-18 21:25:40 -08:00
Anton Romanov
c996a8b90e Merge pull request #490 from tomahawk-player/preferred-result
Enable setting a preferred result on a query
2016-11-15 10:23:55 -08:00
Anton Romanov
c705013ee1 Cache track similarity in Query to speed up result insertion/removal 2016-11-11 21:31:22 -08:00
Dominik Schmidt
84360aed2f Merge pull request #572 from tomahawk-player/vlcargs
Allow specifying additional VLC cmdnline args in advanced settings
2016-11-11 07:20:55 +01:00
Anton Romanov
ada03e1a8d Allow specifying additional VLC cmdnline args in advanced settings 2016-11-10 22:12:50 -08:00
Anton Romanov
3a71da5705 Disable Rovi infoplugin as it gives bogus results and spotify infoplugin as its not working due to using disabled API 2016-11-04 11:19:24 -07:00
Anton Romanov
214e310c91 Rearrange vlc includes for compilation with vlc3 master 2016-11-04 11:18:32 -07:00
Stefan Derkits
ed9a027644 q&d fix: hide stations in UI because they no longer work (#562)
Echonest API is dead :( remove libechonest dependency & hide stations in UI
2016-10-28 23:21:13 +02:00
Dominik Schmidt
3e2d74128d Merge pull request #507 from mickael9/mickael9-patch-1
Allow downloads from a non-collection resolver
2016-09-19 23:08:26 +02:00
Dominik Schmidt
84ed59f4be Merge pull request #560 from theli-ua/cookierootfix
Set redirect path to '/' if its empty, carry-over Accept-Language if set
2016-09-19 23:04:29 +02:00
Romanov
5dd36cbd4e Fix typo 2016-09-19 12:10:36 -07:00
Romanov
7e38d94fe5 Cleanup header carryover a bit 2016-09-19 12:09:40 -07:00
Romanov
28ee9180c8 Set redirect path to '/' if its empty, carry-over Accept-Language if set 2016-09-19 11:54:59 -07:00
Christian Muehlhaeuser
09e9a6e960 Fixed crash in TrackView.cpp triggered by Qt >5.6.1. 2016-06-30 21:43:27 +02:00
Christian Muehlhaeuser
ffa098e52d Coding style fix. 2016-06-30 21:40:42 +02:00
Dominik Schmidt
a439427ca5 Merge pull request #514 from bjoernricks/master
Show notification on resume
2016-05-29 18:26:56 +02:00
Björn Ricks
a9505f75c5 Show notification on resume
Display song notification when a user resumes playing music.
2016-05-27 09:02:25 +02:00
Mickaël Thomas
7e54e506df DownloadJob: make sure resolvedBy() is not null 2016-05-21 19:28:50 +02:00
Mickaël Thomas
abc00b4758 Add getDownloadUrl (similar to getStreamUrl) 2016-05-19 22:14:26 +02:00
Christian Muehlhaeuser
77e9b69679 Merge pull request #489 from tomahawk-player/unify-download-buttons
Unify DownloadButtons
2016-05-11 21:15:23 +02:00
Romanov
58b640d389 Mark overrides as such 2016-04-22 11:39:24 -07:00
Romanov
1a5f073437 Use temporary QString to hold ownership of strings when passing imem params, set media on the player after setting all params 2016-04-22 10:13:35 -07:00
Dominik Schmidt
c9ef7e74d8 Enable setting a preferred result on a query 2016-04-16 04:15:45 +02:00
Dominik Schmidt
34448b1b46 DownloadButton: Share click handling code between primitive and widget mode 2016-04-16 01:16:35 +02:00
Dominik Schmidt
4408ba275c Add localUrlForDownload method 2016-04-16 00:19:36 +02:00
Dominik Schmidt
dfd71d7010 Add DownloadButton to column view 2016-04-15 21:44:34 +02:00
Dominik Schmidt
170e2e1c86 Allow to use DownloadButton as a real standalone widget 2016-04-15 21:42:28 +02:00
Dominik Schmidt
0047763188 Unify DownloadButtons 2016-04-15 18:48:30 +02:00
Christian Muehlhaeuser
525068a706 DirLister should emit finished if there's nothing to scan at all. 2016-04-15 13:50:45 +02:00
Christian Muehlhaeuser
85657e40a6 Update editor geometry correctly for download buttons in GridItemDelegate. 2016-04-14 16:56:56 +02:00
Dominik Schmidt
af459afb0b Show actual DropDownButton (with Format selector) for DownloadFormats in GridView 2016-04-14 16:56:56 +02:00
Dominik Schmidt
5bbc39e6a5 Fix broken button state after download from GridView 2016-04-14 16:56:56 +02:00
Dominik Schmidt
c88640268a Fix DropDownButton activation in GridView 2016-04-14 16:56:56 +02:00
Dominik Schmidt
8749a04e23 Fix album folders not being opened correctly if the path contained whitespaces 2016-04-14 16:56:55 +02:00
Dominik Schmidt
d45917d14a Show View In Folder button when album is completely downloaded 2016-04-14 16:56:39 +02:00
Dominik Schmidt
c87b1390e5 Add Result::isLocal helper method 2016-04-14 16:53:30 +02:00
Christian Muehlhaeuser
bf28f6856e Fixed seeking for HTTP streams without headers, e.g. Spotify (see #453). 2016-04-14 00:57:00 +02:00
Dominik Schmidt
ceab0f9cf2 Fix RTMP streams 2016-04-13 20:03:02 +02:00
Christian Muehlhaeuser
a562e75937 Fixed copy/paste job-gone-wrong: GPL2->GPL3 header updates. 2016-04-13 15:34:27 +02:00
Christian Muehlhaeuser
81eb226146 Abort event-handling when TomahawkWindow's event-filter caught and handled a mouse event. 2016-04-13 14:40:08 +02:00
107 changed files with 1599 additions and 1067 deletions

View File

@@ -315,9 +315,6 @@ if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR APPLE) AND LIBCPP_FOUND)
tomahawk_add_cxx_flags( "-stdlib=libc++" )
endif()
macro_optional_find_package(Echonest 2.3.0)
macro_log_feature(ECHONEST_FOUND "Echonest" "Qt library for communicating with The Echo Nest" "http://projects.kde.org/libechonest" TRUE "" "libechonest 2.3.0 is needed for dynamic playlists and the infosystem")
find_package(Boost REQUIRED COMPONENTS filesystem system)
macro_log_feature(Boost_FOUND "Boost" "Provides free peer-reviewed portable C++ source libraries" "http://www.boost.org" TRUE "" "") #FIXME: give useful explanation

View File

@@ -1,42 +0,0 @@
# - Find libechonest
# Find the libechonest includes and the libechonest libraries
# This module defines
# ECHONEST_INCLUDE_DIR, root echonest include dir. Include echonest includes with echonest/foo.h
# ECHONEST_LIBRARIES, the path to libechonest
# ECHONEST_FOUND, whether libechonest was found
FIND_PACKAGE(PkgConfig QUIET)
if( TOMAHAWK_QT5 )
set(LIBECHONEST_SUFFIX "5")
endif()
PKG_CHECK_MODULES(PC_ECHONEST QUIET libechonest${LIBECHONEST_SUFFIX})
FIND_PATH(ECHONEST_INCLUDE_DIR NAMES echonest${LIBECHONEST_SUFFIX}/Track.h
HINTS
${PC_ECHONEST_INCLUDEDIR}
${PC_ECHONEST_INCLUDE_DIRS}
${CMAKE_INSTALL_INCLUDEDIR}
${KDE4_INCLUDE_DIR}
)
FIND_LIBRARY(ECHONEST_LIBRARIES NAMES echonest${LIBECHONEST_SUFFIX}
HINTS
${PC_ECHONEST_LIBDIR}
${PC_ECHONEST_LIBRARY_DIRS}
${CMAKE_INSTALL_LIBDIR}
${KDE4_LIB_DIR}
)
IF(ECHONEST_LIBRARIES AND ECHONEST_INCLUDE_DIR AND NOT PC_ECHONEST_VERSION)
MESSAGE(WARNING "You don't have pkg-config and so the libechonest version check does not work!")
set(PC_ECHONEST_VERSION "999.9.9")
ENDIF()
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Echonest
REQUIRED_VARS ECHONEST_LIBRARIES ECHONEST_INCLUDE_DIR
VERSION_VAR PC_ECHONEST_VERSION)
MARK_AS_ADVANCED(ECHONEST_INCLUDE_DIR ECHONEST_LIBRARIES)

View File

@@ -79,7 +79,6 @@ Required dependencies:
* [TagLib 1.8](https://taglib.github.io/)
* [Boost 1.3](http://www.boost.org/)
* [Lucene++ 3.0.6](https://github.com/luceneplusplus/LucenePlusPlus/)
* [libechonest 2.3.1](http://projects.kde.org/projects/playground/libs/libechonest/)
* [Attica 5.6.0](http://ftp.kde.org/stable/attica/)
* [QuaZip 0.4.3](http://quazip.sourceforge.net/)
* [liblastfm 1.0.9](https://github.com/lastfm/liblastfm/)

View File

@@ -275,6 +275,9 @@ Tomahawk.Resolver = {
getStreamUrl: function (params) {
return params;
},
getDownloadUrl: function (params) {
return params;
},
resolve: function() {
},
_adapter_resolve: function (params) {
@@ -1763,6 +1766,9 @@ Tomahawk.Collection = {
this.settings.capabilities = [Tomahawk.Collection.BrowseCapability.Artists,
Tomahawk.Collection.BrowseCapability.Albums,
Tomahawk.Collection.BrowseCapability.Tracks];
if (!this.settings.weight && this.resolver && this.resolver.settings.weight) {
this.settings.weight = this.resolver.settings.weight;
}
return this.settings;
},
@@ -1771,6 +1777,14 @@ Tomahawk.Collection = {
return this.resolver.getStreamUrl(params);
}
return params;
},
getDownloadUrl: function(params) {
if(this.resolver) {
return this.resolver.getDownloadUrl(params);
}
return params;
}
};

View File

@@ -44,12 +44,12 @@ namespace Tomahawk {
void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
public slots:
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) override;
protected slots:
void init();
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
void init() override;
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) override;
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) override;
private slots:
void audioStarted( const Tomahawk::InfoSystem::PushInfoPair& pushInfoPair );

View File

@@ -54,14 +54,14 @@ public:
Account::ConnectionState connectionState() const;
public slots:
void connectPlugin();
void disconnectPlugin();
void connectPlugin() override;
void disconnectPlugin() override;
void advertise();
virtual void sendSipInfos( const Tomahawk::peerinfo_ptr& /* receiver */, const QList<SipInfo>& /* info */ ) {}
virtual void sendSipInfos( const Tomahawk::peerinfo_ptr& /* receiver */, const QList<SipInfo>& /* info */ ) override {}
void broadcastMsg( const QString& ) {}
bool addContact( const QString&, AddContactOptions, const QString& ) { return false; }
bool addContact( const QString&, AddContactOptions, const QString& ) override { return false; }
private slots:
void lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid );

View File

@@ -1,5 +1,4 @@
include_directories(
${ECHONEST_INCLUDE_DIR}
${Boost_INCLUDE_DIR}
)
if(WIN32 OR APPLE)
@@ -15,14 +14,13 @@ endif()
endif(WIN32 OR APPLE)
list(APPEND simple_plugins
Echonest
Charts
NewReleases
Spotify
#Spotify
Hypem
MusixMatch
MusicBrainz
Rovi
#Rovi
Discogs
)

View File

@@ -80,7 +80,7 @@ FdoNotifyPlugin::FdoNotifyPlugin()
, m_wmSupportsBodyMarkup( false )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped << InfoInboxReceived;
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoNowResumed << InfoTrackUnresolved << InfoNowStopped << InfoInboxReceived;
// Query the window manager for its capabilties in styling notifications.
notifications_interface = new org::freedesktop::Notifications( "org.freedesktop.Notifications", "/org/freedesktop/Notifications",
@@ -139,6 +139,7 @@ FdoNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
return;
case Tomahawk::InfoSystem::InfoNowPlaying:
case Tomahawk::InfoSystem::InfoNowResumed:
nowPlaying( pushData.infoPair.second );
return;

View File

@@ -120,9 +120,12 @@ ActionCollection::initActions()
m_actionCollection[ "createPlaylist" ] = new QAction( tr( "Create Playlist" ), this );
m_actionCollection[ "createPlaylist" ]->setShortcut( QKeySequence( "Ctrl+N" ) );
m_actionCollection[ "createPlaylist" ]->setShortcutContext( Qt::ApplicationShortcut );
// echonest is dead, disable stations
/*
m_actionCollection[ "createStation" ] = new QAction( tr( "Create Station" ), this );
m_actionCollection[ "createStation" ]->setShortcut( QKeySequence( "Ctrl+S" ) );
m_actionCollection[ "createStation" ]->setShortcutContext( Qt::ApplicationShortcut );
*/
#ifdef Q_OS_MAC
m_actionCollection[ "minimize" ] = new QAction( tr( "Minimize" ), this );
m_actionCollection[ "minimize" ]->setShortcut( QKeySequence( "Ctrl+M" ) );
@@ -171,7 +174,8 @@ ActionCollection::createMenuBar( QWidget *parent )
controlsMenu->addAction( m_actionCollection[ "showOfflineSources" ] );
controlsMenu->addSeparator();
controlsMenu->addAction( m_actionCollection[ "createPlaylist" ] );
controlsMenu->addAction( m_actionCollection[ "createStation" ] );
// echonest is dead, disable stations
// controlsMenu->addAction( m_actionCollection[ "createStation" ] );
controlsMenu->addAction( m_actionCollection[ "importPlaylist" ] );
controlsMenu->addAction( m_actionCollection[ "updateCollection" ] );
controlsMenu->addAction( m_actionCollection[ "rescanCollection" ] );

View File

@@ -74,9 +74,6 @@ set( libGuiSources
playlist/dynamic/DynamicPlaylist.cpp
playlist/dynamic/DynamicView.cpp
playlist/dynamic/DynamicModel.cpp
playlist/dynamic/echonest/EchonestGenerator.cpp
playlist/dynamic/echonest/EchonestControl.cpp
playlist/dynamic/echonest/EchonestSteerer.cpp
playlist/dynamic/widgets/DynamicWidget.cpp
playlist/dynamic/widgets/DynamicControlWrapper.cpp
playlist/dynamic/widgets/DynamicControlList.cpp
@@ -146,6 +143,7 @@ set( libGuiSources
widgets/ClickableLabel.cpp
widgets/ComboBox.cpp
widgets/DropDownButton.cpp
widgets/DownloadButton.cpp
widgets/ElidedLabel.cpp
widgets/FilterHeader.cpp
widgets/CaptionLabel.cpp
@@ -207,7 +205,6 @@ list(APPEND libSources
PlaylistInterface.cpp
UrlHandler.cpp
EchonestCatalogSynchronizer.cpp
accounts/AccountManager.cpp
accounts/Account.cpp
@@ -412,7 +409,6 @@ include_directories(
${QT_INCLUDE_DIR}
${QJSON_INCLUDE_DIR}
${ECHONEST_INCLUDE_DIR}
${LUCENEPP_INCLUDE_DIRS}
${LIBVLC_INCLUDE_DIR}
${Boost_INCLUDE_DIR}
@@ -534,7 +530,6 @@ TARGET_LINK_LIBRARIES( ${TOMAHAWK_LIBRARY}
# External deps
${QJSON_LIBRARIES}
${LUCENEPP_LIBRARIES}
${ECHONEST_LIBRARIES}
${QT_QTSQL_LIBRARY}
${QT_QTUITOOLS_LIBRARY}
${QT_QTGUI_LIBRARY}
@@ -578,7 +573,7 @@ file( GLOB networkHeaders "network/*.h" )
file( GLOB playlistHeaders "playlist/*.h" )
file( GLOB playlistDynamicHeaders "playlist/dynamic/*.h" )
file( GLOB playlistDynamicDatabaseHeaders "playlist/dynamic/database/*.h" )
file( GLOB playlistDynamicEchonestHeaders "playlist/dynamic/echonest/*.h" )
# file( GLOB playlistDynamicEchonestHeaders "playlist/dynamic/echonest/*.h" )
file( GLOB playlistDynamicWidgetsHeaders "playlist/dynamic/widgets/*.h" )
file( GLOB resolversHeaders "resolvers/*.h" )
file( GLOB sipHeaders "sip/*.h" )
@@ -607,7 +602,7 @@ install( FILES ${networkHeaders} DESTINATION include/libtomahawk/network )
install( FILES ${playlistHeaders} DESTINATION include/libtomahawk/playlist )
install( FILES ${playlistDynamicHeaders} DESTINATION include/libtomahawk/playlist/dynamic )
install( FILES ${playlistDynamicDatabaseHeaders} DESTINATION include/libtomahawk/playlist/dynamic/database )
install( FILES ${playlistDynamicEchonestHeaders} DESTINATION include/libtomahawk/playlist/dynamic/echonest )
# install( FILES ${playlistDynamicEchonestHeaders} DESTINATION include/libtomahawk/playlist/dynamic/echonest )
install( FILES ${playlistDynamicWidgetsHeaders} DESTINATION include/libtomahawk/playlist/dynamic/widgets )
install( FILES ${resolversHeaders} DESTINATION include/libtomahawk/resolvers )
install( FILES ${sipHeaders} DESTINATION include/libtomahawk/sip )

View File

@@ -226,8 +226,7 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
if ( m_supportedActions & ActionOpenFileManager &&
queries.length() == 1 &&
queries.first()->numResults() &&
queries.first()->results().first()->resolvedByCollection() &&
queries.first()->results().first()->resolvedByCollection()->isLocal() )
queries.first()->results().first()->isLocal() )
{
m_sigmap->setMapping( addAction( ImageRegistry::instance()->icon( RESPATH "images/folder.svg" ),
tr( "Open Folder in File Manager..." ) ), ActionOpenFileManager );

View File

@@ -118,7 +118,7 @@ DownloadJob::localFile() const
QString
DownloadJob::localPath() const
DownloadJob::localPath( const Tomahawk::album_ptr& album )
{
QDir dir = TomahawkSettings::instance()->downloadsPath();
@@ -127,7 +127,7 @@ DownloadJob::localPath() const
dir.mkpath( "." );
}
QString path = QString( "%1/%2" ).arg( safeEncode( m_track->artist(), true ) ).arg( safeEncode( m_track->album(), true ) );
QString path = QString( "%1/%2" ).arg( safeEncode( album->artist()->name(), true ) ).arg( safeEncode( album->name(), true ) );
dir.mkpath( path );
return QString( dir.path() + "/" + path ).replace( "//", "/" );
@@ -138,7 +138,7 @@ QUrl
DownloadJob::prepareFilename()
{
QString filename = QString( "%1. %2.%3" ).arg( m_track->albumpos() ).arg( safeEncode( m_track->track() ) ).arg( m_format.extension );
QString path = localPath();
QString path = localPath( m_track->albumPtr() );
QString localFile = QString( path + "/" + filename );
if ( !m_tryResuming )
@@ -206,22 +206,17 @@ DownloadJob::download()
{
if ( m_state == Running )
return true;
setState( Running );
if ( m_result->resolvedByCollection() )
{
Tomahawk::ScriptCollection* collection = qobject_cast<Tomahawk::ScriptCollection*>( m_result->resolvedByCollection().data() );
if ( collection )
{
QVariantMap arguments;
arguments[ "url" ] = m_format.url;
// HACK: *shrug* WIP.
Tomahawk::ScriptJob* job = collection->scriptObject()->invoke( "getStreamUrl", arguments );
connect( job, SIGNAL( done(QVariantMap) ), SLOT( onUrlRetrieved(QVariantMap) ) );
job->start();
}
if (m_result->resolvedBy() != nullptr) {
Tomahawk::ScriptJob *job = m_result->resolvedBy()->getDownloadUrl( m_result, m_format );
connect( job, SIGNAL( done(QVariantMap) ), SLOT( onUrlRetrieved(QVariantMap) ) );
job->start();
} else {
onUrlRetrieved({{"url", m_format.url}});
}
return true;
}
@@ -444,7 +439,7 @@ DownloadJob::checkForResumedFile()
QString
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots ) const
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots )
{
//FIXME: make it a regexp
QString res = QString( filename ).toLatin1().replace( "/", "_" ).replace( "\\", "_" )

View File

@@ -58,7 +58,7 @@ public:
long receivedSize() const { return m_rcvdSize; }
long fileSize() const { return m_fileSize; }
QString localPath() const;
static QString localPath( const Tomahawk::album_ptr& album );
QString localFile() const;
DownloadFormat format() const;
@@ -90,7 +90,7 @@ private slots:
private:
void storeState();
QString safeEncode( const QString& filename, bool removeTrailingDots = false ) const;
static QString safeEncode( const QString& filename, bool removeTrailingDots = false );
bool checkForResumedFile();
QUrl prepareFilename();

View File

@@ -24,6 +24,8 @@
#include "TomahawkSettings.h"
#include "infosystem/InfoSystem.h"
#include "utils/Logger.h"
#include "Result.h"
#include "Query.h"
DownloadManager* DownloadManager::s_instance = 0;
@@ -85,6 +87,36 @@ DownloadManager::localFileForDownload( const QString& url ) const
}
QUrl
DownloadManager::localUrlForDownload( const Tomahawk::query_ptr& query ) const
{
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
if ( result )
{
return localUrlForDownload( result );
}
return QUrl();
}
QUrl
DownloadManager::localUrlForDownload( const Tomahawk::result_ptr& result ) const
{
if ( result && !result->downloadFormats().isEmpty() &&
!localFileForDownload( result->downloadFormats().first().url.toString() ).isEmpty() )
{
return QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( result->downloadFormats().first().url.toString() ) ).absolutePath() );
}
else if ( result && result->downloadJob() && result->downloadJob()->state() == DownloadJob::Finished )
{
return QUrl::fromLocalFile( QFileInfo( result->downloadJob()->localFile() ).absolutePath() );
}
return QUrl();
}
void
DownloadManager::storeJobs( const QList<downloadjob_ptr>& jobs )
{

View File

@@ -45,6 +45,8 @@ public:
void storeJobs( const QList<downloadjob_ptr>& jobs );
QString localFileForDownload( const QString& url ) const;
QUrl localUrlForDownload( const Tomahawk::result_ptr& result ) const;
QUrl localUrlForDownload( const Tomahawk::query_ptr& query ) const;
public slots:
bool addJob( const downloadjob_ptr& job );

View File

@@ -980,7 +980,7 @@ DropJob::removeRemoteSources()
foreach ( const Tomahawk::result_ptr& result, item->results() )
{
if ( !result->resolvedByCollection().isNull() && !result->resolvedByCollection()->isLocal() )
if ( !result->isLocal() )
{
list.append( item );
break;

View File

@@ -1,14 +1,14 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright (C) 2011-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright (C) 2013, Teo Mrnjavac <teo@kde.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -20,7 +20,6 @@
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GlobalActionManager.h"
#include "accounts/AccountManager.h"
@@ -47,12 +46,6 @@
#include "TomahawkSettings.h"
#include "ViewManager.h"
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <echonest5/Playlist.h>
#else
#include <echonest/Playlist.h>
#endif
#include <QMessageBox>
#include <QFileInfo>
@@ -913,144 +906,144 @@ GlobalActionManager::loadDynamicPlaylist( const QUrl& url, bool station )
{
dyncontrol_ptr c = pl->generator()->createControl( "Artist" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistRadioType ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistRadioType ) );
// controls << c;
}
else if ( param.first == "artist_limitto" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Artist" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistType ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistType ) );
// controls << c;
}
else if ( param.first == "description" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Artist Description" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistDescriptionType ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistDescriptionType ) );
// controls << c;
}
else if ( param.first == "variety" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Variety" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Variety ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Variety ) );
// controls << c;
}
else if ( param.first.startsWith( "tempo" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Tempo" );
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinTempo + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinTempo + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "duration" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Duration" );
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDuration + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDuration + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "loudness" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Loudness" );
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinLoudness + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinLoudness + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "danceability" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Danceability" );
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDanceability + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDanceability + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "energy" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Energy" );
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinEnergy + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinEnergy + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "artist_familiarity" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Artist Familiarity" );
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinFamiliarity + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinFamiliarity + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "artist_hotttnesss" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Artist Hotttnesss" );
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinHotttnesss + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinHotttnesss + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "song_hotttnesss" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Song Hotttnesss" );
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongMinHotttnesss + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongMinHotttnesss + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "longitude" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Longitude" );
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLongitude + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLongitude + extra ) );
// controls << c;
}
else if ( param.first.startsWith( "latitude" ) )
{
dyncontrol_ptr c = pl->generator()->createControl( "Latitude" );
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLatitude + extra ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLatitude + extra ) );
// controls << c;
}
else if ( param.first == "key" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Key" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Key ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Key ) );
// controls << c;
}
else if ( param.first == "mode" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Mode" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mode ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mode ) );
// controls << c;
}
else if ( param.first == "mood" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Mood" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mood ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mood ) );
// controls << c;
}
else if ( param.first == "style" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Style" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Style ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Style ) );
// controls << c;
}
else if ( param.first == "song" )
{
dyncontrol_ptr c = pl->generator()->createControl( "Song" );
c->setInput( param.second );
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongRadioType ) );
controls << c;
// c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongRadioType ) );
// controls << c;
}
}

View File

@@ -1,21 +1,21 @@
/*
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef GLOBALACTIONMANAGER_H
#define GLOBALACTIONMANAGER_H

View File

@@ -194,7 +194,7 @@ Query::addResults( const QList< Tomahawk::result_ptr >& newresults )
}*/
d->results << newresults;
qStableSort( d->results.begin(), d->results.end(), std::bind( &Query::resultSorter, this, std::placeholders::_1, std::placeholders::_2 ) );
sortResults();
// hook up signals, and check solved status
foreach( const result_ptr& rp, newresults )
@@ -258,7 +258,7 @@ Query::onResultStatusChanged()
Q_D( Query );
QMutexLocker lock( &d->mutex );
if ( !d->results.isEmpty() )
qStableSort( d->results.begin(), d->results.end(), std::bind( &Query::resultSorter, this, std::placeholders::_1, std::placeholders::_2 ) );
sortResults();
}
checkResults();
@@ -273,6 +273,11 @@ Query::removeResult( const Tomahawk::result_ptr& result )
Q_D( Query );
QMutexLocker lock( &d->mutex );
d->results.removeAll( result );
if ( d->preferredResult == result )
{
d->preferredResult.clear();
}
sortResults();
}
emit resultsRemoved( result );
@@ -396,12 +401,21 @@ Query::id() const
bool
Query::resultSorter( const result_ptr& left, const result_ptr& right )
{
Q_D( Query );
if ( !d->preferredResult.isNull() )
{
if ( d->preferredResult == left )
return true;
if ( d->preferredResult == right )
return false;
}
const float ls = left->isOnline() ? howSimilar( left ) : 0.0;
const float rs = right->isOnline() ? howSimilar( right ) : 0.0;
if ( ls == rs )
{
if ( right->resolvedByCollection() && right->resolvedByCollection()->isLocal() )
if ( right->isLocal() )
{
return false;
}
@@ -427,6 +441,30 @@ Query::resultSorter( const result_ptr& left, const result_ptr& right )
}
result_ptr
Query::preferredResult() const
{
Q_D( const Query );
return d->preferredResult;
}
void
Query::setPreferredResult( const result_ptr& result )
{
{
Q_D( Query );
QMutexLocker lock( &d->mutex );
Q_ASSERT( d->results.contains( result ) );
d->preferredResult = result;
sortResults();
}
emit resultsChanged();
}
void
Query::setCurrentResolver( Tomahawk::Resolver* resolver )
{
@@ -622,6 +660,10 @@ float
Query::howSimilar( const Tomahawk::result_ptr& r )
{
Q_D( Query );
if (d->howSimilarCache.find(r->id()) != d->howSimilarCache.end())
{
return d->howSimilarCache[r->id()];
}
// result values
const QString& rArtistname = r->track()->artistSortname();
const QString& rAlbumname = r->track()->albumSortname();
@@ -643,10 +685,12 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
qTrackname = queryTrack()->trackSortname();
}
static const QRegExp filterOutChars = QRegExp(QString::fromUtf8("[-`´~!@#$%^&*\\(\\)_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]"));
//Cleanup symbols for minor naming differences
qArtistname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
qTrackname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
qAlbumname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
qArtistname.remove(filterOutChars);
qTrackname.remove(filterOutChars);
qAlbumname.remove(filterOutChars);
// normal edit distance
const int artdist = TomahawkUtils::levenshtein( qArtistname, rArtistname );
@@ -678,12 +722,16 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
const int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
const float dcatr = (float)( mlatr - atrdist ) / mlatr;
return qMax( dctrk, qMax( dcatr, qMax( dcart, dcalb ) ) );
float resultScore = qMax( dctrk, qMax( dcatr, qMax( dcart, dcalb ) ) );
d->howSimilarCache[r->id()] = resultScore;
return resultScore;
}
else
{
// weighted, so album match is worth less than track title
return ( dcart * 4 + dcalb + dctrk * 5 ) / 10;
float resultScore = ( dcart * 4 + dcalb + dctrk * 5 ) / 10;
d->howSimilarCache[r->id()] = resultScore;
return resultScore;
}
}
@@ -734,3 +782,11 @@ Query::setWeakRef( QWeakPointer<Query> weakRef )
Q_D( Query );
d->ownRef = weakRef;
}
void
Query::sortResults()
{
Q_D( Query );
qStableSort( d->results.begin(), d->results.end(), std::bind( &Query::resultSorter, this, std::placeholders::_1, std::placeholders::_2 ) );
}

View File

@@ -112,6 +112,8 @@ public:
/// sorter for list of results
bool resultSorter( const result_ptr& left, const result_ptr& right );
result_ptr preferredResult() const;
void setPreferredResult( const result_ptr& result );
signals:
void resultsAdded( const QList<Tomahawk::result_ptr>& );
@@ -158,6 +160,7 @@ private:
void setCurrentResolver( Tomahawk::Resolver* resolver );
void clearResults();
void checkResults();
void sortResults();
};
} //ns

View File

@@ -4,6 +4,7 @@
#include "Query.h"
#include <QMutex>
#include <map>
namespace Tomahawk
{
@@ -39,6 +40,7 @@ private:
QList< Tomahawk::artist_ptr > artists;
QList< Tomahawk::album_ptr > albums;
QList< Tomahawk::result_ptr > results;
Tomahawk::result_ptr preferredResult;
float score;
bool solved;
@@ -58,6 +60,8 @@ private:
mutable QMutex mutex;
QWeakPointer< Tomahawk::Query > ownRef;
std::map<QString, float> howSimilarCache;
};
} // Tomahawk

View File

@@ -234,6 +234,13 @@ Result::playable() const
}
bool
Result::isLocal() const
{
return resolvedByCollection().isNull() ? false : resolvedByCollection()->isLocal();
}
QVariant
Result::toVariant() const
{

View File

@@ -94,6 +94,12 @@ public:
bool isOnline() const;
bool playable() const;
/**
* @brief whether this result isLocal, i.e. resolved by a local collection
* @return isLocal
*/
bool isLocal() const;
QString url() const;
/**
* Has the given url been checked that it is accessible/valid.

View File

@@ -1764,3 +1764,15 @@ TomahawkSettings::setPlaydarKey( const QByteArray& key )
setValue( "playdar/key", key );
}
QString
TomahawkSettings::vlcArguments() const
{
return value( "vlc/cmdline_args" ).value< QString >();
}
void
TomahawkSettings::setVlcArguments( const QString& args )
{
setValue( "vlc/cmdline_args", args);
}

View File

@@ -253,6 +253,10 @@ public:
QByteArray playdarKey() const;
void setPlaydarKey( const QByteArray& key );
// VLC Settings
QString vlcArguments() const;
void setVlcArguments( const QString& arguments );
signals:
void changed();
void recentlyPlayedPlaylistAdded( const QString& playlistId, int sourceId );

View File

@@ -1,6 +1,6 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
*
@@ -572,10 +572,10 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
void
AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
AudioEngine::loadTrack( const Tomahawk::result_ptr& result, bool preload )
{
Q_D( AudioEngine );
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ) << " preload:" << preload;
if ( !d->audioOutput->isInitialized() )
@@ -589,36 +589,82 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
return;
}
// We do this to stop the audio as soon as a user activated another track
// If we don't block the audioOutput signals, the state change will trigger
// loading yet another track
d->audioOutput->blockSignals( true );
d->audioOutput->stop();
d->audioOutput->blockSignals( false );
if (preload && d->preloadedTrack == result)
return;
setCurrentTrack( result );
if (preload)
tDebug( LOGEXTRA ) << Q_FUNC_INFO << "not preloaded yet, preloading";
if (preload)
{
setPreloadTrack( result );
}
else
{
// We do this to stop the audio as soon as a user activated another track
// If we don't block the audioOutput signals, the state change will trigger
// loading yet another track
d->audioOutput->blockSignals( true );
d->audioOutput->stop();
d->audioOutput->blockSignals( false );
setCurrentTrack( result );
if ( result == d->preloadedTrack )
{
setPreloadTrack( Tomahawk::result_ptr(nullptr) );
d->state = Loading;
emit loading( d->currentTrack );
d->audioOutput->switchToPreloadedMedia();
if ( !d->input.isNull() )
{
d->input->close();
d->input.clear();
}
d->input = d->inputPreloaded;
d->audioOutput->play();
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
{
d->currentTrack->track()->startPlaying();
}
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
return;
}
setPreloadTrack( Tomahawk::result_ptr(nullptr) );
}
ScriptJob* job = result->resolvedBy()->getStreamUrl( result );
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( gotStreamUrl( QVariantMap ) ) );
job->setProperty( "result", QVariant::fromValue( result ) );
job->setProperty( "isPreload", QVariant::fromValue(preload) );
tDebug() << "preload:" << preload << ", for result:" << result;
job->start();
}
void
AudioEngine::gotStreamUrl( const QVariantMap& data )
{
QString streamUrl = data[ "url" ].toString();
QVariantMap headers = data[ "headers" ].toMap();
Tomahawk::result_ptr result = sender()->property( "result" ).value<result_ptr>();
bool isPreload = sender()->property( "isPreload" ).value<bool>();
if ( streamUrl.isEmpty() || !( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
tDebug() << Q_FUNC_INFO << " is preload:" << isPreload << ", for result:" << result;
if ( streamUrl.isEmpty() || headers.isEmpty() ||
!( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
{
// Not an http(s) or RTMP URL, get IO device
// We can't supply custom headers to VLC - but prefer using its HTTP streaming due to improved seeking ability
// Not an RTMP or HTTP-with-headers URL, get IO device
QSharedPointer< QIODevice > sp;
performLoadIODevice( result, streamUrl );
performLoadIODevice( result, streamUrl, isPreload );
}
else
{
// We need our own QIODevice for streaming
// TODO: just make this part of the http(s) IoDeviceFactory (?)
QUrl url = QUrl::fromEncoded( streamUrl.toUtf8() );
QNetworkRequest req( url );
@@ -640,35 +686,42 @@ AudioEngine::gotStreamUrl( const QVariantMap& data )
tDebug() << "Creating a QNetworkReply with url:" << req.url().toString();
NetworkReply* reply = new NetworkReply( Tomahawk::Utils::nam()->get( req ) );
NewClosure( reply, SIGNAL( finalUrlReached() ), this, SLOT( gotRedirectedStreamUrl( Tomahawk::result_ptr, NetworkReply* )), result, reply );
NewClosure( reply, SIGNAL( finalUrlReached() ), this, SLOT( gotRedirectedStreamUrl( Tomahawk::result_ptr, NetworkReply* ) ), result, reply );
}
sender()->deleteLater();
}
void
AudioEngine::gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply )
{
Q_D( AudioEngine );
// std::functions cannot accept temporaries as parameters
QSharedPointer< QIODevice > sp ( reply->reply(), &QObject::deleteLater );
QString url = reply->reply()->url().toString();
reply->disconnectFromReply();
reply->deleteLater();
performLoadTrack( result, url, sp );
bool isPreload = result == d->preloadedTrack;
tDebug() << Q_FUNC_INFO << " is preload:" << isPreload;
performLoadTrack( result, url, sp, isPreload );
}
void
AudioEngine::onPositionChanged( float new_position )
{
if ( new_position >= 0.90 )
loadNextTrack(true);
// tDebug() << Q_FUNC_INFO << new_position << state();
emit trackPosition( new_position );
}
void
AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url, bool preload )
{
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : url );
@@ -678,37 +731,39 @@ AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
std::function< void ( const QString, QSharedPointer< QIODevice > ) > callback =
std::bind( &AudioEngine::performLoadTrack, this, result,
std::placeholders::_1,
std::placeholders::_2 );
std::placeholders::_2,
preload );
Tomahawk::UrlHandler::getIODeviceForUrl( result, url, callback );
}
else
{
QSharedPointer< QIODevice > io;
performLoadTrack( result, url, io );
performLoadTrack( result, url, io, preload );
}
}
void
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io )
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io, bool preload )
{
if ( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this, "performLoadTrack", Qt::QueuedConnection,
Q_ARG( const Tomahawk::result_ptr, result ),
Q_ARG( const QString, url ),
Q_ARG( QSharedPointer< QIODevice >, io )
Q_ARG( QSharedPointer< QIODevice >, io ),
Q_ARG( bool, preload )
);
return;
}
Q_D( AudioEngine );
if ( currentTrack() != result )
if ( !preload && currentTrack() != result )
{
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Track loaded too late, skip.";
return;
}
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ) << preload;
QSharedPointer< QIODevice > ioToKeep = io;
bool err = false;
@@ -722,9 +777,16 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
if ( !err )
{
tLog() << Q_FUNC_INFO << "Starting new song:" << url;
d->state = Loading;
emit loading( d->currentTrack );
if (preload)
{
tLog() << Q_FUNC_INFO << "Preloading new song:" << url;
}
else
{
tLog() << Q_FUNC_INFO << "Starting new song:" << url;
d->state = Loading;
emit loading( d->currentTrack );
}
if ( !TomahawkUtils::isLocalResult( url )
&& !( TomahawkUtils::isHttpResult( url ) && io.isNull() )
@@ -733,18 +795,18 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
QSharedPointer<QNetworkReply> qnr = io.objectCast<QNetworkReply>();
if ( !qnr.isNull() )
{
d->audioOutput->setCurrentSource( new QNR_IODeviceStream( qnr, this ) );
d->audioOutput->setCurrentSource( new QNR_IODeviceStream( qnr, this ), preload );
// We keep track of the QNetworkReply in QNR_IODeviceStream
// and AudioOutput handles the deletion of the
// QNR_IODeviceStream object
ioToKeep.clear();
d->audioOutput->setAutoDelete( true );
d->audioOutput->setAutoDelete( true, preload );
}
else
{
d->audioOutput->setCurrentSource( io.data() );
d->audioOutput->setCurrentSource( io.data(), preload);
// We handle the deletion via tracking in d->input
d->audioOutput->setAutoDelete( false );
d->audioOutput->setAutoDelete( false, preload);
}
}
else
@@ -763,7 +825,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
}
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Passing to VLC:" << furl;
d->audioOutput->setCurrentSource( furl );
d->audioOutput->setCurrentSource( furl, preload );
}
else
{
@@ -772,26 +834,37 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
furl = furl.right( furl.length() - 7 );
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Passing to VLC:" << QUrl::fromLocalFile( furl );
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ) );
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ), preload );
}
d->audioOutput->setAutoDelete( true );
d->audioOutput->setAutoDelete( true, preload );
}
if ( !d->input.isNull() )
if ( preload ) {
if ( !d->inputPreloaded.isNull() )
{
d->inputPreloaded->close();
d->inputPreloaded.clear();
}
d->inputPreloaded = ioToKeep;
}
else
{
d->input->close();
d->input.clear();
}
d->input = ioToKeep;
d->audioOutput->play();
if ( !d->input.isNull() )
{
d->input->close();
d->input.clear();
}
d->input = ioToKeep;
d->audioOutput->play();
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
{
d->currentTrack->track()->startPlaying();
}
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
{
d->currentTrack->track()->startPlaying();
}
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
}
}
}
@@ -801,7 +874,10 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
return;
}
d->waitingOnNewTrack = false;
if ( !preload )
{
d->waitingOnNewTrack = false;
}
return;
}
@@ -833,18 +909,19 @@ AudioEngine::loadPreviousTrack()
}
if ( result )
loadTrack( result );
loadTrack( result, false );
else
stop();
}
void
AudioEngine::loadNextTrack()
AudioEngine::loadNextTrack( bool preload )
{
if ( QThread::currentThread() != thread() )
{
QMetaObject::invokeMethod( this, "loadNextTrack", Qt::QueuedConnection );
QMetaObject::invokeMethod( this, "loadNextTrack", Qt::QueuedConnection,
Q_ARG( bool, preload ));
return;
}
@@ -858,8 +935,11 @@ AudioEngine::loadNextTrack()
{
if ( d->stopAfterTrack->track()->equals( d->currentTrack->track() ) )
{
d->stopAfterTrack.clear();
stop();
if ( !preload )
{
d->stopAfterTrack.clear();
stop();
}
return;
}
}
@@ -877,17 +957,24 @@ AudioEngine::loadNextTrack()
if ( d->playlist.data()->nextResult() )
{
result = d->playlist.data()->setSiblingResult( 1 );
setCurrentTrackPlaylist( d->playlist );
if ( preload )
{
result = d->playlist.data()->nextResult();
}
else
{
result = d->playlist.data()->setSiblingResult( 1 );
setCurrentTrackPlaylist( d->playlist );
}
}
}
if ( result )
{
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got next item, loading track";
loadTrack( result );
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got next item, loading track, preload:" << preload;
loadTrack( result, preload );
}
else
else if ( !preload )
{
if ( !d->playlist.isNull() && d->playlist.data()->retryMode() == Tomahawk::PlaylistModes::Retry )
d->waitingOnNewTrack = true;
@@ -956,7 +1043,7 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
if ( result )
{
loadTrack( result );
loadTrack( result, false );
}
else if ( !d->playlist.isNull() && d->playlist.data()->retryMode() == PlaylistModes::Retry )
{
@@ -1231,6 +1318,14 @@ AudioEngine::setStopAfterTrack( const query_ptr& query )
}
void
AudioEngine::setPreloadTrack( const Tomahawk::result_ptr& result )
{
Q_D( AudioEngine );
d->preloadedTrack = result;
}
void
AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
{
@@ -1257,7 +1352,6 @@ AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
}
}
void
AudioEngine::setState( AudioState state )
{

View File

@@ -135,10 +135,10 @@ public slots:
void toggleMute();
void play( const QUrl& url );
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery = Tomahawk::query_ptr() );
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query );
void playItem( const Tomahawk::artist_ptr& artist );
void playItem( const Tomahawk::album_ptr& album );
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery = Tomahawk::query_ptr());
void playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query);
void playItem( const Tomahawk::artist_ptr& artist);
void playItem( const Tomahawk::album_ptr& album);
void playPlaylistInterface( const Tomahawk::playlistinterface_ptr& playlist );
void setPlaylist( Tomahawk::playlistinterface_ptr playlist );
void setQueue( const Tomahawk::playlistinterface_ptr& queue );
@@ -182,21 +182,22 @@ signals:
void error( AudioEngine::AudioErrorCode errorCode );
private slots:
void loadTrack( const Tomahawk::result_ptr& result ); //async!
void loadTrack( const Tomahawk::result_ptr& result, bool preload ); //async!
void gotStreamUrl( const QVariantMap& data );
void gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply );
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url ); //only call from loadTrack kthxbi
void performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url, bool preload ); //only call from loadTrack kthxbi
void performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io, bool preload ); //only call from loadTrack or performLoadIODevice kthxbi
void loadPreviousTrack();
void loadNextTrack();
void loadNextTrack(bool preload = false);
void onVolumeChanged( qreal volume );
void timerTriggered( qint64 time );
void onPositionChanged( float new_position );
void setCurrentTrack( const Tomahawk::result_ptr& result );
void setPreloadTrack( const Tomahawk::result_ptr& result );
void onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type );
void onPlaylistNextTrackAvailable();

View File

@@ -28,9 +28,11 @@ public slots:
private:
QSharedPointer<QIODevice> input;
QSharedPointer<QIODevice> inputPreloaded;
Tomahawk::query_ptr stopAfterTrack;
Tomahawk::result_ptr currentTrack;
Tomahawk::result_ptr preloadedTrack;
Tomahawk::playlistinterface_ptr playlist;
Tomahawk::playlistinterface_ptr currentTrackPlaylist;
Tomahawk::playlistinterface_ptr queue;

View File

@@ -22,6 +22,7 @@
#include "AudioEngine.h"
#include "AudioOutput.h"
#include "TomahawkVersion.h"
#include "TomahawkSettings.h"
#include "audio/MediaStream.h"
#include "utils/Logger.h"
@@ -35,10 +36,12 @@
#include <vlc/libvlc.h>
#include <vlc/libvlc_media.h>
#include <vlc/libvlc_media_player.h>
#include <vlc/libvlc_events.h>
#include <vlc/libvlc_media_player.h>
#include <vlc/libvlc_version.h>
#include <algorithm>
AudioOutput* AudioOutput::s_instance = 0;
@@ -53,9 +56,11 @@ AudioOutput::AudioOutput( QObject* parent )
: QObject( parent )
, m_currentState( Stopped )
, m_currentStream( nullptr )
, m_preloadedStream( nullptr )
, m_seekable( true )
, m_muted( false )
, m_autoDelete( true )
, m_preloadedAutoDelete( true )
, m_volume( 1.0 )
, m_currentTime( 0 )
, m_totalTime( 0 )
@@ -65,6 +70,8 @@ AudioOutput::AudioOutput( QObject* parent )
, m_vlcInstance( nullptr )
, m_vlcPlayer( nullptr )
, m_vlcMedia( nullptr )
, m_vlcPreloadedPlayer( nullptr )
, m_vlcPreloadedMedia( nullptr )
{
tDebug() << Q_FUNC_INFO;
@@ -72,7 +79,7 @@ AudioOutput::AudioOutput( QObject* parent )
qRegisterMetaType<AudioOutput::AudioState>("AudioOutput::AudioState");
const char* vlcArgs[] = {
QVector<const char*> vlcArgs = {
"--ignore-config",
"--extraintf=logger",
qApp->arguments().contains( "--verbose" ) ? "--verbose=3" : "",
@@ -84,11 +91,28 @@ AudioOutput::AudioOutput( QObject* parent )
// "--no-snapshot-preview",
// "--services-discovery=''",
"--no-video",
//"--network-caching=10000",
//"--file-caching=10000",
//"--clock-synchro=0",
//"--cr-average=10000",
//"--clock-jitter=1",
"--no-xlib"
};
TomahawkSettings* s = TomahawkSettings::instance();
//Save a list of Latin1 byte arrays for additional args
auto additionalVlcArgs = s->vlcArguments().split(",");
QVector<QByteArray> additionalArgsChar;
std::transform(additionalVlcArgs.begin(), additionalVlcArgs.end(),
std::back_inserter(additionalArgsChar), [](QString str) { return str.toLatin1(); });
for (auto&& str : additionalArgsChar)
{
vlcArgs.append(str.constData());
}
// Create and initialize a libvlc instance (it should be done only once)
m_vlcInstance = libvlc_new( sizeof(vlcArgs) / sizeof(*vlcArgs), vlcArgs );
m_vlcInstance = libvlc_new( vlcArgs.size(), vlcArgs.constData() );
if ( !m_vlcInstance )
{
tDebug() << Q_FUNC_INFO << "libVLC: could not initialize";
@@ -103,37 +127,46 @@ AudioOutput::AudioOutput( QObject* parent )
#endif
m_vlcPlayer = libvlc_media_player_new( m_vlcInstance );
libvlc_event_manager_t* manager = libvlc_media_player_event_manager( m_vlcPlayer );
libvlc_event_type_t events[] = {
libvlc_MediaPlayerMediaChanged,
libvlc_MediaPlayerNothingSpecial,
libvlc_MediaPlayerOpening,
libvlc_MediaPlayerBuffering,
libvlc_MediaPlayerPlaying,
libvlc_MediaPlayerPaused,
libvlc_MediaPlayerStopped,
libvlc_MediaPlayerForward,
libvlc_MediaPlayerBackward,
libvlc_MediaPlayerEndReached,
libvlc_MediaPlayerEncounteredError,
libvlc_MediaPlayerTimeChanged,
libvlc_MediaPlayerPositionChanged,
libvlc_MediaPlayerSeekableChanged,
libvlc_MediaPlayerPausableChanged,
libvlc_MediaPlayerTitleChanged,
libvlc_MediaPlayerSnapshotTaken,
//libvlc_MediaPlayerLengthChanged,
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
libvlc_MediaPlayerAudioVolume,
libvlc_MediaPlayerMuted,
libvlc_MediaPlayerUnmuted,
#endif
libvlc_MediaPlayerVout
};
const int eventCount = sizeof(events) / sizeof( *events );
for ( int i = 0; i < eventCount; i++ )
m_vlcPreloadedPlayer = libvlc_media_player_new( m_vlcInstance );
for( auto player : { m_vlcPlayer, m_vlcPreloadedPlayer } )
{
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
libvlc_audio_set_mute( player, 0 );
{
libvlc_event_manager_t* current_manager = libvlc_media_player_event_manager( player );
libvlc_event_manager_t* new_manager = libvlc_media_player_event_manager( player );
static libvlc_event_type_t events[] = {
libvlc_MediaPlayerMediaChanged,
libvlc_MediaPlayerNothingSpecial,
libvlc_MediaPlayerOpening,
libvlc_MediaPlayerBuffering,
libvlc_MediaPlayerPlaying,
libvlc_MediaPlayerPaused,
libvlc_MediaPlayerStopped,
libvlc_MediaPlayerForward,
libvlc_MediaPlayerBackward,
libvlc_MediaPlayerEndReached,
libvlc_MediaPlayerEncounteredError,
libvlc_MediaPlayerTimeChanged,
libvlc_MediaPlayerPositionChanged,
libvlc_MediaPlayerSeekableChanged,
libvlc_MediaPlayerPausableChanged,
libvlc_MediaPlayerTitleChanged,
libvlc_MediaPlayerSnapshotTaken,
//libvlc_MediaPlayerLengthChanged,
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
libvlc_MediaPlayerAudioVolume,
libvlc_MediaPlayerMuted,
libvlc_MediaPlayerUnmuted,
#endif
libvlc_MediaPlayerVout
};
const int eventCount = sizeof(events) / sizeof( *events );
for ( int i = 0; i < eventCount; i++ )
{
libvlc_event_attach( new_manager, events[ i ], &AudioOutput::vlcEventCallback, this );
}
}
}
// HACK: play silent ogg file and set volume on that to workaround vlc not allowing to set volume before a file is played
@@ -141,7 +174,9 @@ AudioOutput::AudioOutput( QObject* parent )
Q_ASSERT( m_silenceFile.exists() );
Q_ASSERT( m_silenceFile.open( QIODevice::ReadOnly ) );
setCurrentSource( new MediaStream( &m_silenceFile, true ) );
setCurrentSource( new MediaStream( &m_silenceFile, true ), false );
setCurrentSource( new MediaStream( &m_silenceFile, true ), true );
libvlc_media_player_play( m_vlcPlayer );
#if QT_VERSION >= QT_VERSION_CHECK(5,4,0)
@@ -149,24 +184,71 @@ AudioOutput::AudioOutput( QObject* parent )
QTimer::singleShot( 15000, [&]()
{
if ( !m_initialized ) {
m_initialized = true;
m_initialized = 2;
emit initialized();
}
} );
#endif
}
void AudioOutput::switchToPreloadedMedia( void )
{
//Swap
auto tempPlayer = m_vlcPreloadedPlayer;
m_vlcPreloadedPlayer = m_vlcPlayer;
m_vlcPlayer = tempPlayer;
libvlc_media_player_stop( m_vlcPreloadedPlayer );
if ( m_vlcMedia != nullptr )
{
libvlc_media_release( m_vlcMedia );
}
//Now Media
{
if ( m_autoDelete && m_currentStream != nullptr )
{
delete m_currentStream;
}
m_vlcMedia = m_vlcPreloadedMedia;
m_vlcPreloadedMedia = nullptr;
m_currentStream = m_preloadedStream;
m_preloadedStream = nullptr;
m_autoDelete = m_preloadedAutoDelete;
m_totalTime = libvlc_media_get_duration( m_vlcMedia );
m_currentTime = 0;
m_justSeeked = false;
m_seekable = true;
}
libvlc_media_player_set_position( m_vlcPlayer, 0.0 );
}
AudioOutput::~AudioOutput()
{
tDebug() << Q_FUNC_INFO;
if ( m_vlcPreloadedPlayer != nullptr )
{
libvlc_media_player_stop( m_vlcPreloadedPlayer );
libvlc_media_player_release( m_vlcPreloadedPlayer );
m_vlcPreloadedPlayer = nullptr;
}
if ( m_vlcPlayer != nullptr )
{
libvlc_media_player_stop( m_vlcPlayer );
libvlc_media_player_release( m_vlcPlayer );
m_vlcPlayer = nullptr;
}
if ( m_vlcPreloadedMedia != nullptr )
{
libvlc_media_release( m_vlcPreloadedMedia );
m_vlcPreloadedMedia = nullptr;
}
if ( m_vlcMedia != nullptr )
{
libvlc_media_release( m_vlcMedia );
@@ -188,11 +270,19 @@ AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
setVolume( volume() );
setMuted( isMuted() );
m_initialized = true;
m_silenceFile.close();
m_initialized ++;
tDebug() << Q_FUNC_INFO << "Init OK";
emit initialized();
if (m_initialized >=2)
{
m_silenceFile.close();
emit initialized();
}
else
{
switchToPreloadedMedia();
libvlc_media_player_play( m_vlcPlayer );
}
break;
default:
@@ -202,23 +292,26 @@ AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
void
AudioOutput::setAutoDelete( bool ad )
AudioOutput::setAutoDelete( bool ad, bool preload )
{
m_autoDelete = ad;
if (preload)
m_preloadedAutoDelete = ad;
else
m_autoDelete = ad;
}
void
AudioOutput::setCurrentSource( const QUrl& stream )
AudioOutput::setCurrentSource( const QUrl& stream, bool preload )
{
setCurrentSource( new MediaStream( stream ) );
setCurrentSource( new MediaStream( stream ), preload );
}
void
AudioOutput::setCurrentSource( QIODevice* stream )
AudioOutput::setCurrentSource( QIODevice* stream, bool preload )
{
setCurrentSource( new MediaStream( stream ) );
setCurrentSource( new MediaStream( stream ), preload );
}
@@ -238,29 +331,24 @@ readDoneCallback( void* data, const char* cookie, size_t bufferSize, void* buffe
void
AudioOutput::setCurrentSource( MediaStream* stream )
AudioOutput::setCurrentSource( MediaStream* stream, bool preload )
{
tDebug() << Q_FUNC_INFO;
tDebug() << Q_FUNC_INFO << ", preload = " << preload;
setState( Loading );
if ( !preload )
setState( Loading );
if ( m_vlcMedia != nullptr )
{
// Ensure playback is stopped, then release media
libvlc_media_player_stop( m_vlcPlayer );
libvlc_media_release( m_vlcMedia );
m_vlcMedia = nullptr;
if ( m_vlcPreloadedMedia ) {
libvlc_media_player_stop( m_vlcPreloadedPlayer );
libvlc_media_release( m_vlcPreloadedMedia );
m_vlcPreloadedMedia = nullptr;
}
if ( m_autoDelete && m_currentStream != nullptr )
if ( m_preloadedAutoDelete && m_preloadedStream != nullptr )
{
delete m_currentStream;
delete m_preloadedStream;
}
m_currentStream = stream;
m_totalTime = 0;
m_currentTime = 0;
m_justSeeked = false;
m_seekable = true;
m_preloadedStream = stream;
QByteArray url;
switch ( stream->type() )
@@ -294,34 +382,19 @@ AudioOutput::setCurrentSource( MediaStream* stream )
tDebug() << Q_FUNC_INFO << "MediaStream::Final Url:" << url;
m_vlcMedia = libvlc_media_new_location( m_vlcInstance, url.constData() );
libvlc_event_manager_t* manager = libvlc_media_event_manager( m_vlcMedia );
libvlc_event_type_t events[] = {
libvlc_MediaDurationChanged,
};
const int eventCount = sizeof(events) / sizeof( *events );
for ( int i = 0; i < eventCount; i++ )
m_vlcPreloadedMedia = libvlc_media_new_location( m_vlcInstance, url.constData() );
if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice )
{
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
}
libvlc_media_player_set_media( m_vlcPlayer, m_vlcMedia );
if ( stream->type() == MediaStream::Url )
{
m_totalTime = libvlc_media_get_duration( m_vlcMedia );
}
else if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice )
{
libvlc_media_add_option_flag(m_vlcMedia, "imem-cat=4", libvlc_media_option_trusted);
const char* imemData = QString( "imem-data=%1" ).arg( (uintptr_t)stream ).toLatin1().constData();
libvlc_media_add_option_flag(m_vlcMedia, imemData, libvlc_media_option_trusted);
const char* imemGet = QString( "imem-get=%1" ).arg( (uintptr_t)&readCallback ).toLatin1().constData();
libvlc_media_add_option_flag(m_vlcMedia, imemGet, libvlc_media_option_trusted);
const char* imemRelease = QString( "imem-release=%1" ).arg( (uintptr_t)&readDoneCallback ).toLatin1().constData();
libvlc_media_add_option_flag(m_vlcMedia, imemRelease, libvlc_media_option_trusted);
const char* imemSeek = QString( "imem-seek=%1" ).arg( (uintptr_t)&MediaStream::seekCallback ).toLatin1().constData();
libvlc_media_add_option_flag(m_vlcMedia, imemSeek, libvlc_media_option_trusted);
QString tempString;
libvlc_media_add_option_flag(m_vlcPreloadedMedia, "imem-cat=4", libvlc_media_option_trusted);
tempString = QString( "imem-data=%1" ).arg( (uintptr_t)stream );
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
tempString = QString( "imem-get=%1" ).arg( (uintptr_t)&readCallback );
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
tempString = QString( "imem-release=%1" ).arg( (uintptr_t)&readDoneCallback );
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
tempString = QString( "imem-seek=%1" ).arg( (uintptr_t)&MediaStream::seekCallback );
libvlc_media_add_option_flag(m_vlcPreloadedMedia, tempString.toLatin1().constData(), libvlc_media_option_trusted);
}
if ( qApp->arguments().contains( "--chromecast-ip" ) )
{
@@ -337,7 +410,7 @@ AudioOutput::setCurrentSource( MediaStream* stream )
{
QString castIP = qApp->arguments().at( qApp->arguments().indexOf( "--chromecast-ip" ) + 1 );
QString sout( ":sout=#transcode{vcodec=none,acodec=vorb,ab=320,channels=2,samplerate=44100}:chromecast{ip=%1,mux=webm}" );
libvlc_media_add_option( m_vlcMedia, sout.arg( castIP ).toLatin1().constData() );
libvlc_media_add_option( m_vlcPreloadedMedia, sout.arg( castIP ).toLatin1().constData() );
}
else
{
@@ -345,6 +418,24 @@ AudioOutput::setCurrentSource( MediaStream* stream )
}
}
libvlc_event_manager_t* manager = libvlc_media_event_manager( m_vlcPreloadedMedia );
static libvlc_event_type_t events[] = {
libvlc_MediaDurationChanged,
};
const int eventCount = sizeof(events) / sizeof( *events );
for ( int i = 0; i < eventCount; i++ )
{
libvlc_event_attach( manager, events[ i ], &AudioOutput::vlcEventCallback, this );
}
libvlc_media_player_set_media( m_vlcPreloadedPlayer, m_vlcPreloadedMedia );
libvlc_audio_set_volume( m_vlcPreloadedPlayer, 0.0 );
libvlc_media_player_play( m_vlcPreloadedPlayer );
if ( !preload )
switchToPreloadedMedia();
// setState( Stopped );
}
@@ -352,7 +443,7 @@ AudioOutput::setCurrentSource( MediaStream* stream )
bool
AudioOutput::isInitialized() const
{
return m_initialized;
return m_initialized > 1;
}
@@ -505,7 +596,7 @@ AudioOutput::seek( qint64 milliseconds )
bool
AudioOutput::isSeekable() const
{
// tDebug() << Q_FUNC_INFO << m_seekable << m_havePosition << m_totalTime << libvlc_media_player_is_seekable( m_vlcPlayer );
tDebug() << Q_FUNC_INFO << m_seekable << m_havePosition << m_totalTime << libvlc_media_player_is_seekable( m_vlcPlayer );
return m_havePosition || (libvlc_media_player_is_seekable( m_vlcPlayer ) && m_totalTime > 0 );
}
@@ -555,64 +646,107 @@ AudioOutput::setVolume( qreal vol )
void
AudioOutput::onVlcEvent( const libvlc_event_t* event )
{
switch ( event->type )
if ( event->p_obj == m_vlcPlayer || event->p_obj == m_vlcMedia )
{
case libvlc_MediaPlayerTimeChanged:
setCurrentTime( event->u.media_player_time_changed.new_time );
break;
case libvlc_MediaPlayerPositionChanged:
setCurrentPosition( event->u.media_player_position_changed.new_position );
break;
case libvlc_MediaPlayerSeekableChanged:
// tDebug() << Q_FUNC_INFO << " : seekable changed : " << event->u.media_player_seekable_changed.new_seekable;
break;
case libvlc_MediaDurationChanged:
setTotalTime( event->u.media_duration_changed.new_duration );
break;
case libvlc_MediaPlayerLengthChanged:
// tDebug() << Q_FUNC_INFO << " : length changed : " << event->u.media_player_length_changed.new_length;
break;
case libvlc_MediaPlayerPlaying:
setState( Playing );
break;
case libvlc_MediaPlayerPaused:
setState( Paused );
break;
case libvlc_MediaPlayerEndReached:
setState( Stopped );
break;
case libvlc_MediaPlayerEncounteredError:
tDebug() << Q_FUNC_INFO << "LibVLC error: MediaPlayerEncounteredError. Stopping";
// Don't call stop() here - it will deadlock libvlc
setState( Error );
break;
switch ( event->type )
{
case libvlc_MediaPlayerTimeChanged:
setCurrentTime( event->u.media_player_time_changed.new_time );
break;
case libvlc_MediaPlayerPositionChanged:
setCurrentPosition( event->u.media_player_position_changed.new_position );
break;
case libvlc_MediaPlayerSeekableChanged:
// tDebug() << Q_FUNC_INFO << " : seekable changed : " << event->u.media_player_seekable_changed.new_seekable;
break;
case libvlc_MediaDurationChanged:
setTotalTime( event->u.media_duration_changed.new_duration );
break;
case libvlc_MediaPlayerLengthChanged:
// tDebug() << Q_FUNC_INFO << " : length changed : " << event->u.media_player_length_changed.new_length;
break;
case libvlc_MediaPlayerPlaying:
setState( Playing );
break;
case libvlc_MediaPlayerPaused:
setState( Paused );
break;
case libvlc_MediaPlayerEndReached:
setState( Stopped );
break;
case libvlc_MediaPlayerEncounteredError:
tDebug() << Q_FUNC_INFO << "LibVLC error: MediaPlayerEncounteredError. Stopping";
// Don't call stop() here - it will deadlock libvlc
setState( Error );
break;
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
case libvlc_MediaPlayerAudioVolume:
m_volume = event->u.media_player_audio_volume.volume;
emit volumeChanged( volume() );
break;
case libvlc_MediaPlayerMuted:
m_muted = true;
emit mutedChanged( true );
break;
case libvlc_MediaPlayerUnmuted:
m_muted = false;
emit mutedChanged( false );
break;
case libvlc_MediaPlayerAudioVolume:
m_volume = event->u.media_player_audio_volume.volume;
tDebug() << Q_FUNC_INFO << "Got signal in current player that volume changed to:" << m_volume;
emit volumeChanged( volume() );
break;
case libvlc_MediaPlayerMuted:
m_muted = true;
emit mutedChanged( true );
break;
case libvlc_MediaPlayerUnmuted:
m_muted = false;
emit mutedChanged( false );
break;
#endif
case libvlc_MediaPlayerNothingSpecial:
case libvlc_MediaPlayerOpening:
case libvlc_MediaPlayerBuffering:
case libvlc_MediaPlayerStopped:
case libvlc_MediaPlayerVout:
case libvlc_MediaPlayerMediaChanged:
case libvlc_MediaPlayerForward:
case libvlc_MediaPlayerBackward:
case libvlc_MediaPlayerPausableChanged:
case libvlc_MediaPlayerTitleChanged:
case libvlc_MediaPlayerSnapshotTaken:
default:
break;
case libvlc_MediaPlayerNothingSpecial:
case libvlc_MediaPlayerOpening:
case libvlc_MediaPlayerBuffering:
case libvlc_MediaPlayerStopped:
case libvlc_MediaPlayerVout:
case libvlc_MediaPlayerMediaChanged:
case libvlc_MediaPlayerForward:
case libvlc_MediaPlayerBackward:
case libvlc_MediaPlayerPausableChanged:
case libvlc_MediaPlayerTitleChanged:
case libvlc_MediaPlayerSnapshotTaken:
default:
break;
}
}
else
{
tDebug() << "Event for preloaded: " << libvlc_event_type_name(event->type);
switch ( event->type )
{
case libvlc_MediaPlayerPausableChanged:
case libvlc_MediaPlayerPlaying:
case libvlc_MediaPlayerMediaChanged:
case libvlc_MediaPlayerTitleChanged:
case libvlc_MediaPlayerSeekableChanged:
case libvlc_MediaDurationChanged:
case libvlc_MediaPlayerPositionChanged:
case libvlc_MediaPlayerPaused:
case libvlc_MediaPlayerBuffering:
libvlc_media_player_set_pause( m_vlcPreloadedPlayer, 1 );
libvlc_audio_set_volume( m_vlcPreloadedPlayer, 0.0 );
libvlc_media_player_set_position( m_vlcPreloadedPlayer, 0.0 );
break;
case libvlc_MediaPlayerTimeChanged:
case libvlc_MediaPlayerLengthChanged:
case libvlc_MediaPlayerOpening:
case libvlc_MediaPlayerEndReached:
case libvlc_MediaPlayerEncounteredError:
//TODO
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 2, 2, 0))
case libvlc_MediaPlayerAudioVolume:
case libvlc_MediaPlayerMuted:
case libvlc_MediaPlayerUnmuted:
#endif
case libvlc_MediaPlayerNothingSpecial:
case libvlc_MediaPlayerStopped:
case libvlc_MediaPlayerVout:
case libvlc_MediaPlayerForward:
case libvlc_MediaPlayerBackward:
case libvlc_MediaPlayerSnapshotTaken:
default:
break;
}
}
}

View File

@@ -49,9 +49,10 @@ public:
bool isInitialized() const;
AudioState state() const;
void setCurrentSource( const QUrl& stream );
void setCurrentSource( QIODevice* stream );
void setCurrentSource( MediaStream* stream );
void setCurrentSource( const QUrl& stream, bool preload );
void setCurrentSource( QIODevice* stream, bool preload );
void setCurrentSource( MediaStream* stream, bool preload );
void setPreloadedSourceAsCurrent( void );
void play();
void pause();
@@ -65,13 +66,15 @@ public:
qreal volume() const;
qint64 currentTime() const;
qint64 totalTime() const;
void setAutoDelete ( bool ad );
void setAutoDelete ( bool ad, bool preload );
void setDspCallback( std::function< void( int, int, float*, int, int ) > cb );
static AudioOutput* instance();
libvlc_instance_t* vlcInstance() const;
void switchToPreloadedMedia( void );
public slots:
signals:
@@ -90,6 +93,7 @@ private:
void setCurrentPosition( float position );
void setTotalTime( qint64 time );
void onVlcEvent( const libvlc_event_t* event );
static void vlcEventCallback( const libvlc_event_t* event, void* opaque );
static void s_dspCallback( int frameNumber, float* samples, int nb_channels, int nb_samples );
@@ -97,9 +101,11 @@ private:
static AudioOutput* s_instance;
AudioState m_currentState;
MediaStream* m_currentStream;
MediaStream* m_preloadedStream;
bool m_seekable;
bool m_muted;
bool m_autoDelete;
bool m_preloadedAutoDelete;
bool m_havePosition;
bool m_haveTiming;
qreal m_volume;
@@ -107,7 +113,7 @@ private:
qint64 m_totalTime;
bool m_justSeeked;
bool m_initialized;
int m_initialized;
QFile m_silenceFile;
std::function< void( int state, int frameNumber, float* samples, int nb_channels, int nb_samples ) > dspPluginCallback;
@@ -115,6 +121,9 @@ private:
libvlc_instance_t* m_vlcInstance;
libvlc_media_player_t* m_vlcPlayer;
libvlc_media_t* m_vlcMedia;
libvlc_media_player_t* m_vlcBackPlayer;
libvlc_media_player_t* m_vlcPreloadedPlayer;
libvlc_media_t* m_vlcPreloadedMedia;
};
#endif // AUDIOOUTPUT_H

View File

@@ -151,7 +151,6 @@ int
MediaStream::readDoneCallback ( const char *cookie, size_t bufferSize, void *buffer )
{
Q_UNUSED(cookie);
Q_UNUSED(bufferSize);
if ( ( m_type == Stream ) && buffer != nullptr && bufferSize > 0 ) {
delete[] reinterpret_cast< char* >( buffer );

View File

@@ -128,10 +128,13 @@ DatabaseCollection::playlists()
QList< dynplaylist_ptr >
DatabaseCollection::autoPlaylists()
{
// echonest is dead, disable all echonest code
/*
if ( Collection::autoPlaylists().isEmpty() )
{
loadAutoPlaylists();
}
*/
return Collection::autoPlaylists();
}
@@ -140,10 +143,13 @@ DatabaseCollection::autoPlaylists()
QList< dynplaylist_ptr >
DatabaseCollection::stations()
{
// echonest is dead, disable all echonest code
/*
if ( Collection::stations().isEmpty() )
{
loadStations();
}
*/
return Collection::stations();
}

View File

@@ -59,10 +59,10 @@ public:
void setLimit( unsigned int amount ) { m_amount = amount; }
void setSortOrder( DatabaseCommand_AllArtists::SortOrder order ) { m_sortOrder = order; }
void setSortDescending( bool descending ) { m_sortDescending = descending; }
void setFilter( const QString& filter ) { m_filter = filter; }
void setFilter( const QString& filter ) override { m_filter = filter; }
signals:
void artists( const QList<Tomahawk::artist_ptr>& );
void artists( const QList<Tomahawk::artist_ptr>& ) override;
void done();
private:

View File

@@ -74,7 +74,7 @@ public:
signals:
void tracks( const QList<Tomahawk::query_ptr>&, const QVariant& data );
void tracks( const QList<Tomahawk::query_ptr>& );
void tracks( const QList<Tomahawk::query_ptr>& ) override;
void done( const Tomahawk::collection_ptr& );
private:

View File

@@ -21,7 +21,6 @@
#include "Source.h"
#include "network/Servent.h"
#include "SourceList.h"
#include "EchonestCatalogSynchronizer.h"
namespace Tomahawk
{
@@ -76,9 +75,11 @@ DatabaseCommand_SetCollectionAttributes::exec( DatabaseImpl *lib )
void
DatabaseCommand_SetCollectionAttributes::postCommitHook()
{
/*
if ( m_type == EchonestSongCatalog ||
m_type == EchonestArtistCatalog )
Tomahawk::EchonestCatalogSynchronizer::instance()->knownCatalogsChanged();
*/
if ( source()->isLocal() )
Servent::instance()->triggerDBSync();

View File

@@ -34,11 +34,11 @@ public:
explicit DatabaseResolver( int weight );
QString name() const override;
virtual unsigned int weight() const { return m_weight; }
virtual unsigned int timeout() const { return 0; }
virtual unsigned int weight() const override{ return m_weight; }
virtual unsigned int timeout() const override{ return 0; }
public slots:
virtual void resolve( const Tomahawk::query_ptr& query );
virtual void resolve( const Tomahawk::query_ptr& query ) override;
private slots:
void gotResults( const Tomahawk::QID qid, QList< Tomahawk::result_ptr> results );

View File

@@ -1,21 +1,20 @@
/*
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LocalCollection.h"

View File

@@ -1,21 +1,20 @@
/*
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOCALCOLLECTION_H
#define LOCALCOLLECTION_H

View File

@@ -240,7 +240,7 @@ MetadataEditor::loadResult( const Tomahawk::result_ptr& result )
return;
m_result = result;
setEditable( result->resolvedByCollection() && result->resolvedByCollection()->isLocal() );
setEditable( result->isLocal() );
setTitle( result->track()->track() );
setArtist( result->track()->artist() );
@@ -250,7 +250,7 @@ MetadataEditor::loadResult( const Tomahawk::result_ptr& result )
setYear( result->track()->year() );
setBitrate( result->bitrate() );
if ( result->resolvedByCollection() && result->resolvedByCollection()->isLocal() )
if ( result->isLocal() )
{
QString furl = m_result->url();
if ( furl.startsWith( "file://" ) )

View File

@@ -40,6 +40,11 @@ using namespace Tomahawk;
void
DirLister::go()
{
if ( m_dirs.isEmpty() )
{
emit finished();
return;
}
foreach ( const QString& dir, m_dirs )
{
m_opcount++;

View File

@@ -42,8 +42,8 @@ public:
explicit DBSyncConnection( Servent* s, const Tomahawk::source_ptr& src );
virtual ~DBSyncConnection();
void setup();
Connection* clone();
void setup() override;
Connection* clone() override;
signals:
void stateChanged( Tomahawk::DBSyncConnectionState newstate, Tomahawk::DBSyncConnectionState oldstate, const QString& info );

View File

@@ -28,6 +28,7 @@
#include "utils/TomahawkUtilsGui.h"
#include "utils/DpiScaler.h"
#include "ViewManager.h"
#include "widgets/DownloadButton.h"
#include <QLabel>
#include <QVBoxLayout>
@@ -164,6 +165,10 @@ ColumnViewPreviewWidget::ColumnViewPreviewWidget( ColumnView* parent )
m_ageValue->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
gridLayout->addWidget( m_ageValue, 4, 1 );
m_downloadButton = new DownloadButton( this );
mainLayout->addWidget( m_downloadButton );
mainLayout->addStretch();
TomahawkUtils::unmarginLayout( mainLayout );
@@ -217,6 +222,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query )
m_bitrateValue->setText( tr( "%1 kbps" ).arg( query->results().first()->bitrate() ) );
m_durationValue->setText( TomahawkUtils::timeToString( query->track()->duration() ) );
m_ageValue->setText( TomahawkUtils::ageToString( QDateTime::fromTime_t( query->results().first()->modificationTime() ) ) );
m_downloadButton->setQuery( query );
m_yearValue->setVisible( query->track()->year() > 0 );
m_yearLabel->setVisible( query->track()->year() > 0 );
@@ -226,6 +232,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query )
m_durationValue->setVisible( query->track()->duration() > 0 );
m_ageLabel->setVisible( query->results().first()->modificationTime() > 0 );
m_ageValue->setVisible( query->results().first()->modificationTime() > 0 );
m_downloadButton->setVisible( true );
}
else
{
@@ -237,6 +244,7 @@ ColumnViewPreviewWidget::setQuery( const Tomahawk::query_ptr& query )
m_durationValue->setVisible( false );
m_ageLabel->setVisible( false );
m_ageValue->setVisible( false );
m_downloadButton->setVisible( false );
}
setMinimumHeight( sizeHint().height() );

View File

@@ -30,6 +30,7 @@ class QueryLabel;
class PlayableCover;
class QLabel;
class ScrollingLabel;
class DownloadButton;
class DLLEXPORT ColumnViewPreviewWidget : public QWidget
{
@@ -71,6 +72,8 @@ private:
ScrollingLabel* m_trackLabel;
QueryLabel* m_artistLabel;
DownloadButton* m_downloadButton;
};
#endif // COLUMNVIEWPREVIEWWIDGET_H

View File

@@ -19,16 +19,6 @@
#include "GridItemDelegate.h"
#include <QApplication>
#include <QDesktopServices>
#include <QPainter>
#include <QAbstractItemView>
#include <QMouseEvent>
#include <QTimeLine>
#include "DownloadManager.h"
#include "DownloadJob.h"
#include "Artist.h"
#include "Query.h"
#include "Result.h"
@@ -39,17 +29,22 @@
#include "playlist/PlayableItem.h"
#include "playlist/PlayableProxyModel.h"
#include "widgets/HoverControls.h"
#include "widgets/DropDownButton.h"
#include "widgets/DownloadButton.h"
#include "widgets/ImageButton.h"
#include "utils/TomahawkStyle.h"
#include "utils/TomahawkUtilsGui.h"
#include "utils/PixmapDelegateFader.h"
#include "utils/Closure.h"
#include "utils/AnimatedSpinner.h"
#include "utils/WebPopup.h"
#include "utils/DpiScaler.h"
#include "utils/Logger.h"
#include <QApplication>
#include <QPainter>
#include <QAbstractItemView>
#include <QMouseEvent>
#include <QTimeLine>
namespace {
static const int FADE_DURATION = 400;
};
@@ -325,41 +320,10 @@ GridItemDelegate::paint( QPainter* painter, const QStyleOptionViewItem& option,
QRect r = textRect;
r.setY( textRect.y() + textRect.height() + 8 );
r.setHeight( 32 );
m_buyButtonRects[ index ] = r;
QString text;
if ( item->result() &&
( ( !item->result()->downloadFormats().isEmpty() && !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() ) ||
( item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished ) ) )
if( DownloadButton::drawPrimitive(painter, r, item->query(), m_hoveringOverBuyButton == index ) )
{
text = tr( "View in Finder" );
}
else if ( item->query() && item->query()->numResults( true ) && !item->query()->results().first()->downloadFormats().isEmpty() )
{
text = tr( "Download %1" ).arg( item->query()->results().first()->downloadFormats().first().extension.toUpper() );
}
else if ( item->query()->numResults( true ) && !item->query()->results().first()->purchaseUrl().isEmpty() )
{
text = tr( "Buy" );
}
if ( !item->result() || !item->result()->downloadJob() )
{
if ( !text.isEmpty() )
DropDownButton::drawPrimitive( painter, r, text, m_hoveringOverBuyButton == index, false );
else
m_buyButtonRects.remove( index );
}
else
{
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND );
painter->drawRect( r.adjusted( 2, 2, -2, -2 ) );
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
QRect fillp = r.adjusted( 3, 3, -3, -3 );
fillp.setWidth( float(fillp.width()) * ( float(item->result()->downloadJob()->progressPercentage()) / 100.0 ) );
painter->drawRect( fillp );
m_buyButtonRects[ index ] = r;
}
}
}
@@ -621,23 +585,7 @@ GridItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, const Q
if ( hoveringBuyButton )
{
if ( event->type() == QEvent::MouseButtonRelease )
{
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( index ) );
if ( !item )
return false;
if ( item->query() && item->query()->numResults( true ) && !item->query()->results().first()->downloadFormats().isEmpty() )
{
m_view->edit( index );
return true;
}
else
{
WebPopup* popup = new WebPopup( item->query()->results().first()->purchaseUrl(), QSize( 400, 800 ) );
connect( item->query()->results().first().data(), SIGNAL( destroyed() ), popup, SLOT( close() ) );
}
}
return DownloadButton::handleEditorEvent( event, m_view, m_model, index );
}
return false;
@@ -867,63 +815,7 @@ GridItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem& opt
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
if ( item->result() && !item->result()->downloadFormats().isEmpty() &&
!DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() )
{
QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ) ).absolutePath() ) );
}
else if ( item->result() && item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished )
{
QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( item->result()->downloadJob()->localFile() ).absolutePath() ) );
}
else if ( item->result() &&
!item->result()->downloadFormats().isEmpty() && !item->result()->downloadJob() )
{
QStringList formats;
foreach ( const DownloadFormat& format, item->result()->downloadFormats() )
{
formats << tr( "Download %1" ).arg( format.extension.toUpper() );
}
DropDownButton* editor = new DropDownButton( parent );
editor->addItems( formats );
NewClosure( editor, SIGNAL( clicked() ),
const_cast<GridItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
NewClosure( editor, SIGNAL( activated( int ) ),
const_cast<GridItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
return editor;
}
return 0;
}
void
GridItemDelegate::addDownloadJob( const QModelIndex& index, QWidget* editor )
{
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
m_view->closePersistentEditor( index );
DropDownButton* cb = static_cast< DropDownButton* >(editor);
if ( !item->result()->downloadFormats().isEmpty() )
DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().at( cb->currentIndex() ) ) );
}
void
GridItemDelegate::closeEditor( const QModelIndex& index, QWidget* editor )
{
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
m_view->closePersistentEditor( index );
DropDownButton* cb = static_cast< DropDownButton* >(editor);
editor->deleteLater();
return DownloadButton::handleCreateEditor( parent, item->query(), m_view, index );
}
@@ -932,13 +824,13 @@ GridItemDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionViewI
{
QStyledItemDelegate::updateEditorGeometry( editor, option, index );
DropDownButton* comboBox = static_cast<DropDownButton*>(editor);
DownloadButton* comboBox = static_cast<DownloadButton*>(editor);
comboBox->resize( option.rect.size() - QSize( 8, 0 ) );
comboBox->move( option.rect.x() + 4, option.rect.y() );
if ( m_downloadDropDownRects.contains( index ) )
if ( m_buyButtonRects.contains( index ) )
{
editor->setGeometry( m_downloadDropDownRects.value( index ) );
editor->setGeometry( m_buyButtonRects.value( index ) );
}
if ( !comboBox->property( "shownPopup" ).toBool() )

View File

@@ -87,9 +87,6 @@ private slots:
void fadingFrameChanged( const QPersistentModelIndex& );
void fadingFrameFinished( const QPersistentModelIndex& );
void closeEditor( const QModelIndex& index, QWidget* editor );
void addDownloadJob( const QModelIndex& index, QWidget* editor );
private:
QTimeLine* createTimeline( QTimeLine::Direction direction, int startFrame = 0 );
void clearButtons();
@@ -104,7 +101,6 @@ private:
mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects;
mutable QHash< QPersistentModelIndex, QRect > m_albumNameRects;
mutable QHash< QPersistentModelIndex, QRect > m_buyButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_downloadDropDownRects;
mutable QHash< QPersistentModelIndex, QSharedPointer< Tomahawk::PixmapDelegateFader > > m_covers;
QPersistentModelIndex m_hoverIndex;

View File

@@ -59,7 +59,7 @@ public:
PlayableModel* sourceModel() const { return m_model; }
virtual void setSourcePlayableModel( PlayableModel* sourceModel );
virtual void setSourceModel( QAbstractItemModel* model );
virtual void setSourceModel( QAbstractItemModel* model ) override;
virtual bool isLoading() const;
@@ -91,9 +91,9 @@ public:
QList< double > columnWeights() const;
virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const;
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const;
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const;
virtual int columnCount( const QModelIndex& parent = QModelIndex() ) const override;
virtual QVariant data( const QModelIndex& index, int role = Qt::DisplayRole ) const override;
virtual QVariant headerData( int section, Qt::Orientation orientation, int role ) const override;
virtual void setFilter( const QString& pattern );
virtual void updateDetailedInfo( const QModelIndex& index );
@@ -120,7 +120,7 @@ signals:
protected:
bool filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent ) const Q_DECL_OVERRIDE;
virtual bool lessThan( const QModelIndex& left, const QModelIndex& right ) const;
virtual bool lessThan( const QModelIndex& left, const QModelIndex& right ) const override;
Tomahawk::playlistinterface_ptr m_playlistInterface;

View File

@@ -20,15 +20,6 @@
#include "PlaylistItemDelegate.h"
#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include <QDateTime>
#include <QDesktopServices>
#include <QMouseEvent>
#include <QPainter>
#include <QDesktopServices>
#include <QToolTip>
#include "Query.h"
#include "Result.h"
#include "Artist.h"
@@ -36,8 +27,6 @@
#include "Source.h"
#include "SourceList.h"
#include "DownloadManager.h"
#include "DownloadJob.h"
#include "PlayableModel.h"
#include "PlayableItem.h"
#include "PlayableProxyModel.h"
@@ -45,16 +34,22 @@
#include "ViewHeader.h"
#include "ViewManager.h"
#include "widgets/DropDownButton.h"
#include "widgets/DownloadButton.h"
#include "audio/AudioEngine.h"
#include "utils/ImageRegistry.h"
#include "utils/PixmapDelegateFader.h"
#include "utils/Closure.h"
#include "utils/TomahawkStyle.h"
#include "utils/TomahawkUtilsGui.h"
#include "utils/WebPopup.h"
#include "utils/Logger.h"
#include <QAbstractTextDocumentLayout>
#include <QApplication>
#include <QDateTime>
#include <QMouseEvent>
#include <QPainter>
#include <QToolTip>
using namespace Tomahawk;
@@ -125,63 +120,7 @@ PlaylistItemDelegate::createEditor( QWidget* parent, const QStyleOptionViewItem&
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
if ( /*index.column() == PlayableModel::Download &&*/ item->result() && !item->result()->downloadFormats().isEmpty() &&
!DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() )
{
QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ) ).absolutePath() ) );
}
else if ( /*index.column() == PlayableModel::Download &&*/ item->result() && item->result()->downloadJob() && item->result()->downloadJob()->state() == DownloadJob::Finished )
{
QDesktopServices::openUrl( QUrl::fromLocalFile( QFileInfo( item->result()->downloadJob()->localFile() ).absolutePath() ) );
}
else if ( /*index.column() == PlayableModel::Download &&*/ item->result() &&
!item->result()->downloadFormats().isEmpty() && !item->result()->downloadJob() )
{
QStringList formats;
foreach ( const DownloadFormat& format, item->result()->downloadFormats() )
{
formats << tr( "Download %1" ).arg( format.extension );
}
DropDownButton* editor = new DropDownButton( parent );
editor->addItems( formats );
NewClosure( editor, SIGNAL( clicked() ),
const_cast<PlaylistItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
NewClosure( editor, SIGNAL( activated( int ) ),
const_cast<PlaylistItemDelegate*>(this), SLOT( addDownloadJob( const QModelIndex&, QWidget* ) ), index, (QWidget*)editor );
return editor;
}
return 0;
}
void
PlaylistItemDelegate::addDownloadJob( const QModelIndex& index, QWidget* editor )
{
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
m_view->closePersistentEditor( index );
DropDownButton* cb = static_cast< DropDownButton* >(editor);
if ( !item->result()->downloadFormats().isEmpty() )
DownloadManager::instance()->addJob( item->result()->toDownloadJob( item->result()->downloadFormats().at( cb->currentIndex() ) ) );
}
void
PlaylistItemDelegate::closeEditor( const QModelIndex& index, QWidget* editor )
{
PlayableItem* item = m_model->itemFromIndex( m_model->mapToSource( index ) );
Q_ASSERT( item );
m_view->closePersistentEditor( index );
DropDownButton* cb = static_cast< DropDownButton* >(editor);
editor->deleteLater();
return DownloadButton::handleCreateEditor( parent, item->query(), m_view, index );
}
@@ -190,7 +129,7 @@ PlaylistItemDelegate::updateEditorGeometry( QWidget* editor, const QStyleOptionV
{
QStyledItemDelegate::updateEditorGeometry( editor, option, index );
DropDownButton* comboBox = static_cast<DropDownButton*>(editor);
DownloadButton* comboBox = static_cast<DownloadButton*>(editor);
comboBox->resize( option.rect.size() - QSize( 8, 0 ) );
comboBox->move( option.rect.x() + 4, option.rect.y() );
@@ -277,69 +216,7 @@ PlaylistItemDelegate::paintDetailed( QPainter* painter, const QStyleOptionViewIt
else */
if ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download )
{
if ( item->result() && !item->result()->downloadFormats().isEmpty() )
{
QStyleOptionComboBox optc;
optc.rect = opt.rect.adjusted( 4, 0, -4, 0 );
optc.editable = false;
optc.currentText = tr( "Download %1" ).arg( item->result()->downloadFormats().first().extension );
optc.palette = m_view->palette();
if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active )
optc.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled;
else
optc.state = QStyle::State_Active | QStyle::State_Enabled;
if ( !DownloadManager::instance()->localFileForDownload( item->result()->downloadFormats().first().url.toString() ).isEmpty() )
{
painter->setPen( opt.palette.text().color() );
const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, opt.rect.width() - 3 );
painter->drawText( opt.rect, text, textOption );
}
else if ( !item->result()->downloadJob() )
{
DropDownButton::drawPrimitive( painter, optc.rect, optc.currentText, hoveringOver() == index, true );
/* QApplication::style()->drawComplexControl( QStyle::CC_ComboBox, &optc, painter, 0 );
optc.rect.adjust( 4, 0, 0, 0 );
QApplication::style()->drawControl( QStyle::CE_ComboBoxLabel, &optc, painter, 0 );*/
}
else
{
if ( item->result()->downloadJob()->state() == DownloadJob::Finished )
{
painter->setPen( opt.palette.text().color() );
const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, opt.rect.width() - 3 );
painter->drawText( opt.rect, text, textOption );
}
else
{
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND );
painter->drawRect( optc.rect.adjusted( 2, 2, -2, -2 ) );
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
QRect fillp = optc.rect.adjusted( 3, 3, -3, -3 );
fillp.setWidth( float(fillp.width()) * ( float(item->result()->downloadJob()->progressPercentage()) / 100.0 ) );
painter->drawRect( fillp );
/* QStyleOptionProgressBarV2 optp;
optp.rect = optc.rect;
optp.minimum = 0;
optp.maximum = 100;
optp.progress = item->result()->downloadJob()->progressPercentage();
optp.palette = m_view->palette();
optp.palette.setColor( QPalette::Highlight, QColor( "#E61878" ) );
if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active )
optp.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled;
else
optp.state = QStyle::State_Active | QStyle::State_Enabled;
QApplication::style()->drawControl( QStyle::CE_ProgressBar, &optp, painter, 0 );*/
}
}
}
DownloadButton::drawPrimitive( painter, opt.rect.adjusted( 4, 0, -4, 0 ), item->query(), hoveringOver() == index );
}
else if ( item->isPlaying() )
{
@@ -657,67 +534,14 @@ PlaylistItemDelegate::drawTrack( QPainter* painter, const QStyleOptionViewItem&
stateWidth += r.width() + 16;
}
if ( hasOnlineResults && !item->query()->results().first()->purchaseUrl().isEmpty() )
{
QRect r = stateRect.adjusted( -stateWidth -144, 6, 0, -6 );
r.setWidth( 144 );
DropDownButton::drawPrimitive( painter, r, tr( "Buy" ), m_hoveringOverBuyButton == index, false );
m_buyButtonRects[ index ] = r;
stateWidth += r.width() + 16;
}
}
if ( hasOnlineResults && !item->query()->results().first()->downloadFormats().isEmpty() )
QRect downloadButtonRect = stateRect.adjusted( -stateWidth -144, 6, 0, -6 );
downloadButtonRect.setWidth( 144 );
stateWidth += downloadButtonRect.width() + 16;
if ( DownloadButton::drawPrimitive( painter, downloadButtonRect, item->query(), m_hoveringOverDownloadButton == index ) )
{
painter->save();
QStyleOptionComboBox optc;
optc.rect = stateRect.adjusted( -stateWidth -144, 6, 0, -6 );
optc.rect.setWidth( 144 );
m_downloadDropDownRects[ index ] = optc.rect;
stateWidth += optc.rect.width() + 16;
optc.editable = false;
optc.currentText = tr( "Download %1" ).arg( item->query()->results().first()->downloadFormats().first().extension.toUpper() );
optc.palette = m_view->palette();
if ( option.state & QStyle::State_Selected && option.state & QStyle::State_Active )
optc.state = QStyle::State_Active | QStyle::State_Selected | QStyle::State_Enabled;
else
optc.state = QStyle::State_Active | QStyle::State_Enabled;
if ( !DownloadManager::instance()->localFileForDownload( item->query()->results().first()->downloadFormats().first().url.toString() ).isEmpty() )
{
painter->setPen( optc.palette.text().color() );
const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, optc.rect.width() - 3 );
painter->drawText( optc.rect, text, QTextOption( Qt::AlignCenter ) );
}
else if ( !item->query()->results().first()->downloadJob() )
{
DropDownButton::drawPrimitive( painter, optc.rect, optc.currentText, hoveringOver() == index, true );
}
else
{
if ( item->query()->results().first()->downloadJob()->state() == DownloadJob::Finished )
{
painter->setPen( optc.palette.text().color() );
const QString text = painter->fontMetrics().elidedText( tr( "View in Finder" ), Qt::ElideRight, optc.rect.width() - 3 );
painter->drawText( optc.rect, text, QTextOption( Qt::AlignCenter ) );
}
else
{
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND );
painter->drawRect( optc.rect.adjusted( 2, 2, -2, -2 ) );
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
QRect fillp = optc.rect.adjusted( 3, 3, -3, -3 );
fillp.setWidth( float(fillp.width()) * ( float(item->query()->results().first()->downloadJob()->progressPercentage()) / 100.0 ) );
painter->drawRect( fillp );
}
}
painter->restore();
m_downloadDropDownRects[ index ] = downloadButtonRect;
}
const int remWidth = r.width() - numberWidth - durationWidth;
@@ -835,7 +659,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
bool hoveringArtist = false;
bool hoveringInfo = false;
bool hoveringLove = false;
bool hoveringBuy = false;
bool hoveringDownloadDropDown = false;
Tomahawk::source_ptr hoveredAvatar;
QRect hoveredAvatarRect;
@@ -858,12 +681,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
const QMouseEvent* ev = static_cast< QMouseEvent* >( event );
hoveringLove = loveRect.contains( ev->pos() );
}
if ( m_buyButtonRects.contains( index ) )
{
const QRect buyRect = m_buyButtonRects[ index ];
const QMouseEvent* ev = static_cast< QMouseEvent* >( event );
hoveringBuy = buyRect.contains( ev->pos() );
}
if ( m_downloadDropDownRects.contains( index ) )
{
const QRect downloadDropDownRect = m_downloadDropDownRects[ index ];
@@ -887,7 +704,7 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
if ( event->type() == QEvent::MouseMove )
{
if ( hoveringInfo || hoveringLove || hoveringArtist || hoveringBuy )
if ( hoveringInfo || hoveringLove || hoveringArtist || hoveringDownloadDropDown )
m_view->setCursor( Qt::PointingHandCursor );
else
m_view->setCursor( Qt::ArrowCursor );
@@ -911,19 +728,19 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
emit updateIndex( m_hoveringOverArtist );
m_hoveringOverArtist = QModelIndex();
}
if ( hoveringBuy && m_hoveringOverBuyButton != index )
if ( hoveringDownloadDropDown && m_hoveringOverDownloadButton != index )
{
QPersistentModelIndex ti = m_hoveringOverBuyButton;
m_hoveringOverBuyButton = index;
QPersistentModelIndex ti = m_hoveringOverDownloadButton;
m_hoveringOverDownloadButton = index;
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( ti ) );
item->requestRepaint();
emit updateIndex( m_hoveringOverBuyButton );
emit updateIndex( m_hoveringOverDownloadButton );
}
if ( !hoveringBuy && m_hoveringOverBuyButton.isValid() )
if ( !hoveringDownloadDropDown && m_hoveringOverDownloadButton.isValid() )
{
QPersistentModelIndex ti = m_hoveringOverBuyButton;
m_hoveringOverBuyButton = QModelIndex();
QPersistentModelIndex ti = m_hoveringOverDownloadButton;
m_hoveringOverDownloadButton = QModelIndex();
PlayableItem* item = m_model->sourceModel()->itemFromIndex( m_model->mapToSource( ti ) );
item->requestRepaint();
@@ -957,10 +774,10 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
{
item->query()->queryTrack()->setLoved( !item->query()->queryTrack()->loved() );
}
else if ( hoveringBuy )
else if ( hoveringDownloadDropDown || ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download ) )
{
WebPopup* popup = new WebPopup( item->query()->results().first()->purchaseUrl(), QSize( 400, 800 ) );
connect( item->query()->results().first().data(), SIGNAL( destroyed() ), popup, SLOT( close() ) );
if ( DownloadButton::handleEditorEvent( event , m_view, m_model, index ) )
return true;
}
else if ( hoveringInfo )
{
@@ -996,13 +813,6 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
}
}
}
else if ( ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download ) || hoveringDownloadDropDown )
{
m_model->sourceModel()->setAllColumnsEditable( true );
m_view->edit( index );
m_model->sourceModel()->setAllColumnsEditable( false );
return true;
}
event->accept();
return true;
@@ -1022,10 +832,9 @@ PlaylistItemDelegate::resetHoverIndex()
m_hoveringOver = QModelIndex();
m_hoveringOverArtist = QModelIndex();
m_hoveringOverBuyButton = QModelIndex();
m_hoveringOverDownloadButton = QModelIndex();
m_infoButtonRects.clear();
m_loveButtonRects.clear();
m_buyButtonRects.clear();
m_artistNameRects.clear();
QModelIndex itemIdx = m_model->mapToSource( idx );

View File

@@ -57,8 +57,6 @@ signals:
private slots:
void doUpdateIndex( const QPersistentModelIndex& index );
void closeEditor( const QModelIndex& index, QWidget* editor );
void addDownloadJob( const QModelIndex& index, QWidget* editor );
protected:
void prepareStyleOption( QStyleOptionViewItemV4* option, const QModelIndex& index, PlayableItem* item ) const;
@@ -116,13 +114,12 @@ private:
mutable QHash< QPersistentModelIndex, QSharedPointer< Tomahawk::PixmapDelegateFader > > m_pixmaps;
mutable QHash< QPersistentModelIndex, QRect > m_infoButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_loveButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_buyButtonRects;
mutable QHash< QPersistentModelIndex, QRect > m_downloadDropDownRects;
mutable QHash< QPersistentModelIndex, QRect > m_artistNameRects;
mutable QHash< QPersistentModelIndex, QHash< Tomahawk::source_ptr, QRect > > m_avatarBoxRects;
QPersistentModelIndex m_hoveringOver;
QPersistentModelIndex m_hoveringOverArtist;
QPersistentModelIndex m_hoveringOverBuyButton;
QPersistentModelIndex m_hoveringOverDownloadButton;
mutable QPersistentModelIndex m_nowPlaying;
TrackView* m_view;

View File

@@ -18,12 +18,6 @@
#include "TrackDetailView.h"
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QSizePolicy>
#include <QVBoxLayout>
#include "Album.h"
#include "Track.h"
#include "audio/AudioEngine.h"
@@ -39,6 +33,13 @@
#include "utils/WebPopup.h"
#include "utils/Logger.h"
#include <QLabel>
#include <QPushButton>
#include <QScrollArea>
#include <QSizePolicy>
#include <QVBoxLayout>
#include <QDesktopServices>
using namespace Tomahawk;
TrackDetailView::TrackDetailView( QWidget* parent )
@@ -197,7 +198,7 @@ TrackDetailView::setQuery( const Tomahawk::query_ptr& query )
connect( m_query->track().data(), SIGNAL( updated() ), SLOT( onCoverUpdated() ) );
connect( m_query->track().data(), SIGNAL( socialActionsLoaded() ), SLOT( onSocialActionsLoaded() ) );
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( onResultsChanged() ) );
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( onResultsChanged() ), Qt::QueuedConnection );
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( onAlbumUpdated() ) );
}
@@ -219,8 +220,44 @@ TrackDetailView::onAlbumUpdated()
{
if ( m_query->track()->albumPtr()->purchased() )
{
m_buyButton->setText( tr( "Download Album" ) );
m_buyButton->setVisible( true );
m_allTracksAvailableLocally = true;
foreach( const query_ptr& currentQuery, m_playlistInterface->tracks() )
{
if ( currentQuery->results().isEmpty() )
{
m_allTracksAvailableLocally = false;
break;
}
else
{
m_allTracksAvailableLocally = false;
foreach ( const result_ptr& currentResult, currentQuery->results() )
{
QList< DownloadFormat > formats = currentResult->downloadFormats();
bool isDownloaded = formats.isEmpty() ? false : !DownloadManager::instance()->localFileForDownload( currentResult->downloadFormats().first().url.toString() ).isEmpty();
if ( currentResult->isLocal() || isDownloaded )
{
m_allTracksAvailableLocally = true;
break;
}
}
if ( !m_allTracksAvailableLocally )
{
break;
}
}
}
if ( m_allTracksAvailableLocally )
{
m_buyButton->setText( tr( "View in Folder" ) );
m_buyButton->setVisible( true );
}
else
{
m_buyButton->setText( tr( "Download Album" ) );
m_buyButton->setVisible( true );
}
}
else
{
@@ -251,7 +288,14 @@ TrackDetailView::onBuyButtonClicked()
{
if ( m_query->track()->albumPtr()->purchased() )
{
emit downloadAll();
if ( m_allTracksAvailableLocally )
{
QDesktopServices::openUrl( QUrl::fromLocalFile( DownloadJob::localPath( m_query->track()->albumPtr() ) ) );
}
else
{
emit downloadAll();
}
}
else
{
@@ -344,7 +388,7 @@ TrackDetailView::onResultsChanged()
resolverIcon->setFixedWidth( 12 );
resolverIcon->setPixmap( result->sourceIcon( TomahawkUtils::RoundedCorners, QSize( 12, 12 ) ) );
QLabel* resolverLabel = new ClickableLabel( this );
ClickableLabel* resolverLabel = new ClickableLabel( this );
resolverLabel->setFont( f );
resolverLabel->setStyleSheet( "QLabel { color: rgba( 0, 0, 0, 50% ) }" );
resolverLabel->setText( QString( "%1 - %2" ).arg( result->track()->track() ).arg( result->track()->artist() ) );
@@ -359,8 +403,8 @@ TrackDetailView::onResultsChanged()
;
resolverLabel->setFixedWidth( width() - 32 - 4 );
NewClosure( resolverLabel, SIGNAL( clicked() ), const_cast< AudioEngine* >( AudioEngine::instance() ),
SLOT( playItem( Tomahawk::playlistinterface_ptr, Tomahawk::result_ptr, Tomahawk::query_ptr ) ),
NewClosure( resolverLabel, SIGNAL( clicked() ), const_cast< TrackDetailView* >( this ),
SLOT( onResultClicked( Tomahawk::playlistinterface_ptr, Tomahawk::result_ptr, Tomahawk::query_ptr ) ),
m_playlistInterface, result, m_query )->setAutoDelete( false );
QWidget* hbox = new QWidget;
@@ -397,3 +441,13 @@ TrackDetailView::setBuyButtonVisible( bool visible )
{
m_buyButtonVisible = visible;
}
void
TrackDetailView::onResultClicked( const Tomahawk::playlistinterface_ptr& playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery )
{
fromQuery->setPreferredResult( result );
if (AudioEngine::instance()->isPlaying() && fromQuery->results().contains( AudioEngine::instance()->currentTrack() )) {
AudioEngine::instance()->playItem( playlist, result, fromQuery );
}
}

View File

@@ -64,6 +64,8 @@ private slots:
void onBuyButtonClicked();
void onDownloadManagerStateChanged( DownloadManager::DownloadManagerState newState, DownloadManager::DownloadManagerState oldState );
void onResultClicked( const Tomahawk::playlistinterface_ptr& playlist, const Tomahawk::result_ptr& result, const Tomahawk::query_ptr& fromQuery );
private:
void setSocialActions();
@@ -77,6 +79,7 @@ private:
CaptionLabel* m_resultsBoxLabel;
QPushButton* m_buyButton;
bool m_buyButtonVisible;
bool m_allTracksAvailableLocally;
QWidget* m_infoBox;
QWidget* m_resultsBox;

View File

@@ -383,6 +383,8 @@ void
TrackView::currentChanged( const QModelIndex& current, const QModelIndex& previous )
{
QTreeView::currentChanged( current, previous );
if ( !m_model )
return;
PlayableItem* item = m_model->itemFromIndex( m_proxyModel->mapToSource( current ) );
if ( item && item->query() )

View File

@@ -247,8 +247,8 @@ TreeProxyModel::filterAcceptsRow( int sourceRow, const QModelIndex& sourceParent
if ( !item->result()->isOnline() && ti->result()->isOnline() )
return false;
if ( ( item->result()->resolvedByCollection().isNull() || !item->result()->resolvedByCollection()->isLocal() ) &&
!ti->result()->resolvedByCollection().isNull() && ti->result()->resolvedByCollection()->isLocal() )
if ( ( !item->result()->isLocal() ) &&
!ti->result()->isLocal() )
{
return false;
}

View File

@@ -190,7 +190,7 @@ JSAccount::reportNativeScriptJobResult( int resultId, const QVariantMap& result
.arg( serializeQVariantMap( result ) );
// Remove when new scripting api turned out to work reliably
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval;
//tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval;
evaluateJavaScript( eval );
}

View File

@@ -711,3 +711,14 @@ JSResolver::getStreamUrl( const result_ptr& result )
return scriptObject()->invoke( "getStreamUrl", arguments );
}
ScriptJob*
JSResolver::getDownloadUrl( const result_ptr& result, const DownloadFormat& format )
{
QVariantMap arguments;
arguments["url"] = format.url.toString();
arguments["extension"] = format.extension;
arguments["mimetype"] = format.mimetype;
return scriptObject()->invoke( "getDownloadUrl", arguments );
}

View File

@@ -76,6 +76,8 @@ public:
ScriptAccount* scriptAccount() const;
ScriptJob* getStreamUrl( const result_ptr& result ) override;
ScriptJob* getDownloadUrl( const result_ptr& result, const DownloadFormat &format ) override;
public slots:
void resolve( const Tomahawk::query_ptr& query ) override;

View File

@@ -45,3 +45,12 @@ Tomahawk::Resolver::getStreamUrl( const result_ptr& result )
return new SyncScriptJob( data );
}
Tomahawk::ScriptJob*
Tomahawk::Resolver::getDownloadUrl( const result_ptr& result, const DownloadFormat& format )
{
QVariantMap data;
data[ "url" ] = format.url.toString();
return new SyncScriptJob( data );
}

View File

@@ -21,6 +21,7 @@
#include "Typedefs.h"
#include "DllMacro.h"
#include "../DownloadJob.h"
#include <QObject>
@@ -52,6 +53,7 @@ public:
virtual void resolve( const Tomahawk::query_ptr& query ) = 0;
virtual ScriptJob* getStreamUrl( const result_ptr& result );
virtual ScriptJob* getDownloadUrl( const result_ptr& result, const DownloadFormat& format );
};
} //ns

View File

@@ -1,12 +1,12 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright (C) 2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -17,6 +17,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptAccount.h"
#include "ScriptObject.h"
@@ -31,11 +32,11 @@
#include "ScriptLinkGeneratorPlugin.h"
#include "ScriptInfoPlugin.h"
// TODO:
#include "../Artist.h"
#include "../Album.h"
#include "../Result.h"
#include "../Track.h"
#include <QTime>

View File

@@ -1,12 +1,12 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright (C) 2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -53,6 +53,7 @@ ScriptCollection::ScriptCollection( const scriptobject_ptr& scriptObject,
qDebug() << Q_FUNC_INFO << scriptAccount->name() << Collection::name();
m_servicePrettyName = scriptAccount->name();
m_weight = readMetaData().value( "weight", 99 ).toUInt();
}
@@ -235,6 +236,16 @@ ScriptCollection::getStreamUrl( const result_ptr& result )
return scriptObject()->invoke( "getStreamUrl", arguments );
}
ScriptJob*
ScriptCollection::getDownloadUrl( const result_ptr& result, const DownloadFormat& format )
{
QVariantMap arguments;
arguments["url"] = format.url.toString();
arguments["extension"] = format.extension;
arguments["mimetype"] = format.mimetype;
return scriptObject()->invoke( "getDownloadUrl", arguments );
}
void
ScriptCollection::parseMetaData( const QVariantMap& metadata )
@@ -350,7 +361,7 @@ ScriptCollection::timeout() const
unsigned int
ScriptCollection::weight() const
{
return 0;
return m_weight;
}

View File

@@ -96,6 +96,7 @@ public:
unsigned int timeout() const override;
void resolve( const Tomahawk::query_ptr& query ) override;
ScriptJob* getStreamUrl( const result_ptr& result ) override;
ScriptJob* getDownloadUrl( const result_ptr& result, const DownloadFormat &format ) override;
private slots:
void onIconFetched();
@@ -106,6 +107,7 @@ private:
QString m_servicePrettyName;
QString m_description;
int m_trackCount;
int m_weight;
QPixmap m_icon;
bool m_isOnline;
};

View File

@@ -41,12 +41,12 @@ public:
void setFilter( const QString& filter ) override;
signals:
void albums( const QList< Tomahawk::album_ptr >& );
void done();
void albums( const QList< Tomahawk::album_ptr >& ) override;
void done() override;
protected:
virtual void exec();
virtual void reportFailure();
virtual void exec() override;
virtual void reportFailure() override;
private slots:
void onAlbumsJobDone( const QVariantMap& result );

View File

@@ -42,8 +42,8 @@ public:
void setFilter( const QString& filter ) override;
signals:
void artists( const QList< Tomahawk::artist_ptr >& );
void done();
void artists( const QList< Tomahawk::artist_ptr >& ) override;
void done() override;
protected:
void exec() override;

View File

@@ -39,8 +39,8 @@ public:
void enqueue() override;
signals:
void tracks( const QList< Tomahawk::query_ptr >& );
void done();
void tracks( const QList< Tomahawk::query_ptr >& ) override;
void done() override;
protected:
Q_INVOKABLE void exec() override;

View File

@@ -45,7 +45,7 @@ public:
signals:
void information( const QString& url, const QSharedPointer<QObject>& variant );
void done();
void done() override;
protected:
void exec() override;

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptPlugin.h"

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -15,4 +15,5 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptPluginFactory.h"

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "SyncScriptJob.h"
#include "../Typedefs.h"

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptCollectionFactory.h"
#include "SourceList.h"

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptInfoPluginFactory.h"
#include "SourceList.h"

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2015, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,15 +1,15 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright (C) 2011-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright (C) 2013, Teo Mrnjavac <teo@kde.org>
* Copyright (C) 2014, Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,11 +1,12 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -15,6 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LinkGeneratorPlugin.h"
#include "LinkGenerator.h"

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,

View File

@@ -96,7 +96,14 @@ NetworkReply::metaDataChanged()
}
else
{
load( redir.toUrl() );
QUrl url = redir.toUrl();
if (url.path().isEmpty())
{
//Default cookie jar gets confused if path is empty
url.setPath("/");
}
load( url );
}
emit redirected();
}
@@ -148,10 +155,14 @@ NetworkReply::load( const QUrl& url )
m_formerUrls << url.toString();
QNetworkRequest request( url );
//Carryover User-Agent
if ( m_reply->request().hasRawHeader( "User-Agent" ))
//Carryover some headers if set
static QList<QByteArray> headersToCarryOver = { "User-Agent", "Accept-Language" };
for (auto&& header : headersToCarryOver)
{
request.setRawHeader( "User-Agent", m_reply->request().rawHeader( "User-Agent" ) );
if ( m_reply->request().hasRawHeader( header ))
{
request.setRawHeader( header, m_reply->request().rawHeader( header ) );
}
}
Q_ASSERT( Tomahawk::Utils::nam() != 0 );

View File

@@ -1,13 +1,13 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright (C) 2011-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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 2 of the License, or
* 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,

View File

@@ -1,13 +1,13 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright (C) 2011-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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 2 of the License, or
* 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,

View File

@@ -1,13 +1,13 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright (C) 2011-2012, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
*
* 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 2 of the License, or
* 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,

View File

@@ -1,15 +1,15 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
* Copyright (C) 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright (C) 2011-2014, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright (C) 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright (C) 2013, Teo Mrnjavac <teo@kde.org>
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2011-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -20,6 +20,7 @@
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "TomaHkLinkGeneratorPlugin.h"
#include "../playlist/dynamic/GeneratorInterface.h"
@@ -30,12 +31,6 @@
#include "../resolvers/SyncScriptJob.h"
#include "../utils/Logger.h"
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <echonest5/Playlist.h>
#else
#include <echonest/Playlist.h>
#endif
QString
Tomahawk::Utils::TomaHkLinkGeneratorPlugin::hostname() const
{
@@ -82,6 +77,7 @@ Tomahawk::Utils::TomaHkLinkGeneratorPlugin::openLink( const Tomahawk::album_ptr&
}
/*
Tomahawk::ScriptJob*
Tomahawk::Utils::TomaHkLinkGeneratorPlugin::openLink( const Tomahawk::dynplaylist_ptr& playlist ) const
{
@@ -130,3 +126,4 @@ Tomahawk::Utils::TomaHkLinkGeneratorPlugin::openLink( const Tomahawk::dynplaylis
return new SyncScriptJob( data );
}
*/

View File

@@ -1,10 +1,10 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright (C) 2014 Dominik Schmidt <domme@tomahawk-player.org>
* Copyright 2014, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* 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,
@@ -37,7 +37,8 @@ public:
ScriptJob* openLink( const QString& title, const QString& artist, const QString& album ) const override;
ScriptJob* openLink( const Tomahawk::artist_ptr& artist ) const override;
ScriptJob* openLink( const Tomahawk::album_ptr& album ) const override;
ScriptJob* openLink( const Tomahawk::dynplaylist_ptr& playlist ) const override;
// echonest is dead, disable all echonest code
// ScriptJob* openLink( const Tomahawk::dynplaylist_ptr& playlist ) const override;
private:
QString hostname() const;

View File

@@ -1,21 +1,20 @@
/*
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "XspfGenerator.h"

View File

@@ -1,21 +1,20 @@
/*
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2011, Leo Franchi <lfranchi@kde.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XSPFGENERATOR_H
#define XSPFGENERATOR_H

View File

@@ -0,0 +1,282 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "DownloadButton.h"
#include "Artist.h"
#include "Album.h"
#include "Result.h"
#include "DownloadManager.h"
#include "utils/TomahawkStyle.h"
#include "utils/WebPopup.h"
#include "utils/Logger.h"
#include <QPainter>
#include <QEvent>
#include <QAbstractItemView>
#include <QDesktopServices>
using namespace Tomahawk;
DownloadButton::DownloadButton( const Tomahawk::query_ptr& query, QWidget* parent, QAbstractItemView* view, const QModelIndex& index )
: DropDownButton( parent )
, m_view( view )
, m_index( index )
{
init();
setQuery( query );
}
DownloadButton::DownloadButton( QWidget* parent )
: DropDownButton( parent )
{
init();
}
void
DownloadButton::init()
{
connect( this, SIGNAL( clicked() ), this, SLOT( addDownloadJob() ) );
connect( this, SIGNAL( activated( int ) ), this, SLOT( addDownloadJob() ) );
}
DownloadButton::~DownloadButton()
{
}
void
DownloadButton::setQuery( const query_ptr& query )
{
if ( !m_query.isNull() )
{
m_query->disconnect( this );
}
if ( !m_result.isNull() )
{
m_result->disconnect( this );
}
clear();
m_result.clear();
m_query = query;
if ( query.isNull() )
return;
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
if ( result.isNull() )
return;
QStringList formats;
foreach ( const DownloadFormat& format, result->downloadFormats() )
{
formats << QObject::tr( "Download %1" ).arg( format.extension.toUpper() );
}
addItems( formats );
}
void
DownloadButton::addDownloadJob()
{
if ( m_query.isNull() )
return;
Tomahawk::result_ptr result = m_query->numResults( true ) ? m_query->results().first() : Tomahawk::result_ptr();
if ( result.isNull() )
return;
if ( handleClickPreDownload( m_query ) )
return;
if ( !result->downloadFormats().isEmpty() )
{
if ( m_view && m_index.isValid() )
{
m_view->closePersistentEditor( m_index );
}
else
{
m_result = result;
connect( result.data(), SIGNAL( updated() ), SLOT( update() ) );
connect( m_query.data(), SIGNAL( resultsChanged() ), SLOT( update() ) );
}
DownloadManager::instance()->addJob( result->toDownloadJob( result->downloadFormats().at( currentIndex() ) ) );
}
else
{
handleClickPostDownload( m_query );
}
}
void
DownloadButton::paintEvent( QPaintEvent* event )
{
QPainter p( this );
setupPainter( &p );
if ( DownloadButton::drawPrimitive( &p, contentsRect(), m_query, m_hovering ) )
setCursor( Qt::PointingHandCursor );
else
setCursor( Qt::ArrowCursor );
}
bool
DownloadButton::drawPrimitive( QPainter* painter, const QRect& rect, const Tomahawk::query_ptr& query, bool hovering )
{
if ( query.isNull() )
return false;
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
if ( result.isNull() )
return false;
if ( result->downloadJob() && result->downloadJob()->state() != DownloadJob::Finished )
{
// if downloadJob exists and is not finished, paint a progress bar
painter->save();
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND.darker() );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_BACKGROUND );
painter->drawRect( rect.adjusted( 2, 2, -2, -2 ) );
painter->setPen( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
painter->setBrush( TomahawkStyle::PLAYLIST_PROGRESS_FOREGROUND );
QRect fillp = rect.adjusted( 3, 3, -3, -3 );
fillp.setWidth( float(fillp.width()) * ( float( result->downloadJob()->progressPercentage() ) / 100.0 ) );
painter->drawRect( fillp );
painter->restore();
}
else
{
QString text;
bool itemsAvailable = false;
if ( result &&
( ( !result->downloadFormats().isEmpty() && !DownloadManager::instance()->localFileForDownload( result->downloadFormats().first().url.toString() ).isEmpty() ) ||
( result->downloadJob() && result->downloadJob()->state() == DownloadJob::Finished ) ) )
{
text = QObject::tr( "View in Finder" );
}
else if ( !result->downloadFormats().isEmpty() )
{
text = tr( "Download %1" ).arg( query->results().first()->downloadFormats().first().extension.toUpper() );
itemsAvailable = true;
}
else if ( !result->purchaseUrl().isEmpty() )
{
text = tr( "Buy" );
}
if ( !text.isEmpty() )
DropDownButton::drawPrimitive( painter, rect, text, hovering, itemsAvailable );
else
{
// this result can neither be bought nor downloaded
return false;
}
}
return true;
}
bool
DownloadButton::handleEditorEvent(QEvent* event , QAbstractItemView* view, PlayableProxyModel* model, const QModelIndex& index)
{
if ( event->type() == QEvent::MouseButtonRelease )
{
PlayableItem* item = model->sourceModel()->itemFromIndex( model->mapToSource( index ) );
if ( !item && ! item->query() )
return false;
if ( handleClickPreDownload( item->query() ) )
return true;
if( item->query()->numResults( true ) && !item->query()->results().first()->downloadFormats().isEmpty() )
{
model->sourceModel()->setAllColumnsEditable( true );
view->edit( index );
model->sourceModel()->setAllColumnsEditable( false );
return true;
}
return handleClickPostDownload( item->query() );
}
return false;
}
bool
DownloadButton::handleClickPreDownload( const Tomahawk::query_ptr& query )
{
// view in folder
if ( !DownloadManager::instance()->localUrlForDownload( query ).isEmpty() )
{
QDesktopServices::openUrl( DownloadManager::instance()->localUrlForDownload( query ) );
return true;
}
// download in progress
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
if ( result && result->downloadJob() && result->downloadJob()->state() != DownloadJob::Finished )
{
// do nothing, handled
return true;
}
return false;
}
bool
DownloadButton::handleClickPostDownload( const Tomahawk::query_ptr& query )
{
// handle buy click
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
if ( result && !result->purchaseUrl().isEmpty() )
{
WebPopup* popup = new WebPopup( result->purchaseUrl(), QSize( 400, 800 ) );
connect( result.data(), SIGNAL( destroyed() ), popup, SLOT( close() ) );
return true;
}
return false;
}
QWidget*
DownloadButton::handleCreateEditor( QWidget* parent, const query_ptr& query, QAbstractItemView* view, const QModelIndex& index )
{
Tomahawk::result_ptr result = query->numResults( true ) ? query->results().first() : Tomahawk::result_ptr();
if ( result && !result->downloadFormats().isEmpty() && !result->downloadJob() )
{
return new DownloadButton( query, parent, view, index );
}
return 0;
}

View File

@@ -0,0 +1,61 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
*
* Tomahawk is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DOWNLOADBUTTON_H
#define DOWNLOADBUTTON_H
#include "DropDownButton.h"
#include "playlist/PlayableProxyModel.h"
#include "Typedefs.h"
#include "DllMacro.h"
class DLLEXPORT DownloadButton : public DropDownButton
{
Q_OBJECT
public:
explicit DownloadButton( const Tomahawk::query_ptr& query, QWidget* parent = nullptr, QAbstractItemView* view = nullptr, const QModelIndex& index = QModelIndex() );
explicit DownloadButton( QWidget* parent = nullptr );
virtual ~DownloadButton();
void setQuery( const Tomahawk::query_ptr& query );
static bool drawPrimitive( QPainter* p, const QRect& rect, const Tomahawk::query_ptr& query, bool hovering );
static bool handleEditorEvent( QEvent* event, QAbstractItemView* view, PlayableProxyModel* model, const QModelIndex& index );
static QWidget* handleCreateEditor( QWidget* parent, const Tomahawk::query_ptr& query , QAbstractItemView* view, const QModelIndex& index );
protected:
void paintEvent( QPaintEvent* event );
private slots:
void addDownloadJob();
private:
static bool handleClickPreDownload( const Tomahawk::query_ptr& query );
static bool handleClickPostDownload( const Tomahawk::query_ptr& query );
void init();
Tomahawk::query_ptr m_query;
Tomahawk::result_ptr m_result;
QAbstractItemView* m_view;
QModelIndex m_index;
};
#endif // DOWNLOADBUTTON_H

View File

@@ -47,7 +47,7 @@ protected:
private slots:
private:
protected:
static void setupPainter( QPainter* p );
bool m_hovering;

View File

@@ -100,7 +100,6 @@ INCLUDE_DIRECTORIES(
${THIRDPARTY_DIR}/kdsingleapplicationguard/
${LIBATTICA_INCLUDE_DIR}
${ECHONEST_INCLUDE_DIR}
${LIBLASTFM_INCLUDE_DIRS}
${Boost_INCLUDE_DIR}
)
@@ -202,7 +201,6 @@ TARGET_LINK_LIBRARIES( ${TOMAHAWK_APPLICATION_TARGET}
${OS_SPECIFIC_LINK_LIBRARIES}
${QT_LIBRARIES}
${MAC_EXTRA_LIBS}
${ECHONEST_LIBRARIES}
${Boost_LIBRARIES}
)

View File

@@ -30,7 +30,6 @@
#include "infosystem/InfoSystem.h"
#include "infosystem/InfoSystemCache.h"
#include "playlist/dynamic/GeneratorFactory.h"
#include "playlist/dynamic/echonest/EchonestGenerator.h"
#include "playlist/dynamic/database/DatabaseGenerator.h"
#include "playlist/XspfUpdater.h"
#include "network/Servent.h"
@@ -45,7 +44,6 @@
#include "Pipeline.h"
#include "DropJob.h"
#include "DownloadManager.h"
#include "EchonestCatalogSynchronizer.h"
#include "database/DatabaseImpl.h"
#include "network/Msg.h"
#include "utils/NetworkAccessManager.h"
@@ -243,10 +241,13 @@ TomahawkApp::init()
QByteArray wand = QByteArray::fromBase64( QCoreApplication::applicationName().toLatin1() );
int length = magic.length(), n2 = wand.length();
for ( int i = 0; i < length; i++ ) magic[i] = magic[i] ^ wand[i%n2];
// echonest is dead, disable all echonest code
/*
Echonest::Config::instance()->setAPIKey( magic );
tDebug() << "Init Echonest Factory.";
GeneratorFactory::registerFactory( "echonest", new EchonestFactory );
*/
tDebug() << "Init Database Factory.";
GeneratorFactory::registerFactory( "database", new DatabaseFactory );
@@ -634,8 +635,11 @@ TomahawkApp::onInfoSystemReady()
TomahawkSettings* s = TomahawkSettings::instance();
// echonest is dead, disable all echonest code
/*
Echonest::Config::instance()->setNetworkAccessManager( Tomahawk::Utils::nam() );
EchonestGenerator::setupCatalogs();
*/
m_scanManager = QPointer<ScanManager>( new ScanManager( this ) );
if ( !m_headless )
@@ -681,8 +685,11 @@ TomahawkApp::onInfoSystemReady()
m_scrobbler = new Scrobbler( this );
#endif
// echonest is dead, disable all echonest code
/*
// Set up echonest catalog synchronizer
Tomahawk::EchonestCatalogSynchronizer::instance();
*/
PlaylistUpdaterInterface::registerUpdaterFactory( new XspfUpdaterFactory );
// PlaylistUpdaterInterface::registerUpdaterFactory( new SpotifyUpdaterFactory );

View File

@@ -1,6 +1,6 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010-2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
* Copyright 2010-2012, Leo Franchi <lfranchi@kde.org>
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
* Copyright 2012, Teo Mrnjavac <teo@kde.org>
@@ -683,7 +683,8 @@ TomahawkWindow::setupSignals()
connect( ac->getAction( "quit" ), SIGNAL( triggered() ), qApp, SLOT( quit() ) );
connect( ac->getAction( "showOfflineSources" ), SIGNAL( triggered() ), SLOT( showOfflineSources() ) );
connect( ac->getAction( "createPlaylist" ), SIGNAL( triggered() ), SLOT( createPlaylist() ) );
connect( ac->getAction( "createStation" ), SIGNAL( triggered() ), SLOT( createStation() ) );
// echonest is dead, disable stations
// connect( ac->getAction( "createStation" ), SIGNAL( triggered() ), SLOT( createStation() ) );
#if defined( Q_OS_MAC )
connect( ac->getAction( "minimize" ), SIGNAL( triggered() ), SLOT( minimize() ) );
@@ -722,11 +723,13 @@ TomahawkWindow::eventFilter( QObject* obj, QEvent* event )
{
case Qt::XButton1:
m_backAction->trigger();
break;
event->accept();
return true;
case Qt::XButton2:
m_forwardAction->trigger();
break;
event->accept();
return true;
default:
break;
@@ -849,7 +852,7 @@ TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
Q_UNUSED(newState);
#else
updatePreview();
QWinThumbnailToolButton *play = m_taskbarList->buttons()[ TP_PLAY_PAUSE ];
switch ( newState )
{
@@ -890,6 +893,7 @@ TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
#endif//Q_OS_WIN
}
void
TomahawkWindow::onHistoryBackAvailable( bool avail )
{

View File

@@ -126,6 +126,8 @@ SettingsDialog::SettingsDialog(QObject *parent )
m_advancedWidgetUi->enableProxyCheckBox->setChecked( useProxy );
m_advancedWidgetUi->proxyButton->setEnabled( useProxy );
m_advancedWidgetUi->vlcArgsLineEdit->setText( s->vlcArguments() );
m_advancedWidgetUi->aclEntryClearButton->setEnabled( TomahawkSettings::instance()->aclEntries().size() > 0 );
connect( m_advancedWidgetUi->aclEntryClearButton, SIGNAL( clicked( bool ) ), this, SLOT( aclEntryClearButtonClicked() ) );
@@ -297,6 +299,9 @@ SettingsDialog::SettingsDialog(QObject *parent )
connect( m_dialog, SIGNAL( accepted() ), SLOT( saveSettings() ) );
connect( m_dialog, SIGNAL( rejected() ), SLOT( onRejected() ) );
// Echonest is dead, make catalog upload checkbox invisible
m_collectionWidgetUi->enableEchonestCatalog->setVisible( false );
}
@@ -332,6 +337,9 @@ SettingsDialog::saveSettings()
s->applyChanges();
s->sync();
m_restartRequired = m_restartRequired || m_advancedWidgetUi->vlcArgsLineEdit->text() != s->vlcArguments();
s->setVlcArguments( m_advancedWidgetUi->vlcArgsLineEdit->text() );
if ( m_restartRequired )
QMessageBox::information( 0, tr( "Information" ), tr( "Some changed settings will not take effect until %applicationName is restarted" ) );

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>515</width>
<height>475</height>
<width>540</width>
<height>520</height>
</rect>
</property>
<property name="sizePolicy">
@@ -250,6 +250,36 @@
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="vlcGroupBox">
<property name="title">
<string>VLC settings</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Additional command line arguments</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_2">
<property name="text">
<string>(separate with comma)</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLineEdit" name="vlcArgsLineEdit"/>
</item>
</layout>
</widget>
</item>
<item>
<spacer name="verticalSpacer_4">
<property name="orientation">

View File

@@ -223,7 +223,6 @@ SourcesModel::index( int row, int column, const QModelIndex& parent ) const
}
return QModelIndex();
}

View File

@@ -1,20 +1,20 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
*
* 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.
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "CategoryItems.h"
@@ -33,12 +33,6 @@
#include "utils/ImageRegistry.h"
#include "utils/Logger.h"
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
#include <echonest5/Playlist.h>
#else
#include <echonest/Playlist.h>
#endif
using namespace Tomahawk;

View File

@@ -1,19 +1,19 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* 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.
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CATEGORY_ITEM_H

View File

@@ -30,9 +30,9 @@ public:
explicit CollectionItem( SourcesModel* model, SourceTreeItem* parent, const Tomahawk::collection_ptr& collection );
virtual ~CollectionItem();
virtual QString text() const;
virtual QIcon icon() const;
virtual int peerSortValue() const;
virtual QString text() const override;
virtual QIcon icon() const override;
virtual int peerSortValue() const override;
void setSortValue( int value );
bool isBeingPlayed() const override;
@@ -40,7 +40,7 @@ public:
int trackCount() const;
public slots:
virtual void activate();
virtual void activate() override;
private:
int m_sortValue;

View File

@@ -1,19 +1,19 @@
/*
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Copyright 2010-2011, Leo Franchi <lfranchi@kde.org>
*
* 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.
* 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.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GenericPageItems.h"

Some files were not shown because too many files have changed in this diff Show More