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

Compare commits

..

3 Commits

Author SHA1 Message Date
Dominik Schmidt
365c7b0e31 Get woah resolvers from synchrotron 2015-11-13 01:55:15 +01:00
Dominik Schmidt
9ae97e50ad Move moar stuff over to es6 foo 2015-11-13 01:55:15 +01:00
Dominik Schmidt
72dab1aae6 Move to new es6 based standalone resolvers 2015-11-13 01:54:32 +01:00
231 changed files with 2606 additions and 5067 deletions

View File

@@ -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)

View 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)

View File

@@ -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
)

View File

@@ -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"

View File

@@ -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.

View File

@@ -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/)

View File

@@ -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} )

View File

@@ -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)

View File

@@ -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>

View File

@@ -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!"

View File

@@ -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

View File

@@ -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))

View File

@@ -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`

View File

@@ -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* \

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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));
}
};

View File

@@ -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, "&lt;");
str = str.replace(/>/g, "&gt;");
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.

View File

@@ -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>

View File

@@ -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

View File

@@ -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 )
{

View File

@@ -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 );

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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
)

View File

@@ -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 );

View File

@@ -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;

View File

@@ -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;

View File

@@ -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}
)

View File

@@ -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

View File

@@ -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 );

View File

@@ -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}
)

View File

@@ -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

View File

@@ -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" ] );

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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 ) ) );

View File

@@ -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 )

View File

@@ -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 );
}

View File

@@ -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 );

View File

@@ -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( "\\", "_" )

View File

@@ -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();

View File

@@ -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 )
{

View File

@@ -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 );

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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 ) );
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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 );

View File

@@ -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

View File

@@ -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.

View File

@@ -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 );

View File

@@ -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." ) ) );
}
}

View File

@@ -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;

View File

@@ -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() ) );
}

View File

@@ -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

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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() ) );
}

View File

@@ -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() );
}

View File

@@ -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;

View File

@@ -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 ) );

View File

@@ -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 )
{

View File

@@ -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();

View File

@@ -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;

View File

@@ -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 );
}

View File

@@ -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

View File

@@ -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 );

View File

@@ -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;

View File

@@ -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 )

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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 );

View File

@@ -59,10 +59,10 @@ public:
void setLimit( unsigned int amount ) { m_amount = amount; }
void setSortOrder( DatabaseCommand_AllArtists::SortOrder order ) { m_sortOrder = order; }
void setSortDescending( bool descending ) { m_sortDescending = descending; }
void setFilter( const QString& filter ) 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:

View File

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

View File

@@ -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();

View File

@@ -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 );

View File

@@ -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"

View File

@@ -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

View File

@@ -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://" ) )

View 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++;

View File

@@ -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;
}

View File

@@ -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 );
}
}
}
}

View File

@@ -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 );

View File

@@ -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