Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bcd29b9fd2 | ||
|
|
046c221bc6 | ||
|
|
29a39b4e7f | ||
|
|
9fb3d06aac | ||
|
|
142d5e2347 | ||
|
|
58ea0bcbb0 | ||
|
|
1c0bbe5d33 | ||
|
|
8a7bba8ef3 | ||
|
|
3b93963688 | ||
|
|
77e5d0288f | ||
|
|
460e78a1b8 | ||
|
|
fcbade267d | ||
|
|
41b99d9aa0 | ||
|
|
96c761dbb5 | ||
|
|
d297564236 | ||
|
|
bca1a98938 | ||
|
|
23205bef65 | ||
|
|
7613b2f526 | ||
|
|
c5a521af1f | ||
|
|
f15c85e807 | ||
|
|
6129ad1f4d | ||
|
|
9972dc192b | ||
|
|
32b96a25e8 | ||
|
|
9d09e7f6fe | ||
|
|
5927483402 | ||
|
|
f228f79a8a | ||
|
|
072a3065cd | ||
|
|
718bd4c081 | ||
|
|
542cc0ec2f | ||
|
|
b357634f51 | ||
|
|
6968c4d0fb | ||
|
|
e35d618133 | ||
|
|
4a23fde6bf | ||
|
|
1ae577641d | ||
|
|
686a3bb42b | ||
|
|
1771d41871 | ||
|
|
ee8f4ca7ab | ||
|
|
4197a508a3 | ||
|
|
f38ffb505d | ||
|
|
679caf73d1 | ||
|
|
56d25c346c | ||
|
|
6ba26ba289 | ||
|
|
27582b7a4e | ||
|
|
2f4417d683 | ||
|
|
de97d29a82 | ||
|
|
b782a2c8a2 | ||
|
|
298783e2c5 | ||
|
|
bc9ec8025c | ||
|
|
26459763e5 | ||
|
|
1213306657 | ||
|
|
50add12e4b | ||
|
|
67c889f982 | ||
|
|
08cba25071 | ||
|
|
ff35b01bac | ||
|
|
faee1977fe | ||
|
|
6105b99a7f | ||
|
|
4993201b70 | ||
|
|
f456ca674d | ||
|
|
2ba350f76f | ||
|
|
3fe92a62ac | ||
|
|
f4dcf6821f | ||
|
|
0c10013858 | ||
|
|
3e9530fa8d | ||
|
|
0f4ffe4fce | ||
|
|
e1c01e5d25 | ||
|
|
51021131d7 | ||
|
|
89a08d1d5e | ||
|
|
ba8717f95a | ||
|
|
c8dfb9b0db | ||
|
|
3a02ece169 | ||
|
|
262df6b461 | ||
|
|
b9516fdfd4 | ||
|
|
9de41bc027 | ||
|
|
53b5cf3855 | ||
|
|
0567358783 | ||
|
|
c97bc55c6f | ||
|
|
3ef0bf60d0 | ||
|
|
b7b8084a38 | ||
|
|
5221f13498 | ||
|
|
0c0a8d70f3 | ||
|
|
2ff971878d | ||
|
|
1a0dc1e614 | ||
|
|
4a0bd99654 | ||
|
|
5cb98e44cb | ||
|
|
13ed99b9c3 | ||
|
|
0cda4e27aa | ||
|
|
0969e7f504 | ||
|
|
cad73e18e2 | ||
|
|
9eadeddfd9 | ||
|
|
de11cb173b | ||
|
|
5853bc68d1 | ||
|
|
7d1fd9d46f | ||
|
|
c977c822d5 | ||
|
|
c05fb33ea2 | ||
|
|
b9d0b3e152 | ||
|
|
a9e905b301 | ||
|
|
a8a714c820 | ||
|
|
9349ad9383 | ||
|
|
f686f00951 | ||
|
|
3d13c12cb7 | ||
|
|
2384a42d33 | ||
|
|
f507fec905 | ||
|
|
83a9724d17 | ||
|
|
4156e26f76 | ||
|
|
6d269e1786 | ||
|
|
ea447cab37 | ||
|
|
4f3e7de441 | ||
|
|
0a81fa99fc | ||
|
|
4aad44cb62 | ||
|
|
69dda39d02 | ||
|
|
ca3ba6f136 | ||
|
|
044cf4624a | ||
|
|
1fbfabdf66 | ||
|
|
db035351be | ||
|
|
2883ef840e | ||
|
|
8254ee911d | ||
|
|
560bc0a150 | ||
|
|
827898cd38 | ||
|
|
184dec146c | ||
|
|
298dbe96c8 | ||
|
|
6d888eb51a | ||
|
|
3694765611 | ||
|
|
b07ae3d34e | ||
|
|
64bcdf4734 | ||
|
|
1c23756fc4 |
2
.gitignore
vendored
@@ -38,6 +38,8 @@ Thumbs.db
|
||||
*.nsi
|
||||
*.plist
|
||||
maketarball.sh
|
||||
dist/debian/changelog
|
||||
dist/pacman/PKGBUILD
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
|
||||
@@ -23,7 +23,7 @@ before_install:
|
||||
- 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
|
||||
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
|
||||
script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
|
||||
|
||||
8
3rdparty/qtsingleapplication/CMakeLists.txt
vendored
@@ -13,11 +13,11 @@ set(SINGLEAPP-MOC-HEADERS
|
||||
qtsinglecoreapplication.h
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
set(SINGLEAPP-SOURCES ${SINGLEAPP-SOURCES} qtlockedfile_win.cpp)
|
||||
elseif(WIN32)
|
||||
if(UNIX)
|
||||
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})
|
||||
|
||||
|
||||
2
3rdparty/qtsingleapplication/qtlocalpeer.cpp
vendored
@@ -157,7 +157,7 @@ bool QtLocalPeer::sendMessage(const QString &message, int timeout)
|
||||
Sleep(DWORD(ms));
|
||||
#else
|
||||
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
|
||||
nanosleep(&ts, NULL);
|
||||
nanosleep(&ts, nullptr);
|
||||
#endif
|
||||
}
|
||||
if (!connOk)
|
||||
|
||||
@@ -58,7 +58,7 @@ Qt::HANDLE QtLockedFile::getMutexHandle(int idx, bool doCreate)
|
||||
|
||||
Qt::HANDLE mutex;
|
||||
if (doCreate) {
|
||||
mutex = CreateMutexW(NULL, FALSE, (WCHAR*)mname.utf16());
|
||||
mutex = CreateMutexW(nullptr, FALSE, (WCHAR*)mname.utf16());
|
||||
if (!mutex) {
|
||||
qErrnoWarning("QtLockedFile::lock(): CreateMutex failed");
|
||||
return 0;
|
||||
|
||||
@@ -45,10 +45,6 @@
|
||||
#include <QWidget>
|
||||
#include <QString>
|
||||
|
||||
#ifdef HAVE_X11_ // FIXME
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#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;
|
||||
otherwise false.
|
||||
|
||||
@@ -48,10 +48,6 @@
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
|
||||
#if defined(HAVE_X11_) // FIXME
|
||||
# include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
class QtLocalPeer;
|
||||
|
||||
#if defined(Q_OS_WIN) || defined(Q_OS_WIN32)
|
||||
@@ -77,11 +73,6 @@ class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
|
||||
public:
|
||||
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
|
||||
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();
|
||||
QString id() const;
|
||||
|
||||
40
3rdparty/qxt/CMakeLists.txt
vendored
@@ -1,6 +1,13 @@
|
||||
cmake_minimum_required(VERSION 2.8.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})
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
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 WIN32 AND NOT APPLE)
|
||||
|
||||
set(QXT-SOURCES
|
||||
qxtglobal.cpp
|
||||
qxtglobalshortcut.cpp
|
||||
)
|
||||
set(QXT-SOURCES qxtglobal.cpp qxtglobalshortcut.cpp)
|
||||
set(QXT-MOC-HEADERS qxtglobalshortcut.h )
|
||||
|
||||
set(QXT-MOC-HEADERS
|
||||
qxtglobalshortcut.h
|
||||
)
|
||||
|
||||
find_package(X11)
|
||||
include_directories(${X11_INCLUDE_DIR})
|
||||
|
||||
if(WIN32)
|
||||
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp)
|
||||
if(X11_FOUND)
|
||||
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_x11.cpp)
|
||||
elseif(APPLE)
|
||||
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_mac.cpp)
|
||||
else(WIN32)
|
||||
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_x11.cpp)
|
||||
endif(WIN32)
|
||||
elseif(WIN32)
|
||||
set(QXT-SOURCES ${QXT-SOURCES} qxtglobalshortcut_win.cpp)
|
||||
endif()
|
||||
|
||||
QT5_WRAP_CPP(QXT-SOURCES-MOC ${QXT-MOC-HEADERS})
|
||||
|
||||
@@ -36,8 +34,8 @@ ADD_LIBRARY(qxt STATIC
|
||||
${QXT-SOURCES-MOC}
|
||||
)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(qxt Qt5::Core Qt5::Widgets)
|
||||
else(WIN32)
|
||||
target_link_libraries(qxt Qt5::Core Qt5::Widgets Qt5::X11Extras)
|
||||
endif(WIN32)
|
||||
target_link_libraries(qxt Qt5::Core Qt5::Widgets)
|
||||
|
||||
if(X11_FOUND)
|
||||
target_link_libraries(qxt Qt5::X11Extras)
|
||||
endif(X11_FOUND)
|
||||
|
||||
1
3rdparty/qxt/qxtglobal.cpp
vendored
@@ -1,4 +1,3 @@
|
||||
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
|
||||
107
3rdparty/qxt/qxtglobal.h
vendored
@@ -1,4 +1,3 @@
|
||||
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
@@ -161,73 +160,73 @@ template <typename PUB>
|
||||
class QxtPrivate
|
||||
{
|
||||
public:
|
||||
virtual ~QxtPrivate()
|
||||
{}
|
||||
inline void QXT_setPublic(PUB* pub)
|
||||
{
|
||||
qxt_p_ptr = pub;
|
||||
}
|
||||
virtual ~QxtPrivate()
|
||||
{}
|
||||
inline void QXT_setPublic(PUB* pub)
|
||||
{
|
||||
qxt_p_ptr = pub;
|
||||
}
|
||||
|
||||
protected:
|
||||
inline PUB& qxt_p()
|
||||
{
|
||||
return *qxt_p_ptr;
|
||||
}
|
||||
inline const PUB& qxt_p() const
|
||||
{
|
||||
return *qxt_p_ptr;
|
||||
}
|
||||
inline PUB* qxt_ptr()
|
||||
{
|
||||
return qxt_p_ptr;
|
||||
}
|
||||
inline const PUB* qxt_ptr() const
|
||||
{
|
||||
return qxt_p_ptr;
|
||||
}
|
||||
inline PUB& qxt_p()
|
||||
{
|
||||
return *qxt_p_ptr;
|
||||
}
|
||||
inline const PUB& qxt_p() const
|
||||
{
|
||||
return *qxt_p_ptr;
|
||||
}
|
||||
inline PUB* qxt_ptr()
|
||||
{
|
||||
return qxt_p_ptr;
|
||||
}
|
||||
inline const PUB* qxt_ptr() const
|
||||
{
|
||||
return qxt_p_ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
PUB* qxt_p_ptr;
|
||||
PUB* qxt_p_ptr;
|
||||
};
|
||||
|
||||
template <typename PUB, typename PVT>
|
||||
class QxtPrivateInterface
|
||||
{
|
||||
friend class QxtPrivate<PUB>;
|
||||
friend class QxtPrivate<PUB>;
|
||||
public:
|
||||
QxtPrivateInterface()
|
||||
{
|
||||
pvt = new PVT;
|
||||
}
|
||||
~QxtPrivateInterface()
|
||||
{
|
||||
delete pvt;
|
||||
}
|
||||
QxtPrivateInterface()
|
||||
{
|
||||
pvt = new PVT;
|
||||
}
|
||||
~QxtPrivateInterface()
|
||||
{
|
||||
delete pvt;
|
||||
}
|
||||
|
||||
inline void setPublic(PUB* pub)
|
||||
{
|
||||
pvt->QXT_setPublic(pub);
|
||||
}
|
||||
inline PVT& operator()()
|
||||
{
|
||||
return *static_cast<PVT*>(pvt);
|
||||
}
|
||||
inline const PVT& operator()() const
|
||||
{
|
||||
return *static_cast<PVT*>(pvt);
|
||||
}
|
||||
inline PVT * operator->()
|
||||
{
|
||||
inline void setPublic(PUB* pub)
|
||||
{
|
||||
pvt->QXT_setPublic(pub);
|
||||
}
|
||||
inline PVT& operator()()
|
||||
{
|
||||
return *static_cast<PVT*>(pvt);
|
||||
}
|
||||
inline const PVT& operator()() const
|
||||
{
|
||||
return *static_cast<PVT*>(pvt);
|
||||
}
|
||||
inline PVT * operator->()
|
||||
{
|
||||
return static_cast<PVT*>(pvt);
|
||||
}
|
||||
inline const PVT * operator->() const
|
||||
{
|
||||
}
|
||||
inline const PVT * operator->() const
|
||||
{
|
||||
return static_cast<PVT*>(pvt);
|
||||
}
|
||||
}
|
||||
private:
|
||||
QxtPrivateInterface(const QxtPrivateInterface&) { }
|
||||
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
|
||||
QxtPrivate<PUB>* pvt;
|
||||
QxtPrivateInterface(const QxtPrivateInterface&) { }
|
||||
QxtPrivateInterface& operator=(const QxtPrivateInterface&) { }
|
||||
QxtPrivate<PUB>* pvt;
|
||||
};
|
||||
|
||||
#endif // QXT_GLOBAL
|
||||
|
||||
221
3rdparty/qxt/qxtglobalshortcut.cpp
vendored
@@ -38,185 +38,160 @@
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
|
||||
bool QxtGlobalShortcutPrivate::error = false;
|
||||
#ifndef Q_OS_MAC
|
||||
#ifndef Q_OS_MACOS
|
||||
int QxtGlobalShortcutPrivate::ref = 0;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
QAbstractEventDispatcher::EventFilter QxtGlobalShortcutPrivate::prevEventFilter = 0;
|
||||
#endif
|
||||
#endif // Q_OS_MAC
|
||||
#endif // Q_OS_MACOS
|
||||
QHash<QPair<quint32, quint32>, QxtGlobalShortcut*> QxtGlobalShortcutPrivate::shortcuts;
|
||||
|
||||
QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier)
|
||||
{
|
||||
#ifndef Q_OS_MAC
|
||||
if (!ref++)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
prevEventFilter = QAbstractEventDispatcher::instance()->setEventFilter(eventFilter);
|
||||
#else
|
||||
QxtGlobalShortcutPrivate::QxtGlobalShortcutPrivate() : enabled(true), key(Qt::Key(0)), mods(Qt::NoModifier) {
|
||||
#ifndef Q_OS_MACOS
|
||||
if (!ref++)
|
||||
QAbstractEventDispatcher::instance()->installNativeEventFilter(this);
|
||||
#endif
|
||||
#endif // Q_OS_MAC
|
||||
#endif // Q_OS_MACOS
|
||||
}
|
||||
|
||||
QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate()
|
||||
{
|
||||
#ifndef Q_OS_MAC
|
||||
if (!--ref)
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
QAbstractEventDispatcher::instance()->setEventFilter(prevEventFilter);
|
||||
#else
|
||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
|
||||
#endif
|
||||
#endif // Q_OS_MAC
|
||||
QxtGlobalShortcutPrivate::~QxtGlobalShortcutPrivate() {
|
||||
#ifndef Q_OS_MACOS
|
||||
if (!--ref)
|
||||
QAbstractEventDispatcher::instance()->removeNativeEventFilter(this);
|
||||
#endif // Q_OS_MACOS
|
||||
}
|
||||
|
||||
bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut)
|
||||
{
|
||||
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
|
||||
key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]);
|
||||
mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods);
|
||||
const quint32 nativeKey = nativeKeycode(key);
|
||||
const quint32 nativeMods = nativeModifiers(mods);
|
||||
const bool res = registerShortcut(nativeKey, nativeMods);
|
||||
if (res)
|
||||
shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
|
||||
else
|
||||
qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString();
|
||||
return res;
|
||||
bool QxtGlobalShortcutPrivate::setShortcut(const QKeySequence& shortcut) {
|
||||
|
||||
Qt::KeyboardModifiers allMods = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier;
|
||||
key = shortcut.isEmpty() ? Qt::Key(0) : Qt::Key((shortcut[0] ^ allMods) & shortcut[0]);
|
||||
mods = shortcut.isEmpty() ? Qt::KeyboardModifiers(0) : Qt::KeyboardModifiers(shortcut[0] & allMods);
|
||||
const quint32 nativeKey = nativeKeycode(key);
|
||||
const quint32 nativeMods = nativeModifiers(mods);
|
||||
const bool res = registerShortcut(nativeKey, nativeMods);
|
||||
if (res)
|
||||
shortcuts.insert(qMakePair(nativeKey, nativeMods), &qxt_p());
|
||||
else
|
||||
qWarning() << "QxtGlobalShortcut failed to register:" << QKeySequence(key + mods).toString();
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
bool QxtGlobalShortcutPrivate::unsetShortcut()
|
||||
{
|
||||
bool res = false;
|
||||
const quint32 nativeKey = nativeKeycode(key);
|
||||
const quint32 nativeMods = nativeModifiers(mods);
|
||||
if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p())
|
||||
res = unregisterShortcut(nativeKey, nativeMods);
|
||||
if (res)
|
||||
shortcuts.remove(qMakePair(nativeKey, nativeMods));
|
||||
else
|
||||
qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString();
|
||||
key = Qt::Key(0);
|
||||
mods = Qt::KeyboardModifiers(0);
|
||||
return res;
|
||||
bool QxtGlobalShortcutPrivate::unsetShortcut() {
|
||||
bool res = false;
|
||||
const quint32 nativeKey = nativeKeycode(key);
|
||||
const quint32 nativeMods = nativeModifiers(mods);
|
||||
if (shortcuts.value(qMakePair(nativeKey, nativeMods)) == &qxt_p())
|
||||
res = unregisterShortcut(nativeKey, nativeMods);
|
||||
if (res)
|
||||
shortcuts.remove(qMakePair(nativeKey, nativeMods));
|
||||
else
|
||||
qWarning() << "QxtGlobalShortcut failed to unregister:" << QKeySequence(key + mods).toString();
|
||||
key = Qt::Key(0);
|
||||
mods = Qt::KeyboardModifiers(0);
|
||||
return res;
|
||||
}
|
||||
|
||||
void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods)
|
||||
{
|
||||
QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
|
||||
if (shortcut && shortcut->isEnabled())
|
||||
emit shortcut->activated();
|
||||
void QxtGlobalShortcutPrivate::activateShortcut(quint32 nativeKey, quint32 nativeMods) {
|
||||
QxtGlobalShortcut* shortcut = shortcuts.value(qMakePair(nativeKey, nativeMods));
|
||||
if (shortcut && shortcut->isEnabled())
|
||||
emit shortcut->activated();
|
||||
}
|
||||
|
||||
/*!
|
||||
\class QxtGlobalShortcut
|
||||
\inmodule QxtWidgets
|
||||
\brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey".
|
||||
\class QxtGlobalShortcut
|
||||
\inmodule QxtWidgets
|
||||
\brief The QxtGlobalShortcut class provides a global shortcut aka "hotkey".
|
||||
|
||||
A global shortcut triggers even if the application is not active. This
|
||||
makes it easy to implement applications that react to certain shortcuts
|
||||
still if some other application is active or if the application is for
|
||||
example minimized to the system tray.
|
||||
A global shortcut triggers even if the application is not active. This
|
||||
makes it easy to implement applications that react to certain shortcuts
|
||||
still if some other application is active or if the application is for
|
||||
example minimized to the system tray.
|
||||
|
||||
Example usage:
|
||||
\code
|
||||
QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
|
||||
connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
|
||||
shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));
|
||||
\endcode
|
||||
Example usage:
|
||||
\code
|
||||
QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(window);
|
||||
connect(shortcut, SIGNAL(activated()), window, SLOT(toggleVisibility()));
|
||||
shortcut->setShortcut(QKeySequence("Ctrl+Shift+F12"));
|
||||
\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)
|
||||
: QObject(parent)
|
||||
{
|
||||
QXT_INIT_PRIVATE(QxtGlobalShortcut);
|
||||
QxtGlobalShortcut::QxtGlobalShortcut(QObject* parent) : QObject(parent) {
|
||||
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)
|
||||
: QObject(parent)
|
||||
{
|
||||
QXT_INIT_PRIVATE(QxtGlobalShortcut);
|
||||
setShortcut(shortcut);
|
||||
QxtGlobalShortcut::QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent) : QObject(parent) {
|
||||
QXT_INIT_PRIVATE(QxtGlobalShortcut);
|
||||
setShortcut(shortcut);
|
||||
}
|
||||
|
||||
/*!
|
||||
Destructs the QxtGlobalShortcut.
|
||||
Destructs the QxtGlobalShortcut.
|
||||
*/
|
||||
QxtGlobalShortcut::~QxtGlobalShortcut()
|
||||
{
|
||||
if (qxt_d().key != 0)
|
||||
qxt_d().unsetShortcut();
|
||||
QxtGlobalShortcut::~QxtGlobalShortcut() {
|
||||
if (qxt_d().key != 0) qxt_d().unsetShortcut();
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QxtGlobalShortcut::shortcut
|
||||
\brief the shortcut key sequence
|
||||
\property QxtGlobalShortcut::shortcut
|
||||
\brief the shortcut key sequence
|
||||
|
||||
\bold {Note:} Notice that corresponding key press and release events are not
|
||||
delivered for registered global shortcuts even if they are disabled.
|
||||
Also, comma separated key sequences are not supported.
|
||||
Only the first part is used:
|
||||
\bold {Note:} Notice that corresponding key press and release events are not
|
||||
delivered for registered global shortcuts even if they are disabled.
|
||||
Also, comma separated key sequences are not supported.
|
||||
Only the first part is used:
|
||||
|
||||
\code
|
||||
qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B"));
|
||||
Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A"));
|
||||
\endcode
|
||||
\code
|
||||
qxtShortcut->setShortcut(QKeySequence("Ctrl+Alt+A,Ctrl+Alt+B"));
|
||||
Q_ASSERT(qxtShortcut->shortcut() == QKeySequence("Ctrl+Alt+A"));
|
||||
\endcode
|
||||
*/
|
||||
QKeySequence QxtGlobalShortcut::shortcut() const
|
||||
{
|
||||
return QKeySequence(qxt_d().key | qxt_d().mods);
|
||||
QKeySequence QxtGlobalShortcut::shortcut() const {
|
||||
return QKeySequence(qxt_d().key | qxt_d().mods);
|
||||
}
|
||||
|
||||
bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut)
|
||||
{
|
||||
if (qxt_d().key != 0)
|
||||
qxt_d().unsetShortcut();
|
||||
return qxt_d().setShortcut(shortcut);
|
||||
bool QxtGlobalShortcut::setShortcut(const QKeySequence& shortcut) {
|
||||
if (qxt_d().key != 0)
|
||||
qxt_d().unsetShortcut();
|
||||
return qxt_d().setShortcut(shortcut);
|
||||
}
|
||||
|
||||
/*!
|
||||
\property QxtGlobalShortcut::enabled
|
||||
\brief whether the shortcut is enabled
|
||||
\property QxtGlobalShortcut::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
|
||||
{
|
||||
return qxt_d().enabled;
|
||||
bool QxtGlobalShortcut::isEnabled() const {
|
||||
return qxt_d().enabled;
|
||||
}
|
||||
|
||||
void QxtGlobalShortcut::setEnabled(bool enabled)
|
||||
{
|
||||
qxt_d().enabled = enabled;
|
||||
void QxtGlobalShortcut::setEnabled(bool enabled) {
|
||||
qxt_d().enabled = enabled;
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the shortcut \a disabled.
|
||||
Sets the shortcut \a disabled.
|
||||
|
||||
\sa enabled
|
||||
\sa enabled
|
||||
*/
|
||||
void QxtGlobalShortcut::setDisabled(bool disabled)
|
||||
{
|
||||
qxt_d().enabled = !disabled;
|
||||
void QxtGlobalShortcut::setDisabled(bool disabled) {
|
||||
qxt_d().enabled = !disabled;
|
||||
}
|
||||
|
||||
|
||||
33
3rdparty/qxt/qxtglobalshortcut.h
vendored
@@ -1,4 +1,3 @@
|
||||
#ifndef QXTGLOBALSHORTCUT_H
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
@@ -29,6 +28,7 @@
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QXTGLOBALSHORTCUT_H
|
||||
#define QXTGLOBALSHORTCUT_H
|
||||
|
||||
#include <QObject>
|
||||
@@ -39,30 +39,29 @@
|
||||
|
||||
class QxtGlobalShortcutPrivate;
|
||||
|
||||
class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QXT_DECLARE_PRIVATE(QxtGlobalShortcut)
|
||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
||||
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
|
||||
class QXT_GUI_EXPORT QxtGlobalShortcut : public QObject {
|
||||
Q_OBJECT
|
||||
QXT_DECLARE_PRIVATE(QxtGlobalShortcut)
|
||||
Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
|
||||
Q_PROPERTY(QKeySequence shortcut READ shortcut WRITE setShortcut)
|
||||
|
||||
public:
|
||||
explicit QxtGlobalShortcut(QObject* parent = 0);
|
||||
explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = 0);
|
||||
virtual ~QxtGlobalShortcut();
|
||||
explicit QxtGlobalShortcut(QObject* parent = nullptr);
|
||||
explicit QxtGlobalShortcut(const QKeySequence& shortcut, QObject* parent = nullptr);
|
||||
~QxtGlobalShortcut();
|
||||
|
||||
QKeySequence shortcut() const;
|
||||
bool setShortcut(const QKeySequence& shortcut);
|
||||
QKeySequence shortcut() const;
|
||||
bool setShortcut(const QKeySequence& shortcut);
|
||||
|
||||
bool isEnabled() const;
|
||||
bool isEnabled() const;
|
||||
|
||||
public Q_SLOTS:
|
||||
void setEnabled(bool enabled = true);
|
||||
void setDisabled(bool disabled = true);
|
||||
void setEnabled(bool enabled = true);
|
||||
void setDisabled(bool disabled = true);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated();
|
||||
void activated();
|
||||
};
|
||||
|
||||
#endif // QXTGLOBALSHORTCUT_H
|
||||
#endif // QXTGLOBALSHORTCUT_H
|
||||
|
||||
|
||||
405
3rdparty/qxt/qxtglobalshortcut_mac.cpp
vendored
@@ -1,4 +1,3 @@
|
||||
#include <Carbon/Carbon.h>
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
@@ -29,230 +28,180 @@
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include <QtDebug>
|
||||
#include <QApplication>
|
||||
|
||||
typedef QPair<uint, uint> Identifier;
|
||||
static QMap<quint32, EventHotKeyRef> keyRefs;
|
||||
static QHash<Identifier, quint32> keyIDs;
|
||||
static quint32 hotKeySerial = 0;
|
||||
static bool qxt_mac_handler_installed = false;
|
||||
|
||||
OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data)
|
||||
{
|
||||
Q_UNUSED(nextHandler);
|
||||
Q_UNUSED(data);
|
||||
if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed)
|
||||
{
|
||||
EventHotKeyID keyID;
|
||||
GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(keyID), NULL, &keyID);
|
||||
Identifier id = keyIDs.key(keyID.id);
|
||||
QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first);
|
||||
}
|
||||
return noErr;
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
native |= shiftKey;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
native |= cmdKey;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
native |= optionKey;
|
||||
if (modifiers & Qt::MetaModifier)
|
||||
native |= controlKey;
|
||||
if (modifiers & Qt::KeypadModifier)
|
||||
native |= kEventKeyModifierNumLockMask;
|
||||
return native;
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
|
||||
{
|
||||
UTF16Char ch;
|
||||
// Constants found in NSEvent.h from AppKit.framework
|
||||
switch (key)
|
||||
{
|
||||
case Qt::Key_Return:
|
||||
return kVK_Return;
|
||||
case Qt::Key_Enter:
|
||||
return kVK_ANSI_KeypadEnter;
|
||||
case Qt::Key_Tab:
|
||||
return kVK_Tab;
|
||||
case Qt::Key_Space:
|
||||
return kVK_Space;
|
||||
case Qt::Key_Backspace:
|
||||
return kVK_Delete;
|
||||
case Qt::Key_Control:
|
||||
return kVK_Command;
|
||||
case Qt::Key_Shift:
|
||||
return kVK_Shift;
|
||||
case Qt::Key_CapsLock:
|
||||
return kVK_CapsLock;
|
||||
case Qt::Key_Option:
|
||||
return kVK_Option;
|
||||
case Qt::Key_Meta:
|
||||
return kVK_Control;
|
||||
case Qt::Key_F17:
|
||||
return kVK_F17;
|
||||
case Qt::Key_VolumeUp:
|
||||
return kVK_VolumeUp;
|
||||
case Qt::Key_VolumeDown:
|
||||
return kVK_VolumeDown;
|
||||
case Qt::Key_F18:
|
||||
return kVK_F18;
|
||||
case Qt::Key_F19:
|
||||
return kVK_F19;
|
||||
case Qt::Key_F20:
|
||||
return kVK_F20;
|
||||
case Qt::Key_F5:
|
||||
return kVK_F5;
|
||||
case Qt::Key_F6:
|
||||
return kVK_F6;
|
||||
case Qt::Key_F7:
|
||||
return kVK_F7;
|
||||
case Qt::Key_F3:
|
||||
return kVK_F3;
|
||||
case Qt::Key_F8:
|
||||
return kVK_F8;
|
||||
case Qt::Key_F9:
|
||||
return kVK_F9;
|
||||
case Qt::Key_F11:
|
||||
return kVK_F11;
|
||||
case Qt::Key_F13:
|
||||
return kVK_F13;
|
||||
case Qt::Key_F16:
|
||||
return kVK_F16;
|
||||
case Qt::Key_F14:
|
||||
return kVK_F14;
|
||||
case Qt::Key_F10:
|
||||
return kVK_F10;
|
||||
case Qt::Key_F12:
|
||||
return kVK_F12;
|
||||
case Qt::Key_F15:
|
||||
return kVK_F15;
|
||||
case Qt::Key_Help:
|
||||
return kVK_Help;
|
||||
case Qt::Key_Home:
|
||||
return kVK_Home;
|
||||
case Qt::Key_PageUp:
|
||||
return kVK_PageUp;
|
||||
case Qt::Key_Delete:
|
||||
return kVK_ForwardDelete;
|
||||
case Qt::Key_F4:
|
||||
return kVK_F4;
|
||||
case Qt::Key_End:
|
||||
return kVK_End;
|
||||
case Qt::Key_F2:
|
||||
return kVK_F2;
|
||||
case Qt::Key_PageDown:
|
||||
return kVK_PageDown;
|
||||
case Qt::Key_F1:
|
||||
return kVK_F1;
|
||||
case Qt::Key_Left:
|
||||
return kVK_LeftArrow;
|
||||
case Qt::Key_Right:
|
||||
return kVK_RightArrow;
|
||||
case Qt::Key_Down:
|
||||
return kVK_DownArrow;
|
||||
case Qt::Key_Up:
|
||||
return kVK_UpArrow;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (key == Qt::Key_Escape) ch = 27;
|
||||
else if (key == Qt::Key_Return) ch = 13;
|
||||
else if (key == Qt::Key_Enter) ch = 3;
|
||||
else if (key == Qt::Key_Tab) ch = 9;
|
||||
else ch = key;
|
||||
|
||||
CFDataRef currentLayoutData;
|
||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
||||
|
||||
if (currentKeyboard == NULL)
|
||||
return 0;
|
||||
|
||||
currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
|
||||
CFRelease(currentKeyboard);
|
||||
if (currentLayoutData == NULL)
|
||||
return 0;
|
||||
|
||||
UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
|
||||
UCKeyboardTypeHeader* table = header->keyboardTypeList;
|
||||
|
||||
uint8_t *data = (uint8_t*)header;
|
||||
// God, would a little documentation for this shit kill you...
|
||||
for (quint32 i=0; i < header->keyboardTypeCount; i++)
|
||||
{
|
||||
UCKeyStateRecordsIndex* stateRec = 0;
|
||||
if (table[i].keyStateRecordsIndexOffset != 0)
|
||||
{
|
||||
stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset);
|
||||
if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
|
||||
}
|
||||
|
||||
UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset);
|
||||
if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
|
||||
|
||||
for (quint32 j=0; j < charTable->keyToCharTableCount; j++)
|
||||
{
|
||||
UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]);
|
||||
for (quint32 k=0; k < charTable->keyToCharTableSize; k++)
|
||||
{
|
||||
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);
|
||||
}
|
||||
#include <Carbon/Carbon.h>
|
||||
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
#include <QMap>
|
||||
#include <QHash>
|
||||
#include <QPair>
|
||||
#include <QtDebug>
|
||||
#include <QApplication>
|
||||
|
||||
typedef QPair<uint, uint> Identifier;
|
||||
static QMap<quint32, EventHotKeyRef> keyRefs;
|
||||
static QHash<Identifier, quint32> keyIDs;
|
||||
static quint32 hotKeySerial = 0;
|
||||
static bool qxt_mac_handler_installed = false;
|
||||
|
||||
OSStatus qxt_mac_handle_hot_key(EventHandlerCallRef nextHandler, EventRef event, void* data) {
|
||||
|
||||
Q_UNUSED(nextHandler);
|
||||
Q_UNUSED(data);
|
||||
if (GetEventClass(event) == kEventClassKeyboard && GetEventKind(event) == kEventHotKeyPressed) {
|
||||
EventHotKeyID keyID;
|
||||
GetEventParameter(event, kEventParamDirectObject, typeEventHotKeyID, nullptr, sizeof(keyID), nullptr, &keyID);
|
||||
Identifier id = keyIDs.key(keyID.id);
|
||||
QxtGlobalShortcutPrivate::activateShortcut(id.second, id.first);
|
||||
}
|
||||
return noErr;
|
||||
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
|
||||
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier) native |= shiftKey;
|
||||
if (modifiers & Qt::ControlModifier) native |= cmdKey;
|
||||
if (modifiers & Qt::AltModifier) native |= optionKey;
|
||||
if (modifiers & Qt::MetaModifier) native |= controlKey;
|
||||
if (modifiers & Qt::KeypadModifier) native |= kEventKeyModifierNumLockMask;
|
||||
return native;
|
||||
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
|
||||
|
||||
UTF16Char ch;
|
||||
// Constants found in NSEvent.h from AppKit.framework
|
||||
switch (key) {
|
||||
case Qt::Key_Return: return kVK_Return;
|
||||
case Qt::Key_Enter: return kVK_ANSI_KeypadEnter;
|
||||
case Qt::Key_Tab: return kVK_Tab;
|
||||
case Qt::Key_Space: return kVK_Space;
|
||||
case Qt::Key_Backspace: return kVK_Delete;
|
||||
case Qt::Key_Control: return kVK_Command;
|
||||
case Qt::Key_Shift: return kVK_Shift;
|
||||
case Qt::Key_CapsLock: return kVK_CapsLock;
|
||||
case Qt::Key_Option: return kVK_Option;
|
||||
case Qt::Key_Meta: return kVK_Control;
|
||||
case Qt::Key_F17: return kVK_F17;
|
||||
case Qt::Key_VolumeUp: return kVK_VolumeUp;
|
||||
case Qt::Key_VolumeDown: return kVK_VolumeDown;
|
||||
case Qt::Key_F18: return kVK_F18;
|
||||
case Qt::Key_F19: return kVK_F19;
|
||||
case Qt::Key_F20: return kVK_F20;
|
||||
case Qt::Key_F5: return kVK_F5;
|
||||
case Qt::Key_F6: return kVK_F6;
|
||||
case Qt::Key_F7: return kVK_F7;
|
||||
case Qt::Key_F3: return kVK_F3;
|
||||
case Qt::Key_F8: return kVK_F8;
|
||||
case Qt::Key_F9: return kVK_F9;
|
||||
case Qt::Key_F11: return kVK_F11;
|
||||
case Qt::Key_F13: return kVK_F13;
|
||||
case Qt::Key_F16: return kVK_F16;
|
||||
case Qt::Key_F14: return kVK_F14;
|
||||
case Qt::Key_F10: return kVK_F10;
|
||||
case Qt::Key_F12: return kVK_F12;
|
||||
case Qt::Key_F15: return kVK_F15;
|
||||
case Qt::Key_Help: return kVK_Help;
|
||||
case Qt::Key_Home: return kVK_Home;
|
||||
case Qt::Key_PageUp: return kVK_PageUp;
|
||||
case Qt::Key_Delete: return kVK_ForwardDelete;
|
||||
case Qt::Key_F4: return kVK_F4;
|
||||
case Qt::Key_End: return kVK_End;
|
||||
case Qt::Key_F2: return kVK_F2;
|
||||
case Qt::Key_PageDown: return kVK_PageDown;
|
||||
case Qt::Key_F1: return kVK_F1;
|
||||
case Qt::Key_Left: return kVK_LeftArrow;
|
||||
case Qt::Key_Right: return kVK_RightArrow;
|
||||
case Qt::Key_Down: return kVK_DownArrow;
|
||||
case Qt::Key_Up: return kVK_UpArrow;
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
if (key == Qt::Key_Escape) ch = 27;
|
||||
else if (key == Qt::Key_Return) ch = 13;
|
||||
else if (key == Qt::Key_Enter) ch = 3;
|
||||
else if (key == Qt::Key_Tab) ch = 9;
|
||||
else ch = key;
|
||||
|
||||
CFDataRef currentLayoutData;
|
||||
TISInputSourceRef currentKeyboard = TISCopyCurrentKeyboardInputSource();
|
||||
|
||||
if (currentKeyboard == nullptr)
|
||||
return 0;
|
||||
|
||||
currentLayoutData = (CFDataRef)TISGetInputSourceProperty(currentKeyboard, kTISPropertyUnicodeKeyLayoutData);
|
||||
CFRelease(currentKeyboard);
|
||||
if (currentLayoutData == nullptr)
|
||||
return 0;
|
||||
|
||||
UCKeyboardLayout* header = (UCKeyboardLayout*)CFDataGetBytePtr(currentLayoutData);
|
||||
UCKeyboardTypeHeader* table = header->keyboardTypeList;
|
||||
|
||||
uint8_t *data = (uint8_t*)header;
|
||||
// God, would a little documentation for this shit kill you...
|
||||
for (quint32 i=0; i < header->keyboardTypeCount; i++) {
|
||||
UCKeyStateRecordsIndex* stateRec = 0;
|
||||
if (table[i].keyStateRecordsIndexOffset != 0) {
|
||||
stateRec = reinterpret_cast<UCKeyStateRecordsIndex*>(data + table[i].keyStateRecordsIndexOffset);
|
||||
if (stateRec->keyStateRecordsIndexFormat != kUCKeyStateRecordsIndexFormat) stateRec = 0;
|
||||
}
|
||||
|
||||
UCKeyToCharTableIndex* charTable = reinterpret_cast<UCKeyToCharTableIndex*>(data + table[i].keyToCharTableIndexOffset);
|
||||
if (charTable->keyToCharTableIndexFormat != kUCKeyToCharTableIndexFormat) continue;
|
||||
|
||||
for (quint32 j=0; j < charTable->keyToCharTableCount; j++) {
|
||||
UCKeyOutput* keyToChar = reinterpret_cast<UCKeyOutput*>(data + charTable->keyToCharTableOffsets[j]);
|
||||
for (quint32 k=0; k < charTable->keyToCharTableSize; k++) {
|
||||
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, nullptr, nullptr);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
156
3rdparty/qxt/qxtglobalshortcut_p.h
vendored
@@ -1,84 +1,72 @@
|
||||
#ifndef QXTGLOBALSHORTCUT_P_H
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the LibQxt project nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** 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
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** 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
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#define QXTGLOBALSHORTCUT_P_H
|
||||
|
||||
#include "qxtglobalshortcut.h"
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QKeySequence>
|
||||
#include <QHash>
|
||||
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#endif
|
||||
|
||||
|
||||
class QxtGlobalShortcutPrivate : public QxtPrivate<QxtGlobalShortcut>
|
||||
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||
,public QAbstractNativeEventFilter
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
|
||||
QxtGlobalShortcutPrivate();
|
||||
~QxtGlobalShortcutPrivate();
|
||||
|
||||
bool enabled;
|
||||
Qt::Key key;
|
||||
Qt::KeyboardModifiers mods;
|
||||
|
||||
bool setShortcut(const QKeySequence& shortcut);
|
||||
bool unsetShortcut();
|
||||
|
||||
static bool error;
|
||||
#ifndef Q_OS_MAC
|
||||
static int ref;
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
static QAbstractEventDispatcher::EventFilter prevEventFilter;
|
||||
static bool eventFilter(void* message);
|
||||
#else
|
||||
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
|
||||
#endif // QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
|
||||
|
||||
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
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the LibQxt project nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** 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
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** 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
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef QXTGLOBALSHORTCUT_P_H
|
||||
#define QXTGLOBALSHORTCUT_P_H
|
||||
|
||||
#include "qxtglobalshortcut.h"
|
||||
|
||||
#include <QHash>
|
||||
#include <QAbstractEventDispatcher>
|
||||
#include <QAbstractNativeEventFilter>
|
||||
#include <QKeySequence>
|
||||
|
||||
class QxtGlobalShortcutPrivate : public QxtPrivate<QxtGlobalShortcut>, public QAbstractNativeEventFilter {
|
||||
public:
|
||||
QXT_DECLARE_PUBLIC(QxtGlobalShortcut)
|
||||
QxtGlobalShortcutPrivate();
|
||||
~QxtGlobalShortcutPrivate();
|
||||
|
||||
bool enabled;
|
||||
Qt::Key key;
|
||||
Qt::KeyboardModifiers mods;
|
||||
|
||||
bool setShortcut(const QKeySequence& shortcut);
|
||||
bool unsetShortcut();
|
||||
|
||||
static bool error;
|
||||
#ifndef Q_OS_MACOS
|
||||
static int ref;
|
||||
virtual bool nativeEventFilter(const QByteArray & eventType, void * message, long * result);
|
||||
#endif // Q_OS_MAC
|
||||
|
||||
static void activateShortcut(quint32 nativeKey, quint32 nativeMods);
|
||||
|
||||
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
|
||||
|
||||
486
3rdparty/qxt/qxtglobalshortcut_win.cpp
vendored
@@ -1,247 +1,239 @@
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the LibQxt project nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** 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
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** 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
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
bool QxtGlobalShortcutPrivate::eventFilter(void* message)
|
||||
{
|
||||
#else
|
||||
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
|
||||
void * message, long * result)
|
||||
{
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
#endif
|
||||
MSG* msg = static_cast<MSG*>(message);
|
||||
if (msg->message == WM_HOTKEY)
|
||||
{
|
||||
const quint32 keycode = HIWORD(msg->lParam);
|
||||
const quint32 modifiers = LOWORD(msg->lParam);
|
||||
activateShortcut(keycode, modifiers);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
native |= MOD_SHIFT;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
native |= MOD_CONTROL;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
native |= MOD_ALT;
|
||||
if (modifiers & Qt::MetaModifier)
|
||||
native |= MOD_WIN;
|
||||
// TODO: resolve these?
|
||||
//if (modifiers & Qt::KeypadModifier)
|
||||
//if (modifiers & Qt::GroupSwitchModifier)
|
||||
return native;
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case Qt::Key_Escape:
|
||||
return VK_ESCAPE;
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Backtab:
|
||||
return VK_TAB;
|
||||
case Qt::Key_Backspace:
|
||||
return VK_BACK;
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
return VK_RETURN;
|
||||
case Qt::Key_Insert:
|
||||
return VK_INSERT;
|
||||
case Qt::Key_Delete:
|
||||
return VK_DELETE;
|
||||
case Qt::Key_Pause:
|
||||
return VK_PAUSE;
|
||||
case Qt::Key_Print:
|
||||
return VK_PRINT;
|
||||
case Qt::Key_Clear:
|
||||
return VK_CLEAR;
|
||||
case Qt::Key_Home:
|
||||
return VK_HOME;
|
||||
case Qt::Key_End:
|
||||
return VK_END;
|
||||
case Qt::Key_Left:
|
||||
return VK_LEFT;
|
||||
case Qt::Key_Up:
|
||||
return VK_UP;
|
||||
case Qt::Key_Right:
|
||||
return VK_RIGHT;
|
||||
case Qt::Key_Down:
|
||||
return VK_DOWN;
|
||||
case Qt::Key_PageUp:
|
||||
return VK_PRIOR;
|
||||
case Qt::Key_PageDown:
|
||||
return VK_NEXT;
|
||||
case Qt::Key_F1:
|
||||
return VK_F1;
|
||||
case Qt::Key_F2:
|
||||
return VK_F2;
|
||||
case Qt::Key_F3:
|
||||
return VK_F3;
|
||||
case Qt::Key_F4:
|
||||
return VK_F4;
|
||||
case Qt::Key_F5:
|
||||
return VK_F5;
|
||||
case Qt::Key_F6:
|
||||
return VK_F6;
|
||||
case Qt::Key_F7:
|
||||
return VK_F7;
|
||||
case Qt::Key_F8:
|
||||
return VK_F8;
|
||||
case Qt::Key_F9:
|
||||
return VK_F9;
|
||||
case Qt::Key_F10:
|
||||
return VK_F10;
|
||||
case Qt::Key_F11:
|
||||
return VK_F11;
|
||||
case Qt::Key_F12:
|
||||
return VK_F12;
|
||||
case Qt::Key_F13:
|
||||
return VK_F13;
|
||||
case Qt::Key_F14:
|
||||
return VK_F14;
|
||||
case Qt::Key_F15:
|
||||
return VK_F15;
|
||||
case Qt::Key_F16:
|
||||
return VK_F16;
|
||||
case Qt::Key_F17:
|
||||
return VK_F17;
|
||||
case Qt::Key_F18:
|
||||
return VK_F18;
|
||||
case Qt::Key_F19:
|
||||
return VK_F19;
|
||||
case Qt::Key_F20:
|
||||
return VK_F20;
|
||||
case Qt::Key_F21:
|
||||
return VK_F21;
|
||||
case Qt::Key_F22:
|
||||
return VK_F22;
|
||||
case Qt::Key_F23:
|
||||
return VK_F23;
|
||||
case Qt::Key_F24:
|
||||
return VK_F24;
|
||||
case Qt::Key_Space:
|
||||
return VK_SPACE;
|
||||
case Qt::Key_Asterisk:
|
||||
return VK_MULTIPLY;
|
||||
case Qt::Key_Plus:
|
||||
return VK_ADD;
|
||||
case Qt::Key_Comma:
|
||||
return VK_SEPARATOR;
|
||||
case Qt::Key_Minus:
|
||||
return VK_SUBTRACT;
|
||||
case Qt::Key_Slash:
|
||||
return VK_DIVIDE;
|
||||
case Qt::Key_MediaNext:
|
||||
return VK_MEDIA_NEXT_TRACK;
|
||||
case Qt::Key_MediaPrevious:
|
||||
return VK_MEDIA_PREV_TRACK;
|
||||
case Qt::Key_MediaPlay:
|
||||
return VK_MEDIA_PLAY_PAUSE;
|
||||
case Qt::Key_MediaStop:
|
||||
return VK_MEDIA_STOP;
|
||||
// couldn't find those in VK_*
|
||||
//case Qt::Key_MediaLast:
|
||||
//case Qt::Key_MediaRecord:
|
||||
case Qt::Key_VolumeDown:
|
||||
return VK_VOLUME_DOWN;
|
||||
case Qt::Key_VolumeUp:
|
||||
return VK_VOLUME_UP;
|
||||
case Qt::Key_VolumeMute:
|
||||
return VK_VOLUME_MUTE;
|
||||
|
||||
// numbers
|
||||
case Qt::Key_0:
|
||||
case Qt::Key_1:
|
||||
case Qt::Key_2:
|
||||
case Qt::Key_3:
|
||||
case Qt::Key_4:
|
||||
case Qt::Key_5:
|
||||
case Qt::Key_6:
|
||||
case Qt::Key_7:
|
||||
case Qt::Key_8:
|
||||
case Qt::Key_9:
|
||||
return key;
|
||||
|
||||
// letters
|
||||
case Qt::Key_A:
|
||||
case Qt::Key_B:
|
||||
case Qt::Key_C:
|
||||
case Qt::Key_D:
|
||||
case Qt::Key_E:
|
||||
case Qt::Key_F:
|
||||
case Qt::Key_G:
|
||||
case Qt::Key_H:
|
||||
case Qt::Key_I:
|
||||
case Qt::Key_J:
|
||||
case Qt::Key_K:
|
||||
case Qt::Key_L:
|
||||
case Qt::Key_M:
|
||||
case Qt::Key_N:
|
||||
case Qt::Key_O:
|
||||
case Qt::Key_P:
|
||||
case Qt::Key_Q:
|
||||
case Qt::Key_R:
|
||||
case Qt::Key_S:
|
||||
case Qt::Key_T:
|
||||
case Qt::Key_U:
|
||||
case Qt::Key_V:
|
||||
case Qt::Key_W:
|
||||
case Qt::Key_X:
|
||||
case Qt::Key_Y:
|
||||
case Qt::Key_Z:
|
||||
return key;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the LibQxt project nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** 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
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** 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
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#include <qt_windows.h>
|
||||
|
||||
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, void * message, long * result) {
|
||||
|
||||
Q_UNUSED(eventType);
|
||||
Q_UNUSED(result);
|
||||
MSG* msg = static_cast<MSG*>(message);
|
||||
if (msg->message == WM_HOTKEY) {
|
||||
const quint32 keycode = HIWORD(msg->lParam);
|
||||
const quint32 modifiers = LOWORD(msg->lParam);
|
||||
activateShortcut(keycode, modifiers);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
|
||||
|
||||
// MOD_ALT, MOD_CONTROL, (MOD_KEYUP), MOD_SHIFT, MOD_WIN
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
native |= MOD_SHIFT;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
native |= MOD_CONTROL;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
native |= MOD_ALT;
|
||||
if (modifiers & Qt::MetaModifier)
|
||||
native |= MOD_WIN;
|
||||
// TODO: resolve these?
|
||||
//if (modifiers & Qt::KeypadModifier)
|
||||
//if (modifiers & Qt::GroupSwitchModifier)
|
||||
return native;
|
||||
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeKeycode(Qt::Key key) {
|
||||
|
||||
switch (key) {
|
||||
case Qt::Key_Escape:
|
||||
return VK_ESCAPE;
|
||||
case Qt::Key_Tab:
|
||||
case Qt::Key_Backtab:
|
||||
return VK_TAB;
|
||||
case Qt::Key_Backspace:
|
||||
return VK_BACK;
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
return VK_RETURN;
|
||||
case Qt::Key_Insert:
|
||||
return VK_INSERT;
|
||||
case Qt::Key_Delete:
|
||||
return VK_DELETE;
|
||||
case Qt::Key_Pause:
|
||||
return VK_PAUSE;
|
||||
case Qt::Key_Print:
|
||||
return VK_PRINT;
|
||||
case Qt::Key_Clear:
|
||||
return VK_CLEAR;
|
||||
case Qt::Key_Home:
|
||||
return VK_HOME;
|
||||
case Qt::Key_End:
|
||||
return VK_END;
|
||||
case Qt::Key_Left:
|
||||
return VK_LEFT;
|
||||
case Qt::Key_Up:
|
||||
return VK_UP;
|
||||
case Qt::Key_Right:
|
||||
return VK_RIGHT;
|
||||
case Qt::Key_Down:
|
||||
return VK_DOWN;
|
||||
case Qt::Key_PageUp:
|
||||
return VK_PRIOR;
|
||||
case Qt::Key_PageDown:
|
||||
return VK_NEXT;
|
||||
case Qt::Key_F1:
|
||||
return VK_F1;
|
||||
case Qt::Key_F2:
|
||||
return VK_F2;
|
||||
case Qt::Key_F3:
|
||||
return VK_F3;
|
||||
case Qt::Key_F4:
|
||||
return VK_F4;
|
||||
case Qt::Key_F5:
|
||||
return VK_F5;
|
||||
case Qt::Key_F6:
|
||||
return VK_F6;
|
||||
case Qt::Key_F7:
|
||||
return VK_F7;
|
||||
case Qt::Key_F8:
|
||||
return VK_F8;
|
||||
case Qt::Key_F9:
|
||||
return VK_F9;
|
||||
case Qt::Key_F10:
|
||||
return VK_F10;
|
||||
case Qt::Key_F11:
|
||||
return VK_F11;
|
||||
case Qt::Key_F12:
|
||||
return VK_F12;
|
||||
case Qt::Key_F13:
|
||||
return VK_F13;
|
||||
case Qt::Key_F14:
|
||||
return VK_F14;
|
||||
case Qt::Key_F15:
|
||||
return VK_F15;
|
||||
case Qt::Key_F16:
|
||||
return VK_F16;
|
||||
case Qt::Key_F17:
|
||||
return VK_F17;
|
||||
case Qt::Key_F18:
|
||||
return VK_F18;
|
||||
case Qt::Key_F19:
|
||||
return VK_F19;
|
||||
case Qt::Key_F20:
|
||||
return VK_F20;
|
||||
case Qt::Key_F21:
|
||||
return VK_F21;
|
||||
case Qt::Key_F22:
|
||||
return VK_F22;
|
||||
case Qt::Key_F23:
|
||||
return VK_F23;
|
||||
case Qt::Key_F24:
|
||||
return VK_F24;
|
||||
case Qt::Key_Space:
|
||||
return VK_SPACE;
|
||||
case Qt::Key_Asterisk:
|
||||
return VK_MULTIPLY;
|
||||
case Qt::Key_Plus:
|
||||
return VK_ADD;
|
||||
case Qt::Key_Comma:
|
||||
return VK_SEPARATOR;
|
||||
case Qt::Key_Minus:
|
||||
return VK_SUBTRACT;
|
||||
case Qt::Key_Slash:
|
||||
return VK_DIVIDE;
|
||||
case Qt::Key_MediaNext:
|
||||
return VK_MEDIA_NEXT_TRACK;
|
||||
case Qt::Key_MediaPrevious:
|
||||
return VK_MEDIA_PREV_TRACK;
|
||||
case Qt::Key_MediaPlay:
|
||||
return VK_MEDIA_PLAY_PAUSE;
|
||||
case Qt::Key_MediaStop:
|
||||
return VK_MEDIA_STOP;
|
||||
// couldn't find those in VK_*
|
||||
//case Qt::Key_MediaLast:
|
||||
//case Qt::Key_MediaRecord:
|
||||
case Qt::Key_VolumeDown:
|
||||
return VK_VOLUME_DOWN;
|
||||
case Qt::Key_VolumeUp:
|
||||
return VK_VOLUME_UP;
|
||||
case Qt::Key_VolumeMute:
|
||||
return VK_VOLUME_MUTE;
|
||||
|
||||
// numbers
|
||||
case Qt::Key_0:
|
||||
case Qt::Key_1:
|
||||
case Qt::Key_2:
|
||||
case Qt::Key_3:
|
||||
case Qt::Key_4:
|
||||
case Qt::Key_5:
|
||||
case Qt::Key_6:
|
||||
case Qt::Key_7:
|
||||
case Qt::Key_8:
|
||||
case Qt::Key_9:
|
||||
return key;
|
||||
|
||||
// letters
|
||||
case Qt::Key_A:
|
||||
case Qt::Key_B:
|
||||
case Qt::Key_C:
|
||||
case Qt::Key_D:
|
||||
case Qt::Key_E:
|
||||
case Qt::Key_F:
|
||||
case Qt::Key_G:
|
||||
case Qt::Key_H:
|
||||
case Qt::Key_I:
|
||||
case Qt::Key_J:
|
||||
case Qt::Key_K:
|
||||
case Qt::Key_L:
|
||||
case Qt::Key_M:
|
||||
case Qt::Key_N:
|
||||
case Qt::Key_O:
|
||||
case Qt::Key_P:
|
||||
case Qt::Key_Q:
|
||||
case Qt::Key_R:
|
||||
case Qt::Key_S:
|
||||
case Qt::Key_T:
|
||||
case Qt::Key_U:
|
||||
case Qt::Key_V:
|
||||
case Qt::Key_W:
|
||||
case Qt::Key_X:
|
||||
case Qt::Key_Y:
|
||||
case Qt::Key_Z:
|
||||
return key;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
499
3rdparty/qxt/qxtglobalshortcut_x11.cpp
vendored
@@ -1,263 +1,236 @@
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the LibQxt project nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** 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
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** 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
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
# include <QX11Info>
|
||||
#else
|
||||
# include <qpa/qplatformnativeinterface.h>
|
||||
# include <xcb/xcb.h>
|
||||
# include <QApplication>
|
||||
#endif
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QByteArray>
|
||||
#include <QGuiApplication>
|
||||
#include <QKeySequence>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
#include "keymapper_x11.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const QVector<quint32> maskModifiers = QVector<quint32>()
|
||||
<< 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
|
||||
|
||||
typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event);
|
||||
|
||||
class QxtX11ErrorHandler {
|
||||
public:
|
||||
static bool error;
|
||||
|
||||
static int qxtX11ErrorHandler(Display *display, XErrorEvent *event)
|
||||
{
|
||||
Q_UNUSED(display);
|
||||
switch (event->error_code)
|
||||
{
|
||||
case BadAccess:
|
||||
case BadValue:
|
||||
case BadWindow:
|
||||
if (event->request_code == 33 /* X_GrabKey */ ||
|
||||
event->request_code == 34 /* X_UngrabKey */)
|
||||
{
|
||||
error = true;
|
||||
//TODO:
|
||||
//char errstr[256];
|
||||
//XGetErrorText(dpy, err->error_code, errstr, 256);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QxtX11ErrorHandler()
|
||||
{
|
||||
error = false;
|
||||
m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler);
|
||||
}
|
||||
|
||||
~QxtX11ErrorHandler()
|
||||
{
|
||||
XSetErrorHandler(m_previousErrorHandler);
|
||||
}
|
||||
|
||||
private:
|
||||
X11ErrorHandler m_previousErrorHandler;
|
||||
};
|
||||
|
||||
bool QxtX11ErrorHandler::error = false;
|
||||
|
||||
class QxtX11Data {
|
||||
public:
|
||||
QxtX11Data()
|
||||
{
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
m_display = QX11Info::display();
|
||||
#else
|
||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||
void *display = native->nativeResourceForScreen(QByteArray("display"),
|
||||
QGuiApplication::primaryScreen());
|
||||
m_display = reinterpret_cast<Display *>(display);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool isValid()
|
||||
{
|
||||
return m_display != 0;
|
||||
}
|
||||
|
||||
Display *display()
|
||||
{
|
||||
Q_ASSERT(isValid());
|
||||
return m_display;
|
||||
}
|
||||
|
||||
Window rootWindow()
|
||||
{
|
||||
return DefaultRootWindow(display());
|
||||
}
|
||||
|
||||
bool grabKey(quint32 keycode, quint32 modifiers, Window window)
|
||||
{
|
||||
QxtX11ErrorHandler errorHandler;
|
||||
|
||||
for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) {
|
||||
XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
|
||||
if (errorHandler.error) {
|
||||
ungrabKey(keycode, modifiers, window);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ungrabKey(quint32 keycode, quint32 modifiers, Window window)
|
||||
{
|
||||
QxtX11ErrorHandler errorHandler;
|
||||
|
||||
foreach (quint32 maskMods, maskModifiers) {
|
||||
XUngrabKey(display(), keycode, modifiers | maskMods, window);
|
||||
}
|
||||
|
||||
return !errorHandler.error;
|
||||
}
|
||||
|
||||
private:
|
||||
Display *m_display;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(5,0,0)
|
||||
bool QxtGlobalShortcutPrivate::eventFilter(void *message)
|
||||
{
|
||||
XEvent *event = static_cast<XEvent *>(message);
|
||||
if (event->type == KeyPress)
|
||||
{
|
||||
XKeyEvent *key = reinterpret_cast<XKeyEvent *>(event);
|
||||
unsigned int keycode = key->keycode;
|
||||
unsigned int keystate = key->state;
|
||||
#else
|
||||
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType,
|
||||
void *message, long *result)
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
|
||||
xcb_key_press_event_t *kev = 0;
|
||||
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)
|
||||
kev = static_cast<xcb_key_press_event_t *>(message);
|
||||
}
|
||||
|
||||
if (kev != 0) {
|
||||
unsigned int keycode = kev->detail;
|
||||
unsigned int keystate = 0;
|
||||
if(kev->state & XCB_MOD_MASK_1)
|
||||
keystate |= Mod1Mask;
|
||||
if(kev->state & XCB_MOD_MASK_CONTROL)
|
||||
keystate |= ControlMask;
|
||||
if(kev->state & XCB_MOD_MASK_4)
|
||||
keystate |= Mod4Mask;
|
||||
if(kev->state & XCB_MOD_MASK_SHIFT)
|
||||
keystate |= ShiftMask;
|
||||
#endif
|
||||
activateShortcut(keycode,
|
||||
// Mod1Mask == Alt, Mod4Mask == Meta
|
||||
keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
// ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
native |= ShiftMask;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
native |= ControlMask;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
native |= Mod1Mask;
|
||||
if (modifiers & Qt::MetaModifier)
|
||||
native |= Mod4Mask;
|
||||
|
||||
// TODO: resolve these?
|
||||
//if (modifiers & Qt::MetaModifier)
|
||||
//if (modifiers & Qt::KeypadModifier)
|
||||
//if (modifiers & Qt::GroupSwitchModifier)
|
||||
return native;
|
||||
}
|
||||
|
||||
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.
|
||||
unsigned int keysym = 0;
|
||||
int i = 0;
|
||||
while (KeyTbl[i]) {
|
||||
if (KeyTbl[i+1] == static_cast<uint>(key)) {
|
||||
keysym = KeyTbl[i];
|
||||
break;
|
||||
}
|
||||
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());
|
||||
}
|
||||
/****************************************************************************
|
||||
** Copyright (c) 2006 - 2011, the LibQxt project.
|
||||
** See the Qxt AUTHORS file for a list of authors and copyright holders.
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in the
|
||||
** documentation and/or other materials provided with the distribution.
|
||||
** * Neither the name of the LibQxt project nor the
|
||||
** names of its contributors may be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** 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
|
||||
** WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
** DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
||||
** DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
** (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
** LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
** 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
|
||||
** SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
**
|
||||
** <http://libqxt.org> <foundation@libqxt.org>
|
||||
*****************************************************************************/
|
||||
|
||||
#include "qxtglobalshortcut_p.h"
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QApplication>
|
||||
#include <QGuiApplication>
|
||||
#include <QKeySequence>
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QX11Info>
|
||||
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
|
||||
#include <X11/X.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <xcb/xcb.h>
|
||||
#include <xcb/xproto.h>
|
||||
|
||||
#include "keymapper_x11.h"
|
||||
|
||||
namespace {
|
||||
|
||||
const QVector<quint32> maskModifiers = QVector<quint32>() << 0 << Mod2Mask << LockMask << (Mod2Mask | LockMask);
|
||||
|
||||
typedef int (*X11ErrorHandler)(Display *display, XErrorEvent *event);
|
||||
|
||||
class QxtX11ErrorHandler {
|
||||
public:
|
||||
static bool error;
|
||||
|
||||
static int qxtX11ErrorHandler(Display *display, XErrorEvent *event) {
|
||||
Q_UNUSED(display);
|
||||
switch (event->error_code) {
|
||||
case BadAccess:
|
||||
case BadValue:
|
||||
case BadWindow:
|
||||
if (event->request_code == 33 /* X_GrabKey */ ||
|
||||
event->request_code == 34 /* X_UngrabKey */)
|
||||
{
|
||||
error = true;
|
||||
//TODO:
|
||||
//char errstr[256];
|
||||
//XGetErrorText(dpy, err->error_code, errstr, 256);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
QxtX11ErrorHandler() {
|
||||
error = false;
|
||||
m_previousErrorHandler = XSetErrorHandler(qxtX11ErrorHandler);
|
||||
}
|
||||
|
||||
~QxtX11ErrorHandler() {
|
||||
XSetErrorHandler(m_previousErrorHandler);
|
||||
}
|
||||
|
||||
private:
|
||||
X11ErrorHandler m_previousErrorHandler;
|
||||
};
|
||||
|
||||
bool QxtX11ErrorHandler::error = false;
|
||||
|
||||
class QxtX11Data {
|
||||
public:
|
||||
QxtX11Data() {
|
||||
QPlatformNativeInterface *native = qApp->platformNativeInterface();
|
||||
//void *display = native->nativeResourceForScreen(QByteArray("display"), QGuiApplication::primaryScreen());
|
||||
//m_display = reinterpret_cast<Display *>(display);
|
||||
m_display = QX11Info::display();
|
||||
}
|
||||
|
||||
bool isValid() {
|
||||
return m_display != nullptr;
|
||||
}
|
||||
|
||||
Display *display() {
|
||||
Q_ASSERT(isValid());
|
||||
return m_display;
|
||||
}
|
||||
|
||||
Window rootWindow() {
|
||||
return DefaultRootWindow(display());
|
||||
}
|
||||
|
||||
bool grabKey(quint32 keycode, quint32 modifiers, Window window) {
|
||||
QxtX11ErrorHandler errorHandler;
|
||||
|
||||
for (int i = 0; !errorHandler.error && i < maskModifiers.size(); ++i) {
|
||||
XGrabKey(display(), keycode, modifiers | maskModifiers[i], window, True, GrabModeAsync, GrabModeAsync);
|
||||
}
|
||||
|
||||
if (errorHandler.error) {
|
||||
ungrabKey(keycode, modifiers, window);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ungrabKey(quint32 keycode, quint32 modifiers, Window window) {
|
||||
QxtX11ErrorHandler errorHandler;
|
||||
|
||||
foreach (quint32 maskMods, maskModifiers) {
|
||||
XUngrabKey(display(), keycode, modifiers | maskMods, window);
|
||||
}
|
||||
|
||||
return !errorHandler.error;
|
||||
}
|
||||
|
||||
private:
|
||||
Display *m_display;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool QxtGlobalShortcutPrivate::nativeEventFilter(const QByteArray & eventType, void *message, long *result) {
|
||||
|
||||
Q_UNUSED(result);
|
||||
|
||||
xcb_key_press_event_t *kev = nullptr;
|
||||
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)
|
||||
kev = static_cast<xcb_key_press_event_t *>(message);
|
||||
}
|
||||
|
||||
if (kev != nullptr) {
|
||||
unsigned int keycode = kev->detail;
|
||||
unsigned int keystate = 0;
|
||||
if(kev->state & XCB_MOD_MASK_1)
|
||||
keystate |= Mod1Mask;
|
||||
if(kev->state & XCB_MOD_MASK_CONTROL)
|
||||
keystate |= ControlMask;
|
||||
if(kev->state & XCB_MOD_MASK_4)
|
||||
keystate |= Mod4Mask;
|
||||
if(kev->state & XCB_MOD_MASK_SHIFT)
|
||||
keystate |= ShiftMask;
|
||||
|
||||
activateShortcut(keycode,
|
||||
// Mod1Mask == Alt, Mod4Mask == Meta
|
||||
keystate & (ShiftMask | ControlMask | Mod1Mask | Mod4Mask));
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
quint32 QxtGlobalShortcutPrivate::nativeModifiers(Qt::KeyboardModifiers modifiers) {
|
||||
|
||||
// ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
|
||||
quint32 native = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
native |= ShiftMask;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
native |= ControlMask;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
native |= Mod1Mask;
|
||||
if (modifiers & Qt::MetaModifier)
|
||||
native |= Mod4Mask;
|
||||
|
||||
// TODO: resolve these?
|
||||
//if (modifiers & Qt::MetaModifier)
|
||||
//if (modifiers & Qt::KeypadModifier)
|
||||
//if (modifiers & Qt::GroupSwitchModifier)
|
||||
return native;
|
||||
|
||||
}
|
||||
|
||||
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.
|
||||
unsigned int keysym = 0;
|
||||
int i = 0;
|
||||
while (KeyTbl[i]) {
|
||||
if (KeyTbl[i+1] == static_cast<uint>(key)) {
|
||||
keysym = KeyTbl[i];
|
||||
break;
|
||||
}
|
||||
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());
|
||||
}
|
||||
|
||||
13
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
@@ -28,6 +28,7 @@
|
||||
#include <id3v2tag.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "tagunion.h"
|
||||
#include "dsdifffile.h"
|
||||
@@ -97,6 +98,18 @@ public:
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
9
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
@@ -185,6 +185,15 @@ namespace TagLib {
|
||||
*/
|
||||
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:
|
||||
enum Endianness { BigEndian, LittleEndian };
|
||||
|
||||
|
||||
14
3rdparty/taglib/dsf/dsffile.cpp
vendored
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013 by Stephen F. Booth
|
||||
copyright : (C) 2013 - 2018 by Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <id3v2tag.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "dsffile.h"
|
||||
|
||||
@@ -56,6 +57,17 @@ public:
|
||||
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
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
11
3rdparty/taglib/dsf/dsffile.h
vendored
@@ -1,5 +1,5 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2013 by Stephen F. Booth
|
||||
copyright : (C) 2013 - 2018 by Stephen F. Booth
|
||||
email : me@sbooth.org
|
||||
***************************************************************************/
|
||||
|
||||
@@ -103,6 +103,15 @@ namespace TagLib {
|
||||
*/
|
||||
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:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
8
3rdparty/taglib/fileref.cpp
vendored
@@ -180,10 +180,10 @@ namespace
|
||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(APE::File::isSupported(stream))
|
||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
//else if(DSF::File::isSupported(stream))
|
||||
//return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
//else if(DSDIFF::File::isSupported(stream))
|
||||
//return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(DSDIFF::File::isSupported(stream))
|
||||
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
else if(DSF::File::isSupported(stream))
|
||||
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
// isSupported() only does a quick check, so double check the file here.
|
||||
|
||||
|
||||
@@ -216,7 +216,23 @@ void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id)
|
||||
|
||||
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
|
||||
|
||||
@@ -339,7 +339,13 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const String &descripti
|
||||
|
||||
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
|
||||
|
||||
14
3rdparty/taglib/ogg/flac/oggflacfile.cpp
vendored
@@ -231,11 +231,21 @@ void Ogg::FLAC::File::scan()
|
||||
|
||||
if(!metadataHeader.startsWith("fLaC")) {
|
||||
// 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")
|
||||
return;
|
||||
|
||||
if(metadataHeader[5] != 1)
|
||||
return; // not version 1
|
||||
if(metadataHeader[5] != 1 && metadataHeader[6] != 0)
|
||||
return; // not version 1.0
|
||||
|
||||
if(metadataHeader.mid(9, 4) != "fLaC")
|
||||
return;
|
||||
|
||||
metadataHeader = metadataHeader.mid(13);
|
||||
}
|
||||
|
||||
41
3rdparty/taglib/toolkit/tfilestream.cpp
vendored
@@ -58,6 +58,11 @@ namespace
|
||||
#endif
|
||||
}
|
||||
|
||||
FileHandle openFile(const int fileDescriptor, bool readOnly)
|
||||
{
|
||||
return InvalidFileHandle;
|
||||
}
|
||||
|
||||
void closeFile(FileHandle file)
|
||||
{
|
||||
CloseHandle(file);
|
||||
@@ -98,6 +103,11 @@ namespace
|
||||
return fopen(path, readOnly ? "rb" : "rb+");
|
||||
}
|
||||
|
||||
FileHandle openFile(const int fileDescriptor, bool readOnly)
|
||||
{
|
||||
return fdopen(fileDescriptor, readOnly ? "rb" : "rb+");
|
||||
}
|
||||
|
||||
void closeFile(FileHandle file)
|
||||
{
|
||||
fclose(file);
|
||||
@@ -149,13 +159,28 @@ FileStream::FileStream(FileName fileName, bool openReadOnly)
|
||||
d->file = openFile(fileName, true);
|
||||
|
||||
if(d->file == InvalidFileHandle)
|
||||
{
|
||||
# ifdef _WIN32
|
||||
debug("Could not open file " + fileName.toString());
|
||||
# else
|
||||
debug("Could not open file " + String(static_cast<const char *>(d->name)));
|
||||
# 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()
|
||||
@@ -255,8 +280,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
|
||||
ByteVector buffer = data;
|
||||
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
|
||||
// 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));
|
||||
|
||||
for(unsigned int bytesRead = -1; bytesRead != 0;)
|
||||
{
|
||||
for(unsigned int bytesRead = -1; bytesRead != 0;) {
|
||||
seek(readPosition);
|
||||
bytesRead = static_cast<unsigned int>(readFile(d->file, buffer));
|
||||
readPosition += bytesRead;
|
||||
@@ -401,7 +424,8 @@ long FileStream::tell() const
|
||||
const LARGE_INTEGER zero = {};
|
||||
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);
|
||||
}
|
||||
else {
|
||||
@@ -470,9 +494,8 @@ void FileStream::truncate(long length)
|
||||
#else
|
||||
|
||||
const int error = ftruncate(fileno(d->file), length);
|
||||
if(error != 0) {
|
||||
if(error != 0)
|
||||
debug("FileStream::truncate() -- Coundn't truncate the file.");
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
5
3rdparty/taglib/toolkit/tfilestream.h
vendored
@@ -54,6 +54,11 @@ namespace TagLib {
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
|
||||
122
CMakeLists.txt
@@ -1,7 +1,5 @@
|
||||
# Strawberry Music Player
|
||||
# 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
|
||||
# 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")
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
if(${CMAKE_VERSION} VERSION_GREATER "3.10.3")
|
||||
cmake_policy(SET CMP0072 NEW)
|
||||
endif()
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckIncludeFiles)
|
||||
@@ -37,24 +32,27 @@ include(cmake/Rpm.cmake)
|
||||
include(cmake/Deb.cmake)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(LINUX 1)
|
||||
set(LINUX ON)
|
||||
endif()
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
set(FREEBSD 1)
|
||||
set(FREEBSD ON)
|
||||
endif()
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set(OPENBSD 1)
|
||||
set(OPENBSD ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
#set(CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
add_definitions(-DNDEBUG)
|
||||
add_definitions(-DQT_NO_DEBUG_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")
|
||||
set(CMAKE_COMPILER_IS_CLANGXX 1)
|
||||
@@ -90,16 +88,12 @@ else(LINUX)
|
||||
find_package(ALSA)
|
||||
pkg_check_modules(DBUS dbus-1)
|
||||
endif(LINUX)
|
||||
if(ALSA_FOUND)
|
||||
set(HAVE_ALSA ON)
|
||||
endif()
|
||||
if (NOT APPLE)
|
||||
find_package(X11)
|
||||
endif()
|
||||
if(X11_FOUND)
|
||||
set(HAVE_X11 ON)
|
||||
endif()
|
||||
find_package(OpenGL REQUIRED)
|
||||
pkg_check_modules(GSTREAMER gstreamer-1.0)
|
||||
pkg_check_modules(GSTREAMER_BASE gstreamer-base-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(LIBPULSE libpulse)
|
||||
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(LIBMTP libmtp>=1.0)
|
||||
pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0)
|
||||
pkg_check_modules(USBMUXD libusbmuxd)
|
||||
pkg_check_modules(PLIST libplist)
|
||||
pkg_check_modules(LIBIMOBILEDEVICE libimobiledevice-1.0)
|
||||
pkg_check_modules(LIBUSBMUXD libusbmuxd)
|
||||
pkg_check_modules(LIBPLIST libplist)
|
||||
pkg_check_modules(LIBDEEZER libdeezer)
|
||||
pkg_check_modules(LIBDZMEDIA libdzmedia)
|
||||
|
||||
if(WIN32)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif(WIN32)
|
||||
|
||||
# QT
|
||||
set(QT_MIN_VERSION 5.6.0)
|
||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql OpenGL Xml)
|
||||
set(QT_MIN_VERSION 5.5.1)
|
||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql Xml)
|
||||
if(X11_FOUND)
|
||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras)
|
||||
endif()
|
||||
@@ -141,7 +134,7 @@ if(WIN32)
|
||||
find_package(Qt5 REQUIRED COMPONENTS WinExtras)
|
||||
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)
|
||||
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::DBus)
|
||||
@@ -158,15 +151,25 @@ endif()
|
||||
|
||||
# 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.
|
||||
# But let the user override as strawberry will still compile and work without.
|
||||
# Only use system taglib if it's greater than 1.11.1
|
||||
# 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)
|
||||
option(USE_SYSTEM_TAGLIB "Use system taglib" ON)
|
||||
else()
|
||||
option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
|
||||
endif()
|
||||
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_LIBRARIES "${TAGLIB_LIBRARIES}")
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
@@ -211,9 +214,9 @@ endif()
|
||||
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication library" OFF)
|
||||
if(USE_SYSTEM_QTSINGLEAPPLICATION)
|
||||
message(STATUS "Using system QtSingleApplication library")
|
||||
find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES QtSolutions)
|
||||
find_library(QTSINGLEAPPLICATION_LIBRARIES QtSolutions_SingleApplication-2.6)
|
||||
find_library(QTSINGLECOREAPPLICATION_LIBRARIES QtSolutions_SingleCoreApplication-2.6)
|
||||
find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES qt5/QtSolutions)
|
||||
find_library(QTSINGLEAPPLICATION_LIBRARIES Qt5Solutions_SingleApplication-2.6)
|
||||
find_library(QTSINGLECOREAPPLICATION_LIBRARIES Qt5Solutions_SingleCoreApplication-2.6)
|
||||
else(USE_SYSTEM_QTSINGLEAPPLICATION)
|
||||
message(STATUS "Using builtin QtSingleApplication library")
|
||||
add_subdirectory(3rdparty/qtsingleapplication)
|
||||
@@ -225,11 +228,11 @@ endif(USE_SYSTEM_QTSINGLEAPPLICATION)
|
||||
option(USE_SYSTEM_QXT "Use system Qxt library" OFF)
|
||||
if (USE_SYSTEM_QXT)
|
||||
message(STATUS "Using system Qxt library")
|
||||
find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES QxtCore)
|
||||
find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES QxtGui)
|
||||
find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES qt5/QxtCore)
|
||||
find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES qt5/QxtWidgets)
|
||||
set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS})
|
||||
# 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)
|
||||
message(STATUS "Using builtin Qxt library")
|
||||
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)
|
||||
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"
|
||||
DEPENDS "D-Bus" DBUS_FOUND
|
||||
)
|
||||
@@ -283,13 +294,21 @@ optional_component(VLC ON "Engine: VLC backend"
|
||||
DEPENDS "libvlc" LIBVLC_FOUND
|
||||
)
|
||||
|
||||
optional_component(PHONON OFF "Engine: Phonon backend"
|
||||
optional_component(PHONON OFF "Engine: Phonon backend (UNSTABLE)"
|
||||
DEPENDS "phonon4qt5" PHONON_FOUND
|
||||
)
|
||||
|
||||
optional_component(LIBPULSE ON "Pulse audio integration"
|
||||
DEPENDS "libpulse" LIBPULSE_FOUND
|
||||
)
|
||||
if (WIN32)
|
||||
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"
|
||||
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"
|
||||
DEPENDS "libimobiledevice" IMOBILEDEVICE_FOUND
|
||||
DEPENDS "libplist" PLIST_FOUND
|
||||
DEPENDS "libusbmuxd" USBMUXD_FOUND
|
||||
DEPENDS "libimobiledevice" LIBIMOBILEDEVICE_FOUND
|
||||
DEPENDS "libplist" LIBPLIST_FOUND
|
||||
DEPENDS "libusbmuxd" LIBUSBMUXD_FOUND
|
||||
DEPENDS "iPod classic support" LIBGPOD_FOUND
|
||||
)
|
||||
|
||||
@@ -336,6 +355,23 @@ optional_component(SPARKLE ON "Sparkle integration"
|
||||
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)
|
||||
#add_subdirectory(ext/gstafc)
|
||||
#endif(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
|
||||
@@ -352,7 +388,7 @@ include_directories(${GLIB_INCLUDE_DIRS})
|
||||
include_directories(${GLIBCONFIG_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)
|
||||
endif()
|
||||
|
||||
@@ -374,6 +410,8 @@ add_custom_target(uninstall
|
||||
|
||||
# Show a summary of what we have enabled
|
||||
summary_show()
|
||||
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON)
|
||||
message(FATAL_ERROR "You need to enable either GStreamer, Xine, VLC or Phonon to compile!")
|
||||
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 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()
|
||||
|
||||
36
Changelog
@@ -2,6 +2,38 @@ Strawberry Music Player
|
||||
=======================
|
||||
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
|
||||
@@ -9,7 +41,7 @@ Version 0.3.3:
|
||||
Version 0.3.2:
|
||||
|
||||
* Fixed search error not shown in Tidal search
|
||||
* Added URL handler for Tidal, now retriving URL's when playing instead of when searching
|
||||
* 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
|
||||
@@ -65,7 +97,7 @@ Version 0.1.4:
|
||||
Version 0.1.3:
|
||||
* Audio file detection by content
|
||||
* 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
|
||||
* 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
|
||||
|
||||
@@ -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 install \
|
||||
lsb-release \
|
||||
git tar make cmake gcc gcc-c++ pkg-config \
|
||||
lsb-release git tar make cmake gcc gcc-c++ pkg-config \
|
||||
glibc-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libpulse-devel libnotify-devel \
|
||||
boost-devel protobuf-devel sqlite3-devel taglib-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 \
|
||||
libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel
|
||||
|
||||
|
||||
26
README.md
@@ -1,8 +1,8 @@
|
||||
:strawberry: Strawberry Music Player [](https://travis-ci.org/jonaski/strawberry)
|
||||
[](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.
|
||||
It's written in C++ and Qt 5. The name is inspired by the band Strawbs.
|
||||
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.
|
||||
|
||||
* Website: http://www.strawbs.org/
|
||||
* 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
|
||||
* Native desktop notifications
|
||||
* 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
|
||||
* Fetch tags from MusicBrainz
|
||||
* 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
|
||||
* Equalizer
|
||||
* 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.
|
||||
|
||||
@@ -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
|
||||
* [Protobuf library and compiler](https://developers.google.com/protocol-buffers/)
|
||||
* [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)
|
||||
* [TagLib 1.11.1 or higher](http://taglib.org/)
|
||||
* [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/)
|
||||
* [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.
|
||||
|
||||
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:
|
||||
|
||||
* The Qt 5 LastFM library is required for fetching album covers from LastFM.
|
||||
@@ -72,5 +77,12 @@ Optional:
|
||||
sudo make install
|
||||
|
||||
(dont change to the source directory, if you created the build directory inside the source directory type: cmake .. instead).
|
||||
|
||||
|
||||
### :computer: Screenshot
|
||||
|
||||
|
||||

|
||||
|
||||
### :moneybag: Donate
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=FRJUYV5QP6HW8)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
find_program(LSB_RELEASE_EXEC lsb_release)
|
||||
find_program(RPMBUILD_EXEC rpmbuild)
|
||||
|
||||
if (LSB_RELEASE_EXEC)
|
||||
if (LSB_RELEASE_EXEC AND RPMBUILD_EXEC)
|
||||
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -is | tr '[:upper:]' '[:lower:]' | cut -d' ' -f1"
|
||||
OUTPUT_VARIABLE DIST_NAME
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
@@ -42,12 +43,12 @@ if (LSB_RELEASE_EXEC)
|
||||
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/opensuse/strawberry.spec
|
||||
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
|
||||
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 "${DIST_NAME}${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
|
||||
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()
|
||||
|
||||
@@ -50,7 +50,7 @@ function(optional_component name default description)
|
||||
set(current_dep_name)
|
||||
set(missing_deps)
|
||||
|
||||
foreach(arg ${ARGN})
|
||||
foreach(arg ${ARGN})
|
||||
if(${next_arg_is_dep_name})
|
||||
set(current_dep_name "${arg}")
|
||||
set(next_arg_is_dep_name FALSE)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(STRAWBERRY_VERSION_MAJOR 0)
|
||||
set(STRAWBERRY_VERSION_MINOR 3)
|
||||
set(STRAWBERRY_VERSION_PATCH 3)
|
||||
set(STRAWBERRY_VERSION_MINOR 4)
|
||||
set(STRAWBERRY_VERSION_PATCH 2)
|
||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||
|
||||
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(STRAWBERRY_VERSION_DISPLAY "${majorminorpatch}")
|
||||
set(STRAWBERRY_VERSION_PACKAGE "${majorminorpatch}")
|
||||
set(STRAWBERRY_VERSION_RPM_V "${majorminorpatch}")
|
||||
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")
|
||||
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_RPM_V "${GIT_TAGNAME}")
|
||||
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()
|
||||
|
||||
message(STATUS "Strawberry Version:")
|
||||
message(STATUS "Display: ${STRAWBERRY_VERSION_DISPLAY}")
|
||||
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}")
|
||||
|
||||
439
data/data.qrc
@@ -7,8 +7,8 @@
|
||||
<file>schema/device-schema.sql</file>
|
||||
<file>style/strawberry.css</file>
|
||||
<file>misc/playing_tooltip.txt</file>
|
||||
<file>misc/oauthsuccess.html</file>
|
||||
<file>pictures/strawberry.png</file>
|
||||
<file>pictures/strawbs-transparent.png</file>
|
||||
<file>pictures/noalbumart.png</file>
|
||||
<file>pictures/nomusic.png</file>
|
||||
<file>pictures/musicbrainz.png</file>
|
||||
@@ -27,442 +27,7 @@
|
||||
<file>pictures/osd_background.png</file>
|
||||
<file>pictures/osd_shadow_corner.png</file>
|
||||
<file>pictures/osd_shadow_edge.png</file>
|
||||
<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/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>pictures/deezer.png</file>
|
||||
<file>fonts/HumongousofEternitySt.ttf</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
444
data/icons.qrc
@@ -1,4 +1,444 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
</qresource>
|
||||
<qresource prefix="/">
|
||||
<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>
|
||||
|
||||
BIN
data/icons/128x128/deezer.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
data/icons/22x22/deezer.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icons/32x32/deezer.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
data/icons/48x48/deezer.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
data/icons/64x64/deezer.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
data/icons/full/deezer.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
41
data/misc/oauthsuccess.html
Normal 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
|
After Width: | Height: | Size: 6.1 KiB |
BIN
data/pictures/deezer_black_big.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
data/pictures/deezer_white_big.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -57,7 +57,7 @@ CREATE TABLE device_%deviceid_songs (
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
#playlist {
|
||||
background-color: %palette-base;
|
||||
alternate-background-color: %palette-alternate-base;
|
||||
|
||||
}
|
||||
|
||||
#playlist[default_background_enabled = "true"] {
|
||||
background-image: url(:pictures/strawbs-transparent.png);
|
||||
background-attachment: fixed;
|
||||
background-position: bottom right;
|
||||
background-repeat: none;
|
||||
@@ -45,11 +43,11 @@ QToolButton:pressed[popupMode="1"] {
|
||||
padding-right: 16px;
|
||||
}
|
||||
|
||||
darwin {
|
||||
macos {
|
||||
font-size: 11pt;
|
||||
}
|
||||
|
||||
darwin QMenu {
|
||||
macos QMenu {
|
||||
font-size: 13pt;
|
||||
}
|
||||
|
||||
|
||||
2
dist/CMakeLists.txt
vendored
@@ -7,6 +7,7 @@ if (RPM_DISTRO)
|
||||
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}/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}/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)
|
||||
@@ -19,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.svg DESTINATION share/icons/hicolor/scalable/apps/)
|
||||
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)
|
||||
endif()
|
||||
|
||||
|
||||
6
dist/debian/control
vendored
@@ -1,7 +1,7 @@
|
||||
Source: strawberry
|
||||
Section: sound
|
||||
Priority: optional
|
||||
Maintainer: "Jonas Kvinge" <jonas@jkvinge.net>
|
||||
Maintainer: Jonas Kvinge <jonas@jkvinge.net>
|
||||
Build-Depends: debhelper (>= 7),
|
||||
make,
|
||||
cmake,
|
||||
@@ -20,7 +20,6 @@ Build-Depends: debhelper (>= 7),
|
||||
qtbase5-dev-tools,
|
||||
qtbase5-private-dev,
|
||||
qt5-dev-tools,
|
||||
libqt5opengl5-dev,
|
||||
libqt5x11extras5-dev,
|
||||
libgstreamer1.0-dev,
|
||||
libgstreamer-plugins-base1.0-dev,
|
||||
@@ -42,13 +41,14 @@ Architecture: any
|
||||
Depends: ${shlibs:Depends},
|
||||
${misc:Depends},
|
||||
libsqlite3-0,
|
||||
libqt5sql5-sqlite,
|
||||
gstreamer1.0-plugins-base,
|
||||
gstreamer1.0-plugins-good,
|
||||
gstreamer1.0-alsa,
|
||||
gstreamer1.0-pulseaudio
|
||||
Homepage: http://www.strawbs.org/
|
||||
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:
|
||||
- Play and organize music
|
||||
|
||||
2
dist/debian/rules
vendored
@@ -35,7 +35,7 @@ install: build
|
||||
dh_testroot
|
||||
dh_prep
|
||||
dh_installdirs
|
||||
|
||||
|
||||
make install
|
||||
|
||||
binary-indep: install
|
||||
|
||||
21
dist/fedora/strawberry.spec.in
vendored
@@ -2,15 +2,15 @@ Name: strawberry
|
||||
Version: @STRAWBERRY_VERSION_RPM_V@
|
||||
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
||||
Summary: A audio player and music collection organiser
|
||||
|
||||
Group: Applications/Multimedia
|
||||
License: GPL-3.0+
|
||||
License: GPLv3+
|
||||
URL: http://www.strawbs.org/
|
||||
Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz
|
||||
|
||||
BuildRequires: boost-devel
|
||||
BuildRequires: cmake
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: libappstream-glib
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: hicolor-icon-theme
|
||||
BuildRequires: liblastfm-qt5-devel
|
||||
@@ -35,7 +35,6 @@ BuildRequires: pkgconfig(Qt5Network)
|
||||
BuildRequires: pkgconfig(Qt5Xml)
|
||||
BuildRequires: pkgconfig(Qt5X11Extras)
|
||||
BuildRequires: pkgconfig(Qt5DBus)
|
||||
BuildRequires: pkgconfig(Qt5OpenGL)
|
||||
BuildRequires: pkgconfig(gstreamer-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-app-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-audio-1.0)
|
||||
@@ -68,7 +67,7 @@ Features:
|
||||
* Audio analyzer
|
||||
* Equalizer
|
||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
* Integrated Tidal support
|
||||
* Integrated Tidal and Deezer support
|
||||
|
||||
%prep
|
||||
%setup -qn %{name}-@STRAWBERRY_VERSION_PACKAGE@
|
||||
@@ -82,7 +81,6 @@ export CXXFLAGS="%{optflags} -fpermissive"
|
||||
|
||||
mkdir %{_target_platform}
|
||||
pushd %{_target_platform}
|
||||
|
||||
%{cmake} \
|
||||
-DBUILD_WERROR:BOOL=OFF \
|
||||
-DCMAKE_BUILD_TYPE:STRING=Release \
|
||||
@@ -93,18 +91,16 @@ popd
|
||||
|
||||
%install
|
||||
make install DESTDIR=%{buildroot} -C %{_target_platform}
|
||||
rm -rf %{buildroot}%{_datadir}/man
|
||||
mv %{buildroot}%{_datadir}/metainfo %{buildroot}%{_datadir}/appdata
|
||||
|
||||
%check
|
||||
desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop
|
||||
pushd %{_target_platform}
|
||||
popd
|
||||
|
||||
%clean
|
||||
appstream-util validate-relax --nonet %{buildroot}%{_datadir}/appdata/strawberry.appdata.xml
|
||||
|
||||
%files
|
||||
%defattr(-,root,root,-)
|
||||
%doc
|
||||
%doc README.md Changelog
|
||||
%license COPYING
|
||||
%{_bindir}/strawberry
|
||||
%{_bindir}/strawberry-tagreader
|
||||
%{_datadir}/applications/strawberry.desktop
|
||||
@@ -112,6 +108,9 @@ popd
|
||||
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png
|
||||
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png
|
||||
%{_datadir}/icons/hicolor/scalable/apps/strawberry.svg
|
||||
%{_datadir}/appdata/strawberry.appdata.xml
|
||||
%{_mandir}/man1/strawberry.1.*
|
||||
%{_mandir}/man1/strawberry-tagreader.1.*
|
||||
|
||||
%changelog
|
||||
* @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@
|
||||
|
||||
26
dist/opensuse/strawberry.spec.in
vendored
@@ -2,7 +2,6 @@ Name: strawberry
|
||||
Version: @STRAWBERRY_VERSION_RPM_V@
|
||||
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
||||
Summary: A audio player and music collection organiser
|
||||
|
||||
Group: Applications/Multimedia
|
||||
License: GPL-3.0+
|
||||
URL: http://www.strawbs.org/
|
||||
@@ -16,6 +15,7 @@ BuildRequires: boost-devel
|
||||
%endif
|
||||
BuildRequires: cmake
|
||||
BuildRequires: desktop-file-utils
|
||||
BuildRequires: appstream-glib
|
||||
BuildRequires: gcc-c++
|
||||
BuildRequires: hicolor-icon-theme
|
||||
BuildRequires: libQt5Gui-private-headers-devel
|
||||
@@ -42,7 +42,6 @@ BuildRequires: pkgconfig(Qt5Network)
|
||||
BuildRequires: pkgconfig(Qt5Xml)
|
||||
BuildRequires: pkgconfig(Qt5X11Extras)
|
||||
BuildRequires: pkgconfig(Qt5DBus)
|
||||
BuildRequires: pkgconfig(Qt5OpenGL)
|
||||
BuildRequires: pkgconfig(gstreamer-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-app-1.0)
|
||||
BuildRequires: pkgconfig(gstreamer-audio-1.0)
|
||||
@@ -58,6 +57,8 @@ BuildRequires: pkgconfig(libudf)
|
||||
BuildRequires: pkgconfig(libxine)
|
||||
BuildRequires: pkgconfig(libvlc)
|
||||
|
||||
Requires: libQt5Sql5-sqlite
|
||||
|
||||
%description
|
||||
Strawberry is a audio player and music collection organizer.
|
||||
It is a fork of Clementine. The name is inspired by the band Strawbs.
|
||||
@@ -77,7 +78,7 @@ Features:
|
||||
* Audio analyzer
|
||||
* Equalizer
|
||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||
* Integrated Tidal support
|
||||
* Integrated Tidal and Deezer support
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-@STRAWBERRY_VERSION_PACKAGE@
|
||||
@@ -89,14 +90,26 @@ make %{?_smp_mflags}
|
||||
%install
|
||||
cd build
|
||||
make install DESTDIR=$RPM_BUILD_ROOT
|
||||
%if 0%{?suse_version} < 1500
|
||||
mv %{buildroot}%{_datadir}/metainfo %{buildroot}%{_datadir}/appdata
|
||||
%endif
|
||||
|
||||
%clean
|
||||
cd build
|
||||
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
|
||||
%defattr(-,root,root,-)
|
||||
%doc
|
||||
%doc README.md Changelog
|
||||
%license COPYING
|
||||
%{_bindir}/strawberry
|
||||
%{_bindir}/strawberry-tagreader
|
||||
%{_datadir}/applications/strawberry.desktop
|
||||
@@ -104,6 +117,11 @@ make clean
|
||||
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png
|
||||
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png
|
||||
%{_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}-tagreader.1%{?ext_man}
|
||||
|
||||
|
||||
65
dist/pacman/PKGBUILD.in
vendored
Normal 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
|
||||
}
|
||||
6
dist/scripts/gen-icons-resource.sh
vendored
@@ -19,7 +19,7 @@ do
|
||||
echo "ERROR: Cannot dermine geometry for image: \"$i\"."
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
# Geometry can be 563x144+0+0 or 75x98
|
||||
# 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
|
||||
@@ -32,10 +32,10 @@ do
|
||||
echo "ERROR: Cannot dermine height for image: \"$x\"."
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
for x in $sizes
|
||||
do
|
||||
|
||||
|
||||
dest="$x/$file"
|
||||
if [ -f $dest ]; then
|
||||
continue
|
||||
|
||||
1
dist/scripts/maketarball.sh.in
vendored
@@ -26,4 +26,5 @@ tar -cJf $name-$version.tar.xz \
|
||||
--exclude="*.nsi" \
|
||||
--exclude="$root/CMakeLists.txt.user" \
|
||||
--exclude="$root/build" \
|
||||
--exclude="$root/dist/debian/changelog" \
|
||||
"$root"
|
||||
|
||||
51
dist/unix/strawberry.appdata.xml
vendored
Normal 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>
|
||||
130
dist/windows/Capabilities.nsh
vendored
@@ -9,107 +9,107 @@ _____________________________________________________________________________
|
||||
|
||||
These functions register an application with Windows Vista's and Windows 7's
|
||||
Default Programs window.
|
||||
|
||||
|
||||
Usage:
|
||||
|
||||
|
||||
!include "Capabilities.nsh"
|
||||
!define CAPABILITIES_NAME "[program name]"
|
||||
!define CAPABILITIES_DESCRIPTION "[description]"
|
||||
!define CAPABILITIES_PROGID "[progid]"
|
||||
!define CAPABILITIES_PATH "[path]"
|
||||
...
|
||||
|
||||
|
||||
During install, call ${RegisterCapabilities}, then use the other register
|
||||
macros to create file type, MIME, and protocol associations.
|
||||
|
||||
|
||||
During uninstall, call ${UnRegisterCapabilities}
|
||||
|
||||
|
||||
_______________________________________________________________________________
|
||||
|
||||
|
||||
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/cc144109(v=VS.85).aspx
|
||||
|
||||
|
||||
Defines: All defines not marked [optional] are required.
|
||||
|
||||
|
||||
CAPABILITIES_NAME
|
||||
The canonical name of the program.
|
||||
|
||||
|
||||
CAPABILITIES_LOCAL_NAME [optional]
|
||||
The localized name of the program as it appears in Default Programs.
|
||||
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
|
||||
in the file.
|
||||
|
||||
|
||||
CAPABILITIES_DESCRIPTION
|
||||
The localized description shown in Default Programs. This can be either a
|
||||
string or in the same format as CAPABILITIES_LOCAL_NAME
|
||||
|
||||
|
||||
CAPABILITIES_PROGID
|
||||
An identifier used in file associations. Usually, this is the name of the
|
||||
program. This should not have any spaces in it.
|
||||
|
||||
|
||||
CAPABILITIES_PATH
|
||||
The location where capabilities info is stored in the registry.
|
||||
The "Capabilities" key will automatically be added. If the application is
|
||||
a client of some sort, (browser, email, media player, etc.) use
|
||||
"Software\Clients\[ClientType]\[ProgramName]". Otherwise, use
|
||||
"Software\[CompanyName]\[ProgramName]" or just "Software\[ProgramName]".
|
||||
|
||||
|
||||
CAPABILITIES_ICON [optional]
|
||||
The icon shown in Default Programs. This should be in the format
|
||||
"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
|
||||
zero-based array of icons stored in the file. If IconIndex is negative,
|
||||
the absolute value is used as a resource ID.
|
||||
|
||||
|
||||
CAPABILITIES_REINSTALL [optional]
|
||||
The command executed when a user uses Set Program Access and Computer
|
||||
Defaults to select this application as the default for its client type.
|
||||
This command should launch a program that associates the application with
|
||||
all the file and protocol types it can handle.
|
||||
|
||||
|
||||
CAPABILITIES_HIDE_ICONS [optional]
|
||||
The command executed when a user uses Set Program Access and Computer
|
||||
Defaults to disable access to this application. This command should launch
|
||||
a program that hides all shortcuts and access points to this application.
|
||||
It should also prevent the application from being run automatically and
|
||||
update the IconsVisible registry value to 0.
|
||||
|
||||
|
||||
CAPABILITIES_SHOW_ICONS [optional]
|
||||
The command executed when a user uses Set Program Access and Computer
|
||||
Defaults to enable access to this application. This command should launch
|
||||
a program that restores shortcuts and access points to the application,
|
||||
allows the program to run, and updates the IconsVisible registry value to 1.
|
||||
|
||||
|
||||
|
||||
|
||||
Macros:
|
||||
|
||||
|
||||
${RegisterCapabilities}
|
||||
Registers the program with Default Programs. Call this once on install
|
||||
before using any other functions.
|
||||
|
||||
|
||||
${UnRegisterCapabilities}
|
||||
Un-registers the program and all its associations. Call this once on
|
||||
uninstall to clean up all installed registry values.
|
||||
|
||||
|
||||
${RegisterFileType} "[extension]" "[executable]" "[icon]" "[description]"
|
||||
Registers a file type with the program
|
||||
extension: The file extension to register (ex: .txt)
|
||||
executable: The executable that opens the file type
|
||||
icon: The icon shown for the file type
|
||||
description: Description for the file type shown in Explorer
|
||||
|
||||
|
||||
${RegisterMediaType} "[extension]" "[executable]" "[icon]" "[description]"
|
||||
Registers a media file type with the program (has a "Play" command)
|
||||
(arguments are same as RegisterFileType)
|
||||
|
||||
|
||||
${RegisterMimeType} "[mime type]" "[shortname]" "[clsid]"
|
||||
Registers a mime type with the program
|
||||
mime type: The MIME type to register (ex: audio/mp3)
|
||||
shortname: A short identifier for the type (ex: mp3)
|
||||
clsid: The CLSID of the program to handle files of this type
|
||||
|
||||
|
||||
${RegisterProtocol} "[protocol]" "[executable]" "[icon]" "[description]"
|
||||
Registers a URL protocol with the program
|
||||
protocol: The protocol to register (ex: http)
|
||||
@@ -118,15 +118,15 @@ ${RegisterProtocol} "[protocol]" "[executable]" "[icon]" "[description]"
|
||||
${UnRegisterFileType} "[extension]"
|
||||
Un-registers a previously registered file type
|
||||
extension: The file extension to un-register
|
||||
|
||||
|
||||
${UnRegisterMimeType} "[mime type]"
|
||||
Un-registers a previously registered MEME type
|
||||
mime type: The MIME type to un-register
|
||||
|
||||
|
||||
${UnRegisterProtocol} "[protocol]"
|
||||
Un-registers a previously registered URL protocol
|
||||
protocol: The URL protocol to un-register
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ ${StrCase}
|
||||
!verbose push
|
||||
!verbose ${_Capabilities_VERBOSE}
|
||||
Push $0
|
||||
|
||||
|
||||
!ifndef CAPABILITIES_PATH
|
||||
!error "CAPABILITIES_PATH not defined"
|
||||
!endif
|
||||
@@ -267,21 +267,21 @@ ${StrCase}
|
||||
!ifndef CAPABILITIES_DESCRIPTION
|
||||
!error "CAPABILITIES_DESCRIPTION not defined"
|
||||
!endif
|
||||
|
||||
|
||||
StrCpy $0 "${CAPABILITIES_PATH}\Capabilities"
|
||||
; add the application to RegisteredApplications
|
||||
WriteRegStr HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}" "$0"
|
||||
|
||||
|
||||
; write application info
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}" "" "${CAPABILITIES_NAME}"
|
||||
|
||||
|
||||
!ifdef CAPABILITIES_LOCAL_NAME
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}" "LocalizedString" "${CAPABILITIES_LOCAL_NAME}"
|
||||
!endif
|
||||
!ifdef CAPABILITIES_ICON
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\DefaultIcon" "" "${CAPABILITIES_ICON}"
|
||||
!endif
|
||||
|
||||
|
||||
; write installinfo if defined
|
||||
!ifdef CAPABILITIES_REINSTALL
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ReinstallCommand" "${CAPABILITIES_REINSTALL}"
|
||||
@@ -294,7 +294,7 @@ ${StrCase}
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\InstallInfo" "ShowIconsCommand" "${CAPABILITIES_SHOW_ICONS}"
|
||||
WriteRegDWORD HKLM "${CAPABILITIES_PATH}\InstallInfo" "IconsVisible" 0x1
|
||||
!endif
|
||||
|
||||
|
||||
; write application capabilities info
|
||||
!ifdef CAPABILITIES_LOCAL_NAME
|
||||
WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_LOCAL_NAME}"
|
||||
@@ -302,7 +302,7 @@ ${StrCase}
|
||||
WriteRegStr HKLM "$0" "ApplicationName" "${CAPABILITIES_NAME}"
|
||||
!endif
|
||||
WriteRegStr HKLM "$0" "ApplicationDescription" "${CAPABILITIES_DESCRIPTION}"
|
||||
|
||||
|
||||
Pop $0
|
||||
!verbose pop
|
||||
!macroend
|
||||
@@ -322,7 +322,7 @@ ${StrCase}
|
||||
!define MacroID ${__LINE__}
|
||||
!verbose push
|
||||
!verbose ${_Capabilities_VERBOSE}
|
||||
|
||||
|
||||
Push $0
|
||||
Push $1
|
||||
|
||||
@@ -330,43 +330,43 @@ ${StrCase}
|
||||
FileTypeLoop_${MacroID}:
|
||||
EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" 0
|
||||
StrCmp $0 "" FileTypeDone_${MacroID}
|
||||
|
||||
|
||||
ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0"
|
||||
DeleteRegKey HKCR $1
|
||||
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$0"
|
||||
|
||||
Goto FileTypeLoop_${MacroID}
|
||||
FileTypeDone_${MacroID}:
|
||||
|
||||
|
||||
; remove all MIME associations
|
||||
MimeTypeLoop_${MacroID}:
|
||||
EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" 0
|
||||
StrCmp $0 "" MimeTypeDone_${MacroID}
|
||||
|
||||
|
||||
ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0"
|
||||
DeleteRegKey HKCR "$1"
|
||||
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$0"
|
||||
|
||||
Goto MimeTypeLoop_${MacroID}
|
||||
MimeTypeDone_${MacroID}:
|
||||
|
||||
|
||||
; remove all protocol associations
|
||||
ProtocolLoop_${MacroID}:
|
||||
EnumRegValue $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" 0
|
||||
StrCmp $0 "" ProtocolDone_${MacroID}
|
||||
|
||||
|
||||
ReadRegStr $1 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0"
|
||||
DeleteRegKey HKCR "$1"
|
||||
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$0"
|
||||
|
||||
Goto ProtocolLoop_${MacroID}
|
||||
ProtocolDone_${MacroID}:
|
||||
|
||||
|
||||
|
||||
|
||||
; remove capabilities keys
|
||||
DeleteRegValue HKLM "Software\RegisteredApplications" "${CAPABILITIES_NAME}"
|
||||
DeleteRegKey HKLM ${CAPABILITIES_PATH}
|
||||
|
||||
|
||||
Pop $1
|
||||
Pop $0
|
||||
!verbose pop
|
||||
@@ -390,7 +390,7 @@ ${StrCase}
|
||||
!macro RegisterFileType_
|
||||
!verbose push
|
||||
!verbose ${_Capabilities_VERBOSE}
|
||||
|
||||
|
||||
Exch $R3 ;ext
|
||||
Exch
|
||||
Exch $R2 ;exe
|
||||
@@ -405,10 +405,10 @@ ${StrCase}
|
||||
; ex: .mp3 becomes ProgID.AssocFile.MP3
|
||||
${StrCase} $0 "$R3" "U"
|
||||
StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0"
|
||||
|
||||
|
||||
; link capabilities to association in classes root
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0"
|
||||
|
||||
|
||||
; write file association in classes root
|
||||
WriteRegStr HKCR "$0" "" "$R0"
|
||||
WriteRegStr HKCR "$0\DefaultIcon" "" "$R1"
|
||||
@@ -441,7 +441,7 @@ ${StrCase}
|
||||
!macro RegisterMediaType_
|
||||
!verbose push
|
||||
!verbose ${_Capabilities_VERBOSE}
|
||||
|
||||
|
||||
Exch $R3 ;ext
|
||||
Exch
|
||||
Exch $R2 ;exe
|
||||
@@ -457,10 +457,10 @@ ${StrCase}
|
||||
; ex: .mp3 becomes ProgID.AssocFile.MP3
|
||||
${StrCase} $0 "$R3" "U"
|
||||
StrCpy $0 "${CAPABILITIES_PROGID}.AssocFile$0"
|
||||
|
||||
|
||||
; link capabilities to association in classes root
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R3" "$0"
|
||||
|
||||
|
||||
; write file association in classes root
|
||||
WriteRegStr HKCR "$0" "" "$R0"
|
||||
WriteRegStr HKCR "$0\DefaultIcon" "" "$R1"
|
||||
@@ -495,24 +495,24 @@ ${StrCase}
|
||||
!macro RegisterMimeType_
|
||||
!verbose push
|
||||
!verbose ${_Capabilities_VERBOSE}
|
||||
|
||||
|
||||
Exch $R2 ;mime
|
||||
Exch
|
||||
Exch $R1 ;shortname
|
||||
Exch
|
||||
Exch 2
|
||||
Exch $R0 ;clsid
|
||||
|
||||
|
||||
Push $0
|
||||
|
||||
; create an association name
|
||||
; ex: audio/mp3 becomes ProgID.AssocMIME.MP3
|
||||
${StrCase} $0 "$R1" "U"
|
||||
StrCpy $0 "${CAPABILITIES_PROGID}.AssocMIME.$0"
|
||||
|
||||
|
||||
; link capabilities to association in classes root
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R2" "$0"
|
||||
|
||||
|
||||
; write file association in classes root
|
||||
WriteRegStr HKCR "$0\CLSID" "" "$R0"
|
||||
|
||||
@@ -538,7 +538,7 @@ ${StrCase}
|
||||
!macro RegisterProtocol_
|
||||
!verbose push
|
||||
!verbose ${_Capabilities_VERBOSE}
|
||||
|
||||
|
||||
Exch $R3 ;protocol
|
||||
Exch
|
||||
Exch $R2 ;exe
|
||||
@@ -554,10 +554,10 @@ ${StrCase}
|
||||
; ex: http becomes ProgID.AssocProtocol.HTTP
|
||||
${StrCase} $0 "$R3" "U"
|
||||
StrCpy $0 "${CAPABILITIES_PROGID}.AssocProtocol.$0"
|
||||
|
||||
|
||||
; link capabilities to association in classes root
|
||||
WriteRegStr HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R3" "$0"
|
||||
|
||||
|
||||
; write file association in classes root
|
||||
WriteRegStr HKCR "$0" "" "$R0"
|
||||
WriteRegStr HKCR "$0\DefaultIcon" "" "$R1"
|
||||
@@ -592,14 +592,14 @@ ${StrCase}
|
||||
|
||||
Exch $R0 ;ext
|
||||
Push $0
|
||||
|
||||
|
||||
ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0"
|
||||
StrCmp $0 "" skip_${MacroID}
|
||||
|
||||
|
||||
DeleteRegKey HKCR "$0"
|
||||
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\FileAssociations" "$R0"
|
||||
skip_${MacroID}:
|
||||
|
||||
|
||||
Pop $0
|
||||
Pop $R0
|
||||
!verbose pop
|
||||
@@ -624,14 +624,14 @@ ${StrCase}
|
||||
|
||||
Exch $R0 ;mime
|
||||
Push $0
|
||||
|
||||
|
||||
ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0"
|
||||
StrCmp $0 "" skip_${MacroID}
|
||||
|
||||
|
||||
DeleteRegKey HKCR "$0"
|
||||
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\MimeAssociations" "$R0"
|
||||
skip_${MacroID}:
|
||||
|
||||
|
||||
Pop $0
|
||||
Pop $R0
|
||||
!verbose pop
|
||||
@@ -656,14 +656,14 @@ ${StrCase}
|
||||
|
||||
Exch $R0 ;protocol
|
||||
Push $0
|
||||
|
||||
|
||||
ReadRegStr $0 HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0"
|
||||
StrCmp $0 "" skip_${MacroID}
|
||||
|
||||
|
||||
DeleteRegKey HKCR "$0"
|
||||
DeleteRegValue HKLM "${CAPABILITIES_PATH}\Capabilities\UrlAssociations" "$R0"
|
||||
skip_${MacroID}:
|
||||
|
||||
|
||||
Pop $0
|
||||
Pop $R0
|
||||
!verbose pop
|
||||
|
||||
16
dist/windows/strawberry-64.nsi.in
vendored
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libcdio-18.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1-x64.dll"
|
||||
File "libfaad-2.dll"
|
||||
@@ -163,6 +163,7 @@ Section "Strawberry" Strawberry
|
||||
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
|
||||
@@ -263,7 +264,7 @@ Section "Start menu items" startmenu
|
||||
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"
|
||||
@@ -289,7 +290,7 @@ Section "Uninstall"
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
@@ -312,14 +313,14 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libcdio-18.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.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_sjlj-1.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"
|
||||
@@ -351,7 +352,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||
Delete "$INSTDIR\libspeex-1.dll"
|
||||
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||
Delete "$INSTDIR\libssl-1_1.dll"
|
||||
Delete "$INSTDIR\libssl-1_1-x64.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libtag.dll"
|
||||
Delete "$INSTDIR\libvorbis-0.dll"
|
||||
@@ -373,6 +374,7 @@ Section "Uninstall"
|
||||
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"
|
||||
|
||||
16
dist/windows/strawberry-debug-64.nsi.in
vendored
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libcdio-18.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1-x64.dll"
|
||||
File "libfaad-2.dll"
|
||||
@@ -164,6 +164,7 @@ Section "Strawberry" Strawberry
|
||||
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
|
||||
@@ -295,7 +296,7 @@ Section "Start menu items" startmenu
|
||||
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"
|
||||
@@ -321,7 +322,7 @@ Section "Uninstall"
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
@@ -344,14 +345,14 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libcdio-18.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.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_sjlj-1.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"
|
||||
@@ -383,7 +384,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||
Delete "$INSTDIR\libspeex-1.dll"
|
||||
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||
Delete "$INSTDIR\libssl-1_1.dll"
|
||||
Delete "$INSTDIR\libssl-1_1-x64.dll"
|
||||
Delete "$INSTDIR\libstdc++-6.dll"
|
||||
Delete "$INSTDIR\libtag.dll"
|
||||
Delete "$INSTDIR\libvorbis-0.dll"
|
||||
@@ -406,6 +407,7 @@ Section "Uninstall"
|
||||
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"
|
||||
|
||||
10
dist/windows/strawberry-debug.nsi.in
vendored
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libcdio-18.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1.dll"
|
||||
File "libfaad-2.dll"
|
||||
@@ -164,6 +164,7 @@ Section "Strawberry" Strawberry
|
||||
File "libxml2-2.dll"
|
||||
File "libsoup-2.4-1.dll"
|
||||
File "liblzma-5.dll"
|
||||
File "libdeezer.x86.dll"
|
||||
|
||||
; Register Strawberry with Default Programs
|
||||
Var /GLOBAL AppIcon
|
||||
@@ -295,7 +296,7 @@ Section "Start menu items" startmenu
|
||||
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"
|
||||
@@ -321,7 +322,7 @@ Section "Uninstall"
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
@@ -344,7 +345,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libcdio-18.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||
Delete "$INSTDIR\libfaad-2.dll"
|
||||
@@ -406,6 +407,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\libxml2-2.dll"
|
||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||
Delete "$INSTDIR\liblzma-5.dll"
|
||||
Delete "$INSTDIR\libdeezer.x86.dll"
|
||||
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||
|
||||
10
dist/windows/strawberry.nsi.in
vendored
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
|
||||
File "strawberry.ico"
|
||||
|
||||
File "libbz2.dll"
|
||||
File "libcdio-16.dll"
|
||||
File "libcdio-18.dll"
|
||||
File "libchromaprint.dll"
|
||||
File "libcrypto-1_1.dll"
|
||||
File "libfaad-2.dll"
|
||||
@@ -163,6 +163,7 @@ Section "Strawberry" Strawberry
|
||||
File "libxml2-2.dll"
|
||||
File "libsoup-2.4-1.dll"
|
||||
File "liblzma-5.dll"
|
||||
File "libdeezer.x86.dll"
|
||||
|
||||
; Register Strawberry with Default Programs
|
||||
Var /GLOBAL AppIcon
|
||||
@@ -263,7 +264,7 @@ Section "Start menu items" startmenu
|
||||
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"
|
||||
@@ -289,7 +290,7 @@ Section "Uninstall"
|
||||
;StrCmp $1 "-1" wooops
|
||||
|
||||
;StrCmp $0 "0" completed
|
||||
|
||||
|
||||
;DetailPrint "Killing running strawberry.exe..."
|
||||
|
||||
;StrCpy $0 "strawberry.exe"
|
||||
@@ -312,7 +313,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||
|
||||
Delete "$INSTDIR\libbz2.dll"
|
||||
Delete "$INSTDIR\libcdio-16.dll"
|
||||
Delete "$INSTDIR\libcdio-18.dll"
|
||||
Delete "$INSTDIR\libchromaprint.dll"
|
||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||
Delete "$INSTDIR\libfaad-2.dll"
|
||||
@@ -373,6 +374,7 @@ Section "Uninstall"
|
||||
Delete "$INSTDIR\libxml2-2.dll"
|
||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||
Delete "$INSTDIR\liblzma-5.dll"
|
||||
Delete "$INSTDIR\libdeezer.x86.dll"
|
||||
|
||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||
|
||||
@@ -64,7 +64,7 @@ void GLog(const char *domain, int level, const char *message, void *user_data) {
|
||||
case G_LOG_LEVEL_DEBUG:
|
||||
default: qLog(Debug) << message; break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
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() {
|
||||
|
||||
|
||||
delete sClassLevels;
|
||||
delete sNullDevice;
|
||||
|
||||
@@ -263,7 +263,6 @@ void DumpStackTrace() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
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); }
|
||||
|
||||
@@ -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 CreateLoggerDebug(int line, const char *class_name) { return qCreateLogger(line, class_name, Debug); }
|
||||
#endif // QT_NO_DEBUG_OUTPUT
|
||||
#endif
|
||||
|
||||
} // namespace logging
|
||||
|
||||
|
||||
@@ -27,22 +27,11 @@
|
||||
#ifdef QT_NO_DEBUG_STREAM
|
||||
# define qLog(level) while (false) QNoDebug()
|
||||
#else
|
||||
#define qLog(level) \
|
||||
logging::CreateLogger(logging::Level_##level, \
|
||||
logging::ParsePrettyFunction(__PRETTY_FUNCTION__), \
|
||||
__LINE__)
|
||||
#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 // 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 {
|
||||
class NullDevice : public QIODevice {
|
||||
protected:
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#include <taglib/tag.h>
|
||||
#include <taglib/apetag.h>
|
||||
#include <taglib/id3v2tag.h>
|
||||
#include "taglib/id3v2frame.h"
|
||||
#include <taglib/id3v2frame.h>
|
||||
#include <taglib/flacfile.h>
|
||||
#include <taglib/oggflacfile.h>
|
||||
#include <taglib/flacproperties.h>
|
||||
@@ -54,12 +54,12 @@
|
||||
#include <taglib/wavpackfile.h>
|
||||
#include <taglib/aifffile.h>
|
||||
#include <taglib/asffile.h>
|
||||
#include "taglib/asftag.h"
|
||||
#include "taglib/asfattribute.h"
|
||||
#include "taglib/asfproperties.h"
|
||||
#include <taglib/asftag.h>
|
||||
#include <taglib/asfattribute.h>
|
||||
#include <taglib/asfproperties.h>
|
||||
#include <taglib/mp4file.h>
|
||||
#include <taglib/mp4tag.h>
|
||||
#include "taglib/mp4item.h"
|
||||
#include <taglib/mp4item.h>
|
||||
#include <taglib/mp4coverart.h>
|
||||
#include <taglib/mp4properties.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())) {
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
|
||||
|
||||
if (file->tag()) {
|
||||
TagLib::MP4::Tag *mp4_tag = file->tag();
|
||||
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) {
|
||||
|
||||
|
||||
if (!codec) {
|
||||
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 {
|
||||
|
||||
|
||||
qLog(Debug) << "Parsing FMPSFrame" << name << ", " << value;
|
||||
FMPSParser parser;
|
||||
|
||||
|
||||
if (!parser.Parse(value) || parser.is_empty()) return;
|
||||
|
||||
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 {
|
||||
|
||||
|
||||
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["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 {
|
||||
|
||||
|
||||
const QByteArray descr_utf8(description.toUtf8());
|
||||
const QByteArray value_utf8(value.toUtf8());
|
||||
qLog(Debug) << "Setting FMPSFrame:" << description << ", " << value;
|
||||
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 {
|
||||
|
||||
|
||||
const TagLib::String t_description = StdStringToTaglibString(description);
|
||||
// Remove the frame if it already exists
|
||||
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 {
|
||||
|
||||
|
||||
const QByteArray utf8(value.toUtf8());
|
||||
SetTextFrame(id, std::string(utf8.constData(), utf8.length()), tag);
|
||||
}
|
||||
|
||||
void TagReader::SetTextFrame(const char *id, const std::string &value, TagLib::ID3v2::Tag *tag) const {
|
||||
|
||||
|
||||
TagLib::ByteVector id_vector(id);
|
||||
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
|
||||
tag->addFrame(frame);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
bool TagReader::IsMediaFile(const QString &filename) const {
|
||||
|
||||
|
||||
qLog(Debug) << "Checking for valid file" << filename;
|
||||
|
||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||
return !fileref->isNull() && fileref->tag();
|
||||
|
||||
|
||||
}
|
||||
|
||||
QByteArray TagReader::LoadEmbeddedArt(const QString &filename) const {
|
||||
|
||||
|
||||
if (filename.isEmpty()) return QByteArray();
|
||||
|
||||
qLog(Debug) << "Loading art from" << filename;
|
||||
|
||||
@@ -21,6 +21,7 @@ message SongMetadata {
|
||||
TRUEAUDIO = 13;
|
||||
DSF = 14;
|
||||
DSDIFF = 15;
|
||||
PCM = 16;
|
||||
CDDA = 90;
|
||||
STREAM = 91;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Strawberry Music Player
|
||||
# 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
|
||||
# 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(${LIBXML_INCLUDE_DIRS})
|
||||
include_directories(${CHROMAPRINT_INCLUDE_DIRS})
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
|
||||
if(HAVE_GSTREAMER)
|
||||
link_directories(${GSTREAMER_LIBRARY_DIRS})
|
||||
@@ -59,6 +56,14 @@ if(HAVE_PHONON)
|
||||
include_directories(${PHONON_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(HAVE_LIBDEEZER)
|
||||
include_directories(${DEEZER_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
if(HAVE_LIBDZMEDIA)
|
||||
include_directories(${DZMEDIA_INCLUDE_DIRS})
|
||||
endif()
|
||||
|
||||
link_directories(${TAGLIB_LIBRARY_DIRS})
|
||||
include_directories(${TAGLIB_INCLUDE_DIRS})
|
||||
|
||||
@@ -109,17 +114,17 @@ set(SOURCES
|
||||
core/windows7thumbbar.cpp
|
||||
core/screensaver.cpp
|
||||
core/scopedtransaction.cpp
|
||||
|
||||
|
||||
engine/enginetype.cpp
|
||||
engine/enginebase.cpp
|
||||
engine/enginedevice.cpp
|
||||
engine/devicefinder.cpp
|
||||
|
||||
|
||||
analyzer/fht.cpp
|
||||
analyzer/analyzerbase.cpp
|
||||
analyzer/analyzercontainer.cpp
|
||||
analyzer/blockanalyzer.cpp
|
||||
|
||||
|
||||
equalizer/equalizer.cpp
|
||||
equalizer/equalizerslider.cpp
|
||||
|
||||
@@ -158,11 +163,12 @@ set(SOURCES
|
||||
playlist/playlisttabbar.cpp
|
||||
playlist/playlistundocommands.cpp
|
||||
playlist/playlistview.cpp
|
||||
playlist/queue.cpp
|
||||
playlist/queuemanager.cpp
|
||||
playlist/songloaderinserter.cpp
|
||||
playlist/songplaylistitem.cpp
|
||||
|
||||
queue/queue.cpp
|
||||
queue/queueview.cpp
|
||||
|
||||
playlistparsers/asxiniparser.cpp
|
||||
playlistparsers/asxparser.cpp
|
||||
playlistparsers/cueparser.cpp
|
||||
@@ -173,7 +179,7 @@ set(SOURCES
|
||||
playlistparsers/wplparser.cpp
|
||||
playlistparsers/xmlparser.cpp
|
||||
playlistparsers/xspfparser.cpp
|
||||
|
||||
|
||||
covermanager/albumcovermanager.cpp
|
||||
covermanager/albumcovermanagerlist.cpp
|
||||
covermanager/albumcoverloader.cpp
|
||||
@@ -211,7 +217,6 @@ set(SOURCES
|
||||
settings/shortcutssettingspage.cpp
|
||||
settings/appearancesettingspage.cpp
|
||||
settings/notificationssettingspage.cpp
|
||||
settings/tidalsettingspage.cpp
|
||||
|
||||
dialogs/about.cpp
|
||||
dialogs/console.cpp
|
||||
@@ -244,27 +249,25 @@ set(SOURCES
|
||||
widgets/tracksliderpopup.cpp
|
||||
widgets/tracksliderslider.cpp
|
||||
widgets/loginstatewidget.cpp
|
||||
|
||||
|
||||
musicbrainz/acoustidclient.cpp
|
||||
musicbrainz/musicbrainzclient.cpp
|
||||
|
||||
|
||||
globalshortcuts/globalshortcutbackend.cpp
|
||||
globalshortcuts/globalshortcuts.cpp
|
||||
globalshortcuts/gnomeglobalshortcutbackend.cpp
|
||||
globalshortcuts/qxtglobalshortcutbackend.cpp
|
||||
globalshortcuts/globalshortcutgrabber.cpp
|
||||
|
||||
internet/internetmodel.cpp
|
||||
internet/internetservices.cpp
|
||||
internet/internetservice.cpp
|
||||
internet/internetplaylistitem.cpp
|
||||
|
||||
tidal/tidalservice.cpp
|
||||
tidal/tidalsearch.cpp
|
||||
tidal/tidalsearchview.cpp
|
||||
tidal/tidalsearchmodel.cpp
|
||||
tidal/tidalsearchsortmodel.cpp
|
||||
tidal/tidalsearchitemdelegate.cpp
|
||||
tidal/tidalurlhandler.cpp
|
||||
internet/internetsearch.cpp
|
||||
internet/internetsearchview.cpp
|
||||
internet/internetsearchmodel.cpp
|
||||
internet/internetsearchsortmodel.cpp
|
||||
internet/internetsearchitemdelegate.cpp
|
||||
internet/localredirectserver.cpp
|
||||
|
||||
)
|
||||
|
||||
@@ -294,10 +297,10 @@ set(HEADERS
|
||||
analyzer/analyzerbase.h
|
||||
analyzer/analyzercontainer.h
|
||||
analyzer/blockanalyzer.h
|
||||
|
||||
|
||||
equalizer/equalizer.h
|
||||
equalizer/equalizerslider.h
|
||||
|
||||
|
||||
context/contextview.h
|
||||
context/contextalbumsmodel.h
|
||||
context/contextalbumsview.h
|
||||
@@ -328,11 +331,12 @@ set(HEADERS
|
||||
playlist/playlisttabbar.h
|
||||
playlist/playlistview.h
|
||||
playlist/playlistitemmimedata.h
|
||||
playlist/queue.h
|
||||
playlist/queuemanager.h
|
||||
playlist/songloaderinserter.h
|
||||
playlist/songmimedata.h
|
||||
|
||||
queue/queue.h
|
||||
queue/queueview.h
|
||||
|
||||
playlistparsers/asxiniparser.h
|
||||
playlistparsers/asxparser.h
|
||||
playlistparsers/cueparser.h
|
||||
@@ -341,7 +345,7 @@ set(HEADERS
|
||||
playlistparsers/playlistparser.h
|
||||
playlistparsers/plsparser.h
|
||||
playlistparsers/xspfparser.h
|
||||
|
||||
|
||||
covermanager/albumcovermanager.h
|
||||
covermanager/albumcovermanagerlist.h
|
||||
covermanager/albumcoverloader.h
|
||||
@@ -378,7 +382,6 @@ set(HEADERS
|
||||
settings/shortcutssettingspage.h
|
||||
settings/appearancesettingspage.h
|
||||
settings/notificationssettingspage.h
|
||||
settings/tidalsettingspage.h
|
||||
|
||||
dialogs/about.h
|
||||
dialogs/errordialog.h
|
||||
@@ -409,25 +412,22 @@ set(HEADERS
|
||||
widgets/tracksliderpopup.h
|
||||
widgets/tracksliderslider.h
|
||||
widgets/loginstatewidget.h
|
||||
|
||||
|
||||
musicbrainz/acoustidclient.h
|
||||
musicbrainz/musicbrainzclient.h
|
||||
|
||||
|
||||
globalshortcuts/globalshortcutbackend.h
|
||||
globalshortcuts/globalshortcuts.h
|
||||
globalshortcuts/gnomeglobalshortcutbackend.h
|
||||
globalshortcuts/globalshortcutgrabber.h
|
||||
|
||||
internet/internetmodel.h
|
||||
internet/internetservices.h
|
||||
internet/internetservice.h
|
||||
internet/internetmimedata.h
|
||||
internet/internetsongmimedata.h
|
||||
|
||||
tidal/tidalservice.h
|
||||
tidal/tidalsearch.h
|
||||
tidal/tidalsearchview.h
|
||||
tidal/tidalsearchmodel.h
|
||||
tidal/tidalurlhandler.h
|
||||
internet/internetsearch.h
|
||||
internet/internetsearchview.h
|
||||
internet/internetsearchmodel.h
|
||||
internet/localredirectserver.h
|
||||
|
||||
)
|
||||
|
||||
@@ -446,7 +446,8 @@ set(UI
|
||||
playlist/playlistlistcontainer.ui
|
||||
playlist/playlistsaveoptionsdialog.ui
|
||||
playlist/playlistsequence.ui
|
||||
playlist/queuemanager.ui
|
||||
|
||||
queue/queueview.ui
|
||||
|
||||
covermanager/albumcoverexport.ui
|
||||
covermanager/albumcovermanager.ui
|
||||
@@ -464,7 +465,6 @@ set(UI
|
||||
settings/shortcutssettingspage.ui
|
||||
settings/appearancesettingspage.ui
|
||||
settings/notificationssettingspage.ui
|
||||
settings/tidalsettingspage.ui
|
||||
|
||||
equalizer/equalizer.ui
|
||||
equalizer/equalizerslider.ui
|
||||
@@ -479,14 +479,14 @@ set(UI
|
||||
widgets/osdpretty.ui
|
||||
widgets/fileview.ui
|
||||
widgets/loginstatewidget.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)
|
||||
|
||||
option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON)
|
||||
@@ -524,6 +524,12 @@ optional_source(HAVE_PHONON
|
||||
HEADERS engine/phononengine.h
|
||||
)
|
||||
|
||||
# Deezer
|
||||
optional_source(HAVE_DEEZER
|
||||
SOURCES engine/deezerengine.cpp
|
||||
HEADERS engine/deezerengine.h
|
||||
)
|
||||
|
||||
# Lastfm
|
||||
optional_source(HAVE_LIBLASTFM
|
||||
SOURCES
|
||||
@@ -711,12 +717,12 @@ optional_source(HAVE_GIO
|
||||
HEADERS device/giolister.h
|
||||
)
|
||||
|
||||
# libimobiledevice backend and device
|
||||
# imobiledevice backend and device
|
||||
optional_source(HAVE_IMOBILEDEVICE
|
||||
INCLUDE_DIRECTORIES
|
||||
${IMOBILEDEVICE_INCLUDE_DIRS}
|
||||
${PLIST_INCLUDE_DIRS}
|
||||
${PLISTPP_INCLUDE_DIRS}
|
||||
${LIBIMOBILEDEVICE_INCLUDE_DIRS}
|
||||
${LIBPLIST_INCLUDE_DIRS}
|
||||
${LIBPLISTPP_INCLUDE_DIRS}
|
||||
SOURCES
|
||||
device/afcdevice.cpp
|
||||
device/afcfile.cpp
|
||||
@@ -848,6 +854,32 @@ optional_source(WIN32
|
||||
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
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||
|
||||
@@ -880,6 +912,7 @@ target_link_libraries(strawberry_lib
|
||||
${QT_LIBRARIES}
|
||||
${CHROMAPRINT_LIBRARIES}
|
||||
${QTSINGLEAPPLICATION_LIBRARIES}
|
||||
${QTSINGLECOREAPPLICATION_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
${SQLITE_LIBRARIES}
|
||||
${QOCOA_LIBRARIES}
|
||||
@@ -906,6 +939,14 @@ if(HAVE_PHONON)
|
||||
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
|
||||
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)
|
||||
target_link_libraries(strawberry_lib ${LASTFM5_LIBRARIES})
|
||||
endif(HAVE_LIBLASTFM)
|
||||
@@ -924,12 +965,12 @@ endif(HAVE_AUDIOCD)
|
||||
|
||||
if(HAVE_IMOBILEDEVICE)
|
||||
target_link_libraries(strawberry_lib
|
||||
${IMOBILEDEVICE_LIBRARIES}
|
||||
${PLIST_LIBRARIES}
|
||||
${USBMUXD_LIBRARIES}
|
||||
${LIBIMOBILEDEVICE_LIBRARIES}
|
||||
${LIBPLIST_LIBRARIES}
|
||||
${LIBUSBMUXD_LIBRARIES}
|
||||
)
|
||||
link_directories(${IMOBILEDEVICE_LIBRARY_DIRS})
|
||||
link_directories(${USBMUXD_LIBRARY_DIRS})
|
||||
link_directories(${LIBIMOBILEDEVICE_LIBRARY_DIRS})
|
||||
link_directories(${LIBUSBMUXD_LIBRARY_DIRS})
|
||||
endif(HAVE_IMOBILEDEVICE)
|
||||
|
||||
if(HAVE_LIBMTP)
|
||||
|
||||
@@ -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>&)));
|
||||
}
|
||||
}
|
||||
@@ -27,14 +27,13 @@
|
||||
|
||||
#include "analyzerbase.h"
|
||||
|
||||
#include "core/logging.h"
|
||||
#include "engine/enginebase.h"
|
||||
|
||||
// INSTRUCTIONS Base2D
|
||||
// 1. do anything that depends on height() in init(), Base2D will call it before
|
||||
// you are shown
|
||||
// 1. do anything that depends on height() in init(), Base2D will call it before you are shown
|
||||
// 2. otherwise you can use the constructor to initialise things
|
||||
// 3. reimplement analyze(), and paint to canvas(), Base2D will update the
|
||||
// widget when you return control to it
|
||||
// 3. reimplement analyze(), and paint to canvas(), Base2D will update the widget when you return control to it
|
||||
// 4. if you want to manipulate the scope, reimplement transform()
|
||||
// 5. for convenience <vector> <qpixmap.h> <qwdiget.h> are pre-included
|
||||
// TODO make an INSTRUCTIONS file
|
||||
@@ -50,37 +49,32 @@ template class Analyzer::Base<QWidget>;
|
||||
|
||||
Analyzer::Base::Base(QWidget *parent, uint scopeSize)
|
||||
: QWidget(parent),
|
||||
m_timeout(40) // msec
|
||||
,
|
||||
m_fht(new FHT(scopeSize)),
|
||||
m_engine(nullptr),
|
||||
m_lastScope(512),
|
||||
timeout_(40),
|
||||
fht_(new FHT(scopeSize)),
|
||||
engine_(nullptr),
|
||||
lastscope_(512),
|
||||
current_chunk_(0),
|
||||
new_frame_(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
|
||||
// an FFT scope that has bands for pretty analyzers
|
||||
// This is a standard transformation that should give an FFT scope that has bands for pretty analyzers
|
||||
|
||||
// NOTE resizing here is redundant as FHT routines only calculate FHT::size()
|
||||
// values
|
||||
// scope.resize( m_fht->size() );
|
||||
// NOTE: Resizing here is redundant as FHT routines only calculate FHT::size() values scope.resize( fht_->size() );
|
||||
|
||||
float *front = static_cast<float*>(&scope.front());
|
||||
|
||||
float *f = new float[m_fht->size()];
|
||||
m_fht->copy(&f[0], front);
|
||||
m_fht->logSpectrum(front, &f[0]);
|
||||
m_fht->scale(front, 1.0 / 20);
|
||||
float *f = new float[fht_->size()];
|
||||
fht_->copy(&f[0], front);
|
||||
fht_->logSpectrum(front, &f[0]);
|
||||
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;
|
||||
|
||||
}
|
||||
@@ -90,28 +84,28 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
|
||||
QPainter p(this);
|
||||
p.fillRect(e->rect(), palette().color(QPalette::Window));
|
||||
|
||||
switch (m_engine->state()) {
|
||||
switch (engine_->state()) {
|
||||
case Engine::Playing: {
|
||||
const Engine::Scope& thescope = m_engine->scope(m_timeout);
|
||||
const Engine::Scope& thescope = engine_->scope(timeout_);
|
||||
int i = 0;
|
||||
|
||||
// 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) {
|
||||
m_lastScope[x] = double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
|
||||
for (uint x = 0; (int)x < fht_->size(); ++x) {
|
||||
lastscope_[x] = double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
|
||||
i += 2;
|
||||
}
|
||||
|
||||
is_playing_ = true;
|
||||
transform(m_lastScope);
|
||||
analyze(p, m_lastScope, new_frame_);
|
||||
transform(lastscope_);
|
||||
analyze(p, lastscope_, new_frame_);
|
||||
|
||||
// scope.resize( m_fht->size() );
|
||||
lastscope_.resize(fht_->size());
|
||||
|
||||
break;
|
||||
}
|
||||
case Engine::Paused:
|
||||
is_playing_ = false;
|
||||
analyze(p, m_lastScope, new_frame_);
|
||||
analyze(p, lastscope_, new_frame_);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -124,16 +118,18 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
|
||||
}
|
||||
|
||||
int Analyzer::Base::resizeExponent(int exp) {
|
||||
|
||||
if (exp < 3)
|
||||
exp = 3;
|
||||
else if (exp > 9)
|
||||
exp = 9;
|
||||
|
||||
if (exp != m_fht->sizeExp()) {
|
||||
delete m_fht;
|
||||
m_fht = new FHT(exp);
|
||||
if (exp != fht_->sizeExp()) {
|
||||
delete fht_;
|
||||
fht_ = new FHT(exp);
|
||||
}
|
||||
return exp;
|
||||
|
||||
}
|
||||
|
||||
int Analyzer::Base::resizeForBands(int bands) {
|
||||
@@ -153,12 +149,11 @@ int Analyzer::Base::resizeForBands(int bands) {
|
||||
exp = 9;
|
||||
|
||||
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
|
||||
|
||||
@@ -171,7 +166,8 @@ void Analyzer::Base::demo(QPainter& p) // virtual
|
||||
s[i] = dt * (sin(M_PI + (i * M_PI) / s.size()) + 1.0);
|
||||
|
||||
analyze(p, s, new_frame_);
|
||||
} else
|
||||
}
|
||||
else
|
||||
analyze(p, Scope(32, 0), new_frame_);
|
||||
|
||||
++t;
|
||||
@@ -179,7 +175,7 @@ void Analyzer::Base::demo(QPainter& p) // virtual
|
||||
}
|
||||
|
||||
void Analyzer::Base::polishEvent() {
|
||||
init(); // virtual
|
||||
init();
|
||||
}
|
||||
|
||||
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) {
|
||||
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;
|
||||
|
||||
unsigned long indexRight = offset + 1;
|
||||
uint64_t indexRight = offset + 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) {
|
||||
|
||||
double step = (M_PI * 2) / size;
|
||||
double radian = 0;
|
||||
|
||||
@@ -212,12 +209,15 @@ void Analyzer::initSin(Scope& v, const uint size) {
|
||||
v.push_back(sin(radian));
|
||||
radian += step;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Analyzer::Base::timerEvent(QTimerEvent *e) {
|
||||
|
||||
QWidget::timerEvent(e);
|
||||
if (e->timerId() != m_timer.timerId()) return;
|
||||
if (e->timerId() != timer_.timerId()) return;
|
||||
|
||||
new_frame_ = true;
|
||||
update();
|
||||
|
||||
}
|
||||
|
||||
@@ -37,17 +37,17 @@ class Base : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
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) {
|
||||
m_timeout = newTimeout;
|
||||
if (m_timer.isActive()) {
|
||||
m_timer.stop();
|
||||
m_timer.start(m_timeout, this);
|
||||
timeout_ = newTimeout;
|
||||
if (timer_.isActive()) {
|
||||
timer_.stop();
|
||||
timer_.start(timeout_, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,13 +71,12 @@ class Base : public QWidget {
|
||||
virtual void demo(QPainter& p);
|
||||
|
||||
protected:
|
||||
QBasicTimer m_timer;
|
||||
uint m_timeout;
|
||||
FHT* m_fht;
|
||||
EngineBase* m_engine;
|
||||
Scope m_lastScope;
|
||||
QBasicTimer timer_;
|
||||
uint timeout_;
|
||||
FHT *fht_;
|
||||
EngineBase *engine_;
|
||||
Scope lastscope_;
|
||||
int current_chunk_;
|
||||
|
||||
bool new_frame_;
|
||||
bool is_playing_;
|
||||
};
|
||||
|
||||
@@ -26,109 +26,105 @@ const uint BlockAnalyzer::MIN_COLUMNS = 32; // arbituary
|
||||
const uint BlockAnalyzer::MAX_COLUMNS = 256; // must be 2**n
|
||||
const uint BlockAnalyzer::FADE_SIZE = 90;
|
||||
|
||||
const char *BlockAnalyzer::kName =
|
||||
QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
|
||||
const char *BlockAnalyzer::kName = QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
|
||||
|
||||
BlockAnalyzer::BlockAnalyzer(QWidget *parent)
|
||||
: Analyzer::Base(parent, 9),
|
||||
m_columns(0) // uint
|
||||
,
|
||||
m_rows(0) // uint
|
||||
,
|
||||
m_y(0) // uint
|
||||
,
|
||||
m_barPixmap(1, 1) // null qpixmaps cause crashes
|
||||
,
|
||||
m_topBarPixmap(WIDTH, HEIGHT),
|
||||
m_scope(MIN_COLUMNS) // Scope
|
||||
,
|
||||
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>
|
||||
{
|
||||
columns_(0),
|
||||
rows_(0),
|
||||
y_(0),
|
||||
barpixmap_(1, 1),
|
||||
topbarpixmap_(WIDTH, HEIGHT),
|
||||
scope_(MIN_COLUMNS),
|
||||
store_(1 << 8, 0),
|
||||
fade_bars_(FADE_SIZE),
|
||||
fade_pos_(1 << 8, 50),
|
||||
fade_intensity_(1 << 8, 32) {
|
||||
|
||||
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);
|
||||
|
||||
// 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() {}
|
||||
|
||||
void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
QWidget::resizeEvent(e);
|
||||
|
||||
m_background = QPixmap(size());
|
||||
background_ = QPixmap(size());
|
||||
canvas_ = QPixmap(size());
|
||||
|
||||
const uint oldRows = m_rows;
|
||||
const uint oldRows = rows_;
|
||||
|
||||
// all is explained in analyze()..
|
||||
//+1 to counter -1 in maxSizes, trust me we need this!
|
||||
m_columns = qMax(uint(double(width() + 1) / (WIDTH + 1)), MAX_COLUMNS);
|
||||
m_rows = uint(double(height() + 1) / (HEIGHT + 1));
|
||||
columns_ = qMax(uint(double(width() + 1) / (WIDTH + 1)), MAX_COLUMNS);
|
||||
rows_ = uint(double(height() + 1) / (HEIGHT + 1));
|
||||
|
||||
// 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) {
|
||||
m_barPixmap = QPixmap(WIDTH, m_rows * (HEIGHT + 1));
|
||||
if (rows_ != oldRows) {
|
||||
barpixmap_ = QPixmap(WIDTH, rows_ * (HEIGHT + 1));
|
||||
|
||||
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,
|
||||
PRO = 1; // PRE and PRO allow us to restrict the range somewhat
|
||||
const uint PRE = 1, PRO = 1; // PRE and PRO allow us to restrict the range somewhat
|
||||
|
||||
for (uint z = 0; z < m_rows; ++z)
|
||||
m_yscale[z] = 1 - (log10(PRE + z) / log10(PRE + m_rows + PRO));
|
||||
for (uint z = 0; z < rows_; ++z)
|
||||
yscale_[z] = 1 - (log10(PRE + z) / log10(PRE + rows_ + PRO));
|
||||
|
||||
m_yscale[m_rows] = 0;
|
||||
yscale_[rows_] = 0;
|
||||
|
||||
determineStep();
|
||||
paletteChange(palette());
|
||||
}
|
||||
|
||||
drawBackground();
|
||||
|
||||
}
|
||||
|
||||
void BlockAnalyzer::determineStep() {
|
||||
|
||||
// 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
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
float* front = static_cast<float*>(&s.front());
|
||||
|
||||
m_fht->spectrum(front);
|
||||
m_fht->scale(front, 1.0 / 20);
|
||||
fht_->spectrum(front);
|
||||
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,
|
||||
bool new_frame) {
|
||||
void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_frame) {
|
||||
|
||||
// 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 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 (!new_frame) {
|
||||
@@ -149,50 +145,51 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
||||
|
||||
QPainter canvas_painter(&canvas_);
|
||||
|
||||
Analyzer::interpolate(s, m_scope);
|
||||
Analyzer::interpolate(s, scope_);
|
||||
|
||||
// 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
|
||||
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)
|
||||
if ((float)y > m_store[x])
|
||||
y = int(m_store[x] += m_step);
|
||||
if ((float)y > store_[x])
|
||||
y = int(store_[x] += step_);
|
||||
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 (y <= m_fade_pos[x] /*|| m_fade_intensity[x] < FADE_SIZE / 3*/) {
|
||||
m_fade_pos[x] = y;
|
||||
m_fade_intensity[x] = FADE_SIZE;
|
||||
if (y <= fade_pos_[x] /*|| fade_intensity_[x] < FADE_SIZE / 3*/) {
|
||||
fade_pos_[x] = y;
|
||||
fade_intensity_[x] = FADE_SIZE;
|
||||
}
|
||||
|
||||
if (m_fade_intensity[x] > 0) {
|
||||
const uint offset = --m_fade_intensity[x];
|
||||
const uint y = m_y + (m_fade_pos[x] * (HEIGHT + 1));
|
||||
canvas_painter.drawPixmap(x * (WIDTH + 1), y, m_fade_bars[offset], 0, 0, WIDTH, height() - y);
|
||||
if (fade_intensity_[x] > 0) {
|
||||
const uint offset = --fade_intensity_[x];
|
||||
const uint y = y_ + (fade_pos_[x] * (HEIGHT + 1));
|
||||
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
|
||||
canvas_painter.drawPixmap(x * (WIDTH + 1), y * (HEIGHT + 1) + m_y, *bar(),
|
||||
// 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) + y_, *bar(),
|
||||
0, y * (HEIGHT + 1), bar()->width(),
|
||||
bar()->height());
|
||||
}
|
||||
|
||||
for (uint x = 0; x < m_store.size(); ++x)
|
||||
canvas_painter.drawPixmap(x * (WIDTH + 1), int(m_store[x]) * (HEIGHT + 1) + m_y, m_topBarPixmap);
|
||||
for (uint x = 0; x < store_.size(); ++x)
|
||||
canvas_painter.drawPixmap(x * (WIDTH + 1), int(store_[x]) * (HEIGHT + 1) + y_, topbarpixmap_);
|
||||
|
||||
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
|
||||
|
||||
if (b < f) {
|
||||
@@ -215,6 +212,7 @@ static inline void adjustToLimits(int& b, int& f, uint& amount) {
|
||||
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
|
||||
* @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 {
|
||||
public:
|
||||
OutputOnExit(const QColor& color) : c(color) {}
|
||||
OutputOnExit(const QColor &color) : c(color) {}
|
||||
~OutputOnExit() {
|
||||
int h, s, v;
|
||||
c.getHsv(&h, &s, &v);
|
||||
}
|
||||
|
||||
private:
|
||||
const QColor& c;
|
||||
const QColor &c;
|
||||
};
|
||||
|
||||
// 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 STAMP
|
||||
|
||||
}
|
||||
|
||||
void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
||||
{
|
||||
void BlockAnalyzer::paletteChange(const QPalette&) {
|
||||
|
||||
const QColor bg = palette().color(QPalette::Background);
|
||||
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 dg = 15 * double(bg.green() - fg.green()) / (m_rows * 16);
|
||||
const double db = 15 * double(bg.blue() - fg.blue()) / (m_rows * 16);
|
||||
const double dr = 15 * double(bg.red() - fg.red()) / (rows_ * 16);
|
||||
const double dg = 15 * double(bg.green() - fg.green()) / (rows_ * 16);
|
||||
const double db = 15 * double(bg.blue() - fg.blue()) / (rows_ * 16);
|
||||
const int r = fg.red(), g = fg.green(), b = fg.blue();
|
||||
|
||||
bar()->fill(bg);
|
||||
|
||||
QPainter p(bar());
|
||||
for (int y = 0; (uint)y < m_rows; ++y)
|
||||
for (int y = 0; (uint)y < rows_; ++y)
|
||||
// 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)));
|
||||
|
||||
@@ -389,9 +389,9 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
||||
|
||||
// Precalculate all fade-bar pixmaps
|
||||
for (uint y = 0; y < FADE_SIZE; ++y) {
|
||||
m_fade_bars[y].fill(palette().color(QPalette::Background));
|
||||
QPainter f(&m_fade_bars[y]);
|
||||
for (int z = 0; (uint)z < m_rows; ++z) {
|
||||
fade_bars_[y].fill(palette().color(QPalette::Background));
|
||||
QPainter f(&fade_bars_[y]);
|
||||
for (int z = 0; (uint)z < rows_; ++z) {
|
||||
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)));
|
||||
}
|
||||
@@ -399,16 +399,19 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
||||
}
|
||||
|
||||
drawBackground();
|
||||
|
||||
}
|
||||
|
||||
void BlockAnalyzer::drawBackground() {
|
||||
|
||||
const QColor bg = palette().color(QPalette::Background);
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -51,24 +51,24 @@ class BlockAnalyzer : public Analyzer::Base {
|
||||
void determineStep();
|
||||
|
||||
private:
|
||||
QPixmap* bar() { return &m_barPixmap; }
|
||||
QPixmap *bar() { return &barpixmap_; }
|
||||
|
||||
uint m_columns, m_rows; // number of rows and columns of blocks
|
||||
uint m_y; // y-offset from top of widget
|
||||
QPixmap m_barPixmap;
|
||||
QPixmap m_topBarPixmap;
|
||||
QPixmap m_background;
|
||||
uint columns_, rows_; // number of rows and columns of blocks
|
||||
uint y_; // y-offset from top of widget
|
||||
QPixmap barpixmap_;
|
||||
QPixmap topbarpixmap_;
|
||||
QPixmap background_;
|
||||
QPixmap canvas_;
|
||||
Analyzer::Scope m_scope; // so we don't create a vector every frame
|
||||
std::vector<float> m_store; // current bar heights
|
||||
std::vector<float> m_yscale;
|
||||
Analyzer::Scope scope_; // so we don't create a vector every frame
|
||||
std::vector<float> store_; // current bar heights
|
||||
std::vector<float> yscale_;
|
||||
|
||||
// FIXME why can't I namespace these? c++ issue?
|
||||
std::vector<QPixmap> m_fade_bars;
|
||||
std::vector<uint> m_fade_pos;
|
||||
std::vector<int> m_fade_intensity;
|
||||
std::vector<QPixmap> fade_bars_;
|
||||
std::vector<uint> fade_pos_;
|
||||
std::vector<int> fade_intensity_;
|
||||
|
||||
float m_step; // rows to fall per frame
|
||||
float step_; // rows to fall per frame
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,7 @@ SCollection::~SCollection() {
|
||||
}
|
||||
|
||||
void SCollection::Init() {
|
||||
|
||||
|
||||
watcher_ = new CollectionWatcher;
|
||||
watcher_thread_ = new Thread(this);
|
||||
watcher_thread_->SetIoPriority(Utilities::IOPRIO_CLASS_IDLE);
|
||||
@@ -116,7 +116,7 @@ void SCollection::Stopped() {
|
||||
}
|
||||
|
||||
void SCollection::CurrentSongChanged(const Song &song) {
|
||||
|
||||
|
||||
TagReaderReply *reply = nullptr;
|
||||
|
||||
if (reply) {
|
||||
|
||||
@@ -531,7 +531,7 @@ void CollectionBackend::MarkSongsUnavailable(const SongList &songs, bool unavail
|
||||
}
|
||||
|
||||
QStringList CollectionBackend::GetAll(const QString &column, const QueryOptions &opt) {
|
||||
|
||||
|
||||
CollectionQuery query(opt);
|
||||
query.SetColumnSpec("DISTINCT " + column);
|
||||
query.AddCompilationRequirement(false);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
@@ -61,6 +62,8 @@
|
||||
#include "playlist/songmimedata.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
|
||||
using std::bind;
|
||||
using std::sort;
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
@@ -329,10 +332,10 @@ QString CollectionModel::DividerKey(GroupBy type, CollectionItem *item) const {
|
||||
|
||||
case GroupBy_Bitrate:
|
||||
return SortTextForNumber(item->metadata.bitrate());
|
||||
|
||||
|
||||
case GroupBy_Samplerate:
|
||||
return SortTextForNumber(item->metadata.samplerate());
|
||||
|
||||
|
||||
case GroupBy_Bitdepth:
|
||||
return SortTextForNumber(item->metadata.bitdepth());
|
||||
|
||||
@@ -374,11 +377,11 @@ QString CollectionModel::DividerDisplayText(GroupBy type, const QString &key) co
|
||||
case GroupBy_Bitrate:
|
||||
if (key == "000") return tr("Unknown");
|
||||
return QString::number(key.toInt()); // To remove leading 0s
|
||||
|
||||
|
||||
case GroupBy_Samplerate:
|
||||
if (key == "000") return tr("Unknown");
|
||||
return QString::number(key.toInt()); // To remove leading 0s
|
||||
|
||||
|
||||
case GroupBy_Bitdepth:
|
||||
if (key == "000") return tr("Unknown");
|
||||
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->sort_text = SortTextForNumber(bitrate) + " ";
|
||||
break;
|
||||
|
||||
|
||||
case GroupBy_Samplerate:
|
||||
samplerate = qMax(0, s.samplerate());
|
||||
item->key = QString::number(samplerate);
|
||||
item->sort_text = SortTextForNumber(samplerate) + " ";
|
||||
break;
|
||||
|
||||
|
||||
case GroupBy_Bitdepth:
|
||||
bitdepth = qMax(0, s.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);
|
||||
|
||||
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)
|
||||
GetChildSongs(child, urls, songs, song_ids);
|
||||
|
||||
@@ -346,7 +346,7 @@ void CollectionView::ReloadSettings() {
|
||||
app_->collection_model()->set_pretty_covers(settings.value("pretty_covers", true).toBool());
|
||||
app_->collection_model()->set_show_dividers(settings.value("show_dividers", true).toBool());
|
||||
}
|
||||
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
}
|
||||
@@ -371,7 +371,7 @@ void CollectionView::TotalSongCountUpdated(int count) {
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
else
|
||||
unsetCursor();
|
||||
|
||||
|
||||
emit TotalSongCountUpdated_();
|
||||
|
||||
}
|
||||
@@ -386,7 +386,7 @@ void CollectionView::TotalArtistCountUpdated(int count) {
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
else
|
||||
unsetCursor();
|
||||
|
||||
|
||||
emit TotalArtistCountUpdated_();
|
||||
|
||||
}
|
||||
@@ -401,7 +401,7 @@ void CollectionView::TotalAlbumCountUpdated(int count) {
|
||||
setCursor(Qt::PointingHandCursor);
|
||||
else
|
||||
unsetCursor();
|
||||
|
||||
|
||||
emit TotalAlbumCountUpdated_();
|
||||
|
||||
}
|
||||
@@ -458,6 +458,7 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
||||
|
||||
context_menu_->addSeparator();
|
||||
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
|
||||
context_menu_->addSeparator();
|
||||
@@ -616,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() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
|
||||
@@ -84,7 +84,7 @@ class CollectionView : public AutoExpandingTreeView {
|
||||
// QTreeView
|
||||
void keyboardSearch(const QString &search);
|
||||
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);
|
||||
|
||||
|
||||
int TotalSongs();
|
||||
int TotalArtists();
|
||||
int TotalAlbums();
|
||||
@@ -117,6 +117,7 @@ signals:
|
||||
void Load();
|
||||
void AddToPlaylist();
|
||||
void AddToPlaylistEnqueue();
|
||||
void AddToPlaylistEnqueueNext();
|
||||
void OpenInNewPlaylist();
|
||||
#ifdef HAVE_GSTREAMER
|
||||
void Organise();
|
||||
@@ -148,6 +149,7 @@ signals:
|
||||
QAction *load_;
|
||||
QAction *add_to_playlist_;
|
||||
QAction *add_to_playlist_enqueue_;
|
||||
QAction *add_to_playlist_enqueue_next_;
|
||||
QAction *open_in_new_playlist_;
|
||||
#ifdef HAVE_GSTREAMER
|
||||
QAction *organise_;
|
||||
|
||||
@@ -76,7 +76,6 @@ CollectionWatcher::CollectionWatcher(QObject *parent)
|
||||
rescan_paused_(false),
|
||||
total_watches_(0),
|
||||
cue_parser_(new CueParser(backend_, this)) {
|
||||
Utilities::SetThreadIOPriority(Utilities::IOPRIO_CLASS_IDLE);
|
||||
|
||||
rescan_timer_->setInterval(1000);
|
||||
rescan_timer_->setSingleShot(true);
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<string>Collection advanced grouping</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<iconset resource="../../data/icons.qrc">
|
||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
@@ -358,6 +358,7 @@
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
<include location="../../data/icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
|
||||
@@ -106,6 +106,7 @@
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
<include location="../../data/icons.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
|
||||
@@ -37,7 +37,7 @@ class SqlRow {
|
||||
SqlRow(const CollectionQuery &query);
|
||||
|
||||
const QVariant &value(int i) const { return columns_[i]; }
|
||||
|
||||
|
||||
QList<QVariant> columns_;
|
||||
|
||||
private:
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
/* This file is part of Strawberry.
|
||||
|
||||
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/>.
|
||||
*/
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
*
|
||||
* 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 CONFIG_H_IN
|
||||
#define CONFIG_H_IN
|
||||
|
||||
#define CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}"
|
||||
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||
#define CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}"
|
||||
|
||||
#cmakedefine DEBUG
|
||||
#cmakedefine HAVE_GIO
|
||||
#cmakedefine HAVE_DBUS
|
||||
#cmakedefine HAVE_X11
|
||||
@@ -38,6 +43,7 @@
|
||||
#cmakedefine HAVE_SPARKLE
|
||||
#cmakedefine HAVE_CHROMAPRINT
|
||||
#cmakedefine HAVE_TAGLIB_DSFFILE
|
||||
#cmakedefine HAVE_DZMEDIA
|
||||
#cmakedefine IMOBILEDEVICE_USES_UDIDS
|
||||
#cmakedefine USE_INSTALL_PREFIX
|
||||
#cmakedefine USE_SYSTEM_SHA2
|
||||
@@ -46,6 +52,10 @@
|
||||
#cmakedefine HAVE_VLC
|
||||
#cmakedefine HAVE_XINE
|
||||
#cmakedefine HAVE_PHONON
|
||||
#cmakedefine HAVE_DEEZER
|
||||
|
||||
#cmakedefine HAVE_STREAM_TIDAL
|
||||
#cmakedefine HAVE_STREAM_DEEZER
|
||||
|
||||
#endif // CONFIG_H_IN
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "config.h"
|
||||
|
||||
#include <functional>
|
||||
#include <algorithm>
|
||||
|
||||
#include <QObject>
|
||||
#include <QtGlobal>
|
||||
@@ -55,6 +56,8 @@
|
||||
|
||||
#include "contextalbumsmodel.h"
|
||||
|
||||
using std::bind;
|
||||
using std::sort;
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
@@ -93,7 +96,7 @@ void ContextAlbumsModel::set_pretty_covers(bool use_pretty_covers) {
|
||||
use_pretty_covers_ = use_pretty_covers;
|
||||
Reset();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ContextAlbumsModel::AddSongs(const SongList &songs) {
|
||||
@@ -479,7 +482,7 @@ void ContextAlbumsModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls,
|
||||
const_cast<ContextAlbumsModel*>(this)->LazyPopulate(item);
|
||||
|
||||
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)
|
||||
GetChildSongs(child, urls, songs, song_ids);
|
||||
|
||||
@@ -155,7 +155,7 @@ void ContextItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &o
|
||||
}
|
||||
|
||||
bool ContextItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &index) {
|
||||
|
||||
|
||||
return true;
|
||||
|
||||
Q_UNUSED(option);
|
||||
@@ -326,7 +326,7 @@ void ContextAlbumsView::ReloadSettings() {
|
||||
if (app_ && model_) {
|
||||
model_->set_pretty_covers(settings.value("pretty_covers", true).toBool());
|
||||
}
|
||||
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
}
|
||||
@@ -334,7 +334,7 @@ void ContextAlbumsView::ReloadSettings() {
|
||||
void ContextAlbumsView::SetApplication(Application *app) {
|
||||
|
||||
app_ = app;
|
||||
|
||||
|
||||
model_ = new ContextAlbumsModel(app_->collection_backend(), app_, this);
|
||||
model_->Reset();
|
||||
|
||||
@@ -342,7 +342,7 @@ void ContextAlbumsView::SetApplication(Application *app) {
|
||||
|
||||
connect(model_, SIGNAL(modelAboutToBeReset()), this, SLOT(SaveFocus()));
|
||||
connect(model_, SIGNAL(modelReset()), this, SLOT(RestoreFocus()));
|
||||
|
||||
|
||||
ReloadSettings();
|
||||
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class ContextAlbumsView : public AutoExpandingTreeView {
|
||||
|
||||
// QTreeView
|
||||
void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible);
|
||||
|
||||
|
||||
ContextAlbumsModel *albums_model() { return model_; }
|
||||
|
||||
public slots:
|
||||
@@ -146,9 +146,9 @@ signals:
|
||||
Song last_selected_song_;
|
||||
QString last_selected_container_;
|
||||
QSet<QString> last_selected_path_;
|
||||
|
||||
|
||||
ContextAlbumsModel *model_;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif // CONTEXTALBUMSVIEW_H
|
||||
|
||||
@@ -133,7 +133,7 @@ void ContextView::AddActions() {
|
||||
|
||||
action_show_output_ = new QAction(tr("Show engine and device"), this);
|
||||
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_->setCheckable(true);
|
||||
@@ -141,7 +141,7 @@ void ContextView::AddActions() {
|
||||
|
||||
action_show_lyrics_ = new QAction(tr("Show song lyrics"), this);
|
||||
action_show_lyrics_->setCheckable(true);
|
||||
action_show_lyrics_->setChecked(false);
|
||||
action_show_lyrics_->setChecked(false);
|
||||
|
||||
menu_->addAction(action_show_data_);
|
||||
menu_->addAction(action_show_output_);
|
||||
@@ -512,13 +512,13 @@ void ContextView::UpdateLyrics(quint64 id, const QString lyrics) {
|
||||
|
||||
bool ContextView::eventFilter(QObject *object, QEvent *event) {
|
||||
|
||||
switch(event->type()) {
|
||||
case QEvent::Paint:{
|
||||
switch(event->type()) {
|
||||
case QEvent::Paint:{
|
||||
handlePaintEvent(object, event);
|
||||
}
|
||||
default:{
|
||||
}
|
||||
default:{
|
||||
return QObject::eventFilter(object, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(true);
|
||||
@@ -530,7 +530,7 @@ void ContextView::handlePaintEvent(QObject *object, QEvent *event) {
|
||||
if (object == ui_->label_play_album) {
|
||||
PaintEventAlbum(event);
|
||||
}
|
||||
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
@@ -562,6 +562,7 @@
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
<include location="../../data/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -26,11 +26,13 @@
|
||||
|
||||
#include <QObject>
|
||||
#include <QThread>
|
||||
#include <QVariant>
|
||||
#include <QString>
|
||||
|
||||
#include "core/closure.h"
|
||||
#include "core/lazy.h"
|
||||
#include "core/tagreaderclient.h"
|
||||
#include "core/song.h"
|
||||
|
||||
#include "database.h"
|
||||
#include "taskmanager.h"
|
||||
@@ -58,8 +60,15 @@
|
||||
#include "lyrics/auddlyricsprovider.h"
|
||||
#include "lyrics/apiseedslyricsprovider.h"
|
||||
|
||||
#include "internet/internetmodel.h"
|
||||
#include "tidal/tidalsearch.h"
|
||||
#include "internet/internetservices.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;
|
||||
|
||||
@@ -108,15 +117,30 @@ class ApplicationImpl {
|
||||
return loader;
|
||||
}),
|
||||
current_art_loader_([=]() { return new CurrentArtLoader(app, app); }),
|
||||
internet_model_([=]() { return new InternetModel(app, app); }),
|
||||
tidal_search_([=]() { return new TidalSearch(app, app); }),
|
||||
lyrics_providers_([=]() {
|
||||
LyricsProviders *lyrics_providers = new LyricsProviders(app);
|
||||
lyrics_providers->AddProvider(new AuddLyricsProvider(app));
|
||||
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
|
||||
return lyrics_providers;
|
||||
})
|
||||
{ }
|
||||
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
|
||||
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<Database> database_;
|
||||
@@ -133,9 +157,15 @@ class ApplicationImpl {
|
||||
Lazy<CoverProviders> cover_providers_;
|
||||
Lazy<AlbumCoverLoader> album_cover_loader_;
|
||||
Lazy<CurrentArtLoader> current_art_loader_;
|
||||
Lazy<InternetModel> internet_model_;
|
||||
Lazy<TidalSearch> tidal_search_;
|
||||
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_;
|
||||
|
||||
};
|
||||
|
||||
@@ -181,73 +211,31 @@ void Application::MoveToThread(QObject *object, QThread *thread) {
|
||||
}
|
||||
|
||||
void Application::AddError(const QString& message) { emit ErrorAdded(message); }
|
||||
|
||||
void Application::ReloadSettings() { emit SettingsChanged(); }
|
||||
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { emit SettingsDialogRequested(page); }
|
||||
|
||||
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
|
||||
emit SettingsDialogRequested(page);
|
||||
}
|
||||
|
||||
AlbumCoverLoader *Application::album_cover_loader() const {
|
||||
return p_->album_cover_loader_.get();
|
||||
}
|
||||
|
||||
TagReaderClient *Application::tag_reader_client() const { return p_->tag_reader_client_.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(); }
|
||||
|
||||
#ifndef Q_OS_WIN
|
||||
DeviceManager *Application::device_manager() const {
|
||||
return p_->device_manager_.get();
|
||||
}
|
||||
#endif
|
||||
|
||||
SCollection *Application::collection() const { return p_->collection_.get(); }
|
||||
|
||||
CollectionBackend *Application::collection_backend() const {
|
||||
return collection()->backend();
|
||||
}
|
||||
|
||||
CollectionModel *Application::collection_model() const { return collection()->model(); }
|
||||
|
||||
TaskManager *Application::task_manager() const { return p_->task_manager_.get(); }
|
||||
Player *Application::player() const { return p_->player_.get(); }
|
||||
|
||||
PlaylistBackend *Application::playlist_backend() const {
|
||||
return p_->playlist_backend_.get();
|
||||
}
|
||||
|
||||
PlaylistManager *Application::playlist_manager() const {
|
||||
return p_->playlist_manager_.get();
|
||||
}
|
||||
|
||||
TagReaderClient *Application::tag_reader_client() const {
|
||||
return p_->tag_reader_client_.get();
|
||||
}
|
||||
|
||||
TaskManager *Application::task_manager() const {
|
||||
return p_->task_manager_.get();
|
||||
}
|
||||
|
||||
EngineDevice *Application::enginedevice() const {
|
||||
return p_->enginedevice_.get();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
EngineDevice *Application::enginedevice() const { return p_->enginedevice_.get(); }
|
||||
#ifndef Q_OS_WIN
|
||||
DeviceManager *Application::device_manager() const { return p_->device_manager_.get(); }
|
||||
#endif
|
||||
SCollection *Application::collection() const { return p_->collection_.get(); }
|
||||
CollectionBackend *Application::collection_backend() const { return collection()->backend(); }
|
||||
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(); }
|
||||
CurrentArtLoader *Application::current_art_loader() const { return p_->current_art_loader_.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(); }
|
||||
InternetServices *Application::internet_services() const { return p_->internet_services_.get(); }
|
||||
#ifdef HAVE_STREAM_TIDAL
|
||||
InternetSearch *Application::tidal_search() const { return p_->tidal_search_.get(); }
|
||||
#endif
|
||||
#ifdef HAVE_STREAM_DEEZER
|
||||
InternetSearch *Application::deezer_search() const { return p_->deezer_search_.get(); }
|
||||
#endif
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "settings/settingsdialog.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
class TaskManager;
|
||||
class ApplicationImpl;
|
||||
class TagReaderClient;
|
||||
@@ -51,9 +53,9 @@ class DeviceManager;
|
||||
class CoverProviders;
|
||||
class AlbumCoverLoader;
|
||||
class CurrentArtLoader;
|
||||
class InternetModel;
|
||||
class TidalSearch;
|
||||
class LyricsProviders;
|
||||
class InternetServices;
|
||||
class InternetSearch;
|
||||
|
||||
class Application : public QObject {
|
||||
Q_OBJECT
|
||||
@@ -75,6 +77,8 @@ class Application : public QObject {
|
||||
#endif
|
||||
|
||||
SCollection *collection() const;
|
||||
CollectionBackend *collection_backend() const;
|
||||
CollectionModel *collection_model() const;
|
||||
|
||||
PlaylistBackend *playlist_backend() const;
|
||||
PlaylistManager *playlist_manager() const;
|
||||
@@ -83,14 +87,16 @@ class Application : public QObject {
|
||||
AlbumCoverLoader *album_cover_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;
|
||||
|
||||
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 MoveToThread(QObject *object, QThread *thread);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -62,7 +62,7 @@ Database::Token::Token(const QString &token, int start, int end)
|
||||
: token(token), start_offset(start), end_offset(end) {}
|
||||
|
||||
struct sqlite3_tokenizer_module {
|
||||
|
||||
|
||||
int iVersion;
|
||||
int (*xCreate)(int argc, /* Size of argv array */
|
||||
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) {
|
||||
|
||||
|
||||
UnicodeTokenizer *real_tokenizer = reinterpret_cast<UnicodeTokenizer*>(tokenizer);
|
||||
delete real_tokenizer;
|
||||
return SQLITE_OK;
|
||||
@@ -283,7 +283,11 @@ QSqlDatabase Database::Connect() {
|
||||
QVariant v = db.driver()->handle();
|
||||
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
|
||||
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
|
||||
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));
|
||||
select.exec();
|
||||
if (CheckErrors(select)) return;
|
||||
|
||||
|
||||
while (select.next()) {
|
||||
const int rowid = select.value(0).toInt();
|
||||
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) {
|
||||
|
||||
|
||||
QSqlError last_error = query.lastError();
|
||||
if (last_error.isValid()) {
|
||||
qLog(Error) << "db error: " << last_error;
|
||||
|
||||
@@ -11,7 +11,7 @@ class PlatformInterface;
|
||||
NSMenu* dock_menu_;
|
||||
MacGlobalShortcutBackend* shortcut_handler_;
|
||||
SPMediaKeyTap* key_tap_;
|
||||
|
||||
|
||||
}
|
||||
|
||||
- (id) initWithHandler: (PlatformInterface*)handler;
|
||||
|
||||
@@ -313,7 +313,7 @@ QString GetApplicationSupportPath() {
|
||||
NSString* user_path = [paths objectAtIndex:0];
|
||||
ret = QString::fromUtf8([user_path UTF8String]);
|
||||
} else {
|
||||
ret = "~/Collection/Application Support";
|
||||
ret = "~/Library/Application Support";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "macsystemtrayicon.h"
|
||||
@@ -183,7 +183,7 @@ void MacSystemTrayIcon::SetupMenu(QAction* previous, QAction* play, QAction* sto
|
||||
SetupMenuItem(mute);
|
||||
p_->AddSeparator();
|
||||
Q_UNUSED(quit); // Mac already has a Quit item.
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MacSystemTrayIcon::SetupMenuItem(QAction* action) {
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
#include <QString>
|
||||
#include <QImage>
|
||||
#include <QSettings>
|
||||
#include <QLoggingCategory>
|
||||
#include <QtDebug>
|
||||
#ifdef HAVE_DBUS
|
||||
# include <QDBusArgument>
|
||||
@@ -200,6 +201,11 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
// Resources
|
||||
Q_INIT_RESOURCE(data);
|
||||
Q_INIT_RESOURCE(icons);
|
||||
|
||||
#ifdef DEBUG
|
||||
QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
|
||||
#endif
|
||||
|
||||
Application app;
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QWidget>
|
||||
#include <QSystemTrayIcon>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QByteArray>
|
||||
#include <QDir>
|
||||
@@ -111,8 +112,8 @@
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/playlistsequence.h"
|
||||
#include "playlist/playlistview.h"
|
||||
#include "playlist/queue.h"
|
||||
#include "playlist/queuemanager.h"
|
||||
#include "queue/queue.h"
|
||||
#include "queue/queueview.h"
|
||||
#include "playlistparsers/playlistparser.h"
|
||||
#include "analyzer/analyzercontainer.h"
|
||||
#include "equalizer/equalizer.h"
|
||||
@@ -128,12 +129,20 @@
|
||||
# include "device/deviceviewcontainer.h"
|
||||
#endif
|
||||
#include "transcoder/transcodedialog.h"
|
||||
#include "settings/settingsdialog.h"
|
||||
#include "settings/behavioursettingspage.h"
|
||||
#include "settings/playbacksettingspage.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)
|
||||
# include "musicbrainz/tagfetcher.h"
|
||||
@@ -143,6 +152,10 @@
|
||||
# include "core/macsystemtrayicon.h"
|
||||
#endif
|
||||
|
||||
using std::bind;
|
||||
using std::floor;
|
||||
using std::stable_sort;
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
// Non exported mac-specific function.
|
||||
void qt_mac_set_dock_menu(QMenu*);
|
||||
@@ -152,7 +165,7 @@ const char *MainWindow::kSettingsGroup = "MainWindow";
|
||||
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
||||
|
||||
namespace {
|
||||
const int kTrackSliderUpdateTimeMs = 40;
|
||||
const int kTrackSliderUpdateTimeMs = 200;
|
||||
const int kTrackPositionUpdateTimeMs = 1000;
|
||||
}
|
||||
|
||||
@@ -174,6 +187,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
device_view_(device_view_container_->view()),
|
||||
#endif
|
||||
playlist_list_(new PlaylistListContainer(this)),
|
||||
queue_view_(new QueueView(this)),
|
||||
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
|
||||
cover_manager_([=]() {
|
||||
AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend());
|
||||
@@ -193,12 +207,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
return dialog;
|
||||
}),
|
||||
#endif
|
||||
queue_manager_([=]() {
|
||||
QueueManager *manager = new QueueManager;
|
||||
manager->SetPlaylistManager(app->playlist_manager());
|
||||
return manager;
|
||||
}),
|
||||
tidal_search_view_(new TidalSearchView(app_, this)),
|
||||
#ifdef HAVE_STREAM_TIDAL
|
||||
tidal_search_view_(new InternetSearchView(app_, app_->tidal_search(), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)),
|
||||
#endif
|
||||
#ifdef HAVE_STREAM_DEEZER
|
||||
deezer_search_view_(new InternetSearchView(app_, app_->deezer_search(), DeezerSettingsPage::kSettingsGroup, SettingsDialog::Page_Deezer, this)),
|
||||
#endif
|
||||
playlist_menu_(new QMenu(this)),
|
||||
playlist_add_to_another_(nullptr),
|
||||
playlistitem_actions_separator_(nullptr),
|
||||
@@ -242,24 +256,29 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
ui_->volume->setValue(volume);
|
||||
VolumeChanged(volume);
|
||||
|
||||
// Initialise the tidal search widget
|
||||
// Initialise the search widget
|
||||
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
|
||||
|
||||
// Add tabs to the fancy tab widget
|
||||
ui_->tabs->addTab(context_view_, IconLoader::Load("strawberry"), tr("Context"));
|
||||
ui_->tabs->addTab(collection_view_, IconLoader::Load("vinyl"), tr("Collection"));
|
||||
ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), tr("Files"));
|
||||
ui_->tabs->addTab(playlist_list_, IconLoader::Load("view-media-playlist"), tr("Playlists"));
|
||||
ui_->tabs->addTab(context_view_, IconLoader::Load("strawberry"), "Context");
|
||||
ui_->tabs->addTab(collection_view_, IconLoader::Load("vinyl"), "Collection");
|
||||
ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), "Files");
|
||||
ui_->tabs->addTab(playlist_list_, IconLoader::Load("view-media-playlist"), "Playlists");
|
||||
ui_->tabs->addTab(queue_view_, IconLoader::Load("footsteps"), "Queue");
|
||||
#ifndef Q_OS_WIN
|
||||
ui_->tabs->addTab(device_view_, IconLoader::Load("device"), tr("Devices"));
|
||||
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
|
||||
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), tr("Tidal", "Tidal"));
|
||||
//ui_->tabs->AddSpacer();
|
||||
|
||||
// Add the playing widget to the fancy tab widget
|
||||
ui_->tabs->addBottomWidget(ui_->widget_playing);
|
||||
|
||||
//ui_->tabs->SetBackgroundPixmap(QPixmap(":/pictures/strawberry-background.png"));
|
||||
ui_->tabs->loadSettings(kSettingsGroup);
|
||||
|
||||
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
|
||||
connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition()));
|
||||
@@ -279,7 +298,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
collection_sort_model_->setDynamicSortFilter(true);
|
||||
collection_sort_model_->setSortLocaleAware(true);
|
||||
collection_sort_model_->sort(0);
|
||||
|
||||
|
||||
qLog(Debug) << "Creating models finished";
|
||||
|
||||
connect(ui_->playlist, SIGNAL(ViewSelectionModelChanged()), SLOT(PlaylistViewSelectionModelChanged()));
|
||||
@@ -316,7 +335,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
ui_->action_stop->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_quit->setIcon(IconLoader::Load("application-exit"));
|
||||
ui_->action_quit->setIcon(IconLoader::Load("application-exit"));
|
||||
|
||||
// Playlist
|
||||
|
||||
@@ -338,7 +357,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
// Configure
|
||||
|
||||
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_equalizer->setIcon(IconLoader::Load("equalizer"));
|
||||
ui_->action_update_collection->setIcon(IconLoader::Load("view-refresh"));
|
||||
@@ -391,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_update_collection, SIGNAL(triggered()), app_->collection(), SLOT(IncrementalScan()));
|
||||
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()));
|
||||
|
||||
// Playlist view actions
|
||||
@@ -512,8 +529,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
collection_view_->filter()->AddMenuAction(separator);
|
||||
collection_view_->filter()->AddMenuAction(collection_config_action);
|
||||
|
||||
// Tidal
|
||||
#ifdef HAVE_STREAM_TIDAL
|
||||
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_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
|
||||
@@ -523,6 +544,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
playlist_queue_->setVisible(false);
|
||||
playlist_queue_->setShortcut(QKeySequence("Ctrl+D"));
|
||||
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_->setVisible(false);
|
||||
ui_->playlist->addAction(playlist_skip_);
|
||||
@@ -574,15 +599,16 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
mac::SetApplicationHandler(this);
|
||||
#endif
|
||||
// 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(SeekForward()), app_->player(), SLOT(SeekForward()));
|
||||
connect(tray_icon_, SIGNAL(SeekBackward()), app_->player(), SLOT(SeekBackward()));
|
||||
connect(tray_icon_, SIGNAL(NextTrack()), app_->player(), SLOT(Next()));
|
||||
connect(tray_icon_, SIGNAL(PreviousTrack()), app_->player(), SLOT(Previous()));
|
||||
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
|
||||
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
|
||||
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(SeekForward()), app_->player(), SLOT(SeekForward()));
|
||||
connect(tray_icon_, SIGNAL(SeekBackward()), app_->player(), SLOT(SeekBackward()));
|
||||
connect(tray_icon_, SIGNAL(NextTrack()), app_->player(), SLOT(Next()));
|
||||
connect(tray_icon_, SIGNAL(PreviousTrack()), app_->player(), SLOT(Previous()));
|
||||
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
|
||||
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
|
||||
}
|
||||
|
||||
// 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
|
||||
@@ -615,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(CurrentChanged(int)), SLOT(TabSwitched()));
|
||||
connect(ui_->tabs, SIGNAL(CurrentChanged(int)), SLOT(SaveGeometry()));
|
||||
|
||||
|
||||
// Context
|
||||
connect(app_->playlist_manager(), SIGNAL(CurrentSongChanged(Song)), context_view_, SLOT(SongChanged(Song)));
|
||||
connect(app_->player(), SIGNAL(PlaylistFinished()), context_view_, SLOT(Stopped()));
|
||||
@@ -672,6 +698,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
// Load playlists
|
||||
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.
|
||||
connect(this, SIGNAL(StopAfterToggled(bool)), osd_, SLOT(StopAfterToggle(bool)));
|
||||
|
||||
@@ -698,7 +726,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
|
||||
ui_->tabs->setCurrentIndex(settings_.value("current_tab", 1 /* Collection tab */ ).toInt());
|
||||
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());
|
||||
|
||||
TabSwitched();
|
||||
@@ -708,43 +739,38 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
|
||||
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
|
||||
osd_->ReloadPrettyOSDSettings();
|
||||
|
||||
// Reload playlist settings, for BG and glowing
|
||||
ui_->playlist->view()->ReloadSettings();
|
||||
|
||||
|
||||
#ifndef Q_OS_MACOS
|
||||
#ifdef Q_OS_MACOS // Always show mainwindow on startup if on macos
|
||||
show();
|
||||
#else
|
||||
QSettings settings;
|
||||
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||
StartupBehaviour behaviour = StartupBehaviour(settings.value("startupbehaviour", Startup_Remember).toInt());
|
||||
settings.endGroup();
|
||||
bool hidden = settings_.value("hidden", false).toBool();
|
||||
|
||||
|
||||
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()) {
|
||||
if (hidden && (!QSystemTrayIcon::isSystemTrayAvailable() || !tray_icon_ || !tray_icon_->IsVisible())) {
|
||||
hidden = false;
|
||||
settings_.setValue("hidden", false);
|
||||
show();
|
||||
}
|
||||
#else // Q_OS_MACOS
|
||||
// Always show mainwindow on startup on OS X.
|
||||
show();
|
||||
else {
|
||||
switch (behaviour) {
|
||||
case Startup_AlwaysHide:
|
||||
hide();
|
||||
break;
|
||||
case Startup_AlwaysShow:
|
||||
show();
|
||||
break;
|
||||
case Startup_Remember:
|
||||
setVisible(!hidden);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
QShortcut *close_window_shortcut = new QShortcut(this);
|
||||
@@ -757,9 +783,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
||||
|
||||
if (!options.contains_play_options()) LoadPlaybackStatus();
|
||||
|
||||
qLog(Debug) << "Started";
|
||||
RefreshStyleSheet();
|
||||
|
||||
|
||||
qLog(Debug) << "Started";
|
||||
initialised_ = true;
|
||||
|
||||
}
|
||||
@@ -774,16 +800,14 @@ void MainWindow::ReloadSettings() {
|
||||
QSettings settings;
|
||||
|
||||
#ifndef Q_OS_MACOS
|
||||
|
||||
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||
bool showtrayicon = settings.value("showtrayicon", true).toBool();
|
||||
bool showtrayicon = settings.value("showtrayicon", QSystemTrayIcon::isSystemTrayAvailable()).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
tray_icon_->SetVisible(showtrayicon);
|
||||
if (!showtrayicon && !isVisible()) show();
|
||||
if (tray_icon_) tray_icon_->SetVisible(showtrayicon);
|
||||
if ((!showtrayicon || !QSystemTrayIcon::isSystemTrayAvailable()) && !isVisible()) show();
|
||||
#endif
|
||||
|
||||
settings.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
||||
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||
doubleclick_addmode_ = AddBehaviour(settings.value("doubleclick_addmode", AddBehaviour_Append).toInt());
|
||||
doubleclick_playmode_ = PlayBehaviour(settings.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt());
|
||||
doubleclick_playlist_addmode_ = PlaylistAddBehaviour(settings.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play).toInt());
|
||||
@@ -794,6 +818,26 @@ void MainWindow::ReloadSettings() {
|
||||
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings.value("search_for_cover_auto", true).toBool());
|
||||
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() {
|
||||
@@ -807,13 +851,21 @@ void MainWindow::ReloadAllSettings() {
|
||||
osd_->ReloadSettings();
|
||||
collection_view_->ReloadSettings();
|
||||
ui_->playlist->view()->ReloadSettings();
|
||||
#ifdef HAVE_STREAM_TIDAL
|
||||
tidal_search_view_->ReloadSettings();
|
||||
#endif
|
||||
#ifdef HAVE_STREAM_DEEZER
|
||||
deezer_search_view_->ReloadSettings();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::RefreshStyleSheet() {
|
||||
setStyleSheet(styleSheet());
|
||||
QString contents(styleSheet());
|
||||
setStyleSheet("");
|
||||
setStyleSheet(contents);
|
||||
}
|
||||
|
||||
void MainWindow::MediaStopped() {
|
||||
|
||||
setWindowTitle("Strawberry Music Player");
|
||||
@@ -828,8 +880,10 @@ void MainWindow::MediaStopped() {
|
||||
track_position_timer_->stop();
|
||||
track_slider_timer_->stop();
|
||||
ui_->track_slider->SetStopped();
|
||||
tray_icon_->SetProgress(0);
|
||||
tray_icon_->SetStopped();
|
||||
if (tray_icon_) {
|
||||
tray_icon_->SetProgress(0);
|
||||
tray_icon_->SetStopped();
|
||||
}
|
||||
|
||||
song_playing_ = Song();
|
||||
song_ = Song();
|
||||
@@ -838,7 +892,7 @@ void MainWindow::MediaStopped() {
|
||||
}
|
||||
|
||||
void MainWindow::MediaPaused() {
|
||||
|
||||
|
||||
ui_->action_stop->setEnabled(true);
|
||||
ui_->action_stop_after_this_track->setEnabled(true);
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-play"));
|
||||
@@ -849,7 +903,7 @@ void MainWindow::MediaPaused() {
|
||||
track_position_timer_->stop();
|
||||
track_slider_timer_->stop();
|
||||
|
||||
tray_icon_->SetPaused();
|
||||
if (tray_icon_) tray_icon_->SetPaused();
|
||||
|
||||
}
|
||||
|
||||
@@ -860,13 +914,15 @@ void MainWindow::MediaPlaying() {
|
||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-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);
|
||||
|
||||
bool can_seek = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::SeekDisabled);
|
||||
ui_->track_slider->SetCanSeek(can_seek);
|
||||
|
||||
tray_icon_->SetPlaying(enable_play_pause);
|
||||
if (tray_icon_) tray_icon_->SetPlaying(enable_play_pause);
|
||||
|
||||
track_position_timer_->start();
|
||||
track_slider_timer_->start();
|
||||
@@ -876,7 +932,7 @@ void MainWindow::MediaPlaying() {
|
||||
|
||||
void MainWindow::VolumeChanged(int volume) {
|
||||
ui_->action_mute->setChecked(!volume);
|
||||
tray_icon_->MuteButtonStateChanged(!volume);
|
||||
if (tray_icon_) tray_icon_->MuteButtonStateChanged(!volume);
|
||||
}
|
||||
|
||||
void MainWindow::SongChanged(const Song &song) {
|
||||
@@ -884,11 +940,12 @@ void MainWindow::SongChanged(const Song &song) {
|
||||
song_playing_ = song;
|
||||
song_ = song;
|
||||
setWindowTitle(song.PrettyTitleWithArtist());
|
||||
tray_icon_->SetProgress(0);
|
||||
if (tray_icon_) tray_icon_->SetProgress(0);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
||||
|
||||
// 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) {
|
||||
@@ -905,6 +962,7 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
||||
app_->collection_backend()->IncrementSkipCountAsync(song.id(), percentage);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::changeEvent(QEvent *event) {
|
||||
@@ -913,16 +971,18 @@ void MainWindow::changeEvent(QEvent *event) {
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent *event) {
|
||||
if (!initialised_) return;
|
||||
SaveGeometry();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
}
|
||||
@@ -936,11 +996,12 @@ void MainWindow::SaveGeometry() {
|
||||
settings_.setValue("splitter_state", ui_->splitter->saveState());
|
||||
settings_.setValue("current_tab", ui_->tabs->currentIndex());
|
||||
settings_.setValue("tab_mode", ui_->tabs->mode());
|
||||
ui_->tabs->saveSettings(kSettingsGroup);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::SavePlaybackStatus() {
|
||||
|
||||
|
||||
QSettings settings;
|
||||
|
||||
settings.beginGroup("Player");
|
||||
@@ -951,13 +1012,13 @@ void MainWindow::SavePlaybackStatus() {
|
||||
else {
|
||||
settings.setValue("playback_position", 0);
|
||||
}
|
||||
|
||||
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::LoadPlaybackStatus() {
|
||||
|
||||
|
||||
QSettings settings;
|
||||
|
||||
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||
@@ -970,7 +1031,7 @@ void MainWindow::LoadPlaybackStatus() {
|
||||
saved_playback_state_ = static_cast<Engine::State> (settings.value("playback_state", Engine::Empty).toInt());
|
||||
saved_playback_position_ = settings.value("playback_position", 0).toDouble();
|
||||
settings.endGroup();
|
||||
|
||||
|
||||
if (saved_playback_state_ == Engine::Empty || saved_playback_state_ == Engine::Idle) {
|
||||
return;
|
||||
}
|
||||
@@ -995,7 +1056,7 @@ void MainWindow::ResumePlayback() {
|
||||
}
|
||||
|
||||
void MainWindow::PlayIndex(const QModelIndex &index) {
|
||||
|
||||
|
||||
if (!index.isValid()) return;
|
||||
|
||||
int row = index.row();
|
||||
@@ -1040,7 +1101,7 @@ void MainWindow::VolumeWheelEvent(int delta) {
|
||||
}
|
||||
|
||||
void MainWindow::ToggleShowHide() {
|
||||
|
||||
|
||||
if (settings_.value("hidden").toBool()) {
|
||||
show();
|
||||
SetHiddenInTray(false);
|
||||
@@ -1078,7 +1139,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
||||
bool keep_running = settings.value("keeprunning", false).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
if (keep_running && event->spontaneous()) {
|
||||
if (keep_running && event->spontaneous() && QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
event->ignore();
|
||||
SetHiddenInTray(true);
|
||||
}
|
||||
@@ -1111,30 +1172,28 @@ void MainWindow::Seeked(qlonglong microseconds) {
|
||||
|
||||
const int position = microseconds / kUsecPerSec;
|
||||
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() {
|
||||
|
||||
|
||||
// Track position in seconds
|
||||
//Playlist *playlist = app_->playlist_manager()->active();
|
||||
|
||||
PlaylistItemPtr item(app_->player()->GetCurrentItem());
|
||||
if (!item) return;
|
||||
const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5);
|
||||
const int length = item->Metadata().length_nanosec() / kNsecPerSec;
|
||||
|
||||
if (length <= 0) {
|
||||
// Probably a stream that we don't know the length of
|
||||
//ui_->track_slider->SetStopped();
|
||||
//tray_icon_->SetProgress(0);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update the tray icon every 10 seconds
|
||||
if (position % 10 == 0) {
|
||||
tray_icon_->SetProgress(double(position) / length * 100);
|
||||
}
|
||||
if (position % 10 == 0 && tray_icon_) tray_icon_->SetProgress(double(position) / length * 100);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::UpdateTrackSliderPosition() {
|
||||
@@ -1215,7 +1274,7 @@ void MainWindow::AddToPlaylist(QMimeData *data) {
|
||||
}
|
||||
|
||||
void MainWindow::AddToPlaylist(QAction *action) {
|
||||
|
||||
|
||||
int destination = action->data().toInt();
|
||||
PlaylistItemList items;
|
||||
|
||||
@@ -1287,17 +1346,17 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
int not_in_queue = 0;
|
||||
int in_skipped = 0;
|
||||
int not_in_skipped = 0;
|
||||
|
||||
|
||||
for (const QModelIndex &index : selection) {
|
||||
|
||||
|
||||
all++;
|
||||
|
||||
if (index.column() != 0) continue;
|
||||
|
||||
|
||||
selected++;
|
||||
|
||||
|
||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(index.row());
|
||||
|
||||
|
||||
if (item->Metadata().has_cue()) {
|
||||
cue_selected = true;
|
||||
}
|
||||
@@ -1344,16 +1403,14 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
#endif
|
||||
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) {
|
||||
playlist_queue_->setVisible(false);
|
||||
playlist_queue_play_next_->setVisible(false);
|
||||
playlist_skip_->setVisible(false);
|
||||
}
|
||||
else {
|
||||
playlist_queue_->setVisible(true);
|
||||
playlist_queue_play_next_->setVisible(true);
|
||||
playlist_skip_->setVisible(true);
|
||||
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"));
|
||||
@@ -1361,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 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"));
|
||||
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"));
|
||||
@@ -1380,8 +1442,8 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
ui_->action_edit_value->setVisible(false);
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
|
||||
|
||||
Playlist::Column column = (Playlist::Column)index.column();
|
||||
bool column_is_editable = Playlist::column_is_editable(column) && editable;
|
||||
|
||||
@@ -1471,6 +1533,7 @@ void MainWindow::PlaylistStopAfter() {
|
||||
}
|
||||
|
||||
void MainWindow::EditTracks() {
|
||||
|
||||
SongList songs;
|
||||
PlaylistItemList items;
|
||||
|
||||
@@ -1489,9 +1552,11 @@ void MainWindow::EditTracks() {
|
||||
//EnsureEditTagDialogCreated();
|
||||
edit_tag_dialog_->SetSongs(songs, items);
|
||||
edit_tag_dialog_->show();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::EditTagDialogAccepted() {
|
||||
|
||||
for (PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) {
|
||||
item->Reload();
|
||||
}
|
||||
@@ -1500,14 +1565,16 @@ void MainWindow::EditTagDialogAccepted() {
|
||||
ui_->playlist->view()->update();
|
||||
|
||||
app_->playlist_manager()->current()->Save();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::RenumberTracks() {
|
||||
|
||||
QModelIndexList indexes =ui_->playlist->view()->selectionModel()->selection().indexes();
|
||||
int track = 1;
|
||||
|
||||
// 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 (!indexes.isEmpty()) {
|
||||
@@ -1532,6 +1599,7 @@ void MainWindow::RenumberTracks() {
|
||||
}
|
||||
track++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIndex &index) {
|
||||
@@ -1542,6 +1610,7 @@ void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIn
|
||||
}
|
||||
|
||||
void MainWindow::SelectionSetValue() {
|
||||
|
||||
Playlist::Column column = (Playlist::Column)playlist_menu_index_.column();
|
||||
QVariant column_value =app_->playlist_manager()->current()->data(playlist_menu_index_);
|
||||
|
||||
@@ -1560,9 +1629,11 @@ void MainWindow::SelectionSetValue() {
|
||||
NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::EditValue() {
|
||||
|
||||
QModelIndex current = ui_->playlist->view()->currentIndex();
|
||||
|
||||
if (!current.isValid()) return;
|
||||
@@ -1582,7 +1653,7 @@ void MainWindow::EditValue() {
|
||||
}
|
||||
|
||||
void MainWindow::AddFile() {
|
||||
|
||||
|
||||
// Last used directory
|
||||
QString directory =settings_.value("add_media_path", QDir::currentPath()).toString();
|
||||
|
||||
@@ -1605,9 +1676,11 @@ void MainWindow::AddFile() {
|
||||
MimeData *data = new MimeData;
|
||||
data->setUrls(urls);
|
||||
AddToPlaylist(data);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::AddFolder() {
|
||||
|
||||
// Last used directory
|
||||
QString directory =settings_.value("add_folder_path", QDir::currentPath()).toString();
|
||||
|
||||
@@ -1622,6 +1695,7 @@ void MainWindow::AddFolder() {
|
||||
MimeData *data = new MimeData;
|
||||
data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath()));
|
||||
AddToPlaylist(data);
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::AddCDTracks() {
|
||||
@@ -1974,6 +2048,15 @@ void MainWindow::PlaylistQueue() {
|
||||
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() {
|
||||
|
||||
QModelIndexList indexes;
|
||||
@@ -2050,7 +2133,7 @@ SettingsDialog *MainWindow::CreateSettingsDialog() {
|
||||
}
|
||||
|
||||
void MainWindow::EnsureSettingsDialogCreated() {
|
||||
|
||||
|
||||
//if (settings_dialog_) return;
|
||||
|
||||
//settings_dialog_.reset(new SettingsDialog(app_));
|
||||
@@ -2062,14 +2145,14 @@ void MainWindow::EnsureSettingsDialogCreated() {
|
||||
|
||||
// Allows custom notification preview
|
||||
//connect(settings_dialog_.get(), SIGNAL(NotificationPreview(OSD::Behaviour,QString,QString)), SLOT(HandleNotificationPreview(OSD::Behaviour, QString, QString)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::OpenSettingsDialog() {
|
||||
|
||||
EnsureSettingsDialogCreated();
|
||||
settings_dialog_->show();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
|
||||
@@ -2125,7 +2208,7 @@ void MainWindow::ShowErrorDialog(const QString &message) {
|
||||
}
|
||||
|
||||
void MainWindow::CheckFullRescanRevisions() {
|
||||
|
||||
|
||||
int from = app_->database()->startup_schema_version();
|
||||
int to = app_->database()->current_schema_version();
|
||||
|
||||
@@ -2152,22 +2235,14 @@ void MainWindow::CheckFullRescanRevisions() {
|
||||
}
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::ShowQueueManager() {
|
||||
//if (!queue_manager_) {
|
||||
//queue_manager_.reset(new QueueManager);
|
||||
//queue_manager_->SetPlaylistManager(app_->playlist_manager());
|
||||
//}
|
||||
queue_manager_->show();
|
||||
}
|
||||
|
||||
void MainWindow::PlaylistViewSelectionModelChanged() {
|
||||
|
||||
|
||||
connect(ui_->playlist->view()->selectionModel(),SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(PlaylistCurrentChanged(QModelIndex)));
|
||||
}
|
||||
|
||||
@@ -2193,8 +2268,8 @@ bool MainWindow::winEvent(MSG *msg, long*) {
|
||||
|
||||
void MainWindow::Exit() {
|
||||
|
||||
SaveGeometry();
|
||||
SavePlaybackStatus();
|
||||
//settings_.setValue("show_sidebar", ui_->action_toggle_show_sidebar->isChecked());
|
||||
|
||||
if (app_->player()->engine()->is_fadeout_enabled()) {
|
||||
// To shut down the application when fadeout will be finished
|
||||
@@ -2202,7 +2277,7 @@ void MainWindow::Exit() {
|
||||
if (app_->player()->GetState() == Engine::Playing) {
|
||||
app_->player()->Stop();
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -2249,7 +2324,7 @@ void MainWindow::AutoCompleteTags() {
|
||||
}
|
||||
|
||||
void MainWindow::AutoCompleteTagsAccepted() {
|
||||
|
||||
|
||||
for (PlaylistItemPtr item : autocomplete_tag_items_) {
|
||||
item->Reload();
|
||||
}
|
||||
@@ -2309,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() {
|
||||
album_cover_choice_controller_->LoadCoverFromFile(&song_);
|
||||
}
|
||||
@@ -2387,7 +2429,7 @@ void MainWindow::AlbumArtLoaded(const Song &song, const QString&, const QImage &
|
||||
}
|
||||
|
||||
void MainWindow::GetCoverAutomatically() {
|
||||
|
||||
|
||||
// Search for cover automatically?
|
||||
bool search =
|
||||
album_cover_choice_controller_->search_cover_auto_action()->isChecked() &&
|
||||
@@ -2400,4 +2442,3 @@ void MainWindow::GetCoverAutomatically() {
|
||||
if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@
|
||||
#include "playlist/playlistitem.h"
|
||||
#include "settings/settingsdialog.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
class About;
|
||||
class AlbumCoverManager;;
|
||||
class Application;
|
||||
@@ -76,7 +78,7 @@ class GlobalShortcuts;
|
||||
class MimeData;
|
||||
class OrganiseDialog;
|
||||
class PlaylistListContainer;
|
||||
class QueueManager;
|
||||
class QueueView;
|
||||
class Song;
|
||||
class SystemTrayIcon;
|
||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||
@@ -88,7 +90,7 @@ class TranscodeDialog;
|
||||
#endif
|
||||
class Ui_MainWindow;
|
||||
class Windows7ThumbBar;
|
||||
class TidalSearchView;
|
||||
class InternetSearchView;
|
||||
|
||||
class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
Q_OBJECT
|
||||
@@ -166,6 +168,7 @@ signals:
|
||||
void PlaylistPlay();
|
||||
void PlaylistStopAfter();
|
||||
void PlaylistQueue();
|
||||
void PlaylistQueuePlayNext();
|
||||
void PlaylistSkip();
|
||||
void PlaylistRemoveCurrent();
|
||||
void PlaylistEditFinished(const QModelIndex& index);
|
||||
@@ -250,7 +253,6 @@ signals:
|
||||
void ShowTranscodeDialog();
|
||||
#endif
|
||||
void ShowErrorDialog(const QString& message);
|
||||
void ShowQueueManager();
|
||||
void EnsureSettingsDialogCreated();
|
||||
void EnsureEditTagDialogCreated();
|
||||
SettingsDialog *CreateSettingsDialog();
|
||||
@@ -273,11 +275,6 @@ signals:
|
||||
|
||||
void ShowConsole();
|
||||
|
||||
void FocusTidalSearchField();
|
||||
void DoTidalSearch(const QString& query);
|
||||
void SearchForArtist();
|
||||
void SearchForAlbum();
|
||||
|
||||
void LoadCoverFromFile();
|
||||
void SaveCoverToFile();
|
||||
void LoadCoverFromURL();
|
||||
@@ -296,7 +293,7 @@ signals:
|
||||
|
||||
// creates the icon by painting the full one depending on the current position
|
||||
QPixmap CreateOverlayedIcon(int position, int scrobble_point);
|
||||
|
||||
|
||||
void GetCoverAutomatically();
|
||||
|
||||
private:
|
||||
@@ -320,6 +317,7 @@ signals:
|
||||
DeviceView *device_view_;
|
||||
#endif
|
||||
PlaylistListContainer *playlist_list_;
|
||||
QueueView *queue_view_;
|
||||
|
||||
Lazy<SettingsDialog> settings_dialog_;
|
||||
Lazy<AlbumCoverManager> cover_manager_;
|
||||
@@ -331,7 +329,6 @@ signals:
|
||||
#ifdef HAVE_GSTREAMER
|
||||
Lazy<OrganiseDialog> organise_dialog_;
|
||||
#endif
|
||||
Lazy<QueueManager> queue_manager_;
|
||||
|
||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||
std::unique_ptr<TagFetcher> tag_fetcher_;
|
||||
@@ -341,7 +338,8 @@ signals:
|
||||
PlaylistItemList autocomplete_tag_items_;
|
||||
#endif
|
||||
|
||||
TidalSearchView *tidal_search_view_;
|
||||
InternetSearchView *tidal_search_view_;
|
||||
InternetSearchView *deezer_search_view_;
|
||||
|
||||
QAction *collection_show_all_;
|
||||
QAction *collection_show_duplicates_;
|
||||
@@ -363,6 +361,7 @@ signals:
|
||||
#endif
|
||||
QAction *playlist_open_in_browser_;
|
||||
QAction *playlist_queue_;
|
||||
QAction* playlist_queue_play_next_;
|
||||
QAction *playlist_skip_;
|
||||
QAction *playlist_add_to_another_;
|
||||
QList<QAction*> playlistitem_actions_;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<string>Strawberry Music Player</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<iconset resource="../../data/icons.qrc">
|
||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
@@ -435,7 +435,6 @@
|
||||
<string>&Tools</string>
|
||||
</property>
|
||||
<addaction name="action_cover_manager"/>
|
||||
<addaction name="action_queue_manager"/>
|
||||
<addaction name="action_equalizer"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_update_collection"/>
|
||||
@@ -553,7 +552,7 @@
|
||||
</action>
|
||||
<action name="action_about_strawberry">
|
||||
<property name="icon">
|
||||
<iconset resource="../../data/data.qrc">
|
||||
<iconset resource="../../data/icons.qrc">
|
||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
@@ -674,11 +673,6 @@
|
||||
<string>&Update changed collection folders</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_queue_manager">
|
||||
<property name="text">
|
||||
<string>&Queue Manager</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_about_qt">
|
||||
<property name="text">
|
||||
<string>About &Qt</string>
|
||||
@@ -782,6 +776,7 @@
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="../../data/data.qrc"/>
|
||||
<include location="../../data/icons.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
|
||||
@@ -453,7 +453,7 @@ bool MergedProxyModel::dropMimeData(const QMimeData *data, Qt::DropAction action
|
||||
}
|
||||
|
||||
QModelIndex MergedProxyModel::FindSourceParent(const QModelIndex &proxy_index) const {
|
||||
|
||||
|
||||
if (!proxy_index.isValid()) return QModelIndex();
|
||||
|
||||
QModelIndex source_index = mapToSource(proxy_index);
|
||||
@@ -463,7 +463,7 @@ QModelIndex MergedProxyModel::FindSourceParent(const QModelIndex &proxy_index) c
|
||||
}
|
||||
|
||||
bool MergedProxyModel::canFetchMore(const QModelIndex &parent) const {
|
||||
|
||||
|
||||
QModelIndex source_index = mapToSource(parent);
|
||||
|
||||
if (!source_index.isValid())
|
||||
@@ -473,7 +473,7 @@ bool MergedProxyModel::canFetchMore(const QModelIndex &parent) const {
|
||||
}
|
||||
|
||||
void MergedProxyModel::fetchMore(const QModelIndex &parent) {
|
||||
|
||||
|
||||
QModelIndex source_index = mapToSource(parent);
|
||||
|
||||
if (!source_index.isValid())
|
||||
|
||||