mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-09 21:50:58 +02:00
Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
365c7b0e31 | ||
|
9ae97e50ad | ||
|
72dab1aae6 |
@@ -179,7 +179,7 @@ if( NOT BUILD_WITH_QT4 )
|
||||
set(HAVE_X11 FALSE)
|
||||
endif()
|
||||
|
||||
message(STATUS "Found Qt5!")
|
||||
message(STATUS "Found Qt5! Be aware that Qt5-support is still experimental and not officially supported!")
|
||||
|
||||
if( UNIX AND NOT APPLE )
|
||||
# We need this to find the paths to qdbusxml2cpp and co
|
||||
@@ -228,10 +228,6 @@ endif()
|
||||
if( NOT Qt5Core_DIR )
|
||||
message(STATUS "Could not find Qt5, searching for Qt4 instead...")
|
||||
|
||||
if(NOT FORCE_QT4)
|
||||
message(FATAL_ERROR "Qt4 support is broken, if you plan to fix it, add -DFORCE_QT4=ON to your cmake arguments otherwise you should compile Tomahawk with Qt5")
|
||||
endif()
|
||||
|
||||
set(NEEDED_QT4_COMPONENTS "QtCore" "QtXml" "QtNetwork")
|
||||
if( BUILD_GUI )
|
||||
list(APPEND NEEDED_QT4_COMPONENTS "QtGui" "QtWebkit" "QtUiTools" "QtSvg")
|
||||
@@ -311,10 +307,14 @@ else()
|
||||
message(STATUS "${CMAKE_CXX_COMPILER} does not support C++11, please use a
|
||||
different compiler")
|
||||
endif()
|
||||
if(("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR APPLE) AND LIBCPP_FOUND)
|
||||
if(LIBCPP_FOUND AND APPLE)
|
||||
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
|
||||
|
||||
@@ -404,8 +404,12 @@ if( WIN32 )
|
||||
endif( WIN32 )
|
||||
|
||||
if( WIN32 OR APPLE )
|
||||
macro_optional_find_package(LibsnoreQt5 0.6.0 QUIET)
|
||||
macro_log_feature(LibsnoreQt5_FOUND "Libsnore" "Library for notifications" "https://projects.kde.org/projects/playground/libs/snorenotify" FALSE "" "")
|
||||
if( TOMAHAWK_QT5 )
|
||||
macro_optional_find_package(LibsnoreQt5 QUIET)
|
||||
else()
|
||||
macro_optional_find_package(Libsnore QUIET)
|
||||
endif()
|
||||
macro_log_feature(LIBSNORE_FOUND "Libsnore" "Library for notifications" "https://github.com/TheOneRing/Snorenotify" FALSE "" "")
|
||||
endif()
|
||||
|
||||
find_package(LIBVLC REQUIRED 2.1.0)
|
||||
|
42
CMakeModules/FindEchonest.cmake
Normal file
42
CMakeModules/FindEchonest.cmake
Normal file
@@ -0,0 +1,42 @@
|
||||
# - 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)
|
@@ -6,16 +6,19 @@ find_path(LIBVLC_INCLUDE_DIR vlc/vlc.h
|
||||
HINTS
|
||||
${PC_LIBVLC_INCLUDEDIR}
|
||||
${PC_LIBVLC_INCLUDE_DIRS}
|
||||
/usr/local/opt/vlc/include
|
||||
)
|
||||
|
||||
find_library(LIBVLC_LIBRARY NAMES vlc libvlc
|
||||
HINTS
|
||||
${PC_LIBVLC_LIBDIR}
|
||||
${PC_LIBVLC_LIBRARY_DIRS}
|
||||
/usr/local/opt/vlc/lib
|
||||
)
|
||||
|
||||
find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore
|
||||
HINTS
|
||||
${PC_LIBVLC_LIBDIR}
|
||||
${PC_LIBVLC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(LIBVLC_VERSION ${PC_LIBVLC_VERSION})
|
||||
|
||||
@@ -29,6 +32,8 @@ int main(int argc, char *argv[]) {
|
||||
HAVE_VLC_ALBUMARTIST)
|
||||
|
||||
find_package_handle_standard_args(LibVLC
|
||||
REQUIRED_VARS LIBVLC_LIBRARY LIBVLC_INCLUDE_DIR
|
||||
REQUIRED_VARS LIBVLC_LIBRARY LIBVLCCORE_LIBRARY LIBVLC_INCLUDE_DIR
|
||||
VERSION_VAR LIBVLC_VERSION
|
||||
)
|
||||
|
||||
|
||||
|
@@ -15,24 +15,21 @@
|
||||
;-----------------------------------------------------------------------------
|
||||
; Some paths.
|
||||
;-----------------------------------------------------------------------------
|
||||
!ifndef MINGW_ROOT
|
||||
!define MINGW_ROOT "/usr/i686-w64-mingw32/sys-root/mingw"
|
||||
!ifndef MING_PATH
|
||||
!define MING_PATH "/usr/i686-w64-mingw32/sys-root/mingw"
|
||||
!endif
|
||||
!define APPLICATION_NAME "@CPACK_PACKAGE_NAME@"
|
||||
!define TARGET_NAME "@CPACK_PACKAGE_TARGET_NAME@"
|
||||
!define APPLICATION_NAME "Tomahawk"
|
||||
!define TARGET_NAME "tomahawk"
|
||||
;define app id needed for Windows 8 notifications
|
||||
!define AppUserModelId "@TOMAHAWK_APPLICATION_PACKAGE_NAME@"
|
||||
|
||||
!define MINGW_BIN "${MINGW_ROOT}/bin"
|
||||
!define MINGW_LIB "${MINGW_ROOT}/lib"
|
||||
!define MINGW_SHARE "${MINGW_ROOT}/share"
|
||||
!define AppUserModelId @TOMAHAWK_APPLICATION_PACKAGE_NAME@
|
||||
|
||||
!define MING_BIN "${MING_PATH}/bin"
|
||||
!define MING_LIB "${MING_PATH}/lib"
|
||||
!define BUILD_PATH "@CMAKE_BINARY_DIR@"
|
||||
!define SOURCE_PATH "@CMAKE_SOURCE_DIR@"
|
||||
!define QT_DLL_PATH "${MINGW_BIN}"
|
||||
!define QT_QML_PATH "${MINGW_SHARE}/qt5/qml"
|
||||
!define SQLITE_DLL_PATH "${MINGW_LIB}/qt5/plugins/sqldrivers"
|
||||
!define IMAGEFORMATS_DLL_PATH "${MINGW_LIB}/qt5/plugins/imageformats"
|
||||
!define QT_DLL_PATH "${MING_BIN}"
|
||||
!define SQLITE_DLL_PATH "${MING_LIB}/qt5/plugins/sqldrivers"
|
||||
!define IMAGEFORMATS_DLL_PATH "${MING_LIB}/qt5/plugins/imageformats"
|
||||
|
||||
; We use official release plugins
|
||||
; mingw32-vlc from obs misses a lot and has even broken ones probably
|
||||
@@ -333,7 +330,7 @@ Section "${APPLICATION_NAME}" SEC_TOMAHAWK_PLAYER
|
||||
File "${QT_DLL_PATH}\Qt5WebKitWidgets.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Multimedia.dll"
|
||||
File "${QT_DLL_PATH}\Qt5MultimediaWidgets.dll"
|
||||
File "${QT_DLL_PATH}\Qt5Positioning.dll"
|
||||
|
||||
|
||||
;Qt deps
|
||||
File "${QT_DLL_PATH}\libpcre16-0.dll"
|
||||
@@ -342,112 +339,96 @@ Section "${APPLICATION_NAME}" SEC_TOMAHAWK_PLAYER
|
||||
File "${QT_DLL_PATH}\libEGL.dll"
|
||||
File "${QT_DLL_PATH}\libGLESv2.dll"
|
||||
File "${QT_DLL_PATH}\libwebp-5.dll"
|
||||
File "${QT_DLL_PATH}\icuuc56.dll"
|
||||
File "${QT_DLL_PATH}\icudata56.dll"
|
||||
File "${QT_DLL_PATH}\icui18n56.dll"
|
||||
|
||||
;SQLite driver
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "${SQLITE_DLL_PATH}\qsqlite.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MINGW_BIN}\libsqlite3-0.dll"
|
||||
;Boost fnord
|
||||
File "${QT_DLL_PATH}\icuuc53.dll"
|
||||
File "${QT_DLL_PATH}\icudata53.dll"
|
||||
File "${QT_DLL_PATH}\icui18n53.dll"
|
||||
|
||||
;Qt platform plugins
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "${MINGW_LIB}/qt5/plugins/platforms/qwindows.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
;SQLite driver
|
||||
SetOutPath "$INSTDIR\sqldrivers"
|
||||
File "${SQLITE_DLL_PATH}\qsqlite.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MING_BIN}\libsqlite3-0.dll"
|
||||
|
||||
;Image plugins
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qgif.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qjpeg.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qsvg.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
;Qt platform plugins
|
||||
SetOutPath "$INSTDIR\platforms"
|
||||
File "${MING_LIB}/qt5/plugins/platforms/qwindows.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
;Qt qml plugins
|
||||
SetOutPath "$INSTDIR\QtQuick.2"
|
||||
File /r /x *.debug "${QT_QML_PATH}\QtQuick.2\*"
|
||||
SetOutPath "$INSTDIR\QtQuick\Window.2"
|
||||
File /r /x *.debug "${QT_QML_PATH}\QtQuick\Window.2\*"
|
||||
SetOutPath "$INSTDIR"
|
||||
;Image plugins
|
||||
SetOutPath "$INSTDIR\imageformats"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qgif.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qjpeg.dll"
|
||||
File "${IMAGEFORMATS_DLL_PATH}\qsvg.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
;Cygwin/c++ stuff
|
||||
File "${MINGW_BIN}\libgcc_s_sjlj-1.dll"
|
||||
File "${MINGW_BIN}\libstdc++-6.dll"
|
||||
;Cygwin/c++ stuff
|
||||
File "${MING_BIN}\libgcc_s_sjlj-1.dll"
|
||||
File "${MING_BIN}\libstdc++-6.dll"
|
||||
|
||||
;VLC
|
||||
File "${VLC_BIN}\libvlc.dll"
|
||||
File "${VLC_BIN}\libvlccore.dll"
|
||||
SetOutPath "$INSTDIR\plugins"
|
||||
File /r "${VLC_PLUGIN_PATH}\*.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
;VLC
|
||||
File "${VLC_BIN}\libvlc.dll"
|
||||
File "${VLC_BIN}\libvlccore.dll"
|
||||
SetOutPath "$INSTDIR\plugins"
|
||||
File /r "${VLC_PLUGIN_PATH}\*.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
|
||||
; Other
|
||||
File "${MINGW_BIN}\libtag.dll"
|
||||
File "${MINGW_BIN}\libpng16-16.dll"
|
||||
File "${MINGW_BIN}\libjpeg-8.dll"
|
||||
File "${MINGW_BIN}\zlib1.dll"
|
||||
File "${MINGW_BIN}\libfreetype-6.dll"
|
||||
File "${MINGW_BIN}\libglib-2.0-0.dll"
|
||||
File "${MINGW_BIN}\libharfbuzz-0.dll"
|
||||
; Other
|
||||
File "${MING_BIN}\libtag.dll"
|
||||
File "${MING_BIN}\libpng16-16.dll"
|
||||
File "${MING_BIN}\libjpeg-8.dll"
|
||||
File "${MING_BIN}\zlib1.dll"
|
||||
|
||||
; ANGLE
|
||||
File "${MINGW_BIN}\D3DCompiler_43.dll"
|
||||
File "${MING_BIN}\libechonest5.dll"
|
||||
File "${MING_BIN}\liblastfm5.dll"
|
||||
File "${MING_BIN}\libquazip5.dll"
|
||||
File "${MING_BIN}\libqt5keychain.dll"
|
||||
|
||||
File "${MINGW_BIN}\libechonest5.dll"
|
||||
File "${MINGW_BIN}\liblastfm5.dll"
|
||||
File "${MINGW_BIN}\libquazip5.dll"
|
||||
File "${MINGW_BIN}\libqt5keychain.dll"
|
||||
; GnuTLS
|
||||
File "${MING_BIN}\libgnutls-28.dll"
|
||||
File "${MING_BIN}\libtasn1-6.dll"
|
||||
File "${MING_BIN}\libgmp-10.dll"
|
||||
File "${MING_BIN}\libhogweed-2-4.dll"
|
||||
File "${MING_BIN}\libintl-8.dll"
|
||||
File "${MING_BIN}\libnettle-4-6.dll"
|
||||
File "${MING_BIN}\libp11-kit-0.dll"
|
||||
File "${MING_BIN}\libffi-6.dll"
|
||||
|
||||
; GnuTLS
|
||||
File "${MINGW_BIN}\libgnutls-28.dll"
|
||||
File "${MINGW_BIN}\libtasn1-6.dll"
|
||||
File "${MINGW_BIN}\libgmp-10.dll"
|
||||
File "${MINGW_BIN}\libhogweed-4-1.dll"
|
||||
File "${MINGW_BIN}\libintl-8.dll"
|
||||
File "${MINGW_BIN}\libnettle-6-1.dll"
|
||||
File "${MINGW_BIN}\libp11-kit-0.dll"
|
||||
File "${MINGW_BIN}\libffi-6.dll"
|
||||
; Snorenotify
|
||||
File "${MING_BIN}\SnoreToast.exe"
|
||||
File "${MING_BIN}\libsnore-qt5.dll"
|
||||
File "${MING_LIB}\plugins\libsnore-qt5\libsnore_backend_growl.dll"
|
||||
File "${MING_LIB}\plugins\libsnore-qt5\libsnore_backend_snarl.dll"
|
||||
File "${MING_LIB}\plugins\libsnore-qt5\libsnore_backend_snore.dll"
|
||||
File "${MING_LIB}\plugins\libsnore-qt5\libsnore_backend_snoretoast.dll"
|
||||
|
||||
; Snorenotify
|
||||
File "${MINGW_BIN}\SnoreToast.exe"
|
||||
File "${MINGW_BIN}\libsnore-qt5.dll"
|
||||
File "${MINGW_BIN}\libsnoresettings-qt5.dll"
|
||||
File "${MINGW_BIN}\snoresettings.exe"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_growl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_growl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_snarl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_snarl.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_snore.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_settings_backend_snore.dll"
|
||||
File "${MINGW_LIB}\plugins\libsnore-qt5\libsnore_backend_windowstoast.dll"
|
||||
|
||||
; Snoregrowl
|
||||
File "${MINGW_BIN}\libsnoregrowl++.dll"
|
||||
File "${MINGW_BIN}\libsnoregrowl.dll"
|
||||
; Snoregrowl
|
||||
File "${MING_BIN}\libsnoregrowl++.dll"
|
||||
File "${MING_BIN}\libsnoregrowl.dll"
|
||||
|
||||
; Jabber
|
||||
File "${MINGW_BIN}\libjreen-qt5.dll"
|
||||
File "${MINGW_BIN}\libidn-11.dll"
|
||||
File "${MINGW_BIN}\libgsasl-7.dll"
|
||||
File "${MINGW_BIN}\libqca-qt5.dll"
|
||||
SetOutPath "$INSTDIR\crypto"
|
||||
File "${MINGW_LIB}\qca-qt5\crypto\libqca-ossl.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MINGW_BIN}\libssl-10.dll"
|
||||
File "${MINGW_BIN}\libcrypto-10.dll"
|
||||
File "${MING_BIN}\libjreen-qt5.dll"
|
||||
File "${MING_BIN}\libidn-11.dll"
|
||||
File "${MING_BIN}\libgsasl-7.dll"
|
||||
File "${MING_BIN}\libqca-qt5.dll"
|
||||
SetOutPath "$INSTDIR\crypto"
|
||||
File "${MING_LIB}\qca-qt5\crypto\libqca-ossl.dll"
|
||||
SetOutPath "$INSTDIR"
|
||||
File "${MING_BIN}\libssl-10.dll"
|
||||
File "${MING_BIN}\libcrypto-10.dll"
|
||||
|
||||
; LucenePlusPlus
|
||||
File "${MINGW_BIN}\liblucene++.dll"
|
||||
File "${MINGW_BIN}\libboost_system-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_filesystem-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_iostreams-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_regex-mt.dll"
|
||||
File "${MINGW_BIN}\libboost_thread-mt.dll"
|
||||
File "${MINGW_BIN}\libbz2-1.dll"
|
||||
; LucenePlusPlus
|
||||
File "${MING_BIN}\liblucene++.dll"
|
||||
File "${MING_BIN}\libboost_system-mt.dll"
|
||||
File "${MING_BIN}\libboost_filesystem-mt.dll"
|
||||
File "${MING_BIN}\libboost_iostreams-mt.dll"
|
||||
File "${MING_BIN}\libboost_regex-mt.dll"
|
||||
File "${MING_BIN}\libboost_thread-mt.dll"
|
||||
File "${MING_BIN}\libbz2-1.dll"
|
||||
|
||||
File "${MINGW_BIN}\libqtsparkle-qt5.dll"
|
||||
File "${MINGW_BIN}\libKF5Attica.dll"
|
||||
File "${MING_BIN}\libqtsparkle-qt5.dll"
|
||||
File "${MING_BIN}\libKF5Attica.dll"
|
||||
SectionEnd
|
||||
|
||||
SectionGroup "Shortcuts"
|
||||
@@ -462,7 +443,7 @@ SectionGroup "Shortcuts"
|
||||
RMDir /r "$SMPROGRAMS\${APPLICATION_NAME}"
|
||||
CreateDirectory "$SMPROGRAMS\${APPLICATION_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${APPLICATION_NAME}\LICENSE.lnk" "$INSTDIR\LICENSE.txt"
|
||||
CreateShortCut "$SMPROGRAMS\${APPLICATION_NAME}\Notification Settings.lnk" "$INSTDIR\snoresettings.exe" "-a ${APPLICATION_NAME}"
|
||||
CreateShortCut "$SMPROGRAMS\${APPLICATION_NAME}\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_NAME}.exe"
|
||||
!insertmacro SnoreShortcut "$SMPROGRAMS\${APPLICATION_NAME}\${APPLICATION_NAME}.lnk" "$INSTDIR\${APPLICATION_NAME}.exe" "${AppUserModelId}"
|
||||
CreateShortCut "$SMPROGRAMS\${APPLICATION_NAME}\Release notes.lnk" "$INSTDIR\NOTES.txt"
|
||||
CreateShortCut "$SMPROGRAMS\${APPLICATION_NAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe"
|
||||
|
@@ -1,7 +1,6 @@
|
||||
Version 0.9.0:
|
||||
* Resolved various playback issues by switching to a new audio engine.
|
||||
* Fixed collection sorting.
|
||||
* Fixed volume/mute state not being reset correctly on startup.
|
||||
|
||||
Version 0.8.4:
|
||||
* Fixed drag & drop issues on sidebar.
|
||||
|
@@ -79,6 +79,7 @@ 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/)
|
||||
|
@@ -2,7 +2,7 @@ INCLUDE( InstallRequiredSystemLibraries )
|
||||
|
||||
SET( CPACK_PACKAGE_CONTACT "Dominik Schmidt <domme@tomahawk-player.org>" )
|
||||
|
||||
SET( CPACK_PACKAGE_FILE_NAME "${TOMAHAWK_TARGET_NAME}-${TOMAHAWK_VERSION}" ) # Package file name without extension. Also a directory of installer cmake-2.5.0-Linux-i686
|
||||
SET( CPACK_PACKAGE_FILE_NAME "${TOMAHAWK_APPLICATION_NAME}-${TOMAHAWK_VERSION}" ) # Package file name without extension. Also a directory of installer cmake-2.5.0-Linux-i686
|
||||
|
||||
# CPACK_GENERATOR CPack generator to be used STGZ;TGZ;TZ
|
||||
# CPACK_INCLUDE_TOPLEVEL_DIRECTORY Controls whether CPack adds a top-level directory, usually of the form ProjectName-Version-OS, to the top of package tree. 0 to disable, 1 to enable
|
||||
@@ -13,9 +13,7 @@ SET( CPACK_PACKAGE_DESCRIPTION_SUMMARY ${TOMAHAWK_DESCRIPTION_SUMMARY} ) # Des
|
||||
SET( CPACK_PACKAGE_INSTALL_DIRECTORY ${TOMAHAWK_APPLICATION_NAME} ) # Installation directory on the target system -> C:\Program Files\fellody
|
||||
SET( CPACK_PACKAGE_INSTALL_REGISTRY_KEY ${TOMAHAWK_APPLICATION_NAME} ) # Registry key used when installing this project CMake 2.5.0
|
||||
SET( CPACK_PACKAGE_NAME ${TOMAHAWK_APPLICATION_NAME} ) # Package name, defaults to the project name
|
||||
SET( CPACK_PACKAGE_TARGET_NAME ${TOMAHAWK_TARGET_NAME} ) # Used to build library and executable names
|
||||
SET( CPACK_PACKAGE_VENDOR ${TOMAHAWK_ORGANIZATION_NAME} ) # Package vendor name
|
||||
SET( TOMAHAWK_APPLICATION_PACKAGE_NAME ${TOMAHAWK_APPLICATION_PACKAGE_NAME} )
|
||||
SET( CPACK_PACKAGE_VERSION_MAJOR ${TOMAHAWK_VERSION_MAJOR} )
|
||||
SET( CPACK_PACKAGE_VERSION_MINOR ${TOMAHAWK_VERSION_MINOR} )
|
||||
SET( CPACK_PACKAGE_VERSION_PATCH ${TOMAHAWK_VERSION_PATCH} )
|
||||
|
@@ -3,6 +3,8 @@
|
||||
set( TOMAHAWK_QT5 @TOMAHAWK_QT5@ )
|
||||
|
||||
if(TOMAHAWK_QT5)
|
||||
message(STATUS "Found Qt5! Be aware that Qt5-support is still experimental and not officially supported!")
|
||||
|
||||
# CMAKE 2.8.13+/3.0.0+ requires these for IMPORTed targets
|
||||
find_package(Qt5Core REQUIRED)
|
||||
find_package(Qt5Concurrent REQUIRED)
|
||||
|
@@ -5,23 +5,23 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@TOMAHAWK_APPLICATION_NAME@</string>
|
||||
<string>Tomahawk</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@TOMAHAWK_APPLICATION_PACKAGE_NAME@</string>
|
||||
<string>org.tomahawk-player.Tomahawk</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@TOMAHAWK_VERSION@</string>
|
||||
<string>TOMAHAWK_VERSION</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@TOMAHAWK_VERSION@</string>
|
||||
<string>TOMAHAWK_VERSION</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>@TOMAHAWK_BASE_TARGET_NAME@</string>
|
||||
<string>tomahawk</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>@TOMAHAWK_APPLICATION_NAME@.icns</string>
|
||||
<string>Tomahawk.icns</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>@TOMAHAWK_APPLICATION_NAME@</string>
|
||||
<string>Tomahawk</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.7.0</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
@@ -29,7 +29,7 @@
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true />
|
||||
<key>SUFeedURL</key>
|
||||
<string>@TOMAHAWK_SPARKLE_UPDATE_URL@</string>
|
||||
<string>http://download.tomahawk-player.org/sparkle/update.php</string>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>sparkle_pub.pem</string>
|
||||
<key>SUEnableSystemProfiling</key>
|
||||
|
@@ -4,10 +4,9 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
TARGET_NAME="Tomahawk"
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
function header {
|
||||
echo -e "\033[0;34m==>\033[0;0;1m $1 \033[0;0m"
|
||||
}
|
||||
@@ -32,28 +31,30 @@ CERT_SIGNER=$2
|
||||
################################################################################
|
||||
|
||||
header "Fixing and copying libraries"
|
||||
$ROOT/../admin/mac/macdeploy.py "${TARGET_NAME}.app" quiet
|
||||
$ROOT/../admin/mac/macdeploy.py Tomahawk.app quiet
|
||||
|
||||
cd "${TARGET_NAME}.app"
|
||||
cd Tomahawk.app
|
||||
|
||||
cp $ROOT/../admin/mac/qt.conf Contents/Resources/qt.conf
|
||||
|
||||
header "Fixing fonts"
|
||||
mkdir "${ROOT}/${TARGET_NAME}.app/Contents/Resources/Fonts"
|
||||
cp -R $ROOT/../data/fonts/*.ttf "${ROOT}/${TARGET_NAME}.app/Contents/Resources/Fonts"
|
||||
|
||||
header "Signing bundle"
|
||||
cd ..
|
||||
if [ -f ~/sign_step.sh ];
|
||||
then
|
||||
~/sign_step.sh "$CERT_SIGNER" "${TARGET_NAME}.app"
|
||||
fi
|
||||
# header "Copying Sparkle framework"
|
||||
# cp -R /Library/Frameworks/Sparkle.framework Contents/Frameworks
|
||||
|
||||
header "Creating DMG"
|
||||
$ROOT/../admin/mac/create-dmg.sh "${TARGET_NAME}.app"
|
||||
mv "${TARGET_NAME}.dmg" "${TARGET_NAME}-$VERSION.dmg"
|
||||
cd ..
|
||||
|
||||
header "Signing bundle"
|
||||
# codesign -s "Developer ID Application: $CERT_SIGNER" -f -v ./Tomahawk.app
|
||||
|
||||
if [ -f ~/sign_step.sh ];
|
||||
then
|
||||
~/sign_step.sh "$CERT_SIGNER" "Tomahawk.app" || true
|
||||
fi
|
||||
|
||||
$ROOT/../admin/mac/create-dmg.sh Tomahawk.app
|
||||
mv Tomahawk.dmg Tomahawk-$VERSION.dmg
|
||||
|
||||
header "Creating signed Sparkle update"
|
||||
# $ROOT/../admin/mac/sign_bundle.rb "${TARGET_NAME}" $VERSION ~/tomahawk_sparkle_privkey.pem
|
||||
$ROOT/../admin/mac/sign_bundle.rb $VERSION ~/tomahawk_sparkle_privkey.pem
|
||||
|
||||
header "Done!"
|
||||
|
@@ -43,7 +43,7 @@ ln -s /Applications "$TMP/Applications"
|
||||
cp -R "$IN" "$TMP"
|
||||
|
||||
# create
|
||||
hdiutil makehybrid -hfs -hfs-volume-name "$NAME" -hfs-openfolder "$TMP" "$TMP" -o tmp.dmg
|
||||
hdiutil makehybrid -hfs -hfs-volume-name Tomahawk -hfs-openfolder "$TMP" "$TMP" -o tmp.dmg
|
||||
hdiutil convert -format UDZO -imagekey zlib-level=9 tmp.dmg -o "$OUT"
|
||||
|
||||
# cleanup
|
||||
|
@@ -22,170 +22,171 @@ import commands
|
||||
import sys
|
||||
import glob
|
||||
|
||||
TARGET_NAME="tomahawk"
|
||||
|
||||
FRAMEWORK_SEARCH_PATH=[
|
||||
'/Library/Frameworks',
|
||||
os.path.join(os.environ['HOME'], 'Library/Frameworks')
|
||||
]
|
||||
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/opt/vlc/lib', '/usr/local/Cellar/gettext/0.19.2/lib', '.']
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Cellar/gettext/0.19.2/lib', '.']
|
||||
|
||||
VLC_PLUGINS=[
|
||||
'libattachment_plugin.dylib',
|
||||
#'libaccess_avio_plugin.dylib',
|
||||
#'libaccess_fake_plugin.dylib',
|
||||
'libftp_plugin.dylib',
|
||||
'libhttp_plugin.dylib',
|
||||
'libhttplive_plugin.dylib',
|
||||
'libimem_plugin.dylib',
|
||||
#'libaccess_mmap_plugin.dylib',
|
||||
'libaccess_mms_plugin.dylib',
|
||||
'libaccess_realrtsp_plugin.dylib',
|
||||
'libtcp_plugin.dylib',
|
||||
'libudp_plugin.dylib',
|
||||
'libcdda_plugin.dylib',
|
||||
'libfilesystem_plugin.dylib',
|
||||
'libqtcapture_plugin.dylib',
|
||||
'librtp_plugin.dylib',
|
||||
'libzip_plugin.dylib',
|
||||
'liba52tofloat32_plugin.dylib',
|
||||
'liba52tospdif_plugin.dylib',
|
||||
'libaudio_format_plugin.dylib',
|
||||
'libaudiobargraph_a_plugin.dylib',
|
||||
'libchorus_flanger_plugin.dylib',
|
||||
'access/libattachment_plugin.dylib',
|
||||
#'access/libaccess_avio_plugin.dylib',
|
||||
#'access/libaccess_fake_plugin.dylib',
|
||||
'access/libftp_plugin.dylib',
|
||||
'access/libhttp_plugin.dylib',
|
||||
'access/libimem_plugin.dylib',
|
||||
#'access/libaccess_mmap_plugin.dylib',
|
||||
'access/libaccess_mms_plugin.dylib',
|
||||
'access/libaccess_realrtsp_plugin.dylib',
|
||||
'access/libtcp_plugin.dylib',
|
||||
'access/libudp_plugin.dylib',
|
||||
'access/libcdda_plugin.dylib',
|
||||
'access/libfilesystem_plugin.dylib',
|
||||
'access/libqtcapture_plugin.dylib',
|
||||
'access/librtp_plugin.dylib',
|
||||
'access/libzip_plugin.dylib',
|
||||
'access_output/libaccess_output_dummy_plugin.dylib',
|
||||
'access_output/libaccess_output_file_plugin.dylib',
|
||||
'access_output/libaccess_output_http_plugin.dylib',
|
||||
'access_output/libaccess_output_shout_plugin.dylib',
|
||||
'access_output/libaccess_output_udp_plugin.dylib',
|
||||
'audio_filter/liba52tofloat32_plugin.dylib',
|
||||
'audio_filter/liba52tospdif_plugin.dylib',
|
||||
'audio_filter/libaudio_format_plugin.dylib',
|
||||
'audio_filter/libaudiobargraph_a_plugin.dylib',
|
||||
'audio_filter/libchorus_flanger_plugin.dylib',
|
||||
#'libconverter_fixed_plugin.dylib',
|
||||
'libdolby_surround_decoder_plugin.dylib',
|
||||
'libdtstofloat32_plugin.dylib',
|
||||
'libdtstospdif_plugin.dylib',
|
||||
'libequalizer_plugin.dylib',
|
||||
'libheadphone_channel_mixer_plugin.dylib',
|
||||
'libmono_plugin.dylib',
|
||||
'libmpgatofixed32_plugin.dylib',
|
||||
'libnormvol_plugin.dylib',
|
||||
'libparam_eq_plugin.dylib',
|
||||
'libscaletempo_plugin.dylib',
|
||||
'libsimple_channel_mixer_plugin.dylib',
|
||||
'libspatializer_plugin.dylib',
|
||||
'libtrivial_channel_mixer_plugin.dylib',
|
||||
'libugly_resampler_plugin.dylib',
|
||||
'libfloat_mixer_plugin.dylib',
|
||||
'audio_filter/libdolby_surround_decoder_plugin.dylib',
|
||||
'audio_filter/libdtstofloat32_plugin.dylib',
|
||||
'audio_filter/libdtstospdif_plugin.dylib',
|
||||
'audio_filter/libequalizer_plugin.dylib',
|
||||
'audio_filter/libheadphone_channel_mixer_plugin.dylib',
|
||||
'audio_filter/libmono_plugin.dylib',
|
||||
'audio_filter/libmpgatofixed32_plugin.dylib',
|
||||
'audio_filter/libnormvol_plugin.dylib',
|
||||
'audio_filter/libparam_eq_plugin.dylib',
|
||||
'audio_filter/libscaletempo_plugin.dylib',
|
||||
'audio_filter/libsimple_channel_mixer_plugin.dylib',
|
||||
'audio_filter/libspatializer_plugin.dylib',
|
||||
'audio_filter/libtrivial_channel_mixer_plugin.dylib',
|
||||
'audio_filter/libugly_resampler_plugin.dylib',
|
||||
'audio_mixer/libfloat_mixer_plugin.dylib',
|
||||
#'libspdif_mixer_plugin.dylib',
|
||||
#'libtrivial_mixer_plugin.dylib',
|
||||
#'libaout_file_plugin.dylib',
|
||||
'libauhal_plugin.dylib',
|
||||
'liba52_plugin.dylib',
|
||||
'libadpcm_plugin.dylib',
|
||||
'libaes3_plugin.dylib',
|
||||
'libaraw_plugin.dylib',
|
||||
'libavcodec_plugin.dylib',
|
||||
'libcc_plugin.dylib',
|
||||
'libcdg_plugin.dylib',
|
||||
'libdts_plugin.dylib',
|
||||
'libfaad_plugin.dylib',
|
||||
'audio_output/libauhal_plugin.dylib',
|
||||
'codec/liba52_plugin.dylib',
|
||||
'codec/libadpcm_plugin.dylib',
|
||||
'codec/libaes3_plugin.dylib',
|
||||
'codec/libaraw_plugin.dylib',
|
||||
'codec/libavcodec_plugin.dylib',
|
||||
'codec/libcc_plugin.dylib',
|
||||
'codec/libcdg_plugin.dylib',
|
||||
'codec/libdts_plugin.dylib',
|
||||
'codec/libfaad_plugin.dylib',
|
||||
#'libfake_plugin.dylib',
|
||||
'libflac_plugin.dylib',
|
||||
'codec/libflac_plugin.dylib',
|
||||
#'libfluidsynth_plugin.dylib',
|
||||
#'libinvmem_plugin.dylib',
|
||||
'liblpcm_plugin.dylib',
|
||||
'libmpeg_audio_plugin.dylib',
|
||||
'libpng_plugin.dylib',
|
||||
'librawvideo_plugin.dylib',
|
||||
'libspeex_plugin.dylib',
|
||||
'libspudec_plugin.dylib',
|
||||
'libtheora_plugin.dylib',
|
||||
'libtwolame_plugin.dylib',
|
||||
'libvorbis_plugin.dylib',
|
||||
#'libgestures_plugin.dylib',
|
||||
'codec/liblpcm_plugin.dylib',
|
||||
'codec/libmpeg_audio_plugin.dylib',
|
||||
'codec/libpng_plugin.dylib',
|
||||
'codec/librawvideo_plugin.dylib',
|
||||
'codec/libspeex_plugin.dylib',
|
||||
'codec/libspudec_plugin.dylib',
|
||||
'codec/libtheora_plugin.dylib',
|
||||
'codec/libtwolame_plugin.dylib',
|
||||
'codec/libvorbis_plugin.dylib',
|
||||
#'control/libgestures_plugin.dylib',
|
||||
#'libhotkeys_plugin.dylib',
|
||||
#'libmotion_plugin.dylib',
|
||||
#'libnetsync_plugin.dylib',
|
||||
#'libsignals_plugin.dylib',
|
||||
'libaiff_plugin.dylib',
|
||||
'libasf_plugin.dylib',
|
||||
'libau_plugin.dylib',
|
||||
'demux/libaiff_plugin.dylib',
|
||||
'demux/libasf_plugin.dylib',
|
||||
'demux/libau_plugin.dylib',
|
||||
#'libavformat_plugin.dylib',
|
||||
'libavi_plugin.dylib',
|
||||
'libdemux_cdg_plugin.dylib',
|
||||
'libdemuxdump_plugin.dylib',
|
||||
'libdiracsys_plugin.dylib',
|
||||
'libes_plugin.dylib',
|
||||
'libflacsys_plugin.dylib',
|
||||
'liblive555_plugin.dylib',
|
||||
'libmkv_plugin.dylib',
|
||||
'libmod_plugin.dylib',
|
||||
'libmp4_plugin.dylib',
|
||||
'libmpc_plugin.dylib',
|
||||
'libmpgv_plugin.dylib',
|
||||
'libnsc_plugin.dylib',
|
||||
'libnsv_plugin.dylib',
|
||||
'libnuv_plugin.dylib',
|
||||
'libogg_plugin.dylib',
|
||||
'libplaylist_plugin.dylib',
|
||||
'libps_plugin.dylib',
|
||||
'libpva_plugin.dylib',
|
||||
'librawaud_plugin.dylib',
|
||||
'librawdv_plugin.dylib',
|
||||
'librawvid_plugin.dylib',
|
||||
'libreal_plugin.dylib',
|
||||
'libsmf_plugin.dylib',
|
||||
'libts_plugin.dylib',
|
||||
'libtta_plugin.dylib',
|
||||
'libty_plugin.dylib',
|
||||
'libvc1_plugin.dylib',
|
||||
'libvoc_plugin.dylib',
|
||||
'libwav_plugin.dylib',
|
||||
'libxa_plugin.dylib',
|
||||
'libfolder_plugin.dylib',
|
||||
'libtaglib_plugin.dylib',
|
||||
'demux/libavi_plugin.dylib',
|
||||
'demux/libdemux_cdg_plugin.dylib',
|
||||
'demux/libdemuxdump_plugin.dylib',
|
||||
'demux/libdiracsys_plugin.dylib',
|
||||
'demux/libes_plugin.dylib',
|
||||
'demux/libflacsys_plugin.dylib',
|
||||
'access/liblive555_plugin.dylib',
|
||||
'demux/libmkv_plugin.dylib',
|
||||
'demux/libmod_plugin.dylib',
|
||||
'demux/libmp4_plugin.dylib',
|
||||
'demux/libmpc_plugin.dylib',
|
||||
'demux/libmpgv_plugin.dylib',
|
||||
'demux/libnsc_plugin.dylib',
|
||||
'demux/libnsv_plugin.dylib',
|
||||
'demux/libnuv_plugin.dylib',
|
||||
'demux/libogg_plugin.dylib',
|
||||
'demux/libplaylist_plugin.dylib',
|
||||
'demux/libps_plugin.dylib',
|
||||
'demux/libpva_plugin.dylib',
|
||||
'demux/librawaud_plugin.dylib',
|
||||
'demux/librawdv_plugin.dylib',
|
||||
'demux/librawvid_plugin.dylib',
|
||||
'demux/libreal_plugin.dylib',
|
||||
'demux/libsmf_plugin.dylib',
|
||||
'demux/libts_plugin.dylib',
|
||||
'demux/libtta_plugin.dylib',
|
||||
'demux/libty_plugin.dylib',
|
||||
'demux/libvc1_plugin.dylib',
|
||||
'demux/libvoc_plugin.dylib',
|
||||
'demux/libwav_plugin.dylib',
|
||||
'demux/libxa_plugin.dylib',
|
||||
'meta_engine/libfolder_plugin.dylib',
|
||||
'meta_engine/libtaglib_plugin.dylib',
|
||||
#'libaudioscrobbler_plugin.dylib',
|
||||
'libdummy_plugin.dylib',
|
||||
'libexport_plugin.dylib',
|
||||
'control/libdummy_plugin.dylib',
|
||||
'misc/libexport_plugin.dylib',
|
||||
#'libfreetype_plugin.dylib',
|
||||
#'libgnutls_plugin.dylib',
|
||||
'liblogger_plugin.dylib',
|
||||
'liblua_plugin.dylib',
|
||||
'misc/liblogger_plugin.dylib',
|
||||
'lua/liblua_plugin.dylib',
|
||||
#'libosd_parser_plugin.dylib',
|
||||
#'libquartztext_plugin.dylib',
|
||||
#'libstats_plugin.dylib',
|
||||
'libvod_rtsp_plugin.dylib',
|
||||
'libxml_plugin.dylib',
|
||||
'misc/libvod_rtsp_plugin.dylib',
|
||||
'misc/libxml_plugin.dylib',
|
||||
#'libxtag_plugin.dylib',
|
||||
'libi420_rgb_mmx_plugin.dylib',
|
||||
'libi420_yuy2_mmx_plugin.dylib',
|
||||
'libi422_yuy2_mmx_plugin.dylib',
|
||||
'video_chroma/libi420_rgb_mmx_plugin.dylib',
|
||||
'video_chroma/libi420_yuy2_mmx_plugin.dylib',
|
||||
'video_chroma/libi422_yuy2_mmx_plugin.dylib',
|
||||
#'libmemcpymmx_plugin.dylib',
|
||||
#'libmemcpymmxext_plugin.dylib',
|
||||
'libmux_asf_plugin.dylib',
|
||||
'libmux_avi_plugin.dylib',
|
||||
'libmux_dummy_plugin.dylib',
|
||||
'libmux_mp4_plugin.dylib',
|
||||
'libmux_mpjpeg_plugin.dylib',
|
||||
'libmux_ogg_plugin.dylib',
|
||||
'libmux_ps_plugin.dylib',
|
||||
'libmux_ts_plugin.dylib',
|
||||
'libmux_wav_plugin.dylib',
|
||||
'libpacketizer_copy_plugin.dylib',
|
||||
'libpacketizer_dirac_plugin.dylib',
|
||||
'libpacketizer_flac_plugin.dylib',
|
||||
'libpacketizer_h264_plugin.dylib',
|
||||
'libpacketizer_mlp_plugin.dylib',
|
||||
'libpacketizer_mpeg4audio_plugin.dylib',
|
||||
'libpacketizer_mpeg4video_plugin.dylib',
|
||||
'libpacketizer_mpegvideo_plugin.dylib',
|
||||
'libpacketizer_vc1_plugin.dylib',
|
||||
'libi420_rgb_sse2_plugin.dylib',
|
||||
'libi420_yuy2_sse2_plugin.dylib',
|
||||
'libi422_yuy2_sse2_plugin.dylib',
|
||||
'libdecomp_plugin.dylib',
|
||||
#'libstream_filter_rar_plugin.dylib',
|
||||
'librecord_plugin.dylib',
|
||||
'mux/libmux_asf_plugin.dylib',
|
||||
'mux/libmux_avi_plugin.dylib',
|
||||
'mux/libmux_dummy_plugin.dylib',
|
||||
'mux/libmux_mp4_plugin.dylib',
|
||||
'mux/libmux_mpjpeg_plugin.dylib',
|
||||
'mux/libmux_ogg_plugin.dylib',
|
||||
'mux/libmux_ps_plugin.dylib',
|
||||
'mux/libmux_ts_plugin.dylib',
|
||||
'mux/libmux_wav_plugin.dylib',
|
||||
'packetizer/libpacketizer_copy_plugin.dylib',
|
||||
'packetizer/libpacketizer_dirac_plugin.dylib',
|
||||
'packetizer/libpacketizer_flac_plugin.dylib',
|
||||
'packetizer/libpacketizer_h264_plugin.dylib',
|
||||
'packetizer/libpacketizer_mlp_plugin.dylib',
|
||||
'packetizer/libpacketizer_mpeg4audio_plugin.dylib',
|
||||
'packetizer/libpacketizer_mpeg4video_plugin.dylib',
|
||||
'packetizer/libpacketizer_mpegvideo_plugin.dylib',
|
||||
'packetizer/libpacketizer_vc1_plugin.dylib',
|
||||
'video_chroma/libi420_rgb_sse2_plugin.dylib',
|
||||
'video_chroma/libi420_yuy2_sse2_plugin.dylib',
|
||||
'video_chroma/libi422_yuy2_sse2_plugin.dylib',
|
||||
'stream_filter/libdecomp_plugin.dylib',
|
||||
#'access/libstream_filter_rar_plugin.dylib',
|
||||
'stream_filter/librecord_plugin.dylib',
|
||||
#'libvisual_plugin.dylib',
|
||||
'libsecuretransport_plugin.dylib'
|
||||
]
|
||||
|
||||
VLC_SEARCH_PATH=[
|
||||
'/usr/local/opt/vlc/lib/vlc/plugins/',
|
||||
'/usr/local/lib/vlc/plugins/',
|
||||
]
|
||||
|
||||
QT_PLUGINS = [
|
||||
@@ -200,39 +201,39 @@ QT_PLUGINS = [
|
||||
]
|
||||
|
||||
SNORE_PLUGINS = [
|
||||
'libsnore_backend_growl.so',
|
||||
'libsnore_backend_osxnotificationcenter.so',
|
||||
# 'libsnore_backend_growl.so',
|
||||
# 'libsnore_backend_osxnotificationcenter.so',
|
||||
]
|
||||
|
||||
TOMAHAWK_PLUGINS = [
|
||||
'lib%s_account_xmpp.dylib' % TARGET_NAME,
|
||||
'lib%s_account_google.so' % TARGET_NAME,
|
||||
'lib%s_account_zeroconf.so' % TARGET_NAME,
|
||||
'lib%s_account_hatchet.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_adium.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_charts.so' % TARGET_NAME,
|
||||
# 'lib%s_infoplugin_discogs.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_echonest.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_hypem.so' % TARGET_NAME,
|
||||
# 'lib%s_infoplugin_musicbrainz.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_musixmatch.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_newreleases.so' % TARGET_NAME,
|
||||
# 'lib%s_infoplugin_rovi.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_snorenotify.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_spotify.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_dashboard.so' % TARGET_NAME,
|
||||
# 'lib%s_viewpage_networkactivity.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_charts.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_newreleases.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_whatsnew_0_8.so' % TARGET_NAME,
|
||||
'libtomahawk_account_xmpp.dylib',
|
||||
'libtomahawk_account_google.so',
|
||||
'libtomahawk_account_zeroconf.so',
|
||||
# 'libtomahawk_account_hatchet.so',
|
||||
'libtomahawk_infoplugin_adium.so',
|
||||
'libtomahawk_infoplugin_charts.so',
|
||||
'libtomahawk_infoplugin_discogs.so',
|
||||
'libtomahawk_infoplugin_echonest.so',
|
||||
'libtomahawk_infoplugin_hypem.so',
|
||||
'libtomahawk_infoplugin_musicbrainz.so',
|
||||
'libtomahawk_infoplugin_musixmatch.so',
|
||||
'libtomahawk_infoplugin_newreleases.so',
|
||||
'libtomahawk_infoplugin_rovi.so',
|
||||
# 'libtomahawk_infoplugin_snorenotify.so',
|
||||
'libtomahawk_infoplugin_spotify.so',
|
||||
'libtomahawk_viewpage_dashboard.so',
|
||||
# 'libtomahawk_viewpage_networkactivity.so',
|
||||
'libtomahawk_viewpage_charts.so',
|
||||
'libtomahawk_viewpage_newreleases.so',
|
||||
'libtomahawk_viewpage_whatsnew_0_8.so',
|
||||
]
|
||||
|
||||
QT_PLUGINS_SEARCH_PATH=[
|
||||
'/usr/local/opt/qt5/plugins',
|
||||
'/usr/local/Cellar/qt5/5.4.0/plugins',
|
||||
]
|
||||
|
||||
SNORE_PLUGINS_SEARCH_PATH=[
|
||||
'/usr/local/opt/snorenotify/lib/plugins/libsnore-qt5',
|
||||
'/usr/local/Cellar/snorenotify/HEAD/lib/libsnore',
|
||||
]
|
||||
|
||||
class Error(Exception):
|
||||
@@ -246,8 +247,6 @@ class CouldNotFindQtPluginErrorFindFrameworkError(Error):
|
||||
class InstallNameToolError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindFrameworkError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindQtPluginError(Error):
|
||||
pass
|
||||
@@ -309,7 +308,7 @@ def GetBrokenLibraries(binary):
|
||||
continue # unix style system library
|
||||
elif re.match(r'Breakpad', line):
|
||||
continue # Manually added by cmake.
|
||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line) and not re.match(r'^\s*@loader_path/../lib', line):
|
||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line):
|
||||
# Potentially already fixed library
|
||||
if '.framework' in line:
|
||||
relative_path = os.path.join(*line.split('/')[3:])
|
||||
@@ -333,11 +332,6 @@ def FindFramework(path):
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
|
||||
# replace rpath with /Library/Frameworks for Sparkle
|
||||
abs_path = path.replace("@rpath/", "/Library/Frameworks/")
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
|
||||
raise CouldNotFindFrameworkError(path)
|
||||
|
||||
def FindLibrary(path):
|
||||
@@ -582,12 +576,12 @@ for plugin in TOMAHAWK_PLUGINS:
|
||||
FixPlugin(plugin, '../MacOS')
|
||||
|
||||
for plugin in SNORE_PLUGINS:
|
||||
FixPlugin(FindSnorePlugin(plugin), '../lib/plugins/libsnore-qt5')
|
||||
FixPlugin(FindSnorePlugin(plugin), '../MacOS/libsnore')
|
||||
|
||||
try:
|
||||
FixPlugin('%s_crash_reporter' % TARGET_NAME, '../MacOS')
|
||||
FixPlugin('tomahawk_crash_reporter', '../MacOS')
|
||||
except:
|
||||
print 'Failed to find %s_crash_reporter' % TARGET_NAME
|
||||
print 'Failed to find tomahawk_crash_reporter'
|
||||
|
||||
for plugin in QT_PLUGINS:
|
||||
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
@@ -6,9 +6,9 @@ if ARGV.length < 2
|
||||
exit
|
||||
end
|
||||
|
||||
tarball = "#{ARGV[0].downcase}-#{ARGV[1]}.tar.bz2"
|
||||
tarball = "tomahawk-#{ARGV[0]}.tar.bz2"
|
||||
puts "Zipping: #{tarball}..."
|
||||
`tar jcvf "#{tarball}" #{ARGV[0]}.app`
|
||||
`tar jcvf "#{tarball}" Tomahawk.app`
|
||||
|
||||
puts "Signing..."
|
||||
puts `openssl dgst -sha1 -binary < "#{tarball}" | openssl dgst -dss1 -sign "#{ARGV[2]}" | openssl enc -base64`
|
||||
puts `openssl dgst -sha1 -binary < "#{tarball}" | openssl dgst -dss1 -sign "#{ARGV[1]}" | openssl enc -base64`
|
||||
|
@@ -9,20 +9,19 @@ fi
|
||||
|
||||
rm -rvf vlc/
|
||||
|
||||
VLC_TARBALL="vlc.tar.bz2"
|
||||
|
||||
echo "Download phonon archive..."
|
||||
# wget -c "http://downloads.sourceforge.net/project/vlc/1.1.9/win32/vlc-1.1.9-win32.7z?r=http%3A%2F%2Fwww.videolan.org%2Fvlc%2Fdownload-windows.html&ts=1306272584&use_mirror=leaseweb"
|
||||
# wget -c "http://download.tomahawk-player.org/tomahawk-vlc-0.1.zip"
|
||||
# wget -c http://people.videolan.org/~jb/phonon/phonon-vlc-last.7z
|
||||
# wget -c http://people.videolan.org/~jb/phonon/phonon_phonon-vlc_20111128.7z
|
||||
wget -c "http://download.tomahawk-player.org/test/$VLC_TARBALL"
|
||||
wget -c http://download.tomahawk-player.org/test/vlc.tar.bz2
|
||||
|
||||
echo "Extract binary..."
|
||||
# 7z x phonon*.7z
|
||||
# mv -v vlc-*/ vlc/
|
||||
# unzip tomahawk-vlc-0.1.zip
|
||||
tar xvjf "$VLC_TARBALL"
|
||||
tar xvjf vlc.tar.bz2
|
||||
|
||||
# echo "Download phonon_vlc_no_video.dll..."
|
||||
# wget -c http://people.videolan.org/~jb/phonon/phonon_vlc_no_video.dll
|
||||
@@ -73,9 +72,7 @@ rm -rvf \
|
||||
**/libi420* \
|
||||
**/libi422* \
|
||||
mux/ \
|
||||
stream_filter/*dash* \
|
||||
stream_filter/*smooth* \
|
||||
stream_filter/*record* \
|
||||
stream_filter/ \
|
||||
**/libtheora_plugin* \
|
||||
**/liblibbluray_plugin* \
|
||||
**/libdtv_plugin* \
|
||||
|
@@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="86px" height="86px" viewBox="0 0 86 86" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>folder</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="folder" sketch:type="MSLayerGroup" transform="translate(0.000000, 13.000000)" fill="#000000">
|
||||
<g id="Page-1" sketch:type="MSShapeGroup">
|
||||
<path d="M84.1450038,10.4833376 C82.8248024,9.1092149 80.9427764,8.3195294 78.9789985,8.3195294 L72.233622,8.3195294 L34.4730823,8.3195294 L34.4730823,7.0184614 C34.4730823,3.1483061 31.3247762,0 27.4563602,0 L10.1441555,0 C6.27226058,0 3.12569415,3.1500456 3.12569415,7.0184614 L3.12569415,9.4918821 C1.2088801,10.761641 0,12.9237099 0,15.3362515 L0,54.4987445 C0,54.5057021 0,54.5178779 0.0017394,54.5265748 L0,54.5439688 C0,58.3897726 3.14656684,61.5154666 7.0184614,61.5154666 L72.2336242,61.5154666 C72.4736608,61.5154666 72.7102186,61.5050302 72.9432977,61.4789393 C72.9850432,61.4771999 73.028528,61.4650241 73.0702735,61.4615453 C73.2616071,61.4389332 73.4529406,61.4145816 73.6390559,61.3745755 C73.6686257,61.3693573 73.6947166,61.3606604 73.7242863,61.3519634 C73.9225774,61.3119573 74.1208685,61.2597754 74.3139414,61.200636 C74.3243778,61.1954178 74.3348142,61.191939 74.3452506,61.1884602 C76.756053,60.4300837 78.5998126,58.4123847 79.1059765,55.9198305 C79.1077159,55.912873 79.1077159,55.9024366 79.1077159,55.895479 C79.1512008,55.6937091 79.18251,55.4919392 79.2051221,55.2797329 C79.2103403,55.2240723 79.2155585,55.1684116 79.2190373,55.1092721 C79.2277343,55.0136054 79.2433888,54.9266356 79.2451282,54.8309688 L85.9539776,15.7937099 L85.9939837,15.4127822 C86.0705187,13.5587047 85.4147685,11.8086925 84.1450038,10.4833376 C84.1450038,10.4833376 85.4147685,11.8086925 84.1450038,10.4833376 L84.1450038,10.4833376" id="Shape"></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>nav-back</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="nav-back" sketch:type="MSLayerGroup" transform="translate(4.000000, 6.000000)">
|
||||
<g id="Layer_2"></g>
|
||||
<g id="Layer_3"></g>
|
||||
<g id="Layer_4"></g>
|
||||
<g id="Layer_5"></g>
|
||||
<g id="Layer_6"></g>
|
||||
<g id="Layer_8"></g>
|
||||
<g id="Layer_9"></g>
|
||||
<g id="Layer_10"></g>
|
||||
<g id="Layer_11"></g>
|
||||
<g id="Layer_12"></g>
|
||||
<g id="Layer_13"></g>
|
||||
<g id="Layer_14"></g>
|
||||
<g id="Layer_15"></g>
|
||||
<g id="Layer_16"></g>
|
||||
<g id="Layer_17"></g>
|
||||
<g id="Layer_18"></g>
|
||||
<g id="Layer_19"></g>
|
||||
<g id="Layer_20"></g>
|
||||
<g id="Layer_21"></g>
|
||||
<g id="Layer_24"></g>
|
||||
<g id="Layer_25"></g>
|
||||
<g id="Layer_26"></g>
|
||||
<g id="Layer_27"></g>
|
||||
<g id="Layer_28"></g>
|
||||
<g id="Layer_29"></g>
|
||||
<g id="Layer_47"></g>
|
||||
<g id="Layer_30"></g>
|
||||
<g id="Layer_31"></g>
|
||||
<g id="Layer_32"></g>
|
||||
<g id="Layer_33"></g>
|
||||
<g id="Layer_34"></g>
|
||||
<g id="Layer_35"></g>
|
||||
<g id="Layer_36"></g>
|
||||
<g id="Layer_37"></g>
|
||||
<g id="Layer_38" transform="translate(2.000000, 0.000000)" fill="#000000" sketch:type="MSShapeGroup">
|
||||
<path d="M9.7,13.9 L-0.3,7 L9.7,0.1 L10.3,0.9 L1.5,7 L10.3,13.1 L9.7,13.9 Z" id="Shape"></path>
|
||||
</g>
|
||||
<g id="Layer_39"></g>
|
||||
<g id="Layer_40"></g>
|
||||
<g id="Layer_41"></g>
|
||||
<g id="Layer_42"></g>
|
||||
<g id="Layer_43"></g>
|
||||
<g id="Layer_44"></g>
|
||||
<g id="Layer_45"></g>
|
||||
<g id="Layer_46"></g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>nav-forward</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="nav-forward" sketch:type="MSLayerGroup" transform="translate(6.000000, 6.000000)">
|
||||
<g id="Layer_2"></g>
|
||||
<g id="Layer_3"></g>
|
||||
<g id="Layer_4"></g>
|
||||
<g id="Layer_5"></g>
|
||||
<g id="Layer_6"></g>
|
||||
<g id="Layer_8"></g>
|
||||
<g id="Layer_9"></g>
|
||||
<g id="Layer_10"></g>
|
||||
<g id="Layer_11"></g>
|
||||
<g id="Layer_12"></g>
|
||||
<g id="Layer_13"></g>
|
||||
<g id="Layer_14"></g>
|
||||
<g id="Layer_15"></g>
|
||||
<g id="Layer_16"></g>
|
||||
<g id="Layer_17"></g>
|
||||
<g id="Layer_18"></g>
|
||||
<g id="Layer_19"></g>
|
||||
<g id="Layer_20"></g>
|
||||
<g id="Layer_21"></g>
|
||||
<g id="Layer_24"></g>
|
||||
<g id="Layer_25"></g>
|
||||
<g id="Layer_26"></g>
|
||||
<g id="Layer_27"></g>
|
||||
<g id="Layer_28"></g>
|
||||
<g id="Layer_29"></g>
|
||||
<g id="Layer_47"></g>
|
||||
<g id="Layer_30"></g>
|
||||
<g id="Layer_31"></g>
|
||||
<g id="Layer_32"></g>
|
||||
<g id="Layer_33"></g>
|
||||
<g id="Layer_34"></g>
|
||||
<g id="Layer_35"></g>
|
||||
<g id="Layer_36"></g>
|
||||
<g id="Layer_37"></g>
|
||||
<g id="Layer_38"></g>
|
||||
<g id="Layer_39"></g>
|
||||
<g id="Layer_40"></g>
|
||||
<g id="Layer_41" transform="translate(2.000000, 0.000000)" fill="#000000" sketch:type="MSShapeGroup">
|
||||
<path d="M0.5,13.7 L-0.1,12.9 L8.3,7 L-0.1,1.1 L0.5,0.3 L10.1,7 L0.5,13.7 Z" id="Shape"></path>
|
||||
</g>
|
||||
<g id="Layer_42"></g>
|
||||
<g id="Layer_43"></g>
|
||||
<g id="Layer_44"></g>
|
||||
<g id="Layer_45"></g>
|
||||
<g id="Layer_46"></g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -102,7 +102,7 @@ Tomahawk.InfoSystem.InfoPlugin = {
|
||||
notInCache: function (infoType, criteria) {
|
||||
var requestMethod = 'request' + this.infoTypeString(infoType);
|
||||
|
||||
return RSVP.Promise.resolve(this[requestMethod](criteria));
|
||||
return Promise.resolve(this[requestMethod](criteria));
|
||||
},
|
||||
pushInfo: function (pushData) {
|
||||
var pushMethod = 'push' + this.infoTypeString(pushData.type);
|
||||
@@ -114,6 +114,6 @@ Tomahawk.InfoSystem.InfoPlugin = {
|
||||
getInfo: function (type, infoHash) {
|
||||
var getInfoMethod = 'get' + this.infoTypeString(type);
|
||||
|
||||
return RSVP.Promise.resolve(this[getInfoMethod](infoHash));
|
||||
return Promise.resolve(this[getInfoMethod](infoHash));
|
||||
}
|
||||
};
|
||||
|
@@ -39,103 +39,7 @@ if ((typeof Tomahawk === "undefined") || (Tomahawk === null)) {
|
||||
|
||||
Tomahawk.apiVersion = "0.2.2";
|
||||
|
||||
//Statuses considered a success for HTTP request
|
||||
var httpSuccessStatuses = [200, 201];
|
||||
|
||||
Tomahawk.error = console.error;
|
||||
|
||||
// install RSVP error handler for uncaught(!) errors
|
||||
RSVP.on('error', function (reason) {
|
||||
var resolverName = "";
|
||||
if (Tomahawk.resolver.instance) {
|
||||
resolverName = Tomahawk.resolver.instance.settings.name + " - ";
|
||||
}
|
||||
if (reason) {
|
||||
Tomahawk.error(resolverName + 'Uncaught error:', reason);
|
||||
} else {
|
||||
Tomahawk.error(resolverName + 'Uncaught error: error thrown from RSVP but it was empty');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Compares versions strings
|
||||
* (version1 < version2) == -1
|
||||
* (version1 = version2) == 0
|
||||
* (version1 > version2) == 1
|
||||
*/
|
||||
Tomahawk.versionCompare = function (version1, version2) {
|
||||
var v1 = version1.split('.').map(function (item) {
|
||||
return parseInt(item);
|
||||
});
|
||||
var v2 = version2.split('.').map(function (item) {
|
||||
return parseInt(item);
|
||||
});
|
||||
var length = Math.max(v1.length, v2.length);
|
||||
var i = 0;
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (typeof v1[i] == "undefined" || v1[i] === null) {
|
||||
if (typeof v2[i] == "undefined" || v2[i] === null) {
|
||||
// v1 == v2
|
||||
return 0;
|
||||
} else if (v2[i] === 0) {
|
||||
continue;
|
||||
} else {
|
||||
// v1 < v2
|
||||
return -1;
|
||||
}
|
||||
} else if (typeof v2[i] == "undefined" || v2[i] === null) {
|
||||
if (v1[i] === 0) {
|
||||
continue;
|
||||
} else {
|
||||
// v1 > v2
|
||||
return 1;
|
||||
}
|
||||
} else if (v2[i] > v1[i]) {
|
||||
// v1 < v2
|
||||
return -1;
|
||||
} else if (v2[i] < v1[i]) {
|
||||
// v1 > v2
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// v1 == v2
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this is at least specified tomahawk-api-version.
|
||||
*/
|
||||
Tomahawk.atLeastVersion = function (version) {
|
||||
return (Tomahawk.versionCompare(Tomahawk.apiVersion, version) >= 0);
|
||||
};
|
||||
|
||||
Tomahawk.resolver = {
|
||||
scriptPath: Tomahawk.resolverData().scriptPath
|
||||
};
|
||||
|
||||
Tomahawk.timestamp = function () {
|
||||
return Math.round(new Date() / 1000);
|
||||
};
|
||||
|
||||
Tomahawk.htmlDecode = (function () {
|
||||
// this prevents any overhead from creating the object each time
|
||||
var element = document.createElement('textarea');
|
||||
|
||||
function decodeHTMLEntities(str) {
|
||||
if (str && typeof str === 'string') {
|
||||
str = str.replace(/</g, "<");
|
||||
str = str.replace(/>/g, ">");
|
||||
element.innerHTML = str;
|
||||
str = element.textContent;
|
||||
element.textContent = '';
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
return decodeHTMLEntities;
|
||||
})();
|
||||
|
||||
Tomahawk.dumpResult = function (result) {
|
||||
var results = result.results;
|
||||
@@ -147,173 +51,6 @@ Tomahawk.dumpResult = function (result) {
|
||||
Tomahawk.log("Done.");
|
||||
};
|
||||
|
||||
// javascript part of Tomahawk-Object API
|
||||
Tomahawk.extend = function (object, members) {
|
||||
var F = function () {};
|
||||
F.prototype = object;
|
||||
var newObject = new F();
|
||||
|
||||
for (var key in members) {
|
||||
newObject[key] = members[key];
|
||||
}
|
||||
|
||||
return newObject;
|
||||
};
|
||||
|
||||
//Deprecated for 0.9 resolvers. Reporting resolver capabilities is no longer necessary.
|
||||
var TomahawkResolverCapability = {
|
||||
NullCapability: 0,
|
||||
Browsable: 1,
|
||||
PlaylistSync: 2,
|
||||
AccountFactory: 4,
|
||||
UrlLookup: 8
|
||||
};
|
||||
|
||||
//Deprecated for 0.9 resolvers. Use Tomahawk.UrlType instead.
|
||||
var TomahawkUrlType = {
|
||||
Any: 0,
|
||||
Playlist: 1,
|
||||
Track: 2,
|
||||
Album: 4,
|
||||
Artist: 8,
|
||||
Xspf: 16
|
||||
};
|
||||
|
||||
//Deprecated for 0.9 resolvers. Use Tomahawk.ConfigTestResultType instead.
|
||||
var TomahawkConfigTestResultType = {
|
||||
Other: 0,
|
||||
Success: 1,
|
||||
Logout: 2,
|
||||
CommunicationError: 3,
|
||||
InvalidCredentials: 4,
|
||||
InvalidAccount: 5,
|
||||
PlayingElsewhere: 6,
|
||||
AccountExpired: 7
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolver BaseObject, inherit it to implement your own resolver.
|
||||
*/
|
||||
var TomahawkResolver = {
|
||||
init: function () {
|
||||
},
|
||||
scriptPath: function () {
|
||||
return Tomahawk.resolverData().scriptPath;
|
||||
},
|
||||
getConfigUi: function () {
|
||||
return {};
|
||||
},
|
||||
getUserConfig: function () {
|
||||
return JSON.parse(window.localStorage[this.scriptPath()] || "{}");
|
||||
},
|
||||
saveUserConfig: function () {
|
||||
var configJson = JSON.stringify(Tomahawk.resolverData().config);
|
||||
window.localStorage[this.scriptPath()] = configJson;
|
||||
this.newConfigSaved();
|
||||
},
|
||||
newConfigSaved: function () {
|
||||
},
|
||||
resolve: function (qid, artist, album, title) {
|
||||
return {
|
||||
qid: qid
|
||||
};
|
||||
},
|
||||
search: function (qid, searchString) {
|
||||
return this.resolve(qid, "", "", searchString);
|
||||
},
|
||||
artists: function (qid) {
|
||||
return {
|
||||
qid: qid
|
||||
};
|
||||
},
|
||||
albums: function (qid, artist) {
|
||||
return {
|
||||
qid: qid
|
||||
};
|
||||
},
|
||||
tracks: function (qid, artist, album) {
|
||||
return {
|
||||
qid: qid
|
||||
};
|
||||
},
|
||||
collection: function () {
|
||||
return {};
|
||||
},
|
||||
_adapter_testConfig: function (config) {
|
||||
return RSVP.Promise.resolve(this.testConfig(config)).then(function () {
|
||||
return {result: Tomahawk.ConfigTestResultType.Success};
|
||||
});
|
||||
},
|
||||
testConfig: function () {
|
||||
this.configTest();
|
||||
},
|
||||
getStreamUrl: function (qid, url) {
|
||||
Tomahawk.reportStreamUrl(qid, url);
|
||||
}
|
||||
};
|
||||
|
||||
Tomahawk.Resolver = {
|
||||
init: function () {
|
||||
},
|
||||
scriptPath: function () {
|
||||
return Tomahawk.resolverData().scriptPath;
|
||||
},
|
||||
getConfigUi: function () {
|
||||
return {};
|
||||
},
|
||||
getUserConfig: function () {
|
||||
return JSON.parse(window.localStorage[this.scriptPath()] || "{}");
|
||||
},
|
||||
saveUserConfig: function () {
|
||||
window.localStorage[this.scriptPath()] = JSON.stringify(Tomahawk.resolverData().config);
|
||||
this.newConfigSaved(Tomahawk.resolverData().config);
|
||||
},
|
||||
newConfigSaved: function () {
|
||||
},
|
||||
testConfig: function () {
|
||||
},
|
||||
getStreamUrl: function (params) {
|
||||
return params;
|
||||
},
|
||||
getDownloadUrl: function (params) {
|
||||
return params;
|
||||
},
|
||||
resolve: function() {
|
||||
},
|
||||
_adapter_resolve: function (params) {
|
||||
return RSVP.Promise.resolve(this.resolve(params)).then(function (results) {
|
||||
if(Array.isArray(results)) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_search: function (params) {
|
||||
return RSVP.Promise.resolve(this.search(params)).then(function (results) {
|
||||
if(Array.isArray(results)) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
}
|
||||
|
||||
return results;
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_testConfig: function (config) {
|
||||
return RSVP.Promise.resolve(this.testConfig(config)).then(function (results) {
|
||||
results = results || Tomahawk.ConfigTestResultType.Success;
|
||||
return results;
|
||||
}, function (error) {
|
||||
return error;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// help functions
|
||||
|
||||
Tomahawk.valueForSubNode = function (node, tag) {
|
||||
@@ -329,6 +66,7 @@ Tomahawk.valueForSubNode = function (node, tag) {
|
||||
return element.textContent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal counter used to identify retrievedMetadata call back from native
|
||||
* code.
|
||||
@@ -385,177 +123,46 @@ Tomahawk.retrievedMetadata = function (metadataId, metadata, error) {
|
||||
};
|
||||
|
||||
/**
|
||||
* This method is externalized from Tomahawk.asyncRequest, so that other clients
|
||||
* (like tomahawk-android) can inject their own logic that determines whether or not to do a request
|
||||
* natively.
|
||||
*
|
||||
* @returns boolean indicating whether or not to do a request with the given parameters natively
|
||||
* Internal counter used to identify asyncRequest callback from native code.
|
||||
*/
|
||||
var shouldDoNativeRequest = function (options) {
|
||||
var extraHeaders = options.headers;
|
||||
return (extraHeaders && (extraHeaders.hasOwnProperty("Referer")
|
||||
|| extraHeaders.hasOwnProperty("referer")
|
||||
|| extraHeaders.hasOwnProperty("User-Agent")));
|
||||
};
|
||||
Tomahawk.asyncRequestIdCounter = 0;
|
||||
/**
|
||||
* Internal map used to map asyncRequestIds to the respective javascript
|
||||
* callback functions.
|
||||
*/
|
||||
Tomahawk.asyncRequestCallbacks = {};
|
||||
|
||||
/**
|
||||
* Possible options:
|
||||
* - url: The URL to call
|
||||
* - method: The HTTP request method (default: GET)
|
||||
* - username: The username for HTTP Basic Auth
|
||||
* - password: The password for HTTP Basic Auth
|
||||
* - errorHandler: callback called if the request was not completed
|
||||
* - data: body data included in POST requests
|
||||
* - needCookieHeader: boolean indicating whether or not the request needs to be able to get the
|
||||
* "Set-Cookie" response header
|
||||
* - headers: headers set on the request
|
||||
* Pass the natively retrieved reply back to the javascript callback
|
||||
* and augment the fake XMLHttpRequest object.
|
||||
*
|
||||
* Internal use only!
|
||||
*/
|
||||
var doRequest = function(options) {
|
||||
if (shouldDoNativeRequest(options)) {
|
||||
return Tomahawk.NativeScriptJobManager.invoke('httpRequest', options).then(function(xhr) {
|
||||
xhr.responseHeaders = xhr.responseHeaders || {};
|
||||
xhr.getAllResponseHeaders = function() {
|
||||
return this.responseHeaders;
|
||||
};
|
||||
xhr.getResponseHeader = function (header) {
|
||||
for(key in xhr.responseHeaders) {
|
||||
if(key.toLowerCase() === header.toLowerCase()) {
|
||||
return xhr.responseHeaders[key];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
return xhr;
|
||||
});
|
||||
} else {
|
||||
return new RSVP.Promise(function(resolve, reject) {
|
||||
var xmlHttpRequest = new XMLHttpRequest();
|
||||
xmlHttpRequest.open(options.method, options.url, true, options.username, options.password);
|
||||
if (options.headers) {
|
||||
for (var headerName in options.headers) {
|
||||
xmlHttpRequest.setRequestHeader(headerName, options.headers[headerName]);
|
||||
}
|
||||
}
|
||||
xmlHttpRequest.onreadystatechange = function () {
|
||||
if (xmlHttpRequest.readyState == 4
|
||||
&& httpSuccessStatuses.indexOf(xmlHttpRequest.status) != -1) {
|
||||
resolve(xmlHttpRequest);
|
||||
} else if (xmlHttpRequest.readyState === 4) {
|
||||
Tomahawk.log("Failed to do " + options.method + " request: to: " + options.url);
|
||||
Tomahawk.log("Status Code was: " + xmlHttpRequest.status);
|
||||
reject(xmlHttpRequest);
|
||||
}
|
||||
};
|
||||
xmlHttpRequest.send(options.data || null);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Tomahawk.ajax = function (url, settings) {
|
||||
if (typeof url === "object") {
|
||||
settings = url;
|
||||
} else {
|
||||
settings = settings || {};
|
||||
settings.url = url;
|
||||
Tomahawk.nativeAsyncRequestDone = function (reqId, xhr) {
|
||||
// Check that we have a matching callback stored.
|
||||
if (!Tomahawk.asyncRequestCallbacks.hasOwnProperty(reqId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
settings.type = settings.type || settings.method || 'get';
|
||||
settings.method = settings.type;
|
||||
settings.dataFormat = settings.dataFormat || 'form';
|
||||
|
||||
if (settings.data) {
|
||||
var formEncode = function (obj) {
|
||||
var str = [];
|
||||
for (var p in obj) {
|
||||
if (obj[p] !== undefined) {
|
||||
if (Array.isArray(obj[p])) {
|
||||
for (var i = 0; i < obj[p].length; i++) {
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p][i]));
|
||||
}
|
||||
} else {
|
||||
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
str.sort();
|
||||
|
||||
return str.join("&");
|
||||
};
|
||||
if (typeof settings.data === 'object') {
|
||||
if (settings.dataFormat == 'form') {
|
||||
settings.data = formEncode(settings.data);
|
||||
settings.contentType = settings.contentType || 'application/x-www-form-urlencoded';
|
||||
} else if (settings.dataFormat == 'json') {
|
||||
settings.data = JSON.stringify(settings.data);
|
||||
settings.contentType = settings.contentType || 'application/json';
|
||||
} else {
|
||||
throw new Error("Tomahawk.ajax: unknown dataFormat requested: "
|
||||
+ settings.dataFormat);
|
||||
}
|
||||
} else {
|
||||
throw new Error("Tomahawk.ajax: data should be either object or string");
|
||||
// Call the real callback
|
||||
if (xhr.readyState == 4 && httpSuccessStatuses.indexOf(xhr.status) != -1) {
|
||||
// Call the real callback
|
||||
if (Tomahawk.asyncRequestCallbacks[reqId].callback) {
|
||||
Tomahawk.asyncRequestCallbacks[reqId].callback(xhr);
|
||||
}
|
||||
|
||||
if (settings.type.toLowerCase() === 'get') {
|
||||
settings.url += '?' + settings.data;
|
||||
delete settings.data;
|
||||
} else {
|
||||
settings.headers = settings.headers || {};
|
||||
if (!settings.headers.hasOwnProperty('Content-Type')) {
|
||||
settings.headers['Content-Type'] = settings.contentType;
|
||||
}
|
||||
} else if (xhr.readyState === 4) {
|
||||
Tomahawk.log("Failed to do nativeAsyncRequest");
|
||||
Tomahawk.log("Status Code was: " + xhr.status);
|
||||
if (Tomahawk.asyncRequestCallbacks[reqId].errorHandler) {
|
||||
Tomahawk.asyncRequestCallbacks[reqId].errorHandler(xhr);
|
||||
}
|
||||
}
|
||||
|
||||
return doRequest(settings).then(function (xhr) {
|
||||
if (settings.rawResponse) {
|
||||
return xhr;
|
||||
}
|
||||
var responseText = xhr.responseText;
|
||||
var contentType;
|
||||
if (settings.dataType === 'json') {
|
||||
contentType = 'application/json';
|
||||
} else if (settings.dataType === 'xml') {
|
||||
contentType = 'text/xml';
|
||||
} else if (typeof xhr.getResponseHeader !== 'undefined') {
|
||||
contentType = xhr.getResponseHeader('Content-Type');
|
||||
} else if (xhr.hasOwnProperty('contentType')) {
|
||||
contentType = xhr['contentType'];
|
||||
} else {
|
||||
contentType = 'text/html';
|
||||
}
|
||||
|
||||
if (~contentType.indexOf('application/json')) {
|
||||
return JSON.parse(responseText);
|
||||
}
|
||||
|
||||
if (~contentType.indexOf('text/xml')) {
|
||||
var domParser = new DOMParser();
|
||||
return domParser.parseFromString(responseText, "text/xml");
|
||||
}
|
||||
|
||||
return xhr.responseText;
|
||||
});
|
||||
// Callbacks are only used once.
|
||||
delete Tomahawk.asyncRequestCallbacks[reqId];
|
||||
};
|
||||
|
||||
Tomahawk.post = function (url, settings) {
|
||||
if (typeof url === "object") {
|
||||
settings = url;
|
||||
} else {
|
||||
settings = settings || {};
|
||||
settings.url = url;
|
||||
}
|
||||
|
||||
settings.method = 'POST';
|
||||
|
||||
return Tomahawk.ajax(settings);
|
||||
};
|
||||
|
||||
Tomahawk.get = function (url, settings) {
|
||||
return Tomahawk.ajax(url, settings);
|
||||
};
|
||||
|
||||
Tomahawk.assert = function (assertion, message) {
|
||||
Tomahawk.nativeAssert(assertion, message);
|
||||
@@ -572,127 +179,6 @@ Tomahawk.hmac = function (key, message) {
|
||||
return CryptoJS.HmacMD5(message, key).toString(CryptoJS.enc.Hex);
|
||||
};
|
||||
|
||||
// Extracted from https://github.com/andrewrk/diacritics version 1.2.0
|
||||
// Thanks to Andrew Kelley for this MIT-licensed diacritic removal code
|
||||
// Initialisation / precomputation
|
||||
(function() {
|
||||
var replacementList = [
|
||||
{base: ' ', chars: "\u00A0"},
|
||||
{base: '0', chars: "\u07C0"},
|
||||
{base: 'A', chars: "\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F"},
|
||||
{base: 'AA', chars: "\uA732"},
|
||||
{base: 'AE', chars: "\u00C6\u01FC\u01E2"},
|
||||
{base: 'AO', chars: "\uA734"},
|
||||
{base: 'AU', chars: "\uA736"},
|
||||
{base: 'AV', chars: "\uA738\uA73A"},
|
||||
{base: 'AY', chars: "\uA73C"},
|
||||
{base: 'B', chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181"},
|
||||
{base: 'C', chars: "\uFF43\u24b8\uff23\uA73E\u1E08"},
|
||||
{base: 'D', chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779"},
|
||||
{base: 'Dh', chars: "\u00D0"},
|
||||
{base: 'DZ', chars: "\u01F1\u01C4"},
|
||||
{base: 'Dz', chars: "\u01F2\u01C5"},
|
||||
{base: 'E', chars: "\u025B\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E\u1D07"},
|
||||
{base: 'F', chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B"},
|
||||
{base: 'G', chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262"},
|
||||
{base: 'H', chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D"},
|
||||
{base: 'I', chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197"},
|
||||
{base: 'J', chars: "\u24BF\uFF2A\u0134\u0248\u0237"},
|
||||
{base: 'K', chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2"},
|
||||
{base: 'L', chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780"},
|
||||
{base: 'LJ', chars: "\u01C7"},
|
||||
{base: 'Lj', chars: "\u01C8"},
|
||||
{base: 'M', chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB"},
|
||||
{base: 'N', chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E"},
|
||||
{base: 'NJ', chars: "\u01CA"},
|
||||
{base: 'Nj', chars: "\u01CB"},
|
||||
{base: 'O', chars: "\u24C4\uFF2F\xD2\xD3\xD4\u1ED2\u1ED0\u1ED6\u1ED4\xD5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\xD6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\xD8\u01FE\u0186\u019F\uA74A\uA74C"},
|
||||
{base: 'OE', chars: "\u0152"},
|
||||
{base: 'OI', chars: "\u01A2"},
|
||||
{base: 'OO', chars: "\uA74E"},
|
||||
{base: 'OU', chars: "\u0222"},
|
||||
{base: 'P', chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754"},
|
||||
{base: 'Q', chars: "\u24C6\uFF31\uA756\uA758\u024A"},
|
||||
{base: 'R', chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782"},
|
||||
{base: 'S', chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784"},
|
||||
{base: 'T', chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786"},
|
||||
{base: 'Th', chars: "\u00DE"},
|
||||
{base: 'TZ', chars: "\uA728"},
|
||||
{base: 'U', chars: "\u24CA\uFF35\xD9\xDA\xDB\u0168\u1E78\u016A\u1E7A\u016C\xDC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244"},
|
||||
{base: 'V', chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245"},
|
||||
{base: 'VY', chars: "\uA760"},
|
||||
{base: 'W', chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72"},
|
||||
{base: 'X', chars: "\u24CD\uFF38\u1E8A\u1E8C"},
|
||||
{base: 'Y', chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE"},
|
||||
{base: 'Z', chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762"},
|
||||
{base: 'a', chars: "\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0251"},
|
||||
{base: 'aa', chars: "\uA733"},
|
||||
{base: 'ae', chars: "\u00E6\u01FD\u01E3"},
|
||||
{base: 'ao', chars: "\uA735"},
|
||||
{base: 'au', chars: "\uA737"},
|
||||
{base: 'av', chars: "\uA739\uA73B"},
|
||||
{base: 'ay', chars: "\uA73D"},
|
||||
{base: 'b', chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182"},
|
||||
{base: 'c', chars: "\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184\u0043\u0106\u0108\u010A\u010C\u00C7\u0187\u023B"},
|
||||
{base: 'd', chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA"},
|
||||
{base: 'dh', chars: "\u00F0"},
|
||||
{base: 'dz', chars: "\u01F3\u01C6"},
|
||||
{base: 'e', chars: "\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u01DD"},
|
||||
{base: 'f', chars: "\u24D5\uFF46\u1E1F\u0192"},
|
||||
{base: 'ff', chars: "\uFB00"},
|
||||
{base: 'fi', chars: "\uFB01"},
|
||||
{base: 'fl', chars: "\uFB02"},
|
||||
{base: 'ffi', chars: "\uFB03"},
|
||||
{base: 'ffl', chars: "\uFB04"},
|
||||
{base: 'g', chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79"},
|
||||
{base: 'h', chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265"},
|
||||
{base: 'hv', chars: "\u0195"},
|
||||
{base: 'i', chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131"},
|
||||
{base: 'j', chars: "\u24D9\uFF4A\u0135\u01F0\u0249"},
|
||||
{base: 'k', chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3"},
|
||||
{base: 'l', chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D"},
|
||||
{base: 'lj', chars: "\u01C9"},
|
||||
{base: 'm', chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F"},
|
||||
{base: 'n', chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509"},
|
||||
{base: 'nj', chars: "\u01CC"},
|
||||
{base: 'o', chars: "\u24DE\uFF4F\xF2\xF3\xF4\u1ED3\u1ED1\u1ED7\u1ED5\xF5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\xF6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\xF8\u01FF\uA74B\uA74D\u0275\u0254\u1D11"},
|
||||
{base: 'oe', chars: "\u0153"},
|
||||
{base: 'oi', chars: "\u01A3"},
|
||||
{base: 'oo', chars: "\uA74F"},
|
||||
{base: 'ou', chars: "\u0223"},
|
||||
{base: 'p', chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1"},
|
||||
{base: 'q', chars: "\u24E0\uFF51\u024B\uA757\uA759"},
|
||||
{base: 'r', chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783"},
|
||||
{base: 's', chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282"},
|
||||
{base: 'ss', chars: "\xDF"},
|
||||
{base: 't', chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787"},
|
||||
{base: 'th', chars: "\u00FE"},
|
||||
{base: 'tz', chars: "\uA729"},
|
||||
{base: 'u', chars: "\u24E4\uFF55\xF9\xFA\xFB\u0169\u1E79\u016B\u1E7B\u016D\xFC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289"},
|
||||
{base: 'v', chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C"},
|
||||
{base: 'vy', chars: "\uA761"},
|
||||
{base: 'w', chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73"},
|
||||
{base: 'x', chars: "\u24E7\uFF58\u1E8B\u1E8D"},
|
||||
{base: 'y', chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF"},
|
||||
{base: 'z', chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763"}
|
||||
];
|
||||
|
||||
Tomahawk.diacriticsMap = {};
|
||||
var i, j, chars;
|
||||
for (i = 0; i < replacementList.length; i += 1) {
|
||||
chars = replacementList[i].chars;
|
||||
for (j = 0; j < chars.length; j += 1) {
|
||||
Tomahawk.diacriticsMap[chars[j]] = replacementList[i].base;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
Tomahawk.removeDiacritics = function (str) {
|
||||
return str.replace(/[^\u0000-\u007E]/g, function (c) {
|
||||
return Tomahawk.diacriticsMap[c] || c;
|
||||
});
|
||||
};
|
||||
|
||||
Tomahawk.localStorage = Tomahawk.localStorage || {
|
||||
setItem: function (key, value) {
|
||||
window.localStorage[key] = value;
|
||||
@@ -715,113 +201,24 @@ Tomahawk.base64Encode = function (b) {
|
||||
return window.btoa(b);
|
||||
};
|
||||
|
||||
Tomahawk.PluginManager = {
|
||||
wrapperPrefix: '_adapter_',
|
||||
objects: {},
|
||||
objectCounter: 0,
|
||||
identifyObject: function (object) {
|
||||
if (!object.hasOwnProperty('id')) {
|
||||
object.id = this.objectCounter++;
|
||||
}
|
||||
|
||||
return object.id;
|
||||
},
|
||||
registerPlugin: function (type, object) {
|
||||
this.objects[this.identifyObject(object)] = object;
|
||||
Tomahawk.log("registerPlugin: " + type + " id: " + object.id);
|
||||
Tomahawk.registerScriptPlugin(type, object.id);
|
||||
},
|
||||
|
||||
unregisterPlugin: function (type, object) {
|
||||
this.objects[this.identifyObject(object)] = object;
|
||||
|
||||
Tomahawk.log("unregisterPlugin: " + type + " id: " + object.id);
|
||||
Tomahawk.unregisterScriptPlugin(type, object.id);
|
||||
},
|
||||
|
||||
resolve: [],
|
||||
invokeSync: function (requestId, objectId, methodName, params) {
|
||||
if (this.objects[objectId][this.wrapperPrefix + methodName]) {
|
||||
methodName = this.wrapperPrefix + methodName;
|
||||
}
|
||||
|
||||
if (!this.objects[objectId]) {
|
||||
Tomahawk.log("Object not found! objectId: " + objectId + " methodName: " + methodName);
|
||||
} else {
|
||||
if (!this.objects[objectId][methodName]) {
|
||||
Tomahawk.log("Function not found: " + methodName);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.objects[objectId][methodName] !== 'function' && this.objects[objectId][methodName]) {
|
||||
return this.objects[objectId][methodName];
|
||||
} else if (typeof this.objects[objectId][methodName] !== 'function') {
|
||||
throw new Error('\'' + methodName + '\' on ScriptObject ' + objectId + ' is not a function', typeof this.objects[objectId][methodName]);
|
||||
}
|
||||
|
||||
return this.objects[objectId][methodName](params);
|
||||
},
|
||||
|
||||
invoke: function (requestId, objectId, methodName, params) {
|
||||
RSVP.Promise.resolve(this.invokeSync(requestId, objectId, methodName, params))
|
||||
.then(function (result) {
|
||||
var params = {
|
||||
requestId: requestId,
|
||||
data: result
|
||||
};
|
||||
Tomahawk.reportScriptJobResults(encodeParamsToNativeFunctions(params));
|
||||
}, function (error) {
|
||||
var params = {
|
||||
requestId: requestId,
|
||||
error: error
|
||||
};
|
||||
Tomahawk.reportScriptJobResults(encodeParamsToNativeFunctions(params));
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var encodeParamsToNativeFunctions = function(param) {
|
||||
return param;
|
||||
};
|
||||
|
||||
Tomahawk.NativeScriptJobManager = {
|
||||
idCounter: 0,
|
||||
deferreds: {},
|
||||
invoke: function (methodName, params) {
|
||||
params = params || {};
|
||||
|
||||
var requestId = this.idCounter++;
|
||||
var deferred = RSVP.defer();
|
||||
this.deferreds[requestId] = deferred;
|
||||
Tomahawk.invokeNativeScriptJob(requestId, methodName, encodeParamsToNativeFunctions(params));
|
||||
return deferred.promise;
|
||||
Tomahawk.invokeNativeScriptJob(requestId, methodName, JSON.stringify(params));
|
||||
this.deferreds[requestId] = RSVP.defer();
|
||||
return this.deferreds[requestId].promise;
|
||||
},
|
||||
reportNativeScriptJobResult: function(requestId, result) {
|
||||
reportNativeScriptJobResult: function (requestId, result) {
|
||||
var deferred = this.deferreds[requestId];
|
||||
if (!deferred) {
|
||||
Tomahawk.log("Deferred object with the given requestId is not present!");
|
||||
}
|
||||
deferred.resolve(result);
|
||||
delete this.deferreds[requestId];
|
||||
},
|
||||
reportNativeScriptJobError: function(requestId, error) {
|
||||
var deferred = this.deferreds[requestId];
|
||||
if (!deferred) {
|
||||
console.log("Deferred object with the given requestId is not present!");
|
||||
}
|
||||
deferred.reject(error);
|
||||
delete this.deferreds[requestId];
|
||||
}
|
||||
};
|
||||
|
||||
Tomahawk.UrlType = {
|
||||
Any: 0,
|
||||
Playlist: 1,
|
||||
Track: 2,
|
||||
Album: 3,
|
||||
Artist: 4,
|
||||
XspfPlaylist: 5
|
||||
};
|
||||
<<<<<<< HEAD
|
||||
|
||||
Tomahawk.ConfigTestResultType = {
|
||||
Other: 0,
|
||||
@@ -1462,7 +859,9 @@ Tomahawk.Collection = {
|
||||
return new RSVP.Promise(function (resolve, reject) {
|
||||
that.cachedDbs[id].changeVersion(that.cachedDbs[id].version, "", null,
|
||||
function (err) {
|
||||
Tomahawk.error("Error trying to change db version!", err);
|
||||
if (console.error) {
|
||||
console.error("Error!: %o", err);
|
||||
}
|
||||
reject();
|
||||
}, function () {
|
||||
delete that.cachedDbs[id];
|
||||
@@ -1474,10 +873,6 @@ Tomahawk.Collection = {
|
||||
});
|
||||
},
|
||||
|
||||
revision: function (params) {
|
||||
return RSVP.resolve();
|
||||
},
|
||||
|
||||
_fuzzyIndexIdsToTracks: function (resultIds, id) {
|
||||
if (typeof id === 'undefined') {
|
||||
id = this.settings.id;
|
||||
@@ -1529,14 +924,6 @@ Tomahawk.Collection = {
|
||||
});
|
||||
},
|
||||
|
||||
_adapter_resolve: function (params) {
|
||||
return RSVP.Promise.resolve(this.resolve(params)).then(function (results) {
|
||||
return {
|
||||
'tracks': results
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
resolve: function (params) {
|
||||
var resultIds = Tomahawk.resolveFromFuzzyIndex(params.artist, params.album, params.track);
|
||||
return this._fuzzyIndexIdsToTracks(resultIds);
|
||||
@@ -1544,12 +931,7 @@ Tomahawk.Collection = {
|
||||
|
||||
search: function (params) {
|
||||
var resultIds = Tomahawk.searchFuzzyIndex(params.query);
|
||||
|
||||
return this._fuzzyIndexIdsToTracks(resultIds).then(function(tracks) {
|
||||
return {
|
||||
tracks: tracks
|
||||
};
|
||||
});
|
||||
return this._fuzzyIndexIdsToTracks(resultIds);
|
||||
},
|
||||
|
||||
tracks: function (params, where) {
|
||||
@@ -1593,7 +975,7 @@ Tomahawk.Collection = {
|
||||
);
|
||||
return t.execDeferredStatements();
|
||||
}).then(function (results) {
|
||||
return {tracks: results[0]};
|
||||
return {results: resolverInstance._convertUrls(results[0])};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1766,25 +1148,74 @@ 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;
|
||||
},
|
||||
|
||||
getStreamUrl: function(params) {
|
||||
if(this.resolver) {
|
||||
return this.resolver.getStreamUrl(params);
|
||||
}
|
||||
|
||||
return params;
|
||||
},
|
||||
|
||||
getDownloadUrl: function(params) {
|
||||
if(this.resolver) {
|
||||
return this.resolver.getDownloadUrl(params);
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
};
|
||||
|
||||
// Legacy compability for 0.8 and before
|
||||
Tomahawk.reportCapabilities = function (capabilities) {
|
||||
if (capabilities & TomahawkResolverCapability.Browsable) {
|
||||
Tomahawk.PluginManager.registerPlugin("collection", Tomahawk.resolver.instance);
|
||||
}
|
||||
|
||||
Tomahawk.nativeReportCapabilities(capabilities);
|
||||
};
|
||||
|
||||
Tomahawk.addArtistResults = Tomahawk.addAlbumResults = Tomahawk.addAlbumTrackResults
|
||||
= function (result) {
|
||||
Tomahawk.PluginManager.resolve[result.qid](result);
|
||||
delete Tomahawk.PluginManager.resolve[result.qid];
|
||||
};
|
||||
|
||||
Tomahawk.addTrackResults = function (result) {
|
||||
Tomahawk.PluginManager.resolve[result.qid](result.results);
|
||||
delete Tomahawk.PluginManager.resolve[result.qid];
|
||||
};
|
||||
|
||||
Tomahawk.reportStreamUrl = function (qid, streamUrl, headers) {
|
||||
Tomahawk.PluginManager.resolve[qid]({
|
||||
url: streamUrl,
|
||||
headers: headers
|
||||
});
|
||||
delete Tomahawk.PluginManager.resolve[qid];
|
||||
};
|
||||
|
||||
Tomahawk.addUrlResult = function (url, result) {
|
||||
/* Merge the whole mess into one consistent result which is independent of type
|
||||
var cleanResult = {
|
||||
type: result.type,
|
||||
guid: result.guid,
|
||||
info: result.info,
|
||||
creator: result.creator,
|
||||
linkUrl: result.url
|
||||
};
|
||||
if (cleanResult.type == "track") {
|
||||
cleanResult.track = result.title;
|
||||
cleanResult.artist = result.artist;
|
||||
} else if (cleanResult.type == "artist") {
|
||||
cleanResult.artist = result.name;
|
||||
} else if (cleanResult.type == "album") {
|
||||
cleanResult.album = result.name;
|
||||
cleanResult.artist = result.artist;
|
||||
} else if (cleanResult.type == "playlist") {
|
||||
cleanResult.title = result.title;
|
||||
} else if (cleanResult.type == "xspf-url") {
|
||||
cleanResult.url = result.url;
|
||||
}
|
||||
if (result.tracks) {
|
||||
cleanResult.tracks = [];
|
||||
var i;
|
||||
for (i=0;i<result.tracks.length;i++) {
|
||||
var cleanTrack = {
|
||||
track: result.tracks[i].title,
|
||||
artist: result.tracks[i].artist
|
||||
};
|
||||
cleanResult.push(cleanTrack)
|
||||
}
|
||||
Tomahawk.PluginManager.resolve[url](cleanResult);
|
||||
*/
|
||||
Tomahawk.PluginManager.resolve[url](result);
|
||||
delete Tomahawk.PluginManager.resolve[url];
|
||||
};
|
||||
=======
|
||||
>>>>>>> Move moar stuff over to es6 foo
|
||||
|
Binary file not shown.
@@ -3,7 +3,6 @@
|
||||
<file>data/images/collection_background.png</file>
|
||||
<file>data/images/playlist_background.png</file>
|
||||
<file>data/images/filter.svg</file>
|
||||
<file>data/images/folder.svg</file>
|
||||
<file>data/images/loved.svg</file>
|
||||
<file>data/images/love.svg</file>
|
||||
<file>data/images/not-loved.svg</file>
|
||||
@@ -168,8 +167,5 @@
|
||||
<file>data/images/repeat-one.svg</file>
|
||||
<file>data/images/downloads.svg</file>
|
||||
<file>data/images/downloadbutton.svg</file>
|
||||
<file>data/images/nav-back.svg</file>
|
||||
<file>data/images/nav-forward.svg</file>
|
||||
<file>data/sounds/silence.ogg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -24,6 +24,13 @@ include_directories(
|
||||
|
||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||
|
||||
if(APPLE)
|
||||
# http://stackoverflow.com/questions/7226753/osx-lion-xcode-4-1-how-do-i-setup-a-c0x-project/7236451#7236451
|
||||
add_definitions(-std=c++11 -stdlib=libc++ -U__STRICT_ANSI__)
|
||||
set(PLATFORM_SPECIFIC_LINK_LIBRARIES "/usr/lib/libc++.dylib")
|
||||
else()
|
||||
add_definitions(-std=c++0x)
|
||||
endif()
|
||||
|
||||
tomahawk_add_plugin(hatchet
|
||||
TYPE account
|
||||
|
@@ -69,13 +69,6 @@ Tomahawk::InfoSystem::XmppInfoPlugin::init()
|
||||
}
|
||||
|
||||
|
||||
const QString
|
||||
Tomahawk::InfoSystem::XmppInfoPlugin::friendlyName() const
|
||||
{
|
||||
return "xmpp";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
{
|
||||
|
@@ -38,18 +38,16 @@ namespace Tomahawk {
|
||||
XmppInfoPlugin(XmppSipPlugin* parent);
|
||||
virtual ~XmppInfoPlugin();
|
||||
|
||||
const QString friendlyName() const override;
|
||||
|
||||
signals:
|
||||
void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
|
||||
|
||||
public slots:
|
||||
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData ) override;
|
||||
void notInCacheSlot( const Tomahawk::InfoSystem::InfoStringHash criteria, Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
protected slots:
|
||||
void init() override;
|
||||
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData ) override;
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData ) override;
|
||||
void init();
|
||||
void pushInfo( Tomahawk::InfoSystem::InfoPushData pushData );
|
||||
void getInfo( Tomahawk::InfoSystem::InfoRequestData requestData );
|
||||
|
||||
private slots:
|
||||
void audioStarted( const Tomahawk::InfoSystem::PushInfoPair& pushInfoPair );
|
||||
|
@@ -194,9 +194,9 @@ InfoSystem::InfoPluginPtr
|
||||
XmppSipPlugin::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
m_infoPlugin = QSharedPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
|
||||
m_infoPlugin = QPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
|
||||
|
||||
return m_infoPlugin;
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ XmppSipPlugin::onConnect()
|
||||
// load XmppInfoPlugin
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
@@ -359,6 +359,7 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
if ( !m_infoPlugin.isNull() )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
delete m_infoPlugin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -128,7 +128,7 @@ private:
|
||||
int m_currentPort;
|
||||
QString m_currentResource;
|
||||
|
||||
QSharedPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_infoPlugin;
|
||||
QPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_infoPlugin;
|
||||
Tomahawk::Accounts::Account::ConnectionState m_state;
|
||||
|
||||
// sort out
|
||||
|
@@ -54,14 +54,14 @@ public:
|
||||
Account::ConnectionState connectionState() const;
|
||||
|
||||
public slots:
|
||||
void connectPlugin() override;
|
||||
void disconnectPlugin() override;
|
||||
void connectPlugin();
|
||||
void disconnectPlugin();
|
||||
|
||||
void advertise();
|
||||
|
||||
virtual void sendSipInfos( const Tomahawk::peerinfo_ptr& /* receiver */, const QList<SipInfo>& /* info */ ) override {}
|
||||
virtual void sendSipInfos( const Tomahawk::peerinfo_ptr& /* receiver */, const QList<SipInfo>& /* info */ ) {}
|
||||
void broadcastMsg( const QString& ) {}
|
||||
bool addContact( const QString&, AddContactOptions, const QString& ) override { return false; }
|
||||
bool addContact( const QString&, AddContactOptions, const QString& ) { return false; }
|
||||
|
||||
private slots:
|
||||
void lanHostFound( const QString& host, int port, const QString& name, const QString& nodeid );
|
||||
|
@@ -174,7 +174,7 @@ int main( int argc, char* argv[] )
|
||||
reporter.setLogo( QPixmap( CRASHREPORTER_ICON ) );
|
||||
#endif
|
||||
reporter.setWindowTitle( CRASHREPORTER_PRODUCT_NAME );
|
||||
reporter.setText("<html><head/><body><p><span style=\"font-weight:600;\">Sorry!</span> " CRASHREPORTER_PRODUCT_NAME " crashed. Please tell us about it! " CRASHREPORTER_PRODUCT_NAME " has created an error report for you that can help improve the stability in the future. You can now send this report directly to the " CRASHREPORTER_PRODUCT_NAME " developers.</p><p>Can you tell us what you were doing when this happened?</p></body></html>");
|
||||
reporter.setText("<html><head/><body><p><span style=\" font-weight:600;\">Sorry!</span> " CRASHREPORTER_PRODUCT_NAME " crashed. Please tell us about it! " CRASHREPORTER_PRODUCT_NAME " has created an error report for you that can help improve the stability in the future. You can now send this report directly to the " CRASHREPORTER_PRODUCT_NAME " developers.</p></body></html>");
|
||||
|
||||
reporter.setReportData( "BuildID", CRASHREPORTER_BUILD_ID );
|
||||
reporter.setReportData( "ProductName", CRASHREPORTER_PRODUCT_NAME );
|
||||
|
@@ -1,26 +1,30 @@
|
||||
include_directories(
|
||||
${ECHONEST_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIR}
|
||||
)
|
||||
if(WIN32 OR APPLE)
|
||||
if(BUILD_GUI AND LibsnoreQt5_FOUND)
|
||||
if(BUILD_GUI AND LIBSNORE_FOUND)
|
||||
SET(snore_srcs
|
||||
snorenotify/SnoreNotifyPlugin.cpp
|
||||
)
|
||||
SET(SNORE_LINK_LIBRARIES ${LINK_LIBRARIES} ${LIBSNORE_LIBRARIES} )
|
||||
|
||||
tomahawk_add_plugin(snorenotify
|
||||
TYPE infoplugin EXPORT_MACRO INFOPLUGINDLLEXPORT_PRO
|
||||
SOURCES "${snore_srcs}" LINK_LIBRARIES Snore::Libsnore
|
||||
SOURCES "${snore_srcs}" LINK_LIBRARIES "${SNORE_LINK_LIBRARIES}"
|
||||
)
|
||||
endif()
|
||||
endif(BUILD_GUI AND LIBSNORE_FOUND)
|
||||
endif(WIN32 OR APPLE)
|
||||
|
||||
list(APPEND simple_plugins
|
||||
Echonest
|
||||
Charts
|
||||
NewReleases
|
||||
#Spotify
|
||||
Spotify
|
||||
Hypem
|
||||
MusixMatch
|
||||
MusicBrainz
|
||||
#Rovi
|
||||
Rovi
|
||||
Discogs
|
||||
)
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2013-2015, Hannah von Reth <vonreth@kde.org>
|
||||
* Copyright 2013-2014, Patrick von Reth <vonreth@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
*
|
||||
@@ -27,15 +27,27 @@
|
||||
|
||||
#include "TomahawkVersion.h"
|
||||
|
||||
#include <libsnore/application.h>
|
||||
#include <libsnore/notification/icon.h>
|
||||
#include <snore/core/application.h>
|
||||
#include <snore/core/notification/icon.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
namespace Qt
|
||||
{
|
||||
inline QString escape( const QString &x )
|
||||
{
|
||||
return x.toHtmlEscaped();
|
||||
}
|
||||
}
|
||||
#else
|
||||
// QTextDocument provides Qt::escape()
|
||||
#include <QTextDocument>
|
||||
#endif
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
@@ -49,13 +61,27 @@ SnoreNotifyPlugin::SnoreNotifyPlugin()
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped << InfoInboxReceived;
|
||||
|
||||
Snore::SnoreCore &snore = Snore::SnoreCore::instance();
|
||||
snore.loadPlugins( Snore::SnorePlugin::Backend | Snore::SnorePlugin::SecondaryBackend );
|
||||
snore.setDefaultSettingsValue("Silent", true, Snore::LocalSetting );
|
||||
m_snore = new Snore::SnoreCore();
|
||||
m_snore->loadPlugins( Snore::SnorePlugin::BACKEND );
|
||||
QString backend = qgetenv( "SNORE_BACKEND" ).constData();
|
||||
|
||||
if( backend.isEmpty() )
|
||||
{
|
||||
m_snore->setPrimaryNotificationBackend();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_snore->setPrimaryNotificationBackend( backend ) )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Ivalid or unavailible Snore backend: " << backend << " availible backens: " << m_snore->notificationBackends();
|
||||
m_snore->setPrimaryNotificationBackend();
|
||||
}
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << m_snore->primaryNotificationBackend();
|
||||
|
||||
m_application = Snore::Application( qApp->applicationName(), m_defaultIcon );
|
||||
m_application.hints().setValue( "use-markup", true );
|
||||
m_application.hints().setValue( "windows-app-id", TOMAHAWK_APPLICATION_PACKAGE_NAME );
|
||||
m_application.hints().setValue( "windows_app_id", TOMAHAWK_APPLICATION_PACKAGE_NAME );
|
||||
m_application.hints().setValue( "desktop-entry", TOMAHAWK_APPLICATION_NAME );
|
||||
|
||||
addAlert( InfoNotifyUser, tr( "Notify User" ) );
|
||||
@@ -64,10 +90,9 @@ SnoreNotifyPlugin::SnoreNotifyPlugin()
|
||||
addAlert( InfoNowStopped, tr( "Playback Stopped" ) );
|
||||
addAlert( InfoInboxReceived, tr( "You received a Song recommendation" ) );
|
||||
|
||||
snore.registerApplication( m_application );
|
||||
snore.setDefaultApplication( m_application );
|
||||
m_snore->registerApplication( m_application );
|
||||
|
||||
connect( &snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
connect( m_snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +100,8 @@ SnoreNotifyPlugin::~SnoreNotifyPlugin()
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
|
||||
Snore::SnoreCore::instance().deregisterApplication( m_application );
|
||||
m_snore->deregisterApplication( m_application );
|
||||
m_snore->deleteLater();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -85,19 +111,25 @@ SnoreNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
if ( !TomahawkSettings::instance()->songChangeNotificationEnabled() )
|
||||
return;
|
||||
|
||||
if( m_snore->primaryNotificationBackend().isNull() )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "no notification backend set";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch ( pushData.type )
|
||||
{
|
||||
case Tomahawk::InfoSystem::InfoTrackUnresolved:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoTrackUnresolved, tr( "The current track could not be resolved. %applicationName will pick back up with the next resolvable track from this source." ), m_defaultIcon );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoTrackUnresolved, tr( "The current track could not be resolved. %applicationName will pick back up with the next resolvable track from this source." ) );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNotifyUser:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNotifyUser,pushData.infoPair.second.toString(), m_defaultIcon );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNotifyUser,pushData.infoPair.second.toString() );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowStopped:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNowStopped, tr( "%applicationName stopped playback." ), m_defaultIcon );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNowStopped, tr( "%applicationName stopped playback." ) );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowPlaying:
|
||||
@@ -125,10 +157,15 @@ SnoreNotifyPlugin::slotActionInvoked( Snore::Notification n )
|
||||
void
|
||||
SnoreNotifyPlugin::notifyUser( Tomahawk::InfoSystem::InfoType type, const QString& messageText, Snore::Icon icon )
|
||||
{
|
||||
if(!icon.isValid())
|
||||
{
|
||||
icon = m_defaultIcon;
|
||||
}
|
||||
const Snore::Alert &alert = m_alerts[ type ];
|
||||
Snore::Notification n( m_application , alert, alert.name(), messageText, icon );
|
||||
Snore::SnoreCore::instance().broadcastNotification( n );
|
||||
m_snore->broadcastNotification( n );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "showing notification:" << messageText;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -157,28 +194,41 @@ SnoreNotifyPlugin::nowPlaying( const QVariant& input )
|
||||
|
||||
QString messageText;
|
||||
// If the window manager supports notification styling then use it.
|
||||
if ( m_snore->primaryBackendSupportsRichtext() )
|
||||
{
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( "<br><i>%1</i> %2" ).arg( tr( "on", "'on' is followed by an album name" ) ).arg( Qt::escape( hash[ "album" ] ) );
|
||||
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( "<br><i>%1</i> %2" ).arg( tr( "on", "'on' is followed by an album name" ) ).arg( hash[ "album" ].toHtmlEscaped() );
|
||||
messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( Qt::escape( hash[ "title" ] ) )
|
||||
.arg( Qt::escape( hash[ "artist" ] ) )
|
||||
.arg( album )
|
||||
.arg( QString( "<br><i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
|
||||
messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( hash[ "title" ].toHtmlEscaped() )
|
||||
.arg( hash[ "artist" ].toHtmlEscaped() )
|
||||
.arg( album )
|
||||
.arg( QString( "<br><i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
}
|
||||
else
|
||||
{
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( " %1" ).arg( tr( "on \"%1\"", "%1 is an album name" ).arg( hash[ "album" ] ) );
|
||||
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
messageText = tr( "\"%1\" by %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing" )
|
||||
.arg( hash[ "title" ] )
|
||||
.arg( hash[ "artist" ] )
|
||||
.arg( album );
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;
|
||||
|
||||
// If there is a cover availble use it, else use Tomahawk logo as default.
|
||||
Snore::Icon image = m_defaultIcon;
|
||||
Snore::Icon image;
|
||||
if ( map.contains( "cover" ) && map[ "cover" ].canConvert< QImage >() )
|
||||
{
|
||||
image = Snore::Icon( QPixmap::fromImage( map[ "cover" ].value< QImage >() ) );
|
||||
image = Snore::Icon( map[ "cover" ].value< QImage >() );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << image;
|
||||
}
|
||||
notifyUser( InfoNowPlaying, messageText, image );
|
||||
@@ -209,15 +259,26 @@ SnoreNotifyPlugin::inboxReceived( const QVariant& input )
|
||||
return;
|
||||
|
||||
QString messageText;
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( src["friendlyname"].toHtmlEscaped() )
|
||||
.arg( hash[ "title" ].toHtmlEscaped() )
|
||||
.arg( hash[ "artist" ].toHtmlEscaped() )
|
||||
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
// If the window manager supports notification styling then use it.
|
||||
if ( m_snore->primaryBackendSupportsRichtext() )
|
||||
{
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( Qt::escape( src["friendlyname"] ) )
|
||||
.arg( Qt::escape( hash[ "title" ] ) )
|
||||
.arg( Qt::escape( hash[ "artist" ] ) )
|
||||
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
}
|
||||
else
|
||||
{
|
||||
messageText = tr( "%1 sent you \"%2\" by %3.", "%1 is a nickname, %2 is a title, %3 is an artist" )
|
||||
.arg( src["friendlyname"] )
|
||||
.arg( hash[ "title" ] )
|
||||
.arg( hash[ "artist" ] );
|
||||
}
|
||||
|
||||
Snore::Icon icon( RESPATH "images/inbox-512x512.png" );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoInboxReceived, messageText, icon );
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2013-2015, Hannah von Reth <vonreth@kde.org>
|
||||
* Copyright 2013-2014, Patrick von Reth <vonreth@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
*
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "../../InfoPluginDllMacro.h"
|
||||
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include <libsnore/snore.h>
|
||||
#include <snore/core/snore.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@@ -63,8 +63,9 @@ protected slots:
|
||||
void slotActionInvoked(Snore::Notification n);
|
||||
|
||||
private:
|
||||
void notifyUser( InfoType type, const QString &messageText, Snore::Icon icon );
|
||||
void notifyUser( InfoType type, const QString &messageText, Snore::Icon icon = Snore::Icon() );
|
||||
void addAlert( Tomahawk::InfoSystem::InfoType type, const QString &title );
|
||||
Snore::SnoreCore *m_snore;
|
||||
Snore::Application m_application;
|
||||
Snore::Icon m_defaultIcon;
|
||||
QHash< Tomahawk::InfoSystem::InfoType, Snore::Alert > m_alerts;
|
||||
|
@@ -80,7 +80,7 @@ FdoNotifyPlugin::FdoNotifyPlugin()
|
||||
, m_wmSupportsBodyMarkup( false )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoNowResumed << InfoTrackUnresolved << InfoNowStopped << InfoInboxReceived;
|
||||
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << 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,7 +139,6 @@ FdoNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowPlaying:
|
||||
case Tomahawk::InfoSystem::InfoNowResumed:
|
||||
nowPlaying( pushData.infoPair.second );
|
||||
return;
|
||||
|
||||
|
@@ -24,7 +24,6 @@ tomahawk_add_library(${TOMAHAWK_PLAYDARAPI_LIBRARY_TARGET}
|
||||
qtcertificateaddon
|
||||
${GNUTLS_LIBRARIES}
|
||||
EXPORT TomahawkLibraryDepends
|
||||
EXPORT_MACRO TOMAHAWK_WIDGETS_EXPORT_PRO
|
||||
VERSION ${TOMAHAWK_VERSION_SHORT}
|
||||
)
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef TOMAHAWK_PLAYDARAPI_EXPORT
|
||||
# if defined (TOMAHAWK_WIDGETS_EXPORT_PRO)
|
||||
# if defined (tomahawk_playdarapi_EXPORTS)
|
||||
# define TOMAHAWK_PLAYDARAPI_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define TOMAHAWK_PLAYDARAPI_EXPORT Q_DECL_IMPORT
|
||||
|
@@ -34,7 +34,7 @@ public:
|
||||
* Creates a Playdar HTTP interface
|
||||
* @param ha Address to listen on
|
||||
* @param port Port to listen on with HTTP
|
||||
* @param sport Port to listen on with HTTPS
|
||||
* @param sport Pot to listen on with HTTPS
|
||||
* @param parent
|
||||
*/
|
||||
explicit PlaydarApi( QHostAddress ha, qint16 port, qint16 sport, QObject *parent = 0 );
|
||||
|
@@ -13,6 +13,5 @@ tomahawk_add_library(${TOMAHAWK_WIDGETS_LIBRARY_TARGET}
|
||||
SOURCES ${${TOMAHAWK_WIDGETS_LIBRARY_TARGET}_SOURCES}
|
||||
UI ${${TOMAHAWK_WIDGETS_LIBRARY_TARGET}_UI}
|
||||
EXPORT TomahawkLibraryDepends
|
||||
EXPORT_MACRO TOMAHAWK_WIDGETS_EXPORT_PRO
|
||||
VERSION ${TOMAHAWK_VERSION_SHORT}
|
||||
)
|
||||
|
@@ -23,7 +23,7 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
|
||||
#ifndef TOMAHAWK_WIDGETS_EXPORT
|
||||
# if defined (TOMAHAWK_WIDGETS_EXPORT_PRO)
|
||||
# if defined (tomahawk_widgets_EXPORTS)
|
||||
# define TOMAHAWK_WIDGETS_EXPORT Q_DECL_EXPORT
|
||||
# else
|
||||
# define TOMAHAWK_WIDGETS_EXPORT Q_DECL_IMPORT
|
||||
|
@@ -62,8 +62,6 @@ ActionCollection::~ActionCollection()
|
||||
void
|
||||
ActionCollection::initActions()
|
||||
{
|
||||
// ATTENTION: Don't set ApplicationSpecificRole for submenu actions: they won't show up on OS X (Qt 5.5)
|
||||
|
||||
QAction *latchOn = new QAction( tr( "&Listen Along" ), this );
|
||||
latchOn->setIcon( ImageRegistry::instance()->icon( RESPATH "images/headphones.svg" ) );
|
||||
m_actionCollection[ "latchOn" ] = latchOn;
|
||||
@@ -120,12 +118,9 @@ 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" ) );
|
||||
@@ -152,6 +147,7 @@ ActionCollection::initActions()
|
||||
#endif
|
||||
m_actionCollection[ "crashNow" ] = new QAction( "Crash now...", this );
|
||||
m_actionCollection[ "whatsnew_0_8" ] = new QAction( tr( "%applicationName 0.8" ) , this );
|
||||
m_actionCollection[ "whatsnew_0_8" ]->setMenuRole( QAction::ApplicationSpecificRole );
|
||||
m_actionCollection[ "reportBug" ] = new QAction( tr( "Report a Bug" ) , this );
|
||||
m_actionCollection[ "getSupport" ] = new QAction( tr( "Get Support" ) , this );
|
||||
m_actionCollection[ "helpTranslate" ] = new QAction( tr( "Help Us Translate" ) , this );
|
||||
@@ -174,8 +170,7 @@ ActionCollection::createMenuBar( QWidget *parent )
|
||||
controlsMenu->addAction( m_actionCollection[ "showOfflineSources" ] );
|
||||
controlsMenu->addSeparator();
|
||||
controlsMenu->addAction( m_actionCollection[ "createPlaylist" ] );
|
||||
// echonest is dead, disable stations
|
||||
// controlsMenu->addAction( m_actionCollection[ "createStation" ] );
|
||||
controlsMenu->addAction( m_actionCollection[ "createStation" ] );
|
||||
controlsMenu->addAction( m_actionCollection[ "importPlaylist" ] );
|
||||
controlsMenu->addAction( m_actionCollection[ "updateCollection" ] );
|
||||
controlsMenu->addAction( m_actionCollection[ "rescanCollection" ] );
|
||||
|
@@ -33,7 +33,6 @@
|
||||
|
||||
#include <QReadWriteLock>
|
||||
#include <QPixmapCache>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -76,7 +75,6 @@ Album::get( const Tomahawk::artist_ptr& artist, const QString& name, bool autoCr
|
||||
}
|
||||
|
||||
album_ptr album = album_ptr( new Album( name, artist ), &Album::deleteLater );
|
||||
album->moveToThread( QCoreApplication::instance()->thread() );
|
||||
album->setWeakRef( album.toWeakRef() );
|
||||
album->loadId( autoCreate );
|
||||
s_albumsByName.insert( key, album );
|
||||
|
@@ -36,7 +36,6 @@
|
||||
|
||||
#include <QReadWriteLock>
|
||||
#include <QPixmapCache>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -110,7 +109,6 @@ Artist::get( unsigned int id, const QString& name )
|
||||
}
|
||||
|
||||
artist_ptr a = artist_ptr( new Artist( id, name ), &Artist::deleteLater );
|
||||
a->moveToThread( QCoreApplication::instance()->thread() );
|
||||
a->setWeakRef( a.toWeakRef() );
|
||||
s_artistsByName.insert( key, a );
|
||||
|
||||
|
@@ -67,7 +67,7 @@ AtticaManager::AtticaManager( QObject* parent )
|
||||
connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) );
|
||||
|
||||
// resolvers
|
||||
// m_manager.addProviderFile( QUrl( "http://v09.bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
|
||||
const QString url = QString( "%1/resolvers/providers.xml?version=%2" ).arg( hostname() ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( QUrl( url ) ) );
|
||||
|
@@ -37,7 +37,6 @@ set( libGuiSources
|
||||
jobview/ErrorStatusMessage.cpp
|
||||
jobview/IndexingJobItem.cpp
|
||||
jobview/InboxJobItem.cpp
|
||||
jobview/ScriptErrorStatusMessage.cpp
|
||||
|
||||
playlist/InboxModel.cpp
|
||||
playlist/InboxView.cpp
|
||||
@@ -74,6 +73,9 @@ 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
|
||||
@@ -143,7 +145,6 @@ set( libGuiSources
|
||||
widgets/ClickableLabel.cpp
|
||||
widgets/ComboBox.cpp
|
||||
widgets/DropDownButton.cpp
|
||||
widgets/DownloadButton.cpp
|
||||
widgets/ElidedLabel.cpp
|
||||
widgets/FilterHeader.cpp
|
||||
widgets/CaptionLabel.cpp
|
||||
@@ -198,6 +199,7 @@ list(APPEND libSources
|
||||
MetaPlaylistInterface.cpp
|
||||
Query.cpp
|
||||
Result.cpp
|
||||
ResultProvider.cpp
|
||||
Source.cpp
|
||||
Track.cpp
|
||||
TrackData.cpp
|
||||
@@ -205,6 +207,7 @@ list(APPEND libSources
|
||||
PlaylistInterface.cpp
|
||||
UrlHandler.cpp
|
||||
|
||||
EchonestCatalogSynchronizer.cpp
|
||||
|
||||
accounts/AccountManager.cpp
|
||||
accounts/Account.cpp
|
||||
@@ -409,12 +412,13 @@ include_directories(
|
||||
|
||||
${QT_INCLUDE_DIR}
|
||||
${QJSON_INCLUDE_DIR}
|
||||
${ECHONEST_INCLUDE_DIR}
|
||||
${LUCENEPP_INCLUDE_DIRS}
|
||||
${LIBVLC_INCLUDE_DIR}
|
||||
${Boost_INCLUDE_DIR}
|
||||
|
||||
${LIBPORTFWD_INCLUDE_DIR}
|
||||
${QUAZIP_INCLUDE_DIRS}
|
||||
${QUAZIP_INCLUDE_DIR}
|
||||
${QTKEYCHAIN_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
@@ -497,7 +501,7 @@ set_target_properties(
|
||||
AUTOMOC TRUE
|
||||
VERSION ${TOMAHAWK_VERSION_SHORT}
|
||||
SOVERSION ${TOMAHAWK_VERSION_SHORT}
|
||||
OUTPUT_NAME ${TOMAHAWK_BASE_TARGET_NAME}
|
||||
OUTPUT_NAME ${TOMAHAWK_TARGET_NAME}
|
||||
)
|
||||
|
||||
|
||||
@@ -520,6 +524,7 @@ ENDIF( UNIX AND NOT APPLE )
|
||||
TARGET_LINK_LIBRARIES( ${TOMAHAWK_LIBRARY}
|
||||
LINK_PRIVATE
|
||||
${LIBVLC_LIBRARY}
|
||||
${LIBVLCCORE_LIBRARY}
|
||||
|
||||
# Thirdparty shipped with tomahawk
|
||||
${LIBPORTFWD_LIBRARIES}
|
||||
@@ -530,6 +535,7 @@ TARGET_LINK_LIBRARIES( ${TOMAHAWK_LIBRARY}
|
||||
# External deps
|
||||
${QJSON_LIBRARIES}
|
||||
${LUCENEPP_LIBRARIES}
|
||||
${ECHONEST_LIBRARIES}
|
||||
${QT_QTSQL_LIBRARY}
|
||||
${QT_QTUITOOLS_LIBRARY}
|
||||
${QT_QTGUI_LIBRARY}
|
||||
@@ -573,7 +579,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" )
|
||||
@@ -602,7 +608,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 )
|
||||
|
@@ -37,9 +37,6 @@
|
||||
#include "utils/ImageRegistry.h"
|
||||
#include "utils/Logger.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QFileInfo>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
|
||||
@@ -54,7 +51,7 @@ ContextMenu::ContextMenu( QWidget* parent )
|
||||
m_sigmap = new QSignalMapper( this );
|
||||
connect( m_sigmap, SIGNAL( mapped( int ) ), SLOT( onTriggered( int ) ) );
|
||||
|
||||
clear();
|
||||
m_supportedActions = ActionPlay | ActionQueue | ActionPlaylist | ActionCopyLink | ActionLove | ActionStopAfter | ActionPage | ActionEditMetadata | ActionSend;
|
||||
}
|
||||
|
||||
|
||||
@@ -72,7 +69,7 @@ ContextMenu::clear()
|
||||
m_albums.clear();
|
||||
m_artists.clear();
|
||||
|
||||
m_supportedActions = ActionPlay | ActionQueue | ActionPlaylist | ActionCopyLink | ActionLove | ActionStopAfter | ActionPage | ActionEditMetadata | ActionSend | ActionOpenFileManager;
|
||||
m_supportedActions = ActionPlay | ActionQueue | ActionPlaylist | ActionCopyLink | ActionLove | ActionStopAfter | ActionPage | ActionEditMetadata | ActionSend;
|
||||
}
|
||||
|
||||
|
||||
@@ -219,23 +216,10 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
addSeparator();
|
||||
|
||||
if ( m_supportedActions & ActionCopyLink && itemCount() == 1 )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( tr( "&Copy Track Link" ) ), ActionCopyLink );
|
||||
}
|
||||
|
||||
if ( m_supportedActions & ActionOpenFileManager &&
|
||||
queries.length() == 1 &&
|
||||
queries.first()->numResults() &&
|
||||
queries.first()->results().first()->isLocal() )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( ImageRegistry::instance()->icon( RESPATH "images/folder.svg" ),
|
||||
tr( "Open Folder in File Manager..." ) ), ActionOpenFileManager );
|
||||
}
|
||||
|
||||
if ( m_supportedActions & ActionEditMetadata && itemCount() == 1 )
|
||||
{
|
||||
m_sigmap->setMapping( addAction( tr( "Properties..." ) ), ActionEditMetadata );
|
||||
}
|
||||
|
||||
addSeparator();
|
||||
|
||||
@@ -255,8 +239,6 @@ ContextMenu::setQueries( const QList<Tomahawk::query_ptr>& queries )
|
||||
m_sigmap->setMapping( addAction( tr( "Mark as &Listened" ) ), ActionMarkListened );
|
||||
}
|
||||
|
||||
addSeparator();
|
||||
|
||||
if ( m_supportedActions & ActionDelete )
|
||||
m_sigmap->setMapping( addAction( queries.count() > 1 ? tr( "&Remove Items" ) : tr( "&Remove Item" ) ), ActionDelete );
|
||||
|
||||
@@ -412,15 +394,6 @@ ContextMenu::onTriggered( int action )
|
||||
}
|
||||
break;
|
||||
|
||||
case ActionOpenFileManager:
|
||||
{
|
||||
result_ptr result = m_queries.first()->results().first();
|
||||
QString path = QFileInfo( result->url() ).path();
|
||||
tLog() << Q_FUNC_INFO << "open directory" << path;
|
||||
QDesktopServices::openUrl( path );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
emit triggered( action );
|
||||
}
|
||||
|
@@ -37,22 +37,21 @@ Q_OBJECT
|
||||
public:
|
||||
enum MenuActions
|
||||
{
|
||||
ActionPlay = 1,
|
||||
ActionQueue = 2,
|
||||
ActionDelete = 4,
|
||||
ActionCopyLink = 8,
|
||||
ActionLove = 16,
|
||||
ActionStopAfter = 32,
|
||||
ActionPage = 64,
|
||||
ActionTrackPage = 128,
|
||||
ActionArtistPage = 256,
|
||||
ActionAlbumPage = 512,
|
||||
ActionEditMetadata = 1024,
|
||||
ActionPlaylist = 2048,
|
||||
ActionSend = 4096,
|
||||
ActionMarkListened = 8192,
|
||||
ActionDownload = 16384,
|
||||
ActionOpenFileManager = 32768
|
||||
ActionPlay = 1,
|
||||
ActionQueue = 2,
|
||||
ActionDelete = 4,
|
||||
ActionCopyLink = 8,
|
||||
ActionLove = 16,
|
||||
ActionStopAfter = 32,
|
||||
ActionPage = 64,
|
||||
ActionTrackPage = 128,
|
||||
ActionArtistPage = 256,
|
||||
ActionAlbumPage = 512,
|
||||
ActionEditMetadata = 1024,
|
||||
ActionPlaylist = 2048,
|
||||
ActionSend = 4096,
|
||||
ActionMarkListened = 8192,
|
||||
ActionDownload = 16384
|
||||
};
|
||||
|
||||
explicit ContextMenu( QWidget* parent = 0 );
|
||||
|
@@ -118,7 +118,7 @@ DownloadJob::localFile() const
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::localPath( const Tomahawk::album_ptr& album )
|
||||
DownloadJob::localPath() const
|
||||
{
|
||||
QDir dir = TomahawkSettings::instance()->downloadsPath();
|
||||
|
||||
@@ -127,7 +127,7 @@ DownloadJob::localPath( const Tomahawk::album_ptr& album )
|
||||
dir.mkpath( "." );
|
||||
}
|
||||
|
||||
QString path = QString( "%1/%2" ).arg( safeEncode( album->artist()->name(), true ) ).arg( safeEncode( album->name(), true ) );
|
||||
QString path = QString( "%1/%2" ).arg( safeEncode( m_track->artist(), true ) ).arg( safeEncode( m_track->album(), 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( m_track->albumPtr() );
|
||||
QString path = localPath();
|
||||
QString localFile = QString( path + "/" + filename );
|
||||
|
||||
if ( !m_tryResuming )
|
||||
@@ -206,17 +206,22 @@ DownloadJob::download()
|
||||
{
|
||||
if ( m_state == Running )
|
||||
return true;
|
||||
|
||||
setState( Running );
|
||||
|
||||
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}});
|
||||
}
|
||||
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( "getStreamUrlPromise", arguments );
|
||||
connect( job, SIGNAL( done(QVariantMap) ), SLOT( onUrlRetrieved(QVariantMap) ) );
|
||||
job->start();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -439,7 +444,7 @@ DownloadJob::checkForResumedFile()
|
||||
|
||||
|
||||
QString
|
||||
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots )
|
||||
DownloadJob::safeEncode( const QString& filename, bool removeTrailingDots ) const
|
||||
{
|
||||
//FIXME: make it a regexp
|
||||
QString res = QString( filename ).toLatin1().replace( "/", "_" ).replace( "\\", "_" )
|
||||
|
@@ -58,7 +58,7 @@ public:
|
||||
long receivedSize() const { return m_rcvdSize; }
|
||||
long fileSize() const { return m_fileSize; }
|
||||
|
||||
static QString localPath( const Tomahawk::album_ptr& album );
|
||||
QString localPath() const;
|
||||
QString localFile() const;
|
||||
DownloadFormat format() const;
|
||||
|
||||
@@ -90,7 +90,7 @@ private slots:
|
||||
|
||||
private:
|
||||
void storeState();
|
||||
static QString safeEncode( const QString& filename, bool removeTrailingDots = false );
|
||||
QString safeEncode( const QString& filename, bool removeTrailingDots = false ) const;
|
||||
bool checkForResumedFile();
|
||||
QUrl prepareFilename();
|
||||
|
||||
|
@@ -24,8 +24,6 @@
|
||||
#include "TomahawkSettings.h"
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "Result.h"
|
||||
#include "Query.h"
|
||||
|
||||
DownloadManager* DownloadManager::s_instance = 0;
|
||||
|
||||
@@ -87,36 +85,6 @@ 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 )
|
||||
{
|
||||
|
@@ -45,8 +45,6 @@ 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 );
|
||||
|
@@ -175,7 +175,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
// Check Scriptresolvers
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::UrlTypePlaylist ) )
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::Playlist ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -201,7 +201,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
// Check Scriptresolvers
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeTrack ) )
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::Track ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -218,7 +218,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
// Check Scriptresolvers
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeAlbum ) )
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::Album ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -235,7 +235,7 @@ DropJob::acceptsMimeData( const QMimeData* data, DropJob::DropTypes acceptedType
|
||||
// Check Scriptresolvers
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeArtist ) )
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::Artist ) )
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -263,14 +263,9 @@ bool
|
||||
DropJob::validateLocalFiles(const QString &paths, const QString &suffix)
|
||||
{
|
||||
QStringList filePaths = paths.split( QRegExp( "\\s+" ), QString::SkipEmptyParts );
|
||||
QStringList::iterator it = filePaths.begin();
|
||||
while ( it != filePaths.end() )
|
||||
{
|
||||
for ( QStringList::iterator it = filePaths.begin(); it != filePaths.end(); ++it )
|
||||
if ( !validateLocalFile( *it, suffix ) )
|
||||
it = filePaths.erase( it );
|
||||
else
|
||||
++it;
|
||||
}
|
||||
filePaths.erase( it );
|
||||
return !filePaths.isEmpty();
|
||||
}
|
||||
|
||||
@@ -311,7 +306,7 @@ DropJob::isDropType( DropJob::DropType desired, const QMimeData* data )
|
||||
// Check Scriptresolvers
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::UrlTypePlaylist ) )
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::Playlist ) )
|
||||
{
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Accepting current drop as a playlist" << resolver->name();
|
||||
return true;
|
||||
@@ -768,7 +763,7 @@ DropJob::handleTrackUrls( const QString& urls )
|
||||
{
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( track, ExternalResolver::UrlTypeAny ) )
|
||||
if ( resolver->canParseUrl( track, ExternalResolver::Any ) )
|
||||
{
|
||||
ScriptCommand_LookupUrl* cmd = new ScriptCommand_LookupUrl( resolver, track );
|
||||
connect( cmd, SIGNAL( information( QString, QSharedPointer<QObject> ) ), this, SLOT( informationForUrl( QString, QSharedPointer<QObject> ) ) );
|
||||
@@ -980,7 +975,7 @@ DropJob::removeRemoteSources()
|
||||
|
||||
foreach ( const Tomahawk::result_ptr& result, item->results() )
|
||||
{
|
||||
if ( !result->isLocal() )
|
||||
if ( !result->resolvedByCollection().isNull() && !result->resolvedByCollection()->isLocal() )
|
||||
{
|
||||
list.append( item );
|
||||
break;
|
||||
|
@@ -1,14 +1,14 @@
|
||||
/* === 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>
|
||||
* Copyright 2011, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright 2013, Uwe L. Korn <uwelk@xhochy.com>
|
||||
* Copyright 2013, Teo Mrnjavac <teo@kde.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>
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation, either version 2 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 @@
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include "GlobalActionManager.h"
|
||||
|
||||
#include "accounts/AccountManager.h"
|
||||
@@ -46,6 +47,12 @@
|
||||
#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>
|
||||
|
||||
@@ -160,7 +167,7 @@ GlobalActionManager::openUrl( const QString& url )
|
||||
QList< QPointer< ExternalResolver > > possibleResolvers;
|
||||
foreach ( QPointer<ExternalResolver> resolver, Pipeline::instance()->scriptResolvers() )
|
||||
{
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::UrlTypeAny ) )
|
||||
if ( resolver->canParseUrl( url, ExternalResolver::Any ) )
|
||||
{
|
||||
canParse = true;
|
||||
possibleResolvers << resolver;
|
||||
@@ -906,144 +913,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,21 +1,21 @@
|
||||
/* === 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/>.
|
||||
*/
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GLOBALACTIONMANAGER_H
|
||||
#define GLOBALACTIONMANAGER_H
|
||||
|
@@ -36,7 +36,7 @@
|
||||
#define MAX_CONCURRENT_QUERIES 16
|
||||
#define CLEANUP_TIMEOUT 5 * 60 * 1000
|
||||
#define MINSCORE 0.5
|
||||
#define DEFAULT_RESOLVER_TIMEOUT 5000 // 5 seconds
|
||||
#define DEFAULT_RESOLVER_TIMEOUT 5000 //5 seconds
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -149,15 +149,6 @@ Pipeline::removeResolver( Resolver* r )
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::Resolver* >
|
||||
Pipeline::resolvers() const
|
||||
{
|
||||
Q_D( const Pipeline );
|
||||
|
||||
return d->resolvers;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipeline::addResolver( Resolver* r )
|
||||
{
|
||||
@@ -332,13 +323,6 @@ Pipeline::resolve( QID qid, bool prioritized, bool temporaryQuery )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipeline::reportError( QID qid, Tomahawk::Resolver* r )
|
||||
{
|
||||
reportResults( qid, r, QList< result_ptr>() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Pipeline::reportResults( QID qid, Tomahawk::Resolver* r, const QList< result_ptr >& results )
|
||||
{
|
||||
@@ -349,7 +333,7 @@ Pipeline::reportResults( QID qid, Tomahawk::Resolver* r, const QList< result_ptr
|
||||
{
|
||||
if ( !results.isEmpty() )
|
||||
{
|
||||
Resolver* resolvedBy = results[0]->resolvedBy();
|
||||
ResultProvider* resolvedBy = results[0]->resolvedBy();
|
||||
if ( resolvedBy )
|
||||
{
|
||||
tDebug() << "Result arrived too late for:" << qid << "by" << resolvedBy->name();
|
||||
@@ -542,12 +526,12 @@ Pipeline::shuntNext()
|
||||
q->setCurrentResolver( 0 );
|
||||
}
|
||||
|
||||
// Zero-patient, a stub so that query is not resolved until we go through
|
||||
// all resolvers
|
||||
// As query considered as 'finished trying to resolve' when there are no
|
||||
// more qid entries in qidsState we'll put one as sort of 'keep this until
|
||||
// we kick off all our resolvers' entry
|
||||
// once we kick off all resolvers we'll remove this entry
|
||||
//Zero-patient, a stub so that query is not resolved until we go through
|
||||
//all resolvers
|
||||
//As query considered as 'finished trying to resolve' when there are no
|
||||
//more qid entries in qidsState we'll put one as sort of 'keep this until
|
||||
//we kick off all our resolvers' entry
|
||||
//once we kick off all resolvers we'll remove this entry
|
||||
incQIDState( q, nullptr );
|
||||
checkQIDState( q );
|
||||
}
|
||||
@@ -595,8 +579,8 @@ Pipeline::shunt( const query_ptr& q )
|
||||
// we get here if we disable a resolver while a query is resolving
|
||||
// OR we are just out of resolvers while query is still resolving
|
||||
|
||||
// since we seem to at least tried to kick off all of the resolvers,
|
||||
// remove the '.keep' entry
|
||||
//since we seem to at least tried to kick off all of the resolvers,
|
||||
//remove the '.keep' entry
|
||||
decQIDState( q, nullptr );
|
||||
return;
|
||||
}
|
||||
@@ -636,7 +620,7 @@ Pipeline::checkQIDState( const Tomahawk::query_ptr& query )
|
||||
Q_D( Pipeline );
|
||||
QMutexLocker lock( &d->mut );
|
||||
|
||||
tDebug() << Q_FUNC_INFO << query->id() << d->qidsState.count( query->id() );
|
||||
tDebug() << Q_FUNC_INFO << " " << query->id() << " " << d->qidsState.count( query->id() );
|
||||
|
||||
if ( d->qidsState.contains( query->id() ) )
|
||||
{
|
||||
@@ -673,7 +657,7 @@ Pipeline::decQIDState( const Tomahawk::query_ptr& query, Tomahawk::Resolver* r )
|
||||
{
|
||||
{
|
||||
QMutexLocker lock( &d->mut );
|
||||
d->qidsState.remove( query->id(), r ); // Removes all matching pairs
|
||||
d->qidsState.remove( query->id(), r );//Removes all matching pairs
|
||||
}
|
||||
|
||||
checkQIDState( query );
|
||||
|
@@ -54,7 +54,6 @@ public:
|
||||
unsigned int pendingQueryCount() const;
|
||||
unsigned int activeQueryCount() const;
|
||||
|
||||
void reportError( QID qid, Tomahawk::Resolver* r );
|
||||
void reportResults( QID qid, Tomahawk::Resolver* r, const QList< result_ptr >& results );
|
||||
void reportAlbums( QID qid, const QList< album_ptr >& albums );
|
||||
void reportArtists( QID qid, const QList< artist_ptr >& artists );
|
||||
@@ -66,7 +65,6 @@ public:
|
||||
QList< QPointer< ExternalResolver > > scriptResolvers() const;
|
||||
Tomahawk::ExternalResolver* resolverForPath( const QString& scriptPath );
|
||||
|
||||
QList< Resolver* > resolvers() const;
|
||||
void addResolver( Resolver* r );
|
||||
void removeResolver( Resolver* r );
|
||||
|
||||
|
@@ -33,7 +33,6 @@
|
||||
|
||||
#include <QtAlgorithms>
|
||||
#include <QDebug>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -48,7 +47,6 @@ Query::get( const QString& artist, const QString& track, const QString& album, c
|
||||
autoResolve = false;
|
||||
|
||||
query_ptr q = query_ptr( new Query( Track::get( artist, track, album ), qid, autoResolve ), &QObject::deleteLater );
|
||||
q->moveToThread( QCoreApplication::instance()->thread() );
|
||||
q->setWeakRef( q.toWeakRef() );
|
||||
|
||||
if ( autoResolve )
|
||||
@@ -194,7 +192,7 @@ Query::addResults( const QList< Tomahawk::result_ptr >& newresults )
|
||||
}*/
|
||||
|
||||
d->results << newresults;
|
||||
sortResults();
|
||||
qStableSort( d->results.begin(), d->results.end(), std::bind( &Query::resultSorter, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
|
||||
// hook up signals, and check solved status
|
||||
foreach( const result_ptr& rp, newresults )
|
||||
@@ -258,7 +256,7 @@ Query::onResultStatusChanged()
|
||||
Q_D( Query );
|
||||
QMutexLocker lock( &d->mutex );
|
||||
if ( !d->results.isEmpty() )
|
||||
sortResults();
|
||||
qStableSort( d->results.begin(), d->results.end(), std::bind( &Query::resultSorter, this, std::placeholders::_1, std::placeholders::_2 ) );
|
||||
}
|
||||
|
||||
checkResults();
|
||||
@@ -273,11 +271,6 @@ 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 );
|
||||
@@ -401,35 +394,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->isLocal() )
|
||||
if ( right->resolvedByCollection() && right->resolvedByCollection()->isLocal() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( left->isPreview() != right->isPreview() )
|
||||
if ( !right->isPreview() )
|
||||
{
|
||||
return !left->isPreview();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( left->resolvedBy() != nullptr && right->resolvedBy() != nullptr )
|
||||
{
|
||||
return left->resolvedBy()->weight() > right->resolvedBy()->weight();
|
||||
}
|
||||
|
||||
return left->id() > right->id();
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( left->isPreview() != right->isPreview() )
|
||||
@@ -441,30 +420,6 @@ 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 )
|
||||
{
|
||||
@@ -660,10 +615,6 @@ 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();
|
||||
@@ -685,13 +636,6 @@ 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(filterOutChars);
|
||||
qTrackname.remove(filterOutChars);
|
||||
qAlbumname.remove(filterOutChars);
|
||||
|
||||
// normal edit distance
|
||||
const int artdist = TomahawkUtils::levenshtein( qArtistname, rArtistname );
|
||||
const int trkdist = TomahawkUtils::levenshtein( qTrackname, rTrackname );
|
||||
@@ -722,16 +666,12 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
const int mlatr = qMax( artistTrackname.length(), rArtistTrackname.length() );
|
||||
const float dcatr = (float)( mlatr - atrdist ) / mlatr;
|
||||
|
||||
float resultScore = qMax( dctrk, qMax( dcatr, qMax( dcart, dcalb ) ) );
|
||||
d->howSimilarCache[r->id()] = resultScore;
|
||||
return resultScore;
|
||||
return qMax( dctrk, qMax( dcatr, qMax( dcart, dcalb ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
// weighted, so album match is worth less than track title
|
||||
float resultScore = ( dcart * 4 + dcalb + dctrk * 5 ) / 10;
|
||||
d->howSimilarCache[r->id()] = resultScore;
|
||||
return resultScore;
|
||||
return ( dcart * 4 + dcalb + dctrk * 5 ) / 10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -782,11 +722,3 @@ 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 ) );
|
||||
}
|
||||
|
@@ -112,8 +112,6 @@ 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>& );
|
||||
@@ -160,7 +158,6 @@ private:
|
||||
void setCurrentResolver( Tomahawk::Resolver* resolver );
|
||||
void clearResults();
|
||||
void checkResults();
|
||||
void sortResults();
|
||||
};
|
||||
|
||||
} //ns
|
||||
|
@@ -4,7 +4,6 @@
|
||||
#include "Query.h"
|
||||
|
||||
#include <QMutex>
|
||||
#include <map>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@@ -40,7 +39,6 @@ private:
|
||||
QList< Tomahawk::artist_ptr > artists;
|
||||
QList< Tomahawk::album_ptr > albums;
|
||||
QList< Tomahawk::result_ptr > results;
|
||||
Tomahawk::result_ptr preferredResult;
|
||||
|
||||
float score;
|
||||
bool solved;
|
||||
@@ -60,8 +58,6 @@ private:
|
||||
|
||||
mutable QMutex mutex;
|
||||
QWeakPointer< Tomahawk::Query > ownRef;
|
||||
|
||||
std::map<QString, float> howSimilarCache;
|
||||
};
|
||||
|
||||
} // Tomahawk
|
||||
|
@@ -35,8 +35,6 @@
|
||||
#include "Track.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
static QHash< QString, result_wptr > s_results;
|
||||
@@ -71,7 +69,6 @@ Result::get( const QString& url, const track_ptr& track )
|
||||
}
|
||||
|
||||
result_ptr r = result_ptr( new Result( url, track ), &Result::deleteLater );
|
||||
r->moveToThread( QCoreApplication::instance()->thread() );
|
||||
r->setWeakRef( r.toWeakRef() );
|
||||
s_results.insert( url, r );
|
||||
|
||||
@@ -135,19 +132,11 @@ Result::deleteLater()
|
||||
void
|
||||
Result::onResolverRemoved( Tomahawk::Resolver* resolver )
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
if ( m_resolver.data() == resolver )
|
||||
{
|
||||
m_resolver = 0;
|
||||
m_mutex.unlock();
|
||||
|
||||
emit statusChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -161,8 +150,6 @@ Result::resolvedByCollection() const
|
||||
QString
|
||||
Result::url() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_url;
|
||||
}
|
||||
|
||||
@@ -170,8 +157,6 @@ Result::url() const
|
||||
bool
|
||||
Result::checked() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_checked;
|
||||
}
|
||||
|
||||
@@ -179,8 +164,6 @@ Result::checked() const
|
||||
bool
|
||||
Result::isPreview() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_isPreview;
|
||||
}
|
||||
|
||||
@@ -188,8 +171,6 @@ Result::isPreview() const
|
||||
QString
|
||||
Result::mimetype() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_mimetype;
|
||||
}
|
||||
|
||||
@@ -197,8 +178,6 @@ Result::mimetype() const
|
||||
RID
|
||||
Result::id() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
if ( m_rid.isEmpty() )
|
||||
m_rid = uuid();
|
||||
|
||||
@@ -215,8 +194,6 @@ Result::isOnline() const
|
||||
}
|
||||
else
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return !m_resolver.isNull();
|
||||
}
|
||||
}
|
||||
@@ -234,36 +211,27 @@ Result::playable() const
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Result::isLocal() const
|
||||
{
|
||||
return resolvedByCollection().isNull() ? false : resolvedByCollection()->isLocal();
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
Result::toVariant() const
|
||||
{
|
||||
track_ptr t = track();
|
||||
|
||||
QVariantMap m;
|
||||
m.insert( "artist", t->artist() );
|
||||
m.insert( "album", t->album() );
|
||||
m.insert( "track", t->track() );
|
||||
m.insert( "artist", m_track->artist() );
|
||||
m.insert( "album", m_track->album() );
|
||||
m.insert( "track", m_track->track() );
|
||||
m.insert( "source", friendlySource() );
|
||||
m.insert( "mimetype", mimetype() );
|
||||
m.insert( "size", size() );
|
||||
m.insert( "bitrate", bitrate() );
|
||||
m.insert( "duration", t->duration() );
|
||||
m.insert( "duration", m_track->duration() );
|
||||
// m.insert( "score", score() );
|
||||
m.insert( "sid", id() );
|
||||
m.insert( "discnumber", t->discnumber() );
|
||||
m.insert( "albumpos", t->albumpos() );
|
||||
m.insert( "discnumber", m_track->discnumber() );
|
||||
m.insert( "albumpos", m_track->albumpos() );
|
||||
m.insert( "preview", isPreview() );
|
||||
m.insert( "purchaseUrl", purchaseUrl() );
|
||||
|
||||
if ( !t->composer().isEmpty() )
|
||||
m.insert( "composer", t->composer() );
|
||||
if ( !m_track->composer().isEmpty() )
|
||||
m.insert( "composer", m_track->composer() );
|
||||
|
||||
return m;
|
||||
}
|
||||
@@ -272,25 +240,20 @@ Result::toVariant() const
|
||||
QString
|
||||
Result::toString() const
|
||||
{
|
||||
m_mutex.lock();
|
||||
track_ptr track = m_track;
|
||||
QString url = m_url;
|
||||
m_mutex.unlock();
|
||||
|
||||
if ( track )
|
||||
if ( m_track )
|
||||
{
|
||||
return QString( "Result(%1) %2 - %3%4 (%5)" )
|
||||
.arg( id() )
|
||||
.arg( track->artist() )
|
||||
.arg( track->track() )
|
||||
.arg( track->album().isEmpty() ? QString() : QString( " on %1" ).arg( track->album() ) )
|
||||
.arg( url );
|
||||
.arg( m_track->artist() )
|
||||
.arg( m_track->track() )
|
||||
.arg( m_track->album().isEmpty() ? QString() : QString( " on %1" ).arg( m_track->album() ) )
|
||||
.arg( m_url );
|
||||
}
|
||||
else
|
||||
{
|
||||
return QString( "Result(%1) (%2)" )
|
||||
.arg( id() )
|
||||
.arg( url );
|
||||
.arg( m_url );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,8 +261,6 @@ Result::toString() const
|
||||
Tomahawk::query_ptr
|
||||
Result::toQuery()
|
||||
{
|
||||
QMutexLocker l( &m_mutex );
|
||||
|
||||
if ( m_query.isNull() )
|
||||
{
|
||||
query_ptr query = Tomahawk::Query::get( m_track );
|
||||
@@ -309,15 +270,12 @@ Result::toQuery()
|
||||
m_query = query->weakRef();
|
||||
|
||||
QList<Tomahawk::result_ptr> rl;
|
||||
rl << m_ownRef.toStrongRef();
|
||||
m_mutex.unlock();
|
||||
rl << weakRef().toStrongRef();
|
||||
query->addResults( rl );
|
||||
m_mutex.lock();
|
||||
query->setResolveFinished( true );
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
return m_query.toStrongRef();
|
||||
}
|
||||
|
||||
@@ -337,10 +295,9 @@ Result::onOffline()
|
||||
|
||||
|
||||
void
|
||||
Result::setResolvedByCollection( const Tomahawk::collection_ptr& collection, bool emitOnlineEvents )
|
||||
Result::setResolvedByCollection( const Tomahawk::collection_ptr& collection , bool emitOnlineEvents )
|
||||
{
|
||||
m_collection = collection;
|
||||
|
||||
if ( emitOnlineEvents )
|
||||
{
|
||||
Q_ASSERT( !collection.isNull() );
|
||||
@@ -354,8 +311,6 @@ Result::setResolvedByCollection( const Tomahawk::collection_ptr& collection, boo
|
||||
void
|
||||
Result::setFriendlySource( const QString& s )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_friendlySource = s;
|
||||
}
|
||||
|
||||
@@ -363,8 +318,6 @@ Result::setFriendlySource( const QString& s )
|
||||
void
|
||||
Result::setPreview( bool isPreview )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_isPreview = isPreview;
|
||||
}
|
||||
|
||||
@@ -372,8 +325,6 @@ Result::setPreview( bool isPreview )
|
||||
void
|
||||
Result::setPurchaseUrl( const QString& u )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_purchaseUrl = u;
|
||||
}
|
||||
|
||||
@@ -381,8 +332,6 @@ Result::setPurchaseUrl( const QString& u )
|
||||
void
|
||||
Result::setLinkUrl( const QString& u )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_linkUrl = u;
|
||||
}
|
||||
|
||||
@@ -390,8 +339,6 @@ Result::setLinkUrl( const QString& u )
|
||||
void
|
||||
Result::setChecked( bool checked )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_checked = checked;
|
||||
}
|
||||
|
||||
@@ -399,8 +346,6 @@ Result::setChecked( bool checked )
|
||||
void
|
||||
Result::setMimetype( const QString& mimetype )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_mimetype = mimetype;
|
||||
}
|
||||
|
||||
@@ -408,8 +353,6 @@ Result::setMimetype( const QString& mimetype )
|
||||
void
|
||||
Result::setBitrate( unsigned int bitrate )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_bitrate = bitrate;
|
||||
}
|
||||
|
||||
@@ -417,8 +360,6 @@ Result::setBitrate( unsigned int bitrate )
|
||||
void
|
||||
Result::setSize( unsigned int size )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_size = size;
|
||||
}
|
||||
|
||||
@@ -426,8 +367,6 @@ Result::setSize( unsigned int size )
|
||||
void
|
||||
Result::setModificationTime( unsigned int modtime )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_modtime = modtime;
|
||||
}
|
||||
|
||||
@@ -435,8 +374,6 @@ Result::setModificationTime( unsigned int modtime )
|
||||
void
|
||||
Result::setTrack( const track_ptr& track )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_track = track;
|
||||
}
|
||||
|
||||
@@ -444,8 +381,6 @@ Result::setTrack( const track_ptr& track )
|
||||
unsigned int
|
||||
Result::fileId() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_fileId;
|
||||
}
|
||||
|
||||
@@ -455,8 +390,6 @@ Result::friendlySource() const
|
||||
{
|
||||
if ( resolvedByCollection().isNull() )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_friendlySource;
|
||||
}
|
||||
else
|
||||
@@ -467,8 +400,6 @@ Result::friendlySource() const
|
||||
QString
|
||||
Result::purchaseUrl() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_purchaseUrl;
|
||||
}
|
||||
|
||||
@@ -476,8 +407,6 @@ Result::purchaseUrl() const
|
||||
QString
|
||||
Result::linkUrl() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_linkUrl;
|
||||
}
|
||||
|
||||
@@ -487,8 +416,6 @@ Result::sourceIcon( TomahawkUtils::ImageMode style, const QSize& desiredSize ) c
|
||||
{
|
||||
if ( resolvedByCollection().isNull() )
|
||||
{
|
||||
//QMutexLocker lock( &m_mutex );
|
||||
|
||||
const ExternalResolver* resolver = qobject_cast< ExternalResolver* >( m_resolver.data() );
|
||||
if ( !resolver )
|
||||
{
|
||||
@@ -539,8 +466,6 @@ Result::sourceIcon( TomahawkUtils::ImageMode style, const QSize& desiredSize ) c
|
||||
unsigned int
|
||||
Result::bitrate() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_bitrate;
|
||||
}
|
||||
|
||||
@@ -548,8 +473,6 @@ Result::bitrate() const
|
||||
unsigned int
|
||||
Result::size() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_size;
|
||||
}
|
||||
|
||||
@@ -557,8 +480,6 @@ Result::size() const
|
||||
unsigned int
|
||||
Result::modificationTime() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_modtime;
|
||||
}
|
||||
|
||||
@@ -566,17 +487,13 @@ Result::modificationTime() const
|
||||
void
|
||||
Result::setFileId( unsigned int id )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_fileId = id;
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::Resolver*
|
||||
Tomahawk::ResultProvider*
|
||||
Result::resolvedBy() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
if ( !m_collection.isNull() )
|
||||
return m_collection.data();
|
||||
|
||||
@@ -587,16 +504,12 @@ Result::resolvedBy() const
|
||||
void
|
||||
Result::setResolvedByResolver( Tomahawk::Resolver* resolver )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_resolver = QPointer< Tomahawk::Resolver >( resolver );
|
||||
}
|
||||
|
||||
|
||||
QPointer< Resolver > Result::resolvedByResolver() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_resolver;
|
||||
}
|
||||
|
||||
@@ -612,29 +525,16 @@ Result::doneEditing()
|
||||
track_ptr
|
||||
Result::track() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_track;
|
||||
}
|
||||
|
||||
|
||||
QList< DownloadFormat >
|
||||
Result::downloadFormats() const
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_formats;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Result::setDownloadFormats( const QList<DownloadFormat>& formats )
|
||||
{
|
||||
if ( formats.isEmpty() )
|
||||
return;
|
||||
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_formats.clear();
|
||||
foreach ( const DownloadFormat& format, formats )
|
||||
{
|
||||
@@ -662,7 +562,7 @@ Result::setDownloadFormats( const QList<DownloadFormat>& formats )
|
||||
void
|
||||
Result::onSettingsChanged()
|
||||
{
|
||||
if ( TomahawkSettings::instance()->downloadsPreferredFormat().toLower() != downloadFormats().first().extension.toLower() )
|
||||
if ( TomahawkSettings::instance()->downloadsPreferredFormat().toLower() != m_formats.first().extension.toLower() )
|
||||
{
|
||||
setDownloadFormats( downloadFormats() );
|
||||
emit updated();
|
||||
@@ -699,8 +599,6 @@ Result::onDownloadJobStateChanged( DownloadJob::TrackState newState, DownloadJob
|
||||
QWeakPointer<Result>
|
||||
Result::weakRef()
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
return m_ownRef;
|
||||
}
|
||||
|
||||
@@ -708,7 +606,5 @@ Result::weakRef()
|
||||
void
|
||||
Result::setWeakRef( QWeakPointer<Result> weakRef )
|
||||
{
|
||||
QMutexLocker lock( &m_mutex );
|
||||
|
||||
m_ownRef = weakRef;
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#ifndef RESULT_H
|
||||
#define RESULT_H
|
||||
|
||||
#include "ResultProvider.h"
|
||||
#include "DownloadJob.h"
|
||||
#include "utils/TomahawkUtils.h"
|
||||
#include "Typedefs.h"
|
||||
@@ -31,7 +32,6 @@
|
||||
#include <QPixmap>
|
||||
#include <QPointer>
|
||||
#include <QVariant>
|
||||
#include <QMutex>
|
||||
|
||||
class MetadataEditor;
|
||||
|
||||
@@ -86,20 +86,14 @@ public:
|
||||
void setResolvedByResolver( Tomahawk::Resolver* resolver );
|
||||
|
||||
/**
|
||||
* TODO: Make this a smart pointer
|
||||
* This is very bad. ResultProvider is not a QObject and thus can not be tracked by a qt smart pointer ... :-(
|
||||
*/
|
||||
Resolver* resolvedBy() const;
|
||||
ResultProvider* resolvedBy() const;
|
||||
|
||||
RID id() const;
|
||||
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.
|
||||
@@ -138,7 +132,7 @@ public:
|
||||
|
||||
track_ptr track() const;
|
||||
|
||||
QList< DownloadFormat > downloadFormats() const;
|
||||
QList<DownloadFormat> downloadFormats() const { return m_formats; }
|
||||
void setDownloadFormats( const QList<DownloadFormat>& formats );
|
||||
|
||||
downloadjob_ptr downloadJob() const { return m_downloadJob; }
|
||||
@@ -168,8 +162,6 @@ private:
|
||||
explicit Result( const QString& url, const Tomahawk::track_ptr& track );
|
||||
explicit Result();
|
||||
|
||||
mutable QMutex m_mutex;
|
||||
|
||||
mutable RID m_rid;
|
||||
collection_wptr m_collection;
|
||||
QPointer< Tomahawk::Resolver > m_resolver;
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright (C) 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 3 of the License, or
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
@@ -15,23 +15,10 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "ResultProvider.h"
|
||||
|
||||
#include "ScriptErrorStatusMessage.h"
|
||||
#include "../utils/Logger.h"
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptErrorStatusMessage::ScriptErrorStatusMessage( const QString& message, Tomahawk::ScriptAccount* account )
|
||||
: ErrorStatusMessage( tr( "Script Error: %1" ).arg( message ) )
|
||||
, m_account( account )
|
||||
ResultProvider::~ResultProvider()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ScriptErrorStatusMessage::activated()
|
||||
{
|
||||
if ( m_account.isNull() )
|
||||
return;
|
||||
|
||||
tDebug() << "ScriptErrorStatusMessage clicked: " << mainText() << m_account->name();
|
||||
m_account->showDebugger();
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright (C) 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 3 of the License, or
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
@@ -15,25 +15,28 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTERRORSTATUSMESSAGE_H
|
||||
#define SCRIPTERRORSTATUSMESSAGE_H
|
||||
|
||||
#include "ErrorStatusMessage.h"
|
||||
#include "../resolvers/ScriptAccount.h"
|
||||
#pragma once
|
||||
#ifndef TOMAHAWK_RESULTPROVIDER_H
|
||||
#define TOMAHAWK_RESULTPROVIDER_H
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class DLLEXPORT ScriptErrorStatusMessage : public ErrorStatusMessage
|
||||
class QPixmap;
|
||||
class QString;
|
||||
class QSize;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT ResultProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScriptErrorStatusMessage( const QString& scriptErrorMessage, Tomahawk::ScriptAccount* );
|
||||
virtual ~ResultProvider();
|
||||
|
||||
void activated() override;
|
||||
|
||||
private:
|
||||
QPointer< Tomahawk::ScriptAccount > m_account;
|
||||
virtual QString name() const = 0;
|
||||
virtual QPixmap icon( const QSize& size ) const = 0;
|
||||
};
|
||||
|
||||
#endif // SCRIPTERRORSTATUSMESSAGE_H
|
||||
}
|
||||
|
||||
#endif // TOMAHAWK_RESULTPROVIDER_H
|
@@ -929,20 +929,6 @@ TomahawkSettings::setVolume( unsigned int volume )
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
TomahawkSettings::muted() const
|
||||
{
|
||||
return value( "audio/muted" ).toBool();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkSettings::setMuted( bool muted )
|
||||
{
|
||||
setValue( "audio/muted", muted );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
TomahawkSettings::proxyHost() const
|
||||
{
|
||||
@@ -1764,15 +1750,3 @@ 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);
|
||||
}
|
||||
|
||||
|
@@ -107,9 +107,6 @@ public:
|
||||
unsigned int volume() const;
|
||||
void setVolume( unsigned int volume );
|
||||
|
||||
bool muted() const;
|
||||
void setMuted( bool muted );
|
||||
|
||||
/// Playlist stuff
|
||||
QByteArray playlistColumnSizes( const QString& playlistid ) const;
|
||||
void setPlaylistColumnSizes( const QString& playlistid, const QByteArray& state );
|
||||
@@ -253,10 +250,6 @@ 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 );
|
||||
|
@@ -37,7 +37,6 @@
|
||||
#include <QtAlgorithms>
|
||||
#include <QDateTime>
|
||||
#include <QReadWriteLock>
|
||||
#include <QCoreApplication>
|
||||
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -93,7 +92,6 @@ Track::get( const QString& artist, const QString& track, const QString& album, c
|
||||
}
|
||||
|
||||
track_ptr t = track_ptr( new Track( artist, track, album, albumArtist, duration, composer, albumpos, discnumber ), &Track::deleteLater );
|
||||
t->moveToThread( QCoreApplication::instance()->thread() );
|
||||
t->setWeakRef( t.toWeakRef() );
|
||||
s_tracksByName.insert( key, t );
|
||||
|
||||
|
@@ -19,7 +19,8 @@
|
||||
|
||||
#include "TrackData.h"
|
||||
|
||||
|
||||
#include <QtAlgorithms>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include "audio/AudioEngine.h"
|
||||
#include "collection/Collection.h"
|
||||
@@ -40,10 +41,6 @@
|
||||
#include "PlaylistEntry.h"
|
||||
#include "SourceList.h"
|
||||
|
||||
#include <QtAlgorithms>
|
||||
#include <QReadWriteLock>
|
||||
#include <QCoreApplication>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
QHash< QString, trackdata_wptr > TrackData::s_trackDatasByName = QHash< QString, trackdata_wptr >();
|
||||
@@ -87,7 +84,6 @@ TrackData::get( unsigned int id, const QString& artist, const QString& track )
|
||||
}
|
||||
|
||||
trackdata_ptr t = trackdata_ptr( new TrackData( id, artist, track ), &TrackData::deleteLater );
|
||||
t->moveToThread( QCoreApplication::instance()->thread() );
|
||||
t->setWeakRef( t.toWeakRef() );
|
||||
s_trackDatasByName.insert( key, t );
|
||||
|
||||
|
@@ -253,7 +253,7 @@ namespace Tomahawk
|
||||
typedef QHash< QString, QString > InfoStringHash;
|
||||
typedef QPair< QVariantMap, QVariant > PushInfoPair;
|
||||
|
||||
typedef QSharedPointer< InfoPlugin > InfoPluginPtr;
|
||||
typedef QPointer< InfoPlugin > InfoPluginPtr;
|
||||
}
|
||||
|
||||
namespace Network
|
||||
|
@@ -76,8 +76,6 @@ public:
|
||||
*/
|
||||
virtual bool addPageItem() const;
|
||||
|
||||
virtual bool isRemovable() const { return false; }
|
||||
|
||||
/**
|
||||
* This page is actually a constant page that will be shown on every
|
||||
* restart of Tomahawk until the user selects it to be removed.
|
||||
|
@@ -167,7 +167,7 @@ signals:
|
||||
void connectionStateChanged( Tomahawk::Accounts::Account::ConnectionState state );
|
||||
|
||||
void configurationChanged();
|
||||
void configTestResult( int, const QString& = QString() );
|
||||
void configTestResult( Tomahawk::Accounts::ConfigTestResultType );
|
||||
|
||||
protected:
|
||||
virtual void loadFromConfig( const QString &accountId );
|
||||
|
@@ -68,7 +68,6 @@ DelegateConfigWrapper::DelegateConfigWrapper( Tomahawk::Accounts::Account* accou
|
||||
h->setContentsMargins( m_widget->contentsMargins() );
|
||||
|
||||
m_errorLabel->setAlignment( Qt::AlignCenter );
|
||||
m_errorLabel->setWordWrap( true );
|
||||
v->addWidget( m_errorLabel );
|
||||
|
||||
v->addLayout( h );
|
||||
@@ -82,7 +81,7 @@ DelegateConfigWrapper::DelegateConfigWrapper( Tomahawk::Accounts::Account* accou
|
||||
if ( m_widget->metaObject()->indexOfSignal( "sizeHintChanged()" ) > -1 )
|
||||
connect( m_widget, SIGNAL( sizeHintChanged() ), this, SLOT( updateSizeHint() ) );
|
||||
|
||||
connect( m_account, SIGNAL( configTestResult( int, const QString& ) ), SLOT( onConfigTestResult( int, const QString& ) ) );
|
||||
connect( m_account, SIGNAL( configTestResult( Tomahawk::Accounts::ConfigTestResultType ) ), SLOT( onConfigTestResult( Tomahawk::Accounts::ConfigTestResultType ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -193,11 +192,11 @@ DelegateConfigWrapper::aboutClicked( bool )
|
||||
|
||||
|
||||
void
|
||||
DelegateConfigWrapper::onConfigTestResult( int code, const QString& message )
|
||||
DelegateConfigWrapper::onConfigTestResult( Tomahawk::Accounts::ConfigTestResultType result )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << code << ": " << message;
|
||||
tLog() << Q_FUNC_INFO << result;
|
||||
|
||||
if( code == Tomahawk::Accounts::ConfigTestResultSuccess )
|
||||
if( result == Tomahawk::Accounts::ConfigTestResultSuccess )
|
||||
{
|
||||
m_invalidData = QVariantMap();
|
||||
closeDialog( QDialog::Accepted );
|
||||
@@ -227,25 +226,8 @@ DelegateConfigWrapper::onConfigTestResult( int code, const QString& message )
|
||||
|
||||
m_invalidData = m_widget->readData();
|
||||
|
||||
QString msg = !message.isEmpty() ? message : getTestConfigMessage( code );
|
||||
m_errorLabel->setText( QString( "<font color='red'>%1</font>" ).arg( msg ) );
|
||||
}
|
||||
}
|
||||
|
||||
QString
|
||||
DelegateConfigWrapper::getTestConfigMessage( int code )
|
||||
{
|
||||
switch(code) {
|
||||
case Tomahawk::Accounts::ConfigTestResultCommunicationError:
|
||||
return tr( "Unable to authenticate. Please check your connection." );
|
||||
case Tomahawk::Accounts::ConfigTestResultInvalidCredentials:
|
||||
return tr( "Username or password incorrect." );
|
||||
case Tomahawk::Accounts::ConfigTestResultInvalidAccount:
|
||||
return tr( "Account rejected by server." );
|
||||
case Tomahawk::Accounts::ConfigTestResultPlayingElsewhere:
|
||||
return tr( "Action not allowed, account is in use elsewhere." );
|
||||
case Tomahawk::Accounts::ConfigTestResultAccountExpired:
|
||||
return tr( "Your account has expired." );
|
||||
// TODO: generate message based on status code
|
||||
m_errorLabel->setText( QString( "<font color='red'>%1</font>" ).arg( tr( "Your config is invalid." ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -60,11 +60,10 @@ protected:
|
||||
|
||||
private slots:
|
||||
void aboutClicked( bool );
|
||||
void onConfigTestResult( int, const QString& );
|
||||
void onConfigTestResult( Tomahawk::Accounts::ConfigTestResultType );
|
||||
|
||||
private:
|
||||
void closeDialog( QDialog::DialogCode code );
|
||||
QString getTestConfigMessage( int code );
|
||||
|
||||
Tomahawk::Accounts::Account* m_account;
|
||||
AccountConfigWidget* m_widget;
|
||||
|
@@ -79,7 +79,7 @@ ResolverAccountFactory::createFromPath( const QString& path )
|
||||
}
|
||||
|
||||
|
||||
ResolverAccount*
|
||||
Account*
|
||||
ResolverAccountFactory::createFromPath( const QString& path, const QString& factory, bool isAttica )
|
||||
{
|
||||
qDebug() << "Creating ResolverAccount from path:" << path << "is attica" << isAttica;
|
||||
@@ -110,8 +110,57 @@ ResolverAccountFactory::createFromPath( const QString& path, const QString& fact
|
||||
|
||||
if ( pathInfo.suffix() == "axe" )
|
||||
{
|
||||
if ( !installAxe( realPath, configuration ) )
|
||||
QString uniqueName = uuid();
|
||||
QDir dir( TomahawkUtils::extractScriptPayload( pathInfo.filePath(),
|
||||
uniqueName,
|
||||
MANUALRESOLVERS_DIR ) );
|
||||
if ( !( dir.exists() && dir.isReadable() ) ) //decompression fubar
|
||||
{
|
||||
displayError( tr( "Resolver installation error: cannot open bundle." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( !dir.cd( "content" ) ) //more fubar
|
||||
{
|
||||
displayError( tr( "Resolver installation error: incomplete bundle." ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString metadataFilePath = dir.absoluteFilePath( "metadata.json" );
|
||||
configuration = metadataFromJsonFile( metadataFilePath );
|
||||
|
||||
configuration[ "bundleDir" ] = uniqueName;
|
||||
|
||||
if ( !configuration[ "pluginName" ].isNull() && !configuration[ "pluginName" ].toString().isEmpty() )
|
||||
{
|
||||
dir.cdUp();
|
||||
if ( !dir.cdUp() ) //we're in MANUALRESOLVERS_DIR
|
||||
return 0;
|
||||
|
||||
QString name = configuration[ "pluginName" ].toString();
|
||||
|
||||
QString namePath = dir.absoluteFilePath( name );
|
||||
QFileInfo npI( namePath );
|
||||
|
||||
if ( npI.exists() && npI.isDir() )
|
||||
{
|
||||
TomahawkUtils::removeDirectory( namePath );
|
||||
}
|
||||
|
||||
dir.rename( uniqueName, name );
|
||||
|
||||
configuration[ "bundleDir" ] = name;
|
||||
|
||||
if ( !dir.cd( QString( "%1/content" ).arg( name ) ) ) //should work if it worked once
|
||||
return 0;
|
||||
}
|
||||
|
||||
expandPaths( dir, configuration );
|
||||
|
||||
realPath = configuration[ "path" ].toString();
|
||||
if ( realPath.isEmpty() )
|
||||
{
|
||||
displayError( tr( "Resolver installation error: bad metadata in bundle." ) );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -172,71 +221,6 @@ ResolverAccountFactory::createFromPath( const QString& path, const QString& fact
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ResolverAccountFactory::installAxe( QString& realPath, QVariantHash& configuration )
|
||||
{
|
||||
const QFileInfo pathInfo( realPath );
|
||||
QString uniqueName = uuid();
|
||||
QDir dir( TomahawkUtils::extractScriptPayload( pathInfo.filePath(),
|
||||
uniqueName,
|
||||
MANUALRESOLVERS_DIR ) );
|
||||
if ( !( dir.exists() && dir.isReadable() ) ) //decompression fubar
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage(
|
||||
tr( "Resolver installation error: cannot open bundle." ) ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( !dir.cd( "content" ) ) //more fubar
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage(
|
||||
tr( "Resolver installation error: incomplete bundle." ) ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
QString metadataFilePath = dir.absoluteFilePath( "metadata.json" );
|
||||
configuration = metadataFromJsonFile( metadataFilePath );
|
||||
|
||||
configuration[ "bundleDir" ] = uniqueName;
|
||||
|
||||
if ( !configuration[ "pluginName" ].isNull() && !configuration[ "pluginName" ].toString().isEmpty() )
|
||||
{
|
||||
dir.cdUp();
|
||||
if ( !dir.cdUp() ) //we're in MANUALRESOLVERS_DIR
|
||||
return 0;
|
||||
|
||||
QString name = configuration[ "pluginName" ].toString();
|
||||
|
||||
QString namePath = dir.absoluteFilePath( name );
|
||||
QFileInfo npI( namePath );
|
||||
|
||||
if ( npI.exists() && npI.isDir() )
|
||||
{
|
||||
TomahawkUtils::removeDirectory( namePath );
|
||||
}
|
||||
|
||||
dir.rename( uniqueName, name );
|
||||
|
||||
configuration[ "bundleDir" ] = name;
|
||||
|
||||
if ( !dir.cd( QString( "%1/content" ).arg( name ) ) ) //should work if it worked once
|
||||
return 0;
|
||||
}
|
||||
|
||||
expandPaths( dir, configuration );
|
||||
|
||||
realPath = configuration[ "path" ].toString();
|
||||
if ( realPath.isEmpty() )
|
||||
{
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage(
|
||||
tr( "Resolver installation error: bad metadata in bundle." ) ) );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
QVariantHash
|
||||
ResolverAccountFactory::metadataFromJsonFile( const QString& path )
|
||||
{
|
||||
@@ -533,16 +517,15 @@ ResolverAccount::removeBundle()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::testConfig()
|
||||
void ResolverAccount::testConfig()
|
||||
{
|
||||
// HACK: move to JSAccount once we have that properly
|
||||
JSResolver* resolver = qobject_cast< Tomahawk::JSResolver* >( m_resolver );
|
||||
if ( resolver )
|
||||
{
|
||||
QVariantMap data = resolver->loadDataFromWidgets();
|
||||
ScriptJob* job = resolver->scriptObject()->invoke( "testConfig", data );
|
||||
connect( job, SIGNAL( done( QVariant ) ), SLOT( onTestConfig( QVariant ) ) );
|
||||
ScriptJob* job = resolver->scriptObject()->invoke( "_testConfig", data );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onTestConfig( QVariantMap ) ) );
|
||||
job->start();
|
||||
}
|
||||
else
|
||||
@@ -552,25 +535,19 @@ ResolverAccount::testConfig()
|
||||
}
|
||||
|
||||
|
||||
ExternalResolverGui*
|
||||
ResolverAccount::resolver() const
|
||||
{
|
||||
return m_resolver;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::onTestConfig( const QVariant& result )
|
||||
ResolverAccount::onTestConfig( const QVariantMap& result )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << result;
|
||||
|
||||
if ( result.type() == QVariant::String )
|
||||
int resultCode = result[ "result" ].toInt();
|
||||
if ( resultCode == 1 )
|
||||
{
|
||||
emit configTestResult( Accounts::ConfigTestResultOther, result.toString() );
|
||||
emit configTestResult( Accounts::ConfigTestResultSuccess );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit configTestResult( result.toInt() );
|
||||
emit configTestResult( Accounts::ConfigTestResultOther );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
@@ -589,7 +566,6 @@ AtticaResolverAccount::AtticaResolverAccount( const QString& accountId )
|
||||
|
||||
}
|
||||
|
||||
|
||||
AtticaResolverAccount::AtticaResolverAccount( const QString& accountId, const QString& path, const QString& atticaId, const QVariantHash& initialConfiguration )
|
||||
: ResolverAccount( accountId, path, initialConfiguration )
|
||||
, m_atticaId( atticaId )
|
||||
@@ -619,6 +595,8 @@ AtticaResolverAccount::init()
|
||||
loadIcon();
|
||||
else
|
||||
connect( AtticaManager::instance(), SIGNAL( resolversLoaded( Attica::Content::List ) ), this, SLOT( loadIcon() ) );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -33,8 +33,6 @@ class ExternalResolverGui;
|
||||
|
||||
namespace Accounts {
|
||||
|
||||
class ResolverAccount;
|
||||
|
||||
class DLLEXPORT ResolverAccountFactory : public AccountFactory
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -55,10 +53,7 @@ public:
|
||||
Account* createFromPath( const QString& path ) override;
|
||||
|
||||
// Internal use
|
||||
static ResolverAccount* createFromPath( const QString& path, const QString& factoryId, bool isAttica );
|
||||
// YES, non const parameters!
|
||||
static bool installAxe( QString& realPath, QVariantHash& configuration );
|
||||
|
||||
static Account* createFromPath( const QString& path, const QString& factoryId, bool isAttica );
|
||||
|
||||
private:
|
||||
static void displayError( const QString& error );
|
||||
@@ -106,11 +101,9 @@ public:
|
||||
|
||||
void testConfig() override;
|
||||
|
||||
ExternalResolverGui* resolver() const;
|
||||
|
||||
private slots:
|
||||
void resolverChanged();
|
||||
void onTestConfig( const QVariant& result );
|
||||
void onTestConfig( const QVariantMap& result );
|
||||
|
||||
protected:
|
||||
// Created by factory, when user installs a new resolver
|
||||
|
@@ -71,7 +71,7 @@ LastFmAccount::LastFmAccount( const QString& accountId )
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,7 @@ LastFmAccount::~LastFmAccount()
|
||||
if ( m_infoPlugin )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
delete m_infoPlugin;
|
||||
}
|
||||
|
||||
delete m_resolver.data();
|
||||
@@ -167,11 +168,9 @@ InfoPluginPtr
|
||||
LastFmAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QSharedPointer< LastFmInfoPlugin>( new LastFmInfoPlugin( this ) );
|
||||
}
|
||||
m_infoPlugin = QPointer< LastFmInfoPlugin >( new LastFmInfoPlugin( this ) );
|
||||
|
||||
return m_infoPlugin;
|
||||
return InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
bool
|
||||
|
@@ -105,7 +105,7 @@ private:
|
||||
void hookupResolver();
|
||||
|
||||
QPointer<Tomahawk::ExternalResolverGui> m_resolver;
|
||||
QSharedPointer<Tomahawk::InfoSystem::LastFmInfoPlugin> m_infoPlugin;
|
||||
QPointer<Tomahawk::InfoSystem::LastFmInfoPlugin> m_infoPlugin;
|
||||
QPointer<LastFmConfig> m_configWidget;
|
||||
};
|
||||
|
||||
|
@@ -65,6 +65,13 @@ LastFmInfoPlugin::init()
|
||||
return;
|
||||
}
|
||||
|
||||
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
||||
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
||||
lastfm::ws::Username = m_account.data()->username();
|
||||
lastfm::setNetworkAccessManager( Tomahawk::Utils::nam() );
|
||||
|
||||
m_pw = m_account.data()->password();
|
||||
|
||||
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
|
||||
// tries to write the track cache, it fails silently. until we have a fixed version, do this
|
||||
// code taken from Amarok (src/services/lastfm/ScrobblerAdapter.cpp)
|
||||
@@ -79,17 +86,6 @@ LastFmInfoPlugin::init()
|
||||
|
||||
m_badUrls << QUrl( "http://cdn.last.fm/flatness/catalogue/noimage" );
|
||||
|
||||
|
||||
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
||||
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
||||
lastfm::setNetworkAccessManager( Tomahawk::Utils::nam() );
|
||||
|
||||
if ( !m_account.isNull() )
|
||||
{
|
||||
lastfm::ws::Username = m_account->username();
|
||||
m_pw = m_account->password();
|
||||
}
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( settingsChanged() ) );
|
||||
}
|
||||
|
||||
|
@@ -116,12 +116,6 @@ SpotifyAccount::~SpotifyAccount()
|
||||
{
|
||||
clearUser();
|
||||
|
||||
if ( m_infoPlugin )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
|
||||
if ( m_spotifyResolver.isNull() )
|
||||
return;
|
||||
|
||||
@@ -141,7 +135,7 @@ SpotifyAccount::init()
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
@@ -372,10 +366,10 @@ SpotifyAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QSharedPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
m_infoPlugin = QPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
}
|
||||
|
||||
return m_infoPlugin;
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -170,7 +170,7 @@ private:
|
||||
QPointer<SpotifyAccountConfig> m_configWidget;
|
||||
QPointer<QWidget> m_aboutWidget;
|
||||
QPointer<ScriptResolver> m_spotifyResolver;
|
||||
QSharedPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
QPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
|
||||
QMap<QString, QPair<QObject*, QString> > m_qidToSlotMap;
|
||||
QMap<QString, QVariant > m_qidToExtraData;
|
||||
|
@@ -277,7 +277,7 @@ SpotifyAccountConfig::showLoggedIn()
|
||||
m_ui->verticalLayout->insertWidget( 1, m_loggedInUser, 0, Qt::AlignCenter );
|
||||
}
|
||||
|
||||
qDebug() << "Showing logged in with username:" << m_verifiedUsername;
|
||||
qDebug() << "Showing logged in withuserame:" << m_verifiedUsername;
|
||||
m_loggedInUser->show();
|
||||
m_loggedInUser->setText( tr( "Logged in as %1" ).arg( m_verifiedUsername ) );
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2010-2016, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2015, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
* Copyright 2013, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
@@ -32,8 +32,6 @@
|
||||
#include "playlist/SingleTrackPlaylistInterface.h"
|
||||
#include "utils/Closure.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/NetworkReply.h"
|
||||
#include "utils/NetworkAccessManager.h"
|
||||
|
||||
#include "Album.h"
|
||||
#include "Artist.h"
|
||||
@@ -42,7 +40,6 @@
|
||||
#include "SourceList.h"
|
||||
#include "TomahawkSettings.h"
|
||||
#include "UrlHandler.h"
|
||||
#include "resolvers/ScriptJob.h"
|
||||
|
||||
#include <QDir>
|
||||
|
||||
@@ -165,19 +162,12 @@ AudioEngine::AudioEngine()
|
||||
d->s_instance = this;
|
||||
tDebug() << "Init AudioEngine";
|
||||
|
||||
d->audioOutput = new AudioOutput( this );
|
||||
d->audioOutput = new AudioOutput(this);
|
||||
|
||||
connect( d->audioOutput, SIGNAL( initialized() ), this, SIGNAL( initialized() ) );
|
||||
connect( d->audioOutput, SIGNAL( stateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ), d_func(), SLOT( onStateChanged( AudioOutput::AudioState, AudioOutput::AudioState ) ) );
|
||||
connect( d->audioOutput, SIGNAL( tick( qint64 ) ), SLOT( timerTriggered( qint64 ) ) );
|
||||
connect( d->audioOutput, SIGNAL( positionChanged( float ) ), SLOT( onPositionChanged( float ) ) );
|
||||
connect( d->audioOutput, SIGNAL( volumeChanged( qreal ) ), SLOT( onVolumeChanged( qreal ) ) );
|
||||
connect( d->audioOutput, SIGNAL( mutedChanged( bool ) ), SIGNAL( mutedChanged( bool ) ) );
|
||||
|
||||
if ( TomahawkSettings::instance()->muted() )
|
||||
{
|
||||
mute();
|
||||
}
|
||||
setVolume( TomahawkSettings::instance()->volume() );
|
||||
|
||||
qRegisterMetaType< AudioErrorCode >("AudioErrorCode");
|
||||
@@ -190,7 +180,6 @@ AudioEngine::~AudioEngine()
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
TomahawkSettings::instance()->setVolume( volume() );
|
||||
TomahawkSettings::instance()->setMuted( isMuted() );
|
||||
|
||||
delete d_ptr;
|
||||
}
|
||||
@@ -297,11 +286,8 @@ AudioEngine::stop( AudioErrorCode errorCode )
|
||||
if ( d->waitingOnNewTrack )
|
||||
sendWaitingNotification();
|
||||
|
||||
if ( d->audioOutput->isInitialized() )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||
}
|
||||
Tomahawk::InfoSystem::InfoPushData pushData( s_aeInfoIdentifier, Tomahawk::InfoSystem::InfoNowStopped, QVariant(), Tomahawk::InfoSystem::PushNoFlag );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->pushInfo( pushData );
|
||||
}
|
||||
|
||||
|
||||
@@ -466,8 +452,6 @@ AudioEngine::mute()
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
d->audioOutput->setMuted( true );
|
||||
|
||||
emit volumeChanged( volume() );
|
||||
}
|
||||
|
||||
|
||||
@@ -476,8 +460,6 @@ AudioEngine::toggleMute()
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
d->audioOutput->setMuted( !d->audioOutput->isMuted() );
|
||||
|
||||
emit volumeChanged( volume() );
|
||||
}
|
||||
|
||||
|
||||
@@ -572,16 +554,10 @@ AudioEngine::onNowPlayingInfoReady( const Tomahawk::InfoSystem::InfoType type )
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::loadTrack( const Tomahawk::result_ptr& result, bool preload )
|
||||
AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
{
|
||||
Q_D( AudioEngine );
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ) << " preload:" << preload;
|
||||
|
||||
|
||||
if ( !d->audioOutput->isInitialized() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
|
||||
if ( !result )
|
||||
{
|
||||
@@ -589,139 +565,38 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result, bool preload )
|
||||
return;
|
||||
}
|
||||
|
||||
if (preload && d->preloadedTrack == 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)
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << "not preloaded yet, preloading";
|
||||
setCurrentTrack( result );
|
||||
|
||||
if (preload)
|
||||
if ( !TomahawkUtils::isLocalResult( d->currentTrack->url() ) && !TomahawkUtils::isHttpResult( d->currentTrack->url() )
|
||||
&& !TomahawkUtils::isRtmpResult( d->currentTrack->url() ) )
|
||||
{
|
||||
setPreloadTrack( result );
|
||||
performLoadIODevice( d->currentTrack, d->currentTrack->url() );
|
||||
}
|
||||
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) );
|
||||
QSharedPointer< QIODevice > io;
|
||||
performLoadTrack( result, result->url(), io );
|
||||
}
|
||||
|
||||
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>();
|
||||
|
||||
tDebug() << Q_FUNC_INFO << " is preload:" << isPreload << ", for result:" << result;
|
||||
|
||||
if ( streamUrl.isEmpty() || headers.isEmpty() ||
|
||||
!( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
|
||||
{
|
||||
// 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, 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 );
|
||||
|
||||
QMap<QString, QString> parsedHeaders;
|
||||
foreach ( const QString& key, headers.keys() )
|
||||
{
|
||||
Q_ASSERT_X( headers[key].canConvert( QVariant::String ), Q_FUNC_INFO, "Expected a Map of string for additional headers" );
|
||||
if ( headers[key].canConvert( QVariant::String ) )
|
||||
{
|
||||
parsedHeaders.insert( key, headers[key].toString() );
|
||||
}
|
||||
}
|
||||
|
||||
foreach ( const QString& key, parsedHeaders.keys() )
|
||||
{
|
||||
req.setRawHeader( key.toLatin1(), parsedHeaders[key].toLatin1() );
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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, bool preload )
|
||||
AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
|
||||
{
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : url );
|
||||
|
||||
@@ -731,39 +606,37 @@ 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,
|
||||
preload );
|
||||
std::placeholders::_2 );
|
||||
Tomahawk::UrlHandler::getIODeviceForUrl( result, url, callback );
|
||||
}
|
||||
else
|
||||
{
|
||||
QSharedPointer< QIODevice > io;
|
||||
performLoadTrack( result, url, io, preload );
|
||||
performLoadTrack( result, url, io );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io, bool preload )
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString url, QSharedPointer< QIODevice > io )
|
||||
{
|
||||
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( bool, preload )
|
||||
Q_ARG( QSharedPointer< QIODevice >, io )
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( AudioEngine );
|
||||
if ( !preload && currentTrack() != result )
|
||||
if ( currentTrack() != result )
|
||||
{
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Track loaded too late, skip.";
|
||||
return;
|
||||
}
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() ) << preload;
|
||||
tDebug( LOGEXTRA ) << Q_FUNC_INFO << ( result.isNull() ? QString() : result->url() );
|
||||
QSharedPointer< QIODevice > ioToKeep = io;
|
||||
|
||||
bool err = false;
|
||||
@@ -777,16 +650,9 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
|
||||
if ( !err )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
tLog() << Q_FUNC_INFO << "Starting new song:" << url;
|
||||
d->state = Loading;
|
||||
emit loading( d->currentTrack );
|
||||
|
||||
if ( !TomahawkUtils::isLocalResult( url )
|
||||
&& !( TomahawkUtils::isHttpResult( url ) && io.isNull() )
|
||||
@@ -795,18 +661,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 ), preload );
|
||||
d->audioOutput->setCurrentSource( new QNR_IODeviceStream( qnr, this ) );
|
||||
// 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, preload );
|
||||
d->audioOutput->setAutoDelete( true );
|
||||
}
|
||||
else
|
||||
{
|
||||
d->audioOutput->setCurrentSource( io.data(), preload);
|
||||
d->audioOutput->setCurrentSource( io.data() );
|
||||
// We handle the deletion via tracking in d->input
|
||||
d->audioOutput->setAutoDelete( false, preload);
|
||||
d->audioOutput->setAutoDelete( false );
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -825,7 +691,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
}
|
||||
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << "Passing to VLC:" << furl;
|
||||
d->audioOutput->setCurrentSource( furl, preload );
|
||||
d->audioOutput->setCurrentSource( furl );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -834,37 +700,26 @@ 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 ), preload );
|
||||
d->audioOutput->setCurrentSource( QUrl::fromLocalFile( furl ) );
|
||||
}
|
||||
|
||||
d->audioOutput->setAutoDelete( true, preload );
|
||||
d->audioOutput->setAutoDelete( true );
|
||||
}
|
||||
|
||||
if ( preload ) {
|
||||
if ( !d->inputPreloaded.isNull() )
|
||||
{
|
||||
d->inputPreloaded->close();
|
||||
d->inputPreloaded.clear();
|
||||
}
|
||||
d->inputPreloaded = ioToKeep;
|
||||
}
|
||||
else
|
||||
if ( !d->input.isNull() )
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
||||
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
|
||||
d->input->close();
|
||||
d->input.clear();
|
||||
}
|
||||
d->input = ioToKeep;
|
||||
d->audioOutput->play();
|
||||
|
||||
if ( TomahawkSettings::instance()->privateListeningMode() != TomahawkSettings::FullyPrivate )
|
||||
{
|
||||
d->currentTrack->track()->startPlaying();
|
||||
}
|
||||
|
||||
sendNowPlayingNotification( Tomahawk::InfoSystem::InfoNowPlaying );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -874,10 +729,7 @@ AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString&
|
||||
return;
|
||||
}
|
||||
|
||||
if ( !preload )
|
||||
{
|
||||
d->waitingOnNewTrack = false;
|
||||
}
|
||||
d->waitingOnNewTrack = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -909,19 +761,18 @@ AudioEngine::loadPreviousTrack()
|
||||
}
|
||||
|
||||
if ( result )
|
||||
loadTrack( result, false );
|
||||
loadTrack( result );
|
||||
else
|
||||
stop();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::loadNextTrack( bool preload )
|
||||
AudioEngine::loadNextTrack()
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "loadNextTrack", Qt::QueuedConnection,
|
||||
Q_ARG( bool, preload ));
|
||||
QMetaObject::invokeMethod( this, "loadNextTrack", Qt::QueuedConnection );
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -935,11 +786,8 @@ AudioEngine::loadNextTrack( bool preload )
|
||||
{
|
||||
if ( d->stopAfterTrack->track()->equals( d->currentTrack->track() ) )
|
||||
{
|
||||
if ( !preload )
|
||||
{
|
||||
d->stopAfterTrack.clear();
|
||||
stop();
|
||||
}
|
||||
d->stopAfterTrack.clear();
|
||||
stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -957,24 +805,17 @@ AudioEngine::loadNextTrack( bool preload )
|
||||
|
||||
if ( d->playlist.data()->nextResult() )
|
||||
{
|
||||
if ( preload )
|
||||
{
|
||||
result = d->playlist.data()->nextResult();
|
||||
}
|
||||
else
|
||||
{
|
||||
result = d->playlist.data()->setSiblingResult( 1 );
|
||||
setCurrentTrackPlaylist( d->playlist );
|
||||
}
|
||||
result = d->playlist.data()->setSiblingResult( 1 );
|
||||
setCurrentTrackPlaylist( d->playlist );
|
||||
}
|
||||
}
|
||||
|
||||
if ( result )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got next item, loading track, preload:" << preload;
|
||||
loadTrack( result, preload );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Got next item, loading track";
|
||||
loadTrack( result );
|
||||
}
|
||||
else if ( !preload )
|
||||
else
|
||||
{
|
||||
if ( !d->playlist.isNull() && d->playlist.data()->retryMode() == Tomahawk::PlaylistModes::Retry )
|
||||
d->waitingOnNewTrack = true;
|
||||
@@ -1043,7 +884,7 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
|
||||
if ( result )
|
||||
{
|
||||
loadTrack( result, false );
|
||||
loadTrack( result );
|
||||
}
|
||||
else if ( !d->playlist.isNull() && d->playlist.data()->retryMode() == PlaylistModes::Retry )
|
||||
{
|
||||
@@ -1059,9 +900,9 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
void
|
||||
AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk::query_ptr& query )
|
||||
{
|
||||
if ( query->resolvingFinished() || query->numResults( true ) )
|
||||
if ( query->resolvingFinished() )
|
||||
{
|
||||
if ( query->numResults( true ) )
|
||||
if ( query->numResults() && query->results().first()->isOnline() )
|
||||
{
|
||||
playItem( playlist, query->results().first(), query );
|
||||
return;
|
||||
@@ -1077,7 +918,7 @@ AudioEngine::playItem( Tomahawk::playlistinterface_ptr playlist, const Tomahawk:
|
||||
{
|
||||
Pipeline::instance()->resolve( query );
|
||||
|
||||
NewClosure( query.data(), SIGNAL( resultsChanged() ),
|
||||
NewClosure( query.data(), SIGNAL( resolvingFinished( bool ) ),
|
||||
const_cast<AudioEngine*>(this), SLOT( playItem( Tomahawk::playlistinterface_ptr, Tomahawk::query_ptr ) ), playlist, query );
|
||||
}
|
||||
}
|
||||
@@ -1318,14 +1159,6 @@ 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 )
|
||||
{
|
||||
@@ -1352,6 +1185,7 @@ AudioEngine::setCurrentTrack( const Tomahawk::result_ptr& result )
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::setState( AudioState state )
|
||||
{
|
||||
|
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class NetworkReply;
|
||||
class AudioEnginePrivate;
|
||||
|
||||
class DLLEXPORT AudioEngine : public QObject
|
||||
@@ -135,10 +134,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 );
|
||||
@@ -149,8 +148,6 @@ public slots:
|
||||
void setShuffled( bool enabled );
|
||||
|
||||
signals:
|
||||
void initialized();
|
||||
|
||||
void loading( const Tomahawk::result_ptr track );
|
||||
void started( const Tomahawk::result_ptr track );
|
||||
void finished( const Tomahawk::result_ptr track );
|
||||
@@ -182,22 +179,17 @@ signals:
|
||||
void error( AudioEngine::AudioErrorCode errorCode );
|
||||
|
||||
private slots:
|
||||
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, 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 loadTrack( const Tomahawk::result_ptr& result ); //async!
|
||||
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 loadPreviousTrack();
|
||||
void loadNextTrack(bool preload = false);
|
||||
void loadNextTrack();
|
||||
|
||||
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();
|
||||
|
||||
|
@@ -28,11 +28,9 @@ 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;
|
||||
|
@@ -22,26 +22,21 @@
|
||||
#include "AudioEngine.h"
|
||||
#include "AudioOutput.h"
|
||||
#include "TomahawkVersion.h"
|
||||
#include "TomahawkSettings.h"
|
||||
|
||||
#include "audio/MediaStream.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/TomahawkUtils.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QVarLengthArray>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QTimer>
|
||||
|
||||
#include <vlc/libvlc.h>
|
||||
#include <vlc/libvlc_media.h>
|
||||
#include <vlc/libvlc_events.h>
|
||||
#include <vlc/libvlc_media_player.h>
|
||||
#include <vlc/libvlc_events.h>
|
||||
#include <vlc/libvlc_version.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
AudioOutput* AudioOutput::s_instance = 0;
|
||||
|
||||
|
||||
@@ -56,22 +51,17 @@ 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 )
|
||||
, m_justSeeked( false )
|
||||
, m_initialized( false )
|
||||
, dspPluginCallback( nullptr )
|
||||
, m_vlcInstance( nullptr )
|
||||
, m_vlcPlayer( nullptr )
|
||||
, m_vlcMedia( nullptr )
|
||||
, m_vlcPreloadedPlayer( nullptr )
|
||||
, m_vlcPreloadedMedia( nullptr )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
@@ -79,7 +69,7 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
|
||||
qRegisterMetaType<AudioOutput::AudioState>("AudioOutput::AudioState");
|
||||
|
||||
QVector<const char*> vlcArgs = {
|
||||
const char* vlcArgs[] = {
|
||||
"--ignore-config",
|
||||
"--extraintf=logger",
|
||||
qApp->arguments().contains( "--verbose" ) ? "--verbose=3" : "",
|
||||
@@ -91,28 +81,11 @@ 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( vlcArgs.size(), vlcArgs.constData() );
|
||||
m_vlcInstance = libvlc_new( sizeof(vlcArgs) / sizeof(*vlcArgs), vlcArgs );
|
||||
if ( !m_vlcInstance )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << "libVLC: could not initialize";
|
||||
@@ -122,133 +95,53 @@ AudioOutput::AudioOutput( QObject* parent )
|
||||
TOMAHAWK_APPLICATION_NAME "/" TOMAHAWK_VERSION );
|
||||
// FIXME: icon is named tomahawk, so we need the lowercase application name
|
||||
#if (LIBVLC_VERSION_INT >= LIBVLC_VERSION(2, 1, 0, 0))
|
||||
libvlc_set_app_id( m_vlcInstance, TOMAHAWK_APPLICATION_PACKAGE_NAME,
|
||||
TOMAHAWK_VERSION, TOMAHAWK_TARGET_NAME );
|
||||
libvlc_set_app_id( m_vlcInstance, "org.tomahawk-player.desktop",
|
||||
TOMAHAWK_VERSION, "tomahawk" );
|
||||
#endif
|
||||
|
||||
m_vlcPlayer = libvlc_media_player_new( m_vlcInstance );
|
||||
m_vlcPreloadedPlayer = libvlc_media_player_new( m_vlcInstance );
|
||||
|
||||
for( auto player : { m_vlcPlayer, m_vlcPreloadedPlayer } )
|
||||
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,
|
||||
libvlc_MediaPlayerVout
|
||||
};
|
||||
const int eventCount = sizeof(events) / sizeof( *events );
|
||||
for ( int i = 0; i < eventCount; i++ )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
libvlc_event_attach( 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
|
||||
m_silenceFile.setFileName( RESPATH "sounds/silence.ogg" );
|
||||
Q_ASSERT( m_silenceFile.exists() );
|
||||
Q_ASSERT( m_silenceFile.open( QIODevice::ReadOnly ) );
|
||||
|
||||
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)
|
||||
// if the silence file did not play for 15 secs, we pretend the AudioOutput is initialized, to allow proper error reporting
|
||||
QTimer::singleShot( 15000, [&]()
|
||||
{
|
||||
if ( !m_initialized ) {
|
||||
m_initialized = 2;
|
||||
emit initialized();
|
||||
}
|
||||
} );
|
||||
#endif
|
||||
tDebug() << Q_FUNC_INFO << "Init OK";
|
||||
}
|
||||
|
||||
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 );
|
||||
@@ -262,56 +155,23 @@ AudioOutput::~AudioOutput()
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::onInitVlcEvent( const libvlc_event_t* event )
|
||||
AudioOutput::setAutoDelete( bool ad )
|
||||
{
|
||||
switch ( event->type )
|
||||
{
|
||||
case libvlc_MediaPlayerTimeChanged:
|
||||
setVolume( volume() );
|
||||
setMuted( isMuted() );
|
||||
|
||||
m_initialized ++;
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "Init OK";
|
||||
if (m_initialized >=2)
|
||||
{
|
||||
m_silenceFile.close();
|
||||
emit initialized();
|
||||
}
|
||||
else
|
||||
{
|
||||
switchToPreloadedMedia();
|
||||
libvlc_media_player_play( m_vlcPlayer );
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
m_autoDelete = ad;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setAutoDelete( bool ad, bool preload )
|
||||
AudioOutput::setCurrentSource( const QUrl& stream )
|
||||
{
|
||||
if (preload)
|
||||
m_preloadedAutoDelete = ad;
|
||||
else
|
||||
m_autoDelete = ad;
|
||||
setCurrentSource( new MediaStream( stream ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setCurrentSource( const QUrl& stream, bool preload )
|
||||
AudioOutput::setCurrentSource( QIODevice* stream )
|
||||
{
|
||||
setCurrentSource( new MediaStream( stream ), preload );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setCurrentSource( QIODevice* stream, bool preload )
|
||||
{
|
||||
setCurrentSource( new MediaStream( stream ), preload );
|
||||
setCurrentSource( new MediaStream( stream ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -331,24 +191,29 @@ readDoneCallback( void* data, const char* cookie, size_t bufferSize, void* buffe
|
||||
|
||||
|
||||
void
|
||||
AudioOutput::setCurrentSource( MediaStream* stream, bool preload )
|
||||
AudioOutput::setCurrentSource( MediaStream* stream )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << ", preload = " << preload;
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
if ( !preload )
|
||||
setState( Loading );
|
||||
setState( Loading );
|
||||
|
||||
if ( m_vlcPreloadedMedia ) {
|
||||
libvlc_media_player_stop( m_vlcPreloadedPlayer );
|
||||
libvlc_media_release( m_vlcPreloadedMedia );
|
||||
m_vlcPreloadedMedia = nullptr;
|
||||
}
|
||||
if ( m_preloadedAutoDelete && m_preloadedStream != nullptr )
|
||||
if ( m_vlcMedia != nullptr )
|
||||
{
|
||||
delete m_preloadedStream;
|
||||
// Ensure playback is stopped, then release media
|
||||
libvlc_media_player_stop( m_vlcPlayer );
|
||||
libvlc_media_release( m_vlcMedia );
|
||||
m_vlcMedia = nullptr;
|
||||
}
|
||||
if ( m_autoDelete && m_currentStream != nullptr )
|
||||
{
|
||||
delete m_currentStream;
|
||||
}
|
||||
|
||||
m_preloadedStream = stream;
|
||||
m_currentStream = stream;
|
||||
m_totalTime = 0;
|
||||
m_currentTime = 0;
|
||||
m_justSeeked = false;
|
||||
m_seekable = true;
|
||||
|
||||
QByteArray url;
|
||||
switch ( stream->type() )
|
||||
@@ -382,19 +247,34 @@ AudioOutput::setCurrentSource( MediaStream* stream, bool preload )
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "MediaStream::Final Url:" << url;
|
||||
|
||||
m_vlcPreloadedMedia = libvlc_media_new_location( m_vlcInstance, url.constData() );
|
||||
if ( stream->type() == MediaStream::Stream || stream->type() == MediaStream::IODevice )
|
||||
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++ )
|
||||
{
|
||||
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);
|
||||
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);
|
||||
}
|
||||
if ( qApp->arguments().contains( "--chromecast-ip" ) )
|
||||
{
|
||||
@@ -410,7 +290,7 @@ AudioOutput::setCurrentSource( MediaStream* stream, bool preload )
|
||||
{
|
||||
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_vlcPreloadedMedia, sout.arg( castIP ).toLatin1().constData() );
|
||||
libvlc_media_add_option( m_vlcMedia, sout.arg( castIP ).toLatin1().constData() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -418,35 +298,10 @@ AudioOutput::setCurrentSource( MediaStream* stream, bool preload )
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
AudioOutput::isInitialized() const
|
||||
{
|
||||
return m_initialized > 1;
|
||||
}
|
||||
|
||||
|
||||
AudioOutput::AudioState
|
||||
AudioOutput::state() const
|
||||
{
|
||||
@@ -572,19 +427,16 @@ AudioOutput::seek( qint64 milliseconds )
|
||||
return;
|
||||
}
|
||||
|
||||
qint64 duration = AudioEngine::instance()->currentTrackTotalTime();
|
||||
// for some tracks, seeking to an end seems not to work correctly with libvlc
|
||||
// (tracks enter a random and infinite loop) - this is a temporary fix for that
|
||||
if (duration == milliseconds)
|
||||
milliseconds -= 1;
|
||||
|
||||
if ( m_seekable )
|
||||
{
|
||||
|
||||
// tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking" << milliseconds << "msec";
|
||||
libvlc_media_player_set_time( m_vlcPlayer, milliseconds );
|
||||
setCurrentTime( milliseconds );
|
||||
}
|
||||
else
|
||||
{
|
||||
qint64 duration = AudioEngine::instance()->currentTrackTotalTime();
|
||||
float position = float(float(milliseconds) / duration);
|
||||
libvlc_media_player_set_position(m_vlcPlayer, position);
|
||||
tDebug() << Q_FUNC_INFO << "AudioOutput:: seeking via position" << position << "pos";
|
||||
@@ -596,7 +448,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 );
|
||||
}
|
||||
|
||||
@@ -614,9 +466,11 @@ AudioOutput::setMuted( bool m )
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_muted = m;
|
||||
libvlc_audio_set_mute( m_vlcPlayer, m );
|
||||
|
||||
if ( !m_muted )
|
||||
if ( m_muted )
|
||||
{
|
||||
libvlc_audio_set_volume( m_vlcPlayer, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
libvlc_audio_set_volume( m_vlcPlayer, m_volume * 100.0 );
|
||||
}
|
||||
@@ -633,7 +487,7 @@ AudioOutput::volume() const
|
||||
void
|
||||
AudioOutput::setVolume( qreal vol )
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO << vol << m_muted;
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
|
||||
m_volume = vol;
|
||||
if ( !m_muted )
|
||||
@@ -646,107 +500,50 @@ AudioOutput::setVolume( qreal vol )
|
||||
void
|
||||
AudioOutput::onVlcEvent( const libvlc_event_t* event )
|
||||
{
|
||||
if ( event->p_obj == m_vlcPlayer || event->p_obj == m_vlcMedia )
|
||||
switch ( event->type )
|
||||
{
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -759,14 +556,7 @@ AudioOutput::vlcEventCallback( const libvlc_event_t* event, void* opaque )
|
||||
AudioOutput* that = reinterpret_cast < AudioOutput * > ( opaque );
|
||||
Q_ASSERT( that );
|
||||
|
||||
if ( !that->isInitialized() )
|
||||
{
|
||||
that->onInitVlcEvent( event );
|
||||
}
|
||||
else
|
||||
{
|
||||
that->onVlcEvent( event );
|
||||
}
|
||||
that->onVlcEvent( event );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -25,8 +25,6 @@
|
||||
#include "DllMacro.h"
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QFile>
|
||||
|
||||
#include <functional>
|
||||
|
||||
struct libvlc_instance_t;
|
||||
@@ -46,13 +44,11 @@ public:
|
||||
explicit AudioOutput( QObject* parent = nullptr );
|
||||
~AudioOutput();
|
||||
|
||||
bool isInitialized() const;
|
||||
AudioState state() const;
|
||||
|
||||
void setCurrentSource( const QUrl& stream, bool preload );
|
||||
void setCurrentSource( QIODevice* stream, bool preload );
|
||||
void setCurrentSource( MediaStream* stream, bool preload );
|
||||
void setPreloadedSourceAsCurrent( void );
|
||||
void setCurrentSource( const QUrl& stream );
|
||||
void setCurrentSource( QIODevice* stream );
|
||||
void setCurrentSource( MediaStream* stream );
|
||||
|
||||
void play();
|
||||
void pause();
|
||||
@@ -66,34 +62,26 @@ public:
|
||||
qreal volume() const;
|
||||
qint64 currentTime() const;
|
||||
qint64 totalTime() const;
|
||||
void setAutoDelete ( bool ad, bool preload );
|
||||
void setAutoDelete ( bool ad );
|
||||
|
||||
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:
|
||||
void initialized();
|
||||
void stateChanged( AudioOutput::AudioState, AudioOutput::AudioState );
|
||||
void tick( qint64 );
|
||||
void positionChanged( float );
|
||||
void volumeChanged( qreal volume );
|
||||
void mutedChanged( bool );
|
||||
|
||||
private:
|
||||
void onInitVlcEvent( const libvlc_event_t* event );
|
||||
|
||||
void setState( AudioState state );
|
||||
void setCurrentTime( qint64 time );
|
||||
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 );
|
||||
@@ -101,11 +89,9 @@ 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;
|
||||
@@ -113,17 +99,11 @@ private:
|
||||
qint64 m_totalTime;
|
||||
bool m_justSeeked;
|
||||
|
||||
int m_initialized;
|
||||
QFile m_silenceFile;
|
||||
|
||||
std::function< void( int state, int frameNumber, float* samples, int nb_channels, int nb_samples ) > dspPluginCallback;
|
||||
|
||||
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
|
||||
|
@@ -41,16 +41,12 @@ MediaStream::MediaStream( const QUrl &url )
|
||||
}
|
||||
|
||||
|
||||
MediaStream::MediaStream( QIODevice* device, bool bufferingFinished )
|
||||
MediaStream::MediaStream( QIODevice* device )
|
||||
: QObject( nullptr )
|
||||
, m_type( IODevice )
|
||||
, m_ioDevice ( device )
|
||||
, m_bufferingFinished( bufferingFinished )
|
||||
{
|
||||
if ( !bufferingFinished )
|
||||
{
|
||||
QObject::connect( m_ioDevice, SIGNAL( readChannelFinished() ), this, SLOT( bufferingFinished() ) );
|
||||
}
|
||||
QObject::connect( m_ioDevice, SIGNAL( readChannelFinished() ), this, SLOT( bufferingFinished() ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -151,6 +147,7 @@ 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 );
|
||||
|
@@ -42,7 +42,7 @@ public:
|
||||
|
||||
MediaStream( QObject* parent = nullptr );
|
||||
explicit MediaStream( const QUrl &url );
|
||||
explicit MediaStream( QIODevice* device, bool bufferingFinished = false );
|
||||
explicit MediaStream( QIODevice* device );
|
||||
virtual ~MediaStream();
|
||||
|
||||
MediaType type() const;
|
||||
|
@@ -35,7 +35,7 @@ using namespace Tomahawk;
|
||||
|
||||
|
||||
Collection::Collection( const source_ptr& source, const QString& name, QObject* parent )
|
||||
: Resolver( parent )
|
||||
: QObject( parent )
|
||||
, m_name( name )
|
||||
, m_lastmodified( 0 )
|
||||
, m_changed( false )
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#include "collection/ArtistsRequest.h"
|
||||
#include "collection/AlbumsRequest.h"
|
||||
#include "collection/TracksRequest.h"
|
||||
#include "../resolvers/Resolver.h"
|
||||
#include "../ResultProvider.h"
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT Collection : public Resolver
|
||||
class DLLEXPORT Collection : public QObject, public ResultProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -128,13 +128,10 @@ DatabaseCollection::playlists()
|
||||
QList< dynplaylist_ptr >
|
||||
DatabaseCollection::autoPlaylists()
|
||||
{
|
||||
// echonest is dead, disable all echonest code
|
||||
/*
|
||||
if ( Collection::autoPlaylists().isEmpty() )
|
||||
{
|
||||
loadAutoPlaylists();
|
||||
}
|
||||
*/
|
||||
|
||||
return Collection::autoPlaylists();
|
||||
}
|
||||
@@ -143,13 +140,10 @@ DatabaseCollection::autoPlaylists()
|
||||
QList< dynplaylist_ptr >
|
||||
DatabaseCollection::stations()
|
||||
{
|
||||
// echonest is dead, disable all echonest code
|
||||
/*
|
||||
if ( Collection::stations().isEmpty() )
|
||||
{
|
||||
loadStations();
|
||||
}
|
||||
*/
|
||||
|
||||
return Collection::stations();
|
||||
}
|
||||
@@ -257,32 +251,3 @@ DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Resolver interface
|
||||
*
|
||||
* We implement searching the database in the DatabaseResolver which avoids a n+1 query here.
|
||||
* We can't simply let ScriptCollection inherit Collection and Resolver because both are QObjects,
|
||||
* although Resolver doesn't need to be a QObject atm, blocking adding signals/slots to Resolver
|
||||
* in future seems to me worse than violating Liskov's law here. ~ domme
|
||||
*/
|
||||
unsigned int
|
||||
DatabaseCollection::timeout() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
DatabaseCollection::weight() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DatabaseCollection::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
Q_UNUSED( query );
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
@@ -65,11 +65,6 @@ public:
|
||||
int trackCount() const override;
|
||||
QPixmap icon( const QSize& size ) const override;
|
||||
|
||||
// Resolver interface
|
||||
unsigned int weight() const override;
|
||||
unsigned int timeout() const override;
|
||||
void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
|
||||
public slots:
|
||||
virtual void addTracks( const QList<QVariant>& newitems );
|
||||
virtual void removeTracks( const QDir& dir );
|
||||
|
@@ -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 ) override { m_filter = filter; }
|
||||
void setFilter( const QString& filter ) { m_filter = filter; }
|
||||
|
||||
signals:
|
||||
void artists( const QList<Tomahawk::artist_ptr>& ) override;
|
||||
void artists( const QList<Tomahawk::artist_ptr>& );
|
||||
void done();
|
||||
|
||||
private:
|
||||
|
@@ -74,7 +74,7 @@ public:
|
||||
|
||||
signals:
|
||||
void tracks( const QList<Tomahawk::query_ptr>&, const QVariant& data );
|
||||
void tracks( const QList<Tomahawk::query_ptr>& ) override;
|
||||
void tracks( const QList<Tomahawk::query_ptr>& );
|
||||
void done( const Tomahawk::collection_ptr& );
|
||||
|
||||
private:
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include "Source.h"
|
||||
#include "network/Servent.h"
|
||||
#include "SourceList.h"
|
||||
#include "EchonestCatalogSynchronizer.h"
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@@ -75,11 +76,9 @@ 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();
|
||||
|
@@ -34,11 +34,11 @@ public:
|
||||
explicit DatabaseResolver( int weight );
|
||||
|
||||
QString name() const override;
|
||||
virtual unsigned int weight() const override{ return m_weight; }
|
||||
virtual unsigned int timeout() const override{ return 0; }
|
||||
virtual unsigned int weight() const { return m_weight; }
|
||||
virtual unsigned int timeout() const { return 0; }
|
||||
|
||||
public slots:
|
||||
virtual void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
virtual void resolve( const Tomahawk::query_ptr& query );
|
||||
|
||||
private slots:
|
||||
void gotResults( const Tomahawk::QID qid, QList< Tomahawk::result_ptr> results );
|
||||
|
@@ -1,20 +1,21 @@
|
||||
/* === 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/>.
|
||||
*/
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "LocalCollection.h"
|
||||
|
||||
|
@@ -1,20 +1,21 @@
|
||||
/* === 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/>.
|
||||
*/
|
||||
/*
|
||||
Copyright (C) 2011 Leo Franchi <lfranchi@kde.org>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LOCALCOLLECTION_H
|
||||
#define LOCALCOLLECTION_H
|
||||
|
@@ -240,7 +240,7 @@ MetadataEditor::loadResult( const Tomahawk::result_ptr& result )
|
||||
return;
|
||||
|
||||
m_result = result;
|
||||
setEditable( result->isLocal() );
|
||||
setEditable( result->resolvedByCollection() && result->resolvedByCollection()->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->isLocal() )
|
||||
if ( result->resolvedByCollection() && result->resolvedByCollection()->isLocal() )
|
||||
{
|
||||
QString furl = m_result->url();
|
||||
if ( furl.startsWith( "file://" ) )
|
||||
|
@@ -40,11 +40,6 @@ using namespace Tomahawk;
|
||||
void
|
||||
DirLister::go()
|
||||
{
|
||||
if ( m_dirs.isEmpty() )
|
||||
{
|
||||
emit finished();
|
||||
return;
|
||||
}
|
||||
foreach ( const QString& dir, m_dirs )
|
||||
{
|
||||
m_opcount++;
|
||||
|
@@ -277,8 +277,8 @@ InfoSystem::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
|
||||
|
||||
if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread(): " << plugin->friendlyName();
|
||||
Q_ASSERT( false );
|
||||
tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -58,7 +58,13 @@ InfoSystemWorker::InfoSystemWorker()
|
||||
|
||||
InfoSystemWorker::~InfoSystemWorker()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
tDebug() << Q_FUNC_INFO << " beginning";
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
if( plugin )
|
||||
delete plugin.data();
|
||||
}
|
||||
tDebug() << Q_FUNC_INFO << " finished";
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +136,29 @@ InfoSystemWorker::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
|
||||
|
||||
emit updatedSupportedGetTypes( QSet< InfoType >::fromList( m_infoGetMap.keys() ) );
|
||||
emit updatedSupportedPushTypes( QSet< InfoType >::fromList( m_infoPushMap.keys() ) );
|
||||
|
||||
connect( plugin.data(), SIGNAL( destroyed( QObject* ) ), SLOT( onInfoPluginDeleted() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::onInfoPluginDeleted()
|
||||
{
|
||||
foreach( const InfoPluginPtr& plugin, m_plugins )
|
||||
{
|
||||
if ( plugin.isNull() )
|
||||
{
|
||||
m_plugins.removeOne( plugin );
|
||||
foreach( InfoType type, m_infoGetMap.keys() )
|
||||
{
|
||||
m_infoGetMap[type].removeOne( plugin );
|
||||
}
|
||||
foreach( InfoType type, m_infoPushMap.keys() )
|
||||
{
|
||||
m_infoPushMap[type].removeOne( plugin );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -72,6 +72,7 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void checkTimeoutsTimerFired();
|
||||
void onInfoPluginDeleted();
|
||||
|
||||
private:
|
||||
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
|
||||
|
@@ -33,12 +33,6 @@ JobStatusItem::~JobStatusItem()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusItem::activated()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
JobStatusItem::allowMultiLine() const
|
||||
{
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user