mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-09-09 05:30:52 +02:00
Compare commits
3 Commits
albumandar
...
woah
Author | SHA1 | Date | |
---|---|---|---|
|
365c7b0e31 | ||
|
9ae97e50ad | ||
|
72dab1aae6 |
@@ -307,10 +307,11 @@ 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")
|
||||
|
||||
@@ -403,8 +404,12 @@ if( WIN32 )
|
||||
endif( WIN32 )
|
||||
|
||||
if( WIN32 OR APPLE )
|
||||
macro_optional_find_package(LibsnoreQt5 0.5.70 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)
|
||||
|
@@ -6,16 +6,19 @@ find_path(LIBVLC_INCLUDE_DIR vlc/vlc.h
|
||||
HINTS
|
||||
${PC_LIBVLC_INCLUDEDIR}
|
||||
${PC_LIBVLC_INCLUDE_DIRS}
|
||||
/usr/local/opt/vlc/include
|
||||
)
|
||||
|
||||
find_library(LIBVLC_LIBRARY NAMES vlc libvlc
|
||||
HINTS
|
||||
${PC_LIBVLC_LIBDIR}
|
||||
${PC_LIBVLC_LIBRARY_DIRS}
|
||||
/usr/local/opt/vlc/lib
|
||||
)
|
||||
|
||||
find_library(LIBVLCCORE_LIBRARY NAMES vlccore libvlccore
|
||||
HINTS
|
||||
${PC_LIBVLC_LIBDIR}
|
||||
${PC_LIBVLC_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(LIBVLC_VERSION ${PC_LIBVLC_VERSION})
|
||||
|
||||
@@ -29,6 +32,8 @@ int main(int argc, char *argv[]) {
|
||||
HAVE_VLC_ALBUMARTIST)
|
||||
|
||||
find_package_handle_standard_args(LibVLC
|
||||
REQUIRED_VARS LIBVLC_LIBRARY LIBVLC_INCLUDE_DIR
|
||||
REQUIRED_VARS LIBVLC_LIBRARY LIBVLCCORE_LIBRARY LIBVLC_INCLUDE_DIR
|
||||
VERSION_VAR LIBVLC_VERSION
|
||||
)
|
||||
|
||||
|
||||
|
@@ -15,25 +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 "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 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
|
||||
@@ -334,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"
|
||||
@@ -343,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"
|
||||
@@ -463,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"
|
||||
|
@@ -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
|
||||
|
@@ -5,23 +5,23 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>@TOMAHAWK_APPLICATION_NAME@</string>
|
||||
<string>Tomahawk</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>@TOMAHAWK_APPLICATION_PACKAGE_NAME@</string>
|
||||
<string>org.tomahawk-player.Tomahawk</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>@TOMAHAWK_VERSION@</string>
|
||||
<string>TOMAHAWK_VERSION</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>@TOMAHAWK_VERSION@</string>
|
||||
<string>TOMAHAWK_VERSION</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>@TOMAHAWK_BASE_TARGET_NAME@</string>
|
||||
<string>tomahawk</string>
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>@TOMAHAWK_APPLICATION_NAME@.icns</string>
|
||||
<string>Tomahawk.icns</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>@TOMAHAWK_APPLICATION_NAME@</string>
|
||||
<string>Tomahawk</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.7.0</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
@@ -29,7 +29,7 @@
|
||||
<key>NSHighResolutionCapable</key>
|
||||
<true />
|
||||
<key>SUFeedURL</key>
|
||||
<string>@TOMAHAWK_SPARKLE_UPDATE_URL@</string>
|
||||
<string>http://download.tomahawk-player.org/sparkle/update.php</string>
|
||||
<key>SUPublicDSAKeyFile</key>
|
||||
<string>sparkle_pub.pem</string>
|
||||
<key>SUEnableSystemProfiling</key>
|
||||
|
@@ -4,10 +4,9 @@
|
||||
#
|
||||
################################################################################
|
||||
|
||||
TARGET_NAME="Tomahawk"
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
function header {
|
||||
echo -e "\033[0;34m==>\033[0;0;1m $1 \033[0;0m"
|
||||
}
|
||||
@@ -32,28 +31,30 @@ CERT_SIGNER=$2
|
||||
################################################################################
|
||||
|
||||
header "Fixing and copying libraries"
|
||||
$ROOT/../admin/mac/macdeploy.py "${TARGET_NAME}.app" quiet
|
||||
$ROOT/../admin/mac/macdeploy.py Tomahawk.app quiet
|
||||
|
||||
cd "${TARGET_NAME}.app"
|
||||
cd Tomahawk.app
|
||||
|
||||
cp $ROOT/../admin/mac/qt.conf Contents/Resources/qt.conf
|
||||
|
||||
header "Fixing fonts"
|
||||
mkdir "${ROOT}/${TARGET_NAME}.app/Contents/Resources/Fonts"
|
||||
cp -R $ROOT/../data/fonts/*.ttf "${ROOT}/${TARGET_NAME}.app/Contents/Resources/Fonts"
|
||||
|
||||
header "Signing bundle"
|
||||
cd ..
|
||||
if [ -f ~/sign_step.sh ];
|
||||
then
|
||||
~/sign_step.sh "$CERT_SIGNER" "${TARGET_NAME}.app" || true
|
||||
fi
|
||||
# header "Copying Sparkle framework"
|
||||
# cp -R /Library/Frameworks/Sparkle.framework Contents/Frameworks
|
||||
|
||||
header "Creating DMG"
|
||||
$ROOT/../admin/mac/create-dmg.sh "${TARGET_NAME}.app"
|
||||
mv "${TARGET_NAME}.dmg" "${TARGET_NAME}-$VERSION.dmg"
|
||||
cd ..
|
||||
|
||||
header "Signing bundle"
|
||||
# codesign -s "Developer ID Application: $CERT_SIGNER" -f -v ./Tomahawk.app
|
||||
|
||||
if [ -f ~/sign_step.sh ];
|
||||
then
|
||||
~/sign_step.sh "$CERT_SIGNER" "Tomahawk.app" || true
|
||||
fi
|
||||
|
||||
$ROOT/../admin/mac/create-dmg.sh Tomahawk.app
|
||||
mv Tomahawk.dmg Tomahawk-$VERSION.dmg
|
||||
|
||||
header "Creating signed Sparkle update"
|
||||
# $ROOT/../admin/mac/sign_bundle.rb "${TARGET_NAME}" $VERSION ~/tomahawk_sparkle_privkey.pem
|
||||
$ROOT/../admin/mac/sign_bundle.rb $VERSION ~/tomahawk_sparkle_privkey.pem
|
||||
|
||||
header "Done!"
|
||||
|
@@ -43,7 +43,7 @@ ln -s /Applications "$TMP/Applications"
|
||||
cp -R "$IN" "$TMP"
|
||||
|
||||
# create
|
||||
hdiutil makehybrid -hfs -hfs-volume-name "$NAME" -hfs-openfolder "$TMP" "$TMP" -o tmp.dmg
|
||||
hdiutil makehybrid -hfs -hfs-volume-name Tomahawk -hfs-openfolder "$TMP" "$TMP" -o tmp.dmg
|
||||
hdiutil convert -format UDZO -imagekey zlib-level=9 tmp.dmg -o "$OUT"
|
||||
|
||||
# cleanup
|
||||
|
@@ -22,170 +22,171 @@ import commands
|
||||
import sys
|
||||
import glob
|
||||
|
||||
TARGET_NAME="tomahawk"
|
||||
|
||||
FRAMEWORK_SEARCH_PATH=[
|
||||
'/Library/Frameworks',
|
||||
os.path.join(os.environ['HOME'], 'Library/Frameworks')
|
||||
]
|
||||
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/opt/vlc/lib', '/usr/local/Cellar/gettext/0.19.2/lib', '.']
|
||||
LIBRARY_SEARCH_PATH=['/usr/local/lib', '/usr/local/Cellar/gettext/0.19.2/lib', '.']
|
||||
|
||||
VLC_PLUGINS=[
|
||||
'libattachment_plugin.dylib',
|
||||
#'libaccess_avio_plugin.dylib',
|
||||
#'libaccess_fake_plugin.dylib',
|
||||
'libftp_plugin.dylib',
|
||||
'libhttp_plugin.dylib',
|
||||
'libhttplive_plugin.dylib',
|
||||
'libimem_plugin.dylib',
|
||||
#'libaccess_mmap_plugin.dylib',
|
||||
'libaccess_mms_plugin.dylib',
|
||||
'libaccess_realrtsp_plugin.dylib',
|
||||
'libtcp_plugin.dylib',
|
||||
'libudp_plugin.dylib',
|
||||
'libcdda_plugin.dylib',
|
||||
'libfilesystem_plugin.dylib',
|
||||
'libqtcapture_plugin.dylib',
|
||||
'librtp_plugin.dylib',
|
||||
'libzip_plugin.dylib',
|
||||
'liba52tofloat32_plugin.dylib',
|
||||
'liba52tospdif_plugin.dylib',
|
||||
'libaudio_format_plugin.dylib',
|
||||
'libaudiobargraph_a_plugin.dylib',
|
||||
'libchorus_flanger_plugin.dylib',
|
||||
'access/libattachment_plugin.dylib',
|
||||
#'access/libaccess_avio_plugin.dylib',
|
||||
#'access/libaccess_fake_plugin.dylib',
|
||||
'access/libftp_plugin.dylib',
|
||||
'access/libhttp_plugin.dylib',
|
||||
'access/libimem_plugin.dylib',
|
||||
#'access/libaccess_mmap_plugin.dylib',
|
||||
'access/libaccess_mms_plugin.dylib',
|
||||
'access/libaccess_realrtsp_plugin.dylib',
|
||||
'access/libtcp_plugin.dylib',
|
||||
'access/libudp_plugin.dylib',
|
||||
'access/libcdda_plugin.dylib',
|
||||
'access/libfilesystem_plugin.dylib',
|
||||
'access/libqtcapture_plugin.dylib',
|
||||
'access/librtp_plugin.dylib',
|
||||
'access/libzip_plugin.dylib',
|
||||
'access_output/libaccess_output_dummy_plugin.dylib',
|
||||
'access_output/libaccess_output_file_plugin.dylib',
|
||||
'access_output/libaccess_output_http_plugin.dylib',
|
||||
'access_output/libaccess_output_shout_plugin.dylib',
|
||||
'access_output/libaccess_output_udp_plugin.dylib',
|
||||
'audio_filter/liba52tofloat32_plugin.dylib',
|
||||
'audio_filter/liba52tospdif_plugin.dylib',
|
||||
'audio_filter/libaudio_format_plugin.dylib',
|
||||
'audio_filter/libaudiobargraph_a_plugin.dylib',
|
||||
'audio_filter/libchorus_flanger_plugin.dylib',
|
||||
#'libconverter_fixed_plugin.dylib',
|
||||
'libdolby_surround_decoder_plugin.dylib',
|
||||
'libdtstofloat32_plugin.dylib',
|
||||
'libdtstospdif_plugin.dylib',
|
||||
'libequalizer_plugin.dylib',
|
||||
'libheadphone_channel_mixer_plugin.dylib',
|
||||
'libmono_plugin.dylib',
|
||||
'libmpgatofixed32_plugin.dylib',
|
||||
'libnormvol_plugin.dylib',
|
||||
'libparam_eq_plugin.dylib',
|
||||
'libscaletempo_plugin.dylib',
|
||||
'libsimple_channel_mixer_plugin.dylib',
|
||||
'libspatializer_plugin.dylib',
|
||||
'libtrivial_channel_mixer_plugin.dylib',
|
||||
'libugly_resampler_plugin.dylib',
|
||||
'libfloat_mixer_plugin.dylib',
|
||||
'audio_filter/libdolby_surround_decoder_plugin.dylib',
|
||||
'audio_filter/libdtstofloat32_plugin.dylib',
|
||||
'audio_filter/libdtstospdif_plugin.dylib',
|
||||
'audio_filter/libequalizer_plugin.dylib',
|
||||
'audio_filter/libheadphone_channel_mixer_plugin.dylib',
|
||||
'audio_filter/libmono_plugin.dylib',
|
||||
'audio_filter/libmpgatofixed32_plugin.dylib',
|
||||
'audio_filter/libnormvol_plugin.dylib',
|
||||
'audio_filter/libparam_eq_plugin.dylib',
|
||||
'audio_filter/libscaletempo_plugin.dylib',
|
||||
'audio_filter/libsimple_channel_mixer_plugin.dylib',
|
||||
'audio_filter/libspatializer_plugin.dylib',
|
||||
'audio_filter/libtrivial_channel_mixer_plugin.dylib',
|
||||
'audio_filter/libugly_resampler_plugin.dylib',
|
||||
'audio_mixer/libfloat_mixer_plugin.dylib',
|
||||
#'libspdif_mixer_plugin.dylib',
|
||||
#'libtrivial_mixer_plugin.dylib',
|
||||
#'libaout_file_plugin.dylib',
|
||||
'libauhal_plugin.dylib',
|
||||
'liba52_plugin.dylib',
|
||||
'libadpcm_plugin.dylib',
|
||||
'libaes3_plugin.dylib',
|
||||
'libaraw_plugin.dylib',
|
||||
'libavcodec_plugin.dylib',
|
||||
'libcc_plugin.dylib',
|
||||
'libcdg_plugin.dylib',
|
||||
'libdts_plugin.dylib',
|
||||
'libfaad_plugin.dylib',
|
||||
'audio_output/libauhal_plugin.dylib',
|
||||
'codec/liba52_plugin.dylib',
|
||||
'codec/libadpcm_plugin.dylib',
|
||||
'codec/libaes3_plugin.dylib',
|
||||
'codec/libaraw_plugin.dylib',
|
||||
'codec/libavcodec_plugin.dylib',
|
||||
'codec/libcc_plugin.dylib',
|
||||
'codec/libcdg_plugin.dylib',
|
||||
'codec/libdts_plugin.dylib',
|
||||
'codec/libfaad_plugin.dylib',
|
||||
#'libfake_plugin.dylib',
|
||||
'libflac_plugin.dylib',
|
||||
'codec/libflac_plugin.dylib',
|
||||
#'libfluidsynth_plugin.dylib',
|
||||
#'libinvmem_plugin.dylib',
|
||||
'liblpcm_plugin.dylib',
|
||||
'libmpeg_audio_plugin.dylib',
|
||||
'libpng_plugin.dylib',
|
||||
'librawvideo_plugin.dylib',
|
||||
'libspeex_plugin.dylib',
|
||||
'libspudec_plugin.dylib',
|
||||
'libtheora_plugin.dylib',
|
||||
'libtwolame_plugin.dylib',
|
||||
'libvorbis_plugin.dylib',
|
||||
#'libgestures_plugin.dylib',
|
||||
'codec/liblpcm_plugin.dylib',
|
||||
'codec/libmpeg_audio_plugin.dylib',
|
||||
'codec/libpng_plugin.dylib',
|
||||
'codec/librawvideo_plugin.dylib',
|
||||
'codec/libspeex_plugin.dylib',
|
||||
'codec/libspudec_plugin.dylib',
|
||||
'codec/libtheora_plugin.dylib',
|
||||
'codec/libtwolame_plugin.dylib',
|
||||
'codec/libvorbis_plugin.dylib',
|
||||
#'control/libgestures_plugin.dylib',
|
||||
#'libhotkeys_plugin.dylib',
|
||||
#'libmotion_plugin.dylib',
|
||||
#'libnetsync_plugin.dylib',
|
||||
#'libsignals_plugin.dylib',
|
||||
'libaiff_plugin.dylib',
|
||||
'libasf_plugin.dylib',
|
||||
'libau_plugin.dylib',
|
||||
'demux/libaiff_plugin.dylib',
|
||||
'demux/libasf_plugin.dylib',
|
||||
'demux/libau_plugin.dylib',
|
||||
#'libavformat_plugin.dylib',
|
||||
'libavi_plugin.dylib',
|
||||
'libdemux_cdg_plugin.dylib',
|
||||
'libdemuxdump_plugin.dylib',
|
||||
'libdiracsys_plugin.dylib',
|
||||
'libes_plugin.dylib',
|
||||
'libflacsys_plugin.dylib',
|
||||
'liblive555_plugin.dylib',
|
||||
'libmkv_plugin.dylib',
|
||||
'libmod_plugin.dylib',
|
||||
'libmp4_plugin.dylib',
|
||||
'libmpc_plugin.dylib',
|
||||
'libmpgv_plugin.dylib',
|
||||
'libnsc_plugin.dylib',
|
||||
'libnsv_plugin.dylib',
|
||||
'libnuv_plugin.dylib',
|
||||
'libogg_plugin.dylib',
|
||||
'libplaylist_plugin.dylib',
|
||||
'libps_plugin.dylib',
|
||||
'libpva_plugin.dylib',
|
||||
'librawaud_plugin.dylib',
|
||||
'librawdv_plugin.dylib',
|
||||
'librawvid_plugin.dylib',
|
||||
'libreal_plugin.dylib',
|
||||
'libsmf_plugin.dylib',
|
||||
'libts_plugin.dylib',
|
||||
'libtta_plugin.dylib',
|
||||
'libty_plugin.dylib',
|
||||
'libvc1_plugin.dylib',
|
||||
'libvoc_plugin.dylib',
|
||||
'libwav_plugin.dylib',
|
||||
'libxa_plugin.dylib',
|
||||
'libfolder_plugin.dylib',
|
||||
'libtaglib_plugin.dylib',
|
||||
'demux/libavi_plugin.dylib',
|
||||
'demux/libdemux_cdg_plugin.dylib',
|
||||
'demux/libdemuxdump_plugin.dylib',
|
||||
'demux/libdiracsys_plugin.dylib',
|
||||
'demux/libes_plugin.dylib',
|
||||
'demux/libflacsys_plugin.dylib',
|
||||
'access/liblive555_plugin.dylib',
|
||||
'demux/libmkv_plugin.dylib',
|
||||
'demux/libmod_plugin.dylib',
|
||||
'demux/libmp4_plugin.dylib',
|
||||
'demux/libmpc_plugin.dylib',
|
||||
'demux/libmpgv_plugin.dylib',
|
||||
'demux/libnsc_plugin.dylib',
|
||||
'demux/libnsv_plugin.dylib',
|
||||
'demux/libnuv_plugin.dylib',
|
||||
'demux/libogg_plugin.dylib',
|
||||
'demux/libplaylist_plugin.dylib',
|
||||
'demux/libps_plugin.dylib',
|
||||
'demux/libpva_plugin.dylib',
|
||||
'demux/librawaud_plugin.dylib',
|
||||
'demux/librawdv_plugin.dylib',
|
||||
'demux/librawvid_plugin.dylib',
|
||||
'demux/libreal_plugin.dylib',
|
||||
'demux/libsmf_plugin.dylib',
|
||||
'demux/libts_plugin.dylib',
|
||||
'demux/libtta_plugin.dylib',
|
||||
'demux/libty_plugin.dylib',
|
||||
'demux/libvc1_plugin.dylib',
|
||||
'demux/libvoc_plugin.dylib',
|
||||
'demux/libwav_plugin.dylib',
|
||||
'demux/libxa_plugin.dylib',
|
||||
'meta_engine/libfolder_plugin.dylib',
|
||||
'meta_engine/libtaglib_plugin.dylib',
|
||||
#'libaudioscrobbler_plugin.dylib',
|
||||
'libdummy_plugin.dylib',
|
||||
'libexport_plugin.dylib',
|
||||
'control/libdummy_plugin.dylib',
|
||||
'misc/libexport_plugin.dylib',
|
||||
#'libfreetype_plugin.dylib',
|
||||
#'libgnutls_plugin.dylib',
|
||||
'liblogger_plugin.dylib',
|
||||
'liblua_plugin.dylib',
|
||||
'misc/liblogger_plugin.dylib',
|
||||
'lua/liblua_plugin.dylib',
|
||||
#'libosd_parser_plugin.dylib',
|
||||
#'libquartztext_plugin.dylib',
|
||||
#'libstats_plugin.dylib',
|
||||
'libvod_rtsp_plugin.dylib',
|
||||
'libxml_plugin.dylib',
|
||||
'misc/libvod_rtsp_plugin.dylib',
|
||||
'misc/libxml_plugin.dylib',
|
||||
#'libxtag_plugin.dylib',
|
||||
'libi420_rgb_mmx_plugin.dylib',
|
||||
'libi420_yuy2_mmx_plugin.dylib',
|
||||
'libi422_yuy2_mmx_plugin.dylib',
|
||||
'video_chroma/libi420_rgb_mmx_plugin.dylib',
|
||||
'video_chroma/libi420_yuy2_mmx_plugin.dylib',
|
||||
'video_chroma/libi422_yuy2_mmx_plugin.dylib',
|
||||
#'libmemcpymmx_plugin.dylib',
|
||||
#'libmemcpymmxext_plugin.dylib',
|
||||
'libmux_asf_plugin.dylib',
|
||||
'libmux_avi_plugin.dylib',
|
||||
'libmux_dummy_plugin.dylib',
|
||||
'libmux_mp4_plugin.dylib',
|
||||
'libmux_mpjpeg_plugin.dylib',
|
||||
'libmux_ogg_plugin.dylib',
|
||||
'libmux_ps_plugin.dylib',
|
||||
'libmux_ts_plugin.dylib',
|
||||
'libmux_wav_plugin.dylib',
|
||||
'libpacketizer_copy_plugin.dylib',
|
||||
'libpacketizer_dirac_plugin.dylib',
|
||||
'libpacketizer_flac_plugin.dylib',
|
||||
'libpacketizer_h264_plugin.dylib',
|
||||
'libpacketizer_mlp_plugin.dylib',
|
||||
'libpacketizer_mpeg4audio_plugin.dylib',
|
||||
'libpacketizer_mpeg4video_plugin.dylib',
|
||||
'libpacketizer_mpegvideo_plugin.dylib',
|
||||
'libpacketizer_vc1_plugin.dylib',
|
||||
'libi420_rgb_sse2_plugin.dylib',
|
||||
'libi420_yuy2_sse2_plugin.dylib',
|
||||
'libi422_yuy2_sse2_plugin.dylib',
|
||||
'libdecomp_plugin.dylib',
|
||||
#'libstream_filter_rar_plugin.dylib',
|
||||
'librecord_plugin.dylib',
|
||||
'mux/libmux_asf_plugin.dylib',
|
||||
'mux/libmux_avi_plugin.dylib',
|
||||
'mux/libmux_dummy_plugin.dylib',
|
||||
'mux/libmux_mp4_plugin.dylib',
|
||||
'mux/libmux_mpjpeg_plugin.dylib',
|
||||
'mux/libmux_ogg_plugin.dylib',
|
||||
'mux/libmux_ps_plugin.dylib',
|
||||
'mux/libmux_ts_plugin.dylib',
|
||||
'mux/libmux_wav_plugin.dylib',
|
||||
'packetizer/libpacketizer_copy_plugin.dylib',
|
||||
'packetizer/libpacketizer_dirac_plugin.dylib',
|
||||
'packetizer/libpacketizer_flac_plugin.dylib',
|
||||
'packetizer/libpacketizer_h264_plugin.dylib',
|
||||
'packetizer/libpacketizer_mlp_plugin.dylib',
|
||||
'packetizer/libpacketizer_mpeg4audio_plugin.dylib',
|
||||
'packetizer/libpacketizer_mpeg4video_plugin.dylib',
|
||||
'packetizer/libpacketizer_mpegvideo_plugin.dylib',
|
||||
'packetizer/libpacketizer_vc1_plugin.dylib',
|
||||
'video_chroma/libi420_rgb_sse2_plugin.dylib',
|
||||
'video_chroma/libi420_yuy2_sse2_plugin.dylib',
|
||||
'video_chroma/libi422_yuy2_sse2_plugin.dylib',
|
||||
'stream_filter/libdecomp_plugin.dylib',
|
||||
#'access/libstream_filter_rar_plugin.dylib',
|
||||
'stream_filter/librecord_plugin.dylib',
|
||||
#'libvisual_plugin.dylib',
|
||||
'libsecuretransport_plugin.dylib'
|
||||
]
|
||||
|
||||
VLC_SEARCH_PATH=[
|
||||
'/usr/local/opt/vlc/lib/vlc/plugins/',
|
||||
'/usr/local/lib/vlc/plugins/',
|
||||
]
|
||||
|
||||
QT_PLUGINS = [
|
||||
@@ -200,39 +201,39 @@ QT_PLUGINS = [
|
||||
]
|
||||
|
||||
SNORE_PLUGINS = [
|
||||
'libsnore_backend_growl.so',
|
||||
'libsnore_backend_osxnotificationcenter.so',
|
||||
# 'libsnore_backend_growl.so',
|
||||
# 'libsnore_backend_osxnotificationcenter.so',
|
||||
]
|
||||
|
||||
TOMAHAWK_PLUGINS = [
|
||||
'lib%s_account_xmpp.dylib' % TARGET_NAME,
|
||||
'lib%s_account_google.so' % TARGET_NAME,
|
||||
'lib%s_account_zeroconf.so' % TARGET_NAME,
|
||||
'lib%s_account_hatchet.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_adium.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_charts.so' % TARGET_NAME,
|
||||
# 'lib%s_infoplugin_discogs.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_echonest.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_hypem.so' % TARGET_NAME,
|
||||
# 'lib%s_infoplugin_musicbrainz.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_musixmatch.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_newreleases.so' % TARGET_NAME,
|
||||
# 'lib%s_infoplugin_rovi.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_snorenotify.so' % TARGET_NAME,
|
||||
'lib%s_infoplugin_spotify.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_dashboard.so' % TARGET_NAME,
|
||||
# 'lib%s_viewpage_networkactivity.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_charts.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_newreleases.so' % TARGET_NAME,
|
||||
'lib%s_viewpage_whatsnew_0_8.so' % TARGET_NAME,
|
||||
'libtomahawk_account_xmpp.dylib',
|
||||
'libtomahawk_account_google.so',
|
||||
'libtomahawk_account_zeroconf.so',
|
||||
# 'libtomahawk_account_hatchet.so',
|
||||
'libtomahawk_infoplugin_adium.so',
|
||||
'libtomahawk_infoplugin_charts.so',
|
||||
'libtomahawk_infoplugin_discogs.so',
|
||||
'libtomahawk_infoplugin_echonest.so',
|
||||
'libtomahawk_infoplugin_hypem.so',
|
||||
'libtomahawk_infoplugin_musicbrainz.so',
|
||||
'libtomahawk_infoplugin_musixmatch.so',
|
||||
'libtomahawk_infoplugin_newreleases.so',
|
||||
'libtomahawk_infoplugin_rovi.so',
|
||||
# 'libtomahawk_infoplugin_snorenotify.so',
|
||||
'libtomahawk_infoplugin_spotify.so',
|
||||
'libtomahawk_viewpage_dashboard.so',
|
||||
# 'libtomahawk_viewpage_networkactivity.so',
|
||||
'libtomahawk_viewpage_charts.so',
|
||||
'libtomahawk_viewpage_newreleases.so',
|
||||
'libtomahawk_viewpage_whatsnew_0_8.so',
|
||||
]
|
||||
|
||||
QT_PLUGINS_SEARCH_PATH=[
|
||||
'/usr/local/opt/qt5/plugins',
|
||||
'/usr/local/Cellar/qt5/5.4.0/plugins',
|
||||
]
|
||||
|
||||
SNORE_PLUGINS_SEARCH_PATH=[
|
||||
'/usr/local/opt/snorenotify/lib/plugins/libsnore-qt5',
|
||||
'/usr/local/Cellar/snorenotify/HEAD/lib/libsnore',
|
||||
]
|
||||
|
||||
class Error(Exception):
|
||||
@@ -246,8 +247,6 @@ class CouldNotFindQtPluginErrorFindFrameworkError(Error):
|
||||
class InstallNameToolError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindFrameworkError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindQtPluginError(Error):
|
||||
pass
|
||||
@@ -309,7 +308,7 @@ def GetBrokenLibraries(binary):
|
||||
continue # unix style system library
|
||||
elif re.match(r'Breakpad', line):
|
||||
continue # Manually added by cmake.
|
||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line) and not re.match(r'^\s*@loader_path/../lib', line):
|
||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line):
|
||||
# Potentially already fixed library
|
||||
if '.framework' in line:
|
||||
relative_path = os.path.join(*line.split('/')[3:])
|
||||
@@ -333,11 +332,6 @@ def FindFramework(path):
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
|
||||
# replace rpath with /Library/Frameworks for Sparkle
|
||||
abs_path = path.replace("@rpath/", "/Library/Frameworks/")
|
||||
if os.path.exists(abs_path):
|
||||
return abs_path
|
||||
|
||||
raise CouldNotFindFrameworkError(path)
|
||||
|
||||
def FindLibrary(path):
|
||||
@@ -582,12 +576,12 @@ for plugin in TOMAHAWK_PLUGINS:
|
||||
FixPlugin(plugin, '../MacOS')
|
||||
|
||||
for plugin in SNORE_PLUGINS:
|
||||
FixPlugin(FindSnorePlugin(plugin), '../lib/plugins/libsnore-qt5')
|
||||
FixPlugin(FindSnorePlugin(plugin), '../MacOS/libsnore')
|
||||
|
||||
try:
|
||||
FixPlugin('%s_crash_reporter' % TARGET_NAME, '../MacOS')
|
||||
FixPlugin('tomahawk_crash_reporter', '../MacOS')
|
||||
except:
|
||||
print 'Failed to find %s_crash_reporter' % TARGET_NAME
|
||||
print 'Failed to find tomahawk_crash_reporter'
|
||||
|
||||
for plugin in QT_PLUGINS:
|
||||
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
@@ -6,9 +6,9 @@ if ARGV.length < 2
|
||||
exit
|
||||
end
|
||||
|
||||
tarball = "#{ARGV[0].downcase}-#{ARGV[1]}.tar.bz2"
|
||||
tarball = "tomahawk-#{ARGV[0]}.tar.bz2"
|
||||
puts "Zipping: #{tarball}..."
|
||||
`tar jcvf "#{tarball}" #{ARGV[0]}.app`
|
||||
`tar jcvf "#{tarball}" Tomahawk.app`
|
||||
|
||||
puts "Signing..."
|
||||
puts `openssl dgst -sha1 -binary < "#{tarball}" | openssl dgst -dss1 -sign "#{ARGV[2]}" | openssl enc -base64`
|
||||
puts `openssl dgst -sha1 -binary < "#{tarball}" | openssl dgst -dss1 -sign "#{ARGV[1]}" | openssl enc -base64`
|
||||
|
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>nav-back</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="nav-back" sketch:type="MSLayerGroup" transform="translate(4.000000, 6.000000)">
|
||||
<g id="Layer_2"></g>
|
||||
<g id="Layer_3"></g>
|
||||
<g id="Layer_4"></g>
|
||||
<g id="Layer_5"></g>
|
||||
<g id="Layer_6"></g>
|
||||
<g id="Layer_8"></g>
|
||||
<g id="Layer_9"></g>
|
||||
<g id="Layer_10"></g>
|
||||
<g id="Layer_11"></g>
|
||||
<g id="Layer_12"></g>
|
||||
<g id="Layer_13"></g>
|
||||
<g id="Layer_14"></g>
|
||||
<g id="Layer_15"></g>
|
||||
<g id="Layer_16"></g>
|
||||
<g id="Layer_17"></g>
|
||||
<g id="Layer_18"></g>
|
||||
<g id="Layer_19"></g>
|
||||
<g id="Layer_20"></g>
|
||||
<g id="Layer_21"></g>
|
||||
<g id="Layer_24"></g>
|
||||
<g id="Layer_25"></g>
|
||||
<g id="Layer_26"></g>
|
||||
<g id="Layer_27"></g>
|
||||
<g id="Layer_28"></g>
|
||||
<g id="Layer_29"></g>
|
||||
<g id="Layer_47"></g>
|
||||
<g id="Layer_30"></g>
|
||||
<g id="Layer_31"></g>
|
||||
<g id="Layer_32"></g>
|
||||
<g id="Layer_33"></g>
|
||||
<g id="Layer_34"></g>
|
||||
<g id="Layer_35"></g>
|
||||
<g id="Layer_36"></g>
|
||||
<g id="Layer_37"></g>
|
||||
<g id="Layer_38" transform="translate(2.000000, 0.000000)" fill="#000000" sketch:type="MSShapeGroup">
|
||||
<path d="M9.7,13.9 L-0.3,7 L9.7,0.1 L10.3,0.9 L1.5,7 L10.3,13.1 L9.7,13.9 Z" id="Shape"></path>
|
||||
</g>
|
||||
<g id="Layer_39"></g>
|
||||
<g id="Layer_40"></g>
|
||||
<g id="Layer_41"></g>
|
||||
<g id="Layer_42"></g>
|
||||
<g id="Layer_43"></g>
|
||||
<g id="Layer_44"></g>
|
||||
<g id="Layer_45"></g>
|
||||
<g id="Layer_46"></g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -1,55 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
|
||||
<title>nav-forward</title>
|
||||
<description>Created with Sketch (http://www.bohemiancoding.com/sketch)</description>
|
||||
<defs></defs>
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
|
||||
<g id="nav-forward" sketch:type="MSLayerGroup" transform="translate(6.000000, 6.000000)">
|
||||
<g id="Layer_2"></g>
|
||||
<g id="Layer_3"></g>
|
||||
<g id="Layer_4"></g>
|
||||
<g id="Layer_5"></g>
|
||||
<g id="Layer_6"></g>
|
||||
<g id="Layer_8"></g>
|
||||
<g id="Layer_9"></g>
|
||||
<g id="Layer_10"></g>
|
||||
<g id="Layer_11"></g>
|
||||
<g id="Layer_12"></g>
|
||||
<g id="Layer_13"></g>
|
||||
<g id="Layer_14"></g>
|
||||
<g id="Layer_15"></g>
|
||||
<g id="Layer_16"></g>
|
||||
<g id="Layer_17"></g>
|
||||
<g id="Layer_18"></g>
|
||||
<g id="Layer_19"></g>
|
||||
<g id="Layer_20"></g>
|
||||
<g id="Layer_21"></g>
|
||||
<g id="Layer_24"></g>
|
||||
<g id="Layer_25"></g>
|
||||
<g id="Layer_26"></g>
|
||||
<g id="Layer_27"></g>
|
||||
<g id="Layer_28"></g>
|
||||
<g id="Layer_29"></g>
|
||||
<g id="Layer_47"></g>
|
||||
<g id="Layer_30"></g>
|
||||
<g id="Layer_31"></g>
|
||||
<g id="Layer_32"></g>
|
||||
<g id="Layer_33"></g>
|
||||
<g id="Layer_34"></g>
|
||||
<g id="Layer_35"></g>
|
||||
<g id="Layer_36"></g>
|
||||
<g id="Layer_37"></g>
|
||||
<g id="Layer_38"></g>
|
||||
<g id="Layer_39"></g>
|
||||
<g id="Layer_40"></g>
|
||||
<g id="Layer_41" transform="translate(2.000000, 0.000000)" fill="#000000" sketch:type="MSShapeGroup">
|
||||
<path d="M0.5,13.7 L-0.1,12.9 L8.3,7 L-0.1,1.1 L0.5,0.3 L10.1,7 L0.5,13.7 Z" id="Shape"></path>
|
||||
</g>
|
||||
<g id="Layer_42"></g>
|
||||
<g id="Layer_43"></g>
|
||||
<g id="Layer_44"></g>
|
||||
<g id="Layer_45"></g>
|
||||
<g id="Layer_46"></g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 2.2 KiB |
@@ -102,7 +102,7 @@ Tomahawk.InfoSystem.InfoPlugin = {
|
||||
notInCache: function (infoType, criteria) {
|
||||
var requestMethod = 'request' + this.infoTypeString(infoType);
|
||||
|
||||
return RSVP.Promise.resolve(this[requestMethod](criteria));
|
||||
return Promise.resolve(this[requestMethod](criteria));
|
||||
},
|
||||
pushInfo: function (pushData) {
|
||||
var pushMethod = 'push' + this.infoTypeString(pushData.type);
|
||||
@@ -114,6 +114,6 @@ Tomahawk.InfoSystem.InfoPlugin = {
|
||||
getInfo: function (type, infoHash) {
|
||||
var getInfoMethod = 'get' + this.infoTypeString(type);
|
||||
|
||||
return RSVP.Promise.resolve(this[getInfoMethod](infoHash));
|
||||
return Promise.resolve(this[getInfoMethod](infoHash));
|
||||
}
|
||||
};
|
||||
|
@@ -39,101 +39,7 @@ if ((typeof Tomahawk === "undefined") || (Tomahawk === null)) {
|
||||
|
||||
Tomahawk.apiVersion = "0.2.2";
|
||||
|
||||
//Statuses considered a success for HTTP request
|
||||
var httpSuccessStatuses = [200, 201];
|
||||
|
||||
// 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) {
|
||||
console.error(resolverName + 'Uncaught error:', reason);
|
||||
} else {
|
||||
console.error(resolverName + 'Uncaught error: error thrown from RSVP but it was empty');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Compares versions strings
|
||||
* (version1 < version2) == -1
|
||||
* (version1 = version2) == 0
|
||||
* (version1 > version2) == 1
|
||||
*/
|
||||
Tomahawk.versionCompare = function (version1, version2) {
|
||||
var v1 = version1.split('.').map(function (item) {
|
||||
return parseInt(item);
|
||||
});
|
||||
var v2 = version2.split('.').map(function (item) {
|
||||
return parseInt(item);
|
||||
});
|
||||
var length = Math.max(v1.length, v2.length);
|
||||
var i = 0;
|
||||
|
||||
for (; i < length; i++) {
|
||||
if (typeof v1[i] == "undefined" || v1[i] === null) {
|
||||
if (typeof v2[i] == "undefined" || v2[i] === null) {
|
||||
// v1 == v2
|
||||
return 0;
|
||||
} else if (v2[i] === 0) {
|
||||
continue;
|
||||
} else {
|
||||
// v1 < v2
|
||||
return -1;
|
||||
}
|
||||
} else if (typeof v2[i] == "undefined" || v2[i] === null) {
|
||||
if (v1[i] === 0) {
|
||||
continue;
|
||||
} else {
|
||||
// v1 > v2
|
||||
return 1;
|
||||
}
|
||||
} else if (v2[i] > v1[i]) {
|
||||
// v1 < v2
|
||||
return -1;
|
||||
} else if (v2[i] < v1[i]) {
|
||||
// v1 > v2
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// v1 == v2
|
||||
return 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this is at least specified tomahawk-api-version.
|
||||
*/
|
||||
Tomahawk.atLeastVersion = function (version) {
|
||||
return (Tomahawk.versionCompare(Tomahawk.apiVersion, version) >= 0);
|
||||
};
|
||||
|
||||
Tomahawk.resolver = {
|
||||
scriptPath: Tomahawk.resolverData().scriptPath
|
||||
};
|
||||
|
||||
Tomahawk.timestamp = function () {
|
||||
return Math.round(new Date() / 1000);
|
||||
};
|
||||
|
||||
Tomahawk.htmlDecode = (function () {
|
||||
// this prevents any overhead from creating the object each time
|
||||
var element = document.createElement('textarea');
|
||||
|
||||
function decodeHTMLEntities(str) {
|
||||
if (str && typeof str === 'string') {
|
||||
str = str.replace(/</g, "<");
|
||||
str = str.replace(/>/g, ">");
|
||||
element.innerHTML = str;
|
||||
str = element.textContent;
|
||||
element.textContent = '';
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
return decodeHTMLEntities;
|
||||
})();
|
||||
|
||||
Tomahawk.dumpResult = function (result) {
|
||||
var results = result.results;
|
||||
@@ -145,168 +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;
|
||||
},
|
||||
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 () {
|
||||
return {result: Tomahawk.ConfigTestResultType.Success};
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// help functions
|
||||
|
||||
Tomahawk.valueForSubNode = function (node, tag) {
|
||||
@@ -322,6 +66,7 @@ Tomahawk.valueForSubNode = function (node, tag) {
|
||||
return element.textContent;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Internal counter used to identify retrievedMetadata call back from native
|
||||
* code.
|
||||
@@ -419,174 +164,6 @@ Tomahawk.nativeAsyncRequestDone = function (reqId, xhr) {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
var shouldDoNativeRequest = function (options) {
|
||||
var extraHeaders = options.headers;
|
||||
return (extraHeaders && (extraHeaders.hasOwnProperty("Referer")
|
||||
|| extraHeaders.hasOwnProperty("referer")
|
||||
|| extraHeaders.hasOwnProperty("User-Agent")));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Possible options:
|
||||
* - 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
|
||||
*/
|
||||
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) {
|
||||
return this.responseHeaders[header];
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
});
|
||||
};
|
||||
|
||||
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);
|
||||
};
|
||||
@@ -602,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;
|
||||
@@ -745,115 +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;
|
||||
}
|
||||
|
||||
|
||||
var pluginManager = this;
|
||||
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) {
|
||||
Tomahawk.reportScriptJobResults({
|
||||
requestId: requestId,
|
||||
data: result
|
||||
});
|
||||
}, function (error) {
|
||||
Tomahawk.reportScriptJobResults({
|
||||
requestId: requestId,
|
||||
error: error
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
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,
|
||||
@@ -1508,10 +873,6 @@ Tomahawk.Collection = {
|
||||
});
|
||||
},
|
||||
|
||||
revision: function (params) {
|
||||
return RSVP.resolve();
|
||||
},
|
||||
|
||||
_fuzzyIndexIdsToTracks: function (resultIds, id) {
|
||||
if (typeof id === 'undefined') {
|
||||
id = this.settings.id;
|
||||
@@ -1563,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);
|
||||
@@ -1578,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) {
|
||||
@@ -1627,7 +975,7 @@ Tomahawk.Collection = {
|
||||
);
|
||||
return t.execDeferredStatements();
|
||||
}).then(function (results) {
|
||||
return {tracks: results[0]};
|
||||
return {results: resolverInstance._convertUrls(results[0])};
|
||||
});
|
||||
},
|
||||
|
||||
@@ -1801,13 +1149,73 @@ Tomahawk.Collection = {
|
||||
Tomahawk.Collection.BrowseCapability.Albums,
|
||||
Tomahawk.Collection.BrowseCapability.Tracks];
|
||||
return this.settings;
|
||||
},
|
||||
|
||||
getStreamUrl: function(params) {
|
||||
if(this.resolver) {
|
||||
return this.resolver.getStreamUrl(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
|
||||
|
@@ -167,7 +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>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@@ -69,13 +69,6 @@ Tomahawk::InfoSystem::XmppInfoPlugin::init()
|
||||
}
|
||||
|
||||
|
||||
const QString
|
||||
Tomahawk::InfoSystem::XmppInfoPlugin::friendlyName() const
|
||||
{
|
||||
return "xmpp";
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Tomahawk::InfoSystem::XmppInfoPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
{
|
||||
|
@@ -38,8 +38,6 @@ namespace Tomahawk {
|
||||
XmppInfoPlugin(XmppSipPlugin* parent);
|
||||
virtual ~XmppInfoPlugin();
|
||||
|
||||
const QString friendlyName() const override;
|
||||
|
||||
signals:
|
||||
void publishTune( QUrl url, Tomahawk::InfoSystem::InfoStringHash trackInfo );
|
||||
|
||||
|
@@ -194,9 +194,9 @@ InfoSystem::InfoPluginPtr
|
||||
XmppSipPlugin::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
m_infoPlugin = QSharedPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
|
||||
m_infoPlugin = QPointer< Tomahawk::InfoSystem::XmppInfoPlugin >( new Tomahawk::InfoSystem::XmppInfoPlugin( this ) );
|
||||
|
||||
return m_infoPlugin;
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
@@ -285,7 +285,7 @@ XmppSipPlugin::onConnect()
|
||||
// load XmppInfoPlugin
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
@@ -359,6 +359,7 @@ XmppSipPlugin::onDisconnect( Jreen::Client::DisconnectReason reason )
|
||||
if ( !m_infoPlugin.isNull() )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
delete m_infoPlugin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -128,7 +128,7 @@ private:
|
||||
int m_currentPort;
|
||||
QString m_currentResource;
|
||||
|
||||
QSharedPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_infoPlugin;
|
||||
QPointer< Tomahawk::InfoSystem::XmppInfoPlugin > m_infoPlugin;
|
||||
Tomahawk::Accounts::Account::ConnectionState m_state;
|
||||
|
||||
// sort out
|
||||
|
@@ -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 );
|
||||
|
@@ -3,15 +3,17 @@ include_directories(
|
||||
${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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2013-2015, Hannah von Reth <vonreth@kde.org>
|
||||
* Copyright 2013-2014, Patrick von Reth <vonreth@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2012, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
*
|
||||
@@ -27,15 +27,27 @@
|
||||
|
||||
#include "TomahawkVersion.h"
|
||||
|
||||
#include <libsnore/application.h>
|
||||
#include <libsnore/notification/icon.h>
|
||||
#include <snore/core/application.h>
|
||||
#include <snore/core/notification/icon.h>
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
namespace Qt
|
||||
{
|
||||
inline QString escape( const QString &x )
|
||||
{
|
||||
return x.toHtmlEscaped();
|
||||
}
|
||||
}
|
||||
#else
|
||||
// QTextDocument provides Qt::escape()
|
||||
#include <QTextDocument>
|
||||
#endif
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
@@ -49,13 +61,27 @@ SnoreNotifyPlugin::SnoreNotifyPlugin()
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
m_supportedPushTypes << InfoNotifyUser << InfoNowPlaying << InfoTrackUnresolved << InfoNowStopped << InfoInboxReceived;
|
||||
|
||||
Snore::SnoreCore &snore = Snore::SnoreCore::instance();
|
||||
snore.loadPlugins( Snore::SnorePlugin::Backend | Snore::SnorePlugin::SecondaryBackend );
|
||||
snore.setDefaultSettingsValue("Silent", true, Snore::LocalSetting );
|
||||
m_snore = new Snore::SnoreCore();
|
||||
m_snore->loadPlugins( Snore::SnorePlugin::BACKEND );
|
||||
QString backend = qgetenv( "SNORE_BACKEND" ).constData();
|
||||
|
||||
if( backend.isEmpty() )
|
||||
{
|
||||
m_snore->setPrimaryNotificationBackend();
|
||||
}
|
||||
else
|
||||
{
|
||||
if( !m_snore->setPrimaryNotificationBackend( backend ) )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "Ivalid or unavailible Snore backend: " << backend << " availible backens: " << m_snore->notificationBackends();
|
||||
m_snore->setPrimaryNotificationBackend();
|
||||
}
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << m_snore->primaryNotificationBackend();
|
||||
|
||||
m_application = Snore::Application( qApp->applicationName(), m_defaultIcon );
|
||||
m_application.hints().setValue( "use-markup", true );
|
||||
m_application.hints().setValue( "windows-app-id", TOMAHAWK_APPLICATION_PACKAGE_NAME );
|
||||
m_application.hints().setValue( "windows_app_id", TOMAHAWK_APPLICATION_PACKAGE_NAME );
|
||||
m_application.hints().setValue( "desktop-entry", TOMAHAWK_APPLICATION_NAME );
|
||||
|
||||
addAlert( InfoNotifyUser, tr( "Notify User" ) );
|
||||
@@ -64,10 +90,9 @@ SnoreNotifyPlugin::SnoreNotifyPlugin()
|
||||
addAlert( InfoNowStopped, tr( "Playback Stopped" ) );
|
||||
addAlert( InfoInboxReceived, tr( "You received a Song recommendation" ) );
|
||||
|
||||
snore.registerApplication( m_application );
|
||||
snore.setDefaultApplication( m_application );
|
||||
m_snore->registerApplication( m_application );
|
||||
|
||||
connect( &snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
connect( m_snore, SIGNAL( actionInvoked( Snore::Notification ) ), this, SLOT( slotActionInvoked( Snore::Notification ) ) );
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +100,8 @@ SnoreNotifyPlugin::~SnoreNotifyPlugin()
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO;
|
||||
|
||||
Snore::SnoreCore::instance().deregisterApplication( m_application );
|
||||
m_snore->deregisterApplication( m_application );
|
||||
m_snore->deleteLater();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -85,19 +111,25 @@ SnoreNotifyPlugin::pushInfo( Tomahawk::InfoSystem::InfoPushData pushData )
|
||||
if ( !TomahawkSettings::instance()->songChangeNotificationEnabled() )
|
||||
return;
|
||||
|
||||
if( m_snore->primaryNotificationBackend().isNull() )
|
||||
{
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "no notification backend set";
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
switch ( pushData.type )
|
||||
{
|
||||
case Tomahawk::InfoSystem::InfoTrackUnresolved:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoTrackUnresolved, tr( "The current track could not be resolved. %applicationName will pick back up with the next resolvable track from this source." ), m_defaultIcon );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoTrackUnresolved, tr( "The current track could not be resolved. %applicationName will pick back up with the next resolvable track from this source." ) );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNotifyUser:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNotifyUser,pushData.infoPair.second.toString(), m_defaultIcon );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNotifyUser,pushData.infoPair.second.toString() );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowStopped:
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNowStopped, tr( "%applicationName stopped playback." ), m_defaultIcon );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoNowStopped, tr( "%applicationName stopped playback." ) );
|
||||
return;
|
||||
|
||||
case Tomahawk::InfoSystem::InfoNowPlaying:
|
||||
@@ -125,10 +157,15 @@ SnoreNotifyPlugin::slotActionInvoked( Snore::Notification n )
|
||||
void
|
||||
SnoreNotifyPlugin::notifyUser( Tomahawk::InfoSystem::InfoType type, const QString& messageText, Snore::Icon icon )
|
||||
{
|
||||
if(!icon.isValid())
|
||||
{
|
||||
icon = m_defaultIcon;
|
||||
}
|
||||
const Snore::Alert &alert = m_alerts[ type ];
|
||||
Snore::Notification n( m_application , alert, alert.name(), messageText, icon );
|
||||
Snore::SnoreCore::instance().broadcastNotification( n );
|
||||
m_snore->broadcastNotification( n );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "showing notification:" << messageText;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
@@ -157,28 +194,41 @@ SnoreNotifyPlugin::nowPlaying( const QVariant& input )
|
||||
|
||||
QString messageText;
|
||||
// If the window manager supports notification styling then use it.
|
||||
if ( m_snore->primaryBackendSupportsRichtext() )
|
||||
{
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( "<br><i>%1</i> %2" ).arg( tr( "on", "'on' is followed by an album name" ) ).arg( Qt::escape( hash[ "album" ] ) );
|
||||
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( "<br><i>%1</i> %2" ).arg( tr( "on", "'on' is followed by an album name" ) ).arg( hash[ "album" ].toHtmlEscaped() );
|
||||
messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( Qt::escape( hash[ "title" ] ) )
|
||||
.arg( Qt::escape( hash[ "artist" ] ) )
|
||||
.arg( album )
|
||||
.arg( QString( "<br><i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
|
||||
messageText = tr( "%1%4 %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( hash[ "title" ].toHtmlEscaped() )
|
||||
.arg( hash[ "artist" ].toHtmlEscaped() )
|
||||
.arg( album )
|
||||
.arg( QString( "<br><i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
}
|
||||
else
|
||||
{
|
||||
QString album;
|
||||
if ( !hash[ "album" ].isEmpty() )
|
||||
album = QString( " %1" ).arg( tr( "on \"%1\"", "%1 is an album name" ).arg( hash[ "album" ] ) );
|
||||
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
messageText = tr( "\"%1\" by %2%3.", "%1 is a title, %2 is an artist and %3 is replaced by either the previous message or nothing" )
|
||||
.arg( hash[ "title" ] )
|
||||
.arg( hash[ "artist" ] )
|
||||
.arg( album );
|
||||
}
|
||||
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << "sending message" << messageText;
|
||||
|
||||
// If there is a cover availble use it, else use Tomahawk logo as default.
|
||||
Snore::Icon image = m_defaultIcon;
|
||||
Snore::Icon image;
|
||||
if ( map.contains( "cover" ) && map[ "cover" ].canConvert< QImage >() )
|
||||
{
|
||||
image = Snore::Icon( QPixmap::fromImage( map[ "cover" ].value< QImage >() ) );
|
||||
image = Snore::Icon( map[ "cover" ].value< QImage >() );
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << image;
|
||||
}
|
||||
notifyUser( InfoNowPlaying, messageText, image );
|
||||
@@ -209,15 +259,26 @@ SnoreNotifyPlugin::inboxReceived( const QVariant& input )
|
||||
return;
|
||||
|
||||
QString messageText;
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( src["friendlyname"].toHtmlEscaped() )
|
||||
.arg( hash[ "title" ].toHtmlEscaped() )
|
||||
.arg( hash[ "artist" ].toHtmlEscaped() )
|
||||
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
// If the window manager supports notification styling then use it.
|
||||
if ( m_snore->primaryBackendSupportsRichtext() )
|
||||
{
|
||||
// Remark: If using xml-based markup in notifications, the supplied strings need to be escaped.
|
||||
messageText = tr( "%1 sent you\n%2%4 %3.", "%1 is a nickname, %2 is a title, %3 is an artist, %4 is the preposition used to link track and artist ('by' in english)" )
|
||||
.arg( Qt::escape( src["friendlyname"] ) )
|
||||
.arg( Qt::escape( hash[ "title" ] ) )
|
||||
.arg( Qt::escape( hash[ "artist" ] ) )
|
||||
.arg( QString( "\n<i>%1</i>" ).arg( tr( "by", "preposition to link track and artist" ) ) );
|
||||
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
// Dirty hack(TM) so that KNotify/QLabel recognizes the message as Rich Text
|
||||
messageText = QString( "<i></i>%1" ).arg( messageText );
|
||||
}
|
||||
else
|
||||
{
|
||||
messageText = tr( "%1 sent you \"%2\" by %3.", "%1 is a nickname, %2 is a title, %3 is an artist" )
|
||||
.arg( src["friendlyname"] )
|
||||
.arg( hash[ "title" ] )
|
||||
.arg( hash[ "artist" ] );
|
||||
}
|
||||
|
||||
Snore::Icon icon( RESPATH "images/inbox-512x512.png" );
|
||||
notifyUser( Tomahawk::InfoSystem::InfoInboxReceived, messageText, icon );
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2013-2015, Hannah von Reth <vonreth@kde.org>
|
||||
* Copyright 2013-2014, Patrick von Reth <vonreth@kde.org>
|
||||
* Copyright 2010-2011, Christian Muehlhaeuser <muesli@tomahawk-player.org>
|
||||
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
|
||||
*
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "../../InfoPluginDllMacro.h"
|
||||
|
||||
#include "infosystem/InfoSystem.h"
|
||||
#include <libsnore/snore.h>
|
||||
#include <snore/core/snore.h>
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@@ -63,8 +63,9 @@ protected slots:
|
||||
void slotActionInvoked(Snore::Notification n);
|
||||
|
||||
private:
|
||||
void notifyUser( InfoType type, const QString &messageText, Snore::Icon icon );
|
||||
void notifyUser( InfoType type, const QString &messageText, Snore::Icon icon = Snore::Icon() );
|
||||
void addAlert( Tomahawk::InfoSystem::InfoType type, const QString &title );
|
||||
Snore::SnoreCore *m_snore;
|
||||
Snore::Application m_application;
|
||||
Snore::Icon m_defaultIcon;
|
||||
QHash< Tomahawk::InfoSystem::InfoType, Snore::Alert > m_alerts;
|
||||
|
@@ -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 );
|
||||
|
@@ -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;
|
||||
@@ -149,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 );
|
||||
|
@@ -67,7 +67,7 @@ AtticaManager::AtticaManager( QObject* parent )
|
||||
connect( &m_manager, SIGNAL( providerAdded( Attica::Provider ) ), this, SLOT( providerAdded( Attica::Provider ) ) );
|
||||
|
||||
// resolvers
|
||||
// m_manager.addProviderFile( QUrl( "http://v09.bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
// m_manager.addProviderFile( QUrl( "http://bakery.tomahawk-player.org/resolvers/providers.xml" ) );
|
||||
|
||||
const QString url = QString( "%1/resolvers/providers.xml?version=%2" ).arg( hostname() ).arg( TomahawkUtils::appFriendlyVersion() );
|
||||
QNetworkReply* reply = Tomahawk::Utils::nam()->get( QNetworkRequest( QUrl( url ) ) );
|
||||
|
@@ -37,7 +37,6 @@ set( libGuiSources
|
||||
jobview/ErrorStatusMessage.cpp
|
||||
jobview/IndexingJobItem.cpp
|
||||
jobview/InboxJobItem.cpp
|
||||
jobview/ScriptErrorStatusMessage.cpp
|
||||
|
||||
playlist/InboxModel.cpp
|
||||
playlist/InboxView.cpp
|
||||
@@ -200,6 +199,7 @@ list(APPEND libSources
|
||||
MetaPlaylistInterface.cpp
|
||||
Query.cpp
|
||||
Result.cpp
|
||||
ResultProvider.cpp
|
||||
Source.cpp
|
||||
Track.cpp
|
||||
TrackData.cpp
|
||||
@@ -501,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}
|
||||
)
|
||||
|
||||
|
||||
@@ -524,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}
|
||||
|
@@ -217,7 +217,7 @@ DownloadJob::download()
|
||||
arguments[ "url" ] = m_format.url;
|
||||
|
||||
// HACK: *shrug* WIP.
|
||||
Tomahawk::ScriptJob* job = collection->scriptObject()->invoke( "getStreamUrl", arguments );
|
||||
Tomahawk::ScriptJob* job = collection->scriptObject()->invoke( "getStreamUrlPromise", arguments );
|
||||
connect( job, SIGNAL( done(QVariantMap) ), SLOT( onUrlRetrieved(QVariantMap) ) );
|
||||
job->start();
|
||||
}
|
||||
|
@@ -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> ) ) );
|
||||
|
@@ -167,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;
|
||||
|
@@ -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();
|
||||
@@ -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() ) )
|
||||
{
|
||||
|
@@ -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 );
|
||||
|
||||
|
@@ -403,17 +403,12 @@ Query::resultSorter( const result_ptr& left, const result_ptr& right )
|
||||
{
|
||||
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() )
|
||||
@@ -641,11 +636,6 @@ Query::howSimilar( const Tomahawk::result_ptr& r )
|
||||
qTrackname = queryTrack()->trackSortname();
|
||||
}
|
||||
|
||||
//Cleanup symbols for minor naming differences
|
||||
qArtistname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
|
||||
qTrackname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
|
||||
qAlbumname.remove(QRegExp(QString::fromUtf8("[-`~!@#$%^&*()_—+=|:;<>«»,.?/{}\'\"\\[\\]\\\\]")));
|
||||
|
||||
// normal edit distance
|
||||
const int artdist = TomahawkUtils::levenshtein( qArtistname, rArtistname );
|
||||
const int trkdist = TomahawkUtils::levenshtein( qTrackname, rTrackname );
|
||||
|
@@ -491,7 +491,7 @@ Result::setFileId( unsigned int id )
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::Resolver*
|
||||
Tomahawk::ResultProvider*
|
||||
Result::resolvedBy() const
|
||||
{
|
||||
if ( !m_collection.isNull() )
|
||||
@@ -529,23 +529,12 @@ Result::track() const
|
||||
}
|
||||
|
||||
|
||||
QList< DownloadFormat >
|
||||
Result::downloadFormats() const
|
||||
{
|
||||
QMutexLocker lock( &s_mutex );
|
||||
|
||||
return m_formats;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Result::setDownloadFormats( const QList<DownloadFormat>& formats )
|
||||
{
|
||||
if ( formats.isEmpty() )
|
||||
return;
|
||||
|
||||
QMutexLocker lock( &s_mutex );
|
||||
|
||||
m_formats.clear();
|
||||
foreach ( const DownloadFormat& format, formats )
|
||||
{
|
||||
@@ -573,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();
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#ifndef RESULT_H
|
||||
#define RESULT_H
|
||||
|
||||
#include "ResultProvider.h"
|
||||
#include "DownloadJob.h"
|
||||
#include "utils/TomahawkUtils.h"
|
||||
#include "Typedefs.h"
|
||||
@@ -85,9 +86,9 @@ 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;
|
||||
@@ -131,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; }
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
@@ -15,23 +15,10 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "ResultProvider.h"
|
||||
|
||||
#include "ScriptErrorStatusMessage.h"
|
||||
#include "../utils/Logger.h"
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptErrorStatusMessage::ScriptErrorStatusMessage( const QString& message, Tomahawk::ScriptAccount* account )
|
||||
: ErrorStatusMessage( tr( "Script Error: %1" ).arg( message ) )
|
||||
, m_account( account )
|
||||
ResultProvider::~ResultProvider()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
ScriptErrorStatusMessage::activated()
|
||||
{
|
||||
if ( m_account.isNull() )
|
||||
return;
|
||||
|
||||
tDebug() << "ScriptErrorStatusMessage clicked: " << mainText() << m_account->name();
|
||||
m_account->showDebugger();
|
||||
}
|
||||
|
@@ -1,10 +1,10 @@
|
||||
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
|
||||
*
|
||||
* Copyright 2016, Dominik Schmidt <domme@tomahawk-player.org>
|
||||
* Copyright (C) 2015 Dominik Schmidt <domme@tomahawk-player.org>
|
||||
*
|
||||
* Tomahawk is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* the Free Software Foundation, either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Tomahawk is distributed in the hope that it will be useful,
|
||||
@@ -15,25 +15,28 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef SCRIPTERRORSTATUSMESSAGE_H
|
||||
#define SCRIPTERRORSTATUSMESSAGE_H
|
||||
|
||||
#include "ErrorStatusMessage.h"
|
||||
#include "../resolvers/ScriptAccount.h"
|
||||
#pragma once
|
||||
#ifndef TOMAHAWK_RESULTPROVIDER_H
|
||||
#define TOMAHAWK_RESULTPROVIDER_H
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class DLLEXPORT ScriptErrorStatusMessage : public ErrorStatusMessage
|
||||
class QPixmap;
|
||||
class QString;
|
||||
class QSize;
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT ResultProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScriptErrorStatusMessage( const QString& scriptErrorMessage, Tomahawk::ScriptAccount* );
|
||||
virtual ~ResultProvider();
|
||||
|
||||
void activated() override;
|
||||
|
||||
private:
|
||||
QPointer< Tomahawk::ScriptAccount > m_account;
|
||||
virtual QString name() const = 0;
|
||||
virtual QPixmap icon( const QSize& size ) const = 0;
|
||||
};
|
||||
|
||||
#endif // SCRIPTERRORSTATUSMESSAGE_H
|
||||
}
|
||||
|
||||
#endif // TOMAHAWK_RESULTPROVIDER_H
|
@@ -253,7 +253,7 @@ namespace Tomahawk
|
||||
typedef QHash< QString, QString > InfoStringHash;
|
||||
typedef QPair< QVariantMap, QVariant > PushInfoPair;
|
||||
|
||||
typedef QSharedPointer< InfoPlugin > InfoPluginPtr;
|
||||
typedef QPointer< InfoPlugin > InfoPluginPtr;
|
||||
}
|
||||
|
||||
namespace Network
|
||||
|
@@ -76,8 +76,6 @@ public:
|
||||
*/
|
||||
virtual bool addPageItem() const;
|
||||
|
||||
virtual bool isRemovable() const { return false; }
|
||||
|
||||
/**
|
||||
* This page is actually a constant page that will be shown on every
|
||||
* restart of Tomahawk until the user selects it to be removed.
|
||||
|
@@ -517,15 +517,14 @@ 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 );
|
||||
ScriptJob* job = resolver->scriptObject()->invoke( "_testConfig", data );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onTestConfig( QVariantMap ) ) );
|
||||
job->start();
|
||||
}
|
||||
@@ -536,13 +535,6 @@ ResolverAccount::testConfig()
|
||||
}
|
||||
|
||||
|
||||
ExternalResolverGui*
|
||||
ResolverAccount::resolver() const
|
||||
{
|
||||
return m_resolver;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ResolverAccount::onTestConfig( const QVariantMap& result )
|
||||
{
|
||||
|
@@ -101,8 +101,6 @@ public:
|
||||
|
||||
void testConfig() override;
|
||||
|
||||
ExternalResolverGui* resolver() const;
|
||||
|
||||
private slots:
|
||||
void resolverChanged();
|
||||
void onTestConfig( const QVariantMap& result );
|
||||
|
@@ -71,7 +71,7 @@ LastFmAccount::LastFmAccount( const QString& accountId )
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
}
|
||||
@@ -82,6 +82,7 @@ LastFmAccount::~LastFmAccount()
|
||||
if ( m_infoPlugin )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
delete m_infoPlugin;
|
||||
}
|
||||
|
||||
delete m_resolver.data();
|
||||
@@ -167,11 +168,9 @@ InfoPluginPtr
|
||||
LastFmAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QSharedPointer< LastFmInfoPlugin>( new LastFmInfoPlugin( this ) );
|
||||
}
|
||||
m_infoPlugin = QPointer< LastFmInfoPlugin >( new LastFmInfoPlugin( this ) );
|
||||
|
||||
return m_infoPlugin;
|
||||
return InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
bool
|
||||
|
@@ -105,7 +105,7 @@ private:
|
||||
void hookupResolver();
|
||||
|
||||
QPointer<Tomahawk::ExternalResolverGui> m_resolver;
|
||||
QSharedPointer<Tomahawk::InfoSystem::LastFmInfoPlugin> m_infoPlugin;
|
||||
QPointer<Tomahawk::InfoSystem::LastFmInfoPlugin> m_infoPlugin;
|
||||
QPointer<LastFmConfig> m_configWidget;
|
||||
};
|
||||
|
||||
|
@@ -65,6 +65,13 @@ LastFmInfoPlugin::init()
|
||||
return;
|
||||
}
|
||||
|
||||
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
||||
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
||||
lastfm::ws::Username = m_account.data()->username();
|
||||
lastfm::setNetworkAccessManager( Tomahawk::Utils::nam() );
|
||||
|
||||
m_pw = m_account.data()->password();
|
||||
|
||||
//HACK work around a bug in liblastfm---it doesn't create its config dir, so when it
|
||||
// tries to write the track cache, it fails silently. until we have a fixed version, do this
|
||||
// code taken from Amarok (src/services/lastfm/ScrobblerAdapter.cpp)
|
||||
@@ -79,17 +86,6 @@ LastFmInfoPlugin::init()
|
||||
|
||||
m_badUrls << QUrl( "http://cdn.last.fm/flatness/catalogue/noimage" );
|
||||
|
||||
|
||||
lastfm::ws::ApiKey = "7194b85b6d1f424fe1668173a78c0c4a";
|
||||
lastfm::ws::SharedSecret = "ba80f1df6d27ae63e9cb1d33ccf2052f";
|
||||
lastfm::setNetworkAccessManager( Tomahawk::Utils::nam() );
|
||||
|
||||
if ( !m_account.isNull() )
|
||||
{
|
||||
lastfm::ws::Username = m_account->username();
|
||||
m_pw = m_account->password();
|
||||
}
|
||||
|
||||
QTimer::singleShot( 0, this, SLOT( settingsChanged() ) );
|
||||
}
|
||||
|
||||
|
@@ -116,12 +116,6 @@ SpotifyAccount::~SpotifyAccount()
|
||||
{
|
||||
clearUser();
|
||||
|
||||
if ( m_infoPlugin )
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
|
||||
if ( m_spotifyResolver.isNull() )
|
||||
return;
|
||||
|
||||
@@ -141,7 +135,7 @@ SpotifyAccount::init()
|
||||
|
||||
if ( infoPlugin() && Tomahawk::InfoSystem::InfoSystem::instance()->workerThread() )
|
||||
{
|
||||
infoPlugin()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
infoPlugin().data()->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin() );
|
||||
}
|
||||
|
||||
@@ -372,10 +366,10 @@ SpotifyAccount::infoPlugin()
|
||||
{
|
||||
if ( m_infoPlugin.isNull() )
|
||||
{
|
||||
m_infoPlugin = QSharedPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
m_infoPlugin = QPointer< InfoSystem::SpotifyInfoPlugin >( new InfoSystem::SpotifyInfoPlugin( this ) );
|
||||
}
|
||||
|
||||
return m_infoPlugin;
|
||||
return InfoSystem::InfoPluginPtr( m_infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -170,7 +170,7 @@ private:
|
||||
QPointer<SpotifyAccountConfig> m_configWidget;
|
||||
QPointer<QWidget> m_aboutWidget;
|
||||
QPointer<ScriptResolver> m_spotifyResolver;
|
||||
QSharedPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
QPointer< InfoSystem::SpotifyInfoPlugin > m_infoPlugin;
|
||||
|
||||
QMap<QString, QPair<QObject*, QString> > m_qidToSlotMap;
|
||||
QMap<QString, QVariant > m_qidToExtraData;
|
||||
|
@@ -277,7 +277,7 @@ SpotifyAccountConfig::showLoggedIn()
|
||||
m_ui->verticalLayout->insertWidget( 1, m_loggedInUser, 0, Qt::AlignCenter );
|
||||
}
|
||||
|
||||
qDebug() << "Showing logged in with username:" << m_verifiedUsername;
|
||||
qDebug() << "Showing logged in withuserame:" << m_verifiedUsername;
|
||||
m_loggedInUser->show();
|
||||
m_loggedInUser->setText( tr( "Logged in as %1" ).arg( m_verifiedUsername ) );
|
||||
|
||||
|
@@ -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>
|
||||
|
||||
@@ -577,64 +574,16 @@ AudioEngine::loadTrack( const Tomahawk::result_ptr& result )
|
||||
|
||||
setCurrentTrack( result );
|
||||
|
||||
ScriptJob* job = result->resolvedBy()->getStreamUrl( result );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( gotStreamUrl( QVariantMap ) ) );
|
||||
job->setProperty( "result", QVariant::fromValue( 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>();
|
||||
|
||||
if ( streamUrl.isEmpty() || !( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) || TomahawkUtils::isRtmpResult( streamUrl ) ) )
|
||||
if ( !TomahawkUtils::isLocalResult( d->currentTrack->url() ) && !TomahawkUtils::isHttpResult( d->currentTrack->url() )
|
||||
&& !TomahawkUtils::isRtmpResult( d->currentTrack->url() ) )
|
||||
{
|
||||
// Not an http(s) or RTMP URL, get IO device
|
||||
QSharedPointer< QIODevice > sp;
|
||||
performLoadIODevice( result, streamUrl );
|
||||
performLoadIODevice( d->currentTrack, d->currentTrack->url() );
|
||||
}
|
||||
else
|
||||
{
|
||||
// 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 );
|
||||
QSharedPointer< QIODevice > io;
|
||||
performLoadTrack( result, result->url(), io );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
||||
void
|
||||
AudioEngine::gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply )
|
||||
{
|
||||
// std::functions cannot accept temporaries as parameters
|
||||
QSharedPointer< QIODevice > sp ( reply->reply(), &QObject::deleteLater );
|
||||
QString url = reply->reply()->url().toString();
|
||||
reply->disconnectFromReply();
|
||||
reply->deleteLater();
|
||||
|
||||
performLoadTrack( result, url, sp );
|
||||
}
|
||||
|
||||
|
||||
@@ -669,7 +618,7 @@ AudioEngine::performLoadIODevice( const result_ptr& result, const QString& url )
|
||||
|
||||
|
||||
void
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io )
|
||||
AudioEngine::performLoadTrack( const Tomahawk::result_ptr result, const QString url, QSharedPointer< QIODevice > io )
|
||||
{
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
|
@@ -28,7 +28,6 @@
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
class NetworkReply;
|
||||
class AudioEnginePrivate;
|
||||
|
||||
class DLLEXPORT AudioEngine : public QObject
|
||||
@@ -181,12 +180,8 @@ signals:
|
||||
|
||||
private slots:
|
||||
void loadTrack( const Tomahawk::result_ptr& result ); //async!
|
||||
void gotStreamUrl( const QVariantMap& data );
|
||||
void gotRedirectedStreamUrl( const Tomahawk::result_ptr& result, NetworkReply* reply );
|
||||
|
||||
|
||||
void performLoadIODevice( const Tomahawk::result_ptr& result, const QString& url ); //only call from loadTrack kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString& url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void performLoadTrack( const Tomahawk::result_ptr result, const QString url, QSharedPointer< QIODevice > io ); //only call from loadTrack or performLoadIODevice kthxbi
|
||||
void loadPreviousTrack();
|
||||
void loadNextTrack();
|
||||
|
||||
|
@@ -35,7 +35,7 @@ using namespace Tomahawk;
|
||||
|
||||
|
||||
Collection::Collection( const source_ptr& source, const QString& name, QObject* parent )
|
||||
: Resolver( parent )
|
||||
: QObject( parent )
|
||||
, m_name( name )
|
||||
, m_lastmodified( 0 )
|
||||
, m_changed( false )
|
||||
|
@@ -33,7 +33,7 @@
|
||||
#include "collection/ArtistsRequest.h"
|
||||
#include "collection/AlbumsRequest.h"
|
||||
#include "collection/TracksRequest.h"
|
||||
#include "../resolvers/Resolver.h"
|
||||
#include "../ResultProvider.h"
|
||||
|
||||
#include "DllMacro.h"
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
namespace Tomahawk
|
||||
{
|
||||
|
||||
class DLLEXPORT Collection : public Resolver
|
||||
class DLLEXPORT Collection : public QObject, public ResultProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
|
@@ -251,32 +251,3 @@ DatabaseCollection::stationCreated( const source_ptr& source, const QVariantList
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Resolver interface
|
||||
*
|
||||
* We implement searching the database in the DatabaseResolver which avoids a n+1 query here.
|
||||
* We can't simply let ScriptCollection inherit Collection and Resolver because both are QObjects,
|
||||
* although Resolver doesn't need to be a QObject atm, blocking adding signals/slots to Resolver
|
||||
* in future seems to me worse than violating Liskov's law here. ~ domme
|
||||
*/
|
||||
unsigned int
|
||||
DatabaseCollection::timeout() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
DatabaseCollection::weight() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DatabaseCollection::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
Q_UNUSED( query );
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
@@ -65,11 +65,6 @@ public:
|
||||
int trackCount() const override;
|
||||
QPixmap icon( const QSize& size ) const override;
|
||||
|
||||
// Resolver interface
|
||||
unsigned int weight() const override;
|
||||
unsigned int timeout() const override;
|
||||
void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
|
||||
public slots:
|
||||
virtual void addTracks( const QList<QVariant>& newitems );
|
||||
virtual void removeTracks( const QDir& dir );
|
||||
|
@@ -277,8 +277,8 @@ InfoSystem::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
|
||||
|
||||
if ( plugin.data()->thread() != m_infoSystemWorkerThreadController->worker()->thread() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread(): " << plugin->friendlyName();
|
||||
Q_ASSERT( false );
|
||||
tDebug() << Q_FUNC_INFO << "The object must be moved to the worker thread first, see InfoSystem::workerThread()";
|
||||
return;
|
||||
}
|
||||
|
||||
|
@@ -58,7 +58,13 @@ InfoSystemWorker::InfoSystemWorker()
|
||||
|
||||
InfoSystemWorker::~InfoSystemWorker()
|
||||
{
|
||||
tDebug() << Q_FUNC_INFO;
|
||||
tDebug() << Q_FUNC_INFO << " beginning";
|
||||
Q_FOREACH( InfoPluginPtr plugin, m_plugins )
|
||||
{
|
||||
if( plugin )
|
||||
delete plugin.data();
|
||||
}
|
||||
tDebug() << Q_FUNC_INFO << " finished";
|
||||
}
|
||||
|
||||
|
||||
@@ -130,6 +136,29 @@ InfoSystemWorker::addInfoPlugin( Tomahawk::InfoSystem::InfoPluginPtr plugin )
|
||||
|
||||
emit updatedSupportedGetTypes( QSet< InfoType >::fromList( m_infoGetMap.keys() ) );
|
||||
emit updatedSupportedPushTypes( QSet< InfoType >::fromList( m_infoPushMap.keys() ) );
|
||||
|
||||
connect( plugin.data(), SIGNAL( destroyed( QObject* ) ), SLOT( onInfoPluginDeleted() ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
InfoSystemWorker::onInfoPluginDeleted()
|
||||
{
|
||||
foreach( const InfoPluginPtr& plugin, m_plugins )
|
||||
{
|
||||
if ( plugin.isNull() )
|
||||
{
|
||||
m_plugins.removeOne( plugin );
|
||||
foreach( InfoType type, m_infoGetMap.keys() )
|
||||
{
|
||||
m_infoGetMap[type].removeOne( plugin );
|
||||
}
|
||||
foreach( InfoType type, m_infoPushMap.keys() )
|
||||
{
|
||||
m_infoPushMap[type].removeOne( plugin );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@@ -72,6 +72,7 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void checkTimeoutsTimerFired();
|
||||
void onInfoPluginDeleted();
|
||||
|
||||
private:
|
||||
void registerInfoTypes( const InfoPluginPtr &plugin, const QSet< InfoType > &getTypes, const QSet< InfoType > &pushTypes );
|
||||
|
@@ -33,12 +33,6 @@ JobStatusItem::~JobStatusItem()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusItem::activated()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
JobStatusItem::allowMultiLine() const
|
||||
{
|
||||
|
@@ -53,8 +53,6 @@ public:
|
||||
virtual QString mainText() const = 0;
|
||||
virtual QString rightColumnText() const { return QString(); };
|
||||
|
||||
virtual void activated();
|
||||
|
||||
/**
|
||||
* If collapse item is true, sending multiple items of the same type will "collapse" them into one
|
||||
* instead of showing each individually. In this case, the right column from the item will be ignored
|
||||
|
@@ -118,7 +118,6 @@ JobStatusView::setModel( JobStatusSortModel* m )
|
||||
connect( m_view->model(), SIGNAL( customDelegateJobInserted( int, JobStatusItem* ) ), this, SLOT( customDelegateJobInserted( int, JobStatusItem* ) ) );
|
||||
connect( m_view->model(), SIGNAL( customDelegateJobRemoved( int ) ), this, SLOT( customDelegateJobRemoved( int ) ) );
|
||||
connect( m_view->model(), SIGNAL( refreshDelegates() ), this, SLOT( refreshDelegates() ) );
|
||||
connect( m_view, SIGNAL( activated( QModelIndex ) ), this, SLOT( onItemActivated( QModelIndex ) ) );
|
||||
|
||||
foreach ( const QPointer<JobStatusItem> item, s_jobItems )
|
||||
{
|
||||
@@ -185,21 +184,6 @@ JobStatusView::refreshDelegates()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusView::onItemActivated( const QModelIndex& index )
|
||||
{
|
||||
QVariant itemVar = index.data( JobStatusModel::JobDataRole );
|
||||
if ( !itemVar.canConvert< JobStatusItem* >() || !itemVar.value< JobStatusItem* >() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "unable to fetch JobStatusItem*";
|
||||
return;
|
||||
}
|
||||
|
||||
JobStatusItem* item = itemVar.value< JobStatusItem* >();
|
||||
item->activated();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JobStatusView::checkCount()
|
||||
{
|
||||
|
@@ -59,7 +59,6 @@ private slots:
|
||||
void customDelegateJobInserted( int row, JobStatusItem* item );
|
||||
void customDelegateJobRemoved( int row );
|
||||
void refreshDelegates();
|
||||
void onItemActivated( const QModelIndex& index );
|
||||
|
||||
private:
|
||||
QListView* m_view;
|
||||
|
@@ -119,9 +119,8 @@ int
|
||||
PlayableModel::columnCount( const QModelIndex& parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
Q_D( const PlayableModel );
|
||||
|
||||
return d->header.length();
|
||||
return 13;
|
||||
}
|
||||
|
||||
|
||||
@@ -445,21 +444,14 @@ PlayableModel::flags( const QModelIndex& index ) const
|
||||
|
||||
if ( index.isValid() )
|
||||
{
|
||||
Qt::ItemFlags returnFlags = defaultFlags;
|
||||
if ( index.column() == 0 )
|
||||
{
|
||||
returnFlags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
|
||||
return Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled | defaultFlags;
|
||||
}
|
||||
else if ( index.column() == PlayableModel::Download )
|
||||
{
|
||||
returnFlags |= Qt::ItemIsEditable | defaultFlags;
|
||||
return Qt::ItemIsEditable | defaultFlags;
|
||||
}
|
||||
|
||||
if ( areAllColumnsEditable() ) {
|
||||
returnFlags |= Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
return returnFlags;
|
||||
}
|
||||
|
||||
return Qt::ItemIsDropEnabled | defaultFlags;
|
||||
@@ -1179,22 +1171,6 @@ PlayableModel::setIcon( const QPixmap& pixmap )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableModel::setAllColumnsEditable( bool editable )
|
||||
{
|
||||
Q_D( PlayableModel );
|
||||
d->areAllColumnsEditable = editable;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
PlayableModel::areAllColumnsEditable() const
|
||||
{
|
||||
Q_D( const PlayableModel );
|
||||
return d->areAllColumnsEditable;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PlayableModel::trackCount() const
|
||||
{
|
||||
|
@@ -96,11 +96,6 @@ public:
|
||||
virtual QPixmap icon() const;
|
||||
virtual void setIcon( const QPixmap& pixmap );
|
||||
|
||||
|
||||
// HACK: we need to set column 0 editable for DropDownButton in TrackView
|
||||
void setAllColumnsEditable( bool editable );
|
||||
bool areAllColumnsEditable() const;
|
||||
|
||||
virtual int trackCount() const;
|
||||
virtual int itemCount() const;
|
||||
|
||||
|
@@ -38,7 +38,6 @@ public:
|
||||
, rootItem( new PlayableItem( 0 ) )
|
||||
, readOnly( true )
|
||||
, loading( _loading )
|
||||
, areAllColumnsEditable( false )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -59,7 +58,6 @@ private:
|
||||
QStringList header;
|
||||
|
||||
bool loading;
|
||||
bool areAllColumnsEditable;
|
||||
};
|
||||
|
||||
#endif // PLAYABLEMODEL_P_H
|
||||
|
@@ -607,7 +607,25 @@ PlayableProxyModel::columnCount( const QModelIndex& parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
|
||||
return m_headerStyle[ m_style ].length();
|
||||
switch ( m_style )
|
||||
{
|
||||
case SingleColumn:
|
||||
return 1;
|
||||
break;
|
||||
|
||||
case Collection:
|
||||
return 10;
|
||||
break;
|
||||
|
||||
case Locker:
|
||||
return 11;
|
||||
break;
|
||||
|
||||
case Detailed:
|
||||
default:
|
||||
return 12;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -715,13 +733,6 @@ PlayableProxyModel::setFilter( const QString& pattern )
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
PlayableProxyModel::mapSourceColumnToColumn( PlayableModel::Columns column )
|
||||
{
|
||||
return m_headerStyle[ m_style ].indexOf( column );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
PlayableProxyModel::setCurrentIndex( const QModelIndex& index )
|
||||
{
|
||||
|
@@ -98,8 +98,6 @@ public:
|
||||
virtual void setFilter( const QString& pattern );
|
||||
virtual void updateDetailedInfo( const QModelIndex& index );
|
||||
|
||||
int mapSourceColumnToColumn( PlayableModel::Columns column );
|
||||
|
||||
signals:
|
||||
void filterChanged( const QString& filter );
|
||||
|
||||
|
@@ -885,9 +885,7 @@ PlaylistItemDelegate::editorEvent( QEvent* event, QAbstractItemModel* model, con
|
||||
}
|
||||
else if ( m_view->proxyModel()->style() == PlayableProxyModel::Locker && index.column() == PlayableModel::Download )
|
||||
{
|
||||
m_model->sourceModel()->setAllColumnsEditable( true );
|
||||
m_view->edit( index );
|
||||
m_model->sourceModel()->setAllColumnsEditable( false );
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -262,15 +262,8 @@ TrackDetailView::onResultsChanged()
|
||||
resolverLabel->setFont( f );
|
||||
resolverLabel->setStyleSheet( "QLabel { color: rgba( 0, 0, 0, 50% ) }" );
|
||||
resolverLabel->setText( QString( "%1 - %2" ).arg( result->track()->track() ).arg( result->track()->artist() ) );
|
||||
resolverLabel->setToolTip(
|
||||
QString( "%1 by %2%3 (%4)" )
|
||||
.arg( result->track()->track() )
|
||||
.arg( result->track()->artist() )
|
||||
.arg( !result->track()->album().isEmpty() ? QString( " " ) + tr( "on %1" ).arg( result->track()->album() ) : QString() )
|
||||
.arg( result->friendlySource() )
|
||||
);
|
||||
|
||||
;
|
||||
resolverLabel->setToolTip( QString( "%1 by %2%3" ).arg( result->track()->track() ).arg( result->track()->artist() )
|
||||
.arg( !result->track()->album().isEmpty() ? QString( " " ) + tr( "on %1" ).arg( result->track()->album() ) : QString() ) );
|
||||
resolverLabel->setFixedWidth( width() - 32 - 4 );
|
||||
|
||||
NewClosure( resolverLabel, SIGNAL( clicked() ), const_cast< AudioEngine* >( AudioEngine::instance() ),
|
||||
|
@@ -45,9 +45,6 @@
|
||||
#include <QScrollBar>
|
||||
#include <QDrag>
|
||||
|
||||
// HACK
|
||||
#include <QTableView>
|
||||
|
||||
#define SCROLL_TIMEOUT 280
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -86,13 +83,6 @@ TrackView::TrackView( QWidget* parent )
|
||||
setEditTriggers( NoEditTriggers );
|
||||
|
||||
setHeader( m_header );
|
||||
|
||||
// HACK: enable moving of first column: QTBUG-33974 / https://github.com/qtproject/qtbase/commit/e0fc088c0c8bc61dbcaf5928b24986cd61a22777
|
||||
QTableView unused;
|
||||
unused.setVerticalHeader( header() );
|
||||
header()->setParent( this );
|
||||
unused.setVerticalHeader( new QHeaderView( Qt::Horizontal, &unused ) );
|
||||
|
||||
setSortingEnabled( true );
|
||||
sortByColumn( -1 );
|
||||
setContextMenuPolicy( Qt::CustomContextMenu );
|
||||
|
@@ -68,12 +68,11 @@ public:
|
||||
|
||||
enum UrlType
|
||||
{
|
||||
UrlTypeAny = 0x00,
|
||||
UrlTypePlaylist = 0x01,
|
||||
UrlTypeTrack = 0x02,
|
||||
UrlTypeAlbum = 0x04,
|
||||
UrlTypeArtist = 0x08,
|
||||
UrlTypeXspf = 0x10
|
||||
Any = 0x00,
|
||||
Playlist = 0x01,
|
||||
Track = 0x02,
|
||||
Album = 0x04,
|
||||
Artist = 0x08
|
||||
};
|
||||
Q_DECLARE_FLAGS( UrlTypes, UrlType )
|
||||
Q_FLAGS( UrlTypes )
|
||||
|
@@ -30,8 +30,6 @@
|
||||
#include <QWidget>
|
||||
#include <QUiLoader>
|
||||
#include <QBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QDesktopServices>
|
||||
|
||||
Tomahawk::ExternalResolverGui::ExternalResolverGui(const QString& filePath)
|
||||
: Tomahawk::ExternalResolver(filePath)
|
||||
@@ -84,30 +82,6 @@ Tomahawk::ExternalResolverGui::addChildProperties( QObject* widget, QVariantMap&
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Tomahawk::ExternalResolverGui::setupClickHandlerOnUrlButtons( QObject* widget )
|
||||
{
|
||||
if( !widget || !widget->isWidgetType() )
|
||||
return;
|
||||
|
||||
if( qstrcmp( widget->metaObject()->className(), "QPushButton" ) == 0 && !widget->property( "url" ).isNull() )
|
||||
{
|
||||
QPushButton* button = qobject_cast< QPushButton* >( widget );
|
||||
Q_ASSERT( button );
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
connect( button, &QPushButton::clicked, [=]() {
|
||||
QDesktopServices::openUrl( widget->property( "url" ).toUrl() );
|
||||
});
|
||||
#endif
|
||||
}
|
||||
|
||||
// and recurse
|
||||
foreach( QObject* child, widget->children() )
|
||||
setupClickHandlerOnUrlButtons( child );
|
||||
}
|
||||
|
||||
|
||||
AccountConfigWidget*
|
||||
Tomahawk::ExternalResolverGui::widgetFromData( QByteArray& data, QWidget* parent )
|
||||
{
|
||||
@@ -120,8 +94,6 @@ Tomahawk::ExternalResolverGui::widgetFromData( QByteArray& data, QWidget* parent
|
||||
QBuffer b( &data );
|
||||
QWidget* w = l.load( &b, configWidget );
|
||||
|
||||
setupClickHandlerOnUrlButtons( w );
|
||||
|
||||
// HACK: proper way would be to create a designer plugin for this widget type
|
||||
configWidget->setLayout( new QBoxLayout( QBoxLayout::TopToBottom ) );
|
||||
configWidget->layout()->addWidget( w );
|
||||
|
@@ -50,8 +50,7 @@ protected:
|
||||
QByteArray fixDataImagePaths( const QByteArray& data, bool compressed, const QVariantMap& images );
|
||||
|
||||
private:
|
||||
void addChildProperties( QObject* widget, QVariantMap& m );
|
||||
void setupClickHandlerOnUrlButtons( QObject* widget );
|
||||
void addChildProperties( QObject* parent, QVariantMap& m );
|
||||
};
|
||||
|
||||
}; //ns
|
||||
|
@@ -67,14 +67,6 @@ JSAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr& obj
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSAccount::showDebugger()
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << name() << "Show debugger";
|
||||
m_engine->showWebInspector();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSAccount::serializeQVariantMap( const QVariantMap& map )
|
||||
{
|
||||
@@ -178,41 +170,6 @@ JSAccount::syncInvoke( const scriptobject_ptr& scriptObject, const QString& meth
|
||||
return evaluateJavaScriptWithResult( eval );
|
||||
}
|
||||
|
||||
void
|
||||
JSAccount::reportNativeScriptJobResult( int resultId, const QVariantMap& result )
|
||||
{
|
||||
QString eval = QString(
|
||||
"Tomahawk.NativeScriptJobManager.reportNativeScriptJobResult("
|
||||
"%1," // requestId
|
||||
"%2" // results
|
||||
");"
|
||||
).arg( resultId )
|
||||
.arg( serializeQVariantMap( result ) );
|
||||
|
||||
// Remove when new scripting api turned out to work reliably
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval;
|
||||
|
||||
evaluateJavaScript( eval );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSAccount::reportNativeScriptJobError( int resultId, const QVariantMap& error )
|
||||
{
|
||||
QString eval = QString(
|
||||
"Tomahawk.NativeScriptJobManager.reportNativeScriptJobError("
|
||||
"%1," // requestId
|
||||
"%2" // results
|
||||
");"
|
||||
).arg( resultId )
|
||||
.arg( serializeQVariantMap( error ) );
|
||||
|
||||
// Remove when new scripting api turned out to work reliably
|
||||
tDebug( LOGVERBOSE ) << Q_FUNC_INFO << eval;
|
||||
|
||||
evaluateJavaScript( eval );
|
||||
}
|
||||
|
||||
|
||||
QVariant
|
||||
JSAccount::evaluateJavaScriptInternal( const QString& scriptSource )
|
||||
|
@@ -69,20 +69,15 @@ public:
|
||||
void setResolver( JSResolver* resolver );
|
||||
void scriptPluginFactory( const QString& type, const scriptobject_ptr& object ) override;
|
||||
|
||||
void showDebugger() override;
|
||||
|
||||
static QString serializeQVariantMap(const QVariantMap& map);
|
||||
|
||||
void reportNativeScriptJobResult( int resultId, const QVariantMap& result ) override;
|
||||
void reportNativeScriptJobError( int resultId, const QVariantMap& error ) override;
|
||||
|
||||
private:
|
||||
/**
|
||||
* Wrap the pure evaluateJavaScript call in here, while the threadings guards are in public methods
|
||||
*/
|
||||
QVariant evaluateJavaScriptInternal( const QString& scriptSource );
|
||||
|
||||
ScriptEngine* m_engine;
|
||||
std::unique_ptr<ScriptEngine> m_engine;
|
||||
// HACK: the order of initializen is flawed, tbr
|
||||
JSResolver* m_resolver;
|
||||
};
|
||||
|
@@ -44,13 +44,6 @@
|
||||
#include "Track.h"
|
||||
#include "ScriptInfoPlugin.h"
|
||||
#include "JSAccount.h"
|
||||
#include "ScriptJob.h"
|
||||
|
||||
// lookupUrl stuff
|
||||
#include "playlist/PlaylistTemplate.h"
|
||||
#include "playlist/XspfPlaylistTemplate.h"
|
||||
#include "database/Database.h"
|
||||
#include "database/DatabaseImpl.h"
|
||||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
@@ -216,52 +209,21 @@ JSResolver::init()
|
||||
}
|
||||
const QByteArray scriptContents = scriptFile.readAll();
|
||||
|
||||
// tomahawk.js
|
||||
{
|
||||
// add c++ part of tomahawk javascript library
|
||||
d->scriptAccount->addToJavaScriptWindowObject( "Tomahawk", d->resolverHelper );
|
||||
|
||||
// load es6-promises shim
|
||||
d->scriptAccount->loadScript( RESPATH "js/rsvp-latest.min.js" );
|
||||
|
||||
|
||||
// Load CrytoJS core
|
||||
d->scriptAccount->loadScript( RESPATH "js/cryptojs-core.js" );
|
||||
|
||||
// Load CryptoJS modules
|
||||
QStringList jsfiles;
|
||||
jsfiles << "*.js";
|
||||
QDir cryptojs( RESPATH "js/cryptojs" );
|
||||
foreach ( QString jsfile, cryptojs.entryList( jsfiles ) )
|
||||
{
|
||||
d->scriptAccount->loadScript( RESPATH "js/cryptojs/" + jsfile );
|
||||
}
|
||||
|
||||
// Load tomahawk.js
|
||||
d->scriptAccount->loadScript( RESPATH "js/tomahawk.js" );
|
||||
}
|
||||
|
||||
// tomahawk-infosystem.js
|
||||
{
|
||||
// TODO: be smarter about this, only include this if the resolver supports infoplugins
|
||||
|
||||
// add deps
|
||||
d->scriptAccount->loadScript( RESPATH "js/tomahawk-infosystem.js" );
|
||||
}
|
||||
|
||||
// add resolver dependencies, if any
|
||||
d->scriptAccount->loadScripts( d->requiredScriptPaths );
|
||||
|
||||
d->scriptAccount->addToJavaScriptWindowObject( "Tomahawk", d->resolverHelper );
|
||||
|
||||
// add resolver
|
||||
d->scriptAccount->loadScript( filePath() );
|
||||
|
||||
// HACK: register resolver object
|
||||
d->scriptAccount->evaluateJavaScript( "Tomahawk.PluginManager.registerPlugin('resolver', Tomahawk.resolver.instance);" );
|
||||
// init resolver
|
||||
scriptObject()->syncInvoke( "init" );
|
||||
d->scriptAccount->evaluateJavaScript(
|
||||
"var resolverInstance = new (require('main').default);"
|
||||
"Tomahawk.PluginManager.registerPlugin('resolver', resolverInstance);"
|
||||
);
|
||||
|
||||
QVariantMap m = scriptObject()->syncInvoke( "settings" ).toMap();
|
||||
// init resolver
|
||||
resolverInit();
|
||||
|
||||
QVariantMap m = resolverSettings();
|
||||
d->name = m.value( "name" ).toString();
|
||||
d->weight = m.value( "weight", 0 ).toUInt();
|
||||
d->timeout = m.value( "timeout", 25 ).toUInt() * 1000;
|
||||
@@ -311,8 +273,6 @@ JSResolver::start()
|
||||
Q_D( JSResolver );
|
||||
|
||||
d->stopped = false;
|
||||
d->resolverHelper->start();
|
||||
|
||||
if ( d->ready )
|
||||
Tomahawk::Pipeline::instance()->addResolver( this );
|
||||
else
|
||||
@@ -327,13 +287,20 @@ JSResolver::canParseUrl( const QString& url, UrlType type )
|
||||
{
|
||||
Q_D( const JSResolver );
|
||||
|
||||
// FIXME: How can we do this?
|
||||
/*if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "canParseUrl", Qt::QueuedConnection,
|
||||
Q_ARG( QString, url ) );
|
||||
return;
|
||||
}*/
|
||||
|
||||
if ( d->capabilities.testFlag( UrlLookup ) )
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["url"] = url;
|
||||
arguments["type"] = (int) type;
|
||||
|
||||
return scriptObject()->syncInvoke( "canParseUrl", arguments ).toBool();
|
||||
QString eval = QString( "canParseUrl( '%1', %2 )" )
|
||||
.arg( JSAccount::escape( QString( url ) ) )
|
||||
.arg( (int) type );
|
||||
return callOnResolver( eval ).toBool();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -346,8 +313,14 @@ JSResolver::canParseUrl( const QString& url, UrlType type )
|
||||
void
|
||||
JSResolver::lookupUrl( const QString& url )
|
||||
{
|
||||
Q_D( const JSResolver );
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
QMetaObject::invokeMethod( this, "lookupUrl", Qt::QueuedConnection,
|
||||
Q_ARG( QString, url ) );
|
||||
return;
|
||||
}
|
||||
|
||||
Q_D( const JSResolver );
|
||||
|
||||
if ( !d->capabilities.testFlag( UrlLookup ) )
|
||||
{
|
||||
@@ -355,176 +328,19 @@ JSResolver::lookupUrl( const QString& url )
|
||||
return;
|
||||
}
|
||||
|
||||
QVariantMap arguments;
|
||||
arguments["url"] = url;
|
||||
Tomahawk::ScriptJob* job = scriptObject()->invoke( "lookupUrl", arguments );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onLookupUrlRequestDone( QVariantMap ) ) );
|
||||
job->setProperty( "url", url );
|
||||
job->start();
|
||||
}
|
||||
QString eval = QString( "lookupUrl( '%1' )" )
|
||||
.arg( JSAccount::escape( QString( url ) ) );
|
||||
|
||||
|
||||
void
|
||||
JSResolver::onLookupUrlRequestDone( const QVariantMap& result )
|
||||
{
|
||||
sender()->deleteLater();
|
||||
|
||||
QString url = sender()->property( "url" ).toString();
|
||||
|
||||
tLog() << "ON LOOKUP URL REQUEST DONE" << url << result;
|
||||
|
||||
// It may seem a bit weird, but currently no slot should do anything
|
||||
// more as we starting on a new URL and not task are waiting for it yet.
|
||||
m_pendingUrl = QString();
|
||||
m_pendingAlbum = album_ptr();
|
||||
|
||||
UrlTypes type = (UrlTypes) result.value( "type" ).toInt();
|
||||
if ( type == UrlTypeArtist )
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
if ( m.isEmpty() )
|
||||
{
|
||||
QString name = result.value( "name" ).toString();
|
||||
Q_ASSERT( !name.isEmpty() );
|
||||
emit informationFound( url, Artist::get( name, true ).objectCast<QObject>() );
|
||||
}
|
||||
else if ( type == UrlTypeAlbum )
|
||||
{
|
||||
QString name = result.value( "name" ).toString();
|
||||
QString artist = result.value( "artist" ).toString();
|
||||
album_ptr album = Album::get( Artist::get( artist, true ), name );
|
||||
m_pendingUrl = url;
|
||||
m_pendingAlbum = album;
|
||||
connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
|
||||
if ( !album->tracks().isEmpty() )
|
||||
{
|
||||
emit informationFound( url, album.objectCast<QObject>() );
|
||||
}
|
||||
}
|
||||
else if ( type == UrlTypeTrack )
|
||||
{
|
||||
Tomahawk::query_ptr query = parseTrack( result );
|
||||
if ( query.isNull() )
|
||||
{
|
||||
// A valid track result shoud have non-empty title and artist.
|
||||
tLog() << Q_FUNC_INFO << name() << "Got empty track information for " << url;
|
||||
emit informationFound( url, QSharedPointer<QObject>() );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit informationFound( url, query.objectCast<QObject>() );
|
||||
}
|
||||
}
|
||||
else if ( type == UrlTypePlaylist )
|
||||
{
|
||||
QString guid = result.value( "guid" ).toString();
|
||||
Q_ASSERT( !guid.isEmpty() );
|
||||
// Append nodeid to guid to make it globally unique.
|
||||
guid += instanceUUID();
|
||||
|
||||
// Do we already have this playlist loaded?
|
||||
{
|
||||
playlist_ptr playlist = Playlist::get( guid );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
emit informationFound( url, playlist.objectCast<QObject>() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get all information to build a new playlist but do not build it until we know,
|
||||
// if it is really handled as a playlist and not as a set of tracks.
|
||||
Tomahawk::source_ptr source = SourceList::instance()->getLocal();
|
||||
const QString title = result.value( "title" ).toString();
|
||||
const QString info = result.value( "info" ).toString();
|
||||
const QString creator = result.value( "creator" ).toString();
|
||||
QList<query_ptr> queries;
|
||||
foreach( QVariant track, result.value( "tracks" ).toList() )
|
||||
{
|
||||
query_ptr query = parseTrack( track.toMap() );
|
||||
if ( !query.isNull() )
|
||||
{
|
||||
queries << query;
|
||||
}
|
||||
}
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << name() << "Got playlist for " << url;
|
||||
playlisttemplate_ptr pltemplate( new PlaylistTemplate( source, guid, title, info, creator, false, queries ) );
|
||||
emit informationFound( url, pltemplate.objectCast<QObject>() );
|
||||
}
|
||||
else if ( type == UrlTypeXspf )
|
||||
{
|
||||
QString xspfUrl = result.value( "url" ).toString();
|
||||
Q_ASSERT( !xspfUrl.isEmpty() );
|
||||
QString guid = QString( "xspf-%1-%2" ).arg( xspfUrl.toUtf8().toBase64().constData() ).arg( instanceUUID() );
|
||||
|
||||
// Do we already have this playlist loaded?
|
||||
{
|
||||
playlist_ptr playlist = Playlist::get( guid );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
emit informationFound( url, playlist.objectCast<QObject>() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get all information to build a new playlist but do not build it until we know,
|
||||
// if it is really handled as a playlist and not as a set of tracks.
|
||||
Tomahawk::source_ptr source = SourceList::instance()->getLocal();
|
||||
QSharedPointer<XspfPlaylistTemplate> pltemplate( new XspfPlaylistTemplate( xspfUrl, source, guid ) );
|
||||
NewClosure( pltemplate, SIGNAL( tracksLoaded( QList< Tomahawk::query_ptr > ) ),
|
||||
this, SLOT( pltemplateTracksLoadedForUrl( QString, Tomahawk::playlisttemplate_ptr ) ),
|
||||
url, pltemplate.objectCast<Tomahawk::PlaylistTemplate>() );
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << name() << "Got playlist for " << url;
|
||||
pltemplate->load();
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << name() << "No usable information found for " << url;
|
||||
emit informationFound( url, QSharedPointer<QObject>() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
query_ptr
|
||||
JSResolver::parseTrack( const QVariantMap& track )
|
||||
{
|
||||
QString title = track.value( "track" ).toString();
|
||||
QString artist = track.value( "artist" ).toString();
|
||||
QString album = track.value( "album" ).toString();
|
||||
if ( title.isEmpty() || artist.isEmpty() )
|
||||
{
|
||||
return query_ptr();
|
||||
}
|
||||
|
||||
Tomahawk::query_ptr query = Tomahawk::Query::get( artist, title, album );
|
||||
QString resultHint = track.value( "hint" ).toString();
|
||||
if ( !resultHint.isEmpty() )
|
||||
{
|
||||
query->setResultHint( resultHint );
|
||||
query->setSaveHTTPResultHint( true );
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolver::tracksAdded( const QList<query_ptr>&, const ModelMode, const collection_ptr&)
|
||||
{
|
||||
// Check if we still are actively waiting
|
||||
if ( m_pendingAlbum.isNull() || m_pendingUrl.isNull() )
|
||||
// if the resolver doesn't return anything, async api is used
|
||||
return;
|
||||
}
|
||||
|
||||
emit informationFound( m_pendingUrl, m_pendingAlbum.objectCast<QObject>() );
|
||||
m_pendingAlbum = album_ptr();
|
||||
m_pendingUrl = QString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolver::pltemplateTracksLoadedForUrl( const QString& url, const playlisttemplate_ptr& pltemplate )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
emit informationFound( url, pltemplate.objectCast<QObject>() );
|
||||
QString errorMessage = tr( "Script Resolver Warning: API call %1 returned data synchronously." ).arg( eval );
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( errorMessage ) );
|
||||
tDebug() << errorMessage << m;
|
||||
}
|
||||
|
||||
|
||||
@@ -540,59 +356,38 @@ JSResolver::error() const
|
||||
void
|
||||
JSResolver::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
ScriptJob* job = scriptAccount()->resolve( scriptObject(), query, "resolver" );
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onResolveRequestDone( QVariantMap ) ) );
|
||||
|
||||
job->start();
|
||||
}
|
||||
|
||||
void
|
||||
JSResolver::onResolveRequestDone( const QVariantMap& data )
|
||||
{
|
||||
Q_ASSERT( QThread::currentThread() == thread() );
|
||||
Q_D( JSResolver );
|
||||
|
||||
ScriptJob* job = qobject_cast< ScriptJob* >( sender() );
|
||||
|
||||
QID qid = job->property( "qid" ).toString();
|
||||
|
||||
if ( job->error() )
|
||||
if ( QThread::currentThread() != thread() )
|
||||
{
|
||||
Tomahawk::Pipeline::instance()->reportError( qid, this );
|
||||
QMetaObject::invokeMethod( this, "resolve", Qt::QueuedConnection, Q_ARG(Tomahawk::query_ptr, query) );
|
||||
return;
|
||||
}
|
||||
|
||||
QString eval;
|
||||
if ( !query->isFullTextQuery() )
|
||||
{
|
||||
eval = QString( "resolve( '%1', '%2', '%3', '%4' )" )
|
||||
.arg( JSAccount::escape( query->id() ) )
|
||||
.arg( JSAccount::escape( query->queryTrack()->artist() ) )
|
||||
.arg( JSAccount::escape( query->queryTrack()->album() ) )
|
||||
.arg( JSAccount::escape( query->queryTrack()->track() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( !data.value( "artists" ).isNull() )
|
||||
{
|
||||
QList< artist_ptr > artists = scriptAccount()->parseArtistVariantList( data.value( "artists" ).toList() );
|
||||
Tomahawk::Pipeline::instance()->reportArtists( qid, artists );
|
||||
}
|
||||
|
||||
if ( !data.value( "albums" ).isNull() )
|
||||
{
|
||||
QList< album_ptr > albums = scriptAccount()->parseAlbumVariantList( data.value( "albums" ).toList() );
|
||||
Tomahawk::Pipeline::instance()->reportAlbums( qid, albums );
|
||||
}
|
||||
|
||||
QList< Tomahawk::result_ptr > results = scriptAccount()->parseResultVariantList( data.value( "tracks" ).toList() );
|
||||
foreach( const result_ptr& result, results )
|
||||
{
|
||||
result->setResolvedByResolver( this );
|
||||
result->setFriendlySource( name() );
|
||||
}
|
||||
Tomahawk::Pipeline::instance()->reportResults( qid, this, results );
|
||||
eval = QString( "search( '%1', '%2' )" )
|
||||
.arg( JSAccount::escape( query->id() ) )
|
||||
.arg( JSAccount::escape( query->fullTextQuery() ) );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
QVariantMap m = callOnResolver( eval ).toMap();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolver::stop()
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
d->stopped = true;
|
||||
d->resolverHelper->stop();
|
||||
|
||||
scriptAccount()->stop();
|
||||
|
||||
@@ -606,7 +401,7 @@ JSResolver::loadUi()
|
||||
{
|
||||
Q_D( JSResolver );
|
||||
|
||||
QVariantMap m = scriptObject()->syncInvoke( "getConfigUi" ).toMap();
|
||||
QVariantMap m = callOnResolver( "getConfigUi()" ).toMap();
|
||||
|
||||
bool compressed = m.value( "compressed", "false" ).toBool();
|
||||
qDebug() << "Resolver has a preferences widget! compressed?" << compressed;
|
||||
@@ -658,7 +453,7 @@ JSResolver::saveConfig()
|
||||
// qDebug() << Q_FUNC_INFO << saveData;
|
||||
|
||||
d->resolverHelper->setResolverConfig( saveData.toMap() );
|
||||
scriptObject()->syncInvoke( "saveUserConfig" );
|
||||
callOnResolver( "saveUserConfig()" );
|
||||
}
|
||||
|
||||
|
||||
@@ -689,25 +484,39 @@ JSResolver::onCapabilitiesChanged( Tomahawk::ExternalResolver::Capabilities capa
|
||||
}
|
||||
|
||||
|
||||
QVariantMap
|
||||
JSResolver::resolverSettings()
|
||||
{
|
||||
return callOnResolver( "settings" ).toMap();
|
||||
}
|
||||
|
||||
|
||||
QVariantMap
|
||||
JSResolver::resolverUserConfig()
|
||||
{
|
||||
return scriptObject()->syncInvoke( "getUserConfig" ).toMap();
|
||||
return callOnResolver( "getUserConfig()" ).toMap();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSResolver::instanceUUID()
|
||||
QVariantMap
|
||||
JSResolver::resolverInit()
|
||||
{
|
||||
return Tomahawk::Database::instance()->impl()->dbid();
|
||||
return callOnResolver( "init()" ).toMap();
|
||||
}
|
||||
|
||||
|
||||
ScriptJob*
|
||||
JSResolver::getStreamUrl( const result_ptr& result )
|
||||
QVariant
|
||||
JSResolver::callOnResolver( const QString& scriptSource )
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["url"] = result->url();
|
||||
Q_D( JSResolver );
|
||||
|
||||
return scriptObject()->invoke( "getStreamUrl", arguments );
|
||||
QString propertyName = scriptSource.split('(').first();
|
||||
|
||||
return d->scriptAccount->evaluateJavaScriptWithResult( QString(
|
||||
"if(resolverInstance['_adapter_%1']) {"
|
||||
" resolverInstance._adapter_%2;"
|
||||
"} else {"
|
||||
" resolverInstance.%2;"
|
||||
"}"
|
||||
).arg( propertyName ).arg( scriptSource ) );
|
||||
}
|
||||
|
@@ -75,8 +75,6 @@ public:
|
||||
|
||||
ScriptAccount* scriptAccount() const;
|
||||
|
||||
ScriptJob* getStreamUrl( const result_ptr& result ) override;
|
||||
|
||||
public slots:
|
||||
void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
void stop() override;
|
||||
@@ -91,10 +89,6 @@ signals:
|
||||
protected:
|
||||
QVariant callOnResolver( const QString& scriptSource );
|
||||
|
||||
private slots:
|
||||
void onResolveRequestDone(const QVariantMap& data);
|
||||
void onLookupUrlRequestDone(const QVariantMap& data);
|
||||
|
||||
private:
|
||||
void init();
|
||||
|
||||
@@ -102,20 +96,12 @@ private:
|
||||
void onCapabilitiesChanged( Capabilities capabilities );
|
||||
|
||||
// encapsulate javascript calls
|
||||
QVariantMap resolverSettings();
|
||||
QVariantMap resolverUserConfig();
|
||||
QVariantMap resolverInit();
|
||||
|
||||
Q_DECLARE_PRIVATE( JSResolver )
|
||||
QScopedPointer<JSResolverPrivate> d_ptr;
|
||||
|
||||
|
||||
// TODO: move lookupUrl stuff to its own plugin type
|
||||
QString instanceUUID();
|
||||
static Tomahawk::query_ptr parseTrack( const QVariantMap& track );
|
||||
QString m_pendingUrl;
|
||||
Tomahawk::album_ptr m_pendingAlbum;
|
||||
private slots:
|
||||
void tracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::ModelMode, const Tomahawk::collection_ptr& collection );
|
||||
void pltemplateTracksLoadedForUrl( const QString& url, const Tomahawk::playlisttemplate_ptr& pltemplate );
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
@@ -21,6 +21,10 @@
|
||||
|
||||
#include "JSResolverHelper.h"
|
||||
|
||||
#include "database/Database.h"
|
||||
#include "database/DatabaseImpl.h"
|
||||
#include "playlist/PlaylistTemplate.h"
|
||||
#include "playlist/XspfPlaylistTemplate.h"
|
||||
#include "resolvers/ScriptEngine.h"
|
||||
#include "network/Servent.h"
|
||||
#include "utils/Closure.h"
|
||||
@@ -47,8 +51,6 @@
|
||||
#include <QMap>
|
||||
#include <QWebFrame>
|
||||
#include <QLocale>
|
||||
#include <QNetworkReply>
|
||||
|
||||
#include <taglib/asffile.h>
|
||||
#include <taglib/flacfile.h>
|
||||
#include <taglib/id3v2framefactory.h>
|
||||
@@ -74,25 +76,11 @@ JSResolverHelper::JSResolverHelper( const QString& scriptPath, JSResolver* paren
|
||||
: QObject( parent )
|
||||
, m_resolver( parent )
|
||||
, m_scriptPath( scriptPath )
|
||||
, m_stopped( false )
|
||||
, m_urlCallbackIsAsync( false )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::start()
|
||||
{
|
||||
m_stopped = false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::stop()
|
||||
{
|
||||
m_stopped = true;
|
||||
}
|
||||
|
||||
|
||||
QByteArray
|
||||
JSResolverHelper::readRaw( const QString& fileName )
|
||||
{
|
||||
@@ -152,6 +140,55 @@ JSResolverHelper::log( const QString& message )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::addTrackResults( const QVariantMap& results )
|
||||
{
|
||||
Q_ASSERT( results["results"].toMap().isEmpty() );
|
||||
|
||||
QList< Tomahawk::result_ptr > tracks = m_resolver->scriptAccount()->parseResultVariantList( results.value( "results" ).toList() );
|
||||
|
||||
foreach( const result_ptr& track, tracks )
|
||||
{
|
||||
track->setResolvedByResolver( m_resolver );
|
||||
track->setFriendlySource( m_resolver->name() );
|
||||
}
|
||||
|
||||
QString qid = results.value("qid").toString();
|
||||
|
||||
Tomahawk::Pipeline::instance()->reportResults( qid, m_resolver, tracks );
|
||||
}
|
||||
|
||||
|
||||
query_ptr
|
||||
JSResolverHelper::parseTrack( const QVariantMap& track )
|
||||
{
|
||||
QString title = track.value( "title" ).toString();
|
||||
QString artist = track.value( "artist" ).toString();
|
||||
QString album = track.value( "album" ).toString();
|
||||
if ( title.isEmpty() || artist.isEmpty() )
|
||||
{
|
||||
return query_ptr();
|
||||
}
|
||||
|
||||
Tomahawk::query_ptr query = Tomahawk::Query::get( artist, title, album );
|
||||
QString resultHint = track.value( "hint" ).toString();
|
||||
if ( !resultHint.isEmpty() )
|
||||
{
|
||||
query->setResultHint( resultHint );
|
||||
query->setSaveHTTPResultHint( true );
|
||||
}
|
||||
|
||||
return query;
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSResolverHelper::instanceUUID()
|
||||
{
|
||||
return Tomahawk::Database::instance()->impl()->dbid();
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
JSResolverHelper::uuid() const
|
||||
{
|
||||
@@ -446,13 +483,123 @@ JSResolverHelper::currentCountry() const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::addUrlResult( const QString& url, const QVariantMap& result )
|
||||
{
|
||||
// It may seem a bit weird, but currently no slot should do anything
|
||||
// more as we starting on a new URL and not task are waiting for it yet.
|
||||
m_pendingUrl = QString();
|
||||
m_pendingAlbum = album_ptr();
|
||||
|
||||
QString type = result.value( "type" ).toString();
|
||||
if ( type == "artist" )
|
||||
{
|
||||
QString name = result.value( "name" ).toString();
|
||||
Q_ASSERT( !name.isEmpty() );
|
||||
emit m_resolver->informationFound( url, Artist::get( name, true ).objectCast<QObject>() );
|
||||
}
|
||||
else if ( type == "album" )
|
||||
{
|
||||
QString name = result.value( "name" ).toString();
|
||||
QString artist = result.value( "artist" ).toString();
|
||||
album_ptr album = Album::get( Artist::get( artist, true ), name );
|
||||
m_pendingUrl = url;
|
||||
m_pendingAlbum = album;
|
||||
connect( album.data(), SIGNAL( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ),
|
||||
SLOT( tracksAdded( QList<Tomahawk::query_ptr>, Tomahawk::ModelMode, Tomahawk::collection_ptr ) ) );
|
||||
if ( !album->tracks().isEmpty() )
|
||||
{
|
||||
emit m_resolver->informationFound( url, album.objectCast<QObject>() );
|
||||
}
|
||||
}
|
||||
else if ( type == "track" )
|
||||
{
|
||||
Tomahawk::query_ptr query = parseTrack( result );
|
||||
if ( query.isNull() )
|
||||
{
|
||||
// A valid track result shoud have non-empty title and artist.
|
||||
tLog() << Q_FUNC_INFO << m_resolver->name() << "Got empty track information for " << url;
|
||||
emit m_resolver->informationFound( url, QSharedPointer<QObject>() );
|
||||
}
|
||||
else
|
||||
{
|
||||
emit m_resolver->informationFound( url, query.objectCast<QObject>() );
|
||||
}
|
||||
}
|
||||
else if ( type == "playlist" )
|
||||
{
|
||||
QString guid = result.value( "guid" ).toString();
|
||||
Q_ASSERT( !guid.isEmpty() );
|
||||
// Append nodeid to guid to make it globally unique.
|
||||
guid += instanceUUID();
|
||||
|
||||
// Do we already have this playlist loaded?
|
||||
{
|
||||
playlist_ptr playlist = Playlist::get( guid );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
emit m_resolver->informationFound( url, playlist.objectCast<QObject>() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Get all information to build a new playlist but do not build it until we know,
|
||||
// if it is really handled as a playlist and not as a set of tracks.
|
||||
Tomahawk::source_ptr source = SourceList::instance()->getLocal();
|
||||
const QString title = result.value( "title" ).toString();
|
||||
const QString info = result.value( "info" ).toString();
|
||||
const QString creator = result.value( "creator" ).toString();
|
||||
QList<query_ptr> queries;
|
||||
foreach( QVariant track, result.value( "tracks" ).toList() )
|
||||
{
|
||||
query_ptr query = parseTrack( track.toMap() );
|
||||
if ( !query.isNull() )
|
||||
{
|
||||
queries << query;
|
||||
}
|
||||
}
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << m_resolver->name() << "Got playlist for " << url;
|
||||
playlisttemplate_ptr pltemplate( new PlaylistTemplate( source, guid, title, info, creator, false, queries ) );
|
||||
emit m_resolver->informationFound( url, pltemplate.objectCast<QObject>() );
|
||||
}
|
||||
else if ( type == "xspf-url" )
|
||||
{
|
||||
QString xspfUrl = result.value( "url" ).toString();
|
||||
Q_ASSERT( !xspfUrl.isEmpty() );
|
||||
QString guid = QString( "xspf-%1-%2" ).arg( xspfUrl.toUtf8().toBase64().constData() ).arg( instanceUUID() );
|
||||
|
||||
// Do we already have this playlist loaded?
|
||||
{
|
||||
playlist_ptr playlist = Playlist::get( guid );
|
||||
if ( !playlist.isNull() )
|
||||
{
|
||||
emit m_resolver->informationFound( url, playlist.objectCast<QObject>() );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get all information to build a new playlist but do not build it until we know,
|
||||
// if it is really handled as a playlist and not as a set of tracks.
|
||||
Tomahawk::source_ptr source = SourceList::instance()->getLocal();
|
||||
QSharedPointer<XspfPlaylistTemplate> pltemplate( new XspfPlaylistTemplate( xspfUrl, source, guid ) );
|
||||
NewClosure( pltemplate, SIGNAL( tracksLoaded( QList< Tomahawk::query_ptr > ) ),
|
||||
this, SLOT( pltemplateTracksLoadedForUrl( QString, Tomahawk::playlisttemplate_ptr ) ),
|
||||
url, pltemplate.objectCast<Tomahawk::PlaylistTemplate>() );
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << m_resolver->name() << "Got playlist for " << url;
|
||||
pltemplate->load();
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog( LOGVERBOSE ) << Q_FUNC_INFO << m_resolver->name() << "No usable information found for " << url;
|
||||
emit m_resolver->informationFound( url, QSharedPointer<QObject>() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::nativeReportCapabilities( const QVariant& v )
|
||||
{
|
||||
if( m_stopped )
|
||||
return;
|
||||
|
||||
|
||||
bool ok;
|
||||
int intCap = v.toInt( &ok );
|
||||
Tomahawk::ExternalResolver::Capabilities capabilities;
|
||||
@@ -468,9 +615,6 @@ JSResolverHelper::nativeReportCapabilities( const QVariant& v )
|
||||
void
|
||||
JSResolverHelper::reportScriptJobResults( const QVariantMap& result )
|
||||
{
|
||||
if( m_stopped )
|
||||
return;
|
||||
|
||||
m_resolver->d_func()->scriptAccount->reportScriptJobResult( result );
|
||||
}
|
||||
|
||||
@@ -478,9 +622,6 @@ JSResolverHelper::reportScriptJobResults( const QVariantMap& result )
|
||||
void
|
||||
JSResolverHelper::registerScriptPlugin( const QString& type, const QString& objectId )
|
||||
{
|
||||
if( m_stopped )
|
||||
return;
|
||||
|
||||
m_resolver->d_func()->scriptAccount->registerScriptPlugin( type, objectId );
|
||||
}
|
||||
|
||||
@@ -488,10 +629,28 @@ JSResolverHelper::registerScriptPlugin( const QString& type, const QString& obje
|
||||
void
|
||||
JSResolverHelper::unregisterScriptPlugin( const QString& type, const QString& objectId )
|
||||
{
|
||||
if( m_stopped )
|
||||
m_resolver->d_func()->scriptAccount->unregisterScriptPlugin( type, objectId );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::tracksAdded( const QList<query_ptr>&, const ModelMode, const collection_ptr&)
|
||||
{
|
||||
// Check if we still are actively waiting
|
||||
if ( m_pendingAlbum.isNull() || m_pendingUrl.isNull() )
|
||||
return;
|
||||
|
||||
m_resolver->d_func()->scriptAccount->unregisterScriptPlugin( type, objectId );
|
||||
emit m_resolver->informationFound( m_pendingUrl, m_pendingAlbum.objectCast<QObject>() );
|
||||
m_pendingAlbum = album_ptr();
|
||||
m_pendingUrl = QString();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::pltemplateTracksLoadedForUrl( const QString& url, const playlisttemplate_ptr& pltemplate )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO;
|
||||
emit m_resolver->informationFound( url, pltemplate.objectCast<QObject>() );
|
||||
}
|
||||
|
||||
|
||||
@@ -509,6 +668,31 @@ JSResolverHelper::accountId()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::addCustomUrlHandler( const QString& protocol,
|
||||
const QString& callbackFuncName,
|
||||
const QString& isAsynchronous )
|
||||
{
|
||||
m_urlCallbackIsAsync = ( isAsynchronous.toLower() == "true" );
|
||||
|
||||
std::function< void( const Tomahawk::result_ptr&, const QString&,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > )> fac =
|
||||
std::bind( &JSResolverHelper::customIODeviceFactory, this,
|
||||
std::placeholders::_1, std::placeholders::_2,
|
||||
std::placeholders::_3 );
|
||||
Tomahawk::UrlHandler::registerIODeviceFactory( protocol, fac );
|
||||
|
||||
m_urlCallback = callbackFuncName;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::reportStreamUrl( const QString& qid, const QString& streamUrl )
|
||||
{
|
||||
reportStreamUrl( qid, streamUrl, QVariantMap() );
|
||||
}
|
||||
|
||||
|
||||
void JSResolverHelper::nativeAssert( bool assertion, const QString& message )
|
||||
{
|
||||
if ( !assertion )
|
||||
@@ -519,6 +703,61 @@ void JSResolverHelper::nativeAssert( bool assertion, const QString& message )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::customIODeviceFactory( const Tomahawk::result_ptr&, const QString& url,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback )
|
||||
{
|
||||
//can be sync or async
|
||||
if ( m_urlCallbackIsAsync )
|
||||
{
|
||||
QString qid = uuid();
|
||||
QString getUrl = QString(
|
||||
"if(resolverInstance['_adapter_%1']) {"
|
||||
" resolverInstance._adapter_%1( {qid: '%2', url: '%3'} );"
|
||||
"} else {"
|
||||
" resolverInstance.%1( {qid: '%2', url: '%3'} );"
|
||||
"}"
|
||||
).arg( m_urlCallback )
|
||||
.arg( qid )
|
||||
.arg( url );
|
||||
|
||||
m_streamCallbacks.insert( qid, callback );
|
||||
m_resolver->d_func()->scriptAccount->evaluateJavaScript( getUrl );
|
||||
}
|
||||
else
|
||||
{
|
||||
QString getUrl = QString( "resolverInstance.%1( '%2' );" ).arg( m_urlCallback )
|
||||
.arg( url );
|
||||
|
||||
QString urlStr = m_resolver->d_func()->scriptAccount->evaluateJavaScriptWithResult( getUrl ).toString();
|
||||
|
||||
returnStreamUrl( urlStr, QMap<QString, QString>(), callback );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::reportStreamUrl( const QString& qid, const QString& streamUrl, const QVariantMap& headers )
|
||||
{
|
||||
if ( !m_streamCallbacks.contains( qid ) )
|
||||
return;
|
||||
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback = m_streamCallbacks.take( qid );
|
||||
|
||||
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() );
|
||||
}
|
||||
}
|
||||
|
||||
returnStreamUrl( streamUrl, parsedHeaders, callback );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::nativeRetrieveMetadata( int metadataId, const QString& url,
|
||||
const QString& mime_type, int sizehint,
|
||||
@@ -657,27 +896,12 @@ JSResolverHelper::nativeRetrieveMetadata( int metadataId, const QString& url,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
JSResolverHelper::invokeNativeScriptJob( int requestId, const QString& methodName, const QVariantMap& params )
|
||||
{
|
||||
if ( methodName == "httpRequest" ) {
|
||||
nativeAsyncRequest( requestId, params );
|
||||
} else {
|
||||
QVariantMap error;
|
||||
error["message"] = "NativeScriptJob methodName was not found";
|
||||
error["name"] = "method_was_not_found";
|
||||
|
||||
m_resolver->d_func()->scriptAccount->reportNativeScriptJobError( requestId, error );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::nativeAsyncRequest( const int requestId, const QVariantMap& options )
|
||||
JSResolverHelper::nativeAsyncRequest( const int requestId, const QString& url,
|
||||
const QVariantMap& headers,
|
||||
const QVariantMap& options )
|
||||
{
|
||||
QString url = options[ "url" ].toString();
|
||||
QVariantMap headers = options[ "headers" ].toMap();
|
||||
|
||||
QNetworkRequest req( url );
|
||||
foreach ( const QString& key, headers.keys() )
|
||||
{
|
||||
@@ -733,16 +957,17 @@ JSResolverHelper::nativeAsyncRequestDone( int requestId, NetworkReply* reply )
|
||||
map["status"] = reply->reply()->attribute( QNetworkRequest::HttpStatusCodeAttribute ).toInt();
|
||||
map["statusText"] = QString("%1 %2").arg( map["status"].toString() )
|
||||
.arg( reply->reply()->attribute( QNetworkRequest::HttpReasonPhraseAttribute ).toString() );
|
||||
if (reply->reply()->hasRawHeader( "Content-Type" ))
|
||||
map["contentType"] = reply->reply()->rawHeader( "Content-Type" );
|
||||
|
||||
bool ok = false;
|
||||
QString json = QString::fromUtf8( TomahawkUtils::toJson( map, &ok ) );
|
||||
Q_ASSERT( ok );
|
||||
|
||||
QVariantMap responseHeaders;
|
||||
foreach( const QNetworkReply::RawHeaderPair& pair, reply->reply()->rawHeaderPairs() )
|
||||
{
|
||||
responseHeaders[ pair.first ] = pair.second;
|
||||
}
|
||||
map["responseHeaders"] = responseHeaders;
|
||||
|
||||
m_resolver->d_func()->scriptAccount->reportNativeScriptJobResult( requestId, map );
|
||||
QString javascript = QString( "Tomahawk.nativeAsyncRequestDone( %1, %2 );" )
|
||||
.arg( QString::number( requestId ) )
|
||||
.arg( json );
|
||||
m_resolver->d_func()->scriptAccount->evaluateJavaScript( javascript );
|
||||
}
|
||||
|
||||
|
||||
@@ -918,3 +1143,43 @@ JSResolverHelper::readdResolver()
|
||||
Pipeline::instance()->addResolver( m_resolver );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
JSResolverHelper::returnStreamUrl( const QString& streamUrl, const QMap<QString, QString>& headers,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback )
|
||||
{
|
||||
if ( streamUrl.isEmpty() || !( TomahawkUtils::isHttpResult( streamUrl ) || TomahawkUtils::isHttpsResult( streamUrl ) ) )
|
||||
{
|
||||
// Not an https? URL, so let Phonon handle it
|
||||
QSharedPointer< QIODevice > sp;
|
||||
callback( streamUrl, sp );
|
||||
}
|
||||
else
|
||||
{
|
||||
QUrl url = QUrl::fromEncoded( streamUrl.toUtf8() );
|
||||
QNetworkRequest req( url );
|
||||
foreach ( const QString& key, headers.keys() )
|
||||
{
|
||||
req.setRawHeader( key.toLatin1(), headers[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( gotStreamUrl( IODeviceCallback, NetworkReply* )), callback, reply );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Q_DECLARE_METATYPE( IODeviceCallback )
|
||||
|
||||
void
|
||||
JSResolverHelper::gotStreamUrl( std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback, NetworkReply* reply )
|
||||
{
|
||||
// std::functions cannot accept temporaries as parameters
|
||||
QSharedPointer< QIODevice > sp ( reply->reply(), &QObject::deleteLater );
|
||||
QString url = reply->reply()->url().toString();
|
||||
reply->disconnectFromReply();
|
||||
reply->deleteLater();
|
||||
|
||||
callback( url, sp );
|
||||
}
|
||||
|
@@ -54,9 +54,6 @@ public:
|
||||
*/
|
||||
void setResolverConfig( const QVariantMap& config );
|
||||
|
||||
void start();
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Get the instance unique account id for this resolver.
|
||||
*
|
||||
@@ -64,6 +61,9 @@ public:
|
||||
*/
|
||||
Q_INVOKABLE QString accountId();
|
||||
|
||||
Q_INVOKABLE void addCustomUrlHandler( const QString& protocol, const QString& callbackFuncName, const QString& isAsynchronous = "false" );
|
||||
Q_INVOKABLE void reportStreamUrl( const QString& qid, const QString& streamUrl );
|
||||
Q_INVOKABLE void reportStreamUrl( const QString& qid, const QString& streamUrl, const QVariantMap& headers );
|
||||
|
||||
/**
|
||||
* Make Tomahawk assert the assertion is true, probably not to be used by resolvers directly
|
||||
@@ -89,9 +89,20 @@ public:
|
||||
int sizehint,
|
||||
const QVariantMap& options );
|
||||
|
||||
Q_INVOKABLE void invokeNativeScriptJob( int requestId,
|
||||
const QString& methodName,
|
||||
const QVariantMap& params );
|
||||
/**
|
||||
* Native handler for asynchronous HTTP requests.
|
||||
*
|
||||
* This handler shall only be used if we cannot achieve the request with
|
||||
* XMLHttpRequest as that would be more efficient.
|
||||
* Use cases are:
|
||||
* * Referer header: Stripped on MacOS and the specification says it
|
||||
* should be stripped
|
||||
*
|
||||
* INTERNAL USE ONLY!
|
||||
*/
|
||||
Q_INVOKABLE void nativeAsyncRequest( int requestId, const QString& url,
|
||||
const QVariantMap& headers,
|
||||
const QVariantMap& options );
|
||||
|
||||
/**
|
||||
* Lucene++ indices for JS resolvers
|
||||
@@ -111,10 +122,18 @@ public:
|
||||
Q_INVOKABLE void readdResolver();
|
||||
|
||||
|
||||
/**
|
||||
* INTERNAL USE ONLY!
|
||||
*/
|
||||
void customIODeviceFactory( const Tomahawk::result_ptr&, const QString& url,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback ); // async
|
||||
|
||||
|
||||
public slots:
|
||||
QByteArray readRaw( const QString& fileName );
|
||||
QString readBase64( const QString& fileName );
|
||||
QString readCompressed( const QString& fileName );
|
||||
QString instanceUUID();
|
||||
QString uuid() const;
|
||||
int currentCountry() const;
|
||||
QString compress( const QString& data );
|
||||
@@ -123,6 +142,10 @@ public slots:
|
||||
void log( const QString& message );
|
||||
bool fakeEnv() { return false; }
|
||||
|
||||
void addTrackResults( const QVariantMap& results );
|
||||
|
||||
void addUrlResult( const QString& url, const QVariantMap& result );
|
||||
|
||||
void nativeReportCapabilities( const QVariant& capabilities );
|
||||
|
||||
void reportScriptJobResults( const QVariantMap& result );
|
||||
@@ -131,20 +154,27 @@ public slots:
|
||||
void unregisterScriptPlugin( const QString& type, const QString& objectId );
|
||||
|
||||
private slots:
|
||||
void gotStreamUrl( IODeviceCallback callback, NetworkReply* reply );
|
||||
void tracksAdded( const QList<Tomahawk::query_ptr>& tracks, const Tomahawk::ModelMode, const Tomahawk::collection_ptr& collection );
|
||||
void pltemplateTracksLoadedForUrl( const QString& url, const Tomahawk::playlisttemplate_ptr& pltemplate );
|
||||
void nativeAsyncRequestDone( int requestId, NetworkReply* reply );
|
||||
|
||||
private:
|
||||
Tomahawk::query_ptr parseTrack( const QVariantMap& track );
|
||||
void returnStreamUrl( const QString& streamUrl, const QMap<QString, QString>& headers,
|
||||
std::function< void( const QString&, QSharedPointer< QIODevice >& ) > callback );
|
||||
|
||||
bool indexDataFromVariant( const QVariantMap& map, struct Tomahawk::IndexData& indexData );
|
||||
QVariantList searchInFuzzyIndex( const Tomahawk::query_ptr& query );
|
||||
|
||||
// native script jobs
|
||||
void nativeAsyncRequest( int requestId, const QVariantMap& options );
|
||||
|
||||
|
||||
QVariantMap m_resolverConfig;
|
||||
JSResolver* m_resolver;
|
||||
QString m_scriptPath;
|
||||
bool m_stopped;
|
||||
QString m_scriptPath, m_urlCallback, m_urlTranslator;
|
||||
QHash< QString, std::function< void( const QString&, QSharedPointer< QIODevice >& ) > > m_streamCallbacks;
|
||||
QHash< QString, std::function< void( const QString& ) > > m_translatorCallbacks;
|
||||
bool m_urlCallbackIsAsync;
|
||||
QString m_pendingUrl;
|
||||
Tomahawk::album_ptr m_pendingAlbum;
|
||||
};
|
||||
|
||||
} // ns: Tomahawk
|
||||
|
@@ -17,31 +17,10 @@
|
||||
*/
|
||||
#include "Resolver.h"
|
||||
|
||||
#include "../resolvers/SyncScriptJob.h"
|
||||
#include "../Result.h"
|
||||
|
||||
#include <QPixmap>
|
||||
|
||||
|
||||
Tomahawk::Resolver::Resolver( QObject* parent )
|
||||
: QObject( parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QPixmap
|
||||
Tomahawk::Resolver::icon( const QSize& ) const
|
||||
{
|
||||
Q_ASSERT(false);
|
||||
return QPixmap();
|
||||
}
|
||||
|
||||
|
||||
Tomahawk::ScriptJob*
|
||||
Tomahawk::Resolver::getStreamUrl( const result_ptr& result )
|
||||
{
|
||||
QVariantMap data;
|
||||
data[ "url" ] = result->url();
|
||||
|
||||
return new SyncScriptJob( data );
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#ifndef RESOLVER_H
|
||||
#define RESOLVER_H
|
||||
|
||||
#include "../ResultProvider.h"
|
||||
#include "Typedefs.h"
|
||||
#include "DllMacro.h"
|
||||
|
||||
@@ -35,23 +36,21 @@
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
class ScriptJob;
|
||||
|
||||
class DLLEXPORT Resolver : public QObject
|
||||
class DLLEXPORT Resolver : public QObject, public ResultProvider
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Resolver( QObject* parent = nullptr );
|
||||
|
||||
virtual QString name() const = 0;
|
||||
virtual QPixmap icon( const QSize& size ) const;
|
||||
Resolver() {}
|
||||
|
||||
virtual unsigned int weight() const = 0;
|
||||
virtual unsigned int timeout() const = 0;
|
||||
|
||||
virtual QPixmap icon( const QSize& size ) const override;
|
||||
|
||||
public slots:
|
||||
virtual void resolve( const Tomahawk::query_ptr& query ) = 0;
|
||||
virtual ScriptJob* getStreamUrl( const result_ptr& result );
|
||||
};
|
||||
|
||||
} //ns
|
||||
|
@@ -32,8 +32,6 @@
|
||||
#include "ScriptInfoPlugin.h"
|
||||
|
||||
// TODO:
|
||||
#include "../Artist.h"
|
||||
#include "../Album.h"
|
||||
#include "../Result.h"
|
||||
#include "../Track.h"
|
||||
#include <QTime>
|
||||
@@ -203,10 +201,6 @@ ScriptAccount::unregisterScriptPlugin( const QString& type, const QString& objec
|
||||
{
|
||||
m_infoPluginFactory->unregisterPlugin( object );
|
||||
}
|
||||
else if( type == "linkParser" )
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
else
|
||||
{
|
||||
tLog() << "This plugin type is not handled by Tomahawk or simply cannot be removed yet";
|
||||
@@ -237,10 +231,6 @@ ScriptAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr&
|
||||
ScriptLinkGeneratorPlugin* lgp = new ScriptLinkGeneratorPlugin( object );
|
||||
Utils::LinkGenerator::instance()->addPlugin( lgp );
|
||||
}
|
||||
else if( type == "linkParser" )
|
||||
{
|
||||
tLog() << "Plugin registered linkParser, which is not implemented yet. UrlLookup won't work";
|
||||
}
|
||||
else if ( type == "infoPlugin" )
|
||||
{
|
||||
m_infoPluginFactory->registerPlugin( object, this );
|
||||
@@ -257,12 +247,6 @@ ScriptAccount::scriptPluginFactory( const QString& type, const scriptobject_ptr&
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptAccount::showDebugger()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptAccount::onJobDeleted( const QString& jobId )
|
||||
{
|
||||
@@ -270,67 +254,15 @@ ScriptAccount::onJobDeleted( const QString& jobId )
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::artist_ptr >
|
||||
ScriptAccount::parseArtistVariantList( const QVariantList& artistList )
|
||||
{
|
||||
QList< Tomahawk::artist_ptr > artists;
|
||||
|
||||
QString artist;
|
||||
foreach( const QVariant& a, artistList )
|
||||
{
|
||||
artist = a.toString().trimmed();
|
||||
if ( artist.isEmpty() )
|
||||
continue;
|
||||
|
||||
artists << Tomahawk::Artist::get( artist );
|
||||
}
|
||||
|
||||
return artists;
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::album_ptr >
|
||||
ScriptAccount::parseAlbumVariantList( const QVariantList& albumList )
|
||||
{
|
||||
QList< Tomahawk::album_ptr > albums;
|
||||
|
||||
QString artistString;
|
||||
QString albumString;
|
||||
foreach( const QVariant& av, albumList )
|
||||
{
|
||||
QVariantMap m = av.toMap();
|
||||
|
||||
artistString = m.value( "artist" ).toString().trimmed();
|
||||
albumString = m.value( "album" ).toString().trimmed();
|
||||
if ( artistString.isEmpty() || albumString.isEmpty() )
|
||||
continue;
|
||||
|
||||
albums << Tomahawk::Album::get( Tomahawk::Artist::get( artistString ), albumString );
|
||||
}
|
||||
|
||||
return albums;
|
||||
}
|
||||
|
||||
|
||||
QList< Tomahawk::result_ptr >
|
||||
ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
{
|
||||
QList< Tomahawk::result_ptr > results;
|
||||
|
||||
|
||||
foreach( const QVariant& rv, reslist )
|
||||
{
|
||||
QVariantMap m = rv.toMap();
|
||||
|
||||
const QString artistString = m.value("artist").toString().trimmed();
|
||||
const QString trackString = m.value("track").toString().trimmed();
|
||||
|
||||
if ( artistString.isEmpty() || trackString.isEmpty() )
|
||||
{
|
||||
tLog() << Q_FUNC_INFO << "Could not parse Track" << m;
|
||||
continue;
|
||||
}
|
||||
|
||||
int duration = m.value( "duration", 0 ).toInt();
|
||||
if ( duration <= 0 && m.contains( "durationString" ) )
|
||||
{
|
||||
@@ -338,8 +270,8 @@ ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
duration = time.secsTo( QTime( 0, 0 ) ) * -1;
|
||||
}
|
||||
|
||||
Tomahawk::track_ptr track = Tomahawk::Track::get( artistString,
|
||||
trackString,
|
||||
Tomahawk::track_ptr track = Tomahawk::Track::get( m.value( "artist" ).toString(),
|
||||
m.value( "track" ).toString(),
|
||||
m.value( "album" ).toString(),
|
||||
m.value( "albumArtist" ).toString(),
|
||||
duration,
|
||||
@@ -394,6 +326,21 @@ ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
}
|
||||
rp->setDownloadFormats( fl );
|
||||
|
||||
// find collection
|
||||
const QString collectionId = m.value( "collectionId" ).toString();
|
||||
if ( !collectionId.isEmpty() )
|
||||
{
|
||||
if ( scriptCollection( collectionId ).isNull() )
|
||||
{
|
||||
tLog() << "Resolver returned invalid collection id";
|
||||
Q_ASSERT( false );
|
||||
}
|
||||
else
|
||||
{
|
||||
rp->setResolvedByCollection( scriptCollection( collectionId ) );
|
||||
}
|
||||
}
|
||||
|
||||
results << rp;
|
||||
}
|
||||
|
||||
@@ -401,29 +348,8 @@ ScriptAccount::parseResultVariantList( const QVariantList& reslist )
|
||||
}
|
||||
|
||||
|
||||
ScriptJob*
|
||||
ScriptAccount::resolve( const scriptobject_ptr& scriptObject, const query_ptr& query, const QString& resolveType )
|
||||
QSharedPointer< ScriptCollection >
|
||||
ScriptAccount::scriptCollection( const QString& id ) const
|
||||
{
|
||||
ScriptJob* job = nullptr;
|
||||
if ( !query->isFullTextQuery() )
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["artist"] = query->queryTrack()->artist();
|
||||
arguments["album"] = query->queryTrack()->album();
|
||||
arguments["track"] = query->queryTrack()->track();
|
||||
arguments["type"] = resolveType;
|
||||
|
||||
job = scriptObject->invoke( "resolve", arguments );
|
||||
}
|
||||
else
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["query"] = query->fullTextQuery();
|
||||
arguments["type"] = resolveType;
|
||||
job = scriptObject->invoke( "search", arguments );
|
||||
}
|
||||
|
||||
job->setProperty( "qid", query->id() );
|
||||
|
||||
return job;
|
||||
return m_collectionFactory->scriptPlugins().value( id );
|
||||
}
|
||||
|
@@ -65,24 +65,18 @@ public:
|
||||
|
||||
ScriptJob* invoke( const scriptobject_ptr& scriptObject, const QString& methodName, const QVariantMap& arguments );
|
||||
virtual QVariant syncInvoke( const scriptobject_ptr& scriptObject, const QString& methodName, const QVariantMap& arguments ) = 0;
|
||||
|
||||
virtual void startJob( ScriptJob* scriptJob ) = 0;
|
||||
|
||||
void reportScriptJobResult( const QVariantMap& result );
|
||||
void registerScriptPlugin( const QString& type, const QString& objectId );
|
||||
void unregisterScriptPlugin( const QString& type, const QString& objectId );
|
||||
|
||||
virtual void reportNativeScriptJobResult( int resultId, const QVariantMap& result ) = 0;
|
||||
virtual void reportNativeScriptJobError( int resultId, const QVariantMap& error ) = 0;
|
||||
|
||||
virtual void scriptPluginFactory( const QString& type, const scriptobject_ptr& object );
|
||||
|
||||
virtual void showDebugger();
|
||||
|
||||
// helpers
|
||||
QList< Tomahawk::artist_ptr > parseArtistVariantList( const QVariantList& artistList );
|
||||
QList< Tomahawk::album_ptr > parseAlbumVariantList( const QVariantList& albumList );
|
||||
QList< Tomahawk::result_ptr > parseResultVariantList( const QVariantList& reslist );
|
||||
ScriptJob* resolve( const scriptobject_ptr& scriptObject, const query_ptr& query, const QString& resolveType );
|
||||
|
||||
QSharedPointer< ScriptCollection > scriptCollection( const QString& id ) const;
|
||||
|
||||
private slots:
|
||||
void onJobDeleted( const QString& jobId );
|
||||
|
@@ -26,10 +26,7 @@
|
||||
#include "resolvers/ScriptCommand_AllArtists.h"
|
||||
#include "resolvers/ScriptCommand_AllAlbums.h"
|
||||
#include "resolvers/ScriptCommand_AllTracks.h"
|
||||
#include "resolvers/ScriptJob.h"
|
||||
#include "ScriptAccount.h"
|
||||
#include "Result.h"
|
||||
#include "Pipeline.h"
|
||||
|
||||
#include <QImageReader>
|
||||
#include <QPainter>
|
||||
@@ -226,15 +223,6 @@ void ScriptCollection::parseMetaData()
|
||||
return parseMetaData( readMetaData() );
|
||||
}
|
||||
|
||||
ScriptJob*
|
||||
ScriptCollection::getStreamUrl( const result_ptr& result )
|
||||
{
|
||||
QVariantMap arguments;
|
||||
arguments["url"] = result->url();
|
||||
|
||||
return scriptObject()->invoke( "getStreamUrl", arguments );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptCollection::parseMetaData( const QVariantMap& metadata )
|
||||
@@ -338,58 +326,3 @@ ScriptCollection::onIconFetched()
|
||||
reply->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
ScriptCollection::timeout() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
ScriptCollection::weight() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptCollection::resolve( const Tomahawk::query_ptr& query )
|
||||
{
|
||||
ScriptJob* job = scriptAccount()->resolve( scriptObject(), query, "collection" );
|
||||
|
||||
connect( job, SIGNAL( done( QVariantMap ) ), SLOT( onResolveRequestDone( QVariantMap ) ) );
|
||||
|
||||
job->start();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptCollection::onResolveRequestDone( const QVariantMap& data )
|
||||
{
|
||||
Q_ASSERT( QThread::currentThread() == thread() );
|
||||
|
||||
ScriptJob* job = qobject_cast< ScriptJob* >( sender() );
|
||||
|
||||
QID qid = job->property( "qid" ).toString();
|
||||
|
||||
if ( job->error() )
|
||||
{
|
||||
Tomahawk::Pipeline::instance()->reportError( qid, this );
|
||||
}
|
||||
else
|
||||
{
|
||||
QList< Tomahawk::result_ptr > results = scriptAccount()->parseResultVariantList( data.value( "tracks" ).toList() );
|
||||
|
||||
foreach( const result_ptr& result, results )
|
||||
{
|
||||
result->setResolvedByCollection( weakRef().toStrongRef() );
|
||||
result->setFriendlySource( prettyName() );
|
||||
}
|
||||
|
||||
Tomahawk::Pipeline::instance()->reportResults( qid, this, results );
|
||||
}
|
||||
|
||||
sender()->deleteLater();
|
||||
}
|
||||
|
@@ -91,15 +91,8 @@ public:
|
||||
void parseMetaData();
|
||||
void parseMetaData( const QVariantMap& metadata );
|
||||
|
||||
// Resolver interface
|
||||
unsigned int weight() const override;
|
||||
unsigned int timeout() const override;
|
||||
void resolve( const Tomahawk::query_ptr& query ) override;
|
||||
ScriptJob* getStreamUrl( const result_ptr& result ) override;
|
||||
|
||||
private slots:
|
||||
void onIconFetched();
|
||||
void onResolveRequestDone( const QVariantMap& data );
|
||||
|
||||
private:
|
||||
ScriptAccount* m_scriptAccount;
|
||||
|
@@ -28,8 +28,6 @@
|
||||
#include "utils/Logger.h"
|
||||
#include "../Result.h"
|
||||
|
||||
#include <QtConcurrentRun>
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
ScriptCommand_AllTracks::ScriptCommand_AllTracks( const Tomahawk::collection_ptr& collection,
|
||||
@@ -119,22 +117,20 @@ ScriptCommand_AllTracks::onTracksJobDone( const QVariantMap& result )
|
||||
QSharedPointer< ScriptCollection > collection = m_collection.objectCast< ScriptCollection >();
|
||||
Q_ASSERT( !collection.isNull() );
|
||||
|
||||
QtConcurrent::run( [] ( ScriptCommand_AllTracks* t, ScriptJob* job, const QVariantMap& result, const QSharedPointer< ScriptCollection >& collection )
|
||||
QList< Tomahawk::result_ptr > t = collection->scriptAccount()->parseResultVariantList( result[ "results"].toList() );
|
||||
|
||||
|
||||
QList< Tomahawk::query_ptr > queries;
|
||||
foreach ( const Tomahawk::result_ptr& result, t )
|
||||
{
|
||||
QList< Tomahawk::result_ptr > results = collection->scriptAccount()->parseResultVariantList( result[ "tracks" ].toList() );
|
||||
result->setResolvedByCollection( m_collection );
|
||||
queries.append( result->toQuery() );
|
||||
}
|
||||
|
||||
QList< Tomahawk::query_ptr > queries;
|
||||
foreach ( const Tomahawk::result_ptr& result, results )
|
||||
{
|
||||
result->setResolvedByCollection( collection );
|
||||
queries.append( result->toQuery() );
|
||||
}
|
||||
tDebug() << Q_FUNC_INFO << "about to push" << queries.count() << "tracks";
|
||||
|
||||
tDebug() << Q_FUNC_INFO << "about to push" << queries.count() << "tracks";
|
||||
emit tracks( queries );
|
||||
emit done();
|
||||
|
||||
emit t->tracks( queries );
|
||||
emit t->done();
|
||||
|
||||
job->deleteLater();
|
||||
}, this, job, result, collection );
|
||||
job->deleteLater();
|
||||
}
|
||||
|
@@ -21,7 +21,7 @@
|
||||
|
||||
#include "ScriptEngine.h"
|
||||
|
||||
#include "jobview/ScriptErrorStatusMessage.h"
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "jobview/JobStatusModel.h"
|
||||
#include "jobview/JobStatusView.h"
|
||||
#include "utils/Logger.h"
|
||||
@@ -51,13 +51,13 @@ ScriptEngine::ScriptEngine( JSAccount* parent )
|
||||
settings()->setAttribute( QWebSettings::LocalContentCanAccessRemoteUrls, true );
|
||||
settings()->setOfflineStorageDefaultQuota(100 * 1024 * 1024 /* 100 Mb */);
|
||||
settings()->setOfflineWebApplicationCacheQuota(100 * 1024 * 1024 /* 100 Mb */);
|
||||
settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
|
||||
|
||||
// HACK
|
||||
QStringList cmdArgs = QCoreApplication::instance()->arguments();
|
||||
int position = cmdArgs.indexOf( "--show-inspector" ) + 1;
|
||||
if ( position > 0 && !cmdArgs.at( position ).isEmpty() && parent->name().contains( cmdArgs.at( position ), Qt::CaseInsensitive ) ) {
|
||||
QMetaObject::invokeMethod( this, "showWebInspector", Qt::QueuedConnection );
|
||||
settings()->setAttribute( QWebSettings::DeveloperExtrasEnabled, true );
|
||||
QMetaObject::invokeMethod( this, "initWebInspector", Qt::QueuedConnection );
|
||||
}
|
||||
|
||||
// Tomahawk is not a user agent
|
||||
@@ -74,13 +74,24 @@ ScriptEngine::ScriptEngine( JSAccount* parent )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptEngine::initWebInspector()
|
||||
{
|
||||
m_webInspector.reset( new QWebInspector() );
|
||||
m_webInspector->setPage( this );
|
||||
m_webInspector->setMinimumWidth( 800 );
|
||||
m_webInspector->setMinimumHeight( 600 );
|
||||
m_webInspector->show();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptEngine::javaScriptConsoleMessage( const QString& message, int lineNumber, const QString& sourceID )
|
||||
{
|
||||
tLog() << "JAVASCRIPT:" << QString( "%1:%2" ).arg( m_scriptPath ).arg( lineNumber ) << message << sourceID;
|
||||
#ifdef QT_DEBUG
|
||||
QFileInfo scriptPath( m_scriptPath );
|
||||
JobStatusView::instance()->model()->addJob( new ScriptErrorStatusMessage( tr( "%1:%2 %3" ).arg( scriptPath.fileName() ).arg( lineNumber ).arg( message ), m_parent ) );
|
||||
JobStatusView::instance()->model()->addJob( new ErrorStatusMessage( tr( "Resolver Error: %1:%2 %3" ).arg( scriptPath.fileName() ).arg( lineNumber ).arg( message ) ) );
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -137,21 +148,6 @@ ScriptEngine::setScriptPath( const QString& scriptPath )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptEngine::showWebInspector()
|
||||
{
|
||||
if ( m_webInspector.isNull() )
|
||||
{
|
||||
m_webInspector.reset( new QWebInspector() );
|
||||
m_webInspector->setPage( this );
|
||||
m_webInspector->setMinimumWidth( 800 );
|
||||
m_webInspector->setMinimumHeight( 600 );
|
||||
}
|
||||
|
||||
m_webInspector->show();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
ScriptEngine::shouldInterruptJavaScript()
|
||||
{
|
||||
|
@@ -49,13 +49,13 @@ public:
|
||||
|
||||
public slots:
|
||||
bool shouldInterruptJavaScript();
|
||||
void showWebInspector();
|
||||
|
||||
protected:
|
||||
virtual void javaScriptConsoleMessage( const QString& message, int lineNumber, const QString& sourceID );
|
||||
|
||||
private slots:
|
||||
void sslErrorHandler( QNetworkReply* qnr, const QList<QSslError>& errlist );
|
||||
void initWebInspector();
|
||||
|
||||
private:
|
||||
JSAccount* m_parent;
|
||||
|
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "SourceList.h"
|
||||
#include "../ScriptAccount.h"
|
||||
#include "../../Pipeline.h"
|
||||
|
||||
using namespace Tomahawk;
|
||||
|
||||
@@ -30,14 +29,12 @@ void ScriptCollectionFactory::addPlugin( const QSharedPointer<ScriptCollection>&
|
||||
|
||||
collection->setOnline( true );
|
||||
SourceList::instance()->addScriptCollection( collection );
|
||||
Pipeline::instance()->addResolver( collection.data() );
|
||||
}
|
||||
|
||||
void ScriptCollectionFactory::removePlugin( const QSharedPointer<ScriptCollection>& collection ) const
|
||||
{
|
||||
collection->setOnline( false );
|
||||
SourceList::instance()->removeScriptCollection( collection );
|
||||
Pipeline::instance()->removeResolver( collection.data() );
|
||||
}
|
||||
|
||||
QSharedPointer< ScriptCollection > ScriptCollectionFactory::createPlugin( const scriptobject_ptr& object, ScriptAccount* scriptAccount )
|
||||
|
@@ -25,14 +25,14 @@ using namespace Tomahawk;
|
||||
void
|
||||
ScriptInfoPluginFactory::addPlugin( const QSharedPointer< ScriptInfoPlugin >& infoPlugin ) const
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->addInfoPlugin( infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ScriptInfoPluginFactory::removePlugin( const QSharedPointer< ScriptInfoPlugin >& infoPlugin ) const
|
||||
{
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin );
|
||||
Tomahawk::InfoSystem::InfoSystem::instance()->removeInfoPlugin( infoPlugin.data() );
|
||||
}
|
||||
|
||||
|
||||
@@ -42,10 +42,10 @@ ScriptInfoPluginFactory::createPlugin( const scriptobject_ptr& object, ScriptAcc
|
||||
// create infoplugin instance
|
||||
ScriptInfoPlugin* scriptInfoPlugin = new ScriptInfoPlugin( object, scriptAccount->name() );
|
||||
|
||||
QSharedPointer< ScriptInfoPlugin > infoPlugin( scriptInfoPlugin );
|
||||
Tomahawk::InfoSystem::InfoPluginPtr infoPlugin( scriptInfoPlugin );
|
||||
|
||||
// move it to infosystem thread
|
||||
infoPlugin->moveToThread( Tomahawk::InfoSystem::InfoSystem::instance()->workerThread().data() );
|
||||
|
||||
return infoPlugin;
|
||||
return QSharedPointer< ScriptInfoPlugin >( scriptInfoPlugin );
|
||||
}
|
||||
|
@@ -320,11 +320,11 @@ filesizeToString( unsigned int size )
|
||||
|
||||
if ( mb )
|
||||
{
|
||||
return QString( "%1.%2 MB" ).arg( mb ).arg( int( ( kb % 1024 ) / 102.4 ) );
|
||||
return QString( "%1.%2 Mb" ).arg( mb ).arg( int( ( kb % 1024 ) / 102.4 ) );
|
||||
}
|
||||
else if ( kb )
|
||||
{
|
||||
return QString( "%1 KB" ).arg( kb );
|
||||
return QString( "%1 Kb" ).arg( kb );
|
||||
}
|
||||
else
|
||||
return QString::number( size );
|
||||
|
@@ -121,7 +121,7 @@ ArtistInfoWidget::ArtistInfoWidget( const Tomahawk::artist_ptr& artist, QWidget*
|
||||
ui->biography->setObjectName( "biography" );
|
||||
ui->biography->setContentsMargins( 0, 0, 0, 0 );
|
||||
ui->biography->page()->mainFrame()->setScrollBarPolicy( Qt::Horizontal, Qt::ScrollBarAlwaysOff );
|
||||
ui->biography->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAsNeeded );
|
||||
ui->biography->page()->mainFrame()->setScrollBarPolicy( Qt::Vertical, Qt::ScrollBarAlwaysOff );
|
||||
ui->biography->page()->setLinkDelegationPolicy( QWebPage::DelegateAllLinks );
|
||||
ui->biography->installEventFilter( this );
|
||||
|
||||
|
@@ -62,8 +62,6 @@ CollectionViewPage::CollectionViewPage( const Tomahawk::collection_ptr& collecti
|
||||
|
||||
m_columnView->proxyModel()->setStyle( PlayableProxyModel::SingleColumn );
|
||||
|
||||
|
||||
PlayableProxyModel* trackViewProxyModel = m_trackView->proxyModel();
|
||||
if ( collection->backendType() == Collection::ScriptCollectionType )
|
||||
{
|
||||
m_trackView->proxyModel()->setStyle( PlayableProxyModel::Locker );
|
||||
@@ -72,12 +70,6 @@ CollectionViewPage::CollectionViewPage( const Tomahawk::collection_ptr& collecti
|
||||
{
|
||||
m_trackView->proxyModel()->setStyle( PlayableProxyModel::Collection );
|
||||
}
|
||||
// mapSourceColumnToColumn depends on the just set PlayableProxyModel::PlayableItemStyle
|
||||
m_trackView->setColumnHidden( trackViewProxyModel->mapSourceColumnToColumn( PlayableModel::Composer ), true );
|
||||
m_trackView->setColumnHidden( trackViewProxyModel->mapSourceColumnToColumn( PlayableModel::Origin ), true );
|
||||
m_trackView->setColumnHidden( trackViewProxyModel->mapSourceColumnToColumn( PlayableModel::Score ), true );
|
||||
m_trackView->setColumnHidden( trackViewProxyModel->mapSourceColumnToColumn( PlayableModel::Bitrate ), true );
|
||||
|
||||
|
||||
m_trackView->setGuid( QString( "trackview/flat" ) );
|
||||
|
||||
|
@@ -372,18 +372,13 @@ SearchWidget::onAlbumsFound( const QList<Tomahawk::album_ptr>& albums )
|
||||
|
||||
int distance = TomahawkUtils::levenshtein( m_search, album->name() );
|
||||
int maxlen = qMax( m_search.length(), album->name().length() );
|
||||
float scoreAlbum = (float)( maxlen - distance ) / maxlen;
|
||||
float score = (float)( maxlen - distance ) / maxlen;
|
||||
|
||||
distance = TomahawkUtils::levenshtein( m_search, album->artist()->name() );
|
||||
maxlen = qMax( m_search.length(), album->artist()->name().length() );
|
||||
float scoreArtist = (float)( maxlen - distance ) / maxlen;
|
||||
|
||||
float scoreMax = qMax( scoreAlbum, scoreArtist );
|
||||
if ( scoreMax <= 0.1 )
|
||||
if ( score <= 0.1 )
|
||||
continue;
|
||||
|
||||
m_albums.insert( album, scoreMax );
|
||||
// tDebug() << Q_FUNC_INFO << "found album:" << album->name() << "scoreMax:" << scoreMax;
|
||||
m_albums.insert( album, score );
|
||||
// tDebug() << Q_FUNC_INFO << "found album:" << album->name() << "score:" << score;
|
||||
}
|
||||
|
||||
// updateAlbums();
|
||||
|
@@ -85,7 +85,7 @@ ImageButton::paintEvent( QPaintEvent* event )
|
||||
p.setClipRect( event->rect() );
|
||||
|
||||
QIcon::Mode mode = isDown()
|
||||
? QIcon::Selected
|
||||
? QIcon::Active
|
||||
: QIcon::Normal;
|
||||
|
||||
QIcon::State state = isChecked()
|
||||
|
@@ -310,9 +310,8 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr result )
|
||||
connect( m_currentTrack->track().data(), SIGNAL( coverChanged() ), SLOT( onCoverUpdated() ) );
|
||||
connect( m_currentTrack->track().data(), SIGNAL( socialActionsLoaded() ), SLOT( onSocialActionsLoaded() ) );
|
||||
|
||||
setUpdatesEnabled( false );
|
||||
ui->trackLabel->setResult( result );
|
||||
ui->artistLabel->setResult( result );
|
||||
ui->trackLabel->setResult( result );
|
||||
|
||||
const QString duration = TomahawkUtils::timeToString( result.data()->track()->duration() );
|
||||
ui->timeLabel->setFixedWidth( ui->timeLabel->fontMetrics().width( QString( duration.length(), QChar( '0' ) ) ) );
|
||||
@@ -371,7 +370,6 @@ AudioControls::onPlaybackLoading( const Tomahawk::result_ptr result )
|
||||
|
||||
setCover();
|
||||
setSocialActions();
|
||||
setUpdatesEnabled( true );
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,4 +1,4 @@
|
||||
set(TOMAHAWK_APPLICATION_TARGET "tomahawk-bin")
|
||||
set(TOMAHAWK_APPLICATION_TARGET "tomahahawk-bin")
|
||||
|
||||
include( ECMAddAppIcon )
|
||||
|
||||
@@ -146,14 +146,8 @@ IF( BUILD_GUI )
|
||||
ENDIF()
|
||||
|
||||
file( GLOB_RECURSE TOMAHAWK_ICONS "${CMAKE_SOURCE_DIR}/data/icons/*-tomahawk-icon.png" )
|
||||
if(APPLE)
|
||||
# OUTFILE is currently only supported in my branch, see https://git.reviewboard.kde.org/r/126303/
|
||||
# once merged (and released), we can remove this conditional usage
|
||||
ecm_add_app_icon(tomahawkSources ICONS ${TOMAHAWK_ICONS} OUTFILE "${TOMAHAWK_APPLICATION_NAME}")
|
||||
else()
|
||||
ecm_add_app_icon(tomahawkSources ICONS ${TOMAHAWK_ICONS})
|
||||
endif()
|
||||
|
||||
ecm_add_app_icon( tomahawkSources ICONS ${TOMAHAWK_ICONS} )
|
||||
|
||||
qt_add_resources( RC_SRCS "../../resources.qrc" )
|
||||
|
||||
|
@@ -96,6 +96,12 @@
|
||||
#endif
|
||||
#endif
|
||||
#include <shellapi.h>
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,2,0)
|
||||
#include <windows.h>
|
||||
#ifndef THBN_CLICKED
|
||||
#define THBN_CLICKED 0x1800
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
using namespace Tomahawk;
|
||||
@@ -105,6 +111,10 @@ using namespace Accounts;
|
||||
TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
: QMainWindow( parent )
|
||||
, TomahawkUtils::DpiScaler( this )
|
||||
#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
, m_buttonCreatedID( RegisterWindowMessage( L"TaskbarButtonCreated" ) )
|
||||
, m_taskbarList( 0 )
|
||||
#endif
|
||||
, ui( new Ui::TomahawkWindow )
|
||||
, m_searchWidget( 0 )
|
||||
, m_trayIcon( 0 )
|
||||
@@ -144,7 +154,9 @@ TomahawkWindow::TomahawkWindow( QWidget* parent )
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
connect( AudioEngine::instance(), SIGNAL( stateChanged( AudioState, AudioState ) ), SLOT( audioStateChanged( AudioState, AudioState ) ) );
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 2, 0 )
|
||||
setupWindowsButtons();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if ( qApp->arguments().contains( "--debug" ) )
|
||||
@@ -525,12 +537,61 @@ TomahawkWindow::setupUpdateCheck()
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void
|
||||
bool
|
||||
TomahawkWindow::setupWindowsButtons()
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
const GUID IID_ITaskbarList3 = { 0xea1afb91,0x9e28,0x4b86, { 0x90,0xe9,0x9e,0x9f,0x8a,0x5e,0xef,0xaf } };
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
THUMBBUTTONMASK dwMask = THUMBBUTTONMASK( THB_ICON | THB_TOOLTIP | THB_FLAGS );
|
||||
m_thumbButtons[TP_PREVIOUS].dwMask = dwMask;
|
||||
m_thumbButtons[TP_PREVIOUS].iId = TP_PREVIOUS;
|
||||
m_thumbButtons[TP_PREVIOUS].hIcon = thumbIcon(TomahawkUtils::PrevButton);
|
||||
m_thumbButtons[TP_PREVIOUS].dwFlags = THBF_ENABLED;
|
||||
m_thumbButtons[TP_PREVIOUS].szTip[ tr( "Back" ).toWCharArray( m_thumbButtons[TP_PREVIOUS].szTip ) ] = 0;
|
||||
|
||||
m_thumbButtons[TP_PLAY_PAUSE].dwMask = dwMask;
|
||||
m_thumbButtons[TP_PLAY_PAUSE].iId = TP_PLAY_PAUSE;
|
||||
m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PlayButton);
|
||||
m_thumbButtons[TP_PLAY_PAUSE].dwFlags = THBF_ENABLED;
|
||||
m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Play" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
|
||||
|
||||
m_thumbButtons[TP_NEXT].dwMask = dwMask;
|
||||
m_thumbButtons[TP_NEXT].iId = TP_NEXT;
|
||||
m_thumbButtons[TP_NEXT].hIcon = thumbIcon(TomahawkUtils::NextButton);
|
||||
m_thumbButtons[TP_NEXT].dwFlags = THBF_ENABLED;
|
||||
m_thumbButtons[TP_NEXT].szTip[ tr( "Next" ).toWCharArray( m_thumbButtons[TP_NEXT].szTip ) ] = 0;
|
||||
|
||||
m_thumbButtons[3].dwMask = dwMask;
|
||||
m_thumbButtons[3].iId = -1;
|
||||
m_thumbButtons[3].hIcon = 0;
|
||||
m_thumbButtons[3].dwFlags = THBF_NOBACKGROUND | THBF_DISABLED;
|
||||
m_thumbButtons[3].szTip[0] = 0;
|
||||
|
||||
m_thumbButtons[TP_LOVE].dwMask = dwMask;
|
||||
m_thumbButtons[TP_LOVE].iId = TP_LOVE;
|
||||
m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::NotLoved);
|
||||
m_thumbButtons[TP_LOVE].dwFlags = THBF_DISABLED;
|
||||
m_thumbButtons[TP_LOVE].szTip[ tr( "Love" ).toWCharArray( m_thumbButtons[TP_LOVE].szTip ) ] = 0;
|
||||
|
||||
if ( S_OK == CoCreateInstance( CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER, IID_ITaskbarList3, (void **)&m_taskbarList ) )
|
||||
{
|
||||
hr = m_taskbarList->HrInit();
|
||||
if ( SUCCEEDED( hr ) )
|
||||
{
|
||||
hr = m_taskbarList->ThumbBarAddButtons( (HWND)winId(), ARRAYSIZE( m_thumbButtons ), m_thumbButtons );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_taskbarList->Release();
|
||||
m_taskbarList = 0;
|
||||
}
|
||||
}
|
||||
return SUCCEEDED( hr );
|
||||
#else
|
||||
m_taskbarList = new QWinThumbnailToolBar( this );
|
||||
m_taskbarList->setWindow( this->windowHandle() );
|
||||
updatePreview();
|
||||
|
||||
QWinThumbnailToolButton *back = new QWinThumbnailToolButton( m_taskbarList );
|
||||
back->setToolTip( tr( "Back" ) );
|
||||
@@ -564,84 +625,26 @@ TomahawkWindow::setupWindowsButtons()
|
||||
love->setInteractive( false );
|
||||
connect( love , SIGNAL( clicked() ) , this , SLOT( toggleLoved() ) );
|
||||
m_taskbarList->addButton(love);
|
||||
|
||||
return true;
|
||||
#endif//QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::updatePreview()
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
HICON
|
||||
TomahawkWindow::thumbIcon( TomahawkUtils::ImageType type )
|
||||
{
|
||||
const QSize size = QDesktopWidget().availableGeometry().size();
|
||||
const qreal margin = size.height() * 0.05;
|
||||
const QSize coverSize( size.height() - 2 * margin , size.height() - 2 * margin);
|
||||
QPixmap cover;
|
||||
QString title( qApp->applicationName() );
|
||||
if ( !m_currentTrack.isNull() ) {
|
||||
cover = m_currentTrack->track()->albumPtr()->cover( coverSize , false );
|
||||
title = tr( "%1<br><br><b>%2</b>", "track, artist name" ).arg( m_currentTrack->track()->track(), m_currentTrack->track()->artist() );
|
||||
static QMap<TomahawkUtils::ImageType,HICON> thumbIcons;
|
||||
if ( !thumbIcons.contains( type ) )
|
||||
{
|
||||
QPixmap pix ( TomahawkUtils::defaultPixmap(type , TomahawkUtils::Original, QSize( 40, 40 ) ) );
|
||||
thumbIcons[type] = pix.toWinHICON();
|
||||
}
|
||||
if ( cover.isNull() ) {
|
||||
cover = TomahawkUtils::defaultPixmap( TomahawkUtils::DefaultAlbumCover , TomahawkUtils::Original, coverSize );
|
||||
}
|
||||
|
||||
QPixmap thumb( size );
|
||||
thumb.fill( QColor( "#FF004C" ) );
|
||||
|
||||
QPainter paint( &thumb );
|
||||
|
||||
QPen pen = paint.pen();
|
||||
pen.setColor( Qt::white );
|
||||
pen.setWidth( size.height() * 0.01 );
|
||||
paint.setPen( pen );
|
||||
|
||||
paint.drawPixmap(margin , margin , coverSize.width() , coverSize.height() , cover );
|
||||
paint.drawRect( margin , margin , coverSize.width() , coverSize.height() );
|
||||
paint.drawRect( 0 , 0 , size.width() , size.height() );
|
||||
|
||||
QTextDocument doc;
|
||||
|
||||
QFont font = paint.font();
|
||||
font.setPixelSize( size.height() * 0.1 );
|
||||
doc.setDefaultFont( font );
|
||||
|
||||
doc.setPageSize( QSize( size.width() - 2 * margin - coverSize.width() , size.height() - 2 * margin ) );
|
||||
doc.setHtml( QString( "<center><font color=\"white\">%1</font></center>" ).arg( title ));
|
||||
|
||||
paint.save();
|
||||
paint.translate( coverSize.width() + 2 * margin , ( size.height() - doc.size().height() ) / 2);
|
||||
|
||||
doc.drawContents( &paint );
|
||||
|
||||
paint.restore();
|
||||
|
||||
m_taskbarList->setIconicThumbnailPixmap( thumb );
|
||||
m_taskbarList->setIconicLivePreviewPixmap( thumb );
|
||||
return thumbIcons[type];
|
||||
}
|
||||
|
||||
void
|
||||
TomahawkWindow::updateWindowsLoveButton()
|
||||
{
|
||||
QWinThumbnailToolButton *love = m_taskbarList->buttons()[ TP_LOVE ];
|
||||
|
||||
if ( !AudioEngine::instance()->currentTrack().isNull() )
|
||||
{
|
||||
love->setInteractive(true);
|
||||
if ( AudioEngine::instance()->currentTrack()->track()->loved() )
|
||||
{
|
||||
love->setIcon(thumbIcon(TomahawkUtils::Loved));
|
||||
love->setToolTip( tr( "Unlove" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
love->setIcon( thumbIcon(TomahawkUtils::NotLoved) );
|
||||
love->setToolTip( tr( "Love" ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
love->setInteractive(false);
|
||||
love->setIcon( thumbIcon(TomahawkUtils::NotLoved) );
|
||||
love->setToolTip( tr( "Love" ) );
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
QIcon
|
||||
TomahawkWindow::thumbIcon(TomahawkUtils::ImageType type)
|
||||
@@ -649,6 +652,8 @@ TomahawkWindow::thumbIcon(TomahawkUtils::ImageType type)
|
||||
return TomahawkUtils::defaultPixmap( type , TomahawkUtils::Original, QSize( 40, 40 ) );
|
||||
}
|
||||
|
||||
#endif//QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -839,6 +844,51 @@ TomahawkWindow::keyPressEvent( QKeyEvent* e )
|
||||
QMainWindow::keyPressEvent( e );
|
||||
}
|
||||
|
||||
|
||||
#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
bool
|
||||
TomahawkWindow::winEvent( MSG* msg, long* result )
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
#define TB_PRESSED Q_FUNC_INFO << "Taskbar Button Pressed:"
|
||||
|
||||
switch ( msg->message )
|
||||
{
|
||||
case WM_COMMAND:
|
||||
if ( HIWORD( msg->wParam ) == THBN_CLICKED )
|
||||
{
|
||||
switch ( TB_STATES( LOWORD( msg->wParam ) ) )
|
||||
{
|
||||
case TP_PREVIOUS:
|
||||
tLog() << TB_PRESSED << "Previous";
|
||||
AudioEngine::instance()->previous();
|
||||
break;
|
||||
case TP_PLAY_PAUSE:
|
||||
tLog() << TB_PRESSED << "Play/Pause";
|
||||
AudioEngine::instance()->playPause();
|
||||
break;
|
||||
case TP_NEXT:
|
||||
tLog() << TB_PRESSED << "Next";
|
||||
AudioEngine::instance()->next();
|
||||
break;
|
||||
case TP_LOVE:
|
||||
tLog() << TB_PRESSED << "Love";
|
||||
toggleLoved();
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if ( msg->message == m_buttonCreatedID )
|
||||
return setupWindowsButtons();
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif//defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
|
||||
|
||||
void
|
||||
TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
|
||||
{
|
||||
@@ -846,8 +896,48 @@ TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
|
||||
#ifndef Q_OS_WIN
|
||||
Q_UNUSED(newState);
|
||||
#else
|
||||
updatePreview();
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
if ( m_taskbarList == 0 )
|
||||
return;
|
||||
switch ( newState )
|
||||
{
|
||||
case AudioEngine::Playing:
|
||||
{
|
||||
m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PauseButton);
|
||||
m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Pause" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
|
||||
updateWindowsLoveButton();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioEngine::Paused:
|
||||
{
|
||||
m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PlayButton);
|
||||
m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Play" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case AudioEngine::Stopped:
|
||||
{
|
||||
if ( !AudioEngine::instance()->currentTrack().isNull() )
|
||||
{
|
||||
disconnect( AudioEngine::instance()->currentTrack()->track().data(), SIGNAL( socialActionsLoaded() ), this, SLOT( updateWindowsLoveButton() ) );
|
||||
}
|
||||
|
||||
m_thumbButtons[TP_PLAY_PAUSE].hIcon = thumbIcon(TomahawkUtils::PlayButton);
|
||||
m_thumbButtons[TP_PLAY_PAUSE].szTip[ tr( "Play" ).toWCharArray( m_thumbButtons[TP_PLAY_PAUSE].szTip ) ] = 0;
|
||||
|
||||
m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::NotLoved);
|
||||
m_thumbButtons[TP_LOVE].dwFlags = THBF_DISABLED;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
m_taskbarList->ThumbBarUpdateButtons( (HWND)winId(), ARRAYSIZE( m_thumbButtons ), m_thumbButtons );
|
||||
#else
|
||||
QWinThumbnailToolButton *play = m_taskbarList->buttons()[ TP_PLAY_PAUSE ];
|
||||
switch ( newState )
|
||||
{
|
||||
@@ -856,6 +946,7 @@ TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
|
||||
play->setIcon( thumbIcon(TomahawkUtils::PauseButton) );
|
||||
play->setToolTip( tr( "Pause" ) );
|
||||
updateWindowsLoveButton();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -885,9 +976,57 @@ TomahawkWindow::audioStateChanged( AudioState newState, AudioState oldState )
|
||||
default:
|
||||
return;
|
||||
}
|
||||
#endif//QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
#endif//Q_OS_WIN
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkWindow::updateWindowsLoveButton()
|
||||
{
|
||||
#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
if ( m_taskbarList == 0 )
|
||||
return;
|
||||
if ( !AudioEngine::instance()->currentTrack().isNull() && AudioEngine::instance()->currentTrack()->track()->loved() )
|
||||
{
|
||||
m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::Loved);
|
||||
m_thumbButtons[TP_LOVE].szTip[ tr( "Unlove" ).toWCharArray( m_thumbButtons[TP_LOVE].szTip ) ] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_thumbButtons[TP_LOVE].hIcon = thumbIcon(TomahawkUtils::NotLoved);
|
||||
m_thumbButtons[TP_LOVE].szTip[ tr( "Love" ).toWCharArray( m_thumbButtons[TP_LOVE].szTip ) ] = 0;
|
||||
}
|
||||
|
||||
m_thumbButtons[TP_LOVE].dwFlags = THBF_ENABLED;
|
||||
m_taskbarList->ThumbBarUpdateButtons( (HWND)winId(), ARRAYSIZE( m_thumbButtons ), m_thumbButtons );
|
||||
#elif defined(Q_OS_WIN)
|
||||
QWinThumbnailToolButton *love = m_taskbarList->buttons()[ TP_LOVE ];
|
||||
|
||||
if ( !AudioEngine::instance()->currentTrack().isNull() )
|
||||
{
|
||||
love->setInteractive(true);
|
||||
if ( AudioEngine::instance()->currentTrack()->track()->loved() )
|
||||
{
|
||||
love->setIcon(thumbIcon(TomahawkUtils::Loved));
|
||||
love->setToolTip( tr( "Unlove" ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
love->setIcon( thumbIcon(TomahawkUtils::NotLoved) );
|
||||
love->setToolTip( tr( "Love" ) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
love->setInteractive(false);
|
||||
love->setIcon( thumbIcon(TomahawkUtils::NotLoved) );
|
||||
love->setToolTip( tr( "Love" ) );
|
||||
}
|
||||
#endif//defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
TomahawkWindow::onHistoryBackAvailable( bool avail )
|
||||
{
|
||||
|
@@ -37,9 +37,11 @@
|
||||
#include <QToolButton>
|
||||
#ifdef Q_OS_WIN
|
||||
#include <shobjidl.h>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK( 5, 2, 0 )
|
||||
#include <QWinThumbnailToolBar>
|
||||
#include <QWinThumbnailToolButton>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace Tomahawk
|
||||
{
|
||||
@@ -90,6 +92,10 @@ protected:
|
||||
|
||||
bool eventFilter( QObject* obj, QEvent* event );
|
||||
|
||||
#if defined(Q_OS_WIN) && QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
bool winEvent( MSG* message, long* result );
|
||||
#endif
|
||||
|
||||
public slots:
|
||||
void createStation();
|
||||
void createPlaylist();
|
||||
@@ -149,11 +155,7 @@ private slots:
|
||||
void toggleLoved();
|
||||
|
||||
void audioStateChanged( AudioState newState, AudioState oldState );
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void updateWindowsLoveButton();
|
||||
void updatePreview();
|
||||
#endif
|
||||
|
||||
private:
|
||||
void loadSettings();
|
||||
@@ -171,9 +173,16 @@ private:
|
||||
void importPlaylist( const QString& url, bool autoUpdate );
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
void setupWindowsButtons();
|
||||
bool setupWindowsButtons();
|
||||
#if QT_VERSION < QT_VERSION_CHECK( 5, 2, 0 )
|
||||
const unsigned int m_buttonCreatedID;
|
||||
HICON thumbIcon(TomahawkUtils::ImageType type);
|
||||
ITaskbarList3* m_taskbarList;
|
||||
THUMBBUTTON m_thumbButtons[5];
|
||||
#else
|
||||
QIcon thumbIcon(TomahawkUtils::ImageType type);
|
||||
QWinThumbnailToolBar *m_taskbarList;
|
||||
#endif
|
||||
enum TB_STATES{ TP_PREVIOUS = 0,TP_PLAY_PAUSE = 1,TP_NEXT = 2, TP_SPACE = 3, TP_LOVE = 4 };
|
||||
#endif
|
||||
|
||||
|
@@ -37,7 +37,6 @@
|
||||
#include "sip/SipPlugin.h"
|
||||
#include "utils/TomahawkUtilsGui.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "Pipeline.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QClipboard>
|
||||
@@ -124,20 +123,6 @@ DiagnosticsDialog::updateLogView()
|
||||
log.append( accountLog( account ) + "\n" );
|
||||
}
|
||||
|
||||
|
||||
log.append( "RESOLVERS:\n" );
|
||||
|
||||
|
||||
connect( Tomahawk::Pipeline::instance(), SIGNAL( resolverAdded( Tomahawk::Resolver* ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
connect( Tomahawk::Pipeline::instance(), SIGNAL( resolverRemoved( Tomahawk::Resolver* ) ), SLOT( updateLogView() ), Qt::UniqueConnection );
|
||||
|
||||
const QList< Tomahawk::Resolver* > resolvers = Tomahawk::Pipeline::instance()->resolvers();
|
||||
foreach ( Tomahawk::Resolver* resolver, resolvers )
|
||||
{
|
||||
|
||||
log.append( resolver->name() + "\n" );
|
||||
}
|
||||
|
||||
ui->text->setText( log );
|
||||
}
|
||||
|
||||
|
@@ -59,8 +59,6 @@
|
||||
#include "jobview/ErrorStatusMessage.h"
|
||||
#include "utils/NetworkAccessManager.h"
|
||||
#include "utils/NetworkProxyFactory.h"
|
||||
#include "resolvers/JSAccount.h"
|
||||
#include "resolvers/JSResolver.h"
|
||||
|
||||
#include <QDesktopServices>
|
||||
#include <QFileDialog>
|
||||
@@ -70,7 +68,6 @@
|
||||
#include <QVBoxLayout>
|
||||
#include <QSizeGrip>
|
||||
#include <QToolBar>
|
||||
#include <QMenu>
|
||||
|
||||
using namespace Tomahawk;
|
||||
using namespace Accounts;
|
||||
@@ -90,7 +87,6 @@ SettingsDialog::SettingsDialog(QObject *parent )
|
||||
, m_restartRequired( false )
|
||||
, m_accountModel( 0 )
|
||||
, m_sipSpinner( 0 )
|
||||
, m_contextMenu( 0 )
|
||||
{
|
||||
m_accountsWidget->setFont( TomahawkUtils::systemFont() );
|
||||
m_collectionWidget->setFont( TomahawkUtils::systemFont() );
|
||||
@@ -148,12 +144,6 @@ SettingsDialog::SettingsDialog(QObject *parent )
|
||||
m_accountsWidgetUi->accountsView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
|
||||
m_accountsWidgetUi->accountsView->setMouseTracking( true );
|
||||
|
||||
m_contextMenu = new QMenu( m_accountsWidgetUi->accountsView );
|
||||
m_contextMenu->setFont( TomahawkUtils::systemFont() );
|
||||
connect( m_accountsWidgetUi->accountsView, SIGNAL( customContextMenuRequested( QPoint ) ), SLOT( onCustomContextMenu( QPoint ) ) );
|
||||
QAction* showDebuggerAction = m_contextMenu->addAction( tr( "Open Account &Debugger..." ) );
|
||||
connect( showDebuggerAction, SIGNAL( triggered(bool) ), SLOT( onShowDebuggerForSelectedAccount() ) );
|
||||
|
||||
connect( accountDelegate, SIGNAL( openConfig( Tomahawk::Accounts::Account* ) ), SLOT( openAccountConfig( Tomahawk::Accounts::Account* ) ) );
|
||||
connect( accountDelegate, SIGNAL( openConfig( Tomahawk::Accounts::AccountFactory* ) ), SLOT( openAccountFactoryConfig( Tomahawk::Accounts::AccountFactory* ) ) );
|
||||
connect( accountDelegate, SIGNAL( update( QModelIndex ) ), m_accountsWidgetUi->accountsView, SLOT( update( QModelIndex ) ) );
|
||||
@@ -390,34 +380,6 @@ SettingsDialog::onRejected()
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsDialog::onCustomContextMenu( const QPoint& point )
|
||||
{
|
||||
QModelIndex index = m_accountsWidgetUi->accountsView->indexAt( point );
|
||||
if ( !index.isValid() )
|
||||
return;
|
||||
|
||||
// HACK until there is a proper ScriptAccount
|
||||
ResolverAccount* account = qobject_cast< ResolverAccount* >( m_accountProxy->data( index, AccountModel::AccountData ).value< Tomahawk::Accounts::Account* >() );
|
||||
if ( !account )
|
||||
return;
|
||||
Tomahawk::JSResolver* jsResolver = qobject_cast< Tomahawk::JSResolver* >( account->resolver() );
|
||||
if ( !jsResolver )
|
||||
return;
|
||||
|
||||
m_contextMenu->exec( m_accountsWidgetUi->accountsView->mapToGlobal( point ) );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsDialog::onShowDebuggerForSelectedAccount()
|
||||
{
|
||||
ResolverAccount* account = m_accountProxy->data( m_accountsWidgetUi->accountsView->currentIndex(), AccountModel::AccountData ).value< ResolverAccount* >();
|
||||
Tomahawk::JSResolver* jsResolver = qobject_cast< Tomahawk::JSResolver* >( account->resolver() );
|
||||
jsResolver->scriptAccount()->showDebugger();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SettingsDialog::changeEvent( QEvent *e )
|
||||
{
|
||||
|
@@ -37,7 +37,6 @@ class SipPlugin;
|
||||
class ResolversModel;
|
||||
class QNetworkReply;
|
||||
class QToolbarTabDialog;
|
||||
class QMenu;
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
@@ -131,9 +130,6 @@ private slots:
|
||||
void saveSettings();
|
||||
void onRejected();
|
||||
|
||||
void onCustomContextMenu( const QPoint& point );
|
||||
void onShowDebuggerForSelectedAccount();
|
||||
|
||||
private:
|
||||
Ui_Settings_Accounts* m_accountsWidgetUi;
|
||||
QWidget* m_accountsWidget;
|
||||
@@ -156,7 +152,6 @@ private:
|
||||
Tomahawk::Accounts::AccountModelFilterProxy* m_accountProxy;
|
||||
QHash<QString, QString> m_downloadsFormats;
|
||||
AnimatedSpinner* m_sipSpinner;
|
||||
QMenu* m_contextMenu;
|
||||
};
|
||||
|
||||
#endif // SETTINGSDIALOG_H
|
||||
|
@@ -366,8 +366,8 @@ Tomahawk::setupToolBarMac( TomahawkWindow* parent )
|
||||
[toolbar->nativeToolbar() setDisplayMode: NSToolbarDisplayModeIconOnly];
|
||||
[toolbar->nativeToolbar() setSizeMode: NSToolbarSizeModeSmall];
|
||||
|
||||
QMacToolBarItem* backItem = toolbar->addItem( ImageRegistry::instance()->pixmap( RESPATH "images/nav-back.svg", QSize( 32, 32 ) ), QString( "Back" ) );
|
||||
QMacToolBarItem* forwardItem = toolbar->addItem( ImageRegistry::instance()->pixmap( RESPATH "images/nav-forward.svg", QSize( 32, 32 ) ), QString( "Forward" ) );
|
||||
QMacToolBarItem* backItem = toolbar->addItem( ImageRegistry::instance()->pixmap( RESPATH "images/back.svg", QSize( 32, 32 ) ), QString( "Back" ) );
|
||||
QMacToolBarItem* forwardItem = toolbar->addItem( ImageRegistry::instance()->pixmap( RESPATH "images/forward.svg", QSize( 32, 32 ) ), QString( "Forward" ) );
|
||||
|
||||
QObject::connect( backItem, SIGNAL( activated() ), ViewManager::instance(), SLOT( historyBack() ) );
|
||||
QObject::connect( forwardItem, SIGNAL( activated() ), ViewManager::instance(), SLOT( historyForward() ) );
|
||||
@@ -381,12 +381,6 @@ Tomahawk::setupToolBarMac( TomahawkWindow* parent )
|
||||
searchField->parent = parent;
|
||||
[searchItem->nativeToolBarItem() setView: searchField];
|
||||
|
||||
NSSize nsirect = [searchField frame].size;
|
||||
nsirect.width = 250;
|
||||
[searchItem->nativeToolBarItem() setMinSize: nsirect];
|
||||
nsirect.width = 450;
|
||||
[searchItem->nativeToolBarItem() setMaxSize: nsirect];
|
||||
|
||||
QMacToolBarItem* spacerRightItem = toolbar->addItem( QIcon(), QString() );
|
||||
spacerRightItem->setStandardItem( QMacToolBarItem::FlexibleSpace );
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user