Compare commits

...

159 Commits
0.3.1 ... 0.4.2

Author SHA1 Message Date
Jonas Kvinge
bcd29b9fd2 Release 0.4.2 2018-11-28 21:53:38 +01:00
Jonas Kvinge
046c221bc6 Change internet to streaming in settings and change order of settings 2018-11-28 17:53:37 +01:00
Jonas Kvinge
29a39b4e7f Attempt to fix devices issue 2018-11-28 17:45:50 +01:00
Jonas Kvinge
9fb3d06aac Change if statement in qtsingleapplication/CMakeLists.txt 2018-11-28 17:44:45 +01:00
Jonas Kvinge
142d5e2347 Update .travis.yml 2018-11-27 19:36:22 +01:00
Jonas Kvinge
58ea0bcbb0 Turn Deezer OFF by default if dependencies arent found 2018-11-27 19:33:30 +01:00
Jonas Kvinge
1c0bbe5d33 Fix endif in qxt CMakeLists.txt 2018-11-27 19:27:09 +01:00
Jonas Kvinge
8a7bba8ef3 Remove background image
Unsure about copyright issues using it, the image is from the Strawbs boxset, removing
it for now.
2018-11-27 19:20:33 +01:00
Jonas Kvinge
3b93963688 Code cleanup in qxtglobalshortcut 2018-11-27 19:14:35 +01:00
Jonas Kvinge
77e5d0288f Fix typo 2018-11-19 01:38:55 +01:00
Jonas Kvinge
460e78a1b8 Merge branch 'master' of github.com:jonaski/strawberry 2018-11-19 01:32:26 +01:00
Jonas Kvinge
fcbade267d Update changelog and about 2018-11-19 01:31:52 +01:00
Jonas Kvinge
41b99d9aa0 Update README.md 2018-11-19 01:12:32 +01:00
Jonas Kvinge
96c761dbb5 Update README.md 2018-11-19 01:09:51 +01:00
Jonas Kvinge
d297564236 Update README.md 2018-11-19 01:09:12 +01:00
Jonas Kvinge
bca1a98938 Add option to reset playlist columns 2018-11-19 00:18:48 +01:00
Jonas Kvinge
23205bef65 Playlist fixes
- Fix bug resetting playlist view columns to show all when using more than one
playlist.
- Add queue to play next
2018-11-18 23:21:12 +01:00
Jonas Kvinge
7613b2f526 Add alsa to optional_component 2018-11-17 16:28:05 +01:00
Jonas Kvinge
c5a521af1f Fix logging 2018-11-17 03:27:46 +01:00
Jonas Kvinge
f15c85e807 Remove SetThreadIOPriority, fixes poor performance on macos 2018-11-17 03:25:42 +01:00
Jonas Kvinge
6129ad1f4d Track slider fixes 2018-11-17 03:25:21 +01:00
Jonas Kvinge
9972dc192b Add include for QtGlobal 2018-11-17 03:24:20 +01:00
Jonas Kvinge
32b96a25e8 Remove dead code 2018-11-17 03:23:49 +01:00
Jonas Kvinge
9d09e7f6fe Remove dead code 2018-11-17 03:23:22 +01:00
Jonas Kvinge
5927483402 Remove qstyleoption_cast 2018-11-16 17:45:57 +01:00
Jonas Kvinge
f228f79a8a Fix macos code 2018-11-16 17:25:39 +01:00
Jonas Kvinge
072a3065cd Don't set paths for gst scanner and plugins on macos 2018-11-15 20:20:30 +01:00
Jonas Kvinge
718bd4c081 Replace NULL and 0 with nullptr 2018-11-14 00:43:19 +01:00
Jonas Kvinge
542cc0ec2f Remove unused code 2018-11-14 00:31:04 +01:00
Jonas Kvinge
b357634f51 Add pacman package files 2018-11-11 03:37:14 +01:00
Jonas Kvinge
6968c4d0fb Remove OpenGL from Dockerfile 2018-11-09 22:24:55 +01:00
Jonas Kvinge
e35d618133 Make Deezer engine use quality setting 2018-11-09 19:27:36 +01:00
Jonas Kvinge
4a23fde6bf Merge branch 'master' of github.com:jonaski/strawberry 2018-11-05 02:12:24 +01:00
Jonas Kvinge
1ae577641d Remove Qt5OpenGL from spec files and control file 2018-11-05 02:11:26 +01:00
Jonas Kvinge
686a3bb42b Update README.md 2018-11-05 01:21:37 +01:00
Jonas Kvinge
1771d41871 Fixes to makefiles
- Add a warning when using the systems taglib less or equal to version 1.11.1
- Remove OpenGL and Qt5::OpenGL dependency, it is not used by the analyzer
- Rename some variables
2018-11-05 01:14:56 +01:00
Jonas Kvinge
ee8f4ca7ab Add libqt5sql5-sqlite to debian control 2018-11-04 23:24:49 +01:00
Jonas Kvinge
4197a508a3 Remove obsolete xine warning and engine reinitialization 2018-11-04 21:23:34 +01:00
Jonas Kvinge
f38ffb505d Add Requires libQt5Sql5-sqlite to spec 2018-11-04 00:48:39 +01:00
Jonas Kvinge
679caf73d1 Fix strawberry.appdata.xml 2018-11-03 16:30:53 +01:00
Jonas Kvinge
56d25c346c Update appdata file to new AppStream specification 2018-11-03 15:57:45 +01:00
Jonas Kvinge
6ba26ba289 Change fedora rpm suffix 2018-11-02 21:30:07 +01:00
Jonas Kvinge
27582b7a4e Add strawberry.appdata.xml to spec files 2018-11-02 20:30:12 +01:00
Jonas Kvinge
2f4417d683 Fix files to delete on uninstall in nsi 2018-11-01 22:22:39 +01:00
Jonas Kvinge
de97d29a82 Turn back git revision 2018-11-01 22:22:30 +01:00
Jonas Kvinge
b782a2c8a2 Release 0.4.1 2018-11-01 21:18:57 +01:00
Jonas Kvinge
298783e2c5 Attempt to login if streamurl fails 2018-11-01 21:18:09 +01:00
Jonas Kvinge
bc9ec8025c Move some settings 2018-10-31 19:44:24 +01:00
Jonas Kvinge
26459763e5 Only set QtDebugMsg when build type is debug 2018-10-31 19:41:52 +01:00
Jonas Kvinge
1213306657 Update libcdio 2018-10-31 01:30:15 +01:00
Jonas Kvinge
50add12e4b Update changelog 2018-10-30 23:47:51 +01:00
Jonas Kvinge
67c889f982 Improve Xine engine code 2018-10-30 23:40:41 +01:00
Jonas Kvinge
08cba25071 Improve VLC error handling 2018-10-30 23:40:05 +01:00
Jonas Kvinge
ff35b01bac Improve gst engine error handling 2018-10-30 23:39:08 +01:00
Jonas Kvinge
faee1977fe Add better error handling between engine and player 2018-10-30 23:21:51 +01:00
Jonas Kvinge
6105b99a7f Add option to continue to next song in playlist on error
Also rename some settings. Add option to grey out songs both on playback and
on startup.
2018-10-30 23:20:02 +01:00
Jonas Kvinge
4993201b70 Fix deezer url handler 2018-10-30 23:18:25 +01:00
Jonas Kvinge
f456ca674d Update taglib 2018-10-27 12:15:52 +02:00
Jonas Kvinge
2ba350f76f Attempt to fix crash in setStyleSheet() 2018-10-26 20:05:37 +02:00
Jonas Kvinge
3fe92a62ac Add DSF and DSDIFF to IsFileLossless 2018-10-24 00:58:03 +02:00
Jonas Kvinge
f4dcf6821f Rename class InternetModel to InternetServices 2018-10-23 23:25:02 +02:00
Jonas Kvinge
0c10013858 Ops 2018-10-23 21:14:58 +02:00
Jonas Kvinge
3e9530fa8d Set metadata from deezer engine 2018-10-23 20:21:33 +02:00
Jonas Kvinge
0f4ffe4fce Add PCM as filetype 2018-10-23 20:21:01 +02:00
Jonas Kvinge
e1c01e5d25 Fix device selection 2018-10-23 20:18:07 +02:00
Jonas Kvinge
51021131d7 Allow compile on Qt 5.5.1 or above 2018-10-23 20:17:29 +02:00
Jonas Kvinge
89a08d1d5e Fix RPM build 2018-10-22 23:23:25 +02:00
Jonas Kvinge
ba8717f95a Fix Deezer engine error state 2018-10-22 23:04:34 +02:00
Jonas Kvinge
c8dfb9b0db Fix loading custom device 2018-10-22 22:10:27 +02:00
Jonas Kvinge
3a02ece169 Add EnsureInitialised() 2018-10-22 20:40:02 +02:00
Jonas Kvinge
262df6b461 Merge pull request #24 from eclipseo/use_qt5_deps
Use qt5 libraries of system-wide libraries
2018-10-22 19:00:07 +02:00
Jonas Kvinge
b9516fdfd4 Merge pull request #23 from eclipseo/add_appdata_file
Add AppStream data file
2018-10-22 18:49:28 +02:00
Robert-André Mauchin
9de41bc027 Use qt5 version of system-wide libraries 2018-10-22 17:45:47 +02:00
Robert-André Mauchin
53b5cf3855 Add AppStream data file 2018-10-22 16:44:35 +02:00
Jonas Kvinge
0567358783 Update README.md 2018-10-21 20:49:35 +02:00
Jonas Kvinge
c97bc55c6f Move queuemanager to fancytabbar 2018-10-21 15:13:48 +02:00
Jonas Kvinge
3ef0bf60d0 Correct text for right click configure 2018-10-20 22:33:23 +02:00
Jonas Kvinge
b7b8084a38 Remove setExpanding 2018-10-20 22:18:56 +02:00
Jonas Kvinge
5221f13498 Minor code cleanup and fixes 2018-10-20 22:16:22 +02:00
Jonas Kvinge
0c0a8d70f3 Change darwin to macos 2018-10-20 22:15:32 +02:00
Jonas Kvinge
2ff971878d Enable debug logging on Fedora 2018-10-20 22:13:51 +02:00
Jonas Kvinge
1a0dc1e614 Update README 2018-10-20 22:13:21 +02:00
Jonas Kvinge
4a0bd99654 Enable deezer engine by default 2018-10-20 22:13:02 +02:00
Jonas Kvinge
5cb98e44cb Update README 2018-10-19 20:42:58 +02:00
Jonas Kvinge
13ed99b9c3 Update README and Changelog 2018-10-19 20:37:42 +02:00
Jonas Kvinge
0cda4e27aa Replace qSort/qStableSort/qSwap 2018-10-19 20:18:46 +02:00
Jonas Kvinge
0969e7f504 Remove cachedlist.h 2018-10-19 19:38:30 +02:00
Jonas Kvinge
cad73e18e2 Remove unused code 2018-10-19 19:20:29 +02:00
Jonas Kvinge
9eadeddfd9 Fixup and finish deezer engine 2018-10-19 19:15:33 +02:00
Jonas Kvinge
de11cb173b Use previews as default setting if deezer engine and dzmedia is missing 2018-10-19 19:14:49 +02:00
Jonas Kvinge
5853bc68d1 Replace depreciated macro 2018-10-19 19:13:40 +02:00
Jonas Kvinge
7d1fd9d46f Add missing names 2018-10-19 19:13:24 +02:00
Jonas Kvinge
c977c822d5 Add info about Deezer 2018-10-19 19:13:01 +02:00
Jonas Kvinge
c05fb33ea2 Replace FancyTabWidget with improved version 2018-10-19 19:10:22 +02:00
Jonas Kvinge
b9d0b3e152 Add option to diable Tidal and Deezer 2018-10-17 23:49:02 +02:00
Jonas Kvinge
a9e905b301 Fix bug not loading engine 2018-10-17 22:55:36 +02:00
Jonas Kvinge
a8a714c820 Use common classes for Tidal and Deezer 2018-10-17 21:18:39 +02:00
Jonas Kvinge
9349ad9383 Fix missing icon 2018-10-17 00:46:08 +02:00
Jonas Kvinge
f686f00951 Fix missing icon 2018-10-17 00:43:05 +02:00
Jonas Kvinge
3d13c12cb7 Update taglib 2018-10-16 23:58:26 +02:00
Jonas Kvinge
2384a42d33 Update .gitignore 2018-10-16 21:37:27 +02:00
Jonas Kvinge
f507fec905 Update Changelog 2018-10-16 21:32:03 +02:00
Jonas Kvinge
83a9724d17 Improve Tidal code 2018-10-16 21:31:28 +02:00
Jonas Kvinge
4156e26f76 Fix some minor code bugs in deezer 2018-10-16 21:30:27 +02:00
Jonas Kvinge
6d269e1786 Add libdeezer dll to windows nsi 2018-10-16 21:29:40 +02:00
Jonas Kvinge
ea447cab37 Remove quotes 2018-10-16 21:29:21 +02:00
Jonas Kvinge
4f3e7de441 Exclude debian changelog 2018-10-16 21:29:00 +02:00
Jonas Kvinge
0a81fa99fc Add Deezer support 2018-10-14 00:08:33 +02:00
Jonas Kvinge
4aad44cb62 Create timer for login attempts for Tidal 2018-10-13 00:30:52 +02:00
Jonas Kvinge
69dda39d02 Create timer for login attempts for Tidal 2018-10-13 00:18:38 +02:00
Jonas Kvinge
ca3ba6f136 Increase kTrackSliderUpdateTimeMs 2018-10-02 01:01:31 +02:00
Jonas Kvinge
044cf4624a Add hide() 2018-10-02 00:58:46 +02:00
Jonas Kvinge
1fbfabdf66 Remove whitespaces 2018-10-02 00:46:54 +02:00
Jonas Kvinge
db035351be Remove whitespaces 2018-10-02 00:38:52 +02:00
Jonas Kvinge
2883ef840e Fix track stop on error 2018-10-02 00:21:50 +02:00
Jonas Kvinge
8254ee911d Fix default setting for system tray 2018-10-01 00:31:02 +02:00
Jonas Kvinge
560bc0a150 Fix default setting for system tray 2018-10-01 00:29:06 +02:00
Jonas Kvinge
827898cd38 Fix taglib includes 2018-09-30 22:32:56 +02:00
Jonas Kvinge
184dec146c Move resume playback outside of startup group 2018-09-30 15:55:02 +02:00
Jonas Kvinge
298dbe96c8 Check if system has system tray using QSystemTrayIcon::isSystemTrayAvailable() 2018-09-30 15:33:27 +02:00
Jonas Kvinge
6d888eb51a Analyzer code cleanup and try to fix crash on Fedora 2018-09-30 15:32:21 +02:00
Jonas Kvinge
3694765611 Add error handling for enabling FTS3 2018-09-30 14:54:14 +02:00
Jonas Kvinge
b07ae3d34e Remove reset 2018-09-30 00:08:09 +02:00
Jonas Kvinge
64bcdf4734 Fix spelling 2018-09-30 00:07:59 +02:00
Jonas Kvinge
1c23756fc4 Turn on git revision 2018-09-30 00:07:05 +02:00
Jonas Kvinge
50e3eeaafd Release 0.3.3 2018-09-24 19:13:45 +02:00
Jonas Kvinge
843f528ebc Revert change to Tidal login using clientUniqueKey 2018-09-24 19:10:49 +02:00
Jonas Kvinge
faa0076988 Turn back git revision 2018-09-24 19:10:15 +02:00
Jonas Kvinge
59622c52ad Release 0.3.2 2018-09-24 18:42:21 +02:00
Jonas Kvinge
a8e9aba58b Save password as QString 2018-09-24 18:40:05 +02:00
Jonas Kvinge
36563cd1e1 Fix compile 2018-09-22 23:32:11 +02:00
Jonas Kvinge
072e712f0d Add missing QUrl include 2018-09-22 23:30:19 +02:00
Jonas Kvinge
121a186160 Improve contextview and engine code 2018-09-22 23:13:56 +02:00
Jonas Kvinge
15a2ccc21e Change size of comboxes in device settings 2018-09-22 15:54:38 +02:00
Jonas Kvinge
dbd8ea69eb Turn off debug about in Tidal 2018-09-22 15:39:24 +02:00
Jonas Kvinge
8a57356f64 More Tidal fixes 2018-09-22 15:37:42 +02:00
Jonas Kvinge
c77cb002f3 Add support for both ALSA hw and plughw 2018-09-21 23:29:00 +02:00
Jonas Kvinge
aa83a2b40b Add option to change url stream scheme for Tidal 2018-09-21 18:53:27 +02:00
Jonas Kvinge
65b04cac6e Update changelog 2018-09-21 01:20:16 +02:00
Jonas Kvinge
5e577190a8 Fix some copyrights 2018-09-21 01:12:21 +02:00
Jonas Kvinge
0143617056 Fix bug setting wrong temp metadata and bug in pipeline 2018-09-21 00:34:02 +02:00
Jonas Kvinge
a77dde7d3b Fix some includes 2018-09-20 22:48:52 +02:00
Jonas Kvinge
7dcdb7c673 Might be a good idea to actually add the URL Handler :) 2018-09-20 22:37:38 +02:00
Jonas Kvinge
6de8eb56cd Remove dead code in Tidal 2018-09-20 22:29:35 +02:00
Jonas Kvinge
04e272d9bc Fix mistake 2018-09-20 22:22:48 +02:00
Jonas Kvinge
17fe201473 Use URL Handler for Tidal 2018-09-20 22:13:30 +02:00
Jonas Kvinge
25249be37f Change orange to red 2018-09-20 17:44:31 +02:00
Jonas Kvinge
97ec12b5b3 Don't compile devices on windows 2018-09-20 17:36:23 +02:00
Jonas Kvinge
246f82bfad Replace obsolete QStyleOptionViewItemV2-4 2018-09-18 22:17:28 +02:00
Jonas Kvinge
db5679bbe9 Fix lsb-release command 2018-09-18 19:01:59 +02:00
Jonas Kvinge
feb0e1c45b Fix Fedora RPM suffix 2018-09-18 18:43:04 +02:00
Jonas Kvinge
edba837295 Fix RPM Suffix 2018-09-18 17:28:49 +02:00
Jonas Kvinge
55882360ef Fix RPM suffix 2018-09-18 00:45:33 +02:00
Jonas Kvinge
6039370ad6 Fix exclude 2018-09-18 00:45:07 +02:00
Jonas Kvinge
2d238c08d3 Change output filename 2018-09-18 00:31:21 +02:00
Jonas Kvinge
9b337b6a34 Add missing nsi 2018-09-17 19:30:23 +02:00
Jonas Kvinge
370db791aa Add nsi files for x86_64-w64-mingw32 2018-09-17 01:02:48 +02:00
Jonas Kvinge
9e3c547580 Turn back on git revision 2018-09-16 23:13:30 +02:00
Jonas Kvinge
ab5d9b62b8 Fix search error not shown in Tidal search 2018-09-15 22:34:44 +02:00
279 changed files with 9695 additions and 5625 deletions

2
.gitignore vendored
View File

@@ -38,6 +38,8 @@ Thumbs.db
*.nsi *.nsi
*.plist *.plist
maketarball.sh maketarball.sh
dist/debian/changelog
dist/pacman/PKGBUILD
# qtcreator generated files # qtcreator generated files
*.pro.user* *.pro.user*

View File

@@ -23,7 +23,7 @@ before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install chromaprint ; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install chromaprint ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export Qt5_DIR=/usr/local/opt/qt5/lib/cmake ; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export Qt5_DIR=/usr/local/opt/qt5/lib/cmake ; fi
before_script: before_script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild -DENABLE_STREAM_DEEZER=ON ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DFORCE_GIT_REVISION="0.0.0-0-g0000000"; fi - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DFORCE_GIT_REVISION="0.0.0-0-g0000000"; fi
script: script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi

View File

@@ -13,11 +13,11 @@ set(SINGLEAPP-MOC-HEADERS
qtsinglecoreapplication.h qtsinglecoreapplication.h
) )
if(WIN32) if(UNIX)
set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_win.cpp)
elseif(WIN32)
set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_unix.cpp) set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_unix.cpp)
endif(WIN32) elseif(WIN32)
set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_win.cpp)
endif()
QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS}) QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})

View File

@@ -157,7 +157,7 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout)
Sleep(DWORD(ms)); Sleep(DWORD(ms));
#else #else
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 }; struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL); nanosleep(&ts, nullptr);
#endif #endif
} }
if (!connOk) if (!connOk)

View File

@@ -58,7 +58,7 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
Qt::HANDLE mutex; Qt::HANDLE mutex;
if (doCreate) { if (doCreate) {
mutex = CreateMutexW(NULL, FALSE, (WCHAR*)mname.utf16()); mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16());
if (!mutex) { if (!mutex) {
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed"); qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
return 0; return 0;

View File

@@ -45,10 +45,6 @@
#include <QWidget> #include <QWidget>
#include <QString> #include <QString>
#ifdef HAVE_X11_ // FIXME
# include <X11/Xlib.h>
#endif
#include "qtlocalpeer.h" #include "qtlocalpeer.h"
/*! /*!
@@ -178,47 +174,6 @@ QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char *
} }
#if defined(HAVE_X11_) // FIXME
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
and \a cmap are passed on to the QApplication constructor.
*/
QtSingleApplication::QtSingleApplication(Display *dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, visual, cmap)
{
sysInit();
}
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
argv, \a visual, and \a cmap are passed on to the QApplication
constructor.
*/
QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, argc, argv, visual, cmap)
{
sysInit();
}
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be \a appId. \a dpy, \a argc, \a
argv, \a visual, and \a cmap are passed on to the QApplication
constructor.
*/
QtSingleApplication::QtSingleApplication(Display *dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, argc, argv, visual, cmap)
{
sysInit(appId);
}
#endif
/*! /*!
Returns true if another instance of this application is running; Returns true if another instance of this application is running;
otherwise false. otherwise false.

View File

@@ -48,10 +48,6 @@
#include <QApplication> #include <QApplication>
#include <QString> #include <QString>
#if defined(HAVE_X11_) // FIXME
# include <X11/Xlib.h>
#endif
class QtLocalPeer; class QtLocalPeer;
#if defined(Q_OS_WIN) || defined(Q_OS_WIN32) #if defined(Q_OS_WIN) || defined(Q_OS_WIN32)
@@ -77,11 +73,6 @@ class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
public: public:
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true); QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
QtSingleApplication(const QString &id, int &argc, char **argv); QtSingleApplication(const QString &id, int &argc, char **argv);
#if defined(HAVE_X11_) // FIXME
QtSingleApplication(Display *dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
QtSingleApplication(Display *dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
#endif
bool isRunning(); bool isRunning();
QString id() const; QString id() const;

View File

@@ -1,6 +1,13 @@
cmake_minimum_required(VERSION 2.8.11) cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
if (UNIX AND NOT APPLE)
find_package(X11)
if (X11_FOUND)
include_directories(${X11_INCLUDE_DIR})
endif(X11_FOUND)
endif(UNIX AND NOT APPLE)
include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS}) include_directories(${Qt5Gui_PRIVATE_INCLUDE_DIRS})
if (NOT WIN32 AND NOT APPLE) if (NOT WIN32 AND NOT APPLE)
find_path(HAVE_QPA_QPLATFORMNATIVEINTERFACE_H qpa/qplatformnativeinterface.h PATHS ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) find_path(HAVE_QPA_QPLATFORMNATIVEINTERFACE_H qpa/qplatformnativeinterface.h PATHS ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
@@ -9,25 +16,16 @@ if (NOT WIN32 AND NOT APPLE)
endif(NOT HAVE_QPA_QPLATFORMNATIVEINTERFACE_H) endif(NOT HAVE_QPA_QPLATFORMNATIVEINTERFACE_H)
endif(NOT WIN32 AND NOT APPLE) endif(NOT WIN32 AND NOT APPLE)
set(QXT-SOURCES set(QXT-SOURCES qxtglobal.cpp qxtglobalshortcut.cpp)
qxtglobal.cpp set(QXT-MOC-HEADERS qxtglobalshortcut.h )
qxtglobalshortcut.cpp
)
set(QXT-MOC-HEADERS if(X11_FOUND)
qxtglobalshortcut.h set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_x11.cpp)
)
find_package(X11)
include_directories(${X11_INCLUDE_DIR})
if(WIN32)
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp)
elseif(APPLE) elseif(APPLE)
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_mac.cpp) set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_mac.cpp)
else(WIN32) elseif(WIN32)
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_x11.cpp) set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp)
endif(WIN32) endif()
QT5_WRAP_CPP(QXT-SOURCES-MOC ${QXT-MOC-HEADERS}) QT5_WRAP_CPP(QXT-SOURCES-MOC ${QXT-MOC-HEADERS})
@@ -36,8 +34,8 @@ ADD_LIBRARY(qxt STATIC
${QXT-SOURCES-MOC} ${QXT-SOURCES-MOC}
) )
if(WIN32) target_link_libraries(qxt Qt5::Core Qt5::Widgets)
target_link_libraries(qxt Qt5::Core Qt5::Widgets)
else(WIN32) if(X11_FOUND)
target_link_libraries(qxt Qt5::Core Qt5::Widgets Qt5::X11Extras) target_link_libraries(qxt Qt5::X11Extras)
endif(WIN32) endif(X11_FOUND)

View File

@@ -1,4 +1,3 @@
/**************************************************************************** /****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project. ** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** See the Qxt AUTHORS file for a list of authors and copyright holders.

View File

@@ -1,4 +1,3 @@
/**************************************************************************** /****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project. ** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** See the Qxt AUTHORS file for a list of authors and copyright holders.
@@ -161,73 +160,73 @@ template <typename PUB>
class QxtPrivate class QxtPrivate
{ {
public: public:
virtual ~QxtPrivate() virtual ~QxtPrivate()
{} {}
inline void QXT_setPublic(PUB* pub) inline void QXT_setPublic(PUB* pub)
{ {
qxt_p_ptr = pub; qxt_p_ptr = pub;
} }
protected: protected:
inline PUB& qxt_p() inline PUB& qxt_p()
{ {
return *qxt_p_ptr; return *qxt_p_ptr;
} }
inline const PUB& qxt_p() const inline const PUB& qxt_p() const
{ {
return *qxt_p_ptr; return *qxt_p_ptr;
} }
inline PUB* qxt_ptr() inline PUB* qxt_ptr()
{ {
return qxt_p_ptr; return qxt_p_ptr;
} }
inline const PUB* qxt_ptr() const inline const PUB* qxt_ptr() const
{ {
return qxt_p_ptr; return qxt_p_ptr;
} }
private: private:
PUB* qxt_p_ptr; PUB* qxt_p_ptr;
}; };
template <typename PUB, typename PVT> template <typename PUB, typename PVT>
class QxtPrivateInterface class QxtPrivateInterface
{ {
friend class QxtPrivate<PUB>; friend class QxtPrivate<PUB>;
public: public:
QxtPrivateInterface() QxtPrivateInterface()
{ {
pvt = new PVT; pvt = new PVT;
} }
~QxtPrivateInterface() ~QxtPrivateInterface()
{ {
delete pvt; delete pvt;
} }
inline void setPublic(PUB* pub) inline void setPublic(PUB* pub)
{ {
pvt->QXT_setPublic(pub); pvt->QXT_setPublic(pub);
} }
inline PVT& operator()() inline PVT& operator()()
{ {
return *static_cast<PVT*>(pvt); return *static_cast<PVT*>(pvt);
} }
inline const PVT& operator()() const inline const PVT& operator()() const
{ {
return *static_cast<PVT*>(pvt); return *static_cast<PVT*>(pvt);
} }
inline PVT * operator->() inline PVT * operator->()
{ {
return static_cast<PVT*>(pvt); return static_cast<PVT*>(pvt);
} }
inline const PVT * operator->() const inline const PVT * operator->() const
{ {
return static_cast<PVT*>(pvt); return static_cast<PVT*>(pvt);
} }
private: private:
QxtPrivateInterface(const QxtPrivateInterface&) { } QxtPrivateInterface(const QxtPrivateInterface&) { }
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { } QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
QxtPrivate<PUB>* pvt; QxtPrivate<PUB>* pvt;
}; };
#endif // QXT_GLOBAL #endif // QXT_GLOBAL

View File

@@ -38,185 +38,160 @@
#include "qxtglobalshortcut_p.h" #include "qxtglobalshortcut_p.h"
bool QxtGlobalShortcutPrivate::error = false; bool QxtGlobalShortcutPrivate::error = false;
#ifndef Q_OS_MAC #ifndef Q_OS_MACOS
int QxtGlobalShortcutPrivate::ref = 0; int QxtGlobalShortcutPrivate::ref = 0;
#if QT_VERSION < QT_VERSION_CHECK(5,0,0) #endif // Q_OS_MACOS
QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0;
#endif
#endif // Q_OS_MAC
QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts; QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts;
QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) {
{ #ifndef Q_OS_MACOS
#ifndef Q_OS_MAC if (!ref++)
if (!ref++)
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter);
#else
QAbstractEventDispatcher::instance()->installNativeEventFilter(this); QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
#endif #endif // Q_OS_MACOS
#endif // Q_OS_MAC
} }
QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() {
{ #ifndef Q_OS_MACOS
#ifndef Q_OS_MAC if (!--ref)
if (!--ref) QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
#if QT_VERSION < QT_VERSION_CHECK(5,0,0) #endif // Q_OS_MACOS
QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter);
#else
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
#endif
#endif // Q_OS_MAC
} }
bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) {
{
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier; Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]); key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]);
mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods); mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods);
const quint32 nativeKey = nativeKeycode(key); const quint32 nativeKey = nativeKeycode(key);
const quint32 nativeMods = nativeModifiers(mods); const quint32 nativeMods = nativeModifiers(mods);
const bool res = registerShortcut(nativeKey, nativeMods); const bool res = registerShortcut(nativeKey, nativeMods);
if (res) if (res)
shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p()); shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
else else
qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString(); qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString();
return res; return res;
} }
bool QxtGlobalShortcutPrivate::unsetShortcut() bool QxtGlobalShortcutPrivate::unsetShortcut() {
{ bool res = false;
bool res = false; const quint32 nativeKey = nativeKeycode(key);
const quint32 nativeKey = nativeKeycode(key); const quint32 nativeMods = nativeModifiers(mods);
const quint32 nativeMods = nativeModifiers(mods); if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p())
if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p()) res = unregisterShortcut(nativeKey, nativeMods);
res = unregisterShortcut(nativeKey, nativeMods); if (res)
if (res) shortcuts.remove(qMakePair(nativeKey, nativeMods));
shortcuts.remove(qMakePair(nativeKey, nativeMods)); else
else qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString();
qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString(); key = Qt::Key(0);
key = Qt::Key(0); mods = Qt::KeyboardModifiers(0);
mods = Qt::KeyboardModifiers(0); return res;
return res;
} }
void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) {
{ QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods)); if (shortcut && shortcut->isEnabled())
if (shortcut && shortcut->isEnabled()) emit shortcut->activated();
emit shortcut->activated();
} }
/*! /*!
\class QxtGlobalShortcut \class QxtGlobalShortcut
\inmodule QxtWidgets \inmodule QxtWidgets
\brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey". \brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey".
A global shortcut triggers even if the application is not active. This A global shortcut triggers even if the application is not active. This
makes it easy to implement applications that react to certain shortcuts makes it easy to implement applications that react to certain shortcuts
still if some other application is active or if the application is for still if some other application is active or if the application is for
example minimized to the system tray. example minimized to the system tray.
Example usage: Example usage:
\code \code
QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window); QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility())); connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12")); shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));
\endcode \endcode
\bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication. \bold {Note:} Since Qxt 0.6 QxtGlobalShortcut no more requires QxtApplication.
*/ */
/*! /*!
\fn QxtGlobalShortcut::activated() \fn QxtGlobalShortcut::activated()
This signal is emitted when the user types the shortcut's key sequence. This signal is emitted when the user types the shortcut's key sequence.
\sa shortcut \sa shortcut
*/ */
/*! /*!
Constructs a new QxtGlobalShortcut with \a parent. Constructs a new QxtGlobalShortcut with \a parent.
*/ */
QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) : QObject(parent) {
: QObject(parent) QXT_INIT_PRIVATE(QxtGlobalShortcut);
{
QXT_INIT_PRIVATE(QxtGlobalShortcut);
} }
/*! /*!
Constructs a new QxtGlobalShortcut with \a shortcut and \a parent. Constructs a new QxtGlobalShortcut with \a shortcut and \a parent.
*/ */
QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) : QObject(parent) {
: QObject(parent) QXT_INIT_PRIVATE(QxtGlobalShortcut);
{ setShortcut(shortcut);
QXT_INIT_PRIVATE(QxtGlobalShortcut);
setShortcut(shortcut);
} }
/*! /*!
Destructs the QxtGlobalShortcut. Destructs the QxtGlobalShortcut.
*/ */
QxtGlobalShortcut::~QxtGlobalShortcut() QxtGlobalShortcut::~QxtGlobalShortcut() {
{ if (qxt_d().key != 0) qxt_d().unsetShortcut();
if (qxt_d().key != 0)
qxt_d().unsetShortcut();
} }
/*! /*!
\property QxtGlobalShortcut::shortcut \property QxtGlobalShortcut::shortcut
\brief the shortcut key sequence \brief the shortcut key sequence
\bold {Note:} Notice that corresponding key press and release events are not \bold {Note:} Notice that corresponding key press and release events are not
delivered for registered global shortcuts even if they are disabled. delivered for registered global shortcuts even if they are disabled.
Also, comma separated key sequences are not supported. Also, comma separated key sequences are not supported.
Only the first part is used: Only the first part is used:
\code \code
qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B")); qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B"));
Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A")); Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A"));
\endcode \endcode
*/ */
QKeySequence QxtGlobalShortcut::shortcut() const QKeySequence QxtGlobalShortcut::shortcut() const {
{ return QKeySequence(qxt_d().key | qxt_d().mods);
return QKeySequence(qxt_d().key | qxt_d().mods);
} }
bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) {
{ if (qxt_d().key != 0)
if (qxt_d().key != 0) qxt_d().unsetShortcut();
qxt_d().unsetShortcut(); return qxt_d().setShortcut(shortcut);
return qxt_d().setShortcut(shortcut);
} }
/*! /*!
\property QxtGlobalShortcut::enabled \property QxtGlobalShortcut::enabled
\brief whether the shortcut is enabled \brief whether the shortcut is enabled
A disabled shortcut does not get activated. A disabled shortcut does not get activated.
The default value is \c true. The default value is \c true.
\sa setDisabled() \sa setDisabled()
*/ */
bool QxtGlobalShortcut::isEnabled() const bool QxtGlobalShortcut::isEnabled() const {
{ return qxt_d().enabled;
return qxt_d().enabled;
} }
void QxtGlobalShortcut::setEnabled(bool enabled) void QxtGlobalShortcut::setEnabled(bool enabled) {
{ qxt_d().enabled = enabled;
qxt_d().enabled = enabled;
} }
/*! /*!
Sets the shortcut \a disabled. Sets the shortcut \a disabled.
\sa enabled \sa enabled
*/ */
void QxtGlobalShortcut::setDisabled(bool disabled) void QxtGlobalShortcut::setDisabled(bool disabled) {
{ qxt_d().enabled = !disabled;
qxt_d().enabled = !disabled;
} }

View File

@@ -1,4 +1,3 @@
#ifndef QXTGLOBALSHORTCUT_H
/**************************************************************************** /****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project. ** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** See the Qxt AUTHORS file for a list of authors and copyright holders.
@@ -29,6 +28,7 @@
** <http://libqxt.org> <foundation@libqxt.org> ** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/ *****************************************************************************/
#ifndef QXTGLOBALSHORTCUT_H
#define QXTGLOBALSHORTCUT_H #define QXTGLOBALSHORTCUT_H
#include <QObject> #include <QObject>
@@ -39,30 +39,29 @@
class QxtGlobalShortcutPrivate; class QxtGlobalShortcutPrivate;
class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject {
{ Q_OBJECT
Q_OBJECT QXT_DECLARE_PRIVATE(QxtGlobalShortcut)
QXT_DECLARE_PRIVATE(QxtGlobalShortcut) Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled) Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
public: public:
explicit QxtGlobalShortcut(QObject* parent = 0); explicit QxtGlobalShortcut(QObject* parent = nullptr);
explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0); explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = nullptr);
virtual ~QxtGlobalShortcut(); ~QxtGlobalShortcut();
QKeySequence shortcut() const; QKeySequence shortcut() const;
bool setShortcut(const QKeySequence& shortcut); bool setShortcut(const QKeySequence& shortcut);
bool isEnabled() const; bool isEnabled() const;
public Q_SLOTS: public Q_SLOTS:
void setEnabled(bool enabled = true); void setEnabled(bool enabled = true);
void setDisabled(bool disabled = true); void setDisabled(bool disabled = true);
Q_SIGNALS: Q_SIGNALS:
void activated(); void activated();
}; };
#endif // QXTGLOBALSHORTCUT_H #endif // QXTGLOBALSHORTCUT_H

View File

@@ -1,4 +1,3 @@
#include <Carbon/Carbon.h>
/**************************************************************************** /****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project. ** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** See the Qxt AUTHORS file for a list of authors and copyright holders.
@@ -29,230 +28,180 @@
** <http://libqxt.org> <foundation@libqxt.org> ** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/ *****************************************************************************/
#include "qxtglobalshortcut_p.h" #include <Carbon/Carbon.h>
#include <QMap>
#include <QHash> #include "qxtglobalshortcut_p.h"
#include <QtDebug> #include <QMap>
#include <QApplication> #include <QHash>
#include <QPair>
typedef QPair<uint, uint> Identifier; #include <QtDebug>
static QMap<quint32, EventHotKeyRef> keyRefs; #include <QApplication>
static QHash<Identifier, quint32> keyIDs;
static quint32 hotKeySerial = 0; typedef QPair<uint, uint> Identifier;
static bool qxt_mac_handler_installed = false; static QMap<quint32, EventHotKeyRef> keyRefs;
static QHash<Identifier, quint32> keyIDs;
OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) static quint32 hotKeySerial = 0;
{ static bool qxt_mac_handler_installed = false;
Q_UNUSED(nextHandler);
Q_UNUSED(data); OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) {
if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
{ Q_UNUSED(nextHandler);
EventHotKeyID keyID; Q_UNUSED(data);
GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID); if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) {
Identifier id = keyIDs.key(keyID.id); EventHotKeyID keyID;
QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first); GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(keyID), nullptr, &keyID);
} Identifier id = keyIDs.key(keyID.id);
return noErr; QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first);
} }
return noErr;
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
{ }
quint32 native = 0;
if (modifiers & Qt::ShiftModifier) quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
native |= shiftKey;
if (modifiers & Qt::ControlModifier) quint32 native = 0;
native |= cmdKey; if (modifiers & Qt::ShiftModifier) native |= shiftKey;
if (modifiers & Qt::AltModifier) if (modifiers & Qt::ControlModifier) native |= cmdKey;
native |= optionKey; if (modifiers & Qt::AltModifier) native |= optionKey;
if (modifiers & Qt::MetaModifier) if (modifiers & Qt::MetaModifier) native |= controlKey;
native |= controlKey; if (modifiers & Qt::KeypadModifier) native |= kEventKeyModifierNumLockMask;
if (modifiers & Qt::KeypadModifier) return native;
native |= kEventKeyModifierNumLockMask;
return native; }
}
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{ UTF16Char ch;
UTF16Char ch; // Constants found in NSEvent.h from AppKit.framework
// Constants found in NSEvent.h from AppKit.framework switch (key) {
switch (key) case Qt::Key_Return: return kVK_Return;
{ case Qt::Key_Enter: return kVK_ANSI_KeypadEnter;
case Qt::Key_Return: case Qt::Key_Tab: return kVK_Tab;
return kVK_Return; case Qt::Key_Space: return kVK_Space;
case Qt::Key_Enter: case Qt::Key_Backspace: return kVK_Delete;
return kVK_ANSI_KeypadEnter; case Qt::Key_Control: return kVK_Command;
case Qt::Key_Tab: case Qt::Key_Shift: return kVK_Shift;
return kVK_Tab; case Qt::Key_CapsLock: return kVK_CapsLock;
case Qt::Key_Space: case Qt::Key_Option: return kVK_Option;
return kVK_Space; case Qt::Key_Meta: return kVK_Control;
case Qt::Key_Backspace: case Qt::Key_F17: return kVK_F17;
return kVK_Delete; case Qt::Key_VolumeUp: return kVK_VolumeUp;
case Qt::Key_Control: case Qt::Key_VolumeDown: return kVK_VolumeDown;
return kVK_Command; case Qt::Key_F18: return kVK_F18;
case Qt::Key_Shift: case Qt::Key_F19: return kVK_F19;
return kVK_Shift; case Qt::Key_F20: return kVK_F20;
case Qt::Key_CapsLock: case Qt::Key_F5: return kVK_F5;
return kVK_CapsLock; case Qt::Key_F6: return kVK_F6;
case Qt::Key_Option: case Qt::Key_F7: return kVK_F7;
return kVK_Option; case Qt::Key_F3: return kVK_F3;
case Qt::Key_Meta: case Qt::Key_F8: return kVK_F8;
return kVK_Control; case Qt::Key_F9: return kVK_F9;
case Qt::Key_F17: case Qt::Key_F11: return kVK_F11;
return kVK_F17; case Qt::Key_F13: return kVK_F13;
case Qt::Key_VolumeUp: case Qt::Key_F16: return kVK_F16;
return kVK_VolumeUp; case Qt::Key_F14: return kVK_F14;
case Qt::Key_VolumeDown: case Qt::Key_F10: return kVK_F10;
return kVK_VolumeDown; case Qt::Key_F12: return kVK_F12;
case Qt::Key_F18: case Qt::Key_F15: return kVK_F15;
return kVK_F18; case Qt::Key_Help: return kVK_Help;
case Qt::Key_F19: case Qt::Key_Home: return kVK_Home;
return kVK_F19; case Qt::Key_PageUp: return kVK_PageUp;
case Qt::Key_F20: case Qt::Key_Delete: return kVK_ForwardDelete;
return kVK_F20; case Qt::Key_F4: return kVK_F4;
case Qt::Key_F5: case Qt::Key_End: return kVK_End;
return kVK_F5; case Qt::Key_F2: return kVK_F2;
case Qt::Key_F6: case Qt::Key_PageDown: return kVK_PageDown;
return kVK_F6; case Qt::Key_F1: return kVK_F1;
case Qt::Key_F7: case Qt::Key_Left: return kVK_LeftArrow;
return kVK_F7; case Qt::Key_Right: return kVK_RightArrow;
case Qt::Key_F3: case Qt::Key_Down: return kVK_DownArrow;
return kVK_F3; case Qt::Key_Up: return kVK_UpArrow;
case Qt::Key_F8: default:
return kVK_F8; ;
case Qt::Key_F9: }
return kVK_F9;
case Qt::Key_F11: if (key == Qt::Key_Escape) ch = 27;
return kVK_F11; else if (key == Qt::Key_Return) ch = 13;
case Qt::Key_F13: else if (key == Qt::Key_Enter) ch = 3;
return kVK_F13; else if (key == Qt::Key_Tab) ch = 9;
case Qt::Key_F16: else ch = key;
return kVK_F16;
case Qt::Key_F14: CFDataRef currentLayoutData;
return kVK_F14; TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
case Qt::Key_F10:
return kVK_F10; if (currentKeyboard == nullptr)
case Qt::Key_F12: return 0;
return kVK_F12;
case Qt::Key_F15: currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
return kVK_F15; CFRelease(currentKeyboard);
case Qt::Key_Help: if (currentLayoutData == nullptr)
return kVK_Help; return 0;
case Qt::Key_Home:
return kVK_Home; UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
case Qt::Key_PageUp: UCKeyboardTypeHeader* table = header->keyboardTypeList;
return kVK_PageUp;
case Qt::Key_Delete: uint8_t *data = (uint8_t*)header;
return kVK_ForwardDelete; // God, would a little documentation for this shit kill you...
case Qt::Key_F4: for (quint32 i=0; i < header->keyboardTypeCount; i++) {
return kVK_F4; UCKeyStateRecordsIndex* stateRec = 0;
case Qt::Key_End: if (table[i].keyStateRecordsIndexOffset != 0) {
return kVK_End; stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset);
case Qt::Key_F2: if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
return kVK_F2; }
case Qt::Key_PageDown:
return kVK_PageDown; UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset);
case Qt::Key_F1: if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
return kVK_F1;
case Qt::Key_Left: for (quint32 j=0; j < charTable->keyToCharTableCount; j++) {
return kVK_LeftArrow; UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]);
case Qt::Key_Right: for (quint32 k=0; k < charTable->keyToCharTableSize; k++) {
return kVK_RightArrow; if (keyToChar[k] & kUCKeyOutputTestForIndexMask) {
case Qt::Key_Down: long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
return kVK_DownArrow; if (stateRec && idx < stateRec->keyStateRecordCount) {
case Qt::Key_Up: UCKeyStateRecord* rec = reinterpret_cast<UCKeyStateRecord*>(data + stateRec->keyStateRecordOffsets[idx]);
return kVK_UpArrow; if (rec->stateZeroCharData == ch) return k;
default: }
; }
} else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE) {
if (keyToChar[k] == ch) return k;
if (key == Qt::Key_Escape) ch = 27; }
else if (key == Qt::Key_Return) ch = 13; } // for k
else if (key == Qt::Key_Enter) ch = 3; } // for j
else if (key == Qt::Key_Tab) ch = 9; } // for i
else ch = key; return 0;
CFDataRef currentLayoutData; }
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) {
if (currentKeyboard == NULL)
return 0; if (!qxt_mac_handler_installed) {
EventTypeSpec t;
currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData); t.eventClass = kEventClassKeyboard;
CFRelease(currentKeyboard); t.eventKind = kEventHotKeyPressed;
if (currentLayoutData == NULL) InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, nullptr, nullptr);
return 0; }
UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData); EventHotKeyID keyID;
UCKeyboardTypeHeader* table = header->keyboardTypeList; keyID.signature = 'cute';
keyID.id = ++hotKeySerial;
uint8_t *data = (uint8_t*)header;
// God, would a little documentation for this shit kill you... EventHotKeyRef ref = 0;
for (quint32 i=0; i < header->keyboardTypeCount; i++) bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
{ if (rv) {
UCKeyStateRecordsIndex* stateRec = 0; keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id);
if (table[i].keyStateRecordsIndexOffset != 0) keyRefs.insert(keyID.id, ref);
{ }
stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset); return rv;
if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
} }
UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset); bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) {
if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
Identifier id(nativeMods, nativeKey);
for (quint32 j=0; j < charTable->keyToCharTableCount; j++) if (!keyIDs.contains(id)) return false;
{
UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]); EventHotKeyRef ref = keyRefs.take(keyIDs[id]);
for (quint32 k=0; k < charTable->keyToCharTableSize; k++) keyIDs.remove(id);
{ return !UnregisterEventHotKey(ref);
if (keyToChar[k] & kUCKeyOutputTestForIndexMask)
{ }
long idx = keyToChar[k] & kUCKeyOutputGetIndexMask;
if (stateRec && idx < stateRec->keyStateRecordCount)
{
UCKeyStateRecord* rec = reinterpret_cast<UCKeyStateRecord*>(data + stateRec->keyStateRecordOffsets[idx]);
if (rec->stateZeroCharData == ch) return k;
}
}
else if (!(keyToChar[k] & kUCKeyOutputSequenceIndexMask) && keyToChar[k] < 0xFFFE)
{
if (keyToChar[k] == ch) return k;
}
} // for k
} // for j
} // for i
return 0;
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
{
if (!qxt_mac_handler_installed)
{
EventTypeSpec t;
t.eventClass = kEventClassKeyboard;
t.eventKind = kEventHotKeyPressed;
InstallApplicationEventHandler(&qxt_mac_handle_hot_key, 1, &t, NULL, NULL);
}
EventHotKeyID keyID;
keyID.signature = 'cute';
keyID.id = ++hotKeySerial;
EventHotKeyRef ref = 0;
bool rv = !RegisterEventHotKey(nativeKey, nativeMods, keyID, GetApplicationEventTarget(), 0, &ref);
if (rv)
{
keyIDs.insert(Identifier(nativeMods, nativeKey), keyID.id);
keyRefs.insert(keyID.id, ref);
}
return rv;
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
Identifier id(nativeMods, nativeKey);
if (!keyIDs.contains(id)) return false;
EventHotKeyRef ref = keyRefs.take(keyIDs[id]);
keyIDs.remove(id);
return !UnregisterEventHotKey(ref);
}

View File

@@ -1,84 +1,72 @@
#ifndef QXTGLOBALSHORTCUT_P_H /****************************************************************************
/**************************************************************************** ** Copyright (c) 2006 - 2011, the LibQxt project.
** Copyright (c) 2006 - 2011, the LibQxt project. ** See the Qxt AUTHORS file for a list of authors and copyright holders.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** All rights reserved.
** All rights reserved. **
** ** Redistribution and use in source and binary forms, with or without
** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are met:
** modification, are permitted provided that the following conditions are met: ** * Redistributions of source code must retain the above copyright
** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer.
** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright
** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the
** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution.
** documentation and/or other materials provided with the distribution. ** * Neither the name of the LibQxt project nor the
** * Neither the name of the LibQxt project nor the ** names of its contributors may be used to endorse or promote products
** names of its contributors may be used to endorse or promote products ** derived from this software without specific prior written permission.
** derived from this software without specific prior written permission. **
** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **
** ** <http://libqxt.org> <foundation@libqxt.org>
** <http://libqxt.org> <foundation@libqxt.org> *****************************************************************************/
*****************************************************************************/
#ifndef QXTGLOBALSHORTCUT_P_H
#define QXTGLOBALSHORTCUT_P_H #define QXTGLOBALSHORTCUT_P_H
#include "qxtglobalshortcut.h" #include "qxtglobalshortcut.h"
#include <QAbstractEventDispatcher>
#include <QKeySequence> #include <QHash>
#include <QHash> #include <QAbstractEventDispatcher>
#include <QAbstractNativeEventFilter>
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) #include <QKeySequence>
#include <QAbstractNativeEventFilter>
#endif class QxtGlobalShortcutPrivate : public QxtPrivate<QxtGlobalShortcut>, public QAbstractNativeEventFilter {
public:
QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
class QxtGlobalShortcutPrivate : public QxtPrivate<QxtGlobalShortcut> QxtGlobalShortcutPrivate();
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0) ~QxtGlobalShortcutPrivate();
,public QAbstractNativeEventFilter
#endif bool enabled;
{ Qt::Key key;
public: Qt::KeyboardModifiers mods;
QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
QxtGlobalShortcutPrivate(); bool setShortcut(const QKeySequence& shortcut);
~QxtGlobalShortcutPrivate(); bool unsetShortcut();
bool enabled; static bool error;
Qt::Key key; #ifndef Q_OS_MACOS
Qt::KeyboardModifiers mods; static int ref;
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
bool setShortcut(const QKeySequence& shortcut); #endif // Q_OS_MAC
bool unsetShortcut();
static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
static bool error;
#ifndef Q_OS_MAC private:
static int ref; static quint32 nativeKeycode(Qt::Key keycode);
#if QT_VERSION < QT_VERSION_CHECK(5,0,0) static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers);
static QAbstractEventDispatcher::EventFilter prevEventFilter;
static bool eventFilter(void* message); static bool registerShortcut(quint32 nativeKey, quint32 nativeMods);
#else static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods);
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
#endif // QT_VERSION < QT_VERSION_CHECK(5,0,0) static QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> shortcuts;
#endif // Q_OS_MAC };
static void activateShortcut(quint32 nativeKey, quint32 nativeMods); #endif // QXTGLOBALSHORTCUT_P_H
private:
static quint32 nativeKeycode(Qt::Key keycode);
static quint32 nativeModifiers(Qt::KeyboardModifiers modifiers);
static bool registerShortcut(quint32 nativeKey, quint32 nativeMods);
static bool unregisterShortcut(quint32 nativeKey, quint32 nativeMods);
static QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> shortcuts;
};
#endif // QXTGLOBALSHORTCUT_P_H

View File

@@ -1,247 +1,239 @@
#include "qxtglobalshortcut_p.h" #include "qxtglobalshortcut_p.h"
/**************************************************************************** /****************************************************************************
** Copyright (c) 2006 - 2011, the LibQxt project. ** Copyright (c) 2006 - 2011, the LibQxt project.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** See the Qxt AUTHORS file for a list of authors and copyright holders.
** All rights reserved. ** All rights reserved.
** **
** Redistribution and use in source and binary forms, with or without ** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are met: ** modification, are permitted provided that the following conditions are met:
** * Redistributions of source code must retain the above copyright ** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer. ** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright ** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the ** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution. ** documentation and/or other materials provided with the distribution.
** * Neither the name of the LibQxt project nor the ** * Neither the name of the LibQxt project nor the
** names of its contributors may be used to endorse or promote products ** names of its contributors may be used to endorse or promote products
** derived from this software without specific prior written permission. ** derived from this software without specific prior written permission.
** **
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY ** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** **
** <http://libqxt.org> <foundation@libqxt.org> ** <http://libqxt.org> <foundation@libqxt.org>
*****************************************************************************/ *****************************************************************************/
#include <qt_windows.h> #include <qt_windows.h>
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, void * message, long * result) {
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
bool QxtGlobalShortcutPrivate::eventFilter(void* message) Q_UNUSED(eventType);
{ Q_UNUSED(result);
#else MSG* msg = static_cast<MSG*>(message);
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, if (msg->message == WM_HOTKEY) {
void * message, long * result) const quint32 keycode = HIWORD(msg->lParam);
{ const quint32 modifiers = LOWORD(msg->lParam);
Q_UNUSED(eventType); activateShortcut(keycode, modifiers);
Q_UNUSED(result); }
#endif return false;
MSG* msg = static_cast<MSG*>(message);
if (msg->message == WM_HOTKEY) }
{
const quint32 keycode = HIWORD(msg->lParam);
const quint32 modifiers = LOWORD(msg->lParam); quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
activateShortcut(keycode, modifiers);
} // MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
return false; quint32 native = 0;
} if (modifiers & Qt::ShiftModifier)
native |= MOD_SHIFT;
if (modifiers & Qt::ControlModifier)
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) native |= MOD_CONTROL;
{ if (modifiers & Qt::AltModifier)
// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN native |= MOD_ALT;
quint32 native = 0; if (modifiers & Qt::MetaModifier)
if (modifiers & Qt::ShiftModifier) native |= MOD_WIN;
native |= MOD_SHIFT; // TODO: resolve these?
if (modifiers & Qt::ControlModifier) //if (modifiers & Qt::KeypadModifier)
native |= MOD_CONTROL; //if (modifiers & Qt::GroupSwitchModifier)
if (modifiers & Qt::AltModifier) return native;
native |= MOD_ALT;
if (modifiers & Qt::MetaModifier) }
native |= MOD_WIN;
// TODO: resolve these? quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
//if (modifiers & Qt::KeypadModifier)
//if (modifiers & Qt::GroupSwitchModifier) switch (key) {
return native; case Qt::Key_Escape:
} return VK_ESCAPE;
case Qt::Key_Tab:
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) case Qt::Key_Backtab:
{ return VK_TAB;
switch (key) case Qt::Key_Backspace:
{ return VK_BACK;
case Qt::Key_Escape: case Qt::Key_Return:
return VK_ESCAPE; case Qt::Key_Enter:
case Qt::Key_Tab: return VK_RETURN;
case Qt::Key_Backtab: case Qt::Key_Insert:
return VK_TAB; return VK_INSERT;
case Qt::Key_Backspace: case Qt::Key_Delete:
return VK_BACK; return VK_DELETE;
case Qt::Key_Return: case Qt::Key_Pause:
case Qt::Key_Enter: return VK_PAUSE;
return VK_RETURN; case Qt::Key_Print:
case Qt::Key_Insert: return VK_PRINT;
return VK_INSERT; case Qt::Key_Clear:
case Qt::Key_Delete: return VK_CLEAR;
return VK_DELETE; case Qt::Key_Home:
case Qt::Key_Pause: return VK_HOME;
return VK_PAUSE; case Qt::Key_End:
case Qt::Key_Print: return VK_END;
return VK_PRINT; case Qt::Key_Left:
case Qt::Key_Clear: return VK_LEFT;
return VK_CLEAR; case Qt::Key_Up:
case Qt::Key_Home: return VK_UP;
return VK_HOME; case Qt::Key_Right:
case Qt::Key_End: return VK_RIGHT;
return VK_END; case Qt::Key_Down:
case Qt::Key_Left: return VK_DOWN;
return VK_LEFT; case Qt::Key_PageUp:
case Qt::Key_Up: return VK_PRIOR;
return VK_UP; case Qt::Key_PageDown:
case Qt::Key_Right: return VK_NEXT;
return VK_RIGHT; case Qt::Key_F1:
case Qt::Key_Down: return VK_F1;
return VK_DOWN; case Qt::Key_F2:
case Qt::Key_PageUp: return VK_F2;
return VK_PRIOR; case Qt::Key_F3:
case Qt::Key_PageDown: return VK_F3;
return VK_NEXT; case Qt::Key_F4:
case Qt::Key_F1: return VK_F4;
return VK_F1; case Qt::Key_F5:
case Qt::Key_F2: return VK_F5;
return VK_F2; case Qt::Key_F6:
case Qt::Key_F3: return VK_F6;
return VK_F3; case Qt::Key_F7:
case Qt::Key_F4: return VK_F7;
return VK_F4; case Qt::Key_F8:
case Qt::Key_F5: return VK_F8;
return VK_F5; case Qt::Key_F9:
case Qt::Key_F6: return VK_F9;
return VK_F6; case Qt::Key_F10:
case Qt::Key_F7: return VK_F10;
return VK_F7; case Qt::Key_F11:
case Qt::Key_F8: return VK_F11;
return VK_F8; case Qt::Key_F12:
case Qt::Key_F9: return VK_F12;
return VK_F9; case Qt::Key_F13:
case Qt::Key_F10: return VK_F13;
return VK_F10; case Qt::Key_F14:
case Qt::Key_F11: return VK_F14;
return VK_F11; case Qt::Key_F15:
case Qt::Key_F12: return VK_F15;
return VK_F12; case Qt::Key_F16:
case Qt::Key_F13: return VK_F16;
return VK_F13; case Qt::Key_F17:
case Qt::Key_F14: return VK_F17;
return VK_F14; case Qt::Key_F18:
case Qt::Key_F15: return VK_F18;
return VK_F15; case Qt::Key_F19:
case Qt::Key_F16: return VK_F19;
return VK_F16; case Qt::Key_F20:
case Qt::Key_F17: return VK_F20;
return VK_F17; case Qt::Key_F21:
case Qt::Key_F18: return VK_F21;
return VK_F18; case Qt::Key_F22:
case Qt::Key_F19: return VK_F22;
return VK_F19; case Qt::Key_F23:
case Qt::Key_F20: return VK_F23;
return VK_F20; case Qt::Key_F24:
case Qt::Key_F21: return VK_F24;
return VK_F21; case Qt::Key_Space:
case Qt::Key_F22: return VK_SPACE;
return VK_F22; case Qt::Key_Asterisk:
case Qt::Key_F23: return VK_MULTIPLY;
return VK_F23; case Qt::Key_Plus:
case Qt::Key_F24: return VK_ADD;
return VK_F24; case Qt::Key_Comma:
case Qt::Key_Space: return VK_SEPARATOR;
return VK_SPACE; case Qt::Key_Minus:
case Qt::Key_Asterisk: return VK_SUBTRACT;
return VK_MULTIPLY; case Qt::Key_Slash:
case Qt::Key_Plus: return VK_DIVIDE;
return VK_ADD; case Qt::Key_MediaNext:
case Qt::Key_Comma: return VK_MEDIA_NEXT_TRACK;
return VK_SEPARATOR; case Qt::Key_MediaPrevious:
case Qt::Key_Minus: return VK_MEDIA_PREV_TRACK;
return VK_SUBTRACT; case Qt::Key_MediaPlay:
case Qt::Key_Slash: return VK_MEDIA_PLAY_PAUSE;
return VK_DIVIDE; case Qt::Key_MediaStop:
case Qt::Key_MediaNext: return VK_MEDIA_STOP;
return VK_MEDIA_NEXT_TRACK; // couldn't find those in VK_*
case Qt::Key_MediaPrevious: //case Qt::Key_MediaLast:
return VK_MEDIA_PREV_TRACK; //case Qt::Key_MediaRecord:
case Qt::Key_MediaPlay: case Qt::Key_VolumeDown:
return VK_MEDIA_PLAY_PAUSE; return VK_VOLUME_DOWN;
case Qt::Key_MediaStop: case Qt::Key_VolumeUp:
return VK_MEDIA_STOP; return VK_VOLUME_UP;
// couldn't find those in VK_* case Qt::Key_VolumeMute:
//case Qt::Key_MediaLast: return VK_VOLUME_MUTE;
//case Qt::Key_MediaRecord:
case Qt::Key_VolumeDown: // numbers
return VK_VOLUME_DOWN; case Qt::Key_0:
case Qt::Key_VolumeUp: case Qt::Key_1:
return VK_VOLUME_UP; case Qt::Key_2:
case Qt::Key_VolumeMute: case Qt::Key_3:
return VK_VOLUME_MUTE; case Qt::Key_4:
case Qt::Key_5:
// numbers case Qt::Key_6:
case Qt::Key_0: case Qt::Key_7:
case Qt::Key_1: case Qt::Key_8:
case Qt::Key_2: case Qt::Key_9:
case Qt::Key_3: return key;
case Qt::Key_4:
case Qt::Key_5: // letters
case Qt::Key_6: case Qt::Key_A:
case Qt::Key_7: case Qt::Key_B:
case Qt::Key_8: case Qt::Key_C:
case Qt::Key_9: case Qt::Key_D:
return key; case Qt::Key_E:
case Qt::Key_F:
// letters case Qt::Key_G:
case Qt::Key_A: case Qt::Key_H:
case Qt::Key_B: case Qt::Key_I:
case Qt::Key_C: case Qt::Key_J:
case Qt::Key_D: case Qt::Key_K:
case Qt::Key_E: case Qt::Key_L:
case Qt::Key_F: case Qt::Key_M:
case Qt::Key_G: case Qt::Key_N:
case Qt::Key_H: case Qt::Key_O:
case Qt::Key_I: case Qt::Key_P:
case Qt::Key_J: case Qt::Key_Q:
case Qt::Key_K: case Qt::Key_R:
case Qt::Key_L: case Qt::Key_S:
case Qt::Key_M: case Qt::Key_T:
case Qt::Key_N: case Qt::Key_U:
case Qt::Key_O: case Qt::Key_V:
case Qt::Key_P: case Qt::Key_W:
case Qt::Key_Q: case Qt::Key_X:
case Qt::Key_R: case Qt::Key_Y:
case Qt::Key_S: case Qt::Key_Z:
case Qt::Key_T: return key;
case Qt::Key_U:
case Qt::Key_V: default:
case Qt::Key_W: return 0;
case Qt::Key_X: }
case Qt::Key_Y:
case Qt::Key_Z: }
return key;
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) {
default: return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);
return 0; }
}
} bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) {
return UnregisterHotKey(0, nativeMods ^ nativeKey);
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) }
{
return RegisterHotKey(0, nativeMods ^ nativeKey, nativeMods, nativeKey);
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
return UnregisterHotKey(0, nativeMods ^ nativeKey);
}

View File

@@ -1,263 +1,236 @@
#include "qxtglobalshortcut_p.h" /****************************************************************************
/**************************************************************************** ** Copyright (c) 2006 - 2011, the LibQxt project.
** Copyright (c) 2006 - 2011, the LibQxt project. ** See the Qxt AUTHORS file for a list of authors and copyright holders.
** See the Qxt AUTHORS file for a list of authors and copyright holders. ** All rights reserved.
** All rights reserved. **
** ** Redistribution and use in source and binary forms, with or without
** Redistribution and use in source and binary forms, with or without ** modification, are permitted provided that the following conditions are met:
** modification, are permitted provided that the following conditions are met: ** * Redistributions of source code must retain the above copyright
** * Redistributions of source code must retain the above copyright ** notice, this list of conditions and the following disclaimer.
** notice, this list of conditions and the following disclaimer. ** * Redistributions in binary form must reproduce the above copyright
** * Redistributions in binary form must reproduce the above copyright ** notice, this list of conditions and the following disclaimer in the
** notice, this list of conditions and the following disclaimer in the ** documentation and/or other materials provided with the distribution.
** documentation and/or other materials provided with the distribution. ** * Neither the name of the LibQxt project nor the
** * Neither the name of the LibQxt project nor the ** names of its contributors may be used to endorse or promote products
** names of its contributors may be used to endorse or promote products ** derived from this software without specific prior written permission.
** derived from this software without specific prior written permission. **
** ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY ** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **
** ** <http://libqxt.org> <foundation@libqxt.org>
** <http://libqxt.org> <foundation@libqxt.org> *****************************************************************************/
*****************************************************************************/
#include "qxtglobalshortcut_p.h"
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
# include <QX11Info> #include <QtGlobal>
#else #include <QApplication>
# include <qpa/qplatformnativeinterface.h> #include <QGuiApplication>
# include <xcb/xcb.h> #include <QKeySequence>
# include <QApplication> #include <QByteArray>
#endif #include <QString>
#include <X11/X.h> #include <QVector>
#include <X11/Xlib.h> #include <QX11Info>
#include <xcb/xproto.h>
#include <qpa/qplatformnativeinterface.h>
#include <QtGlobal>
#include <QByteArray> #include <X11/X.h>
#include <QGuiApplication> #include <X11/Xlib.h>
#include <QKeySequence> #include <xcb/xcb.h>
#include <QString> #include <xcb/xproto.h>
#include <QVector>
#include "keymapper_x11.h"
#include "keymapper_x11.h"
namespace {
namespace {
const QVector<quint32> maskModifiers = QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
const QVector<quint32> maskModifiers = QVector<quint32>()
<< 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask); typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event);
typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event); class QxtX11ErrorHandler {
public:
class QxtX11ErrorHandler { static bool error;
public:
static bool error; static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) {
Q_UNUSED(display);
static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) switch (event->error_code) {
{ case BadAccess:
Q_UNUSED(display); case BadValue:
switch (event->error_code) case BadWindow:
{ if (event->request_code == 33 /* X_GrabKey */ ||
case BadAccess: event->request_code == 34 /* X_UngrabKey */)
case BadValue: {
case BadWindow: error = true;
if (event->request_code == 33 /* X_GrabKey */ || //TODO:
event->request_code == 34 /* X_UngrabKey */) //char errstr[256];
{ //XGetErrorText(dpy, err->error_code, errstr, 256);
error = true; }
//TODO: }
//char errstr[256]; return 0;
//XGetErrorText(dpy, err->error_code, errstr, 256); }
}
} QxtX11ErrorHandler() {
return 0; error = false;
} m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler);
}
QxtX11ErrorHandler()
{ ~QxtX11ErrorHandler() {
error = false; XSetErrorHandler(m_previousErrorHandler);
m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler); }
}
private:
~QxtX11ErrorHandler() X11ErrorHandler m_previousErrorHandler;
{ };
XSetErrorHandler(m_previousErrorHandler);
} bool QxtX11ErrorHandler::error = false;
private: class QxtX11Data {
X11ErrorHandler m_previousErrorHandler; public:
}; QxtX11Data() {
QPlatformNativeInterface *native = qApp->platformNativeInterface();
bool QxtX11ErrorHandler::error = false; //void *display = native->nativeResourceForScreen(QByteArray("display"), QGuiApplication::primaryScreen());
//m_display = reinterpret_cast<Display *>(display);
class QxtX11Data { m_display = QX11Info::display();
public: }
QxtX11Data()
{ bool isValid() {
#if QT_VERSION < QT_VERSION_CHECK(5,0,0) return m_display != nullptr;
m_display = QX11Info::display(); }
#else
QPlatformNativeInterface *native = qApp->platformNativeInterface(); Display *display() {
void *display = native->nativeResourceForScreen(QByteArray("display"), Q_ASSERT(isValid());
QGuiApplication::primaryScreen()); return m_display;
m_display = reinterpret_cast<Display *>(display); }
#endif
} Window rootWindow() {
return DefaultRootWindow(display());
bool isValid() }
{
return m_display != 0; bool grabKey(quint32 keycode, quint32 modifiers, Window window) {
} QxtX11ErrorHandler errorHandler;
Display *display() for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) {
{ XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, GrabModeAsync, GrabModeAsync);
Q_ASSERT(isValid()); }
return m_display;
} if (errorHandler.error) {
ungrabKey(keycode, modifiers, window);
Window rootWindow() return false;
{ }
return DefaultRootWindow(display());
} return true;
}
bool grabKey(quint32 keycode, quint32 modifiers, Window window)
{ bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) {
QxtX11ErrorHandler errorHandler; QxtX11ErrorHandler errorHandler;
for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) { foreach (quint32 maskMods, maskModifiers) {
XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, XUngrabKey(display(), keycode, modifiers | maskMods, window);
GrabModeAsync, GrabModeAsync); }
}
return !errorHandler.error;
if (errorHandler.error) { }
ungrabKey(keycode, modifiers, window);
return false; private:
} Display *m_display;
};
return true;
} } // namespace
bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, void *message, long *result) {
{
QxtX11ErrorHandler errorHandler; Q_UNUSED(result);
foreach (quint32 maskMods, maskModifiers) { xcb_key_press_event_t *kev = nullptr;
XUngrabKey(display(), keycode, modifiers | maskMods, window); if (eventType == "xcb_generic_event_t") {
} xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message);
if ((ev->response_type & 127) == XCB_KEY_PRESS)
return !errorHandler.error; kev = static_cast<xcb_key_press_event_t *>(message);
} }
private: if (kev != nullptr) {
Display *m_display; unsigned int keycode = kev->detail;
}; unsigned int keystate = 0;
if(kev->state & XCB_MOD_MASK_1)
} // namespace keystate |= Mod1Mask;
if(kev->state & XCB_MOD_MASK_CONTROL)
#if QT_VERSION < QT_VERSION_CHECK(5,0,0) keystate |= ControlMask;
bool QxtGlobalShortcutPrivate::eventFilter(void *message) if(kev->state & XCB_MOD_MASK_4)
{ keystate |= Mod4Mask;
XEvent *event = static_cast<XEvent *>(message); if(kev->state & XCB_MOD_MASK_SHIFT)
if (event->type == KeyPress) keystate |= ShiftMask;
{
XKeyEvent *key = reinterpret_cast<XKeyEvent *>(event); activateShortcut(keycode,
unsigned int keycode = key->keycode; // Mod1Mask == Alt, Mod4Mask == Meta
unsigned int keystate = key->state; keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
#else }
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, return false;
void *message, long *result)
{ }
Q_UNUSED(result);
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
xcb_key_press_event_t *kev = 0;
if (eventType == "xcb_generic_event_t") { // ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
xcb_generic_event_t *ev = static_cast<xcb_generic_event_t *>(message); quint32 native = 0;
if ((ev->response_type & 127) == XCB_KEY_PRESS) if (modifiers & Qt::ShiftModifier)
kev = static_cast<xcb_key_press_event_t *>(message); native |= ShiftMask;
} if (modifiers & Qt::ControlModifier)
native |= ControlMask;
if (kev != 0) { if (modifiers & Qt::AltModifier)
unsigned int keycode = kev->detail; native |= Mod1Mask;
unsigned int keystate = 0; if (modifiers & Qt::MetaModifier)
if(kev->state & XCB_MOD_MASK_1) native |= Mod4Mask;
keystate |= Mod1Mask;
if(kev->state & XCB_MOD_MASK_CONTROL) // TODO: resolve these?
keystate |= ControlMask; //if (modifiers & Qt::MetaModifier)
if(kev->state & XCB_MOD_MASK_4) //if (modifiers & Qt::KeypadModifier)
keystate |= Mod4Mask; //if (modifiers & Qt::GroupSwitchModifier)
if(kev->state & XCB_MOD_MASK_SHIFT) return native;
keystate |= ShiftMask;
#endif }
activateShortcut(keycode,
// Mod1Mask == Alt, Mod4Mask == Meta quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
} // (davidsansome) Try the table from QKeyMapper first - this seems to be
return false; // the only way to get Keysyms for the media keys.
} unsigned int keysym = 0;
int i = 0;
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) while (KeyTbl[i]) {
{ if (KeyTbl[i+1] == static_cast<uint>(key)) {
// ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask keysym = KeyTbl[i];
quint32 native = 0; break;
if (modifiers & Qt::ShiftModifier) }
native |= ShiftMask; i += 2;
if (modifiers & Qt::ControlModifier) }
native |= ControlMask;
if (modifiers & Qt::AltModifier) // If that didn't work then fall back on XStringToKeysym
native |= Mod1Mask; if (!keysym) {
if (modifiers & Qt::MetaModifier) keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
native |= Mod4Mask; if (keysym == NoSymbol)
keysym = static_cast<ushort>(key);
// TODO: resolve these? }
//if (modifiers & Qt::MetaModifier)
//if (modifiers & Qt::KeypadModifier) QxtX11Data x11;
//if (modifiers & Qt::GroupSwitchModifier) if (!x11.isValid())
return native; return 0;
}
return XKeysymToKeycode(x11.display(), keysym);
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
{ }
// (davidsansome) Try the table from QKeyMapper first - this seems to be
// the only way to get Keysyms for the media keys. bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods) {
unsigned int keysym = 0; QxtX11Data x11;
int i = 0; return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow());
while (KeyTbl[i]) { }
if (KeyTbl[i+1] == static_cast<uint>(key)) {
keysym = KeyTbl[i]; bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods) {
break; QxtX11Data x11;
} return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow());
i += 2; }
}
// If that didn't work then fall back on XStringToKeysym
if (!keysym) {
keysym = XStringToKeysym(QKeySequence(key).toString().toLatin1().data());
if (keysym == NoSymbol)
keysym = static_cast<ushort>(key);
}
QxtX11Data x11;
if (!x11.isValid())
return 0;
return XKeysymToKeycode(x11.display(), keysym);
}
bool QxtGlobalShortcutPrivate::registerShortcut(quint32 nativeKey, quint32 nativeMods)
{
QxtX11Data x11;
return x11.isValid() && x11.grabKey(nativeKey, nativeMods, x11.rootWindow());
}
bool QxtGlobalShortcutPrivate::unregisterShortcut(quint32 nativeKey, quint32 nativeMods)
{
QxtX11Data x11;
return x11.isValid() && x11.ungrabKey(nativeKey, nativeMods, x11.rootWindow());
}

View File

@@ -28,6 +28,7 @@
#include <id3v2tag.h> #include <id3v2tag.h>
#include <tstringlist.h> #include <tstringlist.h>
#include <tpropertymap.h> #include <tpropertymap.h>
#include <tagutils.h>
#include "tagunion.h" #include "tagunion.h"
#include "dsdifffile.h" #include "dsdifffile.h"
@@ -97,6 +98,18 @@ public:
bool hasDiin; bool hasDiin;
}; };
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
bool DSDIFF::File::isSupported(IOStream *stream)
{
// A DSDIFF file has to start with "FRM8????????DSD ".
const ByteVector id = Utils::readHeader(stream, 16, false);
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// public members // public members
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -185,6 +185,15 @@ namespace TagLib {
*/ */
bool hasDIINTag() const; bool hasDIINTag() const;
/*!
* Returns whether or not the given \a stream can be opened as a DSDIFF
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
protected: protected:
enum Endianness { BigEndian, LittleEndian }; enum Endianness { BigEndian, LittleEndian };

View File

@@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
copyright : (C) 2013 by Stephen F. Booth copyright : (C) 2013 - 2018 by Stephen F. Booth
email : me@sbooth.org email : me@sbooth.org
***************************************************************************/ ***************************************************************************/
@@ -28,6 +28,7 @@
#include <id3v2tag.h> #include <id3v2tag.h>
#include <tstringlist.h> #include <tstringlist.h>
#include <tpropertymap.h> #include <tpropertymap.h>
#include <tagutils.h>
#include "dsffile.h" #include "dsffile.h"
@@ -56,6 +57,17 @@ public:
ID3v2::Tag *tag; ID3v2::Tag *tag;
}; };
////////////////////////////////////////////////////////////////////////////////
// static members
////////////////////////////////////////////////////////////////////////////////
bool DSF::File::isSupported(IOStream *stream)
{
// A DSF file has to start with "DSD "
const ByteVector id = Utils::readHeader(stream, 4, false);
return id.startsWith("DSD ");
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// public members // public members
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View File

@@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
copyright : (C) 2013 by Stephen F. Booth copyright : (C) 2013 - 2018 by Stephen F. Booth
email : me@sbooth.org email : me@sbooth.org
***************************************************************************/ ***************************************************************************/
@@ -103,6 +103,15 @@ namespace TagLib {
*/ */
virtual bool save(); virtual bool save();
/*!
* Returns whether or not the given \a stream can be opened as a DSF
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private: private:
File(const File &); File(const File &);
File &operator=(const File &); File &operator=(const File &);

View File

@@ -180,10 +180,10 @@ namespace
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle); file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
else if(APE::File::isSupported(stream)) else if(APE::File::isSupported(stream))
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle); file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
//else if(DSF::File::isSupported(stream)) else if(DSDIFF::File::isSupported(stream))
//return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle); file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
//else if(DSDIFF::File::isSupported(stream)) else if(DSF::File::isSupported(stream))
//return new DSF::File(stream, readAudioProperties, audioPropertiesStyle); file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
// isSupported() only does a quick check, so double check the file here. // isSupported() only does a quick check, so double check the file here.

View File

@@ -216,7 +216,23 @@ void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id)
String TableOfContentsFrame::toString() const String TableOfContentsFrame::toString() const
{ {
return String(); String s = String(d->elementID) +
": top level: " + (d->isTopLevel ? "true" : "false") +
", ordered: " + (d->isOrdered ? "true" : "false");
if(!d->childElements.isEmpty()) {
s+= ", chapters: [ " + String(d->childElements.toByteVector(", ")) + " ]";
}
if(!d->embeddedFrameList.isEmpty()) {
StringList frameIDs;
for(FrameList::ConstIterator it = d->embeddedFrameList.begin();
it != d->embeddedFrameList.end(); ++it)
frameIDs.append((*it)->frameID());
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
}
return s;
} }
PropertyMap TableOfContentsFrame::asProperties() const PropertyMap TableOfContentsFrame::asProperties() const

View File

@@ -339,7 +339,13 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const String &descripti
String UserTextIdentificationFrame::toString() const String UserTextIdentificationFrame::toString() const
{ {
return "[" + description() + "] " + fieldList().toString(); // first entry is the description itself, drop from values list
StringList l = fieldList();
for(StringList::Iterator it = l.begin(); it != l.end(); ++it) {
l.erase(it);
break;
}
return "[" + description() + "] " + l.toString();
} }
String UserTextIdentificationFrame::description() const String UserTextIdentificationFrame::description() const

View File

@@ -231,11 +231,21 @@ void Ogg::FLAC::File::scan()
if(!metadataHeader.startsWith("fLaC")) { if(!metadataHeader.startsWith("fLaC")) {
// FLAC 1.1.2+ // FLAC 1.1.2+
// See https://xiph.org/flac/ogg_mapping.html for the header specification.
if(metadataHeader.size() < 13)
return;
if(metadataHeader[0] != 0x7f)
return;
if(metadataHeader.mid(1, 4) != "FLAC") if(metadataHeader.mid(1, 4) != "FLAC")
return; return;
if(metadataHeader[5] != 1) if(metadataHeader[5] != 1 && metadataHeader[6] != 0)
return; // not version 1 return; // not version 1.0
if(metadataHeader.mid(9, 4) != "fLaC")
return;
metadataHeader = metadataHeader.mid(13); metadataHeader = metadataHeader.mid(13);
} }

View File

@@ -58,6 +58,11 @@ namespace
#endif #endif
} }
FileHandle openFile(const int fileDescriptor, bool readOnly)
{
return InvalidFileHandle;
}
void closeFile(FileHandle file) void closeFile(FileHandle file)
{ {
CloseHandle(file); CloseHandle(file);
@@ -98,6 +103,11 @@ namespace
return fopen(path, readOnly ? "rb" : "rb+"); return fopen(path, readOnly ? "rb" : "rb+");
} }
FileHandle openFile(const int fileDescriptor, bool readOnly)
{
return fdopen(fileDescriptor, readOnly ? "rb" : "rb+");
}
void closeFile(FileHandle file) void closeFile(FileHandle file)
{ {
fclose(file); fclose(file);
@@ -149,13 +159,28 @@ FileStream::FileStream(FileName fileName, bool openReadOnly)
d->file = openFile(fileName, true); d->file = openFile(fileName, true);
if(d->file == InvalidFileHandle) if(d->file == InvalidFileHandle)
{
# ifdef _WIN32 # ifdef _WIN32
debug("Could not open file " + fileName.toString()); debug("Could not open file " + fileName.toString());
# else # else
debug("Could not open file " + String(static_cast<const char *>(d->name))); debug("Could not open file " + String(static_cast<const char *>(d->name)));
# endif # endif
} }
FileStream::FileStream(int fileDescriptor, bool openReadOnly)
: d(new FileStreamPrivate(""))
{
// First try with read / write mode, if that fails, fall back to read only.
if(!openReadOnly)
d->file = openFile(fileDescriptor, false);
if(d->file != InvalidFileHandle)
d->readOnly = false;
else
d->file = openFile(fileDescriptor, true);
if(d->file == InvalidFileHandle)
debug("Could not open file using file descriptor");
} }
FileStream::~FileStream() FileStream::~FileStream()
@@ -255,8 +280,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
ByteVector buffer = data; ByteVector buffer = data;
ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength)); ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
while(true) while(true) {
{
// Seek to the current read position and read the data that we're about // Seek to the current read position and read the data that we're about
// to overwrite. Appropriately increment the readPosition. // to overwrite. Appropriately increment the readPosition.
@@ -304,8 +328,7 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
ByteVector buffer(static_cast<unsigned int>(bufferLength)); ByteVector buffer(static_cast<unsigned int>(bufferLength));
for(unsigned int bytesRead = -1; bytesRead != 0;) for(unsigned int bytesRead = -1; bytesRead != 0;) {
{
seek(readPosition); seek(readPosition);
bytesRead = static_cast<unsigned int>(readFile(d->file, buffer)); bytesRead = static_cast<unsigned int>(readFile(d->file, buffer));
readPosition += bytesRead; readPosition += bytesRead;
@@ -401,7 +424,8 @@ long FileStream::tell() const
const LARGE_INTEGER zero = {}; const LARGE_INTEGER zero = {};
LARGE_INTEGER position; LARGE_INTEGER position;
if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) && position.QuadPart <= LONG_MAX) { if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
position.QuadPart <= LONG_MAX) {
return static_cast<long>(position.QuadPart); return static_cast<long>(position.QuadPart);
} }
else { else {
@@ -470,9 +494,8 @@ void FileStream::truncate(long length)
#else #else
const int error = ftruncate(fileno(d->file), length); const int error = ftruncate(fileno(d->file), length);
if(error != 0) { if(error != 0)
debug("FileStream::truncate() -- Coundn't truncate the file."); debug("FileStream::truncate() -- Coundn't truncate the file.");
}
#endif #endif
} }

View File

@@ -54,6 +54,11 @@ namespace TagLib {
*/ */
FileStream(FileName file, bool openReadOnly = false); FileStream(FileName file, bool openReadOnly = false);
/*!
* Construct a File object and opens the \a file using file descriptor.
*/
FileStream(int fileDescriptor, bool openReadOnly = false);
/*! /*!
* Destroys this FileStream instance. * Destroys this FileStream instance.
*/ */

View File

@@ -1,7 +1,5 @@
# Strawberry Music Player # Strawberry Music Player
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net> # Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
# This file was part of Clementine.
# Copyright 2010, David Sansome <me@davidsansome.com>
# #
# Strawberry is free software: you can redistribute it and/or modify # Strawberry is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -21,9 +19,6 @@ cmake_minimum_required(VERSION 2.8.11)
if(${CMAKE_VERSION} VERSION_GREATER "3.0") if(${CMAKE_VERSION} VERSION_GREATER "3.0")
cmake_policy(SET CMP0054 NEW) cmake_policy(SET CMP0054 NEW)
endif() endif()
if(${CMAKE_VERSION} VERSION_GREATER "3.10.3")
cmake_policy(SET CMP0072 NEW)
endif()
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
include(CheckIncludeFiles) include(CheckIncludeFiles)
@@ -37,24 +32,27 @@ include(cmake/Rpm.cmake)
include(cmake/Deb.cmake) include(cmake/Deb.cmake)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(LINUX 1) set(LINUX ON)
endif() endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD") if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
set(FREEBSD 1) set(FREEBSD ON)
endif() endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD") if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
set(OPENBSD 1) set(OPENBSD ON)
endif() endif()
set(CMAKE_CXX_STANDARD 11) set(CMAKE_CXX_STANDARD 11)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
#set(CMAKE_BUILD_TYPE Debug)
if(${CMAKE_BUILD_TYPE} MATCHES "Release") if(${CMAKE_BUILD_TYPE} MATCHES "Release")
add_definitions(-DNDEBUG) add_definitions(-DNDEBUG)
add_definitions(-DQT_NO_DEBUG_OUTPUT) add_definitions(-DQT_NO_DEBUG_OUTPUT)
#add_definitions(-DQT_NO_WARNING_OUTPUT) #add_definitions(-DQT_NO_WARNING_OUTPUT)
endif(${CMAKE_BUILD_TYPE} MATCHES "Release") endif()
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
set(DEBUG ON)
endif()
if (CMAKE_CXX_COMPILER MATCHES ".*clang") if (CMAKE_CXX_COMPILER MATCHES ".*clang")
set(CMAKE_COMPILER_IS_CLANGXX 1) set(CMAKE_COMPILER_IS_CLANGXX 1)
@@ -90,16 +88,12 @@ else(LINUX)
find_package(ALSA) find_package(ALSA)
pkg_check_modules(DBUS dbus-1) pkg_check_modules(DBUS dbus-1)
endif(LINUX) endif(LINUX)
if(ALSA_FOUND)
set(HAVE_ALSA ON)
endif()
if (NOT APPLE) if (NOT APPLE)
find_package(X11) find_package(X11)
endif() endif()
if(X11_FOUND) if(X11_FOUND)
set(HAVE_X11 ON) set(HAVE_X11 ON)
endif() endif()
find_package(OpenGL REQUIRED)
pkg_check_modules(GSTREAMER gstreamer-1.0) pkg_check_modules(GSTREAMER gstreamer-1.0)
pkg_check_modules(GSTREAMER_BASE gstreamer-base-1.0) pkg_check_modules(GSTREAMER_BASE gstreamer-base-1.0)
pkg_check_modules(GSTREAMER_AUDIO gstreamer-audio-1.0) pkg_check_modules(GSTREAMER_AUDIO gstreamer-audio-1.0)
@@ -111,22 +105,21 @@ pkg_check_modules(PHONON phonon4qt5)
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7) pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7)
pkg_check_modules(LIBPULSE libpulse) pkg_check_modules(LIBPULSE libpulse)
pkg_check_modules(CHROMAPRINT libchromaprint) pkg_check_modules(CHROMAPRINT libchromaprint)
#if(CHROMAPRINT_FOUND)
# set(HAVE_CHROMAPRINT ON)
#endif()
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92) pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
pkg_check_modules(LIBMTP libmtp>=1.0) pkg_check_modules(LIBMTP libmtp>=1.0)
pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0) pkg_check_modules(LIBIMOBILEDEVICE libimobiledevice-1.0)
pkg_check_modules(USBMUXD libusbmuxd) pkg_check_modules(LIBUSBMUXD libusbmuxd)
pkg_check_modules(PLIST libplist) pkg_check_modules(LIBPLIST libplist)
pkg_check_modules(LIBDEEZER libdeezer)
pkg_check_modules(LIBDZMEDIA libdzmedia)
if(WIN32) if(WIN32)
find_package(ZLIB REQUIRED) find_package(ZLIB REQUIRED)
endif(WIN32) endif(WIN32)
# QT # QT
set(QT_MIN_VERSION 5.6.0) set(QT_MIN_VERSION 5.5.1)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql OpenGL Xml) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql Xml)
if(X11_FOUND) if(X11_FOUND)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras) find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras)
endif() endif()
@@ -141,7 +134,7 @@ if(WIN32)
find_package(Qt5 REQUIRED COMPONENTS WinExtras) find_package(Qt5 REQUIRED COMPONENTS WinExtras)
endif() endif()
set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql Qt5::OpenGL Qt5::Xml) set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql Qt5::Xml)
if(DBUS_FOUND) if(DBUS_FOUND)
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::DBus) set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::DBus)
@@ -158,15 +151,25 @@ endif()
# TAGLIB # TAGLIB
pkg_check_modules(TAGLIB taglib) pkg_check_modules(TAGLIB taglib)
# Only use system taglib if it's greater than 1.11.1 because of audio file detection by content. # Only use system taglib if it's greater than 1.11.1
# But let the user override as strawberry will still compile and work without. # There is a bug in version 1.11.1 corrupting Ogg files, see: https://github.com/taglib/taglib/issues/864
# If you decide to use the systems taglib, make sure it has been patched with the following commit:
# https://github.com/taglib/taglib/commit/9336c82da3a04552168f208cd7a5fa4646701ea4
# The current taglib in 3rdparty also has the following features used by strawberry:
# - Audio file detection by content.
# - DSF and DSDIFF support
#
if (TAGLIB_VERSION VERSION_GREATER 1.11.1 OR WIN32) if (TAGLIB_VERSION VERSION_GREATER 1.11.1 OR WIN32)
option(USE_SYSTEM_TAGLIB "Use system taglib" ON) option(USE_SYSTEM_TAGLIB "Use system taglib" ON)
else() else()
option(USE_SYSTEM_TAGLIB "Use system taglib" OFF) option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
endif() endif()
if (TAGLIB_FOUND AND USE_SYSTEM_TAGLIB) if (TAGLIB_FOUND AND USE_SYSTEM_TAGLIB)
message(STATUS "Using system taglib library") if (TAGLIB_VERSION VERSION_GREATER 1.11.1 OR WIN32)
message(STATUS "Using system taglib library")
else()
message(WARNING "Using system taglib library. Version 1.11.1 or less has a bug corrupting Ogg files, make sure your systems version has been patched!")
endif()
set(CMAKE_REQUIRED_INCLUDES "${TAGLIB_INCLUDE_DIRS}") set(CMAKE_REQUIRED_INCLUDES "${TAGLIB_INCLUDE_DIRS}")
set(CMAKE_REQUIRED_LIBRARIES "${TAGLIB_LIBRARIES}") set(CMAKE_REQUIRED_LIBRARIES "${TAGLIB_LIBRARIES}")
set(CMAKE_REQUIRED_INCLUDES) set(CMAKE_REQUIRED_INCLUDES)
@@ -211,9 +214,9 @@ endif()
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication library" OFF) option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication library" OFF)
if(USE_SYSTEM_QTSINGLEAPPLICATION) if(USE_SYSTEM_QTSINGLEAPPLICATION)
message(STATUS "Using system QtSingleApplication library") message(STATUS "Using system QtSingleApplication library")
find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES QtSolutions) find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES qt5/QtSolutions)
find_library(QTSINGLEAPPLICATION_LIBRARIES QtSolutions_SingleApplication-2.6) find_library(QTSINGLEAPPLICATION_LIBRARIES Qt5Solutions_SingleApplication-2.6)
find_library(QTSINGLECOREAPPLICATION_LIBRARIES QtSolutions_SingleCoreApplication-2.6) find_library(QTSINGLECOREAPPLICATION_LIBRARIES Qt5Solutions_SingleCoreApplication-2.6)
else(USE_SYSTEM_QTSINGLEAPPLICATION) else(USE_SYSTEM_QTSINGLEAPPLICATION)
message(STATUS "Using builtin QtSingleApplication library") message(STATUS "Using builtin QtSingleApplication library")
add_subdirectory(3rdparty/qtsingleapplication) add_subdirectory(3rdparty/qtsingleapplication)
@@ -225,11 +228,11 @@ endif(USE_SYSTEM_QTSINGLEAPPLICATION)
option(USE_SYSTEM_QXT "Use system Qxt library" OFF) option(USE_SYSTEM_QXT "Use system Qxt library" OFF)
if (USE_SYSTEM_QXT) if (USE_SYSTEM_QXT)
message(STATUS "Using system Qxt library") message(STATUS "Using system Qxt library")
find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES QxtCore) find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES qt5/QxtCore)
find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES QxtGui) find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES qt5/QxtWidgets)
set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS}) set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS})
# We only need its header. We don't need to link to QxtCore. # We only need its header. We don't need to link to QxtCore.
find_library(QXT_LIBRARIES QxtGui) find_library(QXT_LIBRARIES QxtWidgets-qt5)
else (USE_SYSTEM_QXT) else (USE_SYSTEM_QXT)
message(STATUS "Using builtin Qxt library") message(STATUS "Using builtin Qxt library")
add_definitions(-DQXT_STATIC -DBUILD_QXT_GUI -DBUILD_QXT_CORE) add_definitions(-DQXT_STATIC -DBUILD_QXT_GUI -DBUILD_QXT_CORE)
@@ -263,6 +266,14 @@ if(WIN32)
option(ENABLE_WIN32_CONSOLE "Show the windows console even outside Debug mode" OFF) option(ENABLE_WIN32_CONSOLE "Show the windows console even outside Debug mode" OFF)
endif(WIN32) endif(WIN32)
optional_component(ALSA ON "ALSA integration"
DEPENDS "alsa" ALSA_FOUND
)
optional_component(LIBPULSE ON "Pulse audio integration"
DEPENDS "libpulse" LIBPULSE_FOUND
)
optional_component(DBUS ON "D-Bus support" optional_component(DBUS ON "D-Bus support"
DEPENDS "D-Bus" DBUS_FOUND DEPENDS "D-Bus" DBUS_FOUND
) )
@@ -283,13 +294,21 @@ optional_component(VLC ON "Engine: VLC backend"
DEPENDS "libvlc" LIBVLC_FOUND DEPENDS "libvlc" LIBVLC_FOUND
) )
optional_component(PHONON OFF "Engine: Phonon backend" optional_component(PHONON OFF "Engine: Phonon backend (UNSTABLE)"
DEPENDS "phonon4qt5" PHONON_FOUND DEPENDS "phonon4qt5" PHONON_FOUND
) )
optional_component(LIBPULSE ON "Pulse audio integration" if (WIN32)
DEPENDS "libpulse" LIBPULSE_FOUND optional_component(DEEZER ON "Engine: Deezer backend"
) DEPENDS "libdeezer" LIBDEEZER_FOUND
)
else ()
optional_component(DEEZER ON "Engine: Deezer backend"
DEPENDS "Linux" LINUX
DEPENDS "libdeezer" LIBDEEZER_FOUND
DEPENDS "libpulse" LIBPULSE_FOUND
)
endif()
optional_component(LIBLASTFM ON "Last.fm album cover provider" optional_component(LIBLASTFM ON "Last.fm album cover provider"
DEPENDS "liblastfm" LASTFM5_LIBRARIES LASTFM5_INCLUDE_DIRS DEPENDS "liblastfm" LASTFM5_LIBRARIES LASTFM5_INCLUDE_DIRS
@@ -325,9 +344,9 @@ optional_component(LIBMTP ON "Devices: MTP support"
) )
optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support" optional_component(IMOBILEDEVICE ON "Devices: iPod Touch, iPhone, iPad support"
DEPENDS "libimobiledevice" IMOBILEDEVICE_FOUND DEPENDS "libimobiledevice" LIBIMOBILEDEVICE_FOUND
DEPENDS "libplist" PLIST_FOUND DEPENDS "libplist" LIBPLIST_FOUND
DEPENDS "libusbmuxd" USBMUXD_FOUND DEPENDS "libusbmuxd" LIBUSBMUXD_FOUND
DEPENDS "iPod classic support" LIBGPOD_FOUND DEPENDS "iPod classic support" LIBGPOD_FOUND
) )
@@ -336,6 +355,23 @@ optional_component(SPARKLE ON "Sparkle integration"
DEPENDS "Sparkle" SPARKLE DEPENDS "Sparkle" SPARKLE
) )
optional_component(STREAM_TIDAL ON "Streaming: Tidal support")
if (LIBDZMEDIA_FOUND OR LIBDEEZER_FOUND)
optional_component(STREAM_DEEZER ON "Streaming: Deezer support")
else()
optional_component(STREAM_DEEZER OFF "Streaming: Deezer support")
endif()
optional_component(DZMEDIA ON "DZMedia"
DEPENDS "libdzmedia" LIBDZMEDIA_FOUND
DEPENDS "Deezer support" HAVE_STREAM_DEEZER
)
if (HAVE_STREAM_DEEZER AND NOT HAVE_DZMEDIA AND NOT HAVE_DEEZER)
message(STATUS "Deezer is enabled, but not DZMedia or Deezer engine, only preview streams will be available.")
endif()
#if(IMOBILEDEVICE_FOUND AND PLIST_FOUND) #if(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
#add_subdirectory(ext/gstafc) #add_subdirectory(ext/gstafc)
#endif(IMOBILEDEVICE_FOUND AND PLIST_FOUND) #endif(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
@@ -352,7 +388,7 @@ include_directories(${GLIB_INCLUDE_DIRS})
include_directories(${GLIBCONFIG_INCLUDE_DIRS}) include_directories(${GLIBCONFIG_INCLUDE_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS}) include_directories(${TAGLIB_INCLUDE_DIRS})
if(ENABLE_IMOBILEDEVICE AND IMOBILEDEVICE_VERSION VERSION_GREATER 1.1.1) if(HAVE_IMOBILEDEVICE AND LIBIMOBILEDEVICE_VERSION VERSION_GREATER 1.1.1)
set(IMOBILEDEVICE_USES_UDIDS ON) set(IMOBILEDEVICE_USES_UDIDS ON)
endif() endif()
@@ -374,6 +410,8 @@ add_custom_target(uninstall
# Show a summary of what we have enabled # Show a summary of what we have enabled
summary_show() summary_show()
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON) if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON AND NOT HAVE_DEEZER)
message(FATAL_ERROR "You need to enable either GStreamer, Xine, VLC or Phonon to compile!") message(FATAL_ERROR "You need to have either GStreamer, Xine, VLC, Phonon or Deezer to compile!")
elseif(NOT HAVE_GSTREAMER)
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
endif() endif()

View File

@@ -2,6 +2,54 @@ Strawberry Music Player
======================= =======================
ChangeLog ChangeLog
Version 0.4.2:
* Updated AppStream data file to newer specifications
* Fixed Deezer engine to use quality setting
* Removed unneeded dependency Qt5OpenGL
* Removed obsolete xine warning and engine reinitialization
* Added ALSA as optional component in cmake
* Fixed bug in playlist columns setting all visible
* Added option to reset playlist columns
* Fixed/Improved console logging
* Added queue to play next option
* (Windows) Corrected uninstalled files on x64 installer
* (MacOS) Fixed poor performance
Version 0.4.1:
* Fixed crash in analyzer
* Fixed trying to use systray even if the desktop had no systray
* Fixed Tidal login loop bug
* Added Deezer support
* New improved fancy tabwidget
* Fixed bug not loading engine settings
* Moved queue manager into tabbar for easier access
* Fixed crash when changing appearance colors
* Improved error handling between player and engine
* Added setting to allow continue to the next song in the playlist based on error
* Improved Xine engine code
* Moved some settings
* Updated builtin taglib
* Added AppStream data file
* Fixed compiling with Qt 5 versions of system QtSingleApplication and Qxt library
Version 0.3.3:
* Fixed Tidal login
Version 0.3.2:
* Fixed search error not shown in Tidal search
* Added URL handler for Tidal, now retrieving URL's when playing instead of when searching
* Fixed bug in pipeline not setting url
* Fixed bug setting wrong temporary metadata
* Removed device module from windows, since it's not implemented for windows
* Added support for both ALSA hw and plughw
* Added option to change url stream scheme for Tidal
* Added encoding of Tidal token in the source code
* Added encoding of Tidal password in the configuration
Version 0.3.1: Version 0.3.1:
* Added new lyrics provider with lyrics from AudD and API Seeds * Added new lyrics provider with lyrics from AudD and API Seeds
@@ -49,7 +97,7 @@ Version 0.1.4:
Version 0.1.3: Version 0.1.3:
* Audio file detection by content * Audio file detection by content
* Added builtin taglib to 3rdparty to support detecting audio by content instead of just file extension * Added builtin taglib to 3rdparty to support detecting audio by content instead of just file extension
* Removed unneeded bulitin qsqlite from 3rdparty * Removed unneeded qsqlite from 3rdparty
* Added sqldrivers\qsqlite.dll for windows build * Added sqldrivers\qsqlite.dll for windows build
* Replaced incorrect DLL libgstdirectsoundsink.dll (from gst 1.12.4) instead of libgstdirectsound.dll (from gst 1.14.0) for windows build * Replaced incorrect DLL libgstdirectsoundsink.dll (from gst 1.12.4) instead of libgstdirectsound.dll (from gst 1.14.0) for windows build
* Fixed git versioning * Fixed git versioning

View File

@@ -4,12 +4,11 @@ run zypper --non-interactive --gpg-auto-import-keys ref
run zypper --non-interactive --gpg-auto-import-keys dup -l -y run zypper --non-interactive --gpg-auto-import-keys dup -l -y
run zypper --non-interactive --gpg-auto-import-keys install \ run zypper --non-interactive --gpg-auto-import-keys install \
lsb-release \ lsb-release git tar make cmake gcc gcc-c++ pkg-config \
git tar make cmake gcc gcc-c++ pkg-config \
glibc-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libpulse-devel libnotify-devel \ glibc-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libpulse-devel libnotify-devel \
boost-devel protobuf-devel sqlite3-devel taglib-devel \ boost-devel protobuf-devel sqlite3-devel taglib-devel \
gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel \ gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel \
libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5OpenGL-devel libQt5Sql-devel \ libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel \
libqt5-qtx11extras-devel libQt5Gui-private-headers-devel libqt5-qtbase-common-devel liblastfm-qt5-devel \ libqt5-qtx11extras-devel libQt5Gui-private-headers-devel libqt5-qtbase-common-devel liblastfm-qt5-devel \
libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel

View File

@@ -1,8 +1,8 @@
:strawberry: Strawberry Music Player [![Build Status](https://travis-ci.org/jonaski/strawberry.svg?branch=master)](https://travis-ci.org/jonaski/strawberry) :strawberry: Strawberry Music Player [![Build Status](https://travis-ci.org/jonaski/strawberry.svg?branch=master)](https://travis-ci.org/jonaski/strawberry)
[![Donate](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRJUYV5QP6HW8)
======================= =======================
Strawberry is a audio player and music collection organizer. It is a fork of Clementine created in 2013 with a diffrent goal. Strawberry is a audio player and music collection organizer. It is a fork of Clementine released in 2018 aimed at music collectors, audio enthusiasts and audiophiles. The name is inspired by the band Strawbs. It's based on a heavily modified version of Clementine created in 2012-2013. It's written in C++ and Qt 5.
It's written in C++ and Qt 5. The name is inspired by the band Strawbs.
* Website: http://www.strawbs.org/ * Website: http://www.strawbs.org/
* Github: https://github.com/jonaski/strawberry * Github: https://github.com/jonaski/strawberry
@@ -16,7 +16,7 @@ It's written in C++ and Qt 5. The name is inspired by the band Strawbs.
* Audio CD playback * Audio CD playback
* Native desktop notifications * Native desktop notifications
* Playlists in multiple formats * Playlists in multiple formats
* Advanced output and device options with support for bit perfect playback on Linux * Advanced audio output and device configuration for bit-perfect playback on Linux
* Edit tags on music files * Edit tags on music files
* Fetch tags from MusicBrainz * Fetch tags from MusicBrainz
* Album cover art from Last.fm, Musicbrainz and Discogs * Album cover art from Last.fm, Musicbrainz and Discogs
@@ -25,7 +25,7 @@ It's written in C++ and Qt 5. The name is inspired by the band Strawbs.
* Audio analyzer * Audio analyzer
* Equalizer * Equalizer
* Transfer music to iPod, iPhone, MTP or mass-storage USB player * Transfer music to iPod, iPhone, MTP or mass-storage USB player
* Integrated Tidal support * Integrated Tidal and Deezer support
It has so far been tested to work on Linux, OpenBSD, MacOs and Windows. It has so far been tested to work on Linux, OpenBSD, MacOs and Windows.
@@ -39,7 +39,8 @@ To build Strawberry from source you need the following installed on your system
* [GCC](https://gcc.gnu.org/) or [clang](https://clang.llvm.org/) compiler * [GCC](https://gcc.gnu.org/) or [clang](https://clang.llvm.org/) compiler
* [Protobuf library and compiler](https://developers.google.com/protocol-buffers/) * [Protobuf library and compiler](https://developers.google.com/protocol-buffers/)
* [Boost development headers](https://www.boost.org/) * [Boost development headers](https://www.boost.org/)
* [Qt 5 with components Core, Gui, Widgets, Concurrent, Network, Sql, Xml, OpenGL, X11Extras and DBus](https://www.qt.io/) * [Qt 5 with components Core, Gui, Widgets, Concurrent, Network, Sql and Xml](https://www.qt.io/)
* [Qt 5 components X11Extras and DBus for Linux/BSD, MacExtras for MacOs and WinExtras for Windows](https://www.qt.io/)
* [SQLite3](https://www.sqlite.org) * [SQLite3](https://www.sqlite.org)
* [TagLib 1.11.1 or higher](http://taglib.org/) * [TagLib 1.11.1 or higher](http://taglib.org/)
* [Chromaprint library](https://acoustid.org/chromaprint) * [Chromaprint library](https://acoustid.org/chromaprint)
@@ -47,9 +48,13 @@ To build Strawberry from source you need the following installed on your system
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/) * [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?) * [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
Either GStreamer, Xine or VLC engine is required, but only GStreamer is fully implemented so far. Either GStreamer, Xine, VLC, Deezer or Phonon engine is required, but only GStreamer is fully implemented so far.
You should also install the gstreamer plugins base and good, and optionally bad and ugly. You should also install the gstreamer plugins base and good, and optionally bad and ugly.
Deezer streams with full songs are encrypted and only urls for preview streams (MP3) are exposed by the API.
Full length songs requires the use of deezers own engine (Deezer SDK) or the dzmedia library (I dont have it).
Deezer SDK can be found here: https://build-repo.deezer.com/native_sdk/deezer-native-sdk-v1.2.10.zip
Optional: Optional:
* The Qt 5 LastFM library is required for fetching album covers from LastFM. * The Qt 5 LastFM library is required for fetching album covers from LastFM.
@@ -72,5 +77,12 @@ Optional:
sudo make install sudo make install
(dont change to the source directory, if you created the build directory inside the source directory type: cmake .. instead). (dont change to the source directory, if you created the build directory inside the source directory type: cmake .. instead).
### :computer: Screenshot
![Browse](https://www.strawbs.org/pictures/screenshot-002-large.png)
### :moneybag: Donate
[![paypal](https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRJUYV5QP6HW8)

View File

@@ -1,28 +1,66 @@
find_program(LSB_RELEASE_EXEC lsb_release) find_program(LSB_RELEASE_EXEC lsb_release)
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is find_program(RPMBUILD_EXEC rpmbuild)
OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (LSB_RELEASE_EXEC) if (LSB_RELEASE_EXEC AND RPMBUILD_EXEC)
set(RPMBUILD_DIR ~/rpmbuild CACHE STRING "Rpmbuild directory, for the rpm target") execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -is | tr '[:upper:]' '[:lower:]' | cut -d' ' -f1"
set(RPM_ARCH x86_64 CACHE STRING "Architecture of the rpm file") OUTPUT_VARIABLE DIST_NAME
if (${LSB_RELEASE_ID_SHORT} STREQUAL "openSUSE") OUTPUT_STRIP_TRAILING_WHITESPACE
set(RPM_DISTRO opensuse CACHE STRING "Suffix of the rpm file") )
add_custom_target(rpm execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -ds | tr '[:upper:]' '[:lower:]' | sed 's/\"//g' | cut -d' ' -f2"
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh OUTPUT_VARIABLE DIST_RELEASE
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/ OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec )
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -ds | tr '[:upper:]' '[:lower:]' | sed 's/\"//g' | sed 's/\\.//g' | cut -d' ' -f3"
) OUTPUT_VARIABLE DIST_VERSION
endif() OUTPUT_STRIP_TRAILING_WHITESPACE
if (${LSB_RELEASE_ID_SHORT} STREQUAL "Fedora") )
set(RPM_DISTRO fedora CACHE STRING "Suffix of the rpm file") if (DIST_NAME)
add_custom_target(rpm message(STATUS "Distro Name: ${DIST_NAME}")
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh if (DIST_RELEASE)
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/ message(STATUS "Distro Release: ${DIST_RELEASE}")
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec endif()
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec if (DIST_VERSION)
) message(STATUS "Distro Version: ${DIST_VERSION}")
endif()
set(RPM_ARCH x86_64 CACHE STRING "Architecture of the rpm file")
set(RPMBUILD_DIR ~/rpmbuild CACHE STRING "Rpmbuild directory, for the rpm target")
if (${DIST_NAME} STREQUAL "opensuse")
if (DIST_RELEASE)
if (${DIST_RELEASE} STREQUAL "leap")
if (DIST_VERSION)
set(RPM_DISTRO "lp${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
else()
set(RPM_DISTRO ${DIST_RELEASE} CACHE STRING "Suffix of the rpm file")
endif()
elseif (${DIST_RELEASE} STREQUAL "tumbleweed")
set(RPM_DISTRO ${DIST_RELEASE} CACHE STRING "Suffix of the rpm file")
else ()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
else()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
add_custom_target(rpm
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
)
elseif (${DIST_NAME} STREQUAL "fedora")
if (DIST_VERSION)
set(RPM_DISTRO "fc${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
else ()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
add_custom_target(rpm
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
)
else()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
message(STATUS "RPM Suffix: ${RPM_DISTRO}")
endif() endif()
endif() endif()

View File

@@ -50,7 +50,7 @@ function(optional_component name default description)
set(current_dep_name) set(current_dep_name)
set(missing_deps) set(missing_deps)
foreach(arg ${ARGN}) foreach(arg ${ARGN})
if(${next_arg_is_dep_name}) if(${next_arg_is_dep_name})
set(current_dep_name "${arg}") set(current_dep_name "${arg}")
set(next_arg_is_dep_name FALSE) set(next_arg_is_dep_name FALSE)

View File

@@ -1,6 +1,6 @@
set(STRAWBERRY_VERSION_MAJOR 0) set(STRAWBERRY_VERSION_MAJOR 0)
set(STRAWBERRY_VERSION_MINOR 3) set(STRAWBERRY_VERSION_MINOR 4)
set(STRAWBERRY_VERSION_PATCH 1) set(STRAWBERRY_VERSION_PATCH 2)
#set(STRAWBERRY_VERSION_PRERELEASE rc1) #set(STRAWBERRY_VERSION_PRERELEASE rc1)
set(INCLUDE_GIT_REVISION OFF) set(INCLUDE_GIT_REVISION OFF)
@@ -8,9 +8,11 @@ set(INCLUDE_GIT_REVISION OFF)
set(majorminorpatch "${STRAWBERRY_VERSION_MAJOR}.${STRAWBERRY_VERSION_MINOR}.${STRAWBERRY_VERSION_PATCH}") set(majorminorpatch "${STRAWBERRY_VERSION_MAJOR}.${STRAWBERRY_VERSION_MINOR}.${STRAWBERRY_VERSION_PATCH}")
set(STRAWBERRY_VERSION_DISPLAY "${majorminorpatch}") set(STRAWBERRY_VERSION_DISPLAY "${majorminorpatch}")
set(STRAWBERRY_VERSION_PACKAGE "${majorminorpatch}")
set(STRAWBERRY_VERSION_RPM_V "${majorminorpatch}") set(STRAWBERRY_VERSION_RPM_V "${majorminorpatch}")
set(STRAWBERRY_VERSION_RPM_R "1") set(STRAWBERRY_VERSION_RPM_R "1")
set(STRAWBERRY_VERSION_PACKAGE "${majorminorpatch}") set(STRAWBERRY_VERSION_PAC_V "${majorminorpatch}")
set(STRAWBERRY_VERSION_PAC_R "1")
if(${STRAWBERRY_VERSION_PATCH} EQUAL "0") if(${STRAWBERRY_VERSION_PATCH} EQUAL "0")
set(STRAWBERRY_VERSION_DISPLAY "${STRAWBERRY_VERSION_MAJOR}.${STRAWBERRY_VERSION_MINOR}") set(STRAWBERRY_VERSION_DISPLAY "${STRAWBERRY_VERSION_MAJOR}.${STRAWBERRY_VERSION_MINOR}")
@@ -82,10 +84,13 @@ if(GIT_REVISION)
set(STRAWBERRY_VERSION_PACKAGE "${GIT_TAGNAME}.${GIT_COMMITCOUNT}.${GIT_SHA1}") set(STRAWBERRY_VERSION_PACKAGE "${GIT_TAGNAME}.${GIT_COMMITCOUNT}.${GIT_SHA1}")
set(STRAWBERRY_VERSION_RPM_V "${GIT_TAGNAME}") set(STRAWBERRY_VERSION_RPM_V "${GIT_TAGNAME}")
set(STRAWBERRY_VERSION_RPM_R "2.${GIT_COMMITCOUNT}.${GIT_SHA1}") set(STRAWBERRY_VERSION_RPM_R "2.${GIT_COMMITCOUNT}.${GIT_SHA1}")
set(STRAWBERRY_VERSION_PAC_V "${GIT_TAGNAME}")
set(STRAWBERRY_VERSION_PAC_R "${GIT_COMMITCOUNT}")
endif() endif()
message(STATUS "Strawberry Version:") message(STATUS "Strawberry Version:")
message(STATUS "Display: ${STRAWBERRY_VERSION_DISPLAY}") message(STATUS "Display: ${STRAWBERRY_VERSION_DISPLAY}")
message(STATUS "Package: ${STRAWBERRY_VERSION_PACKAGE}") message(STATUS "Package: ${STRAWBERRY_VERSION_PACKAGE}")
message(STATUS "Rpm: ${STRAWBERRY_VERSION_RPM_V}-${STRAWBERRY_VERSION_RPM_R}") message(STATUS "RPM: ${STRAWBERRY_VERSION_RPM_V}-${STRAWBERRY_VERSION_RPM_R}")
message(STATUS "PAC: ${STRAWBERRY_VERSION_PAC_V}-${STRAWBERRY_VERSION_PAC_R}")

View File

@@ -7,8 +7,8 @@
<file>schema/device-schema.sql</file> <file>schema/device-schema.sql</file>
<file>style/strawberry.css</file> <file>style/strawberry.css</file>
<file>misc/playing_tooltip.txt</file> <file>misc/playing_tooltip.txt</file>
<file>misc/oauthsuccess.html</file>
<file>pictures/strawberry.png</file> <file>pictures/strawberry.png</file>
<file>pictures/strawbs-transparent.png</file>
<file>pictures/noalbumart.png</file> <file>pictures/noalbumart.png</file>
<file>pictures/nomusic.png</file> <file>pictures/nomusic.png</file>
<file>pictures/musicbrainz.png</file> <file>pictures/musicbrainz.png</file>
@@ -27,442 +27,7 @@
<file>pictures/osd_background.png</file> <file>pictures/osd_background.png</file>
<file>pictures/osd_shadow_corner.png</file> <file>pictures/osd_shadow_corner.png</file>
<file>pictures/osd_shadow_edge.png</file> <file>pictures/osd_shadow_edge.png</file>
<file>icons/128x128/albums.png</file> <file>pictures/deezer.png</file>
<file>icons/128x128/alsa.png</file>
<file>icons/128x128/application-exit.png</file>
<file>icons/128x128/applications-internet.png</file>
<file>icons/128x128/bluetooth.png</file>
<file>icons/128x128/cdcase.png</file>
<file>icons/128x128/cd.png</file>
<file>icons/128x128/configure.png</file>
<file>icons/128x128/device-ipod-nano.png</file>
<file>icons/128x128/device-ipod.png</file>
<file>icons/128x128/device-phone.png</file>
<file>icons/128x128/device.png</file>
<file>icons/128x128/device-usb-drive.png</file>
<file>icons/128x128/device-usb-flash.png</file>
<file>icons/128x128/dialog-error.png</file>
<file>icons/128x128/dialog-information.png</file>
<file>icons/128x128/dialog-ok-apply.png</file>
<file>icons/128x128/dialog-password.png</file>
<file>icons/128x128/dialog-warning.png</file>
<file>icons/128x128/document-download.png</file>
<file>icons/128x128/document-new.png</file>
<file>icons/128x128/document-open-folder.png</file>
<file>icons/128x128/document-open.png</file>
<file>icons/128x128/document-save.png</file>
<file>icons/128x128/document-search.png</file>
<file>icons/128x128/download.png</file>
<file>icons/128x128/edit-clear-list.png</file>
<file>icons/128x128/edit-clear-locationbar-ltr.png</file>
<file>icons/128x128/edit-copy.png</file>
<file>icons/128x128/edit-delete.png</file>
<file>icons/128x128/edit-find.png</file>
<file>icons/128x128/edit-redo.png</file>
<file>icons/128x128/edit-rename.png</file>
<file>icons/128x128/edit-undo.png</file>
<file>icons/128x128/electrocompaniet.png</file>
<file>icons/128x128/equalizer.png</file>
<file>icons/128x128/folder-new.png</file>
<file>icons/128x128/folder.png</file>
<file>icons/128x128/folder-sound.png</file>
<file>icons/128x128/footsteps.png</file>
<file>icons/128x128/go-down.png</file>
<file>icons/128x128/go-home.png</file>
<file>icons/128x128/go-jump.png</file>
<file>icons/128x128/go-next.png</file>
<file>icons/128x128/go-previous.png</file>
<file>icons/128x128/go-up.png</file>
<file>icons/128x128/gstreamer.png</file>
<file>icons/128x128/headset.png</file>
<file>icons/128x128/help-hint.png</file>
<file>icons/128x128/intel.png</file>
<file>icons/128x128/jack.png</file>
<file>icons/128x128/keyboard.png</file>
<file>icons/128x128/list-add.png</file>
<file>icons/128x128/list-remove.png</file>
<file>icons/128x128/mcintosh-player.png</file>
<file>icons/128x128/mcintosh-text.png</file>
<file>icons/128x128/media-eject.png</file>
<file>icons/128x128/media-forward.png</file>
<file>icons/128x128/media-pause.png</file>
<file>icons/128x128/media-play.png</file>
<file>icons/128x128/media-rewind.png</file>
<file>icons/128x128/media-stop.png</file>
<file>icons/128x128/nvidia.png</file>
<file>icons/128x128/play2.png</file>
<file>icons/128x128/realtek.png</file>
<file>icons/128x128/search.png</file>
<file>icons/128x128/soundcard.png</file>
<file>icons/128x128/speaker.png</file>
<file>icons/128x128/star-grey.png</file>
<file>icons/128x128/star.png</file>
<file>icons/128x128/strawberry.png</file>
<file>icons/128x128/strawberry.svg</file>
<file>icons/128x128/tools-wizard.png</file>
<file>icons/128x128/view-choose.png</file>
<file>icons/128x128/view-fullscreen.png</file>
<file>icons/128x128/view-media-lyrics.png</file>
<file>icons/128x128/view-media-playlist.png</file>
<file>icons/128x128/view-media-visualization.png</file>
<file>icons/128x128/view-refresh.png</file>
<file>icons/128x128/vinyl.png</file>
<file>icons/128x128/vlc.png</file>
<file>icons/128x128/xine.png</file>
<file>icons/128x128/zoom-in.png</file>
<file>icons/128x128/zoom-out.png</file>
<file>icons/128x128/tidal.png</file>
<file>icons/64x64/albums.png</file>
<file>icons/64x64/alsa.png</file>
<file>icons/64x64/application-exit.png</file>
<file>icons/64x64/applications-internet.png</file>
<file>icons/64x64/bluetooth.png</file>
<file>icons/64x64/cdcase.png</file>
<file>icons/64x64/cd.png</file>
<file>icons/64x64/configure.png</file>
<file>icons/64x64/device-ipod-nano.png</file>
<file>icons/64x64/device-ipod.png</file>
<file>icons/64x64/device-phone.png</file>
<file>icons/64x64/device.png</file>
<file>icons/64x64/device-usb-drive.png</file>
<file>icons/64x64/device-usb-flash.png</file>
<file>icons/64x64/dialog-error.png</file>
<file>icons/64x64/dialog-information.png</file>
<file>icons/64x64/dialog-ok-apply.png</file>
<file>icons/64x64/dialog-password.png</file>
<file>icons/64x64/dialog-warning.png</file>
<file>icons/64x64/document-download.png</file>
<file>icons/64x64/document-new.png</file>
<file>icons/64x64/document-open-folder.png</file>
<file>icons/64x64/document-open.png</file>
<file>icons/64x64/document-save.png</file>
<file>icons/64x64/document-search.png</file>
<file>icons/64x64/download.png</file>
<file>icons/64x64/edit-clear-list.png</file>
<file>icons/64x64/edit-clear-locationbar-ltr.png</file>
<file>icons/64x64/edit-copy.png</file>
<file>icons/64x64/edit-delete.png</file>
<file>icons/64x64/edit-find.png</file>
<file>icons/64x64/edit-redo.png</file>
<file>icons/64x64/edit-rename.png</file>
<file>icons/64x64/edit-undo.png</file>
<file>icons/64x64/electrocompaniet.png</file>
<file>icons/64x64/equalizer.png</file>
<file>icons/64x64/folder-new.png</file>
<file>icons/64x64/folder.png</file>
<file>icons/64x64/folder-sound.png</file>
<file>icons/64x64/footsteps.png</file>
<file>icons/64x64/go-down.png</file>
<file>icons/64x64/go-home.png</file>
<file>icons/64x64/go-jump.png</file>
<file>icons/64x64/go-next.png</file>
<file>icons/64x64/go-previous.png</file>
<file>icons/64x64/go-up.png</file>
<file>icons/64x64/gstreamer.png</file>
<file>icons/64x64/headset.png</file>
<file>icons/64x64/help-hint.png</file>
<file>icons/64x64/intel.png</file>
<file>icons/64x64/jack.png</file>
<file>icons/64x64/keyboard.png</file>
<file>icons/64x64/list-add.png</file>
<file>icons/64x64/list-remove.png</file>
<file>icons/64x64/mcintosh-player.png</file>
<file>icons/64x64/mcintosh-text.png</file>
<file>icons/64x64/media-eject.png</file>
<file>icons/64x64/media-forward.png</file>
<file>icons/64x64/media-pause.png</file>
<file>icons/64x64/media-play.png</file>
<file>icons/64x64/media-rewind.png</file>
<file>icons/64x64/media-stop.png</file>
<file>icons/64x64/nvidia.png</file>
<file>icons/64x64/play2.png</file>
<file>icons/64x64/pulseaudio.png</file>
<file>icons/64x64/realtek.png</file>
<file>icons/64x64/search.png</file>
<file>icons/64x64/soundcard.png</file>
<file>icons/64x64/speaker.png</file>
<file>icons/64x64/star-grey.png</file>
<file>icons/64x64/star.png</file>
<file>icons/64x64/strawberry.png</file>
<file>icons/64x64/tools-wizard.png</file>
<file>icons/64x64/view-choose.png</file>
<file>icons/64x64/view-fullscreen.png</file>
<file>icons/64x64/view-media-lyrics.png</file>
<file>icons/64x64/view-media-playlist.png</file>
<file>icons/64x64/view-media-visualization.png</file>
<file>icons/64x64/view-refresh.png</file>
<file>icons/64x64/vinyl.png</file>
<file>icons/64x64/vlc.png</file>
<file>icons/64x64/xine.png</file>
<file>icons/64x64/zoom-in.png</file>
<file>icons/64x64/zoom-out.png</file>
<file>icons/64x64/tidal.png</file>
<file>icons/48x48/albums.png</file>
<file>icons/48x48/alsa.png</file>
<file>icons/48x48/application-exit.png</file>
<file>icons/48x48/applications-internet.png</file>
<file>icons/48x48/bluetooth.png</file>
<file>icons/48x48/cdcase.png</file>
<file>icons/48x48/cd.png</file>
<file>icons/48x48/configure.png</file>
<file>icons/48x48/device-ipod-nano.png</file>
<file>icons/48x48/device-ipod.png</file>
<file>icons/48x48/device-phone.png</file>
<file>icons/48x48/device.png</file>
<file>icons/48x48/device-usb-drive.png</file>
<file>icons/48x48/device-usb-flash.png</file>
<file>icons/48x48/dialog-error.png</file>
<file>icons/48x48/dialog-information.png</file>
<file>icons/48x48/dialog-ok-apply.png</file>
<file>icons/48x48/dialog-password.png</file>
<file>icons/48x48/dialog-warning.png</file>
<file>icons/48x48/document-download.png</file>
<file>icons/48x48/document-new.png</file>
<file>icons/48x48/document-open-folder.png</file>
<file>icons/48x48/document-open.png</file>
<file>icons/48x48/document-save.png</file>
<file>icons/48x48/document-search.png</file>
<file>icons/48x48/download.png</file>
<file>icons/48x48/edit-clear-list.png</file>
<file>icons/48x48/edit-clear-locationbar-ltr.png</file>
<file>icons/48x48/edit-copy.png</file>
<file>icons/48x48/edit-delete.png</file>
<file>icons/48x48/edit-find.png</file>
<file>icons/48x48/edit-redo.png</file>
<file>icons/48x48/edit-rename.png</file>
<file>icons/48x48/edit-undo.png</file>
<file>icons/48x48/electrocompaniet.png</file>
<file>icons/48x48/equalizer.png</file>
<file>icons/48x48/folder-new.png</file>
<file>icons/48x48/folder.png</file>
<file>icons/48x48/folder-sound.png</file>
<file>icons/48x48/footsteps.png</file>
<file>icons/48x48/go-down.png</file>
<file>icons/48x48/go-home.png</file>
<file>icons/48x48/go-jump.png</file>
<file>icons/48x48/go-next.png</file>
<file>icons/48x48/go-previous.png</file>
<file>icons/48x48/go-up.png</file>
<file>icons/48x48/gstreamer.png</file>
<file>icons/48x48/headset.png</file>
<file>icons/48x48/help-hint.png</file>
<file>icons/48x48/intel.png</file>
<file>icons/48x48/jack.png</file>
<file>icons/48x48/keyboard.png</file>
<file>icons/48x48/list-add.png</file>
<file>icons/48x48/list-remove.png</file>
<file>icons/48x48/mcintosh-player.png</file>
<file>icons/48x48/mcintosh.png</file>
<file>icons/48x48/mcintosh-text.png</file>
<file>icons/48x48/media-eject.png</file>
<file>icons/48x48/media-forward.png</file>
<file>icons/48x48/media-pause.png</file>
<file>icons/48x48/media-playlist-repeat.png</file>
<file>icons/48x48/media-playlist-shuffle.png</file>
<file>icons/48x48/media-play.png</file>
<file>icons/48x48/media-rewind.png</file>
<file>icons/48x48/media-stop.png</file>
<file>icons/48x48/nvidia.png</file>
<file>icons/48x48/play2.png</file>
<file>icons/48x48/pulseaudio.png</file>
<file>icons/48x48/realtek.png</file>
<file>icons/48x48/search.png</file>
<file>icons/48x48/soundcard.png</file>
<file>icons/48x48/speaker.png</file>
<file>icons/48x48/star-grey.png</file>
<file>icons/48x48/star.png</file>
<file>icons/48x48/strawberry.png</file>
<file>icons/48x48/tools-wizard.png</file>
<file>icons/48x48/view-choose.png</file>
<file>icons/48x48/view-fullscreen.png</file>
<file>icons/48x48/view-media-lyrics.png</file>
<file>icons/48x48/view-media-playlist.png</file>
<file>icons/48x48/view-media-visualization.png</file>
<file>icons/48x48/view-refresh.png</file>
<file>icons/48x48/vinyl.png</file>
<file>icons/48x48/vlc.png</file>
<file>icons/48x48/xine.png</file>
<file>icons/48x48/zoom-in.png</file>
<file>icons/48x48/zoom-out.png</file>
<file>icons/48x48/tidal.png</file>
<file>icons/32x32/albums.png</file>
<file>icons/32x32/alsa.png</file>
<file>icons/32x32/application-exit.png</file>
<file>icons/32x32/applications-internet.png</file>
<file>icons/32x32/bluetooth.png</file>
<file>icons/32x32/cdcase.png</file>
<file>icons/32x32/cd.png</file>
<file>icons/32x32/configure.png</file>
<file>icons/32x32/device-ipod-nano.png</file>
<file>icons/32x32/device-ipod.png</file>
<file>icons/32x32/device-phone.png</file>
<file>icons/32x32/device.png</file>
<file>icons/32x32/device-usb-drive.png</file>
<file>icons/32x32/device-usb-flash.png</file>
<file>icons/32x32/dialog-error.png</file>
<file>icons/32x32/dialog-information.png</file>
<file>icons/32x32/dialog-ok-apply.png</file>
<file>icons/32x32/dialog-password.png</file>
<file>icons/32x32/dialog-warning.png</file>
<file>icons/32x32/document-download.png</file>
<file>icons/32x32/document-new.png</file>
<file>icons/32x32/document-open-folder.png</file>
<file>icons/32x32/document-open.png</file>
<file>icons/32x32/document-save.png</file>
<file>icons/32x32/document-search.png</file>
<file>icons/32x32/download.png</file>
<file>icons/32x32/edit-clear-list.png</file>
<file>icons/32x32/edit-clear-locationbar-ltr.png</file>
<file>icons/32x32/edit-copy.png</file>
<file>icons/32x32/edit-delete.png</file>
<file>icons/32x32/edit-find.png</file>
<file>icons/32x32/edit-redo.png</file>
<file>icons/32x32/edit-rename.png</file>
<file>icons/32x32/edit-undo.png</file>
<file>icons/32x32/electrocompaniet.png</file>
<file>icons/32x32/equalizer.png</file>
<file>icons/32x32/folder-new.png</file>
<file>icons/32x32/folder.png</file>
<file>icons/32x32/folder-sound.png</file>
<file>icons/32x32/footsteps.png</file>
<file>icons/32x32/go-down.png</file>
<file>icons/32x32/go-home.png</file>
<file>icons/32x32/go-jump.png</file>
<file>icons/32x32/go-next.png</file>
<file>icons/32x32/go-previous.png</file>
<file>icons/32x32/go-up.png</file>
<file>icons/32x32/gstreamer.png</file>
<file>icons/32x32/headset.png</file>
<file>icons/32x32/help-hint.png</file>
<file>icons/32x32/intel.png</file>
<file>icons/32x32/jack.png</file>
<file>icons/32x32/keyboard.png</file>
<file>icons/32x32/list-add.png</file>
<file>icons/32x32/list-remove.png</file>
<file>icons/32x32/mcintosh-player.png</file>
<file>icons/32x32/mcintosh.png</file>
<file>icons/32x32/mcintosh-text.png</file>
<file>icons/32x32/media-eject.png</file>
<file>icons/32x32/media-forward.png</file>
<file>icons/32x32/media-pause.png</file>
<file>icons/32x32/media-playlist-repeat.png</file>
<file>icons/32x32/media-playlist-shuffle.png</file>
<file>icons/32x32/media-play.png</file>
<file>icons/32x32/media-rewind.png</file>
<file>icons/32x32/media-stop.png</file>
<file>icons/32x32/nvidia.png</file>
<file>icons/32x32/play2.png</file>
<file>icons/32x32/pulseaudio.png</file>
<file>icons/32x32/realtek.png</file>
<file>icons/32x32/search.png</file>
<file>icons/32x32/soundcard.png</file>
<file>icons/32x32/speaker.png</file>
<file>icons/32x32/star-grey.png</file>
<file>icons/32x32/star.png</file>
<file>icons/32x32/strawberry.png</file>
<file>icons/32x32/strawberry.svg</file>
<file>icons/32x32/tools-wizard.png</file>
<file>icons/32x32/view-choose.png</file>
<file>icons/32x32/view-fullscreen.png</file>
<file>icons/32x32/view-media-lyrics.png</file>
<file>icons/32x32/view-media-playlist.png</file>
<file>icons/32x32/view-media-visualization.png</file>
<file>icons/32x32/view-refresh.png</file>
<file>icons/32x32/vinyl.png</file>
<file>icons/32x32/vlc.png</file>
<file>icons/32x32/xine.png</file>
<file>icons/32x32/zoom-in.png</file>
<file>icons/32x32/zoom-out.png</file>
<file>icons/32x32/tidal.png</file>
<file>icons/22x22/albums.png</file>
<file>icons/22x22/alsa.png</file>
<file>icons/22x22/application-exit.png</file>
<file>icons/22x22/applications-internet.png</file>
<file>icons/22x22/bluetooth.png</file>
<file>icons/22x22/cdcase.png</file>
<file>icons/22x22/cd.png</file>
<file>icons/22x22/configure.png</file>
<file>icons/22x22/device-ipod-nano.png</file>
<file>icons/22x22/device-ipod.png</file>
<file>icons/22x22/device-phone.png</file>
<file>icons/22x22/device.png</file>
<file>icons/22x22/device-usb-drive.png</file>
<file>icons/22x22/device-usb-flash.png</file>
<file>icons/22x22/dialog-error.png</file>
<file>icons/22x22/dialog-information.png</file>
<file>icons/22x22/dialog-ok-apply.png</file>
<file>icons/22x22/dialog-password.png</file>
<file>icons/22x22/dialog-warning.png</file>
<file>icons/22x22/document-download.png</file>
<file>icons/22x22/document-new.png</file>
<file>icons/22x22/document-open-folder.png</file>
<file>icons/22x22/document-open.png</file>
<file>icons/22x22/document-save.png</file>
<file>icons/22x22/document-search.png</file>
<file>icons/22x22/download.png</file>
<file>icons/22x22/edit-clear-list.png</file>
<file>icons/22x22/edit-clear-locationbar-ltr.png</file>
<file>icons/22x22/edit-copy.png</file>
<file>icons/22x22/edit-delete.png</file>
<file>icons/22x22/edit-find.png</file>
<file>icons/22x22/edit-redo.png</file>
<file>icons/22x22/edit-rename.png</file>
<file>icons/22x22/edit-undo.png</file>
<file>icons/22x22/electrocompaniet.png</file>
<file>icons/22x22/equalizer.png</file>
<file>icons/22x22/folder-new.png</file>
<file>icons/22x22/folder.png</file>
<file>icons/22x22/folder-sound.png</file>
<file>icons/22x22/footsteps.png</file>
<file>icons/22x22/go-down.png</file>
<file>icons/22x22/go-home.png</file>
<file>icons/22x22/go-jump.png</file>
<file>icons/22x22/go-next.png</file>
<file>icons/22x22/go-previous.png</file>
<file>icons/22x22/go-up.png</file>
<file>icons/22x22/gstreamer.png</file>
<file>icons/22x22/headset.png</file>
<file>icons/22x22/help-hint.png</file>
<file>icons/22x22/intel.png</file>
<file>icons/22x22/jack.png</file>
<file>icons/22x22/keyboard.png</file>
<file>icons/22x22/list-add.png</file>
<file>icons/22x22/list-remove.png</file>
<file>icons/22x22/mcintosh-player.png</file>
<file>icons/22x22/mcintosh.png</file>
<file>icons/22x22/mcintosh-text.png</file>
<file>icons/22x22/media-eject.png</file>
<file>icons/22x22/media-forward.png</file>
<file>icons/22x22/media-pause.png</file>
<file>icons/22x22/media-playlist-repeat.png</file>
<file>icons/22x22/media-playlist-shuffle.png</file>
<file>icons/22x22/media-play.png</file>
<file>icons/22x22/media-rewind.png</file>
<file>icons/22x22/media-stop.png</file>
<file>icons/22x22/nvidia.png</file>
<file>icons/22x22/play2.png</file>
<file>icons/22x22/pulseaudio.png</file>
<file>icons/22x22/realtek.png</file>
<file>icons/22x22/search.png</file>
<file>icons/22x22/soundcard.png</file>
<file>icons/22x22/speaker.png</file>
<file>icons/22x22/star-grey.png</file>
<file>icons/22x22/star.png</file>
<file>icons/22x22/strawberry.png</file>
<file>icons/22x22/strawberry.svg</file>
<file>icons/22x22/tools-wizard.png</file>
<file>icons/22x22/view-choose.png</file>
<file>icons/22x22/view-fullscreen.png</file>
<file>icons/22x22/view-media-lyrics.png</file>
<file>icons/22x22/view-media-playlist.png</file>
<file>icons/22x22/view-media-visualization.png</file>
<file>icons/22x22/view-refresh.png</file>
<file>icons/22x22/vinyl.png</file>
<file>icons/22x22/vlc.png</file>
<file>icons/22x22/xine.png</file>
<file>icons/22x22/zoom-in.png</file>
<file>icons/22x22/zoom-out.png</file>
<file>icons/22x22/tidal.png</file>
<file>fonts/HumongousofEternitySt.ttf</file> <file>fonts/HumongousofEternitySt.ttf</file>
</qresource> </qresource>
</RCC> </RCC>

View File

@@ -1,4 +1,444 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
</qresource> <file>icons/128x128/albums.png</file>
<file>icons/128x128/alsa.png</file>
<file>icons/128x128/application-exit.png</file>
<file>icons/128x128/applications-internet.png</file>
<file>icons/128x128/bluetooth.png</file>
<file>icons/128x128/cdcase.png</file>
<file>icons/128x128/cd.png</file>
<file>icons/128x128/configure.png</file>
<file>icons/128x128/device-ipod-nano.png</file>
<file>icons/128x128/device-ipod.png</file>
<file>icons/128x128/device-phone.png</file>
<file>icons/128x128/device.png</file>
<file>icons/128x128/device-usb-drive.png</file>
<file>icons/128x128/device-usb-flash.png</file>
<file>icons/128x128/dialog-error.png</file>
<file>icons/128x128/dialog-information.png</file>
<file>icons/128x128/dialog-ok-apply.png</file>
<file>icons/128x128/dialog-password.png</file>
<file>icons/128x128/dialog-warning.png</file>
<file>icons/128x128/document-download.png</file>
<file>icons/128x128/document-new.png</file>
<file>icons/128x128/document-open-folder.png</file>
<file>icons/128x128/document-open.png</file>
<file>icons/128x128/document-save.png</file>
<file>icons/128x128/document-search.png</file>
<file>icons/128x128/download.png</file>
<file>icons/128x128/edit-clear-list.png</file>
<file>icons/128x128/edit-clear-locationbar-ltr.png</file>
<file>icons/128x128/edit-copy.png</file>
<file>icons/128x128/edit-delete.png</file>
<file>icons/128x128/edit-find.png</file>
<file>icons/128x128/edit-redo.png</file>
<file>icons/128x128/edit-rename.png</file>
<file>icons/128x128/edit-undo.png</file>
<file>icons/128x128/electrocompaniet.png</file>
<file>icons/128x128/equalizer.png</file>
<file>icons/128x128/folder-new.png</file>
<file>icons/128x128/folder.png</file>
<file>icons/128x128/folder-sound.png</file>
<file>icons/128x128/footsteps.png</file>
<file>icons/128x128/go-down.png</file>
<file>icons/128x128/go-home.png</file>
<file>icons/128x128/go-jump.png</file>
<file>icons/128x128/go-next.png</file>
<file>icons/128x128/go-previous.png</file>
<file>icons/128x128/go-up.png</file>
<file>icons/128x128/gstreamer.png</file>
<file>icons/128x128/headset.png</file>
<file>icons/128x128/help-hint.png</file>
<file>icons/128x128/intel.png</file>
<file>icons/128x128/jack.png</file>
<file>icons/128x128/keyboard.png</file>
<file>icons/128x128/list-add.png</file>
<file>icons/128x128/list-remove.png</file>
<file>icons/128x128/mcintosh-player.png</file>
<file>icons/128x128/mcintosh-text.png</file>
<file>icons/128x128/media-eject.png</file>
<file>icons/128x128/media-forward.png</file>
<file>icons/128x128/media-pause.png</file>
<file>icons/128x128/media-play.png</file>
<file>icons/128x128/media-rewind.png</file>
<file>icons/128x128/media-stop.png</file>
<file>icons/128x128/nvidia.png</file>
<file>icons/128x128/play2.png</file>
<file>icons/128x128/realtek.png</file>
<file>icons/128x128/search.png</file>
<file>icons/128x128/soundcard.png</file>
<file>icons/128x128/speaker.png</file>
<file>icons/128x128/star-grey.png</file>
<file>icons/128x128/star.png</file>
<file>icons/128x128/strawberry.png</file>
<file>icons/128x128/strawberry.svg</file>
<file>icons/128x128/tools-wizard.png</file>
<file>icons/128x128/view-choose.png</file>
<file>icons/128x128/view-fullscreen.png</file>
<file>icons/128x128/view-media-lyrics.png</file>
<file>icons/128x128/view-media-playlist.png</file>
<file>icons/128x128/view-media-visualization.png</file>
<file>icons/128x128/view-refresh.png</file>
<file>icons/128x128/vinyl.png</file>
<file>icons/128x128/vlc.png</file>
<file>icons/128x128/xine.png</file>
<file>icons/128x128/zoom-in.png</file>
<file>icons/128x128/zoom-out.png</file>
<file>icons/128x128/tidal.png</file>
<file>icons/128x128/deezer.png</file>
<file>icons/64x64/albums.png</file>
<file>icons/64x64/alsa.png</file>
<file>icons/64x64/application-exit.png</file>
<file>icons/64x64/applications-internet.png</file>
<file>icons/64x64/bluetooth.png</file>
<file>icons/64x64/cdcase.png</file>
<file>icons/64x64/cd.png</file>
<file>icons/64x64/configure.png</file>
<file>icons/64x64/device-ipod-nano.png</file>
<file>icons/64x64/device-ipod.png</file>
<file>icons/64x64/device-phone.png</file>
<file>icons/64x64/device.png</file>
<file>icons/64x64/device-usb-drive.png</file>
<file>icons/64x64/device-usb-flash.png</file>
<file>icons/64x64/dialog-error.png</file>
<file>icons/64x64/dialog-information.png</file>
<file>icons/64x64/dialog-ok-apply.png</file>
<file>icons/64x64/dialog-password.png</file>
<file>icons/64x64/dialog-warning.png</file>
<file>icons/64x64/document-download.png</file>
<file>icons/64x64/document-new.png</file>
<file>icons/64x64/document-open-folder.png</file>
<file>icons/64x64/document-open.png</file>
<file>icons/64x64/document-save.png</file>
<file>icons/64x64/document-search.png</file>
<file>icons/64x64/download.png</file>
<file>icons/64x64/edit-clear-list.png</file>
<file>icons/64x64/edit-clear-locationbar-ltr.png</file>
<file>icons/64x64/edit-copy.png</file>
<file>icons/64x64/edit-delete.png</file>
<file>icons/64x64/edit-find.png</file>
<file>icons/64x64/edit-redo.png</file>
<file>icons/64x64/edit-rename.png</file>
<file>icons/64x64/edit-undo.png</file>
<file>icons/64x64/electrocompaniet.png</file>
<file>icons/64x64/equalizer.png</file>
<file>icons/64x64/folder-new.png</file>
<file>icons/64x64/folder.png</file>
<file>icons/64x64/folder-sound.png</file>
<file>icons/64x64/footsteps.png</file>
<file>icons/64x64/go-down.png</file>
<file>icons/64x64/go-home.png</file>
<file>icons/64x64/go-jump.png</file>
<file>icons/64x64/go-next.png</file>
<file>icons/64x64/go-previous.png</file>
<file>icons/64x64/go-up.png</file>
<file>icons/64x64/gstreamer.png</file>
<file>icons/64x64/headset.png</file>
<file>icons/64x64/help-hint.png</file>
<file>icons/64x64/intel.png</file>
<file>icons/64x64/jack.png</file>
<file>icons/64x64/keyboard.png</file>
<file>icons/64x64/list-add.png</file>
<file>icons/64x64/list-remove.png</file>
<file>icons/64x64/mcintosh-player.png</file>
<file>icons/64x64/mcintosh-text.png</file>
<file>icons/64x64/media-eject.png</file>
<file>icons/64x64/media-forward.png</file>
<file>icons/64x64/media-pause.png</file>
<file>icons/64x64/media-play.png</file>
<file>icons/64x64/media-rewind.png</file>
<file>icons/64x64/media-stop.png</file>
<file>icons/64x64/nvidia.png</file>
<file>icons/64x64/play2.png</file>
<file>icons/64x64/pulseaudio.png</file>
<file>icons/64x64/realtek.png</file>
<file>icons/64x64/search.png</file>
<file>icons/64x64/soundcard.png</file>
<file>icons/64x64/speaker.png</file>
<file>icons/64x64/star-grey.png</file>
<file>icons/64x64/star.png</file>
<file>icons/64x64/strawberry.png</file>
<file>icons/64x64/tools-wizard.png</file>
<file>icons/64x64/view-choose.png</file>
<file>icons/64x64/view-fullscreen.png</file>
<file>icons/64x64/view-media-lyrics.png</file>
<file>icons/64x64/view-media-playlist.png</file>
<file>icons/64x64/view-media-visualization.png</file>
<file>icons/64x64/view-refresh.png</file>
<file>icons/64x64/vinyl.png</file>
<file>icons/64x64/vlc.png</file>
<file>icons/64x64/xine.png</file>
<file>icons/64x64/zoom-in.png</file>
<file>icons/64x64/zoom-out.png</file>
<file>icons/64x64/tidal.png</file>
<file>icons/64x64/deezer.png</file>
<file>icons/48x48/albums.png</file>
<file>icons/48x48/alsa.png</file>
<file>icons/48x48/application-exit.png</file>
<file>icons/48x48/applications-internet.png</file>
<file>icons/48x48/bluetooth.png</file>
<file>icons/48x48/cdcase.png</file>
<file>icons/48x48/cd.png</file>
<file>icons/48x48/configure.png</file>
<file>icons/48x48/device-ipod-nano.png</file>
<file>icons/48x48/device-ipod.png</file>
<file>icons/48x48/device-phone.png</file>
<file>icons/48x48/device.png</file>
<file>icons/48x48/device-usb-drive.png</file>
<file>icons/48x48/device-usb-flash.png</file>
<file>icons/48x48/dialog-error.png</file>
<file>icons/48x48/dialog-information.png</file>
<file>icons/48x48/dialog-ok-apply.png</file>
<file>icons/48x48/dialog-password.png</file>
<file>icons/48x48/dialog-warning.png</file>
<file>icons/48x48/document-download.png</file>
<file>icons/48x48/document-new.png</file>
<file>icons/48x48/document-open-folder.png</file>
<file>icons/48x48/document-open.png</file>
<file>icons/48x48/document-save.png</file>
<file>icons/48x48/document-search.png</file>
<file>icons/48x48/download.png</file>
<file>icons/48x48/edit-clear-list.png</file>
<file>icons/48x48/edit-clear-locationbar-ltr.png</file>
<file>icons/48x48/edit-copy.png</file>
<file>icons/48x48/edit-delete.png</file>
<file>icons/48x48/edit-find.png</file>
<file>icons/48x48/edit-redo.png</file>
<file>icons/48x48/edit-rename.png</file>
<file>icons/48x48/edit-undo.png</file>
<file>icons/48x48/electrocompaniet.png</file>
<file>icons/48x48/equalizer.png</file>
<file>icons/48x48/folder-new.png</file>
<file>icons/48x48/folder.png</file>
<file>icons/48x48/folder-sound.png</file>
<file>icons/48x48/footsteps.png</file>
<file>icons/48x48/go-down.png</file>
<file>icons/48x48/go-home.png</file>
<file>icons/48x48/go-jump.png</file>
<file>icons/48x48/go-next.png</file>
<file>icons/48x48/go-previous.png</file>
<file>icons/48x48/go-up.png</file>
<file>icons/48x48/gstreamer.png</file>
<file>icons/48x48/headset.png</file>
<file>icons/48x48/help-hint.png</file>
<file>icons/48x48/intel.png</file>
<file>icons/48x48/jack.png</file>
<file>icons/48x48/keyboard.png</file>
<file>icons/48x48/list-add.png</file>
<file>icons/48x48/list-remove.png</file>
<file>icons/48x48/mcintosh-player.png</file>
<file>icons/48x48/mcintosh.png</file>
<file>icons/48x48/mcintosh-text.png</file>
<file>icons/48x48/media-eject.png</file>
<file>icons/48x48/media-forward.png</file>
<file>icons/48x48/media-pause.png</file>
<file>icons/48x48/media-playlist-repeat.png</file>
<file>icons/48x48/media-playlist-shuffle.png</file>
<file>icons/48x48/media-play.png</file>
<file>icons/48x48/media-rewind.png</file>
<file>icons/48x48/media-stop.png</file>
<file>icons/48x48/nvidia.png</file>
<file>icons/48x48/play2.png</file>
<file>icons/48x48/pulseaudio.png</file>
<file>icons/48x48/realtek.png</file>
<file>icons/48x48/search.png</file>
<file>icons/48x48/soundcard.png</file>
<file>icons/48x48/speaker.png</file>
<file>icons/48x48/star-grey.png</file>
<file>icons/48x48/star.png</file>
<file>icons/48x48/strawberry.png</file>
<file>icons/48x48/tools-wizard.png</file>
<file>icons/48x48/view-choose.png</file>
<file>icons/48x48/view-fullscreen.png</file>
<file>icons/48x48/view-media-lyrics.png</file>
<file>icons/48x48/view-media-playlist.png</file>
<file>icons/48x48/view-media-visualization.png</file>
<file>icons/48x48/view-refresh.png</file>
<file>icons/48x48/vinyl.png</file>
<file>icons/48x48/vlc.png</file>
<file>icons/48x48/xine.png</file>
<file>icons/48x48/zoom-in.png</file>
<file>icons/48x48/zoom-out.png</file>
<file>icons/48x48/tidal.png</file>
<file>icons/32x32/albums.png</file>
<file>icons/32x32/alsa.png</file>
<file>icons/32x32/application-exit.png</file>
<file>icons/32x32/applications-internet.png</file>
<file>icons/32x32/bluetooth.png</file>
<file>icons/32x32/cdcase.png</file>
<file>icons/32x32/cd.png</file>
<file>icons/32x32/configure.png</file>
<file>icons/32x32/device-ipod-nano.png</file>
<file>icons/32x32/device-ipod.png</file>
<file>icons/32x32/device-phone.png</file>
<file>icons/32x32/device.png</file>
<file>icons/32x32/device-usb-drive.png</file>
<file>icons/32x32/device-usb-flash.png</file>
<file>icons/32x32/dialog-error.png</file>
<file>icons/32x32/dialog-information.png</file>
<file>icons/32x32/dialog-ok-apply.png</file>
<file>icons/32x32/dialog-password.png</file>
<file>icons/32x32/dialog-warning.png</file>
<file>icons/32x32/document-download.png</file>
<file>icons/32x32/document-new.png</file>
<file>icons/32x32/document-open-folder.png</file>
<file>icons/32x32/document-open.png</file>
<file>icons/32x32/document-save.png</file>
<file>icons/32x32/document-search.png</file>
<file>icons/32x32/download.png</file>
<file>icons/32x32/edit-clear-list.png</file>
<file>icons/32x32/edit-clear-locationbar-ltr.png</file>
<file>icons/32x32/edit-copy.png</file>
<file>icons/32x32/edit-delete.png</file>
<file>icons/32x32/edit-find.png</file>
<file>icons/32x32/edit-redo.png</file>
<file>icons/32x32/edit-rename.png</file>
<file>icons/32x32/edit-undo.png</file>
<file>icons/32x32/electrocompaniet.png</file>
<file>icons/32x32/equalizer.png</file>
<file>icons/32x32/folder-new.png</file>
<file>icons/32x32/folder.png</file>
<file>icons/32x32/folder-sound.png</file>
<file>icons/32x32/footsteps.png</file>
<file>icons/32x32/go-down.png</file>
<file>icons/32x32/go-home.png</file>
<file>icons/32x32/go-jump.png</file>
<file>icons/32x32/go-next.png</file>
<file>icons/32x32/go-previous.png</file>
<file>icons/32x32/go-up.png</file>
<file>icons/32x32/gstreamer.png</file>
<file>icons/32x32/headset.png</file>
<file>icons/32x32/help-hint.png</file>
<file>icons/32x32/intel.png</file>
<file>icons/32x32/jack.png</file>
<file>icons/32x32/keyboard.png</file>
<file>icons/32x32/list-add.png</file>
<file>icons/32x32/list-remove.png</file>
<file>icons/32x32/mcintosh-player.png</file>
<file>icons/32x32/mcintosh.png</file>
<file>icons/32x32/mcintosh-text.png</file>
<file>icons/32x32/media-eject.png</file>
<file>icons/32x32/media-forward.png</file>
<file>icons/32x32/media-pause.png</file>
<file>icons/32x32/media-playlist-repeat.png</file>
<file>icons/32x32/media-playlist-shuffle.png</file>
<file>icons/32x32/media-play.png</file>
<file>icons/32x32/media-rewind.png</file>
<file>icons/32x32/media-stop.png</file>
<file>icons/32x32/nvidia.png</file>
<file>icons/32x32/play2.png</file>
<file>icons/32x32/pulseaudio.png</file>
<file>icons/32x32/realtek.png</file>
<file>icons/32x32/search.png</file>
<file>icons/32x32/soundcard.png</file>
<file>icons/32x32/speaker.png</file>
<file>icons/32x32/star-grey.png</file>
<file>icons/32x32/star.png</file>
<file>icons/32x32/strawberry.png</file>
<file>icons/32x32/strawberry.svg</file>
<file>icons/32x32/tools-wizard.png</file>
<file>icons/32x32/view-choose.png</file>
<file>icons/32x32/view-fullscreen.png</file>
<file>icons/32x32/view-media-lyrics.png</file>
<file>icons/32x32/view-media-playlist.png</file>
<file>icons/32x32/view-media-visualization.png</file>
<file>icons/32x32/view-refresh.png</file>
<file>icons/32x32/vinyl.png</file>
<file>icons/32x32/vlc.png</file>
<file>icons/32x32/xine.png</file>
<file>icons/32x32/zoom-in.png</file>
<file>icons/32x32/zoom-out.png</file>
<file>icons/32x32/tidal.png</file>
<file>icons/32x32/deezer.png</file>
<file>icons/22x22/albums.png</file>
<file>icons/22x22/alsa.png</file>
<file>icons/22x22/application-exit.png</file>
<file>icons/22x22/applications-internet.png</file>
<file>icons/22x22/bluetooth.png</file>
<file>icons/22x22/cdcase.png</file>
<file>icons/22x22/cd.png</file>
<file>icons/22x22/configure.png</file>
<file>icons/22x22/device-ipod-nano.png</file>
<file>icons/22x22/device-ipod.png</file>
<file>icons/22x22/device-phone.png</file>
<file>icons/22x22/device.png</file>
<file>icons/22x22/device-usb-drive.png</file>
<file>icons/22x22/device-usb-flash.png</file>
<file>icons/22x22/dialog-error.png</file>
<file>icons/22x22/dialog-information.png</file>
<file>icons/22x22/dialog-ok-apply.png</file>
<file>icons/22x22/dialog-password.png</file>
<file>icons/22x22/dialog-warning.png</file>
<file>icons/22x22/document-download.png</file>
<file>icons/22x22/document-new.png</file>
<file>icons/22x22/document-open-folder.png</file>
<file>icons/22x22/document-open.png</file>
<file>icons/22x22/document-save.png</file>
<file>icons/22x22/document-search.png</file>
<file>icons/22x22/download.png</file>
<file>icons/22x22/edit-clear-list.png</file>
<file>icons/22x22/edit-clear-locationbar-ltr.png</file>
<file>icons/22x22/edit-copy.png</file>
<file>icons/22x22/edit-delete.png</file>
<file>icons/22x22/edit-find.png</file>
<file>icons/22x22/edit-redo.png</file>
<file>icons/22x22/edit-rename.png</file>
<file>icons/22x22/edit-undo.png</file>
<file>icons/22x22/electrocompaniet.png</file>
<file>icons/22x22/equalizer.png</file>
<file>icons/22x22/folder-new.png</file>
<file>icons/22x22/folder.png</file>
<file>icons/22x22/folder-sound.png</file>
<file>icons/22x22/footsteps.png</file>
<file>icons/22x22/go-down.png</file>
<file>icons/22x22/go-home.png</file>
<file>icons/22x22/go-jump.png</file>
<file>icons/22x22/go-next.png</file>
<file>icons/22x22/go-previous.png</file>
<file>icons/22x22/go-up.png</file>
<file>icons/22x22/gstreamer.png</file>
<file>icons/22x22/headset.png</file>
<file>icons/22x22/help-hint.png</file>
<file>icons/22x22/intel.png</file>
<file>icons/22x22/jack.png</file>
<file>icons/22x22/keyboard.png</file>
<file>icons/22x22/list-add.png</file>
<file>icons/22x22/list-remove.png</file>
<file>icons/22x22/mcintosh-player.png</file>
<file>icons/22x22/mcintosh.png</file>
<file>icons/22x22/mcintosh-text.png</file>
<file>icons/22x22/media-eject.png</file>
<file>icons/22x22/media-forward.png</file>
<file>icons/22x22/media-pause.png</file>
<file>icons/22x22/media-playlist-repeat.png</file>
<file>icons/22x22/media-playlist-shuffle.png</file>
<file>icons/22x22/media-play.png</file>
<file>icons/22x22/media-rewind.png</file>
<file>icons/22x22/media-stop.png</file>
<file>icons/22x22/nvidia.png</file>
<file>icons/22x22/play2.png</file>
<file>icons/22x22/pulseaudio.png</file>
<file>icons/22x22/realtek.png</file>
<file>icons/22x22/search.png</file>
<file>icons/22x22/soundcard.png</file>
<file>icons/22x22/speaker.png</file>
<file>icons/22x22/star-grey.png</file>
<file>icons/22x22/star.png</file>
<file>icons/22x22/strawberry.png</file>
<file>icons/22x22/strawberry.svg</file>
<file>icons/22x22/tools-wizard.png</file>
<file>icons/22x22/view-choose.png</file>
<file>icons/22x22/view-fullscreen.png</file>
<file>icons/22x22/view-media-lyrics.png</file>
<file>icons/22x22/view-media-playlist.png</file>
<file>icons/22x22/view-media-visualization.png</file>
<file>icons/22x22/view-refresh.png</file>
<file>icons/22x22/vinyl.png</file>
<file>icons/22x22/vlc.png</file>
<file>icons/22x22/xine.png</file>
<file>icons/22x22/zoom-in.png</file>
<file>icons/22x22/zoom-out.png</file>
<file>icons/22x22/tidal.png</file>
<file>icons/22x22/deezer.png</file>
</qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

BIN
data/icons/22x22/deezer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
data/icons/32x32/deezer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
data/icons/48x48/deezer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
data/icons/64x64/deezer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
data/icons/full/deezer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -0,0 +1,41 @@
<!doctype html>
<html>
<head>
<link href="http://www.strawbs.org/favicon.ico" rel="shortcut icon">
<title>tr("Return to Strawberry")</title>
<style>
#container {
margin: 6em auto 0px auto;
max-width: 400px;
font-family: 'arial regular', arial, sans-serif;
}
#container img {
width: 16px;
height: 16px;
float: left;
margin-right: 0.5em;
}
#container h1 {
margin: 0px 0px 0.75em 0px;
font-size: 16px;
}
#container p {
margin-top: 0px;
margin-left: 10px;
font-size: 13px;
}
</style>
</head>
<body>
<div id="container">
<h1>tr("Success!")</h1>
<img src="data:image/png;base64,@IMAGE_DATA@"/>
<p>tr("Please close your browser and return to Strawberry.")</p>
</div>
</body>
</html>

BIN
data/pictures/deezer.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

View File

@@ -57,7 +57,7 @@ CREATE TABLE device_%deviceid_songs (
effective_albumartist TEXT, effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0, effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT cue_path TEXT
); );

View File

@@ -1,11 +1,9 @@
#playlist { #playlist {
background-color: %palette-base; background-color: %palette-base;
alternate-background-color: %palette-alternate-base; alternate-background-color: %palette-alternate-base;
} }
#playlist[default_background_enabled = "true"] { #playlist[default_background_enabled = "true"] {
background-image: url(:pictures/strawbs-transparent.png);
background-attachment: fixed; background-attachment: fixed;
background-position: bottom right; background-position: bottom right;
background-repeat: none; background-repeat: none;
@@ -45,11 +43,11 @@ QToolButton:pressed[popupMode="1"] {
padding-right: 16px; padding-right: 16px;
} }
darwin { macos {
font-size: 11pt; font-size: 11pt;
} }
darwin QMenu { macos QMenu {
font-size: 13pt; font-size: 13pt;
} }

10
dist/CMakeLists.txt vendored
View File

@@ -2,12 +2,17 @@ execute_process(COMMAND env LC_ALL="en_US.utf8" date "+%a %b %d %Y" OUTPUT_VARIA
execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec @ONLY) if (RPM_DISTRO)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec @ONLY)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog.in ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog.in ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-64.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-64.nsi @ONLY)
if (UNIX AND NOT APPLE) if (UNIX AND NOT APPLE)
install(FILES ../data/icons/48x48/strawberry.png DESTINATION share/icons/hicolor/48x48/apps/) install(FILES ../data/icons/48x48/strawberry.png DESTINATION share/icons/hicolor/48x48/apps/)
@@ -15,6 +20,7 @@ if (UNIX AND NOT APPLE)
install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/) install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/)
install(FILES ../data/icons/128x128/strawberry.svg DESTINATION share/icons/hicolor/scalable/apps/) install(FILES ../data/icons/128x128/strawberry.svg DESTINATION share/icons/hicolor/scalable/apps/)
install(FILES unix/strawberry.desktop DESTINATION share/applications) install(FILES unix/strawberry.desktop DESTINATION share/applications)
install(FILES unix/strawberry.appdata.xml DESTINATION share/metainfo)
install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1) install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1)
endif() endif()

6
dist/debian/control vendored
View File

@@ -1,7 +1,7 @@
Source: strawberry Source: strawberry
Section: sound Section: sound
Priority: optional Priority: optional
Maintainer: "Jonas Kvinge" <jonas@jkvinge.net> Maintainer: Jonas Kvinge <jonas@jkvinge.net>
Build-Depends: debhelper (>= 7), Build-Depends: debhelper (>= 7),
make, make,
cmake, cmake,
@@ -20,7 +20,6 @@ Build-Depends: debhelper (>= 7),
qtbase5-dev-tools, qtbase5-dev-tools,
qtbase5-private-dev, qtbase5-private-dev,
qt5-dev-tools, qt5-dev-tools,
libqt5opengl5-dev,
libqt5x11extras5-dev, libqt5x11extras5-dev,
libgstreamer1.0-dev, libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev, libgstreamer-plugins-base1.0-dev,
@@ -42,13 +41,14 @@ Architecture: any
Depends: ${shlibs:Depends}, Depends: ${shlibs:Depends},
${misc:Depends}, ${misc:Depends},
libsqlite3-0, libsqlite3-0,
libqt5sql5-sqlite,
gstreamer1.0-plugins-base, gstreamer1.0-plugins-base,
gstreamer1.0-plugins-good, gstreamer1.0-plugins-good,
gstreamer1.0-alsa, gstreamer1.0-alsa,
gstreamer1.0-pulseaudio gstreamer1.0-pulseaudio
Homepage: http://www.strawbs.org/ Homepage: http://www.strawbs.org/
Description: Audio player and music collection organizer Description: Audio player and music collection organizer
Strawberry is a audio player especially aimed at audiophiles. Strawberry is a audio player aimed at music collectors, audio enthusiasts and audiophiles.
. .
Features: Features:
- Play and organize music - Play and organize music

2
dist/debian/rules vendored
View File

@@ -35,7 +35,7 @@ install: build
dh_testroot dh_testroot
dh_prep dh_prep
dh_installdirs dh_installdirs
make install make install
binary-indep: install binary-indep: install

View File

@@ -2,15 +2,15 @@ Name: strawberry
Version: @STRAWBERRY_VERSION_RPM_V@ Version: @STRAWBERRY_VERSION_RPM_V@
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@ Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
Summary: A audio player and music collection organiser Summary: A audio player and music collection organiser
Group: Applications/Multimedia Group: Applications/Multimedia
License: GPL-3.0+ License: GPLv3+
URL: http://www.strawbs.org/ URL: http://www.strawbs.org/
Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz
BuildRequires: boost-devel BuildRequires: boost-devel
BuildRequires: cmake BuildRequires: cmake
BuildRequires: desktop-file-utils BuildRequires: desktop-file-utils
BuildRequires: libappstream-glib
BuildRequires: gcc-c++ BuildRequires: gcc-c++
BuildRequires: hicolor-icon-theme BuildRequires: hicolor-icon-theme
BuildRequires: liblastfm-qt5-devel BuildRequires: liblastfm-qt5-devel
@@ -35,7 +35,6 @@ BuildRequires: pkgconfig(Qt5Network)
BuildRequires: pkgconfig(Qt5Xml) BuildRequires: pkgconfig(Qt5Xml)
BuildRequires: pkgconfig(Qt5X11Extras) BuildRequires: pkgconfig(Qt5X11Extras)
BuildRequires: pkgconfig(Qt5DBus) BuildRequires: pkgconfig(Qt5DBus)
BuildRequires: pkgconfig(Qt5OpenGL)
BuildRequires: pkgconfig(gstreamer-1.0) BuildRequires: pkgconfig(gstreamer-1.0)
BuildRequires: pkgconfig(gstreamer-app-1.0) BuildRequires: pkgconfig(gstreamer-app-1.0)
BuildRequires: pkgconfig(gstreamer-audio-1.0) BuildRequires: pkgconfig(gstreamer-audio-1.0)
@@ -68,7 +67,7 @@ Features:
* Audio analyzer * Audio analyzer
* Equalizer * Equalizer
* Transfer music to iPod, iPhone, MTP or mass-storage USB player * Transfer music to iPod, iPhone, MTP or mass-storage USB player
* Integrated Tidal support * Integrated Tidal and Deezer support
%prep %prep
%setup -qn %{name}-@STRAWBERRY_VERSION_PACKAGE@ %setup -qn %{name}-@STRAWBERRY_VERSION_PACKAGE@
@@ -82,7 +81,6 @@ export CXXFLAGS="%{optflags} -fpermissive"
mkdir %{_target_platform} mkdir %{_target_platform}
pushd %{_target_platform} pushd %{_target_platform}
%{cmake} \ %{cmake} \
-DBUILD_WERROR:BOOL=OFF \ -DBUILD_WERROR:BOOL=OFF \
-DCMAKE_BUILD_TYPE:STRING=Release \ -DCMAKE_BUILD_TYPE:STRING=Release \
@@ -93,18 +91,16 @@ popd
%install %install
make install DESTDIR=%{buildroot} -C %{_target_platform} make install DESTDIR=%{buildroot} -C %{_target_platform}
rm -rf %{buildroot}%{_datadir}/man mv %{buildroot}%{_datadir}/metainfo %{buildroot}%{_datadir}/appdata
%check %check
desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop
pushd %{_target_platform} appstream-util validate-relax --nonet %{buildroot}%{_datadir}/appdata/strawberry.appdata.xml
popd
%clean
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc %doc README.md Changelog
%license COPYING
%{_bindir}/strawberry %{_bindir}/strawberry
%{_bindir}/strawberry-tagreader %{_bindir}/strawberry-tagreader
%{_datadir}/applications/strawberry.desktop %{_datadir}/applications/strawberry.desktop
@@ -112,6 +108,9 @@ popd
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png %{_datadir}/icons/hicolor/64x64/apps/strawberry.png
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png %{_datadir}/icons/hicolor/128x128/apps/strawberry.png
%{_datadir}/icons/hicolor/scalable/apps/strawberry.svg %{_datadir}/icons/hicolor/scalable/apps/strawberry.svg
%{_datadir}/appdata/strawberry.appdata.xml
%{_mandir}/man1/strawberry.1.*
%{_mandir}/man1/strawberry-tagreader.1.*
%changelog %changelog
* @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@ * @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@

View File

@@ -2,7 +2,6 @@ Name: strawberry
Version: @STRAWBERRY_VERSION_RPM_V@ Version: @STRAWBERRY_VERSION_RPM_V@
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@ Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
Summary: A audio player and music collection organiser Summary: A audio player and music collection organiser
Group: Applications/Multimedia Group: Applications/Multimedia
License: GPL-3.0+ License: GPL-3.0+
URL: http://www.strawbs.org/ URL: http://www.strawbs.org/
@@ -16,6 +15,7 @@ BuildRequires: boost-devel
%endif %endif
BuildRequires: cmake BuildRequires: cmake
BuildRequires: desktop-file-utils BuildRequires: desktop-file-utils
BuildRequires: appstream-glib
BuildRequires: gcc-c++ BuildRequires: gcc-c++
BuildRequires: hicolor-icon-theme BuildRequires: hicolor-icon-theme
BuildRequires: libQt5Gui-private-headers-devel BuildRequires: libQt5Gui-private-headers-devel
@@ -42,7 +42,6 @@ BuildRequires: pkgconfig(Qt5Network)
BuildRequires: pkgconfig(Qt5Xml) BuildRequires: pkgconfig(Qt5Xml)
BuildRequires: pkgconfig(Qt5X11Extras) BuildRequires: pkgconfig(Qt5X11Extras)
BuildRequires: pkgconfig(Qt5DBus) BuildRequires: pkgconfig(Qt5DBus)
BuildRequires: pkgconfig(Qt5OpenGL)
BuildRequires: pkgconfig(gstreamer-1.0) BuildRequires: pkgconfig(gstreamer-1.0)
BuildRequires: pkgconfig(gstreamer-app-1.0) BuildRequires: pkgconfig(gstreamer-app-1.0)
BuildRequires: pkgconfig(gstreamer-audio-1.0) BuildRequires: pkgconfig(gstreamer-audio-1.0)
@@ -58,6 +57,8 @@ BuildRequires: pkgconfig(libudf)
BuildRequires: pkgconfig(libxine) BuildRequires: pkgconfig(libxine)
BuildRequires: pkgconfig(libvlc) BuildRequires: pkgconfig(libvlc)
Requires: libQt5Sql5-sqlite
%description %description
Strawberry is a audio player and music collection organizer. Strawberry is a audio player and music collection organizer.
It is a fork of Clementine. The name is inspired by the band Strawbs. It is a fork of Clementine. The name is inspired by the band Strawbs.
@@ -77,7 +78,7 @@ Features:
* Audio analyzer * Audio analyzer
* Equalizer * Equalizer
* Transfer music to iPod, iPhone, MTP or mass-storage USB player * Transfer music to iPod, iPhone, MTP or mass-storage USB player
* Integrated Tidal support * Integrated Tidal and Deezer support
%prep %prep
%setup -q -n %{name}-@STRAWBERRY_VERSION_PACKAGE@ %setup -q -n %{name}-@STRAWBERRY_VERSION_PACKAGE@
@@ -89,14 +90,26 @@ make %{?_smp_mflags}
%install %install
cd build cd build
make install DESTDIR=$RPM_BUILD_ROOT make install DESTDIR=$RPM_BUILD_ROOT
%if 0%{?suse_version} < 1500
mv %{buildroot}%{_datadir}/metainfo %{buildroot}%{_datadir}/appdata
%endif
%clean %clean
cd build cd build
make clean make clean
%check
desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop
%if 0%{?suse_version} >= 1500
appstream-util validate-relax --nonet %{buildroot}%{_datadir}/metainfo/strawberry.appdata.xml
%else
appstream-util validate-relax --nonet %{buildroot}%{_datadir}/appdata/strawberry.appdata.xml
%endif
%files %files
%defattr(-,root,root,-) %defattr(-,root,root,-)
%doc %doc README.md Changelog
%license COPYING
%{_bindir}/strawberry %{_bindir}/strawberry
%{_bindir}/strawberry-tagreader %{_bindir}/strawberry-tagreader
%{_datadir}/applications/strawberry.desktop %{_datadir}/applications/strawberry.desktop
@@ -104,6 +117,11 @@ make clean
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png %{_datadir}/icons/hicolor/64x64/apps/strawberry.png
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png %{_datadir}/icons/hicolor/128x128/apps/strawberry.png
%{_datadir}/icons/hicolor/scalable/apps/strawberry.svg %{_datadir}/icons/hicolor/scalable/apps/strawberry.svg
%if 0%{?suse_version} >= 1500
%{_datadir}/metainfo/strawberry.appdata.xml
%else
%{_datadir}/appdata/strawberry.appdata.xml
%endif
%{_mandir}/man1/%{name}.1%{?ext_man} %{_mandir}/man1/%{name}.1%{?ext_man}
%{_mandir}/man1/%{name}-tagreader.1%{?ext_man} %{_mandir}/man1/%{name}-tagreader.1%{?ext_man}

65
dist/pacman/PKGBUILD.in vendored Normal file
View File

@@ -0,0 +1,65 @@
# Maintainer: Jonas Kvinge <jonas@jkvinge.net>
pkgname=strawberry
pkgver=@STRAWBERRY_VERSION_PAC_V@
pkgrel=@STRAWBERRY_VERSION_PAC_R@
pkgdesc="A music player aimed at audio enthusiasts and music collectors"
arch=(x86_64)
url="http://www.strawbs.org/"
license=(GPL3)
makedepends=(git cmake make gcc boost)
depends=(
desktop-file-utils
hicolor-icon-theme
udisks2
protobuf
qt5-base
qt5-x11extras
sqlite3
alsa-lib
pulseaudio
dbus
taglib
gstreamer
gst-plugins-base
gst-plugins-good
xine-lib
vlc
phonon-qt5
chromaprint
liblastfm-qt5
)
optdepends=(
'libgpod: iPod classic support'
'liblastfm-qt5: LastFM cover provider'
'libcdio: Audio CD playback'
'libmtp: MTP device support'
'libusbmuxd: iPod Touch, iPhone, iPad support'
'libplist: iPod Touch, iPhone, iPad support'
'libimobiledevice: iPod Touch, iPhone, iPad support'
)
provides=(strawberry)
conflicts=(strawberry)
source=("git+https://github.com/jonaski/strawberry.git")
sha256sums=('SKIP')
pkgver() {
cd "strawberry"
git describe --long --tags | sed 's/\([^-]*-g\)/r\1/;s/-/./g'
}
prepare() {
cd "${srcdir}/strawberry"
install -d strawberry-build
}
build() {
cd "${srcdir}/strawberry/strawberry-build"
cmake .. \
-DCMAKE_INSTALL_PREFIX=/usr
make
}
package() {
cd "${srcdir}/strawberry/strawberry-build"
make DESTDIR="${pkgdir}" install
}

View File

@@ -19,7 +19,7 @@ do
echo "ERROR: Cannot dermine geometry for image: \"$i\"." echo "ERROR: Cannot dermine geometry for image: \"$i\"."
continue continue
fi fi
# Geometry can be 563x144+0+0 or 75x98 # Geometry can be 563x144+0+0 or 75x98
# we need to get rid of the plus (+) and the x characters: # we need to get rid of the plus (+) and the x characters:
w=`echo $g | sed 's/[^0-9]/ /g' | awk '{print $1}'` || exit 1 w=`echo $g | sed 's/[^0-9]/ /g' | awk '{print $1}'` || exit 1
@@ -32,10 +32,10 @@ do
echo "ERROR: Cannot dermine height for image: \"$x\"." echo "ERROR: Cannot dermine height for image: \"$x\"."
continue continue
fi fi
for x in $sizes for x in $sizes
do do
dest="$x/$file" dest="$x/$file"
if [ -f $dest ]; then if [ -f $dest ]; then
continue continue

View File

@@ -16,12 +16,15 @@ echo "Creating $name-$version.tar.xz..."
rm -f "$name-$version.tar.xz" rm -f "$name-$version.tar.xz"
tar -cJf $name-$version.tar.xz \ tar -cJf $name-$version.tar.xz \
--transform "s,^$rootnoslash,$name-$version," $exclude_vcs \ --transform "s,^$rootnoslash,$name-$version," $exclude_vcs \
--exclude "*.tar" \ --exclude="*.tar" \
--exclude "*.tar.*" \ --exclude="*.tar.*" \
--exclude "*.bz" \ --exclude="*.bz" \
--exclude "*.bz2" \ --exclude="*.bz2" \
--exclude "*.xz" \ --exclude="*.xz" \
--exclude ".directory" \ --exclude=".directory" \
--exclude "$root/CMakeLists.txt.user" \ --exclude="*.spec" \
--exclude "$root/build" \ --exclude="*.nsi" \
--exclude="$root/CMakeLists.txt.user" \
--exclude="$root/build" \
--exclude="$root/dist/debian/changelog" \
"$root" "$root"

51
dist/unix/strawberry.appdata.xml vendored Normal file
View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<component>
<id>org.strawberry.strawberry</id>
<launchable type="desktop-id">strawberry.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license>
<provides>
<binary>strawberry</binary>
<binary>strawberry-tagreader</binary>
</provides>
<name>Strawberry Music Player</name>
<summary>An audio player and music collection organizer</summary>
<url type="homepage">https://www.strawbs.org/</url>
<url type="bugtracker">https://github.com/jonaski/strawberry/</url>
<translation type="qt">strawberry</translation>
<description>
<p>
Strawberry is a audio player and music collection organizer.
It is a fork of Clementine. The name is inspired by the band Strawbs.
</p>
<p>Features:</p>
<ul>
<li>Play and organize music</li>
<li>Supports WAV, FLAC, WavPack, DSF, DSDIFF, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF</li>
<li>Audio CD playback</li>
<li>Native desktop notifications</li>
<li>Playlists in multiple formats</li>
<li>Advanced output and device options with support for bit perfect playback on Linux</li>
<li>Edit tags on music files</li>
<li>Fetch tags from MusicBrainz</li>
<li>Album cover art from Last.fm, Musicbrainz and Discogs</li>
<li>Song lyrics from AudD and API Seeds</li>
<li>Support for multiple backends</li>
<li>Audio analyzer</li>
<li>Audio equalizer</li>
<li>Transfer music to iPod, iPhone, MTP or mass-storage USB player</li>
<li>Integrated Tidal and Deezer support</li>
</ul>
</description>
<screenshots>
<screenshot type="default">
<caption>Song playing showing context</caption>
<image width="1600" height="874">https://www.strawbs.org/pictures/appdata-screenshot-001.png</image>
</screenshot>
<screenshot>
<caption>Collection overview</caption>
<image width="1600" height="874">https://www.strawbs.org/pictures/appdata-screenshot-002.png</image>
</screenshot>
</screenshots>
<update_contact>eclipseo@fedoraproject.org</update_contact>
</component>

View File

@@ -9,107 +9,107 @@ _____________________________________________________________________________
These functions register an application with Windows Vista's and Windows 7's These functions register an application with Windows Vista's and Windows 7's
Default Programs window. Default Programs window.
Usage: Usage:
!include "Capabilities.nsh" !include "Capabilities.nsh"
!define CAPABILITIES_NAME "[program name]" !define CAPABILITIES_NAME "[program name]"
!define CAPABILITIES_DESCRIPTION "[description]" !define CAPABILITIES_DESCRIPTION "[description]"
!define CAPABILITIES_PROGID "[progid]" !define CAPABILITIES_PROGID "[progid]"
!define CAPABILITIES_PATH "[path]" !define CAPABILITIES_PATH "[path]"
... ...
During install, call ${RegisterCapabilities}, then use the other register During install, call ${RegisterCapabilities}, then use the other register
macros to create file type, MIME, and protocol associations. macros to create file type, MIME, and protocol associations.
During uninstall, call ${UnRegisterCapabilities} During uninstall, call ${UnRegisterCapabilities}
_______________________________________________________________________________ _______________________________________________________________________________
More information about Default Programs and Client Types can be found here: More information about Default Programs and Client Types can be found here:
http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx http://msdn.microsoft.com/en-us/library/cc144154(VS.85).aspx
http://msdn.microsoft.com/en-us/library/cc144109(v=VS.85).aspx http://msdn.microsoft.com/en-us/library/cc144109(v=VS.85).aspx
Defines: All defines not marked [optional] are required. Defines: All defines not marked [optional] are required.
CAPABILITIES_NAME CAPABILITIES_NAME
The canonical name of the program. The canonical name of the program.
CAPABILITIES_LOCAL_NAME [optional] CAPABILITIES_LOCAL_NAME [optional]
The localized name of the program as it appears in Default Programs. The localized name of the program as it appears in Default Programs.
This should be in the format "@FilePath,-StringID" where FilePath is the This should be in the format "@FilePath,-StringID" where FilePath is the
path to a .dll or .exe file and StringID is the ID of a resource contained path to a .dll or .exe file and StringID is the ID of a resource contained
in the file. in the file.
CAPABILITIES_DESCRIPTION CAPABILITIES_DESCRIPTION
The localized description shown in Default Programs. This can be either a The localized description shown in Default Programs. This can be either a
string or in the same format as CAPABILITIES_LOCAL_NAME string or in the same format as CAPABILITIES_LOCAL_NAME
CAPABILITIES_PROGID CAPABILITIES_PROGID
An identifier used in file associations. Usually, this is the name of the An identifier used in file associations. Usually, this is the name of the
program. This should not have any spaces in it. program. This should not have any spaces in it.
CAPABILITIES_PATH CAPABILITIES_PATH
The location where capabilities info is stored in the registry. The location where capabilities info is stored in the registry.
The "Capabilities" key will automatically be added. If the application is The "Capabilities" key will automatically be added. If the application is
a client of some sort, (browser, email, media player, etc.) use a client of some sort, (browser, email, media player, etc.) use
"Software\Clients\[ClientType]\[ProgramName]". Otherwise, use "Software\Clients\[ClientType]\[ProgramName]". Otherwise, use
"Software\[CompanyName]\[ProgramName]" or just "Software\[ProgramName]". "Software\[CompanyName]\[ProgramName]" or just "Software\[ProgramName]".
CAPABILITIES_ICON [optional] CAPABILITIES_ICON [optional]
The icon shown in Default Programs. This should be in the format The icon shown in Default Programs. This should be in the format
"FilePath,IconIndex" where FilePath is the path to a file containing the "FilePath,IconIndex" where FilePath is the path to a file containing the
icon. If IconIndex is positive, the number is used as the index of the icon. If IconIndex is positive, the number is used as the index of the
zero-based array of icons stored in the file. If IconIndex is negative, zero-based array of icons stored in the file. If IconIndex is negative,
the absolute value is used as a resource ID. the absolute value is used as a resource ID.
CAPABILITIES_REINSTALL [optional] CAPABILITIES_REINSTALL [optional]
The command executed when a user uses Set Program Access and Computer The command executed when a user uses Set Program Access and Computer
Defaults to select this application as the default for its client type. Defaults to select this application as the default for its client type.
This command should launch a program that associates the application with This command should launch a program that associates the application with
all the file and protocol types it can handle. all the file and protocol types it can handle.
CAPABILITIES_HIDE_ICONS [optional] CAPABILITIES_HIDE_ICONS [optional]
The command executed when a user uses Set Program Access and Computer The command executed when a user uses Set Program Access and Computer
Defaults to disable access to this application. This command should launch Defaults to disable access to this application. This command should launch
a program that hides all shortcuts and access points to this application. a program that hides all shortcuts and access points to this application.
It should also prevent the application from being run automatically and It should also prevent the application from being run automatically and
update the IconsVisible registry value to 0. update the IconsVisible registry value to 0.
CAPABILITIES_SHOW_ICONS [optional] CAPABILITIES_SHOW_ICONS [optional]
The command executed when a user uses Set Program Access and Computer The command executed when a user uses Set Program Access and Computer
Defaults to enable access to this application. This command should launch Defaults to enable access to this application. This command should launch
a program that restores shortcuts and access points to the application, a program that restores shortcuts and access points to the application,
allows the program to run, and updates the IconsVisible registry value to 1. allows the program to run, and updates the IconsVisible registry value to 1.
Macros: Macros:
${RegisterCapabilities} ${RegisterCapabilities}
Registers the program with Default Programs. Call this once on install Registers the program with Default Programs. Call this once on install
before using any other functions. before using any other functions.
${UnRegisterCapabilities} ${UnRegisterCapabilities}
Un-registers the program and all its associations. Call this once on Un-registers the program and all its associations. Call this once on
uninstall to clean up all installed registry values. uninstall to clean up all installed registry values.
${RegisterFileType} "[extension]" "[executable]" "[icon]" "[description]" ${RegisterFileType} "[extension]" "[executable]" "[icon]" "[description]"
Registers a file type with the program Registers a file type with the program
extension: The file extension to register (ex: .txt) extension: The file extension to register (ex: .txt)
executable: The executable that opens the file type executable: The executable that opens the file type
icon: The icon shown for the file type icon: The icon shown for the file type
description: Description for the file type shown in Explorer description: Description for the file type shown in Explorer
${RegisterMediaType} "[extension]" "[executable]" "[icon]" "[description]" ${RegisterMediaType} "[extension]" "[executable]" "[icon]" "[description]"
Registers a media file type with the program (has a "Play" command) Registers a media file type with the program (has a "Play" command)
(arguments are same as RegisterFileType) (arguments are same as RegisterFileType)
${RegisterMimeType} "[mime type]" "[shortname]" "[clsid]" ${RegisterMimeType} "[mime type]" "[shortname]" "[clsid]"
Registers a mime type with the program Registers a mime type with the program
mime type: The MIME type to register (ex: audio/mp3) mime type: The MIME type to register (ex: audio/mp3)
shortname: A short identifier for the type (ex: mp3) shortname: A short identifier for the type (ex: mp3)
clsid: The CLSID of the program to handle files of this type clsid: The CLSID of the program to handle files of this type
${RegisterProtocol} "[protocol]" "[executable]" "[icon]" "[description]" ${RegisterProtocol} "[protocol]" "[executable]" "[icon]" "[description]"
Registers a URL protocol with the program Registers a URL protocol with the program
protocol: The protocol to register (ex: http) protocol: The protocol to register (ex: http)
@@ -118,15 +118,15 @@ ${RegisterProtocol} "[protocol]" "[executable]" "[icon]" "[description]"
${UnRegisterFileType} "[extension]" ${UnRegisterFileType} "[extension]"
Un-registers a previously registered file type Un-registers a previously registered file type
extension: The file extension to un-register extension: The file extension to un-register
${UnRegisterMimeType} "[mime type]" ${UnRegisterMimeType} "[mime type]"
Un-registers a previously registered MEME type Un-registers a previously registered MEME type
mime type: The MIME type to un-register mime type: The MIME type to un-register
${UnRegisterProtocol} "[protocol]" ${UnRegisterProtocol} "[protocol]"
Un-registers a previously registered URL protocol Un-registers a previously registered URL protocol
protocol: The URL protocol to un-register protocol: The URL protocol to un-register
*/ */
@@ -254,7 +254,7 @@ ${StrCase}
!verbose push !verbose push
!verbose ${_Capabilities_VERBOSE} !verbose ${_Capabilities_VERBOSE}
Push $0 Push $0
!ifndef CAPABILITIES_PATH !ifndef CAPABILITIES_PATH
!error "CAPABILITIES_PATH not defined" !error "CAPABILITIES_PATH not defined"
!endif !endif
@@ -267,21 +267,21 @@ ${StrCase}
!ifndef CAPABILITIES_DESCRIPTION !ifndef CAPABILITIES_DESCRIPTION
!error "CAPABILITIES_DESCRIPTION not defined" !error "CAPABILITIES_DESCRIPTION not defined"
!endif !endif
StrCpy $0 "${CAPABILITIES_PATH}\Capabilities" StrCpy $0 "${CAPABILITIES_PATH}\Capabilities"
; add the application to RegisteredApplications ; add the application to RegisteredApplications
WriteRegStr HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}" "$0" WriteRegStr HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}" "$0"
; write application info ; write application info
WriteRegStr HKLM "${CAPABILITIES_PATH}" "" "${CAPABILITIES_NAME}" WriteRegStr HKLM "${CAPABILITIES_PATH}" "" "${CAPABILITIES_NAME}"
!ifdef CAPABILITIES_LOCAL_NAME !ifdef CAPABILITIES_LOCAL_NAME
WriteRegStr HKLM "${CAPABILITIES_PATH}" "LocalizedString" "${CAPABILITIES_LOCAL_NAME}" WriteRegStr HKLM "${CAPABILITIES_PATH}" "LocalizedString" "${CAPABILITIES_LOCAL_NAME}"
!endif !endif
!ifdef CAPABILITIES_ICON !ifdef CAPABILITIES_ICON
WriteRegStr HKLM "${CAPABILITIES_PATH}\DefaultIcon" "" "${CAPABILITIES_ICON}" WriteRegStr HKLM "${CAPABILITIES_PATH}\DefaultIcon" "" "${CAPABILITIES_ICON}"
!endif !endif
; write installinfo if defined ; write installinfo if defined
!ifdef CAPABILITIES_REINSTALL !ifdef CAPABILITIES_REINSTALL
WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ReinstallCommand" "${CAPABILITIES_REINSTALL}" WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ReinstallCommand" "${CAPABILITIES_REINSTALL}"
@@ -294,7 +294,7 @@ ${StrCase}
WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ShowIconsCommand" "${CAPABILITIES_SHOW_ICONS}" WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ShowIconsCommand" "${CAPABILITIES_SHOW_ICONS}"
WriteRegDWORD HKLM "${CAPABILITIES_PATH}\InstallInfo" "IconsVisible" 0x1 WriteRegDWORD HKLM "${CAPABILITIES_PATH}\InstallInfo" "IconsVisible" 0x1
!endif !endif
; write application capabilities info ; write application capabilities info
!ifdef CAPABILITIES_LOCAL_NAME !ifdef CAPABILITIES_LOCAL_NAME
WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_LOCAL_NAME}" WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_LOCAL_NAME}"
@@ -302,7 +302,7 @@ ${StrCase}
WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_NAME}" WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_NAME}"
!endif !endif
WriteRegStr HKLM "$0" "ApplicationDescription" "${CAPABILITIES_DESCRIPTION}" WriteRegStr HKLM "$0" "ApplicationDescription" "${CAPABILITIES_DESCRIPTION}"
Pop $0 Pop $0
!verbose pop !verbose pop
!macroend !macroend
@@ -322,7 +322,7 @@ ${StrCase}
!define MacroID ${__LINE__} !define MacroID ${__LINE__}
!verbose push !verbose push
!verbose ${_Capabilities_VERBOSE} !verbose ${_Capabilities_VERBOSE}
Push $0 Push $0
Push $1 Push $1
@@ -330,43 +330,43 @@ ${StrCase}
FileTypeLoop_${MacroID}: FileTypeLoop_${MacroID}:
EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" 0 EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" 0
StrCmp $0 "" FileTypeDone_${MacroID} StrCmp $0 "" FileTypeDone_${MacroID}
ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0" ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0"
DeleteRegKey HKCR $1 DeleteRegKey HKCR $1
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0"
Goto FileTypeLoop_${MacroID} Goto FileTypeLoop_${MacroID}
FileTypeDone_${MacroID}: FileTypeDone_${MacroID}:
; remove all MIME associations ; remove all MIME associations
MimeTypeLoop_${MacroID}: MimeTypeLoop_${MacroID}:
EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" 0 EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" 0
StrCmp $0 "" MimeTypeDone_${MacroID} StrCmp $0 "" MimeTypeDone_${MacroID}
ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0" ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0"
DeleteRegKey HKCR "$1" DeleteRegKey HKCR "$1"
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0"
Goto MimeTypeLoop_${MacroID} Goto MimeTypeLoop_${MacroID}
MimeTypeDone_${MacroID}: MimeTypeDone_${MacroID}:
; remove all protocol associations ; remove all protocol associations
ProtocolLoop_${MacroID}: ProtocolLoop_${MacroID}:
EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" 0 EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" 0
StrCmp $0 "" ProtocolDone_${MacroID} StrCmp $0 "" ProtocolDone_${MacroID}
ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0" ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0"
DeleteRegKey HKCR "$1" DeleteRegKey HKCR "$1"
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0"
Goto ProtocolLoop_${MacroID} Goto ProtocolLoop_${MacroID}
ProtocolDone_${MacroID}: ProtocolDone_${MacroID}:
; remove capabilities keys ; remove capabilities keys
DeleteRegValue HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}" DeleteRegValue HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}"
DeleteRegKey HKLM ${CAPABILITIES_PATH} DeleteRegKey HKLM ${CAPABILITIES_PATH}
Pop $1 Pop $1
Pop $0 Pop $0
!verbose pop !verbose pop
@@ -390,7 +390,7 @@ ${StrCase}
!macro RegisterFileType_ !macro RegisterFileType_
!verbose push !verbose push
!verbose ${_Capabilities_VERBOSE} !verbose ${_Capabilities_VERBOSE}
Exch $R3 ;ext Exch $R3 ;ext
Exch Exch
Exch $R2 ;exe Exch $R2 ;exe
@@ -405,10 +405,10 @@ ${StrCase}
; ex: .mp3 becomes ProgID.AssocFile.MP3 ; ex: .mp3 becomes ProgID.AssocFile.MP3
${StrCase} $0 "$R3" "U" ${StrCase} $0 "$R3" "U"
StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0" StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0"
; link capabilities to association in classes root ; link capabilities to association in classes root
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0" WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0"
; write file association in classes root ; write file association in classes root
WriteRegStr HKCR "$0" "" "$R0" WriteRegStr HKCR "$0" "" "$R0"
WriteRegStr HKCR "$0\DefaultIcon" "" "$R1" WriteRegStr HKCR "$0\DefaultIcon" "" "$R1"
@@ -441,7 +441,7 @@ ${StrCase}
!macro RegisterMediaType_ !macro RegisterMediaType_
!verbose push !verbose push
!verbose ${_Capabilities_VERBOSE} !verbose ${_Capabilities_VERBOSE}
Exch $R3 ;ext Exch $R3 ;ext
Exch Exch
Exch $R2 ;exe Exch $R2 ;exe
@@ -457,10 +457,10 @@ ${StrCase}
; ex: .mp3 becomes ProgID.AssocFile.MP3 ; ex: .mp3 becomes ProgID.AssocFile.MP3
${StrCase} $0 "$R3" "U" ${StrCase} $0 "$R3" "U"
StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0" StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0"
; link capabilities to association in classes root ; link capabilities to association in classes root
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0" WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0"
; write file association in classes root ; write file association in classes root
WriteRegStr HKCR "$0" "" "$R0" WriteRegStr HKCR "$0" "" "$R0"
WriteRegStr HKCR "$0\DefaultIcon" "" "$R1" WriteRegStr HKCR "$0\DefaultIcon" "" "$R1"
@@ -495,24 +495,24 @@ ${StrCase}
!macro RegisterMimeType_ !macro RegisterMimeType_
!verbose push !verbose push
!verbose ${_Capabilities_VERBOSE} !verbose ${_Capabilities_VERBOSE}
Exch $R2 ;mime Exch $R2 ;mime
Exch Exch
Exch $R1 ;shortname Exch $R1 ;shortname
Exch Exch
Exch 2 Exch 2
Exch $R0 ;clsid Exch $R0 ;clsid
Push $0 Push $0
; create an association name ; create an association name
; ex: audio/mp3 becomes ProgID.AssocMIME.MP3 ; ex: audio/mp3 becomes ProgID.AssocMIME.MP3
${StrCase} $0 "$R1" "U" ${StrCase} $0 "$R1" "U"
StrCpy $0 "${CAPABILITIES_PROGID}.AssocMIME.$0" StrCpy $0 "${CAPABILITIES_PROGID}.AssocMIME.$0"
; link capabilities to association in classes root ; link capabilities to association in classes root
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R2" "$0" WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R2" "$0"
; write file association in classes root ; write file association in classes root
WriteRegStr HKCR "$0\CLSID" "" "$R0" WriteRegStr HKCR "$0\CLSID" "" "$R0"
@@ -538,7 +538,7 @@ ${StrCase}
!macro RegisterProtocol_ !macro RegisterProtocol_
!verbose push !verbose push
!verbose ${_Capabilities_VERBOSE} !verbose ${_Capabilities_VERBOSE}
Exch $R3 ;protocol Exch $R3 ;protocol
Exch Exch
Exch $R2 ;exe Exch $R2 ;exe
@@ -554,10 +554,10 @@ ${StrCase}
; ex: http becomes ProgID.AssocProtocol.HTTP ; ex: http becomes ProgID.AssocProtocol.HTTP
${StrCase} $0 "$R3" "U" ${StrCase} $0 "$R3" "U"
StrCpy $0 "${CAPABILITIES_PROGID}.AssocProtocol.$0" StrCpy $0 "${CAPABILITIES_PROGID}.AssocProtocol.$0"
; link capabilities to association in classes root ; link capabilities to association in classes root
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R3" "$0" WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R3" "$0"
; write file association in classes root ; write file association in classes root
WriteRegStr HKCR "$0" "" "$R0" WriteRegStr HKCR "$0" "" "$R0"
WriteRegStr HKCR "$0\DefaultIcon" "" "$R1" WriteRegStr HKCR "$0\DefaultIcon" "" "$R1"
@@ -592,14 +592,14 @@ ${StrCase}
Exch $R0 ;ext Exch $R0 ;ext
Push $0 Push $0
ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0" ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0"
StrCmp $0 "" skip_${MacroID} StrCmp $0 "" skip_${MacroID}
DeleteRegKey HKCR "$0" DeleteRegKey HKCR "$0"
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0"
skip_${MacroID}: skip_${MacroID}:
Pop $0 Pop $0
Pop $R0 Pop $R0
!verbose pop !verbose pop
@@ -624,14 +624,14 @@ ${StrCase}
Exch $R0 ;mime Exch $R0 ;mime
Push $0 Push $0
ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0" ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0"
StrCmp $0 "" skip_${MacroID} StrCmp $0 "" skip_${MacroID}
DeleteRegKey HKCR "$0" DeleteRegKey HKCR "$0"
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0"
skip_${MacroID}: skip_${MacroID}:
Pop $0 Pop $0
Pop $R0 Pop $R0
!verbose pop !verbose pop
@@ -656,14 +656,14 @@ ${StrCase}
Exch $R0 ;protocol Exch $R0 ;protocol
Push $0 Push $0
ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0" ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0"
StrCmp $0 "" skip_${MacroID} StrCmp $0 "" skip_${MacroID}
DeleteRegKey HKCR "$0" DeleteRegKey HKCR "$0"
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0" DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0"
skip_${MacroID}: skip_${MacroID}:
Pop $0 Pop $0
Pop $R0 Pop $R0
!verbose pop !verbose pop

447
dist/windows/strawberry-64.nsi.in vendored Normal file
View File

@@ -0,0 +1,447 @@
!define PRODUCT_NAME "Strawberry"
!define PRODUCT_PUBLISHER "Strawberry"
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
; Set Application Capabilities info
!define CAPABILITIES_NAME "Strawberry Music Player"
!define CAPABILITIES_LOCAL_NAME "Strawberry"
!define CAPABILITIES_PROGID "Strawberry Music Player"
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
!define CAPABILITIES_REINSTALL "Command to reinstall"
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
SetCompressor /SOLID lzma
!addplugindir nsisplugins
!include "MUI2.nsh"
!include "FileAssociation.nsh"
!include "Capabilities.nsh"
!define MUI_ICON "strawberry.ico"
!define MUI_COMPONENTSPAGE_SMALLDESC
;!define MUI_FINISHPAGE_RUN
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
; Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
; Uninstaller pages
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
Name "${PRODUCT_NAME}"
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Release-x64.exe"
InstallDir "${PRODUCT_INSTALL_DIR}"
; Get the path where Strawberry was installed previously and set it as default path
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
ShowInstDetails show
ShowUnInstDetails show
RequestExecutionLevel admin
;RequestExecutionLevel user
; Check for previous installation, and call the uninstaller if any
Function CheckPreviousInstall
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
StrCmp $R0 "" done
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
previous version or `Cancel` to cancel this upgrade." \
IDOK uninst
Abort
; Run the uninstaller
uninst:
ClearErrors
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
done:
FunctionEnd
Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY
Call CheckPreviousInstall
FunctionEnd
;Function RunStrawberry
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
;FunctionEnd
Section "Delete old files" oldfiles
SectionEnd
Section "Strawberry" Strawberry
SetOutPath "$INSTDIR"
File "strawberry.exe"
File "strawberry-tagreader.exe"
File "strawberry.ico"
File "libbz2.dll"
File "libcdio-18.dll"
File "libchromaprint.dll"
File "libcrypto-1_1-x64.dll"
File "libfaad-2.dll"
File "libffi-6.dll"
File "libFLAC-8.dll"
File "libfreetype-6.dll"
File "libgcc_s_seh-1.dll"
File "libgio-2.0-0.dll"
File "libglib-2.0-0.dll"
File "libgmodule-2.0-0.dll"
File "libgobject-2.0-0.dll"
File "libgstapp-1.0-0.dll"
File "libgstaudio-1.0-0.dll"
File "libgstbase-1.0-0.dll"
File "libgstfft-1.0-0.dll"
File "libgstpbutils-1.0-0.dll"
File "libgstreamer-1.0-0.dll"
File "libgstriff-1.0-0.dll"
File "libgstrtp-1.0-0.dll"
File "libgstrtsp-1.0-0.dll"
File "libgstsdp-1.0-0.dll"
File "libgsttag-1.0-0.dll"
File "libgstvideo-1.0-0.dll"
File "libgstnet-1.0-0.dll"
File "libharfbuzz-0.dll"
File "libiconv-2.dll"
File "libintl-8.dll"
File "libjpeg-9.dll"
File "liblastfm5.dll"
File "libmp3lame-0.dll"
File "libogg-0.dll"
File "libopus-0.dll"
File "libpcre-1.dll"
File "libpcre2-16-0.dll"
File "libpng16-16.dll"
File "libprotobuf-15.dll"
File "libspeex-1.dll"
File "libsqlite3-0.dll"
File "libssl-1_1-x64.dll"
File "libstdc++-6.dll"
File "libtag.dll"
File "libvorbis-0.dll"
File "libvorbisenc-2.dll"
File "libwavpack-1.dll"
File "libwinpthread-1.dll"
File "Qt5Concurrent.dll"
File "Qt5Core.dll"
File "Qt5Gui.dll"
File "Qt5Network.dll"
File "Qt5Sql.dll"
File "Qt5Widgets.dll"
File "Qt5Xml.dll"
File "Qt5WinExtras.dll"
File "zlib1.dll"
;File "libmpcdec-5.dll"
;File "libtheora-0.dll"
File "libfftw3-3.dll"
File "libxml2-2.dll"
File "libsoup-2.4-1.dll"
File "liblzma-5.dll"
File "libdeezer.x64.dll"
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
Var /GLOBAL AppExe
StrCpy $AppExe "$INSTDIR\strawberry.exe"
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
${RegisterCapabilities}
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
SectionEnd
Section "Qt Platforms" platforms
SetOutPath "$INSTDIR\platforms"
File "/oname=qwindows.dll" "platforms\qwindows.dll"
SectionEnd
Section "Qt SQL Drivers" sqldrivers
SetOutPath "$INSTDIR\sqldrivers"
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
SectionEnd
Section "Qt image format plugins" imageformats
SetOutPath "$INSTDIR\imageformats"
File "/oname=qgif.dll" "imageformats\qgif.dll"
File "/oname=qico.dll" "imageformats\qico.dll"
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
SectionEnd
Section "Gstreamer plugins" gstreamer-plugins
SetOutPath "$INSTDIR\gstreamer-plugins"
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
SectionEnd
Section "Start menu items" startmenu
; Create Start Menu folders and shortcuts.
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
SectionEnd
Section "Uninstaller"
; Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
Section "Uninstall"
; Kill strawberry.exe if it's running
; This calling convention is retarded...
;StrCpy $0 "strawberry.exe"
;KillProc::FindProcesses
;StrCmp $1 "-1" wooops
;StrCmp $0 "0" completed
;DetailPrint "Killing running strawberry.exe..."
;StrCpy $0 "strawberry.exe"
;KillProc::KillProcesses
;StrCmp $1 "-1" wooops
;Sleep 2000
;Goto completed
;wooops:
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
;Abort
;completed:
; Delete all the files
Delete "$INSTDIR\strawberry.ico"
Delete "$INSTDIR\strawberry.exe"
Delete "$INSTDIR\strawberry-tagreader.exe"
Delete "$INSTDIR\libbz2.dll"
Delete "$INSTDIR\libcdio-18.dll"
Delete "$INSTDIR\libchromaprint.dll"
Delete "$INSTDIR\libcrypto-1_1-x64.dll"
Delete "$INSTDIR\libfaad-2.dll"
Delete "$INSTDIR\libffi-6.dll"
Delete "$INSTDIR\libFLAC-8.dll"
Delete "$INSTDIR\libfreetype-6.dll"
Delete "$INSTDIR\libgcc_s_seh-1.dll"
Delete "$INSTDIR\libgio-2.0-0.dll"
Delete "$INSTDIR\libglib-2.0-0.dll"
Delete "$INSTDIR\libgmodule-2.0-0.dll"
Delete "$INSTDIR\libgobject-2.0-0.dll"
Delete "$INSTDIR\libgstapp-1.0-0.dll"
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
Delete "$INSTDIR\libgstbase-1.0-0.dll"
Delete "$INSTDIR\libgstfft-1.0-0.dll"
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
Delete "$INSTDIR\libgstriff-1.0-0.dll"
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
Delete "$INSTDIR\libgsttag-1.0-0.dll"
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
Delete "$INSTDIR\libgstnet-1.0-0.dll"
Delete "$INSTDIR\libharfbuzz-0.dll"
Delete "$INSTDIR\libiconv-2.dll"
Delete "$INSTDIR\libintl-8.dll"
Delete "$INSTDIR\libjpeg-9.dll"
Delete "$INSTDIR\liblastfm5.dll"
Delete "$INSTDIR\libmp3lame-0.dll"
Delete "$INSTDIR\libogg-0.dll"
Delete "$INSTDIR\libopus-0.dll"
Delete "$INSTDIR\libpcre-1.dll"
Delete "$INSTDIR\libpcre2-16-0.dll"
Delete "$INSTDIR\libpng16-16.dll"
Delete "$INSTDIR\libprotobuf-15.dll"
Delete "$INSTDIR\libspeex-1.dll"
Delete "$INSTDIR\libsqlite3-0.dll"
Delete "$INSTDIR\libssl-1_1-x64.dll"
Delete "$INSTDIR\libstdc++-6.dll"
Delete "$INSTDIR\libtag.dll"
Delete "$INSTDIR\libvorbis-0.dll"
Delete "$INSTDIR\libvorbisenc-2.dll"
Delete "$INSTDIR\libwavpack-1.dll"
Delete "$INSTDIR\libwinpthread-1.dll"
Delete "$INSTDIR\Qt5Concurrent.dll"
Delete "$INSTDIR\Qt5Core.dll"
Delete "$INSTDIR\Qt5Gui.dll"
Delete "$INSTDIR\Qt5Network.dll"
Delete "$INSTDIR\Qt5Sql.dll"
Delete "$INSTDIR\Qt5Widgets.dll"
Delete "$INSTDIR\Qt5Xml.dll"
Delete "$INSTDIR\Qt5WinExtras.dll"
Delete "$INSTDIR\zlib1.dll"
;Delete "$INSTDIR\libmpcdec-5.dll"
;Delete "$INSTDIR\libtheora-0.dll"
Delete "$INSTDIR\libfftw3-3.dll"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x64.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
Delete "$INSTDIR\imageformats\qgif.dll"
Delete "$INSTDIR\imageformats\qico.dll"
Delete "$INSTDIR\imageformats\qjpeg.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
Delete "$INSTDIR\Uninstall.exe"
; Remove the installation folders.
RMDir "$INSTDIR\platforms"
RMDir "$INSTDIR\sqldrivers"
RMDir "$INSTDIR\imageformats"
RMDir "$INSTDIR\gstreamer-plugins"
RMDir "$INSTDIR\xine-plugins"
RMDir "$INSTDIR"
; Remove the Shortcuts
SetShellVarContext all
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
; Remove the entry from 'installed programs list'
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
; Unregister from Default Programs
${UnRegisterCapabilities}
SectionEnd

507
dist/windows/strawberry-debug-64.nsi.in vendored Normal file
View File

@@ -0,0 +1,507 @@
!define PRODUCT_NAME "Strawberry"
!define PRODUCT_PUBLISHER "Strawberry"
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
; Set Application Capabilities info
!define CAPABILITIES_NAME "Strawberry Music Player"
!define CAPABILITIES_LOCAL_NAME "Strawberry"
!define CAPABILITIES_PROGID "Strawberry Music Player"
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
!define CAPABILITIES_REINSTALL "Command to reinstall"
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
SetCompressor /SOLID lzma
!addplugindir nsisplugins
!include "MUI2.nsh"
!include "FileAssociation.nsh"
!include "Capabilities.nsh"
!define MUI_ICON "strawberry.ico"
!define MUI_COMPONENTSPAGE_SMALLDESC
;!define MUI_FINISHPAGE_RUN
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
; Installer pages
!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH
; Uninstaller pages
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
Name "${PRODUCT_NAME}"
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
InstallDir "${PRODUCT_INSTALL_DIR}"
; Get the path where Strawberry was installed previously and set it as default path
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
ShowInstDetails show
ShowUnInstDetails show
RequestExecutionLevel admin
;RequestExecutionLevel user
; Check for previous installation, and call the uninstaller if any
Function CheckPreviousInstall
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
StrCmp $R0 "" done
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
previous version or `Cancel` to cancel this upgrade." \
IDOK uninst
Abort
; Run the uninstaller
uninst:
ClearErrors
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
done:
FunctionEnd
Function .onInit
!insertmacro MUI_LANGDLL_DISPLAY
Call CheckPreviousInstall
FunctionEnd
;Function RunStrawberry
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
;FunctionEnd
Section "Delete old files" oldfiles
SectionEnd
Section "Strawberry" Strawberry
SetOutPath "$INSTDIR"
File "strawberry.exe"
File "strawberry-tagreader.exe"
File "strawberry.ico"
File "libbz2.dll"
File "libcdio-18.dll"
File "libchromaprint.dll"
File "libcrypto-1_1-x64.dll"
File "libfaad-2.dll"
File "libffi-6.dll"
File "libFLAC-8.dll"
File "libfreetype-6.dll"
File "libgcc_s_seh-1.dll"
File "libgio-2.0-0.dll"
File "libglib-2.0-0.dll"
File "libgmodule-2.0-0.dll"
File "libgobject-2.0-0.dll"
File "libgstapp-1.0-0.dll"
File "libgstaudio-1.0-0.dll"
File "libgstbase-1.0-0.dll"
File "libgstfft-1.0-0.dll"
File "libgstpbutils-1.0-0.dll"
File "libgstreamer-1.0-0.dll"
File "libgstriff-1.0-0.dll"
File "libgstrtp-1.0-0.dll"
File "libgstrtsp-1.0-0.dll"
File "libgstsdp-1.0-0.dll"
File "libgsttag-1.0-0.dll"
File "libgstvideo-1.0-0.dll"
File "libgstnet-1.0-0.dll"
File "libharfbuzz-0.dll"
File "libiconv-2.dll"
File "libintl-8.dll"
File "libjpeg-9.dll"
File "liblastfm5.dll"
File "libmp3lame-0.dll"
File "libogg-0.dll"
File "libopus-0.dll"
File "libpcre-1.dll"
File "libpcre2-16-0.dll"
File "libpng16-16.dll"
File "libprotobuf-15.dll"
File "libspeex-1.dll"
File "libsqlite3-0.dll"
File "libssl-1_1-x64.dll"
File "libstdc++-6.dll"
File "libtag.dll"
File "libvorbis-0.dll"
File "libvorbisenc-2.dll"
File "libwavpack-1.dll"
File "libwinpthread-1.dll"
File "Qt5Concurrent.dll"
File "Qt5Core.dll"
File "Qt5Gui.dll"
File "Qt5Network.dll"
File "Qt5Sql.dll"
File "Qt5Widgets.dll"
File "Qt5Xml.dll"
File "Qt5WinExtras.dll"
File "zlib1.dll"
File "libxine-2.dll"
File "libmpcdec-5.dll"
File "libtheora-0.dll"
File "libfftw3-3.dll"
File "libxml2-2.dll"
File "libsoup-2.4-1.dll"
File "liblzma-5.dll"
File "libdeezer.x64.dll"
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
Var /GLOBAL AppExe
StrCpy $AppExe "$INSTDIR\strawberry.exe"
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
${RegisterCapabilities}
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
SectionEnd
Section "Qt Platforms" platforms
SetOutPath "$INSTDIR\platforms"
File "/oname=qwindows.dll" "platforms\qwindows.dll"
SectionEnd
Section "Qt SQL Drivers" sqldrivers
SetOutPath "$INSTDIR\sqldrivers"
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
SectionEnd
Section "Qt image format plugins" imageformats
SetOutPath "$INSTDIR\imageformats"
File "/oname=qgif.dll" "imageformats\qgif.dll"
File "/oname=qico.dll" "imageformats\qico.dll"
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
SectionEnd
Section "Gstreamer plugins" gstreamer-plugins
SetOutPath "$INSTDIR\gstreamer-plugins"
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
SectionEnd
Section "Xine plugins" xine-plugins
SetOutPath "$INSTDIR\xine-plugins"
File "/oname=xineplug_ao_out_directx2.dll" "xine-plugins\xineplug_ao_out_directx2.dll"
File "/oname=xineplug_ao_out_directx.dll" "xine-plugins\xineplug_ao_out_directx.dll"
File "/oname=xineplug_decode_dts.dll" "xine-plugins\xineplug_decode_dts.dll"
File "/oname=xineplug_decode_dvaudio.dll" "xine-plugins\xineplug_decode_dvaudio.dll"
File "/oname=xineplug_decode_faad.dll" "xine-plugins\xineplug_decode_faad.dll"
File "/oname=xineplug_decode_gsm610.dll" "xine-plugins\xineplug_decode_gsm610.dll"
File "/oname=xineplug_decode_lpcm.dll" "xine-plugins\xineplug_decode_lpcm.dll"
File "/oname=xineplug_decode_mad.dll" "xine-plugins\xineplug_decode_mad.dll"
File "/oname=xineplug_decode_mpc.dll" "xine-plugins\xineplug_decode_mpc.dll"
File "/oname=xineplug_decode_mpeg2.dll" "xine-plugins\xineplug_decode_mpeg2.dll"
File "/oname=xineplug_dmx_asf.dll" "xine-plugins\xineplug_dmx_asf.dll"
File "/oname=xineplug_dmx_audio.dll" "xine-plugins\xineplug_dmx_audio.dll"
File "/oname=xineplug_dmx_playlist.dll" "xine-plugins\xineplug_dmx_playlist.dll"
File "/oname=xineplug_dmx_slave.dll" "xine-plugins\xineplug_dmx_slave.dll"
File "/oname=xineplug_flac.dll" "xine-plugins\xineplug_flac.dll"
File "/oname=xineplug_wavpack.dll" "xine-plugins\xineplug_wavpack.dll"
File "/oname=xineplug_xiph.dll" "xine-plugins\xineplug_xiph.dll"
File "/oname=xineplug_inp_cdda.dll" "xine-plugins\xineplug_inp_cdda.dll"
File "/oname=xineplug_post_audio_filters.dll" "xine-plugins\xineplug_post_audio_filters.dll"
File "/oname=xineplug_post_goom.dll" "xine-plugins\xineplug_post_goom.dll"
File "/oname=xineplug_post_mosaico.dll" "xine-plugins\xineplug_post_mosaico.dll"
File "/oname=xineplug_post_planar.dll" "xine-plugins\xineplug_post_planar.dll"
File "/oname=xineplug_post_switch.dll" "xine-plugins\xineplug_post_switch.dll"
File "/oname=xineplug_post_tvtime.dll" "xine-plugins\xineplug_post_tvtime.dll"
File "/oname=xineplug_post_visualizations.dll" "xine-plugins\xineplug_post_visualizations.dll"
SectionEnd
Section "Start menu items" startmenu
; Create Start Menu folders and shortcuts.
SetShellVarContext all
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
SectionEnd
Section "Uninstaller"
; Create uninstaller
WriteUninstaller "$INSTDIR\Uninstall.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
SectionEnd
Section "Uninstall"
; Kill strawberry.exe if it's running
; This calling convention is retarded...
;StrCpy $0 "strawberry.exe"
;KillProc::FindProcesses
;StrCmp $1 "-1" wooops
;StrCmp $0 "0" completed
;DetailPrint "Killing running strawberry.exe..."
;StrCpy $0 "strawberry.exe"
;KillProc::KillProcesses
;StrCmp $1 "-1" wooops
;Sleep 2000
;Goto completed
;wooops:
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
;Abort
;completed:
; Delete all the files
Delete "$INSTDIR\strawberry.ico"
Delete "$INSTDIR\strawberry.exe"
Delete "$INSTDIR\strawberry-tagreader.exe"
Delete "$INSTDIR\libbz2.dll"
Delete "$INSTDIR\libcdio-18.dll"
Delete "$INSTDIR\libchromaprint.dll"
Delete "$INSTDIR\libcrypto-1_1-x64.dll"
Delete "$INSTDIR\libfaad-2.dll"
Delete "$INSTDIR\libffi-6.dll"
Delete "$INSTDIR\libFLAC-8.dll"
Delete "$INSTDIR\libfreetype-6.dll"
Delete "$INSTDIR\libgcc_s_seh-1.dll"
Delete "$INSTDIR\libgio-2.0-0.dll"
Delete "$INSTDIR\libglib-2.0-0.dll"
Delete "$INSTDIR\libgmodule-2.0-0.dll"
Delete "$INSTDIR\libgobject-2.0-0.dll"
Delete "$INSTDIR\libgstapp-1.0-0.dll"
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
Delete "$INSTDIR\libgstbase-1.0-0.dll"
Delete "$INSTDIR\libgstfft-1.0-0.dll"
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
Delete "$INSTDIR\libgstriff-1.0-0.dll"
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
Delete "$INSTDIR\libgsttag-1.0-0.dll"
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
Delete "$INSTDIR\libgstnet-1.0-0.dll"
Delete "$INSTDIR\libharfbuzz-0.dll"
Delete "$INSTDIR\libiconv-2.dll"
Delete "$INSTDIR\libintl-8.dll"
Delete "$INSTDIR\libjpeg-9.dll"
Delete "$INSTDIR\liblastfm5.dll"
Delete "$INSTDIR\libmp3lame-0.dll"
Delete "$INSTDIR\libogg-0.dll"
Delete "$INSTDIR\libopus-0.dll"
Delete "$INSTDIR\libpcre-1.dll"
Delete "$INSTDIR\libpcre2-16-0.dll"
Delete "$INSTDIR\libpng16-16.dll"
Delete "$INSTDIR\libprotobuf-15.dll"
Delete "$INSTDIR\libspeex-1.dll"
Delete "$INSTDIR\libsqlite3-0.dll"
Delete "$INSTDIR\libssl-1_1-x64.dll"
Delete "$INSTDIR\libstdc++-6.dll"
Delete "$INSTDIR\libtag.dll"
Delete "$INSTDIR\libvorbis-0.dll"
Delete "$INSTDIR\libvorbisenc-2.dll"
Delete "$INSTDIR\libwavpack-1.dll"
Delete "$INSTDIR\libwinpthread-1.dll"
Delete "$INSTDIR\Qt5Concurrent.dll"
Delete "$INSTDIR\Qt5Core.dll"
Delete "$INSTDIR\Qt5Gui.dll"
Delete "$INSTDIR\Qt5Network.dll"
Delete "$INSTDIR\Qt5Sql.dll"
Delete "$INSTDIR\Qt5Widgets.dll"
Delete "$INSTDIR\Qt5Xml.dll"
Delete "$INSTDIR\Qt5WinExtras.dll"
Delete "$INSTDIR\zlib1.dll"
Delete "$INSTDIR\libxine-2.dll"
Delete "$INSTDIR\libmpcdec-5.dll"
Delete "$INSTDIR\libtheora-0.dll"
Delete "$INSTDIR\libfftw3-3.dll"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x64.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
Delete "$INSTDIR\imageformats\qgif.dll"
Delete "$INSTDIR\imageformats\qico.dll"
Delete "$INSTDIR\imageformats\qjpeg.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx2.dll"
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_dts.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_dvaudio.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_faad.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_gsm610.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_lpcm.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_mad.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpc.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpeg2.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_asf.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_audio.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_playlist.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_slave.dll"
Delete "$INSTDIR\xine-plugins\xineplug_flac.dll"
Delete "$INSTDIR\xine-plugins\xineplug_wavpack.dll"
Delete "$INSTDIR\xine-plugins\xineplug_xiph.dll"
Delete "$INSTDIR\xine-plugins\xineplug_inp_cdda.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_audio_filters.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_goom.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_mosaico.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_planar.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_switch.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_tvtime.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_visualizations.dll"
Delete "$INSTDIR\Uninstall.exe"
; Remove the installation folders.
RMDir "$INSTDIR\platforms"
RMDir "$INSTDIR\sqldrivers"
RMDir "$INSTDIR\imageformats"
RMDir "$INSTDIR\gstreamer-plugins"
RMDir "$INSTDIR\xine-plugins"
RMDir "$INSTDIR"
; Remove the Shortcuts
SetShellVarContext all
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
; Remove the entry from 'installed programs list'
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
; Unregister from Default Programs
${UnRegisterCapabilities}
SectionEnd

View File

@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
File "strawberry.ico" File "strawberry.ico"
File "libbz2.dll" File "libbz2.dll"
File "libcdio-16.dll" File "libcdio-18.dll"
File "libchromaprint.dll" File "libchromaprint.dll"
File "libcrypto-1_1.dll" File "libcrypto-1_1.dll"
File "libfaad-2.dll" File "libfaad-2.dll"
@@ -164,6 +164,7 @@ Section "Strawberry" Strawberry
File "libxml2-2.dll" File "libxml2-2.dll"
File "libsoup-2.4-1.dll" File "libsoup-2.4-1.dll"
File "liblzma-5.dll" File "liblzma-5.dll"
File "libdeezer.x86.dll"
; Register Strawberry with Default Programs ; Register Strawberry with Default Programs
Var /GLOBAL AppIcon Var /GLOBAL AppIcon
@@ -295,7 +296,7 @@ Section "Start menu items" startmenu
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
SectionEnd SectionEnd
Section "Uninstaller" Section "Uninstaller"
@@ -321,7 +322,7 @@ Section "Uninstall"
;StrCmp $1 "-1" wooops ;StrCmp $1 "-1" wooops
;StrCmp $0 "0" completed ;StrCmp $0 "0" completed
;DetailPrint "Killing running strawberry.exe..." ;DetailPrint "Killing running strawberry.exe..."
;StrCpy $0 "strawberry.exe" ;StrCpy $0 "strawberry.exe"
@@ -344,7 +345,7 @@ Section "Uninstall"
Delete "$INSTDIR\strawberry-tagreader.exe" Delete "$INSTDIR\strawberry-tagreader.exe"
Delete "$INSTDIR\libbz2.dll" Delete "$INSTDIR\libbz2.dll"
Delete "$INSTDIR\libcdio-16.dll" Delete "$INSTDIR\libcdio-18.dll"
Delete "$INSTDIR\libchromaprint.dll" Delete "$INSTDIR\libchromaprint.dll"
Delete "$INSTDIR\libcrypto-1_1.dll" Delete "$INSTDIR\libcrypto-1_1.dll"
Delete "$INSTDIR\libfaad-2.dll" Delete "$INSTDIR\libfaad-2.dll"
@@ -406,6 +407,7 @@ Section "Uninstall"
Delete "$INSTDIR\libxml2-2.dll" Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll" Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll" Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x86.dll"
Delete "$INSTDIR\platforms\qwindows.dll" Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll" Delete "$INSTDIR\sqldrivers\qsqlite.dll"

View File

@@ -48,7 +48,7 @@ SetCompressor /SOLID lzma
!insertmacro MUI_LANGUAGE "English" ;first language is the default language !insertmacro MUI_LANGUAGE "English" ;first language is the default language
Name "${PRODUCT_NAME}" Name "${PRODUCT_NAME}"
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}.exe" OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Release.exe"
InstallDir "${PRODUCT_INSTALL_DIR}" InstallDir "${PRODUCT_INSTALL_DIR}"
; Get the path where Strawberry was installed previously and set it as default path ; Get the path where Strawberry was installed previously and set it as default path
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
File "strawberry.ico" File "strawberry.ico"
File "libbz2.dll" File "libbz2.dll"
File "libcdio-16.dll" File "libcdio-18.dll"
File "libchromaprint.dll" File "libchromaprint.dll"
File "libcrypto-1_1.dll" File "libcrypto-1_1.dll"
File "libfaad-2.dll" File "libfaad-2.dll"
@@ -163,6 +163,7 @@ Section "Strawberry" Strawberry
File "libxml2-2.dll" File "libxml2-2.dll"
File "libsoup-2.4-1.dll" File "libsoup-2.4-1.dll"
File "liblzma-5.dll" File "liblzma-5.dll"
File "libdeezer.x86.dll"
; Register Strawberry with Default Programs ; Register Strawberry with Default Programs
Var /GLOBAL AppIcon Var /GLOBAL AppIcon
@@ -263,7 +264,7 @@ Section "Start menu items" startmenu
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}" CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe" CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
SectionEnd SectionEnd
Section "Uninstaller" Section "Uninstaller"
@@ -289,7 +290,7 @@ Section "Uninstall"
;StrCmp $1 "-1" wooops ;StrCmp $1 "-1" wooops
;StrCmp $0 "0" completed ;StrCmp $0 "0" completed
;DetailPrint "Killing running strawberry.exe..." ;DetailPrint "Killing running strawberry.exe..."
;StrCpy $0 "strawberry.exe" ;StrCpy $0 "strawberry.exe"
@@ -312,7 +313,7 @@ Section "Uninstall"
Delete "$INSTDIR\strawberry-tagreader.exe" Delete "$INSTDIR\strawberry-tagreader.exe"
Delete "$INSTDIR\libbz2.dll" Delete "$INSTDIR\libbz2.dll"
Delete "$INSTDIR\libcdio-16.dll" Delete "$INSTDIR\libcdio-18.dll"
Delete "$INSTDIR\libchromaprint.dll" Delete "$INSTDIR\libchromaprint.dll"
Delete "$INSTDIR\libcrypto-1_1.dll" Delete "$INSTDIR\libcrypto-1_1.dll"
Delete "$INSTDIR\libfaad-2.dll" Delete "$INSTDIR\libfaad-2.dll"
@@ -373,6 +374,7 @@ Section "Uninstall"
Delete "$INSTDIR\libxml2-2.dll" Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll" Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\liblzma-5.dll" Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libdeezer.x86.dll"
Delete "$INSTDIR\platforms\qwindows.dll" Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll" Delete "$INSTDIR\sqldrivers\qsqlite.dll"

View File

@@ -64,7 +64,7 @@ void GLog(const char *domain, int level, const char *message, void *user_data) {
case G_LOG_LEVEL_DEBUG: case G_LOG_LEVEL_DEBUG:
default: qLog(Debug) << message; break; default: qLog(Debug) << message; break;
} }
} }
static void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) { static void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) {
@@ -93,7 +93,7 @@ static void MessageHandler(QtMsgType type, const QMessageLogContext &context, co
} }
void Init() { void Init() {
delete sClassLevels; delete sClassLevels;
delete sNullDevice; delete sNullDevice;
@@ -263,7 +263,6 @@ void DumpStackTrace() {
#endif #endif
} }
#if 0
QDebug CreateLoggerFatal(int line, const char *class_name) { return qCreateLogger(line, class_name, Fatal); } QDebug CreateLoggerFatal(int line, const char *class_name) { return qCreateLogger(line, class_name, Fatal); }
QDebug CreateLoggerError(int line, const char *class_name) { return qCreateLogger(line, class_name, Error); } QDebug CreateLoggerError(int line, const char *class_name) { return qCreateLogger(line, class_name, Error); }
@@ -280,7 +279,6 @@ QNoDebug CreateLoggerDebug(int, const char*) { return QNoDebug(); }
QDebug CreateLoggerInfo(int line, const char *class_name) { return qCreateLogger(line, class_name, Info); } QDebug CreateLoggerInfo(int line, const char *class_name) { return qCreateLogger(line, class_name, Info); }
QDebug CreateLoggerDebug(int line, const char *class_name) { return qCreateLogger(line, class_name, Debug); } QDebug CreateLoggerDebug(int line, const char *class_name) { return qCreateLogger(line, class_name, Debug); }
#endif // QT_NO_DEBUG_OUTPUT #endif // QT_NO_DEBUG_OUTPUT
#endif
} // namespace logging } // namespace logging

View File

@@ -27,22 +27,11 @@
#ifdef QT_NO_DEBUG_STREAM #ifdef QT_NO_DEBUG_STREAM
# define qLog(level) while (false) QNoDebug() # define qLog(level) while (false) QNoDebug()
#else #else
#define qLog(level) \ #define qLog(level) logging::CreateLogger##level(__LINE__, __PRETTY_FUNCTION__)
logging::CreateLogger(logging::Level_##level, \
logging::ParsePrettyFunction(__PRETTY_FUNCTION__), \ #define qCreateLogger(line, class_name, level) logging::CreateLogger(logging::Level_##level, logging::ParsePrettyFunction(class_name), line)
__LINE__)
#endif // QT_NO_DEBUG_STREAM #endif // QT_NO_DEBUG_STREAM
#if 0
#define qLog(level) \
logging::CreateLogger##level(__LINE__, __PRETTY_FUNCTION__)
#define qCreateLogger(line, class_name, level) \
logging::CreateLogger(logging::Level_##level, \
logging::ParsePrettyFunction(class_name), \
line)
#endif
namespace logging { namespace logging {
class NullDevice : public QIODevice { class NullDevice : public QIODevice {
protected: protected:

View File

@@ -43,7 +43,7 @@
#include <taglib/tag.h> #include <taglib/tag.h>
#include <taglib/apetag.h> #include <taglib/apetag.h>
#include <taglib/id3v2tag.h> #include <taglib/id3v2tag.h>
#include "taglib/id3v2frame.h" #include <taglib/id3v2frame.h>
#include <taglib/flacfile.h> #include <taglib/flacfile.h>
#include <taglib/oggflacfile.h> #include <taglib/oggflacfile.h>
#include <taglib/flacproperties.h> #include <taglib/flacproperties.h>
@@ -54,12 +54,12 @@
#include <taglib/wavpackfile.h> #include <taglib/wavpackfile.h>
#include <taglib/aifffile.h> #include <taglib/aifffile.h>
#include <taglib/asffile.h> #include <taglib/asffile.h>
#include "taglib/asftag.h" #include <taglib/asftag.h>
#include "taglib/asfattribute.h" #include <taglib/asfattribute.h>
#include "taglib/asfproperties.h" #include <taglib/asfproperties.h>
#include <taglib/mp4file.h> #include <taglib/mp4file.h>
#include <taglib/mp4tag.h> #include <taglib/mp4tag.h>
#include "taglib/mp4item.h" #include <taglib/mp4item.h>
#include <taglib/mp4coverart.h> #include <taglib/mp4coverart.h>
#include <taglib/mp4properties.h> #include <taglib/mp4properties.h>
#include <taglib/mpcfile.h> #include <taglib/mpcfile.h>
@@ -269,7 +269,7 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) { else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
song->set_bitdepth(file->audioProperties()->bitsPerSample()); song->set_bitdepth(file->audioProperties()->bitsPerSample());
if (file->tag()) { if (file->tag()) {
TagLib::MP4::Tag *mp4_tag = file->tag(); TagLib::MP4::Tag *mp4_tag = file->tag();
const TagLib::MP4::ItemListMap& items = mp4_tag->itemListMap(); const TagLib::MP4::ItemListMap& items = mp4_tag->itemListMap();
@@ -387,7 +387,7 @@ void TagReader::Decode(const TagLib::String &tag, const QTextCodec *codec, std::
} }
void TagReader::Decode(const QString &tag, const QTextCodec *codec, std::string *output) { void TagReader::Decode(const QString &tag, const QTextCodec *codec, std::string *output) {
if (!codec) { if (!codec) {
output->assign(DataCommaSizeFromQString(tag)); output->assign(DataCommaSizeFromQString(tag));
} }
@@ -399,10 +399,10 @@ void TagReader::Decode(const QString &tag, const QTextCodec *codec, std::string
} }
void TagReader::ParseFMPSFrame(const QString &name, const QString &value, pb::tagreader::SongMetadata *song) const { void TagReader::ParseFMPSFrame(const QString &name, const QString &value, pb::tagreader::SongMetadata *song) const {
qLog(Debug) << "Parsing FMPSFrame" << name << ", " << value; qLog(Debug) << "Parsing FMPSFrame" << name << ", " << value;
FMPSParser parser; FMPSParser parser;
if (!parser.Parse(value) || parser.is_empty()) return; if (!parser.Parse(value) || parser.is_empty()) return;
QVariant var; QVariant var;
@@ -426,7 +426,7 @@ void TagReader::ParseFMPSFrame(const QString &name, const QString &value, pb::ta
} }
void TagReader::ParseOggTag(const TagLib::Ogg::FieldListMap &map, const QTextCodec *codec, QString *disc, QString *compilation, pb::tagreader::SongMetadata *song) const { void TagReader::ParseOggTag(const TagLib::Ogg::FieldListMap &map, const QTextCodec *codec, QString *disc, QString *compilation, pb::tagreader::SongMetadata *song) const {
if (!map["COMPOSER"].isEmpty()) Decode(map["COMPOSER"].front(), codec, song->mutable_composer()); if (!map["COMPOSER"].isEmpty()) Decode(map["COMPOSER"].front(), codec, song->mutable_composer());
if (!map["PERFORMER"].isEmpty()) Decode(map["PERFORMER"].front(), codec, song->mutable_performer()); if (!map["PERFORMER"].isEmpty()) Decode(map["PERFORMER"].front(), codec, song->mutable_performer());
if (!map["CONTENT GROUP"].isEmpty()) Decode(map["CONTENT GROUP"].front(), codec, song->mutable_grouping()); if (!map["CONTENT GROUP"].isEmpty()) Decode(map["CONTENT GROUP"].front(), codec, song->mutable_grouping());
@@ -569,16 +569,16 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
} }
void TagReader::SetUserTextFrame(const QString &description, const QString &value, TagLib::ID3v2::Tag *tag) const { void TagReader::SetUserTextFrame(const QString &description, const QString &value, TagLib::ID3v2::Tag *tag) const {
const QByteArray descr_utf8(description.toUtf8()); const QByteArray descr_utf8(description.toUtf8());
const QByteArray value_utf8(value.toUtf8()); const QByteArray value_utf8(value.toUtf8());
qLog(Debug) << "Setting FMPSFrame:" << description << ", " << value; qLog(Debug) << "Setting FMPSFrame:" << description << ", " << value;
SetUserTextFrame(std::string(descr_utf8.constData(), descr_utf8.length()), std::string(value_utf8.constData(), value_utf8.length()), tag); SetUserTextFrame(std::string(descr_utf8.constData(), descr_utf8.length()), std::string(value_utf8.constData(), value_utf8.length()), tag);
} }
void TagReader::SetUserTextFrame(const std::string &description, const std::string &value, TagLib::ID3v2::Tag *tag) const { void TagReader::SetUserTextFrame(const std::string &description, const std::string &value, TagLib::ID3v2::Tag *tag) const {
const TagLib::String t_description = StdStringToTaglibString(description); const TagLib::String t_description = StdStringToTaglibString(description);
// Remove the frame if it already exists // Remove the frame if it already exists
TagLib::ID3v2::UserTextIdentificationFrame *frame = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, t_description); TagLib::ID3v2::UserTextIdentificationFrame *frame = TagLib::ID3v2::UserTextIdentificationFrame::find(tag, t_description);
@@ -596,13 +596,13 @@ void TagReader::SetUserTextFrame(const std::string &description, const std::stri
} }
void TagReader::SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const { void TagReader::SetTextFrame(const char *id, const QString &value, TagLib::ID3v2::Tag *tag) const {
const QByteArray utf8(value.toUtf8()); const QByteArray utf8(value.toUtf8());
SetTextFrame(id, std::string(utf8.constData(), utf8.length()), tag); SetTextFrame(id, std::string(utf8.constData(), utf8.length()), tag);
} }
void TagReader::SetTextFrame(const char *id, const std::string &value, TagLib::ID3v2::Tag *tag) const { void TagReader::SetTextFrame(const char *id, const std::string &value, TagLib::ID3v2::Tag *tag) const {
TagLib::ByteVector id_vector(id); TagLib::ByteVector id_vector(id);
QVector<TagLib::ByteVector> frames_buffer; QVector<TagLib::ByteVector> frames_buffer;
@@ -627,20 +627,20 @@ void TagReader::SetTextFrame(const char *id, const std::string &value, TagLib::I
// add frame takes ownership and clears the memory // add frame takes ownership and clears the memory
tag->addFrame(frame); tag->addFrame(frame);
} }
} }
bool TagReader::IsMediaFile(const QString &filename) const { bool TagReader::IsMediaFile(const QString &filename) const {
qLog(Debug) << "Checking for valid file" << filename; qLog(Debug) << "Checking for valid file" << filename;
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename)); std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
return !fileref->isNull() && fileref->tag(); return !fileref->isNull() && fileref->tag();
} }
QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const { QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
if (filename.isEmpty()) return QByteArray(); if (filename.isEmpty()) return QByteArray();
qLog(Debug) << "Loading art from" << filename; qLog(Debug) << "Loading art from" << filename;

View File

@@ -21,6 +21,7 @@ message SongMetadata {
TRUEAUDIO = 13; TRUEAUDIO = 13;
DSF = 14; DSF = 14;
DSDIFF = 15; DSDIFF = 15;
PCM = 16;
CDDA = 90; CDDA = 90;
STREAM = 91; STREAM = 91;
} }

View File

@@ -1,7 +1,5 @@
# Strawberry Music Player # Strawberry Music Player
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net> # Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
# This file was part of Clementine.
# Copyright 2010, David Sansome <me@davidsansome.com>
# #
# Strawberry is free software: you can redistribute it and/or modify # Strawberry is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by # it under the terms of the GNU General Public License as published by
@@ -44,7 +42,6 @@ include_directories(${GOBJECT_INCLUDE_DIRS})
include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIRS})
include_directories(${LIBXML_INCLUDE_DIRS}) include_directories(${LIBXML_INCLUDE_DIRS})
include_directories(${CHROMAPRINT_INCLUDE_DIRS}) include_directories(${CHROMAPRINT_INCLUDE_DIRS})
include_directories(${OPENGL_INCLUDE_DIR})
if(HAVE_GSTREAMER) if(HAVE_GSTREAMER)
link_directories(${GSTREAMER_LIBRARY_DIRS}) link_directories(${GSTREAMER_LIBRARY_DIRS})
@@ -59,6 +56,14 @@ if(HAVE_PHONON)
include_directories(${PHONON_INCLUDE_DIRS}) include_directories(${PHONON_INCLUDE_DIRS})
endif() endif()
if(HAVE_LIBDEEZER)
include_directories(${DEEZER_INCLUDE_DIRS})
endif()
if(HAVE_LIBDZMEDIA)
include_directories(${DZMEDIA_INCLUDE_DIRS})
endif()
link_directories(${TAGLIB_LIBRARY_DIRS}) link_directories(${TAGLIB_LIBRARY_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS}) include_directories(${TAGLIB_INCLUDE_DIRS})
@@ -109,17 +114,17 @@ set(SOURCES
core/windows7thumbbar.cpp core/windows7thumbbar.cpp
core/screensaver.cpp core/screensaver.cpp
core/scopedtransaction.cpp core/scopedtransaction.cpp
engine/enginetype.cpp engine/enginetype.cpp
engine/enginebase.cpp engine/enginebase.cpp
engine/enginedevice.cpp engine/enginedevice.cpp
engine/devicefinder.cpp engine/devicefinder.cpp
analyzer/fht.cpp analyzer/fht.cpp
analyzer/analyzerbase.cpp analyzer/analyzerbase.cpp
analyzer/analyzercontainer.cpp analyzer/analyzercontainer.cpp
analyzer/blockanalyzer.cpp analyzer/blockanalyzer.cpp
equalizer/equalizer.cpp equalizer/equalizer.cpp
equalizer/equalizerslider.cpp equalizer/equalizerslider.cpp
@@ -158,11 +163,12 @@ set(SOURCES
playlist/playlisttabbar.cpp playlist/playlisttabbar.cpp
playlist/playlistundocommands.cpp playlist/playlistundocommands.cpp
playlist/playlistview.cpp playlist/playlistview.cpp
playlist/queue.cpp
playlist/queuemanager.cpp
playlist/songloaderinserter.cpp playlist/songloaderinserter.cpp
playlist/songplaylistitem.cpp playlist/songplaylistitem.cpp
queue/queue.cpp
queue/queueview.cpp
playlistparsers/asxiniparser.cpp playlistparsers/asxiniparser.cpp
playlistparsers/asxparser.cpp playlistparsers/asxparser.cpp
playlistparsers/cueparser.cpp playlistparsers/cueparser.cpp
@@ -173,7 +179,7 @@ set(SOURCES
playlistparsers/wplparser.cpp playlistparsers/wplparser.cpp
playlistparsers/xmlparser.cpp playlistparsers/xmlparser.cpp
playlistparsers/xspfparser.cpp playlistparsers/xspfparser.cpp
covermanager/albumcovermanager.cpp covermanager/albumcovermanager.cpp
covermanager/albumcovermanagerlist.cpp covermanager/albumcovermanagerlist.cpp
covermanager/albumcoverloader.cpp covermanager/albumcoverloader.cpp
@@ -192,8 +198,14 @@ set(SOURCES
covermanager/coverfromurldialog.cpp covermanager/coverfromurldialog.cpp
covermanager/musicbrainzcoverprovider.cpp covermanager/musicbrainzcoverprovider.cpp
covermanager/discogscoverprovider.cpp covermanager/discogscoverprovider.cpp
#covermanager/amazoncoverprovider.cpp
lyrics/lyricsproviders.cpp
lyrics/lyricsprovider.cpp
lyrics/lyricsfetcher.cpp
lyrics/lyricsfetchersearch.cpp
lyrics/auddlyricsprovider.cpp
lyrics/apiseedslyricsprovider.cpp
settings/settingsdialog.cpp settings/settingsdialog.cpp
settings/settingspage.cpp settings/settingspage.cpp
settings/behavioursettingspage.cpp settings/behavioursettingspage.cpp
@@ -205,7 +217,6 @@ set(SOURCES
settings/shortcutssettingspage.cpp settings/shortcutssettingspage.cpp
settings/appearancesettingspage.cpp settings/appearancesettingspage.cpp
settings/notificationssettingspage.cpp settings/notificationssettingspage.cpp
settings/tidalsettingspage.cpp
dialogs/about.cpp dialogs/about.cpp
dialogs/console.cpp dialogs/console.cpp
@@ -238,43 +249,25 @@ set(SOURCES
widgets/tracksliderpopup.cpp widgets/tracksliderpopup.cpp
widgets/tracksliderslider.cpp widgets/tracksliderslider.cpp
widgets/loginstatewidget.cpp widgets/loginstatewidget.cpp
musicbrainz/acoustidclient.cpp musicbrainz/acoustidclient.cpp
musicbrainz/musicbrainzclient.cpp musicbrainz/musicbrainzclient.cpp
globalshortcuts/globalshortcutbackend.cpp globalshortcuts/globalshortcutbackend.cpp
globalshortcuts/globalshortcuts.cpp globalshortcuts/globalshortcuts.cpp
globalshortcuts/gnomeglobalshortcutbackend.cpp globalshortcuts/gnomeglobalshortcutbackend.cpp
globalshortcuts/qxtglobalshortcutbackend.cpp globalshortcuts/qxtglobalshortcutbackend.cpp
globalshortcuts/globalshortcutgrabber.cpp globalshortcuts/globalshortcutgrabber.cpp
device/connecteddevice.cpp
device/devicedatabasebackend.cpp
device/devicelister.cpp
device/devicemanager.cpp
device/deviceproperties.cpp
device/devicestatefiltermodel.cpp
device/deviceview.cpp
device/deviceviewcontainer.cpp
device/filesystemdevice.cpp
internet/internetmodel.cpp internet/internetservices.cpp
internet/internetservice.cpp internet/internetservice.cpp
internet/internetplaylistitem.cpp internet/internetplaylistitem.cpp
internet/internetsearch.cpp
tidal/tidalservice.cpp internet/internetsearchview.cpp
tidal/tidalsearch.cpp internet/internetsearchmodel.cpp
tidal/tidalsearchview.cpp internet/internetsearchsortmodel.cpp
tidal/tidalsearchmodel.cpp internet/internetsearchitemdelegate.cpp
tidal/tidalsearchsortmodel.cpp internet/localredirectserver.cpp
tidal/tidalsearchitemdelegate.cpp
lyrics/lyricsproviders.cpp
lyrics/lyricsprovider.cpp
lyrics/lyricsfetcher.cpp
lyrics/lyricsfetchersearch.cpp
lyrics/auddlyricsprovider.cpp
lyrics/apiseedslyricsprovider.cpp
) )
@@ -304,10 +297,10 @@ set(HEADERS
analyzer/analyzerbase.h analyzer/analyzerbase.h
analyzer/analyzercontainer.h analyzer/analyzercontainer.h
analyzer/blockanalyzer.h analyzer/blockanalyzer.h
equalizer/equalizer.h equalizer/equalizer.h
equalizer/equalizerslider.h equalizer/equalizerslider.h
context/contextview.h context/contextview.h
context/contextalbumsmodel.h context/contextalbumsmodel.h
context/contextalbumsview.h context/contextalbumsview.h
@@ -338,11 +331,12 @@ set(HEADERS
playlist/playlisttabbar.h playlist/playlisttabbar.h
playlist/playlistview.h playlist/playlistview.h
playlist/playlistitemmimedata.h playlist/playlistitemmimedata.h
playlist/queue.h
playlist/queuemanager.h
playlist/songloaderinserter.h playlist/songloaderinserter.h
playlist/songmimedata.h playlist/songmimedata.h
queue/queue.h
queue/queueview.h
playlistparsers/asxiniparser.h playlistparsers/asxiniparser.h
playlistparsers/asxparser.h playlistparsers/asxparser.h
playlistparsers/cueparser.h playlistparsers/cueparser.h
@@ -351,7 +345,7 @@ set(HEADERS
playlistparsers/playlistparser.h playlistparsers/playlistparser.h
playlistparsers/plsparser.h playlistparsers/plsparser.h
playlistparsers/xspfparser.h playlistparsers/xspfparser.h
covermanager/albumcovermanager.h covermanager/albumcovermanager.h
covermanager/albumcovermanagerlist.h covermanager/albumcovermanagerlist.h
covermanager/albumcoverloader.h covermanager/albumcoverloader.h
@@ -369,7 +363,13 @@ set(HEADERS
covermanager/coverfromurldialog.h covermanager/coverfromurldialog.h
covermanager/musicbrainzcoverprovider.h covermanager/musicbrainzcoverprovider.h
covermanager/discogscoverprovider.h covermanager/discogscoverprovider.h
#covermanager/amazoncoverprovider.h
lyrics/lyricsproviders.h
lyrics/lyricsprovider.h
lyrics/lyricsfetcher.h
lyrics/lyricsfetchersearch.h
lyrics/auddlyricsprovider.h
lyrics/apiseedslyricsprovider.h
settings/settingsdialog.h settings/settingsdialog.h
settings/settingspage.h settings/settingspage.h
@@ -382,7 +382,6 @@ set(HEADERS
settings/shortcutssettingspage.h settings/shortcutssettingspage.h
settings/appearancesettingspage.h settings/appearancesettingspage.h
settings/notificationssettingspage.h settings/notificationssettingspage.h
settings/tidalsettingspage.h
dialogs/about.h dialogs/about.h
dialogs/errordialog.h dialogs/errordialog.h
@@ -413,41 +412,22 @@ set(HEADERS
widgets/tracksliderpopup.h widgets/tracksliderpopup.h
widgets/tracksliderslider.h widgets/tracksliderslider.h
widgets/loginstatewidget.h widgets/loginstatewidget.h
musicbrainz/acoustidclient.h musicbrainz/acoustidclient.h
musicbrainz/musicbrainzclient.h musicbrainz/musicbrainzclient.h
globalshortcuts/globalshortcutbackend.h globalshortcuts/globalshortcutbackend.h
globalshortcuts/globalshortcuts.h globalshortcuts/globalshortcuts.h
globalshortcuts/gnomeglobalshortcutbackend.h globalshortcuts/gnomeglobalshortcutbackend.h
globalshortcuts/globalshortcutgrabber.h globalshortcuts/globalshortcutgrabber.h
device/connecteddevice.h
device/devicedatabasebackend.h
device/devicelister.h
device/devicemanager.h
device/deviceproperties.h
device/devicestatefiltermodel.h
device/deviceviewcontainer.h
device/deviceview.h
device/filesystemdevice.h
internet/internetmodel.h internet/internetservices.h
internet/internetservice.h internet/internetservice.h
internet/internetmimedata.h
internet/internetsongmimedata.h internet/internetsongmimedata.h
internet/internetsearch.h
tidal/tidalservice.h internet/internetsearchview.h
tidal/tidalsearch.h internet/internetsearchmodel.h
tidal/tidalsearchview.h internet/localredirectserver.h
tidal/tidalsearchmodel.h
lyrics/lyricsproviders.h
lyrics/lyricsprovider.h
lyrics/lyricsfetcher.h
lyrics/lyricsfetchersearch.h
lyrics/auddlyricsprovider.h
lyrics/apiseedslyricsprovider.h
) )
@@ -466,7 +446,8 @@ set(UI
playlist/playlistlistcontainer.ui playlist/playlistlistcontainer.ui
playlist/playlistsaveoptionsdialog.ui playlist/playlistsaveoptionsdialog.ui
playlist/playlistsequence.ui playlist/playlistsequence.ui
playlist/queuemanager.ui
queue/queueview.ui
covermanager/albumcoverexport.ui covermanager/albumcoverexport.ui
covermanager/albumcovermanager.ui covermanager/albumcovermanager.ui
@@ -484,7 +465,6 @@ set(UI
settings/shortcutssettingspage.ui settings/shortcutssettingspage.ui
settings/appearancesettingspage.ui settings/appearancesettingspage.ui
settings/notificationssettingspage.ui settings/notificationssettingspage.ui
settings/tidalsettingspage.ui
equalizer/equalizer.ui equalizer/equalizer.ui
equalizer/equalizerslider.ui equalizer/equalizerslider.ui
@@ -500,16 +480,13 @@ set(UI
widgets/fileview.ui widgets/fileview.ui
widgets/loginstatewidget.ui widgets/loginstatewidget.ui
device/deviceproperties.ui
device/deviceviewcontainer.ui
globalshortcuts/globalshortcutgrabber.ui globalshortcuts/globalshortcutgrabber.ui
tidal/tidalsearchview.ui internet/internetsearchview.ui
) )
set(RESOURCES ../data/data.qrc) set(RESOURCES ../data/data.qrc ../data/icons.qrc)
set(OTHER_SOURCES) set(OTHER_SOURCES)
option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON) option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON)
@@ -547,6 +524,12 @@ optional_source(HAVE_PHONON
HEADERS engine/phononengine.h HEADERS engine/phononengine.h
) )
# Deezer
optional_source(HAVE_DEEZER
SOURCES engine/deezerengine.cpp
HEADERS engine/deezerengine.h
)
# Lastfm # Lastfm
optional_source(HAVE_LIBLASTFM optional_source(HAVE_LIBLASTFM
SOURCES SOURCES
@@ -679,6 +662,32 @@ optional_source(HAVE_DBUS
core/mpris2.h core/mpris2.h
) )
optional_source(UNIX
SOURCES
device/connecteddevice.cpp
device/devicedatabasebackend.cpp
device/devicelister.cpp
device/devicemanager.cpp
device/devicestatefiltermodel.cpp
device/filesystemdevice.cpp
device/deviceviewcontainer.cpp
device/deviceview.cpp
device/deviceproperties.cpp
HEADERS
device/connecteddevice.h
device/devicedatabasebackend.h
device/devicelister.h
device/devicemanager.h
device/devicestatefiltermodel.h
device/filesystemdevice.h
device/deviceviewcontainer.h
device/deviceview.h
device/deviceproperties.h
UI
device/deviceproperties.ui
device/deviceviewcontainer.ui
)
if(HAVE_DBUS) if(HAVE_DBUS)
optional_source(HAVE_DEVICEKIT optional_source(HAVE_DEVICEKIT
SOURCES device/devicekitlister.cpp SOURCES device/devicekitlister.cpp
@@ -708,12 +717,12 @@ optional_source(HAVE_GIO
HEADERS device/giolister.h HEADERS device/giolister.h
) )
# libimobiledevice backend and device # imobiledevice backend and device
optional_source(HAVE_IMOBILEDEVICE optional_source(HAVE_IMOBILEDEVICE
INCLUDE_DIRECTORIES INCLUDE_DIRECTORIES
${IMOBILEDEVICE_INCLUDE_DIRS} ${LIBIMOBILEDEVICE_INCLUDE_DIRS}
${PLIST_INCLUDE_DIRS} ${LIBPLIST_INCLUDE_DIRS}
${PLISTPP_INCLUDE_DIRS} ${LIBPLISTPP_INCLUDE_DIRS}
SOURCES SOURCES
device/afcdevice.cpp device/afcdevice.cpp
device/afcfile.cpp device/afcfile.cpp
@@ -845,6 +854,32 @@ optional_source(WIN32
widgets/osd_win.cpp widgets/osd_win.cpp
) )
optional_source(HAVE_STREAM_TIDAL
SOURCES
tidal/tidalservice.cpp
tidal/tidalurlhandler.cpp
settings/tidalsettingspage.cpp
HEADERS
tidal/tidalservice.h
tidal/tidalurlhandler.h
settings/tidalsettingspage.h
UI
settings/tidalsettingspage.ui
)
optional_source(HAVE_STREAM_DEEZER
SOURCES
deezer/deezerservice.cpp
deezer/deezerurlhandler.cpp
settings/deezersettingspage.cpp
HEADERS
deezer/deezerservice.h
deezer/deezerurlhandler.h
settings/deezersettingspage.h
UI
settings/deezersettingspage.ui
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
${CMAKE_CURRENT_BINARY_DIR}/config.h) ${CMAKE_CURRENT_BINARY_DIR}/config.h)
@@ -877,6 +912,7 @@ target_link_libraries(strawberry_lib
${QT_LIBRARIES} ${QT_LIBRARIES}
${CHROMAPRINT_LIBRARIES} ${CHROMAPRINT_LIBRARIES}
${QTSINGLEAPPLICATION_LIBRARIES} ${QTSINGLEAPPLICATION_LIBRARIES}
${QTSINGLECOREAPPLICATION_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT} ${CMAKE_THREAD_LIBS_INIT}
${SQLITE_LIBRARIES} ${SQLITE_LIBRARIES}
${QOCOA_LIBRARIES} ${QOCOA_LIBRARIES}
@@ -903,6 +939,14 @@ if(HAVE_PHONON)
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES}) target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
endif() endif()
if(HAVE_DEEZER)
target_link_libraries(strawberry_lib ${LIBDEEZER_LIBRARIES})
endif()
if(HAVE_DZMEDIA)
target_link_libraries(strawberry_lib ${LIBDZMEDIA_LIBRARIES})
endif()
if(HAVE_LIBLASTFM) if(HAVE_LIBLASTFM)
target_link_libraries(strawberry_lib ${LASTFM5_LIBRARIES}) target_link_libraries(strawberry_lib ${LASTFM5_LIBRARIES})
endif(HAVE_LIBLASTFM) endif(HAVE_LIBLASTFM)
@@ -921,12 +965,12 @@ endif(HAVE_AUDIOCD)
if(HAVE_IMOBILEDEVICE) if(HAVE_IMOBILEDEVICE)
target_link_libraries(strawberry_lib target_link_libraries(strawberry_lib
${IMOBILEDEVICE_LIBRARIES} ${LIBIMOBILEDEVICE_LIBRARIES}
${PLIST_LIBRARIES} ${LIBPLIST_LIBRARIES}
${USBMUXD_LIBRARIES} ${LIBUSBMUXD_LIBRARIES}
) )
link_directories(${IMOBILEDEVICE_LIBRARY_DIRS}) link_directories(${LIBIMOBILEDEVICE_LIBRARY_DIRS})
link_directories(${USBMUXD_LIBRARY_DIRS}) link_directories(${LIBUSBMUXD_LIBRARY_DIRS})
endif(HAVE_IMOBILEDEVICE) endif(HAVE_IMOBILEDEVICE)
if(HAVE_LIBMTP) if(HAVE_LIBMTP)

View File

@@ -1,20 +0,0 @@
#include "config.h"
#include <QWidget>
#include <QGLWidget>
#include <QVector>
#include "analyzer.h"
#include "engine/enginebase.h"
AnalyzerBase::AnalyzerBase(QWidget *parent)
: QGLWidget(parent), engine_(nullptr) {}
void AnalyzerBase::set_engine(Engine::Base *engine) {
disconnect(engine_);
engine_ = engine;
if (engine_) {
connect(engine_, SIGNAL(SpectrumAvailable(const QVector<float>&)), SLOT(SpectrumAvailable(const QVector<float>&)));
}
}

View File

@@ -27,14 +27,13 @@
#include "analyzerbase.h" #include "analyzerbase.h"
#include "core/logging.h"
#include "engine/enginebase.h" #include "engine/enginebase.h"
// INSTRUCTIONS Base2D // INSTRUCTIONS Base2D
// 1. do anything that depends on height() in init(), Base2D will call it before // 1. do anything that depends on height() in init(), Base2D will call it before you are shown
// you are shown
// 2. otherwise you can use the constructor to initialise things // 2. otherwise you can use the constructor to initialise things
// 3. reimplement analyze(), and paint to canvas(), Base2D will update the // 3. reimplement analyze(), and paint to canvas(), Base2D will update the widget when you return control to it
// widget when you return control to it
// 4. if you want to manipulate the scope, reimplement transform() // 4. if you want to manipulate the scope, reimplement transform()
// 5. for convenience <vector> <qpixmap.h> <qwdiget.h> are pre-included // 5. for convenience <vector> <qpixmap.h> <qwdiget.h> are pre-included
// TODO make an INSTRUCTIONS file // TODO make an INSTRUCTIONS file
@@ -50,37 +49,32 @@ template class Analyzer::Base<QWidget>;
Analyzer::Base::Base(QWidget *parent, uint scopeSize) Analyzer::Base::Base(QWidget *parent, uint scopeSize)
: QWidget(parent), : QWidget(parent),
m_timeout(40) // msec timeout_(40),
, fht_(new FHT(scopeSize)),
m_fht(new FHT(scopeSize)), engine_(nullptr),
m_engine(nullptr), lastscope_(512),
m_lastScope(512),
current_chunk_(0), current_chunk_(0),
new_frame_(false), new_frame_(false),
is_playing_(false) {} is_playing_(false) {}
void Analyzer::Base::hideEvent(QHideEvent*) { m_timer.stop(); } void Analyzer::Base::hideEvent(QHideEvent*) { timer_.stop(); }
void Analyzer::Base::showEvent(QShowEvent*) { m_timer.start(timeout(), this); } void Analyzer::Base::showEvent(QShowEvent*) { timer_.start(timeout(), this); }
void Analyzer::Base::transform(Scope& scope) // virtual void Analyzer::Base::transform(Scope& scope) {
{
// this is a standard transformation that should give // This is a standard transformation that should give an FFT scope that has bands for pretty analyzers
// an FFT scope that has bands for pretty analyzers
// NOTE resizing here is redundant as FHT routines only calculate FHT::size() // NOTE: Resizing here is redundant as FHT routines only calculate FHT::size() values scope.resize( fht_->size() );
// values
// scope.resize( m_fht->size() );
float *front = static_cast<float*>(&scope.front()); float *front = static_cast<float*>(&scope.front());
float *f = new float[m_fht->size()]; float *f = new float[fht_->size()];
m_fht->copy(&f[0], front); fht_->copy(&f[0], front);
m_fht->logSpectrum(front, &f[0]); fht_->logSpectrum(front, &f[0]);
m_fht->scale(front, 1.0 / 20); fht_->scale(front, 1.0 / 20);
scope.resize(m_fht->size() / 2); // second half of values are rubbish scope.resize(fht_->size() / 2); // second half of values are rubbish
delete[] f; delete[] f;
} }
@@ -90,28 +84,28 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
QPainter p(this); QPainter p(this);
p.fillRect(e->rect(), palette().color(QPalette::Window)); p.fillRect(e->rect(), palette().color(QPalette::Window));
switch (m_engine->state()) { switch (engine_->state()) {
case Engine::Playing: { case Engine::Playing: {
const Engine::Scope& thescope = m_engine->scope(m_timeout); const Engine::Scope& thescope = engine_->scope(timeout_);
int i = 0; int i = 0;
// convert to mono here - our built in analyzers need mono, but the engines provide interleaved pcm // convert to mono here - our built in analyzers need mono, but the engines provide interleaved pcm
for (uint x = 0; (int)x < m_fht->size(); ++x) { for (uint x = 0; (int)x < fht_->size(); ++x) {
m_lastScope[x] = double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15)); lastscope_[x] = double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
i += 2; i += 2;
} }
is_playing_ = true; is_playing_ = true;
transform(m_lastScope); transform(lastscope_);
analyze(p, m_lastScope, new_frame_); analyze(p, lastscope_, new_frame_);
// scope.resize( m_fht->size() ); lastscope_.resize(fht_->size());
break; break;
} }
case Engine::Paused: case Engine::Paused:
is_playing_ = false; is_playing_ = false;
analyze(p, m_lastScope, new_frame_); analyze(p, lastscope_, new_frame_);
break; break;
default: default:
@@ -124,16 +118,18 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
} }
int Analyzer::Base::resizeExponent(int exp) { int Analyzer::Base::resizeExponent(int exp) {
if (exp < 3) if (exp < 3)
exp = 3; exp = 3;
else if (exp > 9) else if (exp > 9)
exp = 9; exp = 9;
if (exp != m_fht->sizeExp()) { if (exp != fht_->sizeExp()) {
delete m_fht; delete fht_;
m_fht = new FHT(exp); fht_ = new FHT(exp);
} }
return exp; return exp;
} }
int Analyzer::Base::resizeForBands(int bands) { int Analyzer::Base::resizeForBands(int bands) {
@@ -153,12 +149,11 @@ int Analyzer::Base::resizeForBands(int bands) {
exp = 9; exp = 9;
resizeExponent(exp); resizeExponent(exp);
return m_fht->size() / 2; return fht_->size() / 2;
} }
void Analyzer::Base::demo(QPainter& p) // virtual void Analyzer::Base::demo(QPainter& p) {
{
static int t = 201; // FIXME make static to namespace perhaps static int t = 201; // FIXME make static to namespace perhaps
@@ -171,7 +166,8 @@ void Analyzer::Base::demo(QPainter& p) // virtual
s[i] = dt * (sin(M_PI + (i * M_PI) / s.size()) + 1.0); s[i] = dt * (sin(M_PI + (i * M_PI) / s.size()) + 1.0);
analyze(p, s, new_frame_); analyze(p, s, new_frame_);
} else }
else
analyze(p, Scope(32, 0), new_frame_); analyze(p, Scope(32, 0), new_frame_);
++t; ++t;
@@ -179,7 +175,7 @@ void Analyzer::Base::demo(QPainter& p) // virtual
} }
void Analyzer::Base::polishEvent() { void Analyzer::Base::polishEvent() {
init(); // virtual init();
} }
void Analyzer::interpolate(const Scope& inVec, Scope& outVec) { void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
@@ -189,13 +185,13 @@ void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
for (uint i = 0; i < outVec.size(); ++i, pos += step) { for (uint i = 0; i < outVec.size(); ++i, pos += step) {
const double error = pos - std::floor(pos); const double error = pos - std::floor(pos);
const unsigned long offset = (unsigned long)pos; const uint64_t offset = (uint64_t)pos;
unsigned long indexLeft = offset + 0; uint64_t indexLeft = offset + 0;
if (indexLeft >= inVec.size()) indexLeft = inVec.size() - 1; if (indexLeft >= inVec.size()) indexLeft = inVec.size() - 1;
unsigned long indexRight = offset + 1; uint64_t indexRight = offset + 1;
if (indexRight >= inVec.size()) indexRight = inVec.size() - 1; if (indexRight >= inVec.size()) indexRight = inVec.size() - 1;
@@ -205,6 +201,7 @@ void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
} }
void Analyzer::initSin(Scope& v, const uint size) { void Analyzer::initSin(Scope& v, const uint size) {
double step = (M_PI * 2) / size; double step = (M_PI * 2) / size;
double radian = 0; double radian = 0;
@@ -212,12 +209,15 @@ void Analyzer::initSin(Scope& v, const uint size) {
v.push_back(sin(radian)); v.push_back(sin(radian));
radian += step; radian += step;
} }
} }
void Analyzer::Base::timerEvent(QTimerEvent *e) { void Analyzer::Base::timerEvent(QTimerEvent *e) {
QWidget::timerEvent(e); QWidget::timerEvent(e);
if (e->timerId() != m_timer.timerId()) return; if (e->timerId() != timer_.timerId()) return;
new_frame_ = true; new_frame_ = true;
update(); update();
} }

View File

@@ -37,17 +37,17 @@ class Base : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
~Base() { delete m_fht; } ~Base() { delete fht_; }
uint timeout() const { return m_timeout; } uint timeout() const { return timeout_; }
void set_engine(EngineBase *engine) { m_engine = engine; } void set_engine(EngineBase *engine) { engine_ = engine; }
void changeTimeout(uint newTimeout) { void changeTimeout(uint newTimeout) {
m_timeout = newTimeout; timeout_ = newTimeout;
if (m_timer.isActive()) { if (timer_.isActive()) {
m_timer.stop(); timer_.stop();
m_timer.start(m_timeout, this); timer_.start(timeout_, this);
} }
} }
@@ -71,13 +71,12 @@ class Base : public QWidget {
virtual void demo(QPainter& p); virtual void demo(QPainter& p);
protected: protected:
QBasicTimer m_timer; QBasicTimer timer_;
uint m_timeout; uint timeout_;
FHT* m_fht; FHT *fht_;
EngineBase* m_engine; EngineBase *engine_;
Scope m_lastScope; Scope lastscope_;
int current_chunk_; int current_chunk_;
bool new_frame_; bool new_frame_;
bool is_playing_; bool is_playing_;
}; };

View File

@@ -26,109 +26,105 @@ const uint BlockAnalyzer::MIN_COLUMNS = 32; // arbituary
const uint BlockAnalyzer::MAX_COLUMNS = 256; // must be 2**n const uint BlockAnalyzer::MAX_COLUMNS = 256; // must be 2**n
const uint BlockAnalyzer::FADE_SIZE = 90; const uint BlockAnalyzer::FADE_SIZE = 90;
const char *BlockAnalyzer::kName = const char *BlockAnalyzer::kName = QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
BlockAnalyzer::BlockAnalyzer(QWidget *parent) BlockAnalyzer::BlockAnalyzer(QWidget *parent)
: Analyzer::Base(parent, 9), : Analyzer::Base(parent, 9),
m_columns(0) // uint columns_(0),
, rows_(0),
m_rows(0) // uint y_(0),
, barpixmap_(1, 1),
m_y(0) // uint topbarpixmap_(WIDTH, HEIGHT),
, scope_(MIN_COLUMNS),
m_barPixmap(1, 1) // null qpixmaps cause crashes store_(1 << 8, 0),
, fade_bars_(FADE_SIZE),
m_topBarPixmap(WIDTH, HEIGHT), fade_pos_(1 << 8, 50),
m_scope(MIN_COLUMNS) // Scope fade_intensity_(1 << 8, 32) {
,
m_store(1 << 8, 0) // vector<uint>
,
m_fade_bars(FADE_SIZE) // vector<QPixmap>
,
m_fade_pos(1 << 8, 50) // vector<uint>
,
m_fade_intensity(1 << 8, 32) // vector<uint>
{
setMinimumSize(MIN_COLUMNS * (WIDTH + 1) - 1, MIN_ROWS * (HEIGHT + 1) - 1); //-1 is padding, no drawing takes place there setMinimumSize(MIN_COLUMNS * (WIDTH + 1) - 1, MIN_ROWS * (HEIGHT + 1) - 1); //-1 is padding, no drawing takes place there
setMaximumWidth(MAX_COLUMNS * (WIDTH + 1) - 1); setMaximumWidth(MAX_COLUMNS * (WIDTH + 1) - 1);
// mxcl says null pixmaps cause crashes, so let's play it safe // mxcl says null pixmaps cause crashes, so let's play it safe
for (uint i = 0; i < FADE_SIZE; ++i) m_fade_bars[i] = QPixmap(1, 1); for (uint i = 0; i < FADE_SIZE; ++i) fade_bars_[i] = QPixmap(1, 1);
} }
BlockAnalyzer::~BlockAnalyzer() {} BlockAnalyzer::~BlockAnalyzer() {}
void BlockAnalyzer::resizeEvent(QResizeEvent *e) { void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
QWidget::resizeEvent(e); QWidget::resizeEvent(e);
m_background = QPixmap(size()); background_ = QPixmap(size());
canvas_ = QPixmap(size()); canvas_ = QPixmap(size());
const uint oldRows = m_rows; const uint oldRows = rows_;
// all is explained in analyze().. // all is explained in analyze()..
//+1 to counter -1 in maxSizes, trust me we need this! //+1 to counter -1 in maxSizes, trust me we need this!
m_columns = qMax(uint(double(width() + 1) / (WIDTH + 1)), MAX_COLUMNS); columns_ = qMax(uint(double(width() + 1) / (WIDTH + 1)), MAX_COLUMNS);
m_rows = uint(double(height() + 1) / (HEIGHT + 1)); rows_ = uint(double(height() + 1) / (HEIGHT + 1));
// this is the y-offset for drawing from the top of the widget // this is the y-offset for drawing from the top of the widget
m_y = (height() - (m_rows * (HEIGHT + 1)) + 2) / 2; y_ = (height() - (rows_ * (HEIGHT + 1)) + 2) / 2;
m_scope.resize(m_columns); scope_.resize(columns_);
if (m_rows != oldRows) { if (rows_ != oldRows) {
m_barPixmap = QPixmap(WIDTH, m_rows * (HEIGHT + 1)); barpixmap_ = QPixmap(WIDTH, rows_ * (HEIGHT + 1));
for (uint i = 0; i < FADE_SIZE; ++i) for (uint i = 0; i < FADE_SIZE; ++i)
m_fade_bars[i] = QPixmap(WIDTH, m_rows * (HEIGHT + 1)); fade_bars_[i] = QPixmap(WIDTH, rows_ * (HEIGHT + 1));
m_yscale.resize(m_rows + 1); yscale_.resize(rows_ + 1);
const uint PRE = 1, const uint PRE = 1, PRO = 1; // PRE and PRO allow us to restrict the range somewhat
PRO = 1; // PRE and PRO allow us to restrict the range somewhat
for (uint z = 0; z < m_rows; ++z) for (uint z = 0; z < rows_; ++z)
m_yscale[z] = 1 - (log10(PRE + z) / log10(PRE + m_rows + PRO)); yscale_[z] = 1 - (log10(PRE + z) / log10(PRE + rows_ + PRO));
m_yscale[m_rows] = 0; yscale_[rows_] = 0;
determineStep(); determineStep();
paletteChange(palette()); paletteChange(palette());
} }
drawBackground(); drawBackground();
} }
void BlockAnalyzer::determineStep() { void BlockAnalyzer::determineStep() {
// falltime is dependent on rowcount due to our digital resolution (ie we have boxes/blocks of pixels) // falltime is dependent on rowcount due to our digital resolution (ie we have boxes/blocks of pixels)
// I calculated the value 30 based on some trial and error // I calculated the value 30 based on some trial and error
// the fall time of 30 is too slow on framerates above 50fps // the fall time of 30 is too slow on framerates above 50fps
const double fallTime = timeout() < 20 ? 20 * m_rows : 30 * m_rows; const double fallTime = timeout() < 20 ? 20 * rows_ : 30 * rows_;
step_ = double(rows_ * timeout()) / fallTime;
m_step = double(m_rows * timeout()) / fallTime;
} }
void BlockAnalyzer::framerateChanged() { // virtual void BlockAnalyzer::framerateChanged() {
determineStep(); determineStep();
} }
void BlockAnalyzer::transform(Analyzer::Scope& s) // pure virtual void BlockAnalyzer::transform(Analyzer::Scope &s) {
{
for (uint x = 0; x < s.size(); ++x) s[x] *= 2; for (uint x = 0; x < s.size(); ++x) s[x] *= 2;
float* front = static_cast<float*>(&s.front()); float* front = static_cast<float*>(&s.front());
m_fht->spectrum(front); fht_->spectrum(front);
m_fht->scale(front, 1.0 / 20); fht_->scale(front, 1.0 / 20);
// the second half is pretty dull, so only show it if the user has a large analyzer by setting to scope_.size() if large we prevent interpolation of large analyzers, this is good!
s.resize(scope_.size() <= MAX_COLUMNS / 2 ? MAX_COLUMNS / 2 : scope_.size());
// the second half is pretty dull, so only show it if the user has a large analyzer by setting to m_scope.size() if large we prevent interpolation of large analyzers, this is good!
s.resize(m_scope.size() <= MAX_COLUMNS / 2 ? MAX_COLUMNS / 2 : m_scope.size());
} }
void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s, void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_frame) {
bool new_frame) {
// y = 2 3 2 1 0 2 // y = 2 3 2 1 0 2
// . . . . # . // . . . . # .
// . . . # # . // . . . # # .
@@ -139,7 +135,7 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
// y represents the number of blanks // y represents the number of blanks
// y starts from the top and increases in units of blocks // y starts from the top and increases in units of blocks
// m_yscale looks similar to: { 0.7, 0.5, 0.25, 0.15, 0.1, 0 } // yscale_ looks similar to: { 0.7, 0.5, 0.25, 0.15, 0.1, 0 }
// if it contains 6 elements there are 5 rows in the analyzer // if it contains 6 elements there are 5 rows in the analyzer
if (!new_frame) { if (!new_frame) {
@@ -149,50 +145,51 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
QPainter canvas_painter(&canvas_); QPainter canvas_painter(&canvas_);
Analyzer::interpolate(s, m_scope); Analyzer::interpolate(s, scope_);
// Paint the background // Paint the background
canvas_painter.drawPixmap(0, 0, m_background); canvas_painter.drawPixmap(0, 0, background_);
for (uint y, x = 0; x < m_scope.size(); ++x) { for (uint y, x = 0; x < scope_.size(); ++x) {
// determine y // determine y
for (y = 0; m_scope[x] < m_yscale[y]; ++y) for (y = 0; scope_[x] < yscale_[y]; ++y) continue;
;
// this is opposite to what you'd think, higher than y means the bar is lower than y (physically) // this is opposite to what you'd think, higher than y means the bar is lower than y (physically)
if ((float)y > m_store[x]) if ((float)y > store_[x])
y = int(m_store[x] += m_step); y = int(store_[x] += step_);
else else
m_store[x] = y; store_[x] = y;
// if y is lower than m_fade_pos, then the bar has exceeded the height of the fadeout // if y is lower than fade_pos_, then the bar has exceeded the height of the fadeout
// if the fadeout is quite faded now, then display the new one // if the fadeout is quite faded now, then display the new one
if (y <= m_fade_pos[x] /*|| m_fade_intensity[x] < FADE_SIZE / 3*/) { if (y <= fade_pos_[x] /*|| fade_intensity_[x] < FADE_SIZE / 3*/) {
m_fade_pos[x] = y; fade_pos_[x] = y;
m_fade_intensity[x] = FADE_SIZE; fade_intensity_[x] = FADE_SIZE;
} }
if (m_fade_intensity[x] > 0) { if (fade_intensity_[x] > 0) {
const uint offset = --m_fade_intensity[x]; const uint offset = --fade_intensity_[x];
const uint y = m_y + (m_fade_pos[x] * (HEIGHT + 1)); const uint y = y_ + (fade_pos_[x] * (HEIGHT + 1));
canvas_painter.drawPixmap(x * (WIDTH + 1), y, m_fade_bars[offset], 0, 0, WIDTH, height() - y); canvas_painter.drawPixmap(x * (WIDTH + 1), y, fade_bars_[offset], 0, 0, WIDTH, height() - y);
} }
if (m_fade_intensity[x] == 0) m_fade_pos[x] = m_rows; if (fade_intensity_[x] == 0) fade_pos_[x] = rows_;
// REMEMBER: y is a number from 0 to m_rows, 0 means all blocks are glowing, m_rows means none are // REMEMBER: y is a number from 0 to rows_, 0 means all blocks are glowing, rows_ means none are
canvas_painter.drawPixmap(x * (WIDTH + 1), y * (HEIGHT + 1) + m_y, *bar(), canvas_painter.drawPixmap(x * (WIDTH + 1), y * (HEIGHT + 1) + y_, *bar(),
0, y * (HEIGHT + 1), bar()->width(), 0, y * (HEIGHT + 1), bar()->width(),
bar()->height()); bar()->height());
} }
for (uint x = 0; x < m_store.size(); ++x) for (uint x = 0; x < store_.size(); ++x)
canvas_painter.drawPixmap(x * (WIDTH + 1), int(m_store[x]) * (HEIGHT + 1) + m_y, m_topBarPixmap); canvas_painter.drawPixmap(x * (WIDTH + 1), int(store_[x]) * (HEIGHT + 1) + y_, topbarpixmap_);
p.drawPixmap(0, 0, canvas_); p.drawPixmap(0, 0, canvas_);
} }
static inline void adjustToLimits(int& b, int& f, uint& amount) { static inline void adjustToLimits(int &b, int &f, uint &amount) {
// with a range of 0-255 and maximum adjustment of amount, maximise the difference between f and b // with a range of 0-255 and maximum adjustment of amount, maximise the difference between f and b
if (b < f) { if (b < f) {
@@ -215,6 +212,7 @@ static inline void adjustToLimits(int& b, int& f, uint& amount) {
f = 255; f = 255;
} }
} }
} }
/** /**
@@ -225,17 +223,18 @@ static inline void adjustToLimits(int& b, int& f, uint& amount) {
* It won't modify the hue of fg unless absolutely necessary * It won't modify the hue of fg unless absolutely necessary
* @return the adjusted form of fg * @return the adjusted form of fg
*/ */
QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) { QColor ensureContrast(const QColor &bg, const QColor &fg, uint _amount = 150) {
class OutputOnExit { class OutputOnExit {
public: public:
OutputOnExit(const QColor& color) : c(color) {} OutputOnExit(const QColor &color) : c(color) {}
~OutputOnExit() { ~OutputOnExit() {
int h, s, v; int h, s, v;
c.getHsv(&h, &s, &v); c.getHsv(&h, &s, &v);
} }
private: private:
const QColor& c; const QColor &c;
}; };
// hack so I don't have to cast everywhere // hack so I don't have to cast everywhere
@@ -352,24 +351,25 @@ QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) {
#undef amount #undef amount
// #undef STAMP // #undef STAMP
} }
void BlockAnalyzer::paletteChange(const QPalette&) // virtual void BlockAnalyzer::paletteChange(const QPalette&) {
{
const QColor bg = palette().color(QPalette::Background); const QColor bg = palette().color(QPalette::Background);
const QColor fg = ensureContrast(bg, palette().color(QPalette::Highlight)); const QColor fg = ensureContrast(bg, palette().color(QPalette::Highlight));
m_topBarPixmap.fill(fg); topbarpixmap_.fill(fg);
const double dr = 15 * double(bg.red() - fg.red()) / (m_rows * 16); const double dr = 15 * double(bg.red() - fg.red()) / (rows_ * 16);
const double dg = 15 * double(bg.green() - fg.green()) / (m_rows * 16); const double dg = 15 * double(bg.green() - fg.green()) / (rows_ * 16);
const double db = 15 * double(bg.blue() - fg.blue()) / (m_rows * 16); const double db = 15 * double(bg.blue() - fg.blue()) / (rows_ * 16);
const int r = fg.red(), g = fg.green(), b = fg.blue(); const int r = fg.red(), g = fg.green(), b = fg.blue();
bar()->fill(bg); bar()->fill(bg);
QPainter p(bar()); QPainter p(bar());
for (int y = 0; (uint)y < m_rows; ++y) for (int y = 0; (uint)y < rows_; ++y)
// graduate the fg color // graduate the fg color
p.fillRect(0, y * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * y), g + int(dg * y), b + int(db * y))); p.fillRect(0, y * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * y), g + int(dg * y), b + int(db * y)));
@@ -389,9 +389,9 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
// Precalculate all fade-bar pixmaps // Precalculate all fade-bar pixmaps
for (uint y = 0; y < FADE_SIZE; ++y) { for (uint y = 0; y < FADE_SIZE; ++y) {
m_fade_bars[y].fill(palette().color(QPalette::Background)); fade_bars_[y].fill(palette().color(QPalette::Background));
QPainter f(&m_fade_bars[y]); QPainter f(&fade_bars_[y]);
for (int z = 0; (uint)z < m_rows; ++z) { for (int z = 0; (uint)z < rows_; ++z) {
const double Y = 1.0 - (log10(FADE_SIZE - y) / log10(FADE_SIZE)); const double Y = 1.0 - (log10(FADE_SIZE - y) / log10(FADE_SIZE));
f.fillRect(0, z * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * Y), g + int(dg * Y), b + int(db * Y))); f.fillRect(0, z * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * Y), g + int(dg * Y), b + int(db * Y)));
} }
@@ -399,16 +399,19 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
} }
drawBackground(); drawBackground();
} }
void BlockAnalyzer::drawBackground() { void BlockAnalyzer::drawBackground() {
const QColor bg = palette().color(QPalette::Background); const QColor bg = palette().color(QPalette::Background);
const QColor bgdark = bg.dark(112); const QColor bgdark = bg.dark(112);
m_background.fill(bg); background_.fill(bg);
QPainter p(&background_);
for (int x = 0; (uint)x < columns_; ++x)
for (int y = 0; (uint)y < rows_; ++y)
p.fillRect(x * (WIDTH + 1), y * (HEIGHT + 1) + y_, WIDTH, HEIGHT, bgdark);
QPainter p(&m_background);
for (int x = 0; (uint)x < m_columns; ++x)
for (int y = 0; (uint)y < m_rows; ++y)
p.fillRect(x * (WIDTH + 1), y * (HEIGHT + 1) + m_y, WIDTH, HEIGHT, bgdark);
} }

View File

@@ -51,24 +51,24 @@ class BlockAnalyzer : public Analyzer::Base {
void determineStep(); void determineStep();
private: private:
QPixmap* bar() { return &m_barPixmap; } QPixmap *bar() { return &barpixmap_; }
uint m_columns, m_rows; // number of rows and columns of blocks uint columns_, rows_; // number of rows and columns of blocks
uint m_y; // y-offset from top of widget uint y_; // y-offset from top of widget
QPixmap m_barPixmap; QPixmap barpixmap_;
QPixmap m_topBarPixmap; QPixmap topbarpixmap_;
QPixmap m_background; QPixmap background_;
QPixmap canvas_; QPixmap canvas_;
Analyzer::Scope m_scope; // so we don't create a vector every frame Analyzer::Scope scope_; // so we don't create a vector every frame
std::vector<float> m_store; // current bar heights std::vector<float> store_; // current bar heights
std::vector<float> m_yscale; std::vector<float> yscale_;
// FIXME why can't I namespace these? c++ issue? // FIXME why can't I namespace these? c++ issue?
std::vector<QPixmap> m_fade_bars; std::vector<QPixmap> fade_bars_;
std::vector<uint> m_fade_pos; std::vector<uint> fade_pos_;
std::vector<int> m_fade_intensity; std::vector<int> fade_intensity_;
float m_step; // rows to fall per frame float step_; // rows to fall per frame
}; };
#endif #endif

View File

@@ -69,7 +69,7 @@ SCollection::~SCollection() {
} }
void SCollection::Init() { void SCollection::Init() {
watcher_ = new CollectionWatcher; watcher_ = new CollectionWatcher;
watcher_thread_ = new Thread(this); watcher_thread_ = new Thread(this);
watcher_thread_->SetIoPriority(Utilities::IOPRIO_CLASS_IDLE); watcher_thread_->SetIoPriority(Utilities::IOPRIO_CLASS_IDLE);
@@ -116,7 +116,7 @@ void SCollection::Stopped() {
} }
void SCollection::CurrentSongChanged(const Song &song) { void SCollection::CurrentSongChanged(const Song &song) {
TagReaderReply *reply = nullptr; TagReaderReply *reply = nullptr;
if (reply) { if (reply) {

View File

@@ -531,7 +531,7 @@ void CollectionBackend::MarkSongsUnavailable(const SongList &songs, bool unavail
} }
QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) { QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) {
CollectionQuery query(opt); CollectionQuery query(opt);
query.SetColumnSpec("DISTINCT " + column); query.SetColumnSpec("DISTINCT " + column);
query.AddCompilationRequirement(false); query.AddCompilationRequirement(false);

View File

@@ -21,6 +21,7 @@
#include "config.h" #include "config.h"
#include <functional> #include <functional>
#include <algorithm>
#include <QObject> #include <QObject>
#include <QtGlobal> #include <QtGlobal>
@@ -61,6 +62,8 @@
#include "playlist/songmimedata.h" #include "playlist/songmimedata.h"
#include "covermanager/albumcoverloader.h" #include "covermanager/albumcoverloader.h"
using std::bind;
using std::sort;
using std::placeholders::_1; using std::placeholders::_1;
using std::placeholders::_2; using std::placeholders::_2;
@@ -329,10 +332,10 @@ QString CollectionModel::DividerKey(GroupBy type, CollectionItem *item) const {
case GroupBy_Bitrate: case GroupBy_Bitrate:
return SortTextForNumber(item->metadata.bitrate()); return SortTextForNumber(item->metadata.bitrate());
case GroupBy_Samplerate: case GroupBy_Samplerate:
return SortTextForNumber(item->metadata.samplerate()); return SortTextForNumber(item->metadata.samplerate());
case GroupBy_Bitdepth: case GroupBy_Bitdepth:
return SortTextForNumber(item->metadata.bitdepth()); return SortTextForNumber(item->metadata.bitdepth());
@@ -374,11 +377,11 @@ QString CollectionModel::DividerDisplayText(GroupBy type, const QString &key) co
case GroupBy_Bitrate: case GroupBy_Bitrate:
if (key == "000") return tr("Unknown"); if (key == "000") return tr("Unknown");
return QString::number(key.toInt()); // To remove leading 0s return QString::number(key.toInt()); // To remove leading 0s
case GroupBy_Samplerate: case GroupBy_Samplerate:
if (key == "000") return tr("Unknown"); if (key == "000") return tr("Unknown");
return QString::number(key.toInt()); // To remove leading 0s return QString::number(key.toInt()); // To remove leading 0s
case GroupBy_Bitdepth: case GroupBy_Bitdepth:
if (key == "000") return tr("Unknown"); if (key == "000") return tr("Unknown");
return QString::number(key.toInt()); // To remove leading 0s return QString::number(key.toInt()); // To remove leading 0s
@@ -1125,13 +1128,13 @@ CollectionItem *CollectionModel::ItemFromSong(GroupBy type, bool signal, bool cr
item->key = QString::number(bitrate); item->key = QString::number(bitrate);
item->sort_text = SortTextForNumber(bitrate) + " "; item->sort_text = SortTextForNumber(bitrate) + " ";
break; break;
case GroupBy_Samplerate: case GroupBy_Samplerate:
samplerate = qMax(0, s.samplerate()); samplerate = qMax(0, s.samplerate());
item->key = QString::number(samplerate); item->key = QString::number(samplerate);
item->sort_text = SortTextForNumber(samplerate) + " "; item->sort_text = SortTextForNumber(samplerate) + " ";
break; break;
case GroupBy_Bitdepth: case GroupBy_Bitdepth:
bitdepth = qMax(0, s.bitdepth()); bitdepth = qMax(0, s.bitdepth());
item->key = QString::number(bitdepth); item->key = QString::number(bitdepth);
@@ -1312,7 +1315,7 @@ void CollectionModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls, Son
const_cast<CollectionModel*>(this)->LazyPopulate(item); const_cast<CollectionModel*>(this)->LazyPopulate(item);
QList<CollectionItem*> children = item->children; QList<CollectionItem*> children = item->children;
qSort(children.begin(), children.end(), std::bind(&CollectionModel::CompareItems, this, _1, _2)); std::sort(children.begin(), children.end(), std::bind(&CollectionModel::CompareItems, this, _1, _2));
for (CollectionItem *child : children) for (CollectionItem *child : children)
GetChildSongs(child, urls, songs, song_ids); GetChildSongs(child, urls, songs, song_ids);

View File

@@ -68,8 +68,10 @@
#include "collectionitem.h" #include "collectionitem.h"
#include "collectionmodel.h" #include "collectionmodel.h"
#include "collectionview.h" #include "collectionview.h"
#include "device/devicemanager.h" #ifndef Q_OS_WIN
#include "device/devicestatefiltermodel.h" # include "device/devicemanager.h"
# include "device/devicestatefiltermodel.h"
#endif
#include "dialogs/edittagdialog.h" #include "dialogs/edittagdialog.h"
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
#include "dialogs/organisedialog.h" #include "dialogs/organisedialog.h"
@@ -344,7 +346,7 @@ void CollectionView::ReloadSettings() {
app_->collection_model()->set_pretty_covers(settings.value("pretty_covers", true).toBool()); app_->collection_model()->set_pretty_covers(settings.value("pretty_covers", true).toBool());
app_->collection_model()->set_show_dividers(settings.value("show_dividers", true).toBool()); app_->collection_model()->set_show_dividers(settings.value("show_dividers", true).toBool());
} }
settings.endGroup(); settings.endGroup();
} }
@@ -369,7 +371,7 @@ void CollectionView::TotalSongCountUpdated(int count) {
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
else else
unsetCursor(); unsetCursor();
emit TotalSongCountUpdated_(); emit TotalSongCountUpdated_();
} }
@@ -384,7 +386,7 @@ void CollectionView::TotalArtistCountUpdated(int count) {
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
else else
unsetCursor(); unsetCursor();
emit TotalArtistCountUpdated_(); emit TotalArtistCountUpdated_();
} }
@@ -399,7 +401,7 @@ void CollectionView::TotalAlbumCountUpdated(int count) {
setCursor(Qt::PointingHandCursor); setCursor(Qt::PointingHandCursor);
else else
unsetCursor(); unsetCursor();
emit TotalAlbumCountUpdated_(); emit TotalAlbumCountUpdated_();
} }
@@ -456,11 +458,14 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_->addSeparator(); context_menu_->addSeparator();
add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, SLOT(AddToPlaylistEnqueue())); add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, SLOT(AddToPlaylistEnqueue()));
add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue to play next"), this, SLOT(AddToPlaylistEnqueueNext()));
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
context_menu_->addSeparator(); context_menu_->addSeparator();
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise())); organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
#ifndef Q_OS_WIN
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice())); copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
#endif
//delete_ = context_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(Delete())); //delete_ = context_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(Delete()));
#endif #endif
@@ -477,7 +482,7 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_->addMenu(filter_->menu()); context_menu_->addMenu(filter_->menu());
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0); copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool))); connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool)));
#endif #endif
@@ -518,7 +523,9 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
// only when no smart playlists selected // only when no smart playlists selected
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
organise_->setVisible(regular_elements_only); organise_->setVisible(regular_elements_only);
#ifndef Q_OS_WIN
copy_to_device_->setVisible(regular_elements_only); copy_to_device_->setVisible(regular_elements_only);
#endif
//delete_->setVisible(regular_elements_only); //delete_->setVisible(regular_elements_only);
#endif #endif
show_in_various_->setVisible(regular_elements_only); show_in_various_->setVisible(regular_elements_only);
@@ -527,7 +534,9 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
// only when all selected items are editable // only when all selected items are editable
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
organise_->setEnabled(regular_elements == regular_editable); organise_->setEnabled(regular_elements == regular_editable);
#ifndef Q_OS_WIN
copy_to_device_->setEnabled(regular_elements == regular_editable); copy_to_device_->setEnabled(regular_elements == regular_editable);
#endif
//delete_->setEnabled(regular_elements == regular_editable); //delete_->setEnabled(regular_elements == regular_editable);
#endif #endif
@@ -608,6 +617,16 @@ void CollectionView::AddToPlaylistEnqueue() {
} }
void CollectionView::AddToPlaylistEnqueueNext() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
mime_data->enqueue_next_now_ = true;
}
emit AddToPlaylistSignal(data);
}
void CollectionView::OpenInNewPlaylist() { void CollectionView::OpenInNewPlaylist() {
QMimeData *data = model()->mimeData(selectedIndexes()); QMimeData *data = model()->mimeData(selectedIndexes());
@@ -670,7 +689,7 @@ void CollectionView::EditTracks() {
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
void CollectionView::CopyToDevice() { void CollectionView::CopyToDevice() {
#ifndef Q_OS_WIN
if (!organise_dialog_) if (!organise_dialog_)
organise_dialog_.reset(new OrganiseDialog(app_->task_manager())); organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
@@ -678,7 +697,7 @@ void CollectionView::CopyToDevice() {
organise_dialog_->SetCopy(true); organise_dialog_->SetCopy(true);
organise_dialog_->SetSongs(GetSelectedSongs()); organise_dialog_->SetSongs(GetSelectedSongs());
organise_dialog_->show(); organise_dialog_->show();
#endif
} }
#endif #endif

View File

@@ -84,7 +84,7 @@ class CollectionView : public AutoExpandingTreeView {
// QTreeView // QTreeView
void keyboardSearch(const QString &search); void keyboardSearch(const QString &search);
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible); void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);
int TotalSongs(); int TotalSongs();
int TotalArtists(); int TotalArtists();
int TotalAlbums(); int TotalAlbums();
@@ -117,6 +117,7 @@ signals:
void Load(); void Load();
void AddToPlaylist(); void AddToPlaylist();
void AddToPlaylistEnqueue(); void AddToPlaylistEnqueue();
void AddToPlaylistEnqueueNext();
void OpenInNewPlaylist(); void OpenInNewPlaylist();
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
void Organise(); void Organise();
@@ -148,10 +149,13 @@ signals:
QAction *load_; QAction *load_;
QAction *add_to_playlist_; QAction *add_to_playlist_;
QAction *add_to_playlist_enqueue_; QAction *add_to_playlist_enqueue_;
QAction *add_to_playlist_enqueue_next_;
QAction *open_in_new_playlist_; QAction *open_in_new_playlist_;
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
QAction *organise_; QAction *organise_;
#ifndef Q_OS_WIN
QAction *copy_to_device_; QAction *copy_to_device_;
#endif
#endif #endif
QAction *delete_; QAction *delete_;
QAction *edit_track_; QAction *edit_track_;

View File

@@ -76,7 +76,6 @@ CollectionWatcher::CollectionWatcher(QObject *parent)
rescan_paused_(false), rescan_paused_(false),
total_watches_(0), total_watches_(0),
cue_parser_(new CueParser(backend_, this)) { cue_parser_(new CueParser(backend_, this)) {
Utilities::SetThreadIOPriority(Utilities::IOPRIO_CLASS_IDLE);
rescan_timer_->setInterval(1000); rescan_timer_->setInterval(1000);
rescan_timer_->setSingleShot(true); rescan_timer_->setSingleShot(true);

View File

@@ -14,7 +14,7 @@
<string>Collection advanced grouping</string> <string>Collection advanced grouping</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset resource="../../data/data.qrc"> <iconset resource="../../data/icons.qrc">
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset> <normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@@ -358,6 +358,7 @@
</tabstops> </tabstops>
<resources> <resources>
<include location="../../data/data.qrc"/> <include location="../../data/data.qrc"/>
<include location="../../data/icons.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

View File

@@ -106,6 +106,7 @@
</widget> </widget>
<resources> <resources>
<include location="../../data/data.qrc"/> <include location="../../data/data.qrc"/>
<include location="../../data/icons.qrc"/>
</resources> </resources>
<connections> <connections>
<connection> <connection>

View File

@@ -37,7 +37,7 @@ class SqlRow {
SqlRow(const CollectionQuery &query); SqlRow(const CollectionQuery &query);
const QVariant &value(int i) const { return columns_[i]; } const QVariant &value(int i) const { return columns_[i]; }
QList<QVariant> columns_; QList<QVariant> columns_;
private: private:

View File

@@ -1,25 +1,30 @@
/* This file is part of Strawberry. /*
* Strawberry Music Player
Strawberry is free software: you can redistribute it and/or modify * Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
it under the terms of the GNU General Public License as published by *
the Free Software Foundation, either version 3 of the License, or * Strawberry is free software: you can redistribute it and/or modify
(at your option) any later version. * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
Strawberry is distributed in the hope that it will be useful, * (at your option) any later version.
but WITHOUT ANY WARRANTY; without even the implied warranty of *
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * Strawberry is distributed in the hope that it will be useful,
GNU General Public License for more details. * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
You should have received a copy of the GNU General Public License * GNU General Public License for more details.
along with Strawberry. If not, see <http://www.gnu.org/licenses/>. *
*/ * You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONFIG_H_IN #ifndef CONFIG_H_IN
#define CONFIG_H_IN #define CONFIG_H_IN
#define CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}"
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}" #define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
#define CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}" #define CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}"
#cmakedefine DEBUG
#cmakedefine HAVE_GIO #cmakedefine HAVE_GIO
#cmakedefine HAVE_DBUS #cmakedefine HAVE_DBUS
#cmakedefine HAVE_X11 #cmakedefine HAVE_X11
@@ -38,6 +43,7 @@
#cmakedefine HAVE_SPARKLE #cmakedefine HAVE_SPARKLE
#cmakedefine HAVE_CHROMAPRINT #cmakedefine HAVE_CHROMAPRINT
#cmakedefine HAVE_TAGLIB_DSFFILE #cmakedefine HAVE_TAGLIB_DSFFILE
#cmakedefine HAVE_DZMEDIA
#cmakedefine IMOBILEDEVICE_USES_UDIDS #cmakedefine IMOBILEDEVICE_USES_UDIDS
#cmakedefine USE_INSTALL_PREFIX #cmakedefine USE_INSTALL_PREFIX
#cmakedefine USE_SYSTEM_SHA2 #cmakedefine USE_SYSTEM_SHA2
@@ -46,6 +52,10 @@
#cmakedefine HAVE_VLC #cmakedefine HAVE_VLC
#cmakedefine HAVE_XINE #cmakedefine HAVE_XINE
#cmakedefine HAVE_PHONON #cmakedefine HAVE_PHONON
#cmakedefine HAVE_DEEZER
#cmakedefine HAVE_STREAM_TIDAL
#cmakedefine HAVE_STREAM_DEEZER
#endif // CONFIG_H_IN #endif // CONFIG_H_IN

View File

@@ -22,6 +22,7 @@
#include "config.h" #include "config.h"
#include <functional> #include <functional>
#include <algorithm>
#include <QObject> #include <QObject>
#include <QtGlobal> #include <QtGlobal>
@@ -55,6 +56,8 @@
#include "contextalbumsmodel.h" #include "contextalbumsmodel.h"
using std::bind;
using std::sort;
using std::placeholders::_1; using std::placeholders::_1;
using std::placeholders::_2; using std::placeholders::_2;
@@ -93,7 +96,7 @@ void ContextAlbumsModel::set_pretty_covers(bool use_pretty_covers) {
use_pretty_covers_ = use_pretty_covers; use_pretty_covers_ = use_pretty_covers;
Reset(); Reset();
} }
} }
void ContextAlbumsModel::AddSongs(const SongList &songs) { void ContextAlbumsModel::AddSongs(const SongList &songs) {
@@ -479,7 +482,7 @@ void ContextAlbumsModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls,
const_cast<ContextAlbumsModel*>(this)->LazyPopulate(item); const_cast<ContextAlbumsModel*>(this)->LazyPopulate(item);
QList<CollectionItem*> children = item->children; QList<CollectionItem*> children = item->children;
qSort(children.begin(), children.end(), std::bind(&ContextAlbumsModel::CompareItems, this, _1, _2)); std::sort(children.begin(), children.end(), std::bind(&ContextAlbumsModel::CompareItems, this, _1, _2));
for (CollectionItem *child : children) for (CollectionItem *child : children)
GetChildSongs(child, urls, songs, song_ids); GetChildSongs(child, urls, songs, song_ids);

View File

@@ -66,9 +66,12 @@
#include "core/utilities.h" #include "core/utilities.h"
#include "collection/collectionbackend.h" #include "collection/collectionbackend.h"
#include "collection/collectiondirectorymodel.h" #include "collection/collectiondirectorymodel.h"
#include "collection/collectionmodel.h"
#include "collection/collectionitem.h" #include "collection/collectionitem.h"
#include "device/devicemanager.h" #ifndef Q_OS_WIN
#include "device/devicestatefiltermodel.h" # include "device/devicemanager.h"
# include "device/devicestatefiltermodel.h"
#endif
#include "dialogs/edittagdialog.h" #include "dialogs/edittagdialog.h"
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
#include "dialogs/organisedialog.h" #include "dialogs/organisedialog.h"
@@ -152,7 +155,7 @@ void ContextItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
} }
bool ContextItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) { bool ContextItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) {
return true; return true;
Q_UNUSED(option); Q_UNUSED(option);
@@ -263,9 +266,6 @@ void ContextAlbumsView::SaveFocus() {
} }
void ContextAlbumsView::SaveContainerPath(const QModelIndex &child) { void ContextAlbumsView::SaveContainerPath(const QModelIndex &child) {
// return;
QModelIndex current = model()->parent(child); QModelIndex current = model()->parent(child);
QVariant type = model()->data(current, ContextAlbumsModel::Role_Type); QVariant type = model()->data(current, ContextAlbumsModel::Role_Type);
@@ -326,7 +326,7 @@ void ContextAlbumsView::ReloadSettings() {
if (app_ && model_) { if (app_ && model_) {
model_->set_pretty_covers(settings.value("pretty_covers", true).toBool()); model_->set_pretty_covers(settings.value("pretty_covers", true).toBool());
} }
settings.endGroup(); settings.endGroup();
} }
@@ -334,7 +334,7 @@ void ContextAlbumsView::ReloadSettings() {
void ContextAlbumsView::SetApplication(Application *app) { void ContextAlbumsView::SetApplication(Application *app) {
app_ = app; app_ = app;
model_ = new ContextAlbumsModel(app_->collection_backend(), app_, this); model_ = new ContextAlbumsModel(app_->collection_backend(), app_, this);
model_->Reset(); model_->Reset();
@@ -342,7 +342,7 @@ void ContextAlbumsView::SetApplication(Application *app) {
connect(model_, SIGNAL(modelAboutToBeReset()), this, SLOT(SaveFocus())); connect(model_, SIGNAL(modelAboutToBeReset()), this, SLOT(SaveFocus()));
connect(model_, SIGNAL(modelReset()), this, SLOT(RestoreFocus())); connect(model_, SIGNAL(modelReset()), this, SLOT(RestoreFocus()));
ReloadSettings(); ReloadSettings();
} }
@@ -359,7 +359,6 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
if (!context_menu_) { if (!context_menu_) {
context_menu_ = new QMenu(this); context_menu_ = new QMenu(this);
//context_menu_->setStyleSheet("background-color: #3DADE8;");
add_to_playlist_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Append to current playlist"), this, SLOT(AddToPlaylist())); add_to_playlist_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Append to current playlist"), this, SLOT(AddToPlaylist()));
load_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Replace current playlist"), this, SLOT(Load())); load_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Replace current playlist"), this, SLOT(Load()));
@@ -371,7 +370,9 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
context_menu_->addSeparator(); context_menu_->addSeparator();
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise())); organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
#ifndef Q_OS_WIN
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice())); copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
#endif
#endif #endif
context_menu_->addSeparator(); context_menu_->addSeparator();
@@ -381,7 +382,7 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
context_menu_->addSeparator(); context_menu_->addSeparator();
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0); copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool))); connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool)));
#endif #endif
@@ -418,13 +419,17 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
organise_->setVisible(regular_elements_only); organise_->setVisible(regular_elements_only);
#ifndef Q_OS_WIN
copy_to_device_->setVisible(regular_elements_only); copy_to_device_->setVisible(regular_elements_only);
#endif
#endif #endif
// only when all selected items are editable // only when all selected items are editable
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
organise_->setEnabled(regular_elements == regular_editable); organise_->setEnabled(regular_elements == regular_editable);
#ifndef Q_OS_WIN
copy_to_device_->setEnabled(regular_elements == regular_editable); copy_to_device_->setEnabled(regular_elements == regular_editable);
#endif
#endif #endif
context_menu_->popup(e->globalPos()); context_menu_->popup(e->globalPos());
@@ -509,7 +514,7 @@ void ContextAlbumsView::EditTracks() {
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
void ContextAlbumsView::CopyToDevice() { void ContextAlbumsView::CopyToDevice() {
#ifndef Q_OS_WIN
if (!organise_dialog_) if (!organise_dialog_)
organise_dialog_.reset(new OrganiseDialog(app_->task_manager())); organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
@@ -517,7 +522,7 @@ void ContextAlbumsView::CopyToDevice() {
organise_dialog_->SetCopy(true); organise_dialog_->SetCopy(true);
organise_dialog_->SetSongs(GetSelectedSongs()); organise_dialog_->SetSongs(GetSelectedSongs());
organise_dialog_->show(); organise_dialog_->show();
#endif
} }
#endif #endif

View File

@@ -78,7 +78,7 @@ class ContextAlbumsView : public AutoExpandingTreeView {
// QTreeView // QTreeView
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible); void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);
ContextAlbumsModel *albums_model() { return model_; } ContextAlbumsModel *albums_model() { return model_; }
public slots: public slots:
@@ -103,7 +103,9 @@ signals:
void OpenInNewPlaylist(); void OpenInNewPlaylist();
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
void Organise(); void Organise();
//#ifndef Q_OS_WIN
void CopyToDevice(); void CopyToDevice();
//#endif
#endif #endif
void EditTracks(); void EditTracks();
void ShowInBrowser(); void ShowInBrowser();
@@ -124,7 +126,9 @@ signals:
QAction *open_in_new_playlist_; QAction *open_in_new_playlist_;
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
QAction *organise_; QAction *organise_;
#ifndef Q_OS_WIN
QAction *copy_to_device_; QAction *copy_to_device_;
#endif
#endif #endif
QAction *delete_; QAction *delete_;
QAction *edit_track_; QAction *edit_track_;
@@ -142,9 +146,9 @@ signals:
Song last_selected_song_; Song last_selected_song_;
QString last_selected_container_; QString last_selected_container_;
QSet<QString> last_selected_path_; QSet<QString> last_selected_path_;
ContextAlbumsModel *model_; ContextAlbumsModel *model_;
}; };
#endif // CONTEXTALBUMSVIEW_H #endif // CONTEXTALBUMSVIEW_H

View File

@@ -82,7 +82,8 @@ ContextView::ContextView(QWidget *parent) :
timeline_fade_(new QTimeLine(1000, this)), timeline_fade_(new QTimeLine(1000, this)),
image_strawberry_(":/pictures/strawberry.png"), image_strawberry_(":/pictures/strawberry.png"),
active_(false), active_(false),
downloading_covers_(false) downloading_covers_(false),
lyrics_id_(-1)
{ {
ui_->setupUi(this); ui_->setupUi(this);
@@ -132,7 +133,7 @@ void ContextView::AddActions() {
action_show_output_ = new QAction(tr("Show engine and device"), this); action_show_output_ = new QAction(tr("Show engine and device"), this);
action_show_output_->setCheckable(true); action_show_output_->setCheckable(true);
action_show_output_->setChecked(true); action_show_output_->setChecked(true);
action_show_albums_ = new QAction(tr("Show albums by artist"), this); action_show_albums_ = new QAction(tr("Show albums by artist"), this);
action_show_albums_->setCheckable(true); action_show_albums_->setCheckable(true);
@@ -140,7 +141,7 @@ void ContextView::AddActions() {
action_show_lyrics_ = new QAction(tr("Show song lyrics"), this); action_show_lyrics_ = new QAction(tr("Show song lyrics"), this);
action_show_lyrics_->setCheckable(true); action_show_lyrics_->setCheckable(true);
action_show_lyrics_->setChecked(false); action_show_lyrics_->setChecked(false);
menu_->addAction(action_show_data_); menu_->addAction(action_show_data_);
menu_->addAction(action_show_output_); menu_->addAction(action_show_output_);
@@ -173,10 +174,10 @@ void ContextView::Playing() {}
void ContextView::Stopped() { void ContextView::Stopped() {
active_ = false; active_ = false;
song_playing_ = song_empty_; song_playing_ = Song();
song_ = song_empty_; song_ = Song();
downloading_covers_ = false; downloading_covers_ = false;
prev_artist_ = QString(); song_prev_ = Song();
lyrics_ = QString(); lyrics_ = QString();
SetImage(image_strawberry_); SetImage(image_strawberry_);
@@ -190,21 +191,40 @@ void ContextView::UpdateNoSong() {
void ContextView::SongChanged(const Song &song) { void ContextView::SongChanged(const Song &song) {
image_previous_ = image_original_; if (song_playing_.is_valid() && song.id() == song_playing_.id() && song.url() == song_playing_.url()) {
prev_artist_ = song_playing_.artist(); UpdateSong(song);
lyrics_ = song.lyrics(); }
song_playing_ = song; else {
song_ = song; song_prev_ = song_playing_;
UpdateSong(); lyrics_ = song.lyrics();
update(); lyrics_id_ = -1;
if (action_show_lyrics_->isChecked()) lyrics_fetcher_->Search(song.artist(), song.album(), song.title()); song_playing_ = song;
song_ = song;
SetSong(song);
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked()) {
lyrics_fetcher_->Clear();
lyrics_id_ = lyrics_fetcher_->Search(song.artist(), song.album(), song.title());
}
}
} }
void ContextView::SetText(QLabel *label, int value, const QString &suffix, const QString &def) { void ContextView::SetLabelEnabled(QLabel *label) {
label->setEnabled(true);
label->setVisible(true);
label->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
void ContextView::SetLabelText(QLabel *label, int value, const QString &suffix, const QString &def) {
label->setText(value <= 0 ? def : (QString::number(value) + " " + suffix)); label->setText(value <= 0 ? def : (QString::number(value) + " " + suffix));
} }
void ContextView::SetLabelDisabled(QLabel *label) {
label->setEnabled(false);
label->setVisible(false);
label->setMaximumSize(0, 0);
}
void ContextView::NoSong() { void ContextView::NoSong() {
ui_->label_stop_top->setStyleSheet( ui_->label_stop_top->setStyleSheet(
@@ -232,7 +252,7 @@ void ContextView::NoSong() {
} }
void ContextView::UpdateSong() { void ContextView::SetSong(const Song &song) {
QList <QLabel *> labels_play_data; QList <QLabel *> labels_play_data;
@@ -251,85 +271,58 @@ void ContextView::UpdateSong() {
"font: 11pt;" "font: 11pt;"
"font-weight: regular;" "font-weight: regular;"
); );
ui_->label_play_top->setText( QString("<b>%1 - %2</b><br/>%3").arg(song_.PrettyTitle().toHtmlEscaped(), song_.artist().toHtmlEscaped(), song_.album().toHtmlEscaped())); ui_->label_play_top->setText( QString("<b>%1 - %2</b><br/>%3").arg(song.PrettyTitle().toHtmlEscaped(), song.artist().toHtmlEscaped(), song.album().toHtmlEscaped()));
if (action_show_data_->isChecked()) { if (action_show_data_->isChecked()) {
for (QLabel *l : labels_play_data) {
l->setEnabled(true);
l->setVisible(true);
l->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
}
ui_->layout_play_data->setEnabled(true); ui_->layout_play_data->setEnabled(true);
ui_->filetype->setText(song_.TextForFiletype()); SetLabelEnabled(ui_->label_filetype);
ui_->length->setText(Utilities::PrettyTimeNanosec(song_.length_nanosec())); SetLabelEnabled(ui_->filetype);
if (song_.samplerate() <= 0) { SetLabelEnabled(ui_->label_length);
ui_->label_samplerate->setEnabled(false); SetLabelEnabled(ui_->length);
ui_->label_samplerate->setVisible(false); ui_->filetype->setText(song.TextForFiletype());
ui_->label_samplerate->setMaximumSize(0, 0); ui_->length->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
ui_->samplerate->setEnabled(false); if (song.samplerate() <= 0) {
ui_->samplerate->setVisible(false); SetLabelDisabled(ui_->label_samplerate);
ui_->samplerate->setMaximumSize(0, 0); SetLabelDisabled(ui_->samplerate);
ui_->samplerate->clear(); ui_->samplerate->clear();
} }
else { else {
ui_->label_samplerate->setEnabled(true); SetLabelEnabled(ui_->label_samplerate);
ui_->label_samplerate->setVisible(true); SetLabelEnabled(ui_->samplerate);
ui_->label_samplerate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); SetLabelText(ui_->samplerate, song.samplerate(), "Hz");
ui_->samplerate->setEnabled(true);
ui_->samplerate->setVisible(true);
ui_->samplerate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
SetText(ui_->samplerate, song_.samplerate(), "Hz");
} }
if (song_.bitdepth() <= 0) { if (song.bitdepth() <= 0) {
ui_->label_bitdepth->setEnabled(false); SetLabelDisabled(ui_->label_bitdepth);
ui_->label_bitdepth->setVisible(false); SetLabelDisabled(ui_->bitdepth);
ui_->label_bitdepth->setMaximumSize(0, 0);
ui_->bitdepth->setEnabled(false);
ui_->bitdepth->setVisible(false);
ui_->bitdepth->setMaximumSize(0, 0);
ui_->bitdepth->clear(); ui_->bitdepth->clear();
} }
else { else {
ui_->label_bitdepth->setEnabled(true); SetLabelEnabled(ui_->label_bitdepth);
ui_->label_bitdepth->setVisible(true); SetLabelEnabled(ui_->bitdepth);
ui_->label_bitdepth->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); SetLabelText(ui_->bitdepth, song.bitdepth(), "Bit");
ui_->bitdepth->setEnabled(true);
ui_->bitdepth->setVisible(true);
ui_->bitdepth->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
SetText(ui_->bitdepth, song_.bitdepth(), "Bit");
} }
if (song_.bitrate() <= 0) { if (song.bitrate() <= 0) {
ui_->label_bitrate->setEnabled(false); SetLabelDisabled(ui_->label_bitrate);
ui_->label_bitrate->setVisible(false); SetLabelDisabled(ui_->bitrate);
ui_->label_bitrate->setMaximumSize(0, 0);
ui_->bitrate->setEnabled(false);
ui_->bitrate->setVisible(false);
ui_->bitrate->setMaximumSize(0, 0);
ui_->bitrate->clear(); ui_->bitrate->clear();
} }
else { else {
ui_->label_bitrate->setEnabled(true); SetLabelEnabled(ui_->label_bitrate);
ui_->label_bitrate->setVisible(true); SetLabelEnabled(ui_->bitrate);
ui_->label_bitrate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX); SetLabelText(ui_->bitrate, song.bitrate(), tr("kbps"));
ui_->bitrate->setEnabled(true);
ui_->bitrate->setVisible(true);
ui_->bitrate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
SetText(ui_->bitrate, song_.bitrate(), tr("kbps"));
} }
ui_->spacer_play_data->changeSize(20, 20, QSizePolicy::Fixed); ui_->spacer_play_data->changeSize(20, 20, QSizePolicy::Fixed);
} }
else { else {
for (QLabel *l : labels_play_data) {
l->setEnabled(false);
l->setVisible(false);
l->setMaximumSize(0, 0);
}
ui_->layout_play_data->setEnabled(false);
ui_->filetype->clear(); ui_->filetype->clear();
ui_->length->clear(); ui_->length->clear();
ui_->samplerate->clear(); ui_->samplerate->clear();
ui_->bitdepth->clear(); ui_->bitdepth->clear();
ui_->bitrate->clear(); ui_->bitrate->clear();
for (QLabel *l : labels_play_data) {
SetLabelDisabled(l);
}
ui_->layout_play_data->setEnabled(false);
ui_->spacer_play_data->changeSize(0, 0, QSizePolicy::Fixed); ui_->spacer_play_data->changeSize(0, 0, QSizePolicy::Fixed);
} }
@@ -403,18 +396,18 @@ void ContextView::UpdateSong() {
ui_->device->setMaximumSize(0, 0); ui_->device->setMaximumSize(0, 0);
} }
if (action_show_albums_->isChecked() && prev_artist_ != song_.artist()) { if (action_show_albums_->isChecked() && song_prev_.artist() != song.artist()) {
const QueryOptions opt; const QueryOptions opt;
CollectionBackend::AlbumList albumlist; CollectionBackend::AlbumList albumlist;
ui_->widget_play_albums->albums_model()->Reset(); ui_->widget_play_albums->albums_model()->Reset();
albumlist = app_->collection_backend()->GetAlbumsByArtist(song_.artist(), opt); albumlist = app_->collection_backend()->GetAlbumsByArtist(song.artist(), opt);
if (albumlist.count() > 1) { if (albumlist.count() > 1) {
ui_->label_play_albums->setVisible(true); ui_->label_play_albums->setVisible(true);
ui_->label_play_albums->setMinimumSize(0, 20); ui_->label_play_albums->setMinimumSize(0, 20);
ui_->label_play_albums->setText(QString("<b>Albums by %1</b>").arg( song_.artist().toHtmlEscaped())); ui_->label_play_albums->setText(QString("<b>Albums by %1</b>").arg( song.artist().toHtmlEscaped()));
ui_->label_play_albums->setStyleSheet("background-color: #3DADE8; color: rgb(255, 255, 255); font: 11pt;"); ui_->label_play_albums->setStyleSheet("background-color: #3DADE8; color: rgb(255, 255, 255); font: 11pt;");
for (CollectionBackend::Album album : albumlist) { for (CollectionBackend::Album album : albumlist) {
SongList songs = app_->collection_backend()->GetSongs(song_.artist(), album.album_name, opt); SongList songs = app_->collection_backend()->GetSongs(song.artist(), album.album_name, opt);
ui_->widget_play_albums->albums_model()->AddSongs(songs); ui_->widget_play_albums->albums_model()->AddSongs(songs);
} }
ui_->widget_play_albums->setEnabled(true); ui_->widget_play_albums->setEnabled(true);
@@ -454,9 +447,62 @@ void ContextView::UpdateSong() {
} }
void ContextView::UpdateSong(const Song &song) {
if (song.artist() != song_playing_.artist() || song.album() != song_playing_.album() || song.title() != song_playing_.title()) {
ui_->label_play_top->setText( QString("<b>%1 - %2</b><br/>%3").arg(song.PrettyTitle().toHtmlEscaped(), song.artist().toHtmlEscaped(), song.album().toHtmlEscaped()));
}
if (action_show_data_->isChecked()) {
if (song.filetype() != song_playing_.filetype()) ui_->filetype->setText(song.TextForFiletype());
if (song.length_nanosec() != song_playing_.length_nanosec()) ui_->label_length->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
if (song.samplerate() != song_playing_.samplerate()) {
if (song.samplerate() <= 0) {
SetLabelDisabled(ui_->label_samplerate);
SetLabelDisabled(ui_->samplerate);
ui_->samplerate->clear();
}
else {
SetLabelEnabled(ui_->label_samplerate);
SetLabelEnabled(ui_->samplerate);
SetLabelText(ui_->samplerate, song.samplerate(), "Hz");
}
}
if (song.bitdepth() != song_playing_.bitdepth()) {
if (song.bitdepth() <= 0) {
SetLabelDisabled(ui_->label_bitdepth);
SetLabelDisabled(ui_->bitdepth);
ui_->bitdepth->clear();
}
else {
SetLabelEnabled(ui_->label_bitdepth);
SetLabelEnabled(ui_->bitdepth);
SetLabelText(ui_->bitdepth, song.bitdepth(), "Bit");
}
}
if (song.bitrate() != song_playing_.bitrate()) {
if (song.bitrate() <= 0) {
SetLabelDisabled(ui_->label_bitrate);
SetLabelDisabled(ui_->bitrate);
ui_->bitrate->clear();
}
else {
SetLabelEnabled(ui_->label_bitrate);
SetLabelEnabled(ui_->bitrate);
SetLabelText(ui_->bitrate, song.bitrate(), tr("kbps"));
}
}
}
song_playing_ = song;
song_ = song;
}
void ContextView::UpdateLyrics(quint64 id, const QString lyrics) { void ContextView::UpdateLyrics(quint64 id, const QString lyrics) {
if (id != lyrics_id_) return;
lyrics_ = lyrics; lyrics_ = lyrics;
lyrics_id_ = -1;
if (action_show_lyrics_->isChecked()) { if (action_show_lyrics_->isChecked()) {
ui_->label_play_lyrics->setText(lyrics); ui_->label_play_lyrics->setText(lyrics);
} }
@@ -466,13 +512,13 @@ void ContextView::UpdateLyrics(quint64 id, const QString lyrics) {
bool ContextView::eventFilter(QObject *object, QEvent *event) { bool ContextView::eventFilter(QObject *object, QEvent *event) {
switch(event->type()) { switch(event->type()) {
case QEvent::Paint:{ case QEvent::Paint:{
handlePaintEvent(object, event); handlePaintEvent(object, event);
} }
default:{ default:{
return QObject::eventFilter(object, event); return QObject::eventFilter(object, event);
} }
} }
return(true); return(true);
@@ -484,7 +530,7 @@ void ContextView::handlePaintEvent(QObject *object, QEvent *event) {
if (object == ui_->label_play_album) { if (object == ui_->label_play_album) {
PaintEventAlbum(event); PaintEventAlbum(event);
} }
return; return;
} }
@@ -551,7 +597,9 @@ void ContextView::ScaleCover() {
void ContextView::AlbumArtLoaded(const Song &song, const QString&, const QImage &image) { void ContextView::AlbumArtLoaded(const Song &song, const QString&, const QImage &image) {
if (song.id() != song_playing_.id() || song.url() != song_playing_.url()) return;
if (song.effective_albumartist() != song_playing_.effective_albumartist() || song.effective_album() != song_playing_.effective_album() || song.title() != song_playing_.title()) return; if (song.effective_albumartist() != song_playing_.effective_albumartist() || song.effective_album() != song_playing_.effective_album() || song.title() != song_playing_.title()) return;
if (image == image_original_) return;
active_ = true; active_ = true;
downloading_covers_ = false; downloading_covers_ = false;
@@ -572,6 +620,7 @@ void ContextView::SetImage(const QImage &image) {
DrawImage(&p); DrawImage(&p);
p.end(); p.end();
image_previous_ = image_original_;
image_original_ = image; image_original_ = image;
ScaleCover(); ScaleCover();
@@ -623,7 +672,7 @@ void ContextView::ActionShowData() {
s.beginGroup(kSettingsGroup); s.beginGroup(kSettingsGroup);
s.setValue("show_data", action_show_data_->isChecked()); s.setValue("show_data", action_show_data_->isChecked());
s.endGroup(); s.endGroup();
UpdateSong(); SetSong(song_);
} }
void ContextView::ActionShowOutput() { void ContextView::ActionShowOutput() {
@@ -631,7 +680,7 @@ void ContextView::ActionShowOutput() {
s.beginGroup(kSettingsGroup); s.beginGroup(kSettingsGroup);
s.setValue("show_output", action_show_output_->isChecked()); s.setValue("show_output", action_show_output_->isChecked());
s.endGroup(); s.endGroup();
UpdateSong(); SetSong(song_);
} }
void ContextView::ActionShowAlbums() { void ContextView::ActionShowAlbums() {
@@ -639,8 +688,8 @@ void ContextView::ActionShowAlbums() {
s.beginGroup(kSettingsGroup); s.beginGroup(kSettingsGroup);
s.setValue("show_albums", action_show_albums_->isChecked()); s.setValue("show_albums", action_show_albums_->isChecked());
s.endGroup(); s.endGroup();
prev_artist_ = QString(); song_prev_ = Song();
UpdateSong(); SetSong(song_);
} }
void ContextView::ActionShowLyrics() { void ContextView::ActionShowLyrics() {
@@ -648,8 +697,11 @@ void ContextView::ActionShowLyrics() {
s.beginGroup(kSettingsGroup); s.beginGroup(kSettingsGroup);
s.setValue("show_lyrics", action_show_lyrics_->isChecked()); s.setValue("show_lyrics", action_show_lyrics_->isChecked());
s.endGroup(); s.endGroup();
UpdateSong(); SetSong(song_);
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked()) lyrics_fetcher_->Search(song_.artist(), song_.album(), song_.title()); if (lyrics_.isEmpty() && action_show_lyrics_->isChecked()) {
lyrics_fetcher_->Clear();
lyrics_id_ = lyrics_fetcher_->Search(song_.artist(), song_.album(), song_.title());
}
} }
void ContextView::SearchCoverAutomatically() { void ContextView::SearchCoverAutomatically() {

View File

@@ -94,21 +94,23 @@ class ContextView : public QWidget {
AlbumCoverLoaderOptions cover_loader_options_; AlbumCoverLoaderOptions cover_loader_options_;
Song song_; Song song_;
Song song_playing_; Song song_playing_;
Song song_empty_; Song song_prev_;
QImage image_original_; QImage image_original_;
QImage image_previous_; QImage image_previous_;
QPixmap pixmap_current_; QPixmap pixmap_current_;
QPixmap pixmap_previous_; QPixmap pixmap_previous_;
qreal pixmap_previous_opacity_; qreal pixmap_previous_opacity_;
std::unique_ptr<QMovie> spinner_animation_; std::unique_ptr<QMovie> spinner_animation_;
qint64 lyrics_id_;
QString prev_artist_;
QString lyrics_; QString lyrics_;
void AddActions(); void AddActions();
void SetText(QLabel *label, int value, const QString &suffix, const QString &def = QString()); void SetLabelEnabled(QLabel *label);
void SetLabelDisabled(QLabel *label);
void SetLabelText(QLabel *label, int value, const QString &suffix, const QString &def = QString());
void NoSong(); void NoSong();
void UpdateSong(); void SetSong(const Song &song);
void UpdateSong(const Song &song);
void SetImage(const QImage &image); void SetImage(const QImage &image);
void DrawImage(QPainter *p); void DrawImage(QPainter *p);
void ScaleCover(); void ScaleCover();

View File

@@ -562,6 +562,7 @@
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../../data/data.qrc"/> <include location="../../data/data.qrc"/>
<include location="../../data/icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

View File

@@ -26,11 +26,13 @@
#include <QObject> #include <QObject>
#include <QThread> #include <QThread>
#include <QVariant>
#include <QString> #include <QString>
#include "core/closure.h" #include "core/closure.h"
#include "core/lazy.h" #include "core/lazy.h"
#include "core/tagreaderclient.h" #include "core/tagreaderclient.h"
#include "core/song.h"
#include "database.h" #include "database.h"
#include "taskmanager.h" #include "taskmanager.h"
@@ -38,7 +40,9 @@
#include "appearance.h" #include "appearance.h"
#include "engine/enginedevice.h" #include "engine/enginedevice.h"
#include "device/devicemanager.h" #ifndef Q_OS_WIN
# include "device/devicemanager.h"
#endif
#include "collection/collection.h" #include "collection/collection.h"
#include "playlist/playlistbackend.h" #include "playlist/playlistbackend.h"
#include "playlist/playlistmanager.h" #include "playlist/playlistmanager.h"
@@ -48,7 +52,6 @@
#ifdef HAVE_LIBLASTFM #ifdef HAVE_LIBLASTFM
#include "covermanager/lastfmcoverprovider.h" #include "covermanager/lastfmcoverprovider.h"
#endif #endif
//#include "covermanager/amazoncoverprovider.h"
#include "covermanager/discogscoverprovider.h" #include "covermanager/discogscoverprovider.h"
#include "covermanager/musicbrainzcoverprovider.h" #include "covermanager/musicbrainzcoverprovider.h"
@@ -57,8 +60,15 @@
#include "lyrics/auddlyricsprovider.h" #include "lyrics/auddlyricsprovider.h"
#include "lyrics/apiseedslyricsprovider.h" #include "lyrics/apiseedslyricsprovider.h"
#include "internet/internetmodel.h" #include "internet/internetservices.h"
#include "tidal/tidalsearch.h" #include "internet/internetsearch.h"
#ifdef HAVE_STREAM_TIDAL
# include "tidal/tidalservice.h"
#endif
#ifdef HAVE_STREAM_DEEZER
# include "deezer/deezerservice.h"
#endif
bool Application::kIsPortable = false; bool Application::kIsPortable = false;
@@ -81,7 +91,9 @@ class ApplicationImpl {
task_manager_([=]() { return new TaskManager(app); }), task_manager_([=]() { return new TaskManager(app); }),
player_([=]() { return new Player(app, app); }), player_([=]() { return new Player(app, app); }),
enginedevice_([=]() { return new EngineDevice(app); }), enginedevice_([=]() { return new EngineDevice(app); }),
#ifndef Q_OS_WIN
device_manager_([=]() { return new DeviceManager(app, app); }), device_manager_([=]() { return new DeviceManager(app, app); }),
#endif
collection_([=]() { return new SCollection(app, app); }), collection_([=]() { return new SCollection(app, app); }),
playlist_backend_([=]() { playlist_backend_([=]() {
PlaylistBackend *backend = new PlaylistBackend(app, app); PlaylistBackend *backend = new PlaylistBackend(app, app);
@@ -95,7 +107,6 @@ class ApplicationImpl {
#ifdef HAVE_LIBLASTFM #ifdef HAVE_LIBLASTFM
cover_providers->AddProvider(new LastFmCoverProvider(app)); cover_providers->AddProvider(new LastFmCoverProvider(app));
#endif #endif
//cover_providers->AddProvider(new AmazonCoverProvider(app));
cover_providers->AddProvider(new DiscogsCoverProvider(app)); cover_providers->AddProvider(new DiscogsCoverProvider(app));
cover_providers->AddProvider(new MusicbrainzCoverProvider(app)); cover_providers->AddProvider(new MusicbrainzCoverProvider(app));
return cover_providers; return cover_providers;
@@ -106,15 +117,30 @@ class ApplicationImpl {
return loader; return loader;
}), }),
current_art_loader_([=]() { return new CurrentArtLoader(app, app); }), current_art_loader_([=]() { return new CurrentArtLoader(app, app); }),
internet_model_([=]() { return new InternetModel(app, app); }),
tidal_search_([=]() { return new TidalSearch(app, app); }),
lyrics_providers_([=]() { lyrics_providers_([=]() {
LyricsProviders *lyrics_providers = new LyricsProviders(app); LyricsProviders *lyrics_providers = new LyricsProviders(app);
lyrics_providers->AddProvider(new AuddLyricsProvider(app)); lyrics_providers->AddProvider(new AuddLyricsProvider(app));
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app)); lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
return lyrics_providers; return lyrics_providers;
}) }),
{ } internet_services_([=]() {
InternetServices *internet_services = new InternetServices(app);
#ifdef HAVE_STREAM_TIDAL
internet_services->AddService(new TidalService(app, internet_services));
#endif
#ifdef HAVE_STREAM_DEEZER
internet_services->AddService(new DeezerService(app, internet_services));
#endif
return internet_services;
}),
#ifdef HAVE_STREAM_TIDAL
tidal_search_([=]() { return new InternetSearch(app, Song::Source_Tidal, app); }),
#endif
#ifdef HAVE_STREAM_DEEZER
deezer_search_([=]() { return new InternetSearch(app, Song::Source_Deezer, app); }),
#endif
dummy_([=]() { return new QVariant; })
{}
Lazy<TagReaderClient> tag_reader_client_; Lazy<TagReaderClient> tag_reader_client_;
Lazy<Database> database_; Lazy<Database> database_;
@@ -122,16 +148,24 @@ class ApplicationImpl {
Lazy<TaskManager> task_manager_; Lazy<TaskManager> task_manager_;
Lazy<Player> player_; Lazy<Player> player_;
Lazy<EngineDevice> enginedevice_; Lazy<EngineDevice> enginedevice_;
#ifndef Q_OS_WIN
Lazy<DeviceManager> device_manager_; Lazy<DeviceManager> device_manager_;
#endif
Lazy<SCollection> collection_; Lazy<SCollection> collection_;
Lazy<PlaylistBackend> playlist_backend_; Lazy<PlaylistBackend> playlist_backend_;
Lazy<PlaylistManager> playlist_manager_; Lazy<PlaylistManager> playlist_manager_;
Lazy<CoverProviders> cover_providers_; Lazy<CoverProviders> cover_providers_;
Lazy<AlbumCoverLoader> album_cover_loader_; Lazy<AlbumCoverLoader> album_cover_loader_;
Lazy<CurrentArtLoader> current_art_loader_; Lazy<CurrentArtLoader> current_art_loader_;
Lazy<InternetModel> internet_model_;
Lazy<TidalSearch> tidal_search_;
Lazy<LyricsProviders> lyrics_providers_; Lazy<LyricsProviders> lyrics_providers_;
Lazy<InternetServices> internet_services_;
#ifdef HAVE_STREAM_TIDAL
Lazy<InternetSearch> tidal_search_;
#endif
#ifdef HAVE_STREAM_DEEZER
Lazy<InternetSearch> deezer_search_;
#endif
Lazy<QVariant> dummy_;
}; };
@@ -148,7 +182,9 @@ Application::~Application() {
// It's important that the device manager is deleted before the database. // It's important that the device manager is deleted before the database.
// Deleting the database deletes all objects that have been created in its thread, including some device collection backends. // Deleting the database deletes all objects that have been created in its thread, including some device collection backends.
#ifndef Q_OS_WIN
p_->device_manager_.reset(); p_->device_manager_.reset();
#endif
for (QThread *thread : threads_) { for (QThread *thread : threads_) {
thread->quit(); thread->quit();
@@ -175,71 +211,31 @@ void Application::MoveToThread(QObject *object, QThread *thread) {
} }
void Application::AddError(const QString& message) { emit ErrorAdded(message); } void Application::AddError(const QString& message) { emit ErrorAdded(message); }
void Application::ReloadSettings() { emit SettingsChanged(); } void Application::ReloadSettings() { emit SettingsChanged(); }
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { emit SettingsDialogRequested(page); }
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { TagReaderClient *Application::tag_reader_client() const { return p_->tag_reader_client_.get(); }
emit SettingsDialogRequested(page);
}
AlbumCoverLoader *Application::album_cover_loader() const {
return p_->album_cover_loader_.get();
}
Appearance *Application::appearance() const { return p_->appearance_.get(); } Appearance *Application::appearance() const { return p_->appearance_.get(); }
CoverProviders *Application::cover_providers() const {
return p_->cover_providers_.get();
}
CurrentArtLoader *Application::current_art_loader() const {
return p_->current_art_loader_.get();
}
Database *Application::database() const { return p_->database_.get(); } Database *Application::database() const { return p_->database_.get(); }
TaskManager *Application::task_manager() const { return p_->task_manager_.get(); }
DeviceManager *Application::device_manager() const {
return p_->device_manager_.get();
}
SCollection *Application::collection() const { return p_->collection_.get(); }
CollectionBackend *Application::collection_backend() const {
return collection()->backend();
}
CollectionModel *Application::collection_model() const { return collection()->model(); }
Player *Application::player() const { return p_->player_.get(); } Player *Application::player() const { return p_->player_.get(); }
EngineDevice *Application::enginedevice() const { return p_->enginedevice_.get(); }
PlaylistBackend *Application::playlist_backend() const { #ifndef Q_OS_WIN
return p_->playlist_backend_.get(); DeviceManager *Application::device_manager() const { return p_->device_manager_.get(); }
} #endif
SCollection *Application::collection() const { return p_->collection_.get(); }
PlaylistManager *Application::playlist_manager() const { CollectionBackend *Application::collection_backend() const { return collection()->backend(); }
return p_->playlist_manager_.get(); CollectionModel *Application::collection_model() const { return collection()->model(); }
} AlbumCoverLoader *Application::album_cover_loader() const { return p_->album_cover_loader_.get(); }
CoverProviders *Application::cover_providers() const { return p_->cover_providers_.get(); }
TagReaderClient *Application::tag_reader_client() const { CurrentArtLoader *Application::current_art_loader() const { return p_->current_art_loader_.get(); }
return p_->tag_reader_client_.get(); LyricsProviders *Application::lyrics_providers() const { return p_->lyrics_providers_.get(); }
} PlaylistBackend *Application::playlist_backend() const { return p_->playlist_backend_.get(); }
PlaylistManager *Application::playlist_manager() const { return p_->playlist_manager_.get(); }
TaskManager *Application::task_manager() const { InternetServices *Application::internet_services() const { return p_->internet_services_.get(); }
return p_->task_manager_.get(); #ifdef HAVE_STREAM_TIDAL
} InternetSearch *Application::tidal_search() const { return p_->tidal_search_.get(); }
#endif
EngineDevice *Application::enginedevice() const { #ifdef HAVE_STREAM_DEEZER
return p_->enginedevice_.get(); InternetSearch *Application::deezer_search() const { return p_->deezer_search_.get(); }
} #endif
InternetModel* Application::internet_model() const {
return p_->internet_model_.get();
}
TidalSearch* Application::tidal_search() const {
return p_->tidal_search_.get();
}
LyricsProviders *Application::lyrics_providers() const {
return p_->lyrics_providers_.get();
}

View File

@@ -33,6 +33,8 @@
#include "settings/settingsdialog.h" #include "settings/settingsdialog.h"
using std::unique_ptr;
class TaskManager; class TaskManager;
class ApplicationImpl; class ApplicationImpl;
class TagReaderClient; class TagReaderClient;
@@ -45,13 +47,15 @@ class CollectionBackend;
class CollectionModel; class CollectionModel;
class PlaylistBackend; class PlaylistBackend;
class PlaylistManager; class PlaylistManager;
#ifndef Q_OS_WIN
class DeviceManager; class DeviceManager;
#endif
class CoverProviders; class CoverProviders;
class AlbumCoverLoader; class AlbumCoverLoader;
class CurrentArtLoader; class CurrentArtLoader;
class InternetModel;
class TidalSearch;
class LyricsProviders; class LyricsProviders;
class InternetServices;
class InternetSearch;
class Application : public QObject { class Application : public QObject {
Q_OBJECT Q_OBJECT
@@ -68,9 +72,13 @@ class Application : public QObject {
TaskManager *task_manager() const; TaskManager *task_manager() const;
Player *player() const; Player *player() const;
EngineDevice *enginedevice() const; EngineDevice *enginedevice() const;
#ifndef Q_OS_WIN
DeviceManager *device_manager() const; DeviceManager *device_manager() const;
#endif
SCollection *collection() const; SCollection *collection() const;
CollectionBackend *collection_backend() const;
CollectionModel *collection_model() const;
PlaylistBackend *playlist_backend() const; PlaylistBackend *playlist_backend() const;
PlaylistManager *playlist_manager() const; PlaylistManager *playlist_manager() const;
@@ -79,14 +87,16 @@ class Application : public QObject {
AlbumCoverLoader *album_cover_loader() const; AlbumCoverLoader *album_cover_loader() const;
CurrentArtLoader *current_art_loader() const; CurrentArtLoader *current_art_loader() const;
CollectionBackend *collection_backend() const;
CollectionModel *collection_model() const;
InternetModel *internet_model() const;
TidalSearch *tidal_search() const;
LyricsProviders *lyrics_providers() const; LyricsProviders *lyrics_providers() const;
InternetServices *internet_services() const;
#ifdef HAVE_STREAM_TIDAL
InternetSearch *tidal_search() const;
#endif
#ifdef HAVE_STREAM_DEEZER
InternetSearch *deezer_search() const;
#endif
void MoveToNewThread(QObject *object); void MoveToNewThread(QObject *object);
void MoveToThread(QObject *object, QThread *thread); void MoveToThread(QObject *object, QThread *thread);

View File

@@ -1,105 +0,0 @@
/*
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2011, David Sansome <me@davidsansome.com>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CACHEDLIST_H
#define CACHEDLIST_H
#include "config.h"
#include <QList>
#include <QString>
#include <QDateTime>
#include <QSettings>
template <typename T>
class CachedList {
public:
// Use a CachedList when you want to download and save a list of things from a
// remote service, updating it only periodically.
// T must be a registered metatype and must support being stored in
// QSettings. This usually means you have to implement QDataStream streaming
// operators, and use qRegisterMetaTypeStreamOperators.
typedef QList<T> ListType;
CachedList(const QString &settings_group, const QString &name, int cache_duration_secs)
: settings_group_(settings_group), name_(name), cache_duration_secs_(cache_duration_secs) {
}
void Load() {
QSettings s;
s.beginGroup(settings_group_);
last_updated_ = s.value("last_refreshed_" + name_).toDateTime();
data_.clear();
const int count = s.beginReadArray(name_ + "_data");
for (int i = 0; i < count; ++i) {
s.setArrayIndex(i);
data_ << s.value("value").value<T>();
}
s.endArray();
}
void Save() const {
QSettings s;
s.beginGroup(settings_group_);
s.setValue("last_refreshed_" + name_, last_updated_);
s.beginWriteArray(name_ + "_data", data_.size());
for (int i = 0; i < data_.size(); ++i) {
s.setArrayIndex(i);
s.setValue("value", QVariant::fromValue(data_[i]));
}
s.endArray();
}
void Update(const ListType &data) {
data_ = data;
last_updated_ = QDateTime::currentDateTime();
Save();
}
bool IsStale() const {
return last_updated_.isNull() || last_updated_.secsTo(QDateTime::currentDateTime()) > cache_duration_secs_;
}
void Sort() { qSort(data_); }
const ListType &Data() const { return data_; }
operator ListType() const { return data_; }
// Q_FOREACH support
typedef typename ListType::const_iterator const_iterator;
const_iterator begin() const { return data_.begin(); }
const_iterator end() const { return data_.end(); }
private:
const QString settings_group_;
const QString name_;
const int cache_duration_secs_;
QDateTime last_updated_;
ListType data_;
};
#endif // CACHEDLIST_H

View File

@@ -62,7 +62,7 @@ Database::Token::Token(const QString &token, int start, int end)
: token(token), start_offset(start), end_offset(end) {} : token(token), start_offset(start), end_offset(end) {}
struct sqlite3_tokenizer_module { struct sqlite3_tokenizer_module {
int iVersion; int iVersion;
int (*xCreate)(int argc, /* Size of argv array */ int (*xCreate)(int argc, /* Size of argv array */
const char *const *argv, /* Tokenizer argument strings */ const char *const *argv, /* Tokenizer argument strings */
@@ -106,7 +106,7 @@ int Database::FTSCreate(int argc, const char *const *argv, sqlite3_tokenizer **t
} }
int Database::FTSDestroy(sqlite3_tokenizer *tokenizer) { int Database::FTSDestroy(sqlite3_tokenizer *tokenizer) {
UnicodeTokenizer *real_tokenizer = reinterpret_cast<UnicodeTokenizer*>(tokenizer); UnicodeTokenizer *real_tokenizer = reinterpret_cast<UnicodeTokenizer*>(tokenizer);
delete real_tokenizer; delete real_tokenizer;
return SQLITE_OK; return SQLITE_OK;
@@ -283,7 +283,11 @@ QSqlDatabase Database::Connect() {
QVariant v = db.driver()->handle(); QVariant v = db.driver()->handle();
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) { if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
sqlite3 *handle = *static_cast<sqlite3**>(v.data()); sqlite3 *handle = *static_cast<sqlite3**>(v.data());
if (handle) sqlite3_db_config(handle, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, NULL); if (handle) {
int result = sqlite3_db_config(handle, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, NULL);
if (result != SQLITE_OK) qLog(Fatal) << "Unable to enable FTS3 tokenizer";
}
else qLog(Fatal) << "Unable to enable FTS3 tokenizer";
} }
#endif #endif
QSqlQuery set_fts_tokenizer(db); QSqlQuery set_fts_tokenizer(db);
@@ -456,7 +460,7 @@ void Database::UrlEncodeFilenameColumn(const QString &table, QSqlDatabase &db) {
update.prepare(QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table)); update.prepare(QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table));
select.exec(); select.exec();
if (CheckErrors(select)) return; if (CheckErrors(select)) return;
while (select.next()) { while (select.next()) {
const int rowid = select.value(0).toInt(); const int rowid = select.value(0).toInt();
const QString filename = select.value(1).toString(); const QString filename = select.value(1).toString();
@@ -561,7 +565,7 @@ QStringList Database::SongsTables(QSqlDatabase &db, int schema_version) const {
} }
bool Database::CheckErrors(const QSqlQuery &query) { bool Database::CheckErrors(const QSqlQuery &query) {
QSqlError last_error = query.lastError(); QSqlError last_error = query.lastError();
if (last_error.isValid()) { if (last_error.isValid()) {
qLog(Error) << "db error: " << last_error; qLog(Error) << "db error: " << last_error;

View File

@@ -11,7 +11,7 @@ class PlatformInterface;
NSMenu* dock_menu_; NSMenu* dock_menu_;
MacGlobalShortcutBackend* shortcut_handler_; MacGlobalShortcutBackend* shortcut_handler_;
SPMediaKeyTap* key_tap_; SPMediaKeyTap* key_tap_;
} }
- (id) initWithHandler: (PlatformInterface*)handler; - (id) initWithHandler: (PlatformInterface*)handler;

View File

@@ -313,7 +313,7 @@ QString GetApplicationSupportPath() {
NSString* user_path = [paths objectAtIndex:0]; NSString* user_path = [paths objectAtIndex:0];
ret = QString::fromUtf8([user_path UTF8String]); ret = QString::fromUtf8([user_path UTF8String]);
} else { } else {
ret = "~/Collection/Application Support"; ret = "~/Library/Application Support";
} }
return ret; return ret;
} }

View File

@@ -17,7 +17,7 @@
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>. * along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#include "config.h" #include "config.h"
#include "macsystemtrayicon.h" #include "macsystemtrayicon.h"
@@ -183,7 +183,7 @@ void MacSystemTrayIcon::SetupMenu(QAction* previous, QAction* play, QAction* sto
SetupMenuItem(mute); SetupMenuItem(mute);
p_->AddSeparator(); p_->AddSeparator();
Q_UNUSED(quit); // Mac already has a Quit item. Q_UNUSED(quit); // Mac already has a Quit item.
} }
void MacSystemTrayIcon::SetupMenuItem(QAction* action) { void MacSystemTrayIcon::SetupMenuItem(QAction* action) {

View File

@@ -58,6 +58,7 @@
#include <QString> #include <QString>
#include <QImage> #include <QImage>
#include <QSettings> #include <QSettings>
#include <QLoggingCategory>
#include <QtDebug> #include <QtDebug>
#ifdef HAVE_DBUS #ifdef HAVE_DBUS
# include <QDBusArgument> # include <QDBusArgument>
@@ -200,6 +201,11 @@ int main(int argc, char* argv[]) {
// Resources // Resources
Q_INIT_RESOURCE(data); Q_INIT_RESOURCE(data);
Q_INIT_RESOURCE(icons);
#ifdef DEBUG
QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
#endif
Application app; Application app;

View File

@@ -1,8 +1,8 @@
/* /*
* Strawberry Music Player * Strawberry Music Player
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
* This file was part of Clementine. * This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com> * Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
* *
* Strawberry is free software: you can redistribute it and/or modify * Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@
#include <QApplication> #include <QApplication>
#include <QObject> #include <QObject>
#include <QWidget> #include <QWidget>
#include <QSystemTrayIcon>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <QByteArray> #include <QByteArray>
#include <QDir> #include <QDir>
@@ -111,8 +112,8 @@
#include "playlist/playlistmanager.h" #include "playlist/playlistmanager.h"
#include "playlist/playlistsequence.h" #include "playlist/playlistsequence.h"
#include "playlist/playlistview.h" #include "playlist/playlistview.h"
#include "playlist/queue.h" #include "queue/queue.h"
#include "playlist/queuemanager.h" #include "queue/queueview.h"
#include "playlistparsers/playlistparser.h" #include "playlistparsers/playlistparser.h"
#include "analyzer/analyzercontainer.h" #include "analyzer/analyzercontainer.h"
#include "equalizer/equalizer.h" #include "equalizer/equalizer.h"
@@ -121,17 +122,27 @@
#include "covermanager/albumcoverchoicecontroller.h" #include "covermanager/albumcoverchoicecontroller.h"
#include "covermanager/albumcoverloader.h" #include "covermanager/albumcoverloader.h"
#include "covermanager/currentartloader.h" #include "covermanager/currentartloader.h"
#include "device/devicemanager.h" #ifndef Q_OS_WIN
#include "device/devicestatefiltermodel.h" # include "device/devicemanager.h"
#include "device/deviceview.h" # include "device/devicestatefiltermodel.h"
#include "device/deviceviewcontainer.h" # include "device/deviceview.h"
# include "device/deviceviewcontainer.h"
#endif
#include "transcoder/transcodedialog.h" #include "transcoder/transcodedialog.h"
#include "settings/settingsdialog.h"
#include "settings/behavioursettingspage.h" #include "settings/behavioursettingspage.h"
#include "settings/playbacksettingspage.h" #include "settings/playbacksettingspage.h"
#include "settings/playlistsettingspage.h" #include "settings/playlistsettingspage.h"
#include "settings/settingsdialog.h" #ifdef HAVE_STREAM_TIDAL
# include "settings/tidalsettingspage.h"
#endif
#ifdef HAVE_STREAM_DEEZER
# include "settings/deezersettingspage.h"
#endif
#include "tidal/tidalsearchview.h" #include "internet/internetservices.h"
#include "internet/internetservice.h"
#include "internet/internetsearchview.h"
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT) #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
# include "musicbrainz/tagfetcher.h" # include "musicbrainz/tagfetcher.h"
@@ -141,6 +152,10 @@
# include "core/macsystemtrayicon.h" # include "core/macsystemtrayicon.h"
#endif #endif
using std::bind;
using std::floor;
using std::stable_sort;
#ifdef Q_OS_MACOS #ifdef Q_OS_MACOS
// Non exported mac-specific function. // Non exported mac-specific function.
void qt_mac_set_dock_menu(QMenu*); void qt_mac_set_dock_menu(QMenu*);
@@ -150,7 +165,7 @@ const char *MainWindow::kSettingsGroup = "MainWindow";
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)"); const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
namespace { namespace {
const int kTrackSliderUpdateTimeMs = 40; const int kTrackSliderUpdateTimeMs = 200;
const int kTrackPositionUpdateTimeMs = 1000; const int kTrackPositionUpdateTimeMs = 1000;
} }
@@ -167,9 +182,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
context_view_(new ContextView(this)), context_view_(new ContextView(this)),
collection_view_(new CollectionViewContainer(this)), collection_view_(new CollectionViewContainer(this)),
file_view_(new FileView(this)), file_view_(new FileView(this)),
#ifndef Q_OS_WIN
device_view_container_(new DeviceViewContainer(this)), device_view_container_(new DeviceViewContainer(this)),
device_view_(device_view_container_->view()), device_view_(device_view_container_->view()),
#endif
playlist_list_(new PlaylistListContainer(this)), playlist_list_(new PlaylistListContainer(this)),
queue_view_(new QueueView(this)),
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)), settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
cover_manager_([=]() { cover_manager_([=]() {
AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend()); AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend());
@@ -189,12 +207,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
return dialog; return dialog;
}), }),
#endif #endif
queue_manager_([=]() { #ifdef HAVE_STREAM_TIDAL
QueueManager *manager = new QueueManager; tidal_search_view_(new InternetSearchView(app_, app_->tidal_search(), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)),
manager->SetPlaylistManager(app->playlist_manager()); #endif
return manager; #ifdef HAVE_STREAM_DEEZER
}), deezer_search_view_(new InternetSearchView(app_, app_->deezer_search(), DeezerSettingsPage::kSettingsGroup, SettingsDialog::Page_Deezer, this)),
tidal_search_view_(new TidalSearchView(app_, this)), #endif
playlist_menu_(new QMenu(this)), playlist_menu_(new QMenu(this)),
playlist_add_to_another_(nullptr), playlist_add_to_another_(nullptr),
playlistitem_actions_separator_(nullptr), playlistitem_actions_separator_(nullptr),
@@ -238,22 +256,29 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->volume->setValue(volume); ui_->volume->setValue(volume);
VolumeChanged(volume); VolumeChanged(volume);
// Initialise the tidal search widget // Initialise the search widget
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker()); StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
// Add tabs to the fancy tab widget // Add tabs to the fancy tab widget
ui_->tabs->addTab(context_view_, IconLoader::Load("strawberry"), tr("Context")); ui_->tabs->addTab(context_view_, IconLoader::Load("strawberry"), "Context");
ui_->tabs->addTab(collection_view_, IconLoader::Load("vinyl"), tr("Collection")); ui_->tabs->addTab(collection_view_, IconLoader::Load("vinyl"), "Collection");
ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), tr("Files")); ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), "Files");
ui_->tabs->addTab(playlist_list_, IconLoader::Load("view-media-playlist"), tr("Playlists")); ui_->tabs->addTab(playlist_list_, IconLoader::Load("view-media-playlist"), "Playlists");
ui_->tabs->addTab(device_view_, IconLoader::Load("device"), tr("Devices")); ui_->tabs->addTab(queue_view_, IconLoader::Load("footsteps"), "Queue");
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), tr("Tidal", "Tidal")); #ifndef Q_OS_WIN
//ui_->tabs->AddSpacer(); ui_->tabs->addTab(device_view_, IconLoader::Load("device"), "Devices");
#endif
#ifdef HAVE_STREAM_TIDAL
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), "Tidal");
#endif
#ifdef HAVE_STREAM_DEEZER
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), "Deezer");
#endif
// Add the playing widget to the fancy tab widget // Add the playing widget to the fancy tab widget
ui_->tabs->addBottomWidget(ui_->widget_playing); ui_->tabs->addBottomWidget(ui_->widget_playing);
//ui_->tabs->SetBackgroundPixmap(QPixmap(":/pictures/strawberry-background.png")); //ui_->tabs->SetBackgroundPixmap(QPixmap(":/pictures/strawberry-background.png"));
ui_->tabs->loadSettings(kSettingsGroup);
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs); track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition())); connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition()));
@@ -273,7 +298,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
collection_sort_model_->setDynamicSortFilter(true); collection_sort_model_->setDynamicSortFilter(true);
collection_sort_model_->setSortLocaleAware(true); collection_sort_model_->setSortLocaleAware(true);
collection_sort_model_->sort(0); collection_sort_model_->sort(0);
qLog(Debug) << "Creating models finished"; qLog(Debug) << "Creating models finished";
connect(ui_->playlist, SIGNAL(ViewSelectionModelChanged()), SLOT(PlaylistViewSelectionModelChanged())); connect(ui_->playlist, SIGNAL(ViewSelectionModelChanged()), SLOT(PlaylistViewSelectionModelChanged()));
@@ -284,7 +309,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
collection_view_->view()->setModel(collection_sort_model_); collection_view_->view()->setModel(collection_sort_model_);
collection_view_->view()->SetApplication(app_); collection_view_->view()->SetApplication(app_);
#ifndef Q_OS_WIN
device_view_->SetApplication(app_); device_view_->SetApplication(app_);
#endif
playlist_list_->SetApplication(app_); playlist_list_->SetApplication(app_);
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
@@ -308,7 +335,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->action_stop->setIcon(IconLoader::Load("media-stop")); ui_->action_stop->setIcon(IconLoader::Load("media-stop"));
ui_->action_stop_after_this_track->setIcon(IconLoader::Load("media-stop")); ui_->action_stop_after_this_track->setIcon(IconLoader::Load("media-stop"));
ui_->action_next_track->setIcon(IconLoader::Load("media-forward")); ui_->action_next_track->setIcon(IconLoader::Load("media-forward"));
ui_->action_quit->setIcon(IconLoader::Load("application-exit")); ui_->action_quit->setIcon(IconLoader::Load("application-exit"));
// Playlist // Playlist
@@ -330,7 +357,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
// Configure // Configure
ui_->action_cover_manager->setIcon(IconLoader::Load("document-download")); ui_->action_cover_manager->setIcon(IconLoader::Load("document-download"));
ui_->action_queue_manager->setIcon(IconLoader::Load("footsteps"));
ui_->action_edit_track->setIcon(IconLoader::Load("edit-rename")); ui_->action_edit_track->setIcon(IconLoader::Load("edit-rename"));
ui_->action_equalizer->setIcon(IconLoader::Load("equalizer")); ui_->action_equalizer->setIcon(IconLoader::Load("equalizer"));
ui_->action_update_collection->setIcon(IconLoader::Load("view-refresh")); ui_->action_update_collection->setIcon(IconLoader::Load("view-refresh"));
@@ -344,7 +370,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(file_view_, SIGNAL(CopyToCollection(QList<QUrl>)), SLOT(CopyFilesToCollection(QList<QUrl>))); connect(file_view_, SIGNAL(CopyToCollection(QList<QUrl>)), SLOT(CopyFilesToCollection(QList<QUrl>)));
connect(file_view_, SIGNAL(MoveToCollection(QList<QUrl>)), SLOT(MoveFilesToCollection(QList<QUrl>))); connect(file_view_, SIGNAL(MoveToCollection(QList<QUrl>)), SLOT(MoveFilesToCollection(QList<QUrl>)));
connect(file_view_, SIGNAL(EditTags(QList<QUrl>)), SLOT(EditFileTags(QList<QUrl>))); connect(file_view_, SIGNAL(EditTags(QList<QUrl>)), SLOT(EditFileTags(QList<QUrl>)));
#ifndef Q_OS_WIN
connect(file_view_, SIGNAL(CopyToDevice(QList<QUrl>)), SLOT(CopyFilesToDevice(QList<QUrl>))); connect(file_view_, SIGNAL(CopyToDevice(QList<QUrl>)), SLOT(CopyFilesToDevice(QList<QUrl>)));
#endif
#endif #endif
file_view_->SetTaskManager(app_->task_manager()); file_view_->SetTaskManager(app_->task_manager());
@@ -381,7 +409,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(ui_->action_jump, SIGNAL(triggered()), ui_->playlist->view(), SLOT(JumpToCurrentlyPlayingTrack())); connect(ui_->action_jump, SIGNAL(triggered()), ui_->playlist->view(), SLOT(JumpToCurrentlyPlayingTrack()));
connect(ui_->action_update_collection, SIGNAL(triggered()), app_->collection(), SLOT(IncrementalScan())); connect(ui_->action_update_collection, SIGNAL(triggered()), app_->collection(), SLOT(IncrementalScan()));
connect(ui_->action_full_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(FullScan())); connect(ui_->action_full_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(FullScan()));
connect(ui_->action_queue_manager, SIGNAL(triggered()), SLOT(ShowQueueManager()));
//connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()), SLOT(AddFilesToTranscoder())); //connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()), SLOT(AddFilesToTranscoder()));
// Playlist view actions // Playlist view actions
@@ -469,8 +496,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(app_->task_manager(), SIGNAL(PauseCollectionWatchers()), app_->collection(), SLOT(PauseWatcher())); connect(app_->task_manager(), SIGNAL(PauseCollectionWatchers()), app_->collection(), SLOT(PauseWatcher()));
connect(app_->task_manager(), SIGNAL(ResumeCollectionWatchers()), app_->collection(), SLOT(ResumeWatcher())); connect(app_->task_manager(), SIGNAL(ResumeCollectionWatchers()), app_->collection(), SLOT(ResumeWatcher()));
#ifndef Q_OS_WIN
// Devices connections // Devices connections
connect(device_view_, SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*))); connect(device_view_, SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
#endif
// Collection filter widget // Collection filter widget
QActionGroup *collection_view_group = new QActionGroup(this); QActionGroup *collection_view_group = new QActionGroup(this);
@@ -500,8 +529,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
collection_view_->filter()->AddMenuAction(separator); collection_view_->filter()->AddMenuAction(separator);
collection_view_->filter()->AddMenuAction(collection_config_action); collection_view_->filter()->AddMenuAction(collection_config_action);
// Tidal #ifdef HAVE_STREAM_TIDAL
connect(tidal_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*))); connect(tidal_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
#endif
#ifdef HAVE_STREAM_DEEZER
connect(deezer_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
#endif
// Playlist menu // Playlist menu
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay())); playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
@@ -511,6 +544,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
playlist_queue_->setVisible(false); playlist_queue_->setVisible(false);
playlist_queue_->setShortcut(QKeySequence("Ctrl+D")); playlist_queue_->setShortcut(QKeySequence("Ctrl+D"));
ui_->playlist->addAction(playlist_queue_); ui_->playlist->addAction(playlist_queue_);
playlist_queue_play_next_ = playlist_menu_->addAction(IconLoader::Load("go-next"), tr("Queue selected tracks to play next"), this, SLOT(PlaylistQueuePlayNext()));
playlist_queue_play_next_->setShortcut(QKeySequence("Ctrl+Shift+D"));
playlist_queue_play_next_->setVisible(false);
ui_->playlist->addAction(playlist_queue_play_next_);
playlist_skip_ = playlist_menu_->addAction(IconLoader::Load("media-forward"), tr("Toggle skip status"), this, SLOT(PlaylistSkip())); playlist_skip_ = playlist_menu_->addAction(IconLoader::Load("media-forward"), tr("Toggle skip status"), this, SLOT(PlaylistSkip()));
playlist_skip_->setVisible(false); playlist_skip_->setVisible(false);
ui_->playlist->addAction(playlist_skip_); ui_->playlist->addAction(playlist_skip_);
@@ -529,7 +566,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection())); playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection())); playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
//playlist_organise_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(PlaylistMoveToCollection())); //playlist_organise_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(PlaylistMoveToCollection()));
#ifndef Q_OS_WIN
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice())); playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice()));
#endif
#endif #endif
//playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete())); //playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete()));
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser())); playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
@@ -551,7 +590,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*, QAction*)), SLOT(PlaylistUndoRedoChanged(QAction*, QAction*))); connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*, QAction*)), SLOT(PlaylistUndoRedoChanged(QAction*, QAction*)));
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
playlist_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0); playlist_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), playlist_copy_to_device_, SLOT(setDisabled(bool))); connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), playlist_copy_to_device_, SLOT(setDisabled(bool)));
#endif #endif
@@ -560,15 +599,16 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
mac::SetApplicationHandler(this); mac::SetApplicationHandler(this);
#endif #endif
// Tray icon // Tray icon
tray_icon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause, ui_->action_stop, ui_->action_stop_after_this_track, ui_->action_next_track, ui_->action_mute, ui_->action_quit); if (tray_icon_) {
tray_icon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause, ui_->action_stop, ui_->action_stop_after_this_track, ui_->action_next_track, ui_->action_mute, ui_->action_quit);
connect(tray_icon_, SIGNAL(PlayPause()), app_->player(), SLOT(PlayPause())); connect(tray_icon_, SIGNAL(PlayPause()), app_->player(), SLOT(PlayPause()));
connect(tray_icon_, SIGNAL(SeekForward()), app_->player(), SLOT(SeekForward())); connect(tray_icon_, SIGNAL(SeekForward()), app_->player(), SLOT(SeekForward()));
connect(tray_icon_, SIGNAL(SeekBackward()), app_->player(), SLOT(SeekBackward())); connect(tray_icon_, SIGNAL(SeekBackward()), app_->player(), SLOT(SeekBackward()));
connect(tray_icon_, SIGNAL(NextTrack()), app_->player(), SLOT(Next())); connect(tray_icon_, SIGNAL(NextTrack()), app_->player(), SLOT(Next()));
connect(tray_icon_, SIGNAL(PreviousTrack()), app_->player(), SLOT(Previous())); connect(tray_icon_, SIGNAL(PreviousTrack()), app_->player(), SLOT(Previous()));
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide())); connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int))); connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
}
// Windows 7 thumbbar buttons // Windows 7 thumbbar buttons
thumbbar_->SetActions(QList<QAction*>() << ui_->action_previous_track << ui_->action_play_pause << ui_->action_stop << ui_->action_next_track << nullptr); // spacer thumbbar_->SetActions(QList<QAction*>() << ui_->action_previous_track << ui_->action_play_pause << ui_->action_stop << ui_->action_next_track << nullptr); // spacer
@@ -601,7 +641,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
connect(ui_->tabs, SIGNAL(ModeChanged(FancyTabWidget::Mode)), SLOT(SaveGeometry())); connect(ui_->tabs, SIGNAL(ModeChanged(FancyTabWidget::Mode)), SLOT(SaveGeometry()));
connect(ui_->tabs, SIGNAL(CurrentChanged(int)), SLOT(TabSwitched())); connect(ui_->tabs, SIGNAL(CurrentChanged(int)), SLOT(TabSwitched()));
connect(ui_->tabs, SIGNAL(CurrentChanged(int)), SLOT(SaveGeometry())); connect(ui_->tabs, SIGNAL(CurrentChanged(int)), SLOT(SaveGeometry()));
// Context // Context
connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), context_view_, SLOT(SongChanged(Song))); connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), context_view_, SLOT(SongChanged(Song)));
connect(app_->player(), SIGNAL(PlaylistFinished()), context_view_, SLOT(Stopped())); connect(app_->player(), SIGNAL(PlaylistFinished()), context_view_, SLOT(Stopped()));
@@ -658,6 +698,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
// Load playlists // Load playlists
app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist); app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist);
queue_view_->SetPlaylistManager(app_->playlist_manager());
// This connection must be done after the playlists have been initialized. // This connection must be done after the playlists have been initialized.
connect(this, SIGNAL(StopAfterToggled(bool)), osd_, SLOT(StopAfterToggle(bool))); connect(this, SIGNAL(StopAfterToggled(bool)), osd_, SLOT(StopAfterToggle(bool)));
@@ -684,7 +726,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ui_->tabs->setCurrentIndex(settings_.value("current_tab", 1 /* Collection tab */ ).toInt()); ui_->tabs->setCurrentIndex(settings_.value("current_tab", 1 /* Collection tab */ ).toInt());
FancyTabWidget::Mode default_mode = FancyTabWidget::Mode_LargeSidebar; FancyTabWidget::Mode default_mode = FancyTabWidget::Mode_LargeSidebar;
ui_->tabs->SetMode(FancyTabWidget::Mode(settings_.value("tab_mode", default_mode).toInt())); int tab_mode_int = settings_.value("tab_mode", default_mode).toInt();
FancyTabWidget::Mode tab_mode = FancyTabWidget::Mode(tab_mode_int);
if (tab_mode == FancyTabWidget::Mode_None) tab_mode = default_mode;
ui_->tabs->SetMode(tab_mode);
file_view_->SetPath(settings_.value("file_path", QDir::homePath()).toString()); file_view_->SetPath(settings_.value("file_path", QDir::homePath()).toString());
TabSwitched(); TabSwitched();
@@ -694,43 +739,38 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
ReloadSettings(); ReloadSettings();
// Tidal search shortcut
QAction *tidal_search_action = new QAction(this);
tidal_search_action->setShortcuts(QList<QKeySequence>() << QKeySequence("Ctrl+F") << QKeySequence("Ctrl+L"));
addAction(tidal_search_action);
connect(tidal_search_action, SIGNAL(triggered()), SLOT(FocusTidalSearchField()));
// Reload pretty OSD to avoid issues with fonts // Reload pretty OSD to avoid issues with fonts
osd_->ReloadPrettyOSDSettings(); osd_->ReloadPrettyOSDSettings();
// Reload playlist settings, for BG and glowing // Reload playlist settings, for BG and glowing
ui_->playlist->view()->ReloadSettings(); ui_->playlist->view()->ReloadSettings();
#ifdef Q_OS_MACOS // Always show mainwindow on startup if on macos
#ifndef Q_OS_MACOS show();
#else
QSettings settings; QSettings settings;
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup); settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
StartupBehaviour behaviour = StartupBehaviour(settings.value("startupbehaviour", Startup_Remember).toInt()); StartupBehaviour behaviour = StartupBehaviour(settings.value("startupbehaviour", Startup_Remember).toInt());
settings.endGroup(); settings.endGroup();
bool hidden = settings_.value("hidden", false).toBool(); bool hidden = settings_.value("hidden", false).toBool();
if (hidden && (!QSystemTrayIcon::isSystemTrayAvailable() || !tray_icon_ || !tray_icon_->IsVisible())) {
hidden = false;
switch (behaviour) {
case Startup_AlwaysHide: hide(); break;
case Startup_AlwaysShow: show(); break;
case Startup_Remember:
setVisible(!hidden);
break;
}
// Force the window to show in case somehow the config has tray and window set to hide
if (hidden && !tray_icon_->IsVisible()) {
settings_.setValue("hidden", false); settings_.setValue("hidden", false);
show(); show();
} }
#else // Q_OS_MACOS else {
// Always show mainwindow on startup on OS X. switch (behaviour) {
show(); case Startup_AlwaysHide:
hide();
break;
case Startup_AlwaysShow:
show();
break;
case Startup_Remember:
setVisible(!hidden);
break;
}
}
#endif #endif
QShortcut *close_window_shortcut = new QShortcut(this); QShortcut *close_window_shortcut = new QShortcut(this);
@@ -743,9 +783,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
if (!options.contains_play_options()) LoadPlaybackStatus(); if (!options.contains_play_options()) LoadPlaybackStatus();
qLog(Debug) << "Started";
RefreshStyleSheet(); RefreshStyleSheet();
qLog(Debug) << "Started";
initialised_ = true; initialised_ = true;
} }
@@ -760,16 +800,14 @@ void MainWindow::ReloadSettings() {
QSettings settings; QSettings settings;
#ifndef Q_OS_MACOS #ifndef Q_OS_MACOS
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup); settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
bool showtrayicon = settings.value("showtrayicon", true).toBool(); bool showtrayicon = settings.value("showtrayicon", QSystemTrayIcon::isSystemTrayAvailable()).toBool();
settings.endGroup(); settings.endGroup();
if (tray_icon_) tray_icon_->SetVisible(showtrayicon);
tray_icon_->SetVisible(showtrayicon); if ((!showtrayicon || !QSystemTrayIcon::isSystemTrayAvailable()) && !isVisible()) show();
if (!showtrayicon && !isVisible()) show();
#endif #endif
settings.beginGroup(PlaylistSettingsPage::kSettingsGroup); settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
doubleclick_addmode_ = AddBehaviour(settings.value("doubleclick_addmode", AddBehaviour_Append).toInt()); doubleclick_addmode_ = AddBehaviour(settings.value("doubleclick_addmode", AddBehaviour_Append).toInt());
doubleclick_playmode_ = PlayBehaviour(settings.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt()); doubleclick_playmode_ = PlayBehaviour(settings.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt());
doubleclick_playlist_addmode_ = PlaylistAddBehaviour(settings.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play).toInt()); doubleclick_playlist_addmode_ = PlaylistAddBehaviour(settings.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play).toInt());
@@ -780,6 +818,26 @@ void MainWindow::ReloadSettings() {
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings.value("search_for_cover_auto", true).toBool()); album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings.value("search_for_cover_auto", true).toBool());
settings.endGroup(); settings.endGroup();
#ifdef HAVE_STREAM_TIDAL
settings.beginGroup(TidalSettingsPage::kSettingsGroup);
bool enable_tidal = settings.value("enabled", false).toBool();
settings.endGroup();
if (enable_tidal)
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), "Tidal");
else
ui_->tabs->delTab("Tidal");
#endif
#ifdef HAVE_STREAM_DEEZER
settings.beginGroup(DeezerSettingsPage::kSettingsGroup);
bool enable_deezer = settings.value("enabled", false).toBool();
settings.endGroup();
if (enable_deezer)
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), "Deezer");
else
ui_->tabs->delTab("Deezer");
#endif
} }
void MainWindow::ReloadAllSettings() { void MainWindow::ReloadAllSettings() {
@@ -793,13 +851,21 @@ void MainWindow::ReloadAllSettings() {
osd_->ReloadSettings(); osd_->ReloadSettings();
collection_view_->ReloadSettings(); collection_view_->ReloadSettings();
ui_->playlist->view()->ReloadSettings(); ui_->playlist->view()->ReloadSettings();
#ifdef HAVE_STREAM_TIDAL
tidal_search_view_->ReloadSettings(); tidal_search_view_->ReloadSettings();
#endif
#ifdef HAVE_STREAM_DEEZER
deezer_search_view_->ReloadSettings();
#endif
} }
void MainWindow::RefreshStyleSheet() { void MainWindow::RefreshStyleSheet() {
setStyleSheet(styleSheet()); QString contents(styleSheet());
setStyleSheet("");
setStyleSheet(contents);
} }
void MainWindow::MediaStopped() { void MainWindow::MediaStopped() {
setWindowTitle("Strawberry Music Player"); setWindowTitle("Strawberry Music Player");
@@ -814,17 +880,19 @@ void MainWindow::MediaStopped() {
track_position_timer_->stop(); track_position_timer_->stop();
track_slider_timer_->stop(); track_slider_timer_->stop();
ui_->track_slider->SetStopped(); ui_->track_slider->SetStopped();
tray_icon_->SetProgress(0); if (tray_icon_) {
tray_icon_->SetStopped(); tray_icon_->SetProgress(0);
tray_icon_->SetStopped();
}
song_playing_ = song_empty_; song_playing_ = Song();
song_ = song_empty_; song_ = Song();
image_original_ = QImage(); image_original_ = QImage();
} }
void MainWindow::MediaPaused() { void MainWindow::MediaPaused() {
ui_->action_stop->setEnabled(true); ui_->action_stop->setEnabled(true);
ui_->action_stop_after_this_track->setEnabled(true); ui_->action_stop_after_this_track->setEnabled(true);
ui_->action_play_pause->setIcon(IconLoader::Load("media-play")); ui_->action_play_pause->setIcon(IconLoader::Load("media-play"));
@@ -835,7 +903,7 @@ void MainWindow::MediaPaused() {
track_position_timer_->stop(); track_position_timer_->stop();
track_slider_timer_->stop(); track_slider_timer_->stop();
tray_icon_->SetPaused(); if (tray_icon_) tray_icon_->SetPaused();
} }
@@ -846,13 +914,15 @@ void MainWindow::MediaPlaying() {
ui_->action_play_pause->setIcon(IconLoader::Load("media-pause")); ui_->action_play_pause->setIcon(IconLoader::Load("media-pause"));
ui_->action_play_pause->setText(tr("Pause")); ui_->action_play_pause->setText(tr("Pause"));
bool enable_play_pause = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::PauseDisabled); bool enable_play_pause(false);
bool can_seek(false);
if (app_->player()->GetCurrentItem()) {
enable_play_pause = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::PauseDisabled);
can_seek = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::SeekDisabled);
}
ui_->action_play_pause->setEnabled(enable_play_pause); ui_->action_play_pause->setEnabled(enable_play_pause);
bool can_seek = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::SeekDisabled);
ui_->track_slider->SetCanSeek(can_seek); ui_->track_slider->SetCanSeek(can_seek);
if (tray_icon_) tray_icon_->SetPlaying(enable_play_pause);
tray_icon_->SetPlaying(enable_play_pause);
track_position_timer_->start(); track_position_timer_->start();
track_slider_timer_->start(); track_slider_timer_->start();
@@ -862,7 +932,7 @@ void MainWindow::MediaPlaying() {
void MainWindow::VolumeChanged(int volume) { void MainWindow::VolumeChanged(int volume) {
ui_->action_mute->setChecked(!volume); ui_->action_mute->setChecked(!volume);
tray_icon_->MuteButtonStateChanged(!volume); if (tray_icon_) tray_icon_->MuteButtonStateChanged(!volume);
} }
void MainWindow::SongChanged(const Song &song) { void MainWindow::SongChanged(const Song &song) {
@@ -870,11 +940,12 @@ void MainWindow::SongChanged(const Song &song) {
song_playing_ = song; song_playing_ = song;
song_ = song; song_ = song;
setWindowTitle(song.PrettyTitleWithArtist()); setWindowTitle(song.PrettyTitleWithArtist());
tray_icon_->SetProgress(0); if (tray_icon_) tray_icon_->SetProgress(0);
} }
void MainWindow::TrackSkipped(PlaylistItemPtr item) { void MainWindow::TrackSkipped(PlaylistItemPtr item) {
// If it was a collection item then we have to increment its skipped count in the database. // If it was a collection item then we have to increment its skipped count in the database.
if (item && item->IsLocalCollectionItem() && item->Metadata().id() != -1) { if (item && item->IsLocalCollectionItem() && item->Metadata().id() != -1) {
@@ -891,6 +962,7 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) {
app_->collection_backend()->IncrementSkipCountAsync(song.id(), percentage); app_->collection_backend()->IncrementSkipCountAsync(song.id(), percentage);
} }
} }
} }
void MainWindow::changeEvent(QEvent *event) { void MainWindow::changeEvent(QEvent *event) {
@@ -899,16 +971,18 @@ void MainWindow::changeEvent(QEvent *event) {
} }
void MainWindow::resizeEvent(QResizeEvent *event) { void MainWindow::resizeEvent(QResizeEvent *event) {
if (!initialised_) return;
SaveGeometry(); SaveGeometry();
} }
void MainWindow::TabSwitched() { void MainWindow::TabSwitched() {
if (ui_->tabs->currentIndex() > 0)
ui_->widget_playing->SetEnabled();
else
ui_->widget_playing->SetDisabled();
if (ui_->tabs->tabBar()->tabData(ui_->tabs->currentIndex()).toString().toLower() == "context")
ui_->widget_playing->SetDisabled();
else
ui_->widget_playing->SetEnabled();
if (!initialised_) return;
SaveGeometry(); SaveGeometry();
} }
@@ -922,11 +996,12 @@ void MainWindow::SaveGeometry() {
settings_.setValue("splitter_state", ui_->splitter->saveState()); settings_.setValue("splitter_state", ui_->splitter->saveState());
settings_.setValue("current_tab", ui_->tabs->currentIndex()); settings_.setValue("current_tab", ui_->tabs->currentIndex());
settings_.setValue("tab_mode", ui_->tabs->mode()); settings_.setValue("tab_mode", ui_->tabs->mode());
ui_->tabs->saveSettings(kSettingsGroup);
} }
void MainWindow::SavePlaybackStatus() { void MainWindow::SavePlaybackStatus() {
QSettings settings; QSettings settings;
settings.beginGroup("Player"); settings.beginGroup("Player");
@@ -937,13 +1012,13 @@ void MainWindow::SavePlaybackStatus() {
else { else {
settings.setValue("playback_position", 0); settings.setValue("playback_position", 0);
} }
settings.endGroup(); settings.endGroup();
} }
void MainWindow::LoadPlaybackStatus() { void MainWindow::LoadPlaybackStatus() {
QSettings settings; QSettings settings;
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup); settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
@@ -956,7 +1031,7 @@ void MainWindow::LoadPlaybackStatus() {
saved_playback_state_ = static_cast<Engine::State> (settings.value("playback_state", Engine::Empty).toInt()); saved_playback_state_ = static_cast<Engine::State> (settings.value("playback_state", Engine::Empty).toInt());
saved_playback_position_ = settings.value("playback_position", 0).toDouble(); saved_playback_position_ = settings.value("playback_position", 0).toDouble();
settings.endGroup(); settings.endGroup();
if (saved_playback_state_ == Engine::Empty || saved_playback_state_ == Engine::Idle) { if (saved_playback_state_ == Engine::Empty || saved_playback_state_ == Engine::Idle) {
return; return;
} }
@@ -981,7 +1056,7 @@ void MainWindow::ResumePlayback() {
} }
void MainWindow::PlayIndex(const QModelIndex &index) { void MainWindow::PlayIndex(const QModelIndex &index) {
if (!index.isValid()) return; if (!index.isValid()) return;
int row = index.row(); int row = index.row();
@@ -1026,7 +1101,7 @@ void MainWindow::VolumeWheelEvent(int delta) {
} }
void MainWindow::ToggleShowHide() { void MainWindow::ToggleShowHide() {
if (settings_.value("hidden").toBool()) { if (settings_.value("hidden").toBool()) {
show(); show();
SetHiddenInTray(false); SetHiddenInTray(false);
@@ -1064,7 +1139,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
bool keep_running = settings.value("keeprunning", false).toBool(); bool keep_running = settings.value("keeprunning", false).toBool();
settings.endGroup(); settings.endGroup();
if (keep_running && event->spontaneous()) { if (keep_running && event->spontaneous() && QSystemTrayIcon::isSystemTrayAvailable()) {
event->ignore(); event->ignore();
SetHiddenInTray(true); SetHiddenInTray(true);
} }
@@ -1097,30 +1172,28 @@ void MainWindow::Seeked(qlonglong microseconds) {
const int position = microseconds / kUsecPerSec; const int position = microseconds / kUsecPerSec;
const int length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec; const int length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec;
tray_icon_->SetProgress(double(position) / length * 100); if (tray_icon_) tray_icon_->SetProgress(double(position) / length * 100);
} }
void MainWindow::UpdateTrackPosition() { void MainWindow::UpdateTrackPosition() {
// Track position in seconds // Track position in seconds
//Playlist *playlist = app_->playlist_manager()->active(); //Playlist *playlist = app_->playlist_manager()->active();
PlaylistItemPtr item(app_->player()->GetCurrentItem()); PlaylistItemPtr item(app_->player()->GetCurrentItem());
if (!item) return;
const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5); const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5);
const int length = item->Metadata().length_nanosec() / kNsecPerSec; const int length = item->Metadata().length_nanosec() / kNsecPerSec;
if (length <= 0) { if (length <= 0) {
// Probably a stream that we don't know the length of // Probably a stream that we don't know the length of
//ui_->track_slider->SetStopped();
//tray_icon_->SetProgress(0);
return; return;
} }
// Update the tray icon every 10 seconds // Update the tray icon every 10 seconds
if (position % 10 == 0) { if (position % 10 == 0 && tray_icon_) tray_icon_->SetProgress(double(position) / length * 100);
tray_icon_->SetProgress(double(position) / length * 100);
}
} }
void MainWindow::UpdateTrackSliderPosition() { void MainWindow::UpdateTrackSliderPosition() {
@@ -1201,7 +1274,7 @@ void MainWindow::AddToPlaylist(QMimeData *data) {
} }
void MainWindow::AddToPlaylist(QAction *action) { void MainWindow::AddToPlaylist(QAction *action) {
int destination = action->data().toInt(); int destination = action->data().toInt();
PlaylistItemList items; PlaylistItemList items;
@@ -1273,17 +1346,17 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
int not_in_queue = 0; int not_in_queue = 0;
int in_skipped = 0; int in_skipped = 0;
int not_in_skipped = 0; int not_in_skipped = 0;
for (const QModelIndex &index : selection) { for (const QModelIndex &index : selection) {
all++; all++;
if (index.column() != 0) continue; if (index.column() != 0) continue;
selected++; selected++;
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(index.row()); PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(index.row());
if (item->Metadata().has_cue()) { if (item->Metadata().has_cue()) {
cue_selected = true; cue_selected = true;
} }
@@ -1324,20 +1397,20 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
playlist_copy_to_collection_->setVisible(false); playlist_copy_to_collection_->setVisible(false);
playlist_move_to_collection_->setVisible(false); playlist_move_to_collection_->setVisible(false);
//playlist_organise_->setVisible(false); //playlist_organise_->setVisible(false);
#ifndef Q_OS_WIN
playlist_copy_to_device_->setVisible(false); playlist_copy_to_device_->setVisible(false);
#endif
#endif #endif
playlist_open_in_browser_->setVisible(false); playlist_open_in_browser_->setVisible(false);
//qLog(Debug) << "selected" << selected;
//qLog(Debug) << "in_queue" << in_queue << "not_in_queue" << not_in_queue;
//qLog(Debug) << "in_skipped" << in_skipped << "not_in_skipped" << not_in_skipped;
if (selected < 1) { if (selected < 1) {
playlist_queue_->setVisible(false); playlist_queue_->setVisible(false);
playlist_queue_play_next_->setVisible(false);
playlist_skip_->setVisible(false); playlist_skip_->setVisible(false);
} }
else { else {
playlist_queue_->setVisible(true); playlist_queue_->setVisible(true);
playlist_queue_play_next_->setVisible(true);
playlist_skip_->setVisible(true); playlist_skip_->setVisible(true);
if (in_queue == 1 && not_in_queue == 0) playlist_queue_->setText(tr("Dequeue track")); if (in_queue == 1 && not_in_queue == 0) playlist_queue_->setText(tr("Dequeue track"));
else if (in_queue > 1 && not_in_queue == 0) playlist_queue_->setText(tr("Dequeue selected tracks")); else if (in_queue > 1 && not_in_queue == 0) playlist_queue_->setText(tr("Dequeue selected tracks"));
@@ -1345,6 +1418,11 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
else if (in_queue == 0 && not_in_queue > 1) playlist_queue_->setText(tr("Queue selected tracks")); else if (in_queue == 0 && not_in_queue > 1) playlist_queue_->setText(tr("Queue selected tracks"));
else playlist_queue_->setText(tr("Toggle queue status")); else playlist_queue_->setText(tr("Toggle queue status"));
if (selected > 1)
playlist_queue_play_next_->setText(tr("Queue selected tracks to play next"));
else
playlist_queue_play_next_->setText(tr("Queue to play next"));
if (in_skipped == 1 && not_in_skipped == 0) playlist_skip_->setText(tr("Unskip track")); if (in_skipped == 1 && not_in_skipped == 0) playlist_skip_->setText(tr("Unskip track"));
else if (in_skipped > 1 && not_in_skipped == 0) playlist_skip_->setText(tr("Unskip selected tracks")); else if (in_skipped > 1 && not_in_skipped == 0) playlist_skip_->setText(tr("Unskip selected tracks"));
else if (in_skipped == 0 && not_in_skipped == 1) playlist_skip_->setText(tr("Skip track")); else if (in_skipped == 0 && not_in_skipped == 1) playlist_skip_->setText(tr("Skip track"));
@@ -1364,8 +1442,8 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
ui_->action_edit_value->setVisible(false); ui_->action_edit_value->setVisible(false);
} }
else { else {
Playlist::Column column = (Playlist::Column)index.column(); Playlist::Column column = (Playlist::Column)index.column();
bool column_is_editable = Playlist::column_is_editable(column) && editable; bool column_is_editable = Playlist::column_is_editable(column) && editable;
@@ -1393,7 +1471,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
} }
#endif #endif
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
playlist_copy_to_device_->setVisible(editable); playlist_copy_to_device_->setVisible(editable);
#endif #endif
@@ -1455,6 +1533,7 @@ void MainWindow::PlaylistStopAfter() {
} }
void MainWindow::EditTracks() { void MainWindow::EditTracks() {
SongList songs; SongList songs;
PlaylistItemList items; PlaylistItemList items;
@@ -1473,9 +1552,11 @@ void MainWindow::EditTracks() {
//EnsureEditTagDialogCreated(); //EnsureEditTagDialogCreated();
edit_tag_dialog_->SetSongs(songs, items); edit_tag_dialog_->SetSongs(songs, items);
edit_tag_dialog_->show(); edit_tag_dialog_->show();
} }
void MainWindow::EditTagDialogAccepted() { void MainWindow::EditTagDialogAccepted() {
for (PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) { for (PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) {
item->Reload(); item->Reload();
} }
@@ -1484,14 +1565,16 @@ void MainWindow::EditTagDialogAccepted() {
ui_->playlist->view()->update(); ui_->playlist->view()->update();
app_->playlist_manager()->current()->Save(); app_->playlist_manager()->current()->Save();
} }
void MainWindow::RenumberTracks() { void MainWindow::RenumberTracks() {
QModelIndexList indexes =ui_->playlist->view()->selectionModel()->selection().indexes(); QModelIndexList indexes =ui_->playlist->view()->selectionModel()->selection().indexes();
int track = 1; int track = 1;
// Get the index list in order // Get the index list in order
qStableSort(indexes); std::stable_sort(indexes.begin(), indexes.end());
// if first selected song has a track number set, start from that offset // if first selected song has a track number set, start from that offset
if (!indexes.isEmpty()) { if (!indexes.isEmpty()) {
@@ -1516,6 +1599,7 @@ void MainWindow::RenumberTracks() {
} }
track++; track++;
} }
} }
void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIndex &index) { void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIndex &index) {
@@ -1526,6 +1610,7 @@ void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIn
} }
void MainWindow::SelectionSetValue() { void MainWindow::SelectionSetValue() {
Playlist::Column column = (Playlist::Column)playlist_menu_index_.column(); Playlist::Column column = (Playlist::Column)playlist_menu_index_.column();
QVariant column_value =app_->playlist_manager()->current()->data(playlist_menu_index_); QVariant column_value =app_->playlist_manager()->current()->data(playlist_menu_index_);
@@ -1544,9 +1629,11 @@ void MainWindow::SelectionSetValue() {
NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index)); NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index));
} }
} }
} }
void MainWindow::EditValue() { void MainWindow::EditValue() {
QModelIndex current = ui_->playlist->view()->currentIndex(); QModelIndex current = ui_->playlist->view()->currentIndex();
if (!current.isValid()) return; if (!current.isValid()) return;
@@ -1566,7 +1653,7 @@ void MainWindow::EditValue() {
} }
void MainWindow::AddFile() { void MainWindow::AddFile() {
// Last used directory // Last used directory
QString directory =settings_.value("add_media_path", QDir::currentPath()).toString(); QString directory =settings_.value("add_media_path", QDir::currentPath()).toString();
@@ -1589,9 +1676,11 @@ void MainWindow::AddFile() {
MimeData *data = new MimeData; MimeData *data = new MimeData;
data->setUrls(urls); data->setUrls(urls);
AddToPlaylist(data); AddToPlaylist(data);
} }
void MainWindow::AddFolder() { void MainWindow::AddFolder() {
// Last used directory // Last used directory
QString directory =settings_.value("add_folder_path", QDir::currentPath()).toString(); QString directory =settings_.value("add_folder_path", QDir::currentPath()).toString();
@@ -1606,6 +1695,7 @@ void MainWindow::AddFolder() {
MimeData *data = new MimeData; MimeData *data = new MimeData;
data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath())); data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath()));
AddToPlaylist(data); AddToPlaylist(data);
} }
void MainWindow::AddCDTracks() { void MainWindow::AddCDTracks() {
@@ -1830,6 +1920,7 @@ void MainWindow::MoveFilesToCollection(const QList<QUrl> &urls) {
} }
void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) { void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
#ifndef Q_OS_WIN
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true); organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
organise_dialog_->SetCopy(true); organise_dialog_->SetCopy(true);
if (organise_dialog_->SetUrls(urls)) if (organise_dialog_->SetUrls(urls))
@@ -1837,6 +1928,7 @@ void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
else { else {
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device")); QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
} }
#endif
} }
#endif #endif
@@ -1956,6 +2048,15 @@ void MainWindow::PlaylistQueue() {
app_->playlist_manager()->current()->queue()->ToggleTracks(indexes); app_->playlist_manager()->current()->queue()->ToggleTracks(indexes);
} }
void MainWindow::PlaylistQueuePlayNext() {
QModelIndexList indexes;
for (const QModelIndex& proxy_index : ui_->playlist->view()->selectionModel()->selectedRows()) {
indexes << app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
}
app_->playlist_manager()->current()->queue()->InsertFirst(indexes);
}
void MainWindow::PlaylistSkip() { void MainWindow::PlaylistSkip() {
QModelIndexList indexes; QModelIndexList indexes;
@@ -1968,15 +2069,14 @@ void MainWindow::PlaylistSkip() {
} }
#ifdef HAVE_GSTREAMER #if defined(HAVE_GSTREAMER)
void MainWindow::PlaylistCopyToDevice() { void MainWindow::PlaylistCopyToDevice() {
#if !defined(Q_OS_WIN)
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows(); QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
SongList songs; SongList songs;
for (const QModelIndex &proxy_index : proxy_indexes) { for (const QModelIndex &proxy_index : proxy_indexes) {
QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index); QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata(); songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
} }
@@ -1985,9 +2085,9 @@ void MainWindow::PlaylistCopyToDevice() {
if (organise_dialog_->SetSongs(songs)) if (organise_dialog_->SetSongs(songs))
organise_dialog_->show(); organise_dialog_->show();
else { else {
QMessageBox::warning(this, tr("Error"), QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
tr("None of the selected songs were suitable for copying to a device"));
} }
#endif
} }
#endif #endif
@@ -2033,7 +2133,7 @@ SettingsDialog *MainWindow::CreateSettingsDialog() {
} }
void MainWindow::EnsureSettingsDialogCreated() { void MainWindow::EnsureSettingsDialogCreated() {
//if (settings_dialog_) return; //if (settings_dialog_) return;
//settings_dialog_.reset(new SettingsDialog(app_)); //settings_dialog_.reset(new SettingsDialog(app_));
@@ -2045,14 +2145,14 @@ void MainWindow::EnsureSettingsDialogCreated() {
// Allows custom notification preview // Allows custom notification preview
//connect(settings_dialog_.get(), SIGNAL(NotificationPreview(OSD::Behaviour,QString,QString)), SLOT(HandleNotificationPreview(OSD::Behaviour, QString, QString))); //connect(settings_dialog_.get(), SIGNAL(NotificationPreview(OSD::Behaviour,QString,QString)), SLOT(HandleNotificationPreview(OSD::Behaviour, QString, QString)));
} }
void MainWindow::OpenSettingsDialog() { void MainWindow::OpenSettingsDialog() {
EnsureSettingsDialogCreated(); EnsureSettingsDialogCreated();
settings_dialog_->show(); settings_dialog_->show();
} }
void MainWindow::OpenSettingsDialogAtPage(SettingsDialog::Page page) { void MainWindow::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
@@ -2108,7 +2208,7 @@ void MainWindow::ShowErrorDialog(const QString &message) {
} }
void MainWindow::CheckFullRescanRevisions() { void MainWindow::CheckFullRescanRevisions() {
int from = app_->database()->startup_schema_version(); int from = app_->database()->startup_schema_version();
int to = app_->database()->current_schema_version(); int to = app_->database()->current_schema_version();
@@ -2135,22 +2235,14 @@ void MainWindow::CheckFullRescanRevisions() {
} }
message += "</ul>" + tr("Would you like to run a full rescan right now?"); message += "</ul>" + tr("Would you like to run a full rescan right now?");
if(QMessageBox::question(this, tr("Collection rescan notice"), message, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) { if (QMessageBox::question(this, tr("Collection rescan notice"), message, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
app_->collection()->FullScan(); app_->collection()->FullScan();
} }
} }
} }
void MainWindow::ShowQueueManager() {
//if (!queue_manager_) {
//queue_manager_.reset(new QueueManager);
//queue_manager_->SetPlaylistManager(app_->playlist_manager());
//}
queue_manager_->show();
}
void MainWindow::PlaylistViewSelectionModelChanged() { void MainWindow::PlaylistViewSelectionModelChanged() {
connect(ui_->playlist->view()->selectionModel(),SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(PlaylistCurrentChanged(QModelIndex))); connect(ui_->playlist->view()->selectionModel(),SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(PlaylistCurrentChanged(QModelIndex)));
} }
@@ -2176,8 +2268,8 @@ bool MainWindow::winEvent(MSG *msg, long*) {
void MainWindow::Exit() { void MainWindow::Exit() {
SaveGeometry();
SavePlaybackStatus(); SavePlaybackStatus();
//settings_.setValue("show_sidebar", ui_->action_toggle_show_sidebar->isChecked());
if (app_->player()->engine()->is_fadeout_enabled()) { if (app_->player()->engine()->is_fadeout_enabled()) {
// To shut down the application when fadeout will be finished // To shut down the application when fadeout will be finished
@@ -2185,7 +2277,7 @@ void MainWindow::Exit() {
if (app_->player()->GetState() == Engine::Playing) { if (app_->player()->GetState() == Engine::Playing) {
app_->player()->Stop(); app_->player()->Stop();
hide(); hide();
tray_icon_->SetVisible(false); if (tray_icon_) tray_icon_->SetVisible(false);
return; // Don't quit the application now: wait for the fadeout finished signal return; // Don't quit the application now: wait for the fadeout finished signal
} }
} }
@@ -2232,7 +2324,7 @@ void MainWindow::AutoCompleteTags() {
} }
void MainWindow::AutoCompleteTagsAccepted() { void MainWindow::AutoCompleteTagsAccepted() {
for (PlaylistItemPtr item : autocomplete_tag_items_) { for (PlaylistItemPtr item : autocomplete_tag_items_) {
item->Reload(); item->Reload();
} }
@@ -2292,39 +2384,6 @@ void MainWindow::keyPressEvent(QKeyEvent *event) {
} }
} }
void MainWindow::FocusTidalSearchField() {
ui_->tabs->setCurrentWidget(tidal_search_view_);
tidal_search_view_->FocusSearchField();
}
void MainWindow::DoTidalSearch(const QString& query) {
FocusTidalSearchField();
tidal_search_view_->StartSearch(query);
}
void MainWindow::SearchForArtist() {
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
Song song = item->Metadata();
if (!song.albumartist().isEmpty()) {
DoTidalSearch(song.albumartist().simplified());
}
else if (!song.artist().isEmpty()) {
DoTidalSearch(song.artist().simplified());
}
}
void MainWindow::SearchForAlbum() {
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
Song song = item->Metadata();
if (!song.album().isEmpty()) {
DoTidalSearch(song.album().simplified());
}
}
void MainWindow::LoadCoverFromFile() { void MainWindow::LoadCoverFromFile() {
album_cover_choice_controller_->LoadCoverFromFile(&song_); album_cover_choice_controller_->LoadCoverFromFile(&song_);
} }
@@ -2370,7 +2429,7 @@ void MainWindow::AlbumArtLoaded(const Song &song, const QString&, const QImage &
} }
void MainWindow::GetCoverAutomatically() { void MainWindow::GetCoverAutomatically() {
// Search for cover automatically? // Search for cover automatically?
bool search = bool search =
album_cover_choice_controller_->search_cover_auto_action()->isChecked() && album_cover_choice_controller_->search_cover_auto_action()->isChecked() &&
@@ -2383,4 +2442,3 @@ void MainWindow::GetCoverAutomatically() {
if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_); if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_);
} }

View File

@@ -2,6 +2,7 @@
* Strawberry Music Player * Strawberry Music Player
* This file was part of Clementine. * This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com> * Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
* *
* Strawberry is free software: you can redistribute it and/or modify * Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@@ -56,6 +57,8 @@
#include "playlist/playlistitem.h" #include "playlist/playlistitem.h"
#include "settings/settingsdialog.h" #include "settings/settingsdialog.h"
using std::unique_ptr;
class About; class About;
class AlbumCoverManager;; class AlbumCoverManager;;
class Application; class Application;
@@ -63,8 +66,10 @@ class ContextView;
class CollectionViewContainer; class CollectionViewContainer;
class AlbumCoverChoiceController; class AlbumCoverChoiceController;
class CommandlineOptions; class CommandlineOptions;
#ifndef Q_OS_WIN
class DeviceView; class DeviceView;
class DeviceViewContainer; class DeviceViewContainer;
#endif
class EditTagDialog; class EditTagDialog;
class Equalizer; class Equalizer;
class ErrorDialog; class ErrorDialog;
@@ -73,7 +78,7 @@ class GlobalShortcuts;
class MimeData; class MimeData;
class OrganiseDialog; class OrganiseDialog;
class PlaylistListContainer; class PlaylistListContainer;
class QueueManager; class QueueView;
class Song; class Song;
class SystemTrayIcon; class SystemTrayIcon;
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT) #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
@@ -85,7 +90,7 @@ class TranscodeDialog;
#endif #endif
class Ui_MainWindow; class Ui_MainWindow;
class Windows7ThumbBar; class Windows7ThumbBar;
class TidalSearchView; class InternetSearchView;
class MainWindow : public QMainWindow, public PlatformInterface { class MainWindow : public QMainWindow, public PlatformInterface {
Q_OBJECT Q_OBJECT
@@ -134,7 +139,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
void closeEvent(QCloseEvent *event); void closeEvent(QCloseEvent *event);
#ifdef Q_OS_WIN32 #ifdef Q_OS_WIN
bool winEvent(MSG *message, long *result); bool winEvent(MSG *message, long *result);
#endif #endif
@@ -163,6 +168,7 @@ signals:
void PlaylistPlay(); void PlaylistPlay();
void PlaylistStopAfter(); void PlaylistStopAfter();
void PlaylistQueue(); void PlaylistQueue();
void PlaylistQueuePlayNext();
void PlaylistSkip(); void PlaylistSkip();
void PlaylistRemoveCurrent(); void PlaylistRemoveCurrent();
void PlaylistEditFinished(const QModelIndex& index); void PlaylistEditFinished(const QModelIndex& index);
@@ -183,7 +189,9 @@ signals:
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
void PlaylistCopyToCollection(); void PlaylistCopyToCollection();
void PlaylistMoveToCollection(); void PlaylistMoveToCollection();
#ifndef Q_OS_WIN_
void PlaylistCopyToDevice(); void PlaylistCopyToDevice();
#endif
void PlaylistOrganiseSelected(bool copy); void PlaylistOrganiseSelected(bool copy);
#endif #endif
//void PlaylistDelete(); //void PlaylistDelete();
@@ -202,7 +210,9 @@ signals:
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
void CopyFilesToCollection(const QList<QUrl>& urls); void CopyFilesToCollection(const QList<QUrl>& urls);
void MoveFilesToCollection(const QList<QUrl>& urls); void MoveFilesToCollection(const QList<QUrl>& urls);
//#ifndef Q_OS_WIN
void CopyFilesToDevice(const QList<QUrl>& urls); void CopyFilesToDevice(const QList<QUrl>& urls);
//#endif
#endif #endif
void EditFileTags(const QList<QUrl>& urls); void EditFileTags(const QList<QUrl>& urls);
@@ -243,7 +253,6 @@ signals:
void ShowTranscodeDialog(); void ShowTranscodeDialog();
#endif #endif
void ShowErrorDialog(const QString& message); void ShowErrorDialog(const QString& message);
void ShowQueueManager();
void EnsureSettingsDialogCreated(); void EnsureSettingsDialogCreated();
void EnsureEditTagDialogCreated(); void EnsureEditTagDialogCreated();
SettingsDialog *CreateSettingsDialog(); SettingsDialog *CreateSettingsDialog();
@@ -266,11 +275,6 @@ signals:
void ShowConsole(); void ShowConsole();
void FocusTidalSearchField();
void DoTidalSearch(const QString& query);
void SearchForArtist();
void SearchForAlbum();
void LoadCoverFromFile(); void LoadCoverFromFile();
void SaveCoverToFile(); void SaveCoverToFile();
void LoadCoverFromURL(); void LoadCoverFromURL();
@@ -289,7 +293,7 @@ signals:
// creates the icon by painting the full one depending on the current position // creates the icon by painting the full one depending on the current position
QPixmap CreateOverlayedIcon(int position, int scrobble_point); QPixmap CreateOverlayedIcon(int position, int scrobble_point);
void GetCoverAutomatically(); void GetCoverAutomatically();
private: private:
@@ -308,9 +312,12 @@ signals:
ContextView *context_view_; ContextView *context_view_;
CollectionViewContainer *collection_view_; CollectionViewContainer *collection_view_;
FileView *file_view_; FileView *file_view_;
#ifndef Q_OS_WIN
DeviceViewContainer *device_view_container_; DeviceViewContainer *device_view_container_;
DeviceView *device_view_; DeviceView *device_view_;
#endif
PlaylistListContainer *playlist_list_; PlaylistListContainer *playlist_list_;
QueueView *queue_view_;
Lazy<SettingsDialog> settings_dialog_; Lazy<SettingsDialog> settings_dialog_;
Lazy<AlbumCoverManager> cover_manager_; Lazy<AlbumCoverManager> cover_manager_;
@@ -322,7 +329,6 @@ signals:
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
Lazy<OrganiseDialog> organise_dialog_; Lazy<OrganiseDialog> organise_dialog_;
#endif #endif
Lazy<QueueManager> queue_manager_;
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT) #if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
std::unique_ptr<TagFetcher> tag_fetcher_; std::unique_ptr<TagFetcher> tag_fetcher_;
@@ -332,7 +338,8 @@ signals:
PlaylistItemList autocomplete_tag_items_; PlaylistItemList autocomplete_tag_items_;
#endif #endif
TidalSearchView *tidal_search_view_; InternetSearchView *tidal_search_view_;
InternetSearchView *deezer_search_view_;
QAction *collection_show_all_; QAction *collection_show_all_;
QAction *collection_show_duplicates_; QAction *collection_show_duplicates_;
@@ -347,11 +354,14 @@ signals:
#ifdef HAVE_GSTREAMER #ifdef HAVE_GSTREAMER
QAction *playlist_copy_to_collection_; QAction *playlist_copy_to_collection_;
QAction *playlist_move_to_collection_; QAction *playlist_move_to_collection_;
#ifndef Q_OS_WIN
QAction *playlist_copy_to_device_; QAction *playlist_copy_to_device_;
#endif
//QAction *playlist_delete_; //QAction *playlist_delete_;
#endif #endif
QAction *playlist_open_in_browser_; QAction *playlist_open_in_browser_;
QAction *playlist_queue_; QAction *playlist_queue_;
QAction* playlist_queue_play_next_;
QAction *playlist_skip_; QAction *playlist_skip_;
QAction *playlist_add_to_another_; QAction *playlist_add_to_another_;
QList<QAction*> playlistitem_actions_; QList<QAction*> playlistitem_actions_;
@@ -378,7 +388,6 @@ signals:
Song song_; Song song_;
Song song_playing_; Song song_playing_;
Song song_empty_;
QImage image_original_; QImage image_original_;
}; };

View File

@@ -14,7 +14,7 @@
<string>Strawberry Music Player</string> <string>Strawberry Music Player</string>
</property> </property>
<property name="windowIcon"> <property name="windowIcon">
<iconset resource="../../data/data.qrc"> <iconset resource="../../data/icons.qrc">
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset> <normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
</property> </property>
<widget class="QWidget" name="centralWidget"> <widget class="QWidget" name="centralWidget">
@@ -435,7 +435,6 @@
<string>&amp;Tools</string> <string>&amp;Tools</string>
</property> </property>
<addaction name="action_cover_manager"/> <addaction name="action_cover_manager"/>
<addaction name="action_queue_manager"/>
<addaction name="action_equalizer"/> <addaction name="action_equalizer"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="action_update_collection"/> <addaction name="action_update_collection"/>
@@ -553,7 +552,7 @@
</action> </action>
<action name="action_about_strawberry"> <action name="action_about_strawberry">
<property name="icon"> <property name="icon">
<iconset resource="../../data/data.qrc"> <iconset resource="../../data/icons.qrc">
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset> <normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
</property> </property>
<property name="text"> <property name="text">
@@ -674,11 +673,6 @@
<string>&amp;Update changed collection folders</string> <string>&amp;Update changed collection folders</string>
</property> </property>
</action> </action>
<action name="action_queue_manager">
<property name="text">
<string>&amp;Queue Manager</string>
</property>
</action>
<action name="action_about_qt"> <action name="action_about_qt">
<property name="text"> <property name="text">
<string>About &amp;Qt</string> <string>About &amp;Qt</string>
@@ -782,6 +776,7 @@
</customwidgets> </customwidgets>
<resources> <resources>
<include location="../../data/data.qrc"/> <include location="../../data/data.qrc"/>
<include location="../../data/icons.qrc"/>
</resources> </resources>
<connections/> <connections/>
</ui> </ui>

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