Compare commits

...

99 Commits

Author SHA1 Message Date
Jonas Kvinge
6d8725f268 Release 0.6.10 2020-05-01 16:42:20 +02:00
Jonas Kvinge
373c7cdbc4 Update Changelog 2020-05-01 16:40:54 +02:00
Jonas Kvinge
a4855bb33b Decrease margin for top title in context a little 2020-05-01 16:40:29 +02:00
Jonas Kvinge
57c1358ded Ignore replies not containing images from Discogs 2020-05-01 12:02:15 +02:00
Jonas Kvinge
eb4ce1feab Use toUtf8() not toLocal8Bit() when converting string for UNC path
Fixes #418
2020-04-30 17:32:31 +02:00
Strawbs Bot
838c17e144 Update translations 2020-04-30 01:03:38 +02:00
Strawbs Bot
4499cbca3c Update translations 2020-04-29 01:08:07 +02:00
Jonas Kvinge
a835a4a2f7 Minor fixes to collection pixmap cache
- Add variables for cache size defaults
- Increase default disk cache size
- Change the pixmap cache settings UI to look better
- Add current pixmap disk cache used to settings
2020-04-29 00:33:38 +02:00
Jonas Kvinge
9cc6a94353 Replace some NewClosure's with lambda connects 2020-04-28 22:29:10 +02:00
Jonas Kvinge
5ed9d9c4a0 Update Changelog 2020-04-28 22:28:45 +02:00
Jonas Kvinge
9c5ac7080d Remove unused connect 2020-04-28 22:28:24 +02:00
Jonas Kvinge
6346370e86 Set some properties on font size spinboxes 2020-04-28 20:56:35 +02:00
Jonas Kvinge
80697f8f30 Add toolchain files to cmake dir 2020-04-28 16:24:40 +02:00
Jonas Kvinge
18b8b56367 Use leap 15.1 for source build 2020-04-28 16:23:27 +02:00
Jonas Kvinge
760aacca26 Make context fonts configurable
Fixes #362
2020-04-28 01:11:00 +02:00
Strawbs Bot
1a4f0dcf5a Update translations 2020-04-28 01:02:50 +02:00
Jonas Kvinge
947484a71c Set content margin for label top in context 2020-04-27 22:20:50 +02:00
Jonas Kvinge
a74439d038 Always load 32x32 icon for engine and device
Fixes #417
2020-04-27 21:36:49 +02:00
Jonas Kvinge
c338618593 Do size checking of icon sizes when loading system theme icons 2020-04-27 21:36:08 +02:00
Jonas Kvinge
011897da53 Remove gstreamer registry file on startup for Windows
Workaround for issue #266
2020-04-27 15:54:37 +02:00
Jonas Kvinge
3fcaa58947 Add back libtag.dll (required for GStreamer plugin) 2020-04-27 15:52:38 +02:00
Strawbs Bot
ef8bd4362a Update translations 2020-04-27 01:03:05 +02:00
Jonas Kvinge
627a2ef6dd Dont use system icon for clear search field icon
Fixes #413
2020-04-27 00:24:49 +02:00
Jonas Kvinge
2732536d6e Fix device state text color in devices
Fixes #414
2020-04-27 00:22:46 +02:00
Jonas Kvinge
5a1b4b3ff8 Remove logging include 2020-04-26 18:49:18 +02:00
Jonas Kvinge
d93ec82e4f Fix save album cover to file
Fixes #412
2020-04-26 18:48:07 +02:00
Jonas Kvinge
15080972f3 Turn off uniformItemSizes
Fixes #411
2020-04-26 18:32:42 +02:00
Strawbs Bot
171b58f737 Update translations 2020-04-26 01:09:51 +02:00
Jonas Kvinge
c008ab6141 Fix resume playback on startup for CUE 2020-04-25 15:57:02 +02:00
Jonas Kvinge
f14c3654dc Add search for lyrics as a seperate option
Double click album to show fullsize

Fixes #299
2020-04-25 14:48:43 +02:00
Jonas Kvinge
ae05a61551 Read date and genre from individual tracks in cue sheets
Fixes #347
2020-04-25 13:47:25 +02:00
Jonas Kvinge
8e1def225b Move some files 2020-04-25 01:59:21 +02:00
Jonas Kvinge
6e061764ee Remove phonon 2020-04-25 01:42:29 +02:00
Jonas Kvinge
ac55b22839 Fix scrobble duration 2020-04-25 01:15:23 +02:00
Jonas Kvinge
49f77d3b75 Change timeouts 2020-04-25 00:13:48 +02:00
Jonas Kvinge
4abc650edf Make scrobbler handle streams 2020-04-25 00:07:42 +02:00
Jonas Kvinge
5ba00b61be Remove unneeded includes 2020-04-25 00:07:18 +02:00
Jonas Kvinge
bc16a6c4cb Sort album cover search results by score and pick the first 3 2020-04-25 00:03:43 +02:00
Jonas Kvinge
ea4dc6f040 Add link directories 2020-04-24 19:48:57 +02:00
Strawbs Bot
749ae8d5eb Update translations 2020-04-24 01:10:40 +02:00
Jonas Kvinge
7a56ffb7c3 Use COMPILE_LANGUAGE when setting compile options 2020-04-24 00:01:59 +02:00
Jonas Kvinge
e62ab23de2 Add taglib includes 2020-04-24 00:01:23 +02:00
Jonas Kvinge
c6f6118506 Use system taglib on macOS 2020-04-24 00:00:07 +02:00
Jonas Kvinge
8a5d5ad952 Fix some compile warnings in taglib 2020-04-23 21:51:14 +02:00
Jonas Kvinge
49e2615d14 Fix missing declaration 2020-04-23 21:50:50 +02:00
Jonas Kvinge
9289394261 Remove some compile options 2020-04-23 21:50:25 +02:00
Jonas Kvinge
8da4c88fd3 Fix compile warnings 2020-04-23 21:08:28 +02:00
Jonas Kvinge
a303850341 Use initialization list in cueparser 2020-04-23 21:07:17 +02:00
Jonas Kvinge
fb33610672 Remove unneeded this 2020-04-23 21:06:54 +02:00
Jonas Kvinge
d024dd6563 Minor code fixes to Subsonic 2020-04-23 21:06:26 +02:00
Jonas Kvinge
0be48f9f59 Minor code fixes to Tidal 2020-04-23 21:05:57 +02:00
Jonas Kvinge
df9292bafe Remove unneeded this 2020-04-23 21:05:17 +02:00
Jonas Kvinge
c1dcef3477 Improve Musicbrainz cover provider 2020-04-23 21:04:37 +02:00
Jonas Kvinge
48bc1f8361 Improve Last.fm cover provider code 2020-04-23 21:03:36 +02:00
Jonas Kvinge
2b2b4dbcf4 Improve Discogs cover provider 2020-04-23 21:02:48 +02:00
Jonas Kvinge
a1eadecdef Fix compile warnings in tests 2020-04-23 21:01:34 +02:00
Jonas Kvinge
f0b529952d Fix some compile warnings in singleapplication 2020-04-23 21:00:43 +02:00
Jonas Kvinge
c1ac2debb8 Fix some compile warnings in taglib 2020-04-23 21:00:16 +02:00
Jonas Kvinge
ac40094d37 Update CMakeLists.txt files 2020-04-23 20:59:09 +02:00
Jonas Kvinge
cb2bb4cb67 Fix CI 2020-04-22 15:38:10 +02:00
Strawbs Bot
f2965940cc Update translations 2020-04-22 01:01:32 +02:00
Strawbs Bot
c9ca147898 Update translations 2020-04-21 01:08:13 +02:00
Jonas Kvinge
c379d7f846 Minor code improvements to Deezer cover provider 2020-04-20 23:52:06 +02:00
Jonas Kvinge
45ae1ed265 Make Tidal album cover provider search for tracks too 2020-04-20 23:26:36 +02:00
Jonas Kvinge
9bf00eff40 Minor changes to Qobuz cover provider (and fix compile) 2020-04-20 22:58:57 +02:00
Jonas Kvinge
1677b3d5b9 Add Qobuz album cover provider 2020-04-20 22:12:40 +02:00
Jonas Kvinge
2a6806004a Fix update song length in context 2020-04-20 18:52:59 +02:00
Jonas Kvinge
39347d69df Only show song length in context when available 2020-04-20 18:46:26 +02:00
Jonas Kvinge
a2c0e4d4b1 Improve album cover loader, lyrics search and streaming support
- Improve album cover loader
- Add album cover loader result struct
- Move album cover thumbnail scaling to album cover loader
- Make init art manual look for album cover images in song directory
- Make album cover search work for songs outside of collection and
  streams
- Make album cover search work based on artist + title if album is not
  present
- Update art manual in playlist for local files, devices and CDDA
- Make lyrics search work for streams
- Add stream dialog to menu
- Remove dead code in InternetSearchModel
- Simplify code in InternetSearchView
2020-04-20 18:03:18 +02:00
Jonas Kvinge
ab2ffd9ac1 Add configure internet service to menu 2020-04-20 18:01:45 +02:00
Jonas Kvinge
c69fff52cc Remove useless using std 2020-04-20 17:49:06 +02:00
Strawbs Bot
1cfe61dc72 Update translations 2020-04-20 01:01:39 +02:00
Strawbs Bot
a23f39d81e Update translations 2020-04-19 01:01:32 +02:00
Strawbs Bot
b7724ff583 Update translations 2020-04-18 01:01:40 +02:00
Jonas Kvinge
e5dba60fab Remove song_id and artist_id from initialization list 2020-04-17 22:17:57 +02:00
Jonas Kvinge
2ccf489a83 Remove debug line 2020-04-17 17:23:43 +02:00
Jonas Kvinge
068939ca0b Fallback to SHA1 hash for cover filename if artist / album is stripped 2020-04-17 17:22:50 +02:00
Strawbs Bot
94ba8614ec Update translations 2020-04-16 01:01:39 +02:00
Strawbs Bot
f12a0c2379 Update translations 2020-04-15 01:01:28 +02:00
Strawbs Bot
8ab257645b Update translations 2020-04-14 01:11:19 +02:00
Jonas Kvinge
6331a0615f Update device schema 2020-04-13 23:24:35 +02:00
Jonas Kvinge
a21855fa20 Merge pull request #406 from strawberrymusicplayer/tidal
Add back Tidal support
2020-04-13 22:37:41 +02:00
Jonas Kvinge
12150c2180 Change database file 2020-04-13 19:05:55 +02:00
Jonas Kvinge
d90aecb164 Add back Tidal support 2020-04-13 19:04:06 +02:00
Jonas Kvinge
e738f2bc9f Recreate indexes and views in upgrade schema 11 2020-04-13 16:32:31 +02:00
Jonas Kvinge
2f72c41cda Improve internet classes 2020-04-13 06:30:40 +02:00
Jonas Kvinge
aa43d42cdb Remove const from signal slot connects 2020-04-13 05:57:48 +02:00
Jonas Kvinge
be8228e33c Fix song_id check 2020-04-13 04:17:45 +02:00
Jonas Kvinge
5591472dbd Change artist and song ID to strings 2020-04-13 03:39:51 +02:00
Strawbs Bot
30e6ced4e9 Update translations 2020-04-13 01:01:36 +02:00
Strawbs Bot
5f4c2bae89 Update translations 2020-04-12 01:01:28 +02:00
Strawbs Bot
0f036d9a43 Update translations 2020-04-11 01:01:39 +02:00
Strawbs Bot
1695ac3a32 Update translations 2020-04-10 01:02:01 +02:00
Jonas Kvinge
07a19ba619 Use slash 2020-04-09 20:41:14 +02:00
Jonas Kvinge
4dd78d89a0 Add option to remove problematic filename characters 2020-04-09 19:59:31 +02:00
Jonas Kvinge
8f4056faa6 Allow all characters except slash and backslash when organising music
Fixes #404
2020-04-09 18:14:02 +02:00
Jonas Kvinge
7b40c33892 Add missing semicolon in desktop file 2020-04-09 16:02:06 +02:00
Jonas Kvinge
b06bb5142f Turn on git revision 2020-04-09 16:01:12 +02:00
Jonas Kvinge
d576156ee1 Update snap version 2020-04-09 03:41:08 +02:00
302 changed files with 17139 additions and 8607 deletions

View File

@@ -35,7 +35,7 @@ commands:
working_directory: build
- run:
name: Build RPM
command: rpmbuild -ba ../dist/rpm/strawberry.spec
command: rpmbuild -ba ../dist/unix/strawberry.spec
working_directory: build
@@ -59,14 +59,12 @@ commands:
zypper --non-interactive --gpg-auto-import-keys install
lsb-release
rpm-build
rpmdevtools
git
tar
make
cmake
gcc
gcc-c++
pkg-config
gettext-tools
glibc-devel
libboost_headers-devel
@@ -84,7 +82,6 @@ commands:
gstreamer-plugins-base-devel
libxine-devel
vlc-devel
taglib-devel
libQt5Core-devel
libQt5Gui-devel
libQt5Widgets-devel
@@ -333,7 +330,7 @@ jobs:
build_source:
docker:
- image: opensuse/tumbleweed
- image: opensuse/leap:15.1
steps:
- install_opensuse_dependencies
- checkout
@@ -347,6 +344,12 @@ jobs:
environment:
RPM_BUILD_NCPUS: "2"
steps:
- run:
name: Update packages
command: zypper --non-interactive --gpg-auto-import-keys ref
- run:
name: Upgrade packages
command: zypper --non-interactive --gpg-auto-import-keys dup
- install_opensuse_dependencies
- checkout
- cmake

View File

@@ -6,13 +6,13 @@ jobs:
build-linux:
runs-on: ubuntu-latest
container:
image: opensuse/tumbleweed
image: opensuse/leap:15.1
steps:
- uses: actions/checkout@v1
- name: Update Packages
run: zypper ref
- name: Install Packages
run: zypper --non-interactive --gpg-auto-import-keys install lsb-release rpm-build rpmdevtools git tar make cmake gcc gcc-c++ pkg-config gettext-tools glibc-devel libboost_headers-devel boost-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libnotify-devel libgnutls-devel protobuf-devel sqlite3-devel libpulse-devel gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel taglib-devel libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel libQt5DBus-devel libQt5Test-devel libqt5-qtx11extras-devel libqt5-qtbase-common-devel libQt5Sql5-sqlite libqt5-linguist-devel libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files appstream-glib hicolor-icon-theme
run: zypper --non-interactive --gpg-auto-import-keys install lsb-release rpm-build git tar make cmake gcc gcc-c++ gettext-tools glibc-devel libboost_headers-devel boost-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libnotify-devel libgnutls-devel protobuf-devel sqlite3-devel libpulse-devel gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel taglib-devel libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel libQt5DBus-devel libQt5Test-devel libqt5-qtx11extras-devel libqt5-qtbase-common-devel libQt5Sql5-sqlite libqt5-linguist-devel libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files appstream-glib hicolor-icon-theme
- name: Create Build Environment
run: mkdir -p build
- name: Configure CMake
@@ -31,7 +31,7 @@ jobs:
- name: Unlink python
run: brew unlink python@2
- name: Install Packages
run: brew install glib pkgconfig boost libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav libcdio libmtp libimobiledevice libplist create-dmg
run: brew install glib pkgconfig boost libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav libcdio libmtp libimobiledevice libplist create-dmg taglib
- name: Create Build Environment
run: cmake -E make_directory ${{runner.workspace}}/build
- name: Configure CMake
@@ -40,7 +40,7 @@ jobs:
Qt5LinguistTools_DIR: /usr/local/opt/qt5/lib/cmake/Qt5LinguistTools
working-directory: ${{runner.workspace}}/build
shell: bash
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_BUNDLE=ON
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_BUNDLE=ON -DUSE_SYSTEM_TAGLIB=ON
- name: Build
working-directory: ${{runner.workspace}}/build
shell: bash

View File

@@ -21,7 +21,7 @@ before_install:
git fetch --unshallow || travis_terminate 1;
git pull || travis_terminate 1;
brew unlink python@2 || travis_terminate 1;
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint zlib;
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint zlib taglib;
brew install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav;
brew install libcdio libmtp libimobiledevice libplist;
brew install create-dmg;
@@ -33,7 +33,7 @@ before_install:
fi
before_script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DUSE_SYSTEM_TAGLIB=ON ; fi
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then

View File

@@ -1,16 +1,8 @@
cmake_minimum_required(VERSION 2.8.11)
cmake_minimum_required(VERSION 3.0)
include(CheckIncludeFiles)
include(CheckFunctionExists)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
endif()
if(CMAKE_VERSION VERSION_GREATER 3.0)
check_function_exists(geteuid HAVE_GETEUID)
check_function_exists(getpwuid HAVE_GETPWUID)
@@ -19,14 +11,15 @@ endif()
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)
QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
ADD_LIBRARY(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
add_library(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
target_link_libraries(singleapplication Qt5::Core Qt5::Widgets Qt5::Network)
set(SINGLECOREAPP-SOURCES singlecoreapplication.cpp singlecoreapplication_p.cpp)
set(SINGLECOREAPP-MOC-HEADERS singlecoreapplication.h singlecoreapplication_p.h)
QT5_WRAP_CPP(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
ADD_LIBRARY(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
add_library(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
target_link_libraries(singlecoreapplication Qt5::Core Qt5::Widgets Qt5::Network)
configure_file(config.h.in "${CMAKE_CURRENT_BINARY_DIR}/config.h")
include_directories(${CMAKE_CURRENT_BINARY_DIR})

View File

@@ -61,8 +61,8 @@
# include <lmcons.h>
#endif
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication *q_ptr)
: q_ptr(q_ptr),
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication *_q_ptr)
: q_ptr(_q_ptr),
memory(nullptr),
socket(nullptr),
server(nullptr),
@@ -186,7 +186,7 @@ void SingleApplicationPrivate::startPrimary() {
void SingleApplicationPrivate::startSecondary() {}
void SingleApplicationPrivate::connectToPrimary(int msecs, ConnectionType connectionType) {
void SingleApplicationPrivate::connectToPrimary(const int msecs, const ConnectionType connectionType) {
// Connect to the Local Server of the Primary Instance if not already connected.
if (socket == nullptr) {
@@ -386,14 +386,14 @@ void SingleApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
}
void SingleApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, quint32 instanceId) {
void SingleApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const quint32 instanceId) {
Q_Q(SingleApplication);
Q_EMIT q->receivedMessage(instanceId, dataSocket->readAll());
}
void SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, quint32 instanceId) {
void SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
if (closedSocket->bytesAvailable() > 0)
Q_EMIT slotDataAvailable(closedSocket, instanceId);

View File

@@ -74,14 +74,14 @@ class SingleApplicationPrivate : public QObject {
};
Q_DECLARE_PUBLIC(SingleApplication)
SingleApplicationPrivate( SingleApplication *q_ptr );
SingleApplicationPrivate(SingleApplication *_q_ptr);
~SingleApplicationPrivate();
void genBlockServerName();
void initializeMemoryBlock();
void startPrimary();
void startSecondary();
void connectToPrimary(int msecs, ConnectionType connectionType );
void connectToPrimary(const int msecs, const ConnectionType connectionType);
quint16 blockChecksum();
qint64 primaryPid();
void readInitMessageHeader(QLocalSocket *socket);
@@ -98,8 +98,8 @@ class SingleApplicationPrivate : public QObject {
public slots:
void slotConnectionEstablished();
void slotDataAvailable(QLocalSocket*, quint32);
void slotClientConnectionClosed(QLocalSocket*, quint32);
void slotDataAvailable(QLocalSocket*, const quint32);
void slotClientConnectionClosed(QLocalSocket*, const quint32);
};
#endif // SINGLEAPPLICATION_P_H

View File

@@ -61,8 +61,8 @@
# include <lmcons.h>
#endif
SingleCoreApplicationPrivate::SingleCoreApplicationPrivate(SingleCoreApplication *q_ptr)
: q_ptr(q_ptr),
SingleCoreApplicationPrivate::SingleCoreApplicationPrivate(SingleCoreApplication *_q_ptr)
: q_ptr(_q_ptr),
memory(nullptr),
socket(nullptr),
server(nullptr),
@@ -186,7 +186,7 @@ void SingleCoreApplicationPrivate::startPrimary() {
void SingleCoreApplicationPrivate::startSecondary() {}
void SingleCoreApplicationPrivate::connectToPrimary(int msecs, ConnectionType connectionType) {
void SingleCoreApplicationPrivate::connectToPrimary(const int msecs, const ConnectionType connectionType) {
// Connect to the Local Server of the Primary Instance if not already connected.
if (socket == nullptr) {
@@ -386,14 +386,14 @@ void SingleCoreApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
}
void SingleCoreApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, quint32 instanceId) {
void SingleCoreApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const quint32 instanceId) {
Q_Q(SingleCoreApplication);
Q_EMIT q->receivedMessage(instanceId, dataSocket->readAll());
}
void SingleCoreApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, quint32 instanceId) {
void SingleCoreApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
if (closedSocket->bytesAvailable() > 0)
Q_EMIT slotDataAvailable(closedSocket, instanceId);

View File

@@ -74,14 +74,14 @@ class SingleCoreApplicationPrivate : public QObject {
};
Q_DECLARE_PUBLIC(SingleCoreApplication)
SingleCoreApplicationPrivate( SingleCoreApplication *q_ptr );
SingleCoreApplicationPrivate(SingleCoreApplication *_q_ptr);
~SingleCoreApplicationPrivate();
void genBlockServerName();
void initializeMemoryBlock();
void startPrimary();
void startSecondary();
void connectToPrimary(int msecs, ConnectionType connectionType );
void connectToPrimary(const int msecs, const ConnectionType connectionType);
quint16 blockChecksum();
qint64 primaryPid();
void readInitMessageHeader(QLocalSocket *socket);
@@ -98,8 +98,8 @@ class SingleCoreApplicationPrivate : public QObject {
public slots:
void slotConnectionEstablished();
void slotDataAvailable(QLocalSocket*, quint32);
void slotClientConnectionClosed(QLocalSocket*, quint32);
void slotDataAvailable(QLocalSocket*, const quint32);
void slotClientConnectionClosed(QLocalSocket*, const quint32);
};
#endif // SINGLECOREAPPLICATION_P_H

View File

@@ -1,8 +1,4 @@
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -fpermissive -Wall -Woverloaded-virtual -Wno-sign-compare -Wno-delete-non-virtual-dtor")
cmake_minimum_required(VERSION 3.0)
set(TAGLIB_SOVERSION_CURRENT 17)
set(TAGLIB_SOVERSION_REVISION 0)

View File

@@ -87,7 +87,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool APE::File::isSupported(IOStream *stream)
bool APE::File::isSupported(IOStream*)
{
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.

View File

@@ -264,6 +264,7 @@ int ASF::Attribute::dataSize() const
case BytesType:
if(d->pictureValue.isValid())
return d->pictureValue.dataSize();
break;
case GuidType:
return d->byteVectorValue.size();
}
@@ -305,6 +306,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
data.append(d->pictureValue.render());
break;
}
break;
case GuidType:
data.append(d->byteVectorValue);
break;

View File

@@ -51,7 +51,7 @@ namespace
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
{
for(int i = 0; i < chunks.size(); i++) {
for (unsigned long int i = 0 ; i < chunks.size() ; i++) {
if(chunks[i].name == id)
return i;
}
@@ -64,8 +64,8 @@ namespace
if(name.size() != 4)
return false;
for(int i = 0; i < 4; i++) {
if(name[i] < 32 || name[i] > 127)
for (int i = 0 ; i < 4 ; i++) {
if (name[i] < 32)
return false;
}
@@ -227,7 +227,7 @@ bool DSDIFF::File::save()
return save(AllTags);
}
bool DSDIFF::File::save(TagTypes tags, StripTags strip, ID3v2::Version version)
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
{
if(readOnly()) {
debug("DSDIFF::File::save() -- File is read only.");

View File

@@ -180,7 +180,7 @@ bool DSF::File::save()
////////////////////////////////////////////////////////////////////////////////
void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
{
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
// The file format is not chunked in the sense of a RIFF File, though

View File

@@ -228,10 +228,10 @@ namespace
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "OGA") {
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
if(file->isValid())
return file;
delete file;
File *file_flac = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
if (file_flac->isValid())
return file_flac;
delete file_flac;
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
}
if(ext == "FLAC")

View File

@@ -92,8 +92,8 @@ namespace TagLib {
class TAGLIB_EXPORT FileTypeResolver
{
TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
virtual ~FileTypeResolver();
/*!
* This method must be overridden to provide an additional file type
* resolver. If the resolver is able to determine the file type it should
@@ -286,4 +286,4 @@ namespace TagLib {
}
} // namespace Strawberry_TagLib::TagLib
#endif
#endif // TAGLIB_FILEREF_H

View File

@@ -60,9 +60,9 @@ bool Mod::FileBase::readString(String &s, unsigned long size)
return true;
}
void Mod::FileBase::writeByte(unsigned char byte)
void Mod::FileBase::writeByte(unsigned char _byte)
{
ByteVector data(1, byte);
ByteVector data(1, _byte);
writeBlock(data);
}
@@ -86,11 +86,11 @@ void Mod::FileBase::writeU32B(unsigned long number)
writeBlock(ByteVector::fromUInt(number, true));
}
bool Mod::FileBase::readByte(unsigned char &byte)
bool Mod::FileBase::readByte(unsigned char &_byte)
{
ByteVector data(readBlock(1));
if(data.size() < 1) return false;
byte = data[0];
_byte = data[0];
return true;
}

View File

@@ -122,15 +122,15 @@ MP4::Atom::find(const char *name1, const char *name2, const char *name3, const c
}
MP4::AtomList
MP4::Atom::findall(const char *name, bool recursive)
MP4::Atom::findall(const char *_name, bool recursive)
{
MP4::AtomList result;
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == name) {
if((*it)->name == _name) {
result.append(*it);
}
if(recursive) {
result.append((*it)->findall(name, recursive));
result.append((*it)->findall(_name, recursive));
}
}
return result;

View File

@@ -67,7 +67,7 @@ namespace TagLib {
};
struct AtomData {
AtomData(AtomDataType type, ByteVector data) : type(type), locale(0), data(data) {}
AtomData(AtomDataType _type, ByteVector _data) : type(_type), locale(0), data(_data) {}
AtomDataType type;
int locale;
ByteVector data;

View File

@@ -334,14 +334,14 @@ ByteVector TableOfContentsFrame::renderFields() const
data.append(flags);
data.append((char)(entryCount()));
ByteVectorList::ConstIterator it = d->childElements.begin();
while(it != d->childElements.end()) {
while (it != d->childElements.end()) {
data.append(*it);
data.append('\0');
it++;
}
FrameList l = d->embeddedFrameList;
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
data.append((*it)->render());
for (FrameList::ConstIterator it2 = l.begin(); it2 != l.end(); ++it2)
data.append((*it2)->render());
return data;
}

View File

@@ -417,7 +417,7 @@ namespace
{"TYER", "TDRC"}, // 2.3 -> 2.4
{"TIME", "TDRC"}, // 2.3 -> 2.4
};
const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]);;
const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]);
}
String Frame::frameIDToKey(const ByteVector &id)

View File

@@ -69,7 +69,7 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MPEG::Header::Header(const ByteVector &data) :
MPEG::Header::Header(const ByteVector&) :
d(new HeaderPrivate())
{
debug("MPEG::Header::Header() - This constructor is no longer used.");

View File

@@ -296,10 +296,10 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
break;
page.setPageSequenceNumber(page.pageSequenceNumber() + numberOfNewPages);
const ByteVector data = page.render();
const ByteVector data2 = page.render();
seek(pageOffset + 18);
writeBlock(data.mid(18, 8));
writeBlock(data2.mid(18, 8));
if(page.header()->lastPageOfStream())
break;

View File

@@ -379,8 +379,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
// std::pair<String, StringList> where the first String is the field name and
// the StringList is the values associated with that field.
FieldListMap::ConstIterator it = d->fieldListMap.begin();
for(; it != d->fieldListMap.end(); ++it) {
for(FieldListMap::ConstIterator it = d->fieldListMap.begin() ; it != d->fieldListMap.end() ; ++it) {
// And now iterate over the values of the current list.
@@ -398,7 +397,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
}
}
for(PictureConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
for (PictureConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
ByteVector picture = (*it)->render().toBase64();
data.append(ByteVector::fromUInt(picture.size() + 23, false));
data.append("METADATA_BLOCK_PICTURE=");

View File

@@ -46,8 +46,8 @@ struct Chunk
class RIFF::File::FilePrivate
{
public:
explicit FilePrivate(Endianness endianness) :
endianness(endianness),
explicit FilePrivate(Endianness _endianness) :
endianness(_endianness),
size(0),
sizeOffset(0) {}

View File

@@ -77,11 +77,6 @@ ByteVectorList::ByteVectorList() :
}
ByteVectorList::ByteVectorList(const ByteVectorList &l) : List<ByteVector>(l)
{
}
ByteVectorList::~ByteVectorList()
{

View File

@@ -53,13 +53,6 @@ namespace TagLib {
*/
virtual ~ByteVectorList();
/*!
* Make a shallow, implicitly shared, copy of \a l. Because this is
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
ByteVectorList(const ByteVectorList &l);
/*!
* Convert the ByteVectorList to a ByteVector separated by \a separator. By
* default a space is used.

View File

@@ -43,8 +43,8 @@ public:
long position;
};
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &data) :
data(data),
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) :
data(_data),
position(0)
{
}

View File

@@ -71,9 +71,9 @@ using namespace Strawberry_TagLib::TagLib;
class File::FilePrivate
{
public:
FilePrivate(IOStream *stream, bool owner) :
stream(stream),
streamOwner(owner),
FilePrivate(IOStream *_stream, bool _owner) :
stream(_stream),
streamOwner(_owner),
valid(true) {}
~FilePrivate()

View File

@@ -58,7 +58,7 @@ namespace
#endif
}
FileHandle openFile(const int fileDescriptor, bool readOnly)
FileHandle openFile(const int, bool)
{
return InvalidFileHandle;
}

View File

@@ -28,16 +28,10 @@
using namespace Strawberry_TagLib::TagLib;
PropertyMap::PropertyMap() : SimplePropertyMap()
{
}
PropertyMap::PropertyMap() : SimplePropertyMap() {}
PropertyMap::PropertyMap(const PropertyMap &m) : SimplePropertyMap(m), unsupported(m.unsupported)
{
}
PropertyMap::PropertyMap(const SimplePropertyMap &m) {
PropertyMap::PropertyMap(const SimplePropertyMap &m)
{
for(SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it){
String key = it->first.upper();
if(!key.isEmpty())
@@ -45,14 +39,13 @@ PropertyMap::PropertyMap(const SimplePropertyMap &m)
else
unsupported.append(it->first);
}
}
PropertyMap::~PropertyMap()
{
}
PropertyMap::~PropertyMap() {}
bool PropertyMap::insert(const String &key, const StringList &values) {
bool PropertyMap::insert(const String &key, const StringList &values)
{
String realKey = key.upper();
Iterator result = SimplePropertyMap::find(realKey);
if(result == end())
@@ -60,6 +53,7 @@ bool PropertyMap::insert(const String &key, const StringList &values)
else
SimplePropertyMap::operator[](realKey).append(values);
return true;
}
bool PropertyMap::replace(const String &key, const StringList &values)

View File

@@ -115,8 +115,6 @@ namespace TagLib {
PropertyMap();
PropertyMap(const PropertyMap &m);
/*!
* Creates a PropertyMap initialized from a SimplePropertyMap. Copies all
* entries from \a m that have valid keys.

View File

@@ -62,13 +62,6 @@ StringList::StringList() :
}
StringList::StringList(const StringList &l) :
List<String>(l),
d(nullptr)
{
}
StringList::StringList(const String &s) :
List<String>(),
d(nullptr)

View File

@@ -57,7 +57,7 @@ namespace TagLib {
* implicitly shared, this method is lightweight and suitable for
* pass-by-value usage.
*/
StringList(const StringList &l);
StringList(const StringList &l) = default;
/*!
* Constructs a StringList with \a s as a member.

View File

@@ -193,7 +193,7 @@ namespace TagLib
// The last resort. May cause a buffer overflow.
length = vsprintf(buf, format, args);
if(length >= BufferSize) {
if(length >= (int)BufferSize) {
debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
length = -1;
}

View File

@@ -110,7 +110,7 @@ template<typename T>
class ValueReader : public Reader
{
public:
explicit ValueReader(T &value) : value(value)
explicit ValueReader(T &_value) : value(_value)
{
}
@@ -151,7 +151,7 @@ private:
class ByteReader : public ValueReader<unsigned char>
{
public:
explicit ByteReader(unsigned char &byte) : ValueReader<unsigned char>(byte) {}
explicit ByteReader(unsigned char &_byte) : ValueReader<unsigned char>(_byte) {}
unsigned int read(Strawberry_TagLib::TagLib::File &file, unsigned int limit)
{
@@ -172,8 +172,8 @@ template<typename T>
class NumberReader : public ValueReader<T>
{
public:
NumberReader(T &value, bool bigEndian) :
ValueReader<T>(value), bigEndian(bigEndian)
NumberReader(T &_value, bool _bigEndian) :
ValueReader<T>(_value), bigEndian(_bigEndian)
{
}
@@ -184,8 +184,8 @@ protected:
class U16Reader : public NumberReader<unsigned short>
{
public:
U16Reader(unsigned short &value, bool bigEndian)
: NumberReader<unsigned short>(value, bigEndian) {}
U16Reader(unsigned short &_value, bool _bigEndian)
: NumberReader<unsigned short>(_value, _bigEndian) {}
unsigned int read(Strawberry_TagLib::TagLib::File &file, unsigned int limit)
{
@@ -203,8 +203,8 @@ public:
class U32Reader : public NumberReader<unsigned long>
{
public:
U32Reader(unsigned long &value, bool bigEndian = true) :
NumberReader<unsigned long>(value, bigEndian)
U32Reader(unsigned long &_value, bool _bigEndian = true) :
NumberReader<unsigned long>(_value, _bigEndian)
{
}
@@ -479,11 +479,11 @@ bool XM::File::save()
if(sampleHeaderSize > 18U) {
seek(pos + 18);
const unsigned int len = std::min(sampleHeaderSize - 18U, 22UL);
const unsigned int len2 = std::min(sampleHeaderSize - 18U, 22UL);
if(sampleNameIndex >= lines.size())
writeString(String(), len);
writeString(String(), len2);
else
writeString(lines[sampleNameIndex ++], len);
writeString(lines[sampleNameIndex ++], len2);
}
}
pos += sampleHeaderSize;
@@ -560,10 +560,10 @@ void XM::File::read(bool)
StructReader pattern;
pattern.byte(packingType).u16L(rowCount).u16L(dataSize);
unsigned int count = pattern.read(*this, patternHeaderLength - 4U);
READ_ASSERT(count == std::min(patternHeaderLength - 4U, (unsigned long)pattern.size()));
unsigned int count2 = pattern.read(*this, patternHeaderLength - 4U);
READ_ASSERT(count2 == std::min(patternHeaderLength - 4U, (unsigned long)pattern.size()));
seek(patternHeaderLength - (4 + count) + dataSize, Current);
seek(patternHeaderLength - (4 + count2) + dataSize, Current);
}
StringList intrumentNames;
@@ -583,17 +583,17 @@ void XM::File::read(bool)
instrument.string(instrumentName, 22).byte(instrumentType).u16L(sampleCount);
// 4 for instrumentHeaderSize
unsigned int count = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
READ_ASSERT(count == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
unsigned int count2 = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
READ_ASSERT(count2 == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
long offset = 0;
if(sampleCount > 0) {
unsigned long sampleHeaderSize = 0;
sumSampleCount += sampleCount;
// wouldn't know which header size to assume otherwise:
READ_ASSERT(instrumentHeaderSize >= count + 4 && readU32L(sampleHeaderSize));
READ_ASSERT(instrumentHeaderSize >= count2 + 4 && readU32L(sampleHeaderSize));
// skip unhandled header proportion:
seek(instrumentHeaderSize - count - 4, Current);
seek(instrumentHeaderSize - count2 - 4, Current);
for(unsigned short j = 0; j < sampleCount; ++ j) {
unsigned long sampleLength = 0;
@@ -618,17 +618,17 @@ void XM::File::read(bool)
.byte(compression)
.string(sampleName, 22);
unsigned int count = sample.read(*this, sampleHeaderSize);
READ_ASSERT(count == std::min(sampleHeaderSize, (unsigned long)sample.size()));
unsigned int count3 = sample.read(*this, sampleHeaderSize);
READ_ASSERT(count3 == std::min(sampleHeaderSize, (unsigned long)sample.size()));
// skip unhandled header proportion:
seek(sampleHeaderSize - count, Current);
seek(sampleHeaderSize - count3, Current);
offset += sampleLength;
sampleNames.append(sampleName);
}
}
else {
offset = instrumentHeaderSize - count;
offset = instrumentHeaderSize - count2;
}
intrumentNames.append(instrumentName);
seek(offset, Current);

View File

@@ -1,24 +1,7 @@
# 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/>.
project(strawberry)
cmake_minimum_required(VERSION 2.8.11)
if(CMAKE_VERSION VERSION_GREATER 3.0)
cmake_policy(SET CMP0054 NEW)
endif()
cmake_minimum_required(VERSION 3.0)
cmake_policy(SET CMP0054 NEW)
include(CheckCXXCompilerFlag)
include(CheckCXXSourceRuns)
@@ -32,6 +15,8 @@ include(cmake/Rpm.cmake)
include(cmake/Deb.cmake)
include(cmake/Dmg.cmake)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
set(LINUX ON)
endif()
@@ -42,8 +27,46 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
set(OPENBSD ON)
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
list(APPEND COMPILE_OPTIONS
$<$<COMPILE_LANGUAGE:C>:--std=c99>
$<$<COMPILE_LANGUAGE:CXX>:--std=c++11>
-U__STRICT_ANSI__
-Wall
-Wextra
-Wpedantic
-Wunused
-Wshadow
-Wundef
-Wuninitialized
-Wredundant-decls
-Wcast-align
-Winit-self
-Wmissing-include-dirs
-Wmissing-declarations
-Wstrict-overflow=2
-Wunused-parameter
-Wformat=2
-Wdisabled-optimization
-Wno-sign-conversion
$<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>
$<$<COMPILE_LANGUAGE:CXX>:-Wno-old-style-cast>
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
)
if(APPLE)
list(APPEND COMPILE_OPTIONS -Wno-unused-parameter)
endif()
option(BUILD_WERROR "Build with -Werror" OFF)
if(BUILD_WERROR)
list(APPEND COMPILE_OPTIONS -Werror)
endif(BUILD_WERROR)
add_compile_options(${COMPILE_OPTIONS})
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
add_definitions(-DNDEBUG)
@@ -98,7 +121,6 @@ pkg_check_modules(GSTREAMER_TAG gstreamer-tag-1.0)
pkg_check_modules(GSTREAMER_PBUTILS gstreamer-pbutils-1.0)
pkg_check_modules(LIBXINE libxine)
pkg_check_modules(LIBVLC libvlc)
pkg_check_modules(PHONON phonon4qt5)
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.9)
pkg_check_modules(LIBPULSE libpulse)
pkg_check_modules(CHROMAPRINT libchromaprint)
@@ -175,11 +197,10 @@ pkg_check_modules(TAGLIB taglib)
# - Audio file detection by content.
# - DSF and DSDIFF support
#
if (TAGLIB_VERSION VERSION_GREATER 1.11.1)
option(USE_SYSTEM_TAGLIB "Use system taglib" ON)
else()
option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
endif()
# Some distros create their own version numbers for taglib so versions are not reliable anymore.
# Force to use our own copy of taglib unless USE_SYSTEM_TAGLIB is set.
option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
if (TAGLIB_FOUND AND USE_SYSTEM_TAGLIB)
if (TAGLIB_VERSION VERSION_GREATER 1.11.1)
message(STATUS "Using system taglib library")
@@ -275,10 +296,6 @@ optional_component(VLC ON "Engine: VLC backend"
DEPENDS "libvlc" LIBVLC_FOUND
)
optional_component(PHONON OFF "Engine: Phonon backend (UNSTABLE)"
DEPENDS "phonon4qt5" PHONON_FOUND
)
optional_component(CHROMAPRINT ON "Chromaprint (Tag fetching from Musicbrainz)"
DEPENDS "chromaprint" CHROMAPRINT_FOUND
)
@@ -330,6 +347,7 @@ optional_component(TRANSLATIONS ON "Translations"
)
optional_component(SUBSONIC ON "Subsonic support")
optional_component(TIDAL ON "Tidal support")
optional_component(MOODBAR ON "Moodbar"
DEPENDS "fftw3" FFTW3_FOUND
@@ -387,17 +405,14 @@ if(HAVE_XINE)
XINE_ANALYZER)
endif()
# Set up definitions and paths
# Set up definitions
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_STRICT_ITERATORS)
add_definitions(-DQT_USE_QSTRINGBUILDER)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
add_definitions(-DQT_NO_CAST_TO_ASCII -DQT_STRICT_ITERATORS)
include_directories(${GLIB_INCLUDE_DIRS})
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS})
add_definitions(-DQT_NO_CAST_TO_ASCII)
# Subdirectories
add_subdirectory(src)
@@ -421,8 +436,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 have either GStreamer, Xine, VLC or Phonon to compile!")
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC)
message(FATAL_ERROR "You need to have either GStreamer, Xine or VLC 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()

View File

@@ -2,6 +2,46 @@ Strawberry Music Player
=======================
ChangeLog
0.6.10:
Bugfixes:
* Fixed Subsonic album covers not working for albums with non ASCII charcters.
* Fixed reading date and genre from individual tracks in CUE sheets.
* Fixed resume playback on startup for CUE songs.
* Fixed album cover manager not showing complete album titles in the list of album covers.
* Fixed save album cover to file saving "no cover" image instead of actual album cover.
* Fixed device state text color in devices not being visible when using a dark theme.
* Fixed engine and device in context using too large icons when icons were loaded from the system theme.
* Fixed "Secure connection setup failed" problem on Windows when playing streams.
* Fixed margin for song title text in context.
* Fixed UNC paths with non ASCII charcters not working.
Enhancements:
* Allowing all characters except slash and backslash when organising music unless options to strip characters is checked.
* New option in organising music to remove problematic filename characters that removes less characters than the FAT option.
* General improvements to the album cover loader and album cover providers code.
* Fixed loading album cover images from album directory for songs added to the playlist from outside of the collection.
* Made automatic album cover search work for songs outside of the collection and for streams.
* Made album cover search work based on artist + title if album title is not present for providers supporting song/track search.
* Update art manual in playlist for local files, devices and CDDA to avoid loading covers multiple times.
* Made lyrics search work for streams.
* Added "add stream" to menu.
* Only showing song length in context when available.
* Sort album cover search results by score and pick the best 3 first before trying others to improve album cover search speed.
* Make scrobbler work for streams.
* Added search for lyrics as a seperate option in context.
* Made font and font sizes in context configurable.
* Splitting artist and song title to the relevant metadata when artist and song title is sent as title seperated by a dash in streams.
* Added label to show collection pixmap disk cache used in settings.
* Icreased default collection pixmap disk cache to 360.
New features:
* Added back Tidal streaming support.
* Added Qobuz album cover provider.
Removed features:
* Removed Phonon engine support.
Version 0.6.9:
BugFixes:

View File

@@ -63,7 +63,7 @@ To build Strawberry from source you need the following installed on your system
* [ALSA library (linux)](https://www.alsa-project.org/)
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org), [VLC](https://www.videolan.org) or [Phonon](https://techbase.kde.org/Phonon)
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org) or [VLC](https://www.videolan.org)
* [GnuTLS](https://www.gnutls.org/)
Optional dependencies:
@@ -74,7 +74,7 @@ Optional dependencies:
* iPhone, iPod Touch, iPad and Apple TV devices: [libimobiledevice, libplist and libusbmuxd](https://www.libimobiledevice.org/)
* Moodbar: [fftw3](http://www.fftw.org/)
Either GStreamer, Xine, VLC or Phonon engine is required, but only GStreamer is fully implemented so far.
Either GStreamer, Xine or VLC 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.
### :wrench: Compiling from source

View File

@@ -57,12 +57,12 @@ if (LSB_RELEASE_EXEC AND RPMBUILD_EXEC)
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
message(STATUS "RPM Suffix: ${RPM_DISTRO}")
configure_file(${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec.in ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec @ONLY)
configure_file(${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec.in ${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec @ONLY)
add_custom_target(rpm
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec
)
endif()
endif()

View File

@@ -0,0 +1,9 @@
SET(CMAKE_SYSTEM_NAME Windows)
SET(HOME "$ENV{HOME}")
SET(CMAKE_C_COMPILER "${HOME}/mxe-shared/usr/bin/i686-w64-mingw32.shared-gcc")
SET(CMAKE_CXX_COMPILER "${HOME}/mxe-shared/usr/bin/i686-w64-mingw32.shared-g++")
SET(CMAKE_RC_COMPILER "${HOME}/mxe-shared/usr/bin/i686-w64-mingw32.shared-windres")
SET(CMAKE_FIND_ROOT_PATH "${HOME}/mxe-shared/usr/i686-w64-mingw32.shared/")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@@ -0,0 +1,9 @@
SET(CMAKE_SYSTEM_NAME Windows)
SET(HOME "$ENV{HOME}")
SET(CMAKE_C_COMPILER "${HOME}/mxe-shared/usr/bin/x86_64-w64-mingw32.shared-gcc")
SET(CMAKE_CXX_COMPILER "${HOME}/mxe-shared/usr/bin/x86_64-w64-mingw32.shared-g++")
SET(CMAKE_RC_COMPILER "${HOME}/mxe-shared/usr/bin/x86_64-w64-mingw32.shared-windres")
SET(CMAKE_FIND_ROOT_PATH "${HOME}/mxe-shared/usr/x86_64-w64-mingw32.shared/")
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

View File

@@ -1,6 +1,6 @@
set(STRAWBERRY_VERSION_MAJOR 0)
set(STRAWBERRY_VERSION_MINOR 6)
set(STRAWBERRY_VERSION_PATCH 9)
set(STRAWBERRY_VERSION_PATCH 10)
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
set(INCLUDE_GIT_REVISION OFF)

View File

@@ -11,6 +11,8 @@
<file>schema/schema-8.sql</file>
<file>schema/schema-9.sql</file>
<file>schema/schema-10.sql</file>
<file>schema/schema-11.sql</file>
<file>schema/schema-12.sql</file>
<file>schema/device-schema.sql</file>
<file>style/strawberry.css</file>
<file>html/playing-tooltip-plain.html</file>
@@ -40,5 +42,6 @@
<file>pictures/rainbowdash.png</file>
<file>fonts/HumongousofEternitySt.ttf</file>
<file>mood/sample.mood</file>
<file>text/ghosts.txt</file>
</qresource>
</RCC>

View File

@@ -89,6 +89,7 @@
<file>icons/128x128/moodbar.png</file>
<file>icons/128x128/love.png</file>
<file>icons/128x128/subsonic.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>
@@ -179,6 +180,7 @@
<file>icons/64x64/moodbar.png</file>
<file>icons/64x64/love.png</file>
<file>icons/64x64/subsonic.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>
@@ -201,6 +203,7 @@
<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-remote.png</file>
<file>icons/48x48/document-open.png</file>
<file>icons/48x48/document-save.png</file>
<file>icons/48x48/document-search.png</file>
@@ -272,6 +275,7 @@
<file>icons/48x48/moodbar.png</file>
<file>icons/48x48/love.png</file>
<file>icons/48x48/subsonic.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>
@@ -294,6 +298,7 @@
<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-remote.png</file>
<file>icons/32x32/document-open.png</file>
<file>icons/32x32/document-save.png</file>
<file>icons/32x32/document-search.png</file>
@@ -365,6 +370,7 @@
<file>icons/32x32/moodbar.png</file>
<file>icons/32x32/love.png</file>
<file>icons/32x32/subsonic.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>
@@ -387,6 +393,7 @@
<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-remote.png</file>
<file>icons/22x22/document-open.png</file>
<file>icons/22x22/document-save.png</file>
<file>icons/22x22/document-search.png</file>
@@ -458,5 +465,6 @@
<file>icons/22x22/moodbar.png</file>
<file>icons/22x22/love.png</file>
<file>icons/22x22/subsonic.png</file>
<file>icons/22x22/tidal.png</file>
</qresource>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 933 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View File

@@ -11,25 +11,25 @@ CREATE TABLE device_%deviceid_subdirectories (
CREATE TABLE device_%deviceid_songs (
title TEXT NOT NULL,
album TEXT NOT NULL,
artist TEXT NOT NULL,
albumartist TEXT NOT NULL,
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT NOT NULL,
compilation INTEGER NOT NULL DEFAULT -1,
composer TEXT NOT NULL,
performer TEXT NOT NULL,
grouping TEXT NOT NULL,
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,

247
data/schema/schema-11.sql Normal file
View File

@@ -0,0 +1,247 @@
DROP VIEW IF EXISTS duplicated_songs;
DROP INDEX IF EXISTS idx_url;
DROP INDEX IF EXISTS idx_comp_artist;
DROP INDEX IF EXISTS idx_albumartist;
DROP INDEX IF EXISTS idx_artist;
DROP INDEX IF EXISTS idx_album;
DROP INDEX IF EXISTS idx_title;
ALTER TABLE songs RENAME TO songs_old;
ALTER TABLE subsonic_songs RENAME TO subsonic_songs_old;
ALTER TABLE playlist_items RENAME TO playlist_items_old;
CREATE TABLE songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE INDEX IF NOT EXISTS idx_url ON songs (url);
CREATE INDEX IF NOT EXISTS idx_comp_artist ON songs (compilation_effective, artist);
CREATE INDEX IF NOT EXISTS idx_albumartist ON songs (albumartist);
CREATE INDEX IF NOT EXISTS idx_artist ON songs (artist);
CREATE INDEX IF NOT EXISTS idx_album ON songs (album);
CREATE INDEX IF NOT EXISTS idx_title ON songs (title);
CREATE VIEW duplicated_songs as select artist dup_artist, album dup_album, title dup_title from songs as inner_songs where artist != '' and album != '' and title != '' and unavailable = 0 group by artist, album , title having count(*) > 1;
CREATE TABLE subsonic_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
INSERT INTO songs (ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path)
SELECT ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path
FROM songs_old;
DROP TABLE songs_old;
DELETE FROM songs_fts;
INSERT INTO songs_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
FROM songs;
INSERT INTO subsonic_songs (ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path)
SELECT ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path
FROM subsonic_songs_old;
DROP TABLE subsonic_songs_old;
DELETE FROM subsonic_songs_fts;
INSERT INTO subsonic_songs_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
FROM subsonic_songs;
CREATE TABLE playlist_items (
playlist INTEGER NOT NULL,
type INTEGER NOT NULL DEFAULT 0,
collection_id INTEGER,
playlist_url TEXT,
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER,
disc INTEGER,
year INTEGER,
originalyear INTEGER,
genre TEXT,
compilation INTEGER DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER,
length INTEGER,
bitrate INTEGER,
samplerate INTEGER,
bitdepth INTEGER,
source INTEGER,
directory_id INTEGER,
url TEXT,
filetype INTEGER,
filesize INTEGER,
mtime INTEGER,
ctime INTEGER,
unavailable INTEGER DEFAULT 0,
playcount INTEGER DEFAULT 0,
skipcount INTEGER DEFAULT 0,
lastplayed INTEGER DEFAULT 0,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER DEFAULT 0,
compilation_off INTEGER DEFAULT 0,
compilation_effective INTEGER DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER,
cue_path TEXT
);
INSERT INTO playlist_items (ROWID, playlist, type, collection_id, playlist_url, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path)
SELECT ROWID, playlist, type, collection_id, playlist_url, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path
FROM playlist_items_old;
DROP TABLE playlist_items_old;
DELETE FROM playlist_items_fts_;
INSERT INTO playlist_items_fts_ (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
FROM playlist_items;
UPDATE schema_version SET version=11;

217
data/schema/schema-12.sql Normal file
View File

@@ -0,0 +1,217 @@
CREATE TABLE IF NOT EXISTS tidal_artists_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS tidal_albums_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS tidal_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
UPDATE schema_version SET version=12;

View File

@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS schema_version (
DELETE FROM schema_version;
INSERT INTO schema_version (version) VALUES (10);
INSERT INTO schema_version (version) VALUES (12);
CREATE TABLE IF NOT EXISTS directories (
path TEXT NOT NULL,
@@ -19,25 +19,196 @@ CREATE TABLE IF NOT EXISTS subdirectories (
CREATE TABLE IF NOT EXISTS songs (
title TEXT NOT NULL,
album TEXT NOT NULL,
artist TEXT NOT NULL,
albumartist TEXT NOT NULL,
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT NOT NULL,
compilation INTEGER NOT NULL DEFAULT -1,
composer TEXT NOT NULL,
performer TEXT NOT NULL,
grouping TEXT NOT NULL,
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS tidal_artists_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS tidal_albums_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT -1,
mtime INTEGER NOT NULL DEFAULT -1,
ctime INTEGER NOT NULL DEFAULT -1,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS tidal_songs (
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
@@ -76,25 +247,25 @@ CREATE TABLE IF NOT EXISTS songs (
CREATE TABLE IF NOT EXISTS subsonic_songs (
title TEXT NOT NULL,
album TEXT NOT NULL,
artist TEXT NOT NULL,
albumartist TEXT NOT NULL,
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT NOT NULL,
compilation INTEGER NOT NULL DEFAULT -1,
composer TEXT NOT NULL,
performer TEXT NOT NULL,
grouping TEXT NOT NULL,
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
genre TEXT,
compilation INTEGER NOT NULL DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
@@ -149,56 +320,56 @@ CREATE TABLE IF NOT EXISTS playlist_items (
collection_id INTEGER,
playlist_url TEXT,
title TEXT NOT NULL,
album TEXT NOT NULL,
artist TEXT NOT NULL,
albumartist TEXT NOT NULL,
track INTEGER NOT NULL DEFAULT -1,
disc INTEGER NOT NULL DEFAULT -1,
year INTEGER NOT NULL DEFAULT -1,
originalyear INTEGER NOT NULL DEFAULT 0,
genre TEXT NOT NULL,
compilation INTEGER NOT NULL DEFAULT -1,
composer TEXT NOT NULL,
performer TEXT NOT NULL,
grouping TEXT NOT NULL,
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
title TEXT,
album TEXT,
artist TEXT,
albumartist TEXT,
track INTEGER,
disc INTEGER,
year INTEGER,
originalyear INTEGER,
genre TEXT,
compilation INTEGER DEFAULT 0,
composer TEXT,
performer TEXT,
grouping TEXT,
comment TEXT,
lyrics TEXT,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
artist_id TEXT,
album_id TEXT,
song_id TEXT,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
beginning INTEGER,
length INTEGER,
bitrate INTEGER NOT NULL DEFAULT -1,
samplerate INTEGER NOT NULL DEFAULT -1,
bitdepth INTEGER NOT NULL DEFAULT -1,
bitrate INTEGER,
samplerate INTEGER,
bitdepth INTEGER,
source INTEGER NOT NULL DEFAULT 0,
source INTEGER,
directory_id INTEGER,
url TEXT,
filetype INTEGER NOT NULL DEFAULT 0,
filetype INTEGER,
filesize INTEGER,
mtime INTEGER,
ctime INTEGER,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
playcount INTEGER DEFAULT 0,
skipcount INTEGER DEFAULT 0,
lastplayed INTEGER DEFAULT 0,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
compilation_off INTEGER NOT NULL DEFAULT 0,
compilation_effective INTEGER NOT NULL DEFAULT 0,
compilation_on INTEGER DEFAULT 0,
compilation_off INTEGER DEFAULT 0,
compilation_effective INTEGER DEFAULT 0,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
effective_originalyear INTEGER,
cue_path TEXT
@@ -243,6 +414,51 @@ CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5(
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS subsonic_songs_fts USING fts5(
ftstitle,

42
data/text/ghosts.txt Normal file
View File

@@ -0,0 +1,42 @@
Go to sleep my babies
Don't you wake up
The stars will keep you company
So close your eyes
Old Uncle Moon will shine his dearest sweetest dreams
And hold you in your arms
Until the morning comes.
Night Light
Dark the night, not a sound
Damp and cold, frosty ground
Above your head the lion screams
To tear you from your moonlit dreams.
Damp with sweat, mouth is dry
Twisted branches catch the eye
Beside your bed the angel stands
You cannot touch his withered hands.
Guardian Angel
As the lion's eyes dance before me
They are kindly yet bloody red
I can see that he is smiling
But I cannot live inside his head.
There the needle stands before me
I climb inside it towards the light
Where the angel stands in glory
His sword of peace defends the night.
So the world is spread before
As I fly high on angel wings
But the angel is deceiving
For he is weeping as he sings.
Night Light (continued)
Early birds, morning breeze
Spinning leaves, sleepy trees
Gently tap the window pane
It's good to see the sun again.
(Dave Cousins)

2
debian/copyright vendored
View File

@@ -34,8 +34,6 @@ Files: src/core/main.h
src/engine/devicefinder.h
src/engine/enginedevice.cpp
src/engine/enginedevice.h
src/engine/phononengine.cpp
src/engine/phononengine.h
src/internet/internetservice.cpp
src/internet/internetservice.h
src/internet/internettabsview.cpp

4
debian/rules vendored
View File

@@ -6,8 +6,8 @@
override_dh_auto_clean:
rm -f dist/macos/Info.plist
rm -f dist/macos/create-dmg.sh
rm -f dist/pacman/PKGBUILD
rm -f dist/rpm/strawberry.spec
rm -f dist/unix/PKGBUILD
rm -f dist/unix/strawberry.spec
rm -f dist/scripts/maketarball.sh
rm -f dist/windows/strawberry.nsi
rm -f src/translations/translations.pot

4
dist/CMakeLists.txt vendored
View File

@@ -1,5 +1,5 @@
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD @ONLY)
if (APPLE)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
@@ -16,7 +16,7 @@ if (UNIX AND NOT APPLE)
install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/)
install(FILES unix/org.strawberrymusicplayer.strawberry.desktop DESTINATION share/applications)
install(FILES unix/org.strawberrymusicplayer.strawberry.appdata.xml DESTINATION share/metainfo)
install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1)
install(FILES unix/strawberry.1 unix/strawberry-tagreader.1 DESTINATION share/man/man1)
endif (UNIX AND NOT APPLE)
if (APPLE)

View File

@@ -36,7 +36,7 @@ tar -cJf $name-$version.tar.xz \
--exclude="$root/.zanata-cache" \
--exclude="$root/debian/changelog" \
--exclude="$root/dist/scripts/maketarball.sh" \
--exclude="$root/dist/pacman/PKGBUILD" \
--exclude="$root/dist/unix/PKGBUILD" \
--exclude="$root/dist/macos/create-dmg.sh" \
--exclude="$root/dist/macos/Info.plist" \
--exclude="$root/dist/windows/windres.rc" \

View File

@@ -32,7 +32,6 @@ depends=(
libusbmuxd
libplist
libimobiledevice
phonon-qt5
fftw
)
optdepends=(
@@ -54,7 +53,6 @@ build() {
cmake ../${pkgname}-@STRAWBERRY_VERSION_PACKAGE@ \
-DCMAKE_INSTALL_PREFIX=/usr \
-DUSE_SYSTEM_TAGLIB=ON \
-DENABLE_PHONON=ON \
-DENABLE_TRANSLATIONS=ON
make -j$(nproc)
}

View File

@@ -10,5 +10,5 @@ Icon=strawberry
Terminal=false
Categories=AudioVideo;Player;Qt;Audio;
StartupNotify=false
MimeType=x-content/audio-player;application/ogg;application/x-ogg;application/x-ogm-audio;audio/flac;audio/ogg;audio/vorbis;audio/aac;audio/mp4;audio/mpeg;audio/mpegurl;audio/vnd.rn-realaudio;audio/x-flac;audio/x-oggflac;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-speex;audio/x-wav;audio/x-wavpack;audio/x-ape;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-wma;audio/x-musepack;audio/x-pn-realaudio;audio/x-scpls;video/x-ms-asf
MimeType=x-content/audio-player;application/ogg;application/x-ogg;application/x-ogm-audio;audio/flac;audio/ogg;audio/vorbis;audio/aac;audio/mp4;audio/mpeg;audio/mpegurl;audio/vnd.rn-realaudio;audio/x-flac;audio/x-oggflac;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-speex;audio/x-wav;audio/x-wavpack;audio/x-ape;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-wma;audio/x-musepack;audio/x-pn-realaudio;audio/x-scpls;video/x-ms-asf;x-scheme-handler/tidal;
StartupWMClass=strawberry

View File

@@ -201,7 +201,7 @@ Section "Strawberry" Strawberry
File "libspeex-1.dll"
File "libsqlite3-0.dll"
File "libstdc++-6.dll"
;File "libtag.dll"
File "libtag.dll"
File "libunistring-2.dll"
File "libvorbis-0.dll"
File "libvorbisenc-2.dll"

View File

@@ -1,15 +1,6 @@
cmake_minimum_required(VERSION 2.8.11)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
endif()
cmake_minimum_required(VERSION 3.0)
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${GLIB_INCLUDE_DIRS})
include_directories(${GOBJECT_INCLUDE_DIRS})
include_directories(${GSTREAMER_INCLUDE_DIRS})

View File

@@ -1,13 +1,7 @@
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
cmake_minimum_required(VERSION 3.0)
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/src)
@@ -17,6 +11,8 @@ if (Backtrace_FOUND)
include_directories(${Backtrace_INCLUDE_DIRS})
endif(Backtrace_FOUND)
include_directories(${GLIB_INCLUDE_DIRS})
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
include_directories(${PROTOBUF_INCLUDE_DIRS})
set(SOURCES
@@ -41,18 +37,11 @@ endif(APPLE)
qt5_wrap_cpp(MOC ${HEADERS})
add_library(libstrawberry-common STATIC
${SOURCES}
${MOC}
)
add_library(libstrawberry-common STATIC ${SOURCES} ${MOC})
if (Backtrace_FOUND)
if(Backtrace_FOUND)
target_link_libraries(libstrawberry-common ${Backtrace_LIBRARIES})
endif (Backtrace_FOUND)
target_link_libraries(libstrawberry-common
${TAGLIB_LIBRARIES}
${CMAKE_THREAD_LIBS_INIT}
)
endif(Backtrace_FOUND)
target_link_libraries(libstrawberry-common ${TAGLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(libstrawberry-common Qt5::Core Qt5::Network)

View File

@@ -273,6 +273,8 @@ static T CreateLogger(Level level, const QString &class_name, int line, const ch
return ret.space();
}
QString CXXDemangle(const QString &mangled_function);
QString CXXDemangle(const QString &mangled_function) {
int status;
@@ -286,6 +288,8 @@ QString CXXDemangle(const QString &mangled_function) {
}
QString DarwinDemangle(const QString &symbol);
QString DarwinDemangle(const QString &symbol) {
QStringList split = symbol.split(' ', QString::SkipEmptyParts);
@@ -294,6 +298,8 @@ QString DarwinDemangle(const QString &symbol) {
}
QString LinuxDemangle(const QString &symbol);
QString LinuxDemangle(const QString &symbol) {
QRegExp regex("\\(([^+]+)");
@@ -305,6 +311,8 @@ QString LinuxDemangle(const QString &symbol) {
}
QString DemangleSymbol(const QString &symbol);
QString DemangleSymbol(const QString &symbol) {
#ifdef Q_OS_MACOS
return DarwinDemangle(symbol);

View File

@@ -47,13 +47,13 @@ void _MessageHandlerBase::SetDevice(QIODevice *device) {
connect(device, SIGNAL(readyRead()), SLOT(DeviceReadyRead()));
// Yeah I know.
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(device)) {
if (QAbstractSocket *abstractsocket = qobject_cast<QAbstractSocket*>(device)) {
flush_abstract_socket_ = &QAbstractSocket::flush;
connect(socket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
connect(abstractsocket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
}
else if (QLocalSocket* socket = qobject_cast<QLocalSocket*>(device)) {
else if (QLocalSocket *localsocket = qobject_cast<QLocalSocket*>(device)) {
flush_local_socket_ = &QLocalSocket::flush;
connect(socket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
connect(localsocket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
}
else {
qFatal("Unsupported device type passed to _MessageHandlerBase");

View File

@@ -26,13 +26,16 @@ _MessageReplyBase::_MessageReplyBase(QObject *parent)
: QObject(parent), finished_(false), success_(false) {}
bool _MessageReplyBase::WaitForFinished() {
qLog(Debug) << "Waiting on ID" << id();
semaphore_.acquire();
qLog(Debug) << "Acquired ID" << id();
return success_;
}
void _MessageReplyBase::Abort() {
Q_ASSERT(!finished_);
finished_ = true;
success_ = false;
@@ -40,4 +43,5 @@ void _MessageReplyBase::Abort() {
emit Finished(success_);
qLog(Debug) << "Releasing ID" << id() << "(aborted)";
semaphore_.release();
}

View File

@@ -1,10 +1,4 @@
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
endif()
cmake_minimum_required(VERSION 3.0)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
@@ -12,31 +6,16 @@ include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CMAKE_BINARY_DIR}/src)
link_directories(${PROTOBUF_LIBRARY_DIRS})
include_directories(${PROTOBUF_INCLUDE_DIRS})
set(MESSAGES
tagreadermessages.proto
)
link_directories(${TAGLIB_LIBRARY_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS})
set(SOURCES
fmpsparser.cpp
tagreader.cpp
)
set(HEADERS
)
qt5_wrap_cpp(MOC ${HEADERS})
set(MESSAGES tagreadermessages.proto)
set(SOURCES fmpsparser.cpp tagreader.cpp)
protobuf_generate_cpp(PROTO_SOURCES PROTO_HEADERS ${MESSAGES})
add_library(libstrawberry-tagreader STATIC
${PROTO_SOURCES}
${SOURCES}
${MOC}
)
target_link_libraries(libstrawberry-tagreader
${PROTOBUF_LIBRARY}
libstrawberry-common
)
add_library(libstrawberry-tagreader STATIC ${PROTO_SOURCES} ${SOURCES})
target_link_libraries(libstrawberry-tagreader ${PROTOBUF_LIBRARY} libstrawberry-common)

View File

@@ -212,46 +212,46 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
// apart, so we keep specific behavior for some formats by adding another "else if" block below.
if (TagLib::Ogg::XiphComment *tag = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
ParseOggTag(tag->fieldListMap(), nullptr, &disc, &compilation, song);
if (!tag->pictureList().isEmpty()) {
if (TagLib::Ogg::XiphComment *tag_ogg = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
ParseOggTag(tag_ogg->fieldListMap(), nullptr, &disc, &compilation, song);
if (!tag_ogg->pictureList().isEmpty()) {
song->set_art_automatic(kEmbeddedCover);
}
}
if (TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>(fileref->file())) {
if (TagLib::FLAC::File *file_flac = dynamic_cast<TagLib::FLAC::File *>(fileref->file())) {
song->set_bitdepth(file->audioProperties()->bitsPerSample());
song->set_bitdepth(file_flac->audioProperties()->bitsPerSample());
if (file->xiphComment()) {
ParseOggTag(file->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song);
if (!file->pictureList().isEmpty()) {
if (file_flac->xiphComment()) {
ParseOggTag(file_flac->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song);
if (!file_flac->pictureList().isEmpty()) {
song->set_art_automatic(kEmbeddedCover);
}
}
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
}
else if (TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File *>(fileref->file())) {
song->set_bitdepth(file->audioProperties()->bitsPerSample());
if (file->tag()) {
ParseAPETag(file->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File *>(fileref->file())) {
song->set_bitdepth(file_wavpack->audioProperties()->bitsPerSample());
if (file_wavpack->tag()) {
ParseAPETag(file_wavpack->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
}
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
}
else if (TagLib::APE::File *file = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
if (file->tag()) {
ParseAPETag(file->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
else if (TagLib::APE::File *file_ape = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
if (file_ape->tag()) {
ParseAPETag(file_ape->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
}
song->set_bitdepth(file->audioProperties()->bitsPerSample());
song->set_bitdepth(file_ape->audioProperties()->bitsPerSample());
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
}
else if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
if (file->ID3v2Tag()) {
const TagLib::ID3v2::FrameListMap &map = file->ID3v2Tag()->frameListMap();
if (file_mpeg->ID3v2Tag()) {
const TagLib::ID3v2::FrameListMap &map = file_mpeg->ID3v2Tag()->frameListMap();
if (!map["TPOS"].isEmpty()) disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
if (!map["TCOM"].isEmpty()) Decode(map["TCOM"].front()->toString(), nullptr, song->mutable_composer());
@@ -309,12 +309,12 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
}
}
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
else if (TagLib::MP4::File *file_mp4 = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
song->set_bitdepth(file->audioProperties()->bitsPerSample());
song->set_bitdepth(file_mp4->audioProperties()->bitsPerSample());
if (file->tag()) {
TagLib::MP4::Tag *mp4_tag = file->tag();
if (file_mp4->tag()) {
TagLib::MP4::Tag *mp4_tag = file_mp4->tag();
// Find album artists
if (mp4_tag->item("aART").isValid()) {
@@ -348,11 +348,11 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
}
}
else if (TagLib::ASF::File *file = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
else if (TagLib::ASF::File *file_asf = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
song->set_bitdepth(file->audioProperties()->bitsPerSample());
song->set_bitdepth(file_asf->audioProperties()->bitsPerSample());
const TagLib::ASF::AttributeListMap &attributes_map = file->tag()->attributeListMap();
const TagLib::ASF::AttributeListMap &attributes_map = file_asf->tag()->attributeListMap();
if (attributes_map.contains(kASF_OriginalDate_ID)) {
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalDate_ID];
@@ -368,9 +368,9 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
}
}
else if (TagLib::MPC::File* file = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
if (file->tag()) {
ParseAPETag(file->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
else if (TagLib::MPC::File* file_mpc = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
if (file_mpc->tag()) {
ParseAPETag(file_mpc->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
}
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
}
@@ -578,26 +578,26 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
SetVorbisComments(tag, song);
}
else if (TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
TagLib::APE::Tag *tag = file->APETag(true);
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
TagLib::APE::Tag *tag = file_wavpack->APETag(true);
if (!tag) return false;
SaveAPETag(tag, song);
}
else if (TagLib::APE::File *file = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
TagLib::APE::Tag *tag = file->APETag(true);
else if (TagLib::APE::File *file_ape = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
TagLib::APE::Tag *tag = file_ape->APETag(true);
if (!tag) return false;
SaveAPETag(tag, song);
}
else if (TagLib::MPC::File *file = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
TagLib::APE::Tag *tag = file->APETag(true);
else if (TagLib::MPC::File *file_mpc = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
TagLib::APE::Tag *tag = file_mpc->APETag(true);
if (!tag) return false;
SaveAPETag(tag, song);
}
else if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
TagLib::ID3v2::Tag *tag = file->ID3v2Tag(true);
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
TagLib::ID3v2::Tag *tag = file_mpeg->ID3v2Tag(true);
if (!tag) return false;
SetTextFrame("TPOS", song.disc() <= 0 -1 ? QString() : QString::number(song.disc()), tag);
SetTextFrame("TCOM", song.composer(), tag);
@@ -609,8 +609,8 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
SetUnsyncLyricsFrame(song.lyrics(), tag);
}
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
TagLib::MP4::Tag *tag = file->tag();
else if (TagLib::MP4::File *file_mp4 = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
TagLib::MP4::Tag *tag = file_mp4->tag();
tag->setItem("disk", TagLib::MP4::Item(song.disc() <= 0 -1 ? 0 : song.disc(), 0));
tag->setItem("\251wrt", TagLib::StringList(song.composer().c_str()));
tag->setItem("\251grp", TagLib::StringList(song.grouping().c_str()));

View File

@@ -26,28 +26,18 @@
#include <QByteArray>
#include <QString>
#include <taglib/tstring.h>
#include <taglib/fileref.h>
#include <taglib/xiphcomment.h>
#include <taglib/apetag.h>
#include <taglib/apefile.h>
#include <taglib/id3v2tag.h>
#include "tagreadermessages.pb.h"
class QTextCodec;
#ifndef USE_SYSTEM_TAGLIB
namespace Strawberry_TagLib {
#endif
namespace TagLib {
class FileRef;
class String;
namespace ID3v2 {
class Tag;
class PopularimeterFrame;
}
}
#ifndef USE_SYSTEM_TAGLIB
}
using namespace Strawberry_TagLib;
#endif

View File

@@ -1,4 +1,5 @@
include_directories(${PROTOBUF_INCLUDE_DIRS})
cmake_minimum_required(VERSION 3.0)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
@@ -7,29 +8,20 @@ include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${CMAKE_BINARY_DIR}/src)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
link_directories(${PROTOBUF_LIBRARY_DIRS})
include_directories(${PROTOBUF_INCLUDE_DIRS})
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
endif()
link_directories(${TAGLIB_LIBRARY_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS})
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
set(SOURCES
main.cpp
tagreaderworker.cpp
)
set(SOURCES main.cpp tagreaderworker.cpp)
qt5_wrap_cpp(MOC ${HEADERS})
qt5_add_resources(QRC data/data.qrc)
add_executable(strawberry-tagreader
${SOURCES}
${MOC}
${QRC}
)
add_executable(strawberry-tagreader ${SOURCES} ${MOC} ${QRC})
target_link_libraries(strawberry-tagreader
${TAGLIB_LIBRARIES}
@@ -40,16 +32,11 @@ target_link_libraries(strawberry-tagreader
)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(strawberry-tagreader
execinfo
)
target_link_libraries(strawberry-tagreader execinfo)
endif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
if(APPLE)
target_link_libraries(strawberry-tagreader
/System/Library/Frameworks/Foundation.framework
)
target_link_libraries(strawberry-tagreader /System/Library/Frameworks/Foundation.framework)
endif(APPLE)
install(TARGETS strawberry-tagreader RUNTIME DESTINATION bin)

View File

@@ -1,5 +1,5 @@
name: strawberry
version: '0.6.8+git'
version: '0.6.10+git'
summary: music player and collection organizer
description: |
Strawberry is a music player and collection organizer.

View File

@@ -1,49 +1,16 @@
# 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/>.
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
if(APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
endif()
option(BUILD_WERROR "Build with -Werror" OFF)
if(BUILD_WERROR)
if (LINUX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif (LINUX)
endif(BUILD_WERROR)
cmake_minimum_required(VERSION 3.0)
if(HAVE_TRANSLATIONS)
include(../cmake/Translations.cmake)
endif(HAVE_TRANSLATIONS)
# Set up definitions and paths
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-tagreader)
include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_USE_QSTRINGBUILDER)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
include_directories(${CMAKE_BINARY_DIR})
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
include_directories(${GLIB_INCLUDE_DIRS})
@@ -69,10 +36,6 @@ if(HAVE_GSTREAMER)
include_directories(${GSTREAMER_PBUTILS_INCLUDE_DIRS})
endif(HAVE_GSTREAMER)
if(HAVE_PHONON)
include_directories(${PHONON_INCLUDE_DIRS})
endif(HAVE_PHONON)
if(HAVE_CHROMAPRINT)
link_directories(${CHROMAPRINT_LIBRARY_DIRS})
include_directories(${CHROMAPRINT_INCLUDE_DIRS})
@@ -96,10 +59,6 @@ if(HAVE_LIBMTP)
include_directories(${LIBMTP_INCLUDE_DIRS})
endif(HAVE_LIBMTP)
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-tagreader)
include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
set(SOURCES
core/mainwindow.cpp
core/application.cpp
@@ -227,6 +186,7 @@ set(SOURCES
covermanager/musicbrainzcoverprovider.cpp
covermanager/discogscoverprovider.cpp
covermanager/deezercoverprovider.cpp
covermanager/qobuzcoverprovider.cpp
lyrics/lyricsproviders.cpp
lyrics/lyricsprovider.cpp
@@ -254,6 +214,7 @@ set(SOURCES
dialogs/errordialog.cpp
dialogs/edittagdialog.cpp
dialogs/trackselectiondialog.cpp
dialogs/addstreamdialog.cpp
widgets/autoexpandingtreeview.cpp
widgets/busyindicator.cpp
@@ -286,7 +247,6 @@ set(SOURCES
internet/internetservices.cpp
internet/internetservice.cpp
internet/internetplaylistitem.cpp
internet/internetsearch.cpp
internet/internetsearchview.cpp
internet/internetsearchmodel.cpp
internet/internetsearchsortmodel.cpp
@@ -413,6 +373,7 @@ set(HEADERS
covermanager/musicbrainzcoverprovider.h
covermanager/discogscoverprovider.h
covermanager/deezercoverprovider.h
covermanager/qobuzcoverprovider.h
lyrics/lyricsproviders.h
lyrics/lyricsprovider.h
@@ -440,6 +401,7 @@ set(HEADERS
dialogs/console.h
dialogs/edittagdialog.h
dialogs/trackselectiondialog.h
dialogs/addstreamdialog.h
widgets/autoexpandingtreeview.h
widgets/busyindicator.h
@@ -472,7 +434,6 @@ set(HEADERS
internet/internetservices.h
internet/internetservice.h
internet/internetsongmimedata.h
internet/internetsearch.h
internet/internetsearchview.h
internet/internetsearchmodel.h
internet/localredirectserver.h
@@ -539,6 +500,7 @@ set(UI
dialogs/console.ui
dialogs/edittagdialog.ui
dialogs/trackselectiondialog.ui
dialogs/addstreamdialog.ui
widgets/trackslider.ui
widgets/osdpretty.ui
@@ -622,12 +584,6 @@ optional_source(HAVE_VLC
HEADERS engine/vlcengine.h
)
# Phonon
optional_source(HAVE_PHONON
SOURCES engine/phononengine.cpp
HEADERS engine/phononengine.h
)
# DBUS and MPRIS - Unix specific
if(UNIX AND HAVE_DBUS)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
@@ -923,6 +879,29 @@ optional_source(HAVE_SUBSONIC
settings/subsonicsettingspage.ui
)
optional_source(HAVE_TIDAL
SOURCES
tidal/tidalservice.cpp
tidal/tidalurlhandler.cpp
tidal/tidalbaserequest.cpp
tidal/tidalrequest.cpp
tidal/tidalstreamurlrequest.cpp
tidal/tidalfavoriterequest.cpp
settings/tidalsettingspage.cpp
covermanager/tidalcoverprovider.cpp
HEADERS
tidal/tidalservice.h
tidal/tidalurlhandler.h
tidal/tidalbaserequest.h
tidal/tidalrequest.h
tidal/tidalstreamurlrequest.h
tidal/tidalfavoriterequest.h
settings/tidalsettingspage.h
covermanager/tidalcoverprovider.h
UI
settings/tidalsettingspage.ui
)
# Moodbar
optional_source(HAVE_MOODBAR
SOURCES
@@ -1034,10 +1013,6 @@ if(HAVE_VLC)
target_link_libraries(strawberry_lib ${LIBVLC_LIBRARIES})
endif()
if(HAVE_PHONON)
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
endif()
if(HAVE_LIBGPOD)
target_link_libraries(strawberry_lib ${LIBGPOD_LIBRARIES})
endif(HAVE_LIBGPOD)
@@ -1051,11 +1026,7 @@ if(HAVE_AUDIOCD)
endif(HAVE_AUDIOCD)
if(HAVE_IMOBILEDEVICE)
target_link_libraries(strawberry_lib
${LIBIMOBILEDEVICE_LIBRARIES}
${LIBPLIST_LIBRARIES}
${LIBUSBMUXD_LIBRARIES}
)
target_link_libraries(strawberry_lib ${LIBIMOBILEDEVICE_LIBRARIES} ${LIBPLIST_LIBRARIES} ${LIBUSBMUXD_LIBRARIES})
link_directories(${LIBIMOBILEDEVICE_LIBRARY_DIRS})
link_directories(${LIBUSBMUXD_LIBRARY_DIRS})
endif(HAVE_IMOBILEDEVICE)
@@ -1083,7 +1054,6 @@ if (APPLE)
"-framework ScriptingBridge"
)
target_link_libraries(strawberry_lib ${SPMEDIAKEYTAP_LIBRARIES})
if (HAVE_SPARKLE)
include_directories(${SPARKLE}/Headers)
target_link_libraries(strawberry_lib ${SPARKLE})
@@ -1106,9 +1076,9 @@ if (UNIX AND NOT APPLE)
endif ()
endif ()
if(NOT USE_SYSTEM_SINGLEAPPLICATION)
add_dependencies(strawberry_lib ${SINGLEAPPLICATION_LIBRARIES} ${SINGLECOREAPPLICATION_LIBRARIES})
endif()
if (NOT USE_SYSTEM_SINGLEAPPLICATION)
add_dependencies(strawberry_lib ${SINGLEAPPLICATION_LIBRARIES} ${SINGLECOREAPPLICATION_LIBRARIES})
endif ()
###############################################################################
@@ -1136,9 +1106,7 @@ if(FREEBSD)
target_link_libraries(strawberry execinfo)
endif()
target_link_libraries(strawberry
strawberry_lib
)
target_link_libraries(strawberry strawberry_lib)
# macdeploy.py relies on the blob being built first.
add_dependencies(strawberry strawberry-tagreader)

View File

@@ -185,8 +185,8 @@ void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_fram
if (fade_intensity_[x] > 0) {
const uint offset = --fade_intensity_[x];
const uint y = y_ + (fade_pos_[x] * (kHeight + 1));
canvas_painter.drawPixmap(x * (kWidth + 1), y, fade_bars_[offset], 0, 0, kWidth, height() - y);
const uint y2 = y_ + (fade_pos_[x] * (kHeight + 1));
canvas_painter.drawPixmap(x * (kWidth + 1), y2, fade_bars_[offset], 0, 0, kWidth, height() - y2);
}
if (fade_intensity_[x] == 0) fade_pos_[x] = rows_;
@@ -237,7 +237,8 @@ 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);
QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
class OutputOnExit {
public:
@@ -344,18 +345,18 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
p.fillRect(0, y * (kHeight + 1), kWidth, kHeight, QColor(r + static_cast<int>(dr * y), g + static_cast<int>(dg * y), b + static_cast<int>(db * y)));
{
const QColor bg = palette().color(QPalette::Background).darker(112);
const QColor bg2 = palette().color(QPalette::Background).darker(112);
// make a complimentary fadebar colour
// TODO dark is not always correct, dumbo!
int h, s, v;
palette().color(QPalette::Background).darker(150).getHsv(&h, &s, &v);
const QColor fg(QColor::fromHsv(h + 120, s, v));
const QColor fg2(QColor::fromHsv(h + 120, s, v));
const double dr = fg.red() - bg.red();
const double dg = fg.green() - bg.green();
const double db = fg.blue() - bg.blue();
const int r = bg.red(), g = bg.green(), b = bg.blue();
const double dr2 = fg2.red() - bg2.red();
const double dg2 = fg2.green() - bg2.green();
const double db2 = fg2.blue() - bg2.blue();
const int r2 = bg2.red(), g2 = bg2.green(), b2 = bg2.blue();
// Precalculate all fade-bar pixmaps
for (uint y = 0; y < kFadeSize; ++y) {
@@ -363,7 +364,7 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
QPainter f(&fade_bars_[y]);
for (int z = 0; static_cast<uint>(z) < rows_; ++z) {
const double Y = 1.0 - (log10(kFadeSize - y) / log10(kFadeSize));
f.fillRect(0, z * (kHeight + 1), kWidth, kHeight, QColor(r + static_cast<int>(dr * Y), g + static_cast<int>(dg * Y), b + static_cast<int>(db * Y)));
f.fillRect(0, z * (kHeight + 1), kWidth, kHeight, QColor(r2 + static_cast<int>(dr2 * Y), g2 + static_cast<int>(dg2 * Y), b2 + static_cast<int>(db2 * Y)));
}
}
}

View File

@@ -75,20 +75,20 @@ class RainbowAnalyzer : public Analyzer::Base {
static RainbowType rainbowtype;
inline QRect SourceRect(RainbowType rainbowtype) const {
return QRect(0, kHeight[rainbowtype] * frame_, kWidth[rainbowtype], kHeight[rainbowtype]);
inline QRect SourceRect(RainbowType _rainbowtype) const {
return QRect(0, kHeight[_rainbowtype] * frame_, kWidth[_rainbowtype], kHeight[_rainbowtype]);
}
inline QRect SleepingSourceRect(RainbowType rainbowtype) const {
return QRect(0, kHeight[rainbowtype] * kFrameCount[rainbowtype], kWidth[rainbowtype], kSleepingHeight[rainbowtype]);
inline QRect SleepingSourceRect(RainbowType _rainbowtype) const {
return QRect(0, kHeight[_rainbowtype] * kFrameCount[_rainbowtype], kWidth[_rainbowtype], kSleepingHeight[_rainbowtype]);
}
inline QRect DestRect(RainbowType rainbowtype) const {
return QRect(width() - kWidth[rainbowtype], (height() - kHeight[rainbowtype]) / 2, kWidth[rainbowtype], kHeight[rainbowtype]);
inline QRect DestRect(RainbowType _rainbowtype) const {
return QRect(width() - kWidth[_rainbowtype], (height() - kHeight[_rainbowtype]) / 2, kWidth[_rainbowtype], kHeight[_rainbowtype]);
}
inline QRect SleepingDestRect(RainbowType rainbowtype) const {
return QRect(width() - kWidth[rainbowtype], (height() - kSleepingHeight[rainbowtype]) / 2, kWidth[rainbowtype], kSleepingHeight[rainbowtype]);
inline QRect SleepingDestRect(RainbowType _rainbowtype) const {
return QRect(width() - kWidth[_rainbowtype], (height() - kSleepingHeight[_rainbowtype]) / 2, kWidth[_rainbowtype], kSleepingHeight[_rainbowtype]);
}
private:

View File

@@ -467,7 +467,7 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
continue;
}
else if (song.song_id() != -1) { // Song has a unique id, check if the song exists.
else if (!song.song_id().isEmpty()) { // Song has a unique id, check if the song exists.
// Get the previous song data first
Song old_song(GetSongBySongId(song.song_id()));
@@ -822,35 +822,29 @@ SongList CollectionBackend::GetSongsByUrl(const QUrl &url) {
}
Song CollectionBackend::GetSongBySongId(int song_id) {
Song CollectionBackend::GetSongBySongId(const QString &song_id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
return GetSongBySongId(song_id, db);
}
SongList CollectionBackend::GetSongsBySongId(const QList<int> &song_ids) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QStringList str_song_ids;
for (int song_id : song_ids) {
str_song_ids << QString::number(song_id);
}
return GetSongsBySongId(str_song_ids, db);
}
SongList CollectionBackend::GetSongsBySongId(const QStringList &song_ids) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
return GetSongsBySongId(song_ids, db);
}
Song CollectionBackend::GetSongBySongId(int song_id, QSqlDatabase &db) {
SongList list = GetSongsBySongId(QStringList() << QString::number(song_id), db);
Song CollectionBackend::GetSongBySongId(const QString &song_id, QSqlDatabase &db) {
SongList list = GetSongsBySongId(QStringList() << song_id, db);
if (list.isEmpty()) return Song();
return list.first();
}
SongList CollectionBackend::GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db) {
@@ -1001,7 +995,7 @@ void CollectionBackend::UpdateCompilations(QSqlQuery &find_song, QSqlQuery &upda
}
CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, bool compilation, const QueryOptions &opt) {
CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt) {
AlbumList ret;
@@ -1009,7 +1003,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
query.SetColumnSpec("album, artist, albumartist, compilation, compilation_detected, art_automatic, art_manual, url");
query.SetOrderBy("album");
if (compilation) {
if (compilation_required) {
query.AddCompilationRequirement(true);
}
else if (!artist.isEmpty()) {
@@ -1026,11 +1020,11 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
QString last_artist;
QString last_album_artist;
while (query.Next()) {
bool compilation = query.Value(3).toBool() | query.Value(4).toBool();
bool is_compilation = query.Value(3).toBool() | query.Value(4).toBool();
Album info;
info.artist = compilation ? QString() : query.Value(1).toString();
info.album_artist = compilation ? QString() : query.Value(2).toString();
info.artist = is_compilation ? QString() : query.Value(1).toString();
info.album_artist = is_compilation ? QString() : query.Value(2).toString();
info.album_name = query.Value(0).toString();
info.first_url = QUrl::fromEncoded(query.Value(7).toByteArray());

View File

@@ -141,10 +141,10 @@ class CollectionBackend : public CollectionBackendInterface {
void UpdateTotalArtistCountAsync();
void UpdateTotalAlbumCountAsync();
SongList FindSongsInDirectory(int id);
SubdirectoryList SubdirsInDirectory(int id);
SongList FindSongsInDirectory(const int id);
SubdirectoryList SubdirsInDirectory(const int id);
DirectoryList GetAllDirectories();
void ChangeDirPath(int id, const QString &old_path, const QString &new_path);
void ChangeDirPath(const int id, const QString &old_path, const QString &new_path);
QStringList GetAll(const QString &column, const QueryOptions &opt = QueryOptions());
QStringList GetAllArtists(const QueryOptions &opt = QueryOptions());
@@ -161,7 +161,7 @@ class CollectionBackend : public CollectionBackendInterface {
void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url);
Album GetAlbumArt(const QString &artist, const QString &albumartist, const QString &album);
Song GetSongById(int id);
Song GetSongById(const int id);
SongList GetSongsById(const QList<int> &ids);
SongList GetSongsById(const QStringList &ids);
SongList GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column);
@@ -175,14 +175,13 @@ class CollectionBackend : public CollectionBackendInterface {
bool ExecQuery(CollectionQuery *q);
SongList ExecCollectionQuery(CollectionQuery *query);
void IncrementPlayCountAsync(int id);
void IncrementSkipCountAsync(int id, float progress);
void ResetStatisticsAsync(int id);
void IncrementPlayCountAsync(const int id);
void IncrementSkipCountAsync(const int id, const float progress);
void ResetStatisticsAsync(const int id);
void DeleteAll();
Song GetSongBySongId(int song_id);
SongList GetSongsBySongId(const QList<int> &song_ids);
Song GetSongBySongId(const QString &song_id);
SongList GetSongsBySongId(const QStringList &song_ids);
Song::Source Source() const;
@@ -200,10 +199,10 @@ class CollectionBackend : public CollectionBackendInterface {
void AddOrUpdateSubdirs(const SubdirectoryList &subdirs);
void UpdateCompilations();
void UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url);
void ForceCompilation(const QString &album, const QList<QString> &artists, bool on);
void IncrementPlayCount(int id);
void IncrementSkipCount(int id, float progress);
void ResetStatistics(int id);
void ForceCompilation(const QString &album, const QList<QString> &artists, const bool on);
void IncrementPlayCount(const int id);
void IncrementSkipCount(const int id, const float progress);
void ResetStatistics(const int id);
void SongPathChanged(const Song &song, const QFileInfo &new_file);
signals:
@@ -216,9 +215,9 @@ class CollectionBackend : public CollectionBackendInterface {
void DatabaseReset();
void TotalSongCountUpdated(int total);
void TotalArtistCountUpdated(int total);
void TotalAlbumCountUpdated(int total);
void TotalSongCountUpdated(const int total);
void TotalArtistCountUpdated(const int total);
void TotalAlbumCountUpdated(const int total);
void ExitFinished();
@@ -234,14 +233,14 @@ class CollectionBackend : public CollectionBackendInterface {
};
void UpdateCompilations(QSqlQuery &find_song, QSqlQuery &update_song, SongList &deleted_songs, SongList &added_songs, const QUrl &url, const bool compilation_detected);
AlbumList GetAlbums(const QString &artist, const QString &album_artist, bool compilation = false, const QueryOptions &opt = QueryOptions());
AlbumList GetAlbums(const QString &artist, bool compilation, const QueryOptions &opt = QueryOptions());
SubdirectoryList SubdirsInDirectory(int id, QSqlDatabase &db);
AlbumList GetAlbums(const QString &artist, const QString &album_artist, const bool compilation_required = false, const QueryOptions &opt = QueryOptions());
AlbumList GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt = QueryOptions());
SubdirectoryList SubdirsInDirectory(const int id, QSqlDatabase &db);
Song GetSongById(int id, QSqlDatabase &db);
Song GetSongById(const int id, QSqlDatabase &db);
SongList GetSongsById(const QStringList &ids, QSqlDatabase &db);
Song GetSongBySongId(int song_id, QSqlDatabase &db);
Song GetSongBySongId(const QString &song_id, QSqlDatabase &db);
SongList GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db);
private:

View File

@@ -34,8 +34,6 @@
#include "collectionbackend.h"
#include "collectiondirectorymodel.h"
using std::shared_ptr;
CollectionDirectoryModel::CollectionDirectoryModel(CollectionBackend *backend, QObject *parent)
: QStandardItemModel(parent),
dir_icon_(IconLoader::Load("document-open-folder")),

View File

@@ -297,6 +297,7 @@ void CollectionFilterWidget::SetCollectionModel(CollectionModel *model) {
}
void CollectionFilterWidget::GroupByClicked(QAction *action) {
if (action->property("group_by").isNull()) {
group_by_dialog_->show();
return;
@@ -304,6 +305,7 @@ void CollectionFilterWidget::GroupByClicked(QAction *action) {
CollectionModel::Grouping g = action->property("group_by").value<CollectionModel::Grouping>();
model_->SetGroupBy(g);
}
void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping &g) {

View File

@@ -37,13 +37,13 @@ class CollectionItem : public SimpleTreeItem<CollectionItem> {
Type_LoadingIndicator,
};
explicit CollectionItem(SimpleTreeModel<CollectionItem> *model)
: SimpleTreeItem<CollectionItem>(Type_Root, model),
explicit CollectionItem(SimpleTreeModel<CollectionItem> *_model)
: SimpleTreeItem<CollectionItem>(Type_Root, _model),
container_level(-1),
compilation_artist_node_(nullptr) {}
explicit CollectionItem(Type type, CollectionItem *parent = nullptr)
: SimpleTreeItem<CollectionItem>(type, parent),
explicit CollectionItem(Type _type, CollectionItem *_parent = nullptr)
: SimpleTreeItem<CollectionItem>(_type, _parent),
container_level(-1),
compilation_artist_node_(nullptr) {}

View File

@@ -66,16 +66,15 @@
#include "playlist/playlistmanager.h"
#include "playlist/songmimedata.h"
#include "covermanager/albumcoverloader.h"
#include "covermanager/albumcoverloaderresult.h"
#include "settings/collectionsettingspage.h"
using std::bind;
using std::sort;
using std::placeholders::_1;
using std::placeholders::_2;
const char *CollectionModel::kSavedGroupingsSettingsGroup = "SavedGroupings";
const int CollectionModel::kPrettyCoverSize = 32;
const char *CollectionModel::kPixmapDiskCacheDir = "/pixmapcache";
const char *CollectionModel::kPixmapDiskCacheDir = "pixmapcache";
QNetworkDiskCache *CollectionModel::sIconCache = nullptr;
@@ -115,17 +114,18 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
cover_loader_options_.pad_output_image_ = true;
cover_loader_options_.scale_output_image_ = true;
if (app_)
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(AlbumCoverLoaded(quint64, QUrl, QImage)));
if (app_) {
connect(app_->album_cover_loader(), SIGNAL(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)));
}
QIcon nocover = IconLoader::Load("cdcase");
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
//no_cover_icon_ = QPixmap(":/pictures/noalbumart.png").scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
// When running under gdb, all calls to this constructor came from the same thread.
// If this ever changes, these two lines might need to be protected by a mutex.
if (sIconCache == nullptr)
if (sIconCache == nullptr) {
sIconCache = new QNetworkDiskCache(this);
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/" + kPixmapDiskCacheDir);
}
connect(backend_, SIGNAL(SongsDiscovered(SongList)), SLOT(SongsDiscovered(SongList)));
connect(backend_, SIGNAL(SongsDeleted(SongList)), SLOT(SongsDeleted(SongList)));
@@ -187,16 +187,16 @@ void CollectionModel::ReloadSettings() {
use_disk_cache_ = s.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool();
if (!use_disk_cache_) {
sIconCache->clear();
}
QPixmapCache::setCacheLimit(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024);
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + kPixmapDiskCacheDir);
sIconCache->setMaximumCacheSize(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit));
QPixmapCache::setCacheLimit(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit) / 1024);
sIconCache->setMaximumCacheSize(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit, CollectionSettingsPage::kSettingsDiskCacheSizeDefault));
s.endGroup();
if (!use_disk_cache_) {
ClearDiskCache();
}
}
void CollectionModel::Init(bool async) {
@@ -588,10 +588,10 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
if (use_disk_cache_) {
std::unique_ptr<QIODevice> cache(sIconCache->data(QUrl(cache_key)));
if (cache) {
QImage cached_pixmap;
if (cached_pixmap.load(cache.get(), "XPM")) {
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_pixmap));
return QPixmap::fromImage(cached_pixmap);
QImage cached_image;
if (cached_image.load(cache.get(), "XPM")) {
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_image));
return QPixmap::fromImage(cached_image);
}
}
}
@@ -613,9 +613,7 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
}
void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
Q_UNUSED(cover_url);
void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result) {
if (!pending_art_.contains(id)) return;
@@ -628,26 +626,26 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url,
pending_cache_keys_.remove(cache_key);
// Insert this image in the cache.
if (image.isNull()) {
if (result.image_scaled.isNull()) {
// Set the no_cover image so we don't continually try to load art.
QPixmapCache::insert(cache_key, no_cover_icon_);
}
else {
QPixmap image_pixmap;
image_pixmap = QPixmap::fromImage(image);
image_pixmap = QPixmap::fromImage(result.image_scaled);
QPixmapCache::insert(cache_key, image_pixmap);
}
// If we have a valid cover not already in the disk cache
if (use_disk_cache_) {
std::unique_ptr<QIODevice> cached_img(sIconCache->data(QUrl(cache_key)));
if (!cached_img && !image.isNull()) {
if (!cached_img && !result.image_scaled.isNull()) {
QNetworkCacheMetaData item_metadata;
item_metadata.setSaveToDisk(true);
item_metadata.setUrl(QUrl(cache_key));
QIODevice* cache = sIconCache->prepare(item_metadata);
QIODevice *cache = sIconCache->prepare(item_metadata);
if (cache) {
image.save(cache, "XPM");
result.image_scaled.save(cache, "XPM");
sIconCache->insert(cache);
}
}
@@ -1541,9 +1539,9 @@ bool CollectionModel::CompareItems(const CollectionItem *a, const CollectionItem
}
int CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id) const {
int CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const int cache_size_default) const {
int size = s->value(size_id, 80).toInt();
int size = s->value(size_id, cache_size_default).toInt();
int unit = s->value(size_unit_id, CollectionSettingsPage::CacheSizeUnit::CacheSizeUnit_MB).toInt() + 1;
do {

View File

@@ -41,16 +41,17 @@
#include <QImage>
#include <QIcon>
#include <QPixmap>
#include <QNetworkDiskCache>
#include "core/simpletreemodel.h"
#include "core/song.h"
#include "covermanager/albumcoverloader.h"
#include "collectionquery.h"
#include "collectionitem.h"
#include "sqlrow.h"
#include "covermanager/albumcoverloaderoptions.h"
class QSettings;
class QNetworkDiskCache;
class Application;
class CollectionBackend;
@@ -176,7 +177,9 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
static QString SortTextForYear(int year);
static QString SortTextForBitrate(int bitrate);
signals:
quint64 icon_cache_disk_size() { return sIconCache->cacheSize(); }
signals:
void TotalSongCountUpdated(int count);
void TotalArtistCountUpdated(int count);
void TotalAlbumCountUpdated(int count);
@@ -210,7 +213,7 @@ signals:
// Called after ResetAsync
void ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult> future);
void AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result);
private:
// Provides some optimisations for loading the list of items in the root.
@@ -247,7 +250,7 @@ signals:
QVariant AlbumIcon(const QModelIndex &idx);
QVariant data(const CollectionItem *item, int role) const;
bool CompareItems(const CollectionItem *a, const CollectionItem *b) const;
int MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id) const;
int MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const int cache_size_default) const;
private:
CollectionBackend *backend_;

View File

@@ -43,20 +43,33 @@ void CollectionPlaylistItem::Reload() {
}
bool CollectionPlaylistItem::InitFromQuery(const SqlRow &query) {
// Rows from the songs tables come first
song_.InitFromQuery(query, true);
song_.set_source(Song::Source_Collection);
return song_.is_valid();
}
QVariant CollectionPlaylistItem::DatabaseValue(DatabaseColumn column) const {
switch (column) {
case Column_CollectionId: return song_.id();
default: return PlaylistItem::DatabaseValue(column);
}
}
Song CollectionPlaylistItem::Metadata() const {
if (HasTemporaryMetadata()) return temp_metadata_;
return song_;
}
void CollectionPlaylistItem::SetArtManual(const QUrl &cover_url) {
song_.set_art_manual(cover_url);
temp_metadata_.set_art_manual(cover_url);
}

View File

@@ -46,6 +46,8 @@ class CollectionPlaylistItem : public PlaylistItem {
bool IsLocalCollectionItem() const { return true; }
void SetArtManual(const QUrl &cover_url);
protected:
QVariant DatabaseValue(DatabaseColumn column) const;
Song DatabaseSongMetadata() const { return Song(Song::Source_Collection); }

View File

@@ -64,8 +64,6 @@
#include "organise/organisedialog.h"
#include "settings/collectionsettingspage.h"
using std::unique_ptr;
CollectionView::CollectionView(QWidget *parent)
: AutoExpandingTreeView(parent),
app_(nullptr),
@@ -463,11 +461,11 @@ void CollectionView::ShowInVarious(bool on) {
void CollectionView::Load() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
mime_data->clear_first_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->clear_first_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}
@@ -479,31 +477,31 @@ void CollectionView::AddToPlaylist() {
void CollectionView::AddToPlaylistEnqueue() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
mime_data->enqueue_now_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData* mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->enqueue_now_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}
void CollectionView::AddToPlaylistEnqueueNext() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
mime_data->enqueue_next_now_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->enqueue_next_now_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}
void CollectionView::OpenInNewPlaylist() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
mime_data->open_in_new_playlist_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData* mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->open_in_new_playlist_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}

View File

@@ -47,8 +47,6 @@ class CollectionFilterWidget;
class EditTagDialog;
class OrganiseDialog;
using std::unique_ptr;
class CollectionView : public AutoExpandingTreeView {
Q_OBJECT

View File

@@ -650,7 +650,7 @@ void CollectionWatcher::AddWatch(const Directory &dir, const QString &path) {
if (!QFile::exists(path)) return;
connect(fs_watcher_, SIGNAL(PathChanged(const QString&)), this, SLOT(DirectoryChanged(const QString&)), Qt::UniqueConnection);
connect(fs_watcher_, SIGNAL(PathChanged(QString)), this, SLOT(DirectoryChanged(QString)), Qt::UniqueConnection);
fs_watcher_->AddPath(path);
subdir_mapping_[path] = dir;

View File

@@ -45,10 +45,10 @@
#cmakedefine HAVE_GSTREAMER
#cmakedefine HAVE_VLC
#cmakedefine HAVE_XINE
#cmakedefine HAVE_PHONON
#cmakedefine XINE_ANALYZER
#cmakedefine HAVE_SUBSONIC
#cmakedefine HAVE_TIDAL
#cmakedefine HAVE_MOODBAR

View File

@@ -33,17 +33,22 @@
#include <QTimeLine>
#include <QPainter>
#include <QSizePolicy>
#include <QMenu>
#include <QContextMenuEvent>
#include <QPaintEvent>
#include "covermanager/albumcoverchoicecontroller.h"
#include "covermanager/albumcoverloader.h"
#include "contextview.h"
#include "contextalbum.h"
const int ContextAlbum::kWidgetSpacing = 40;
ContextAlbum::ContextAlbum(QWidget *parent) :
QWidget(parent),
menu_(new QMenu(this)),
context_view_(nullptr),
album_cover_choice_controller_(nullptr),
downloading_covers_(false),
timeline_fade_(new QTimeLine(1000, this)),
@@ -57,18 +62,39 @@ ContextAlbum::ContextAlbum(QWidget *parent) :
cover_loader_options_.desired_height_ = 600;
cover_loader_options_.pad_output_image_ = true;
cover_loader_options_.scale_output_image_ = true;
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_strawberry_));
QPair<QImage, QImage> images = AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_strawberry_);
pixmap_current_ = QPixmap::fromImage(images.first);
connect(timeline_fade_, SIGNAL(valueChanged(qreal)), SLOT(FadePreviousTrack(qreal)));
timeline_fade_->setDirection(QTimeLine::Backward); // 1.0 -> 0.0
}
void ContextAlbum::Init(AlbumCoverChoiceController *album_cover_choice_controller) {
void ContextAlbum::Init(ContextView *context_view, AlbumCoverChoiceController *album_cover_choice_controller) {
context_view_ = context_view;
album_cover_choice_controller_ = album_cover_choice_controller;
connect(album_cover_choice_controller_, SIGNAL(AutomaticCoverSearchDone()), this, SLOT(AutomaticCoverSearchDone()));
QList<QAction*> cover_actions = album_cover_choice_controller_->GetAllActions();
cover_actions.append(album_cover_choice_controller_->search_cover_auto_action());
menu_->addActions(cover_actions);
menu_->addSeparator();
}
void ContextAlbum::contextMenuEvent(QContextMenuEvent *e) {
if (menu_ && image_original_ != image_strawberry_) menu_->popup(mapToGlobal(e->pos()));
}
void ContextAlbum::mouseDoubleClickEvent(QMouseEvent *e) {
// Same behaviour as right-click > Show Fullsize
if (image_original_ != image_strawberry_ && e->button() == Qt::LeftButton && context_view_->song_playing().is_valid()) {
album_cover_choice_controller_->ShowCover(context_view_->song_playing(), image_original_);
}
}
void ContextAlbum::paintEvent(QPaintEvent*) {
@@ -89,7 +115,7 @@ void ContextAlbum::DrawImage(QPainter *p) {
if (width() != prev_width_) {
cover_loader_options_.desired_height_ = width() - kWidgetSpacing;
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_));
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_).first);
prev_width_ = width();
}
@@ -118,7 +144,7 @@ void ContextAlbum::FadePreviousTrack(const qreal value) {
void ContextAlbum::ScaleCover() {
cover_loader_options_.desired_height_ = width() - kWidgetSpacing;
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_));
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_).first);
prev_width_ = width();
update();
@@ -162,7 +188,7 @@ void ContextAlbum::SearchCoverInProgress() {
// Show a spinner animation
spinner_animation_.reset(new QMovie(":/pictures/spinner.gif", QByteArray(), this));
connect(spinner_animation_.get(), SIGNAL(updated(const QRect&)), SLOT(update()));
connect(spinner_animation_.get(), SIGNAL(updated(QRect)), SLOT(update()));
spinner_animation_->start();
update();

View File

@@ -34,10 +34,12 @@
#include "covermanager/albumcoverloaderoptions.h"
class QMenu;
class QTimeLine;
class QPainter;
class QPaintEvent;
class ContextView;
class AlbumCoverChoiceController;
class ContextAlbum : public QWidget {
@@ -46,11 +48,13 @@ class ContextAlbum : public QWidget {
public:
explicit ContextAlbum(QWidget *parent = nullptr);
void Init(AlbumCoverChoiceController *album_cover_choice_controller);
void Init(ContextView *context_view, AlbumCoverChoiceController *album_cover_choice_controller);
void SetImage(QImage image = QImage());
protected:
void paintEvent(QPaintEvent*);
void contextMenuEvent(QContextMenuEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
private:
void DrawImage(QPainter *p);
@@ -67,6 +71,10 @@ class ContextAlbum : public QWidget {
private:
static const int kWidgetSpacing;
private:
QMenu *menu_;
ContextView *context_view_;
AlbumCoverChoiceController *album_cover_choice_controller_;
AlbumCoverLoaderOptions cover_loader_options_;
bool downloading_covers_;

View File

@@ -48,11 +48,11 @@
#include "playlist/playlistmanager.h"
#include "playlist/songmimedata.h"
#include "covermanager/albumcoverloader.h"
#include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h"
#include "contextalbumsmodel.h"
using std::bind;
using std::sort;
using std::placeholders::_1;
using std::placeholders::_2;
@@ -71,7 +71,7 @@ ContextAlbumsModel::ContextAlbumsModel(CollectionBackend *backend, Application *
cover_loader_options_.pad_output_image_ = true;
cover_loader_options_.scale_output_image_ = true;
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(AlbumCoverLoaded(quint64, QUrl, QImage)));
connect(app_->album_cover_loader(), SIGNAL(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)));
QIcon nocover = IconLoader::Load("cdcase");
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
@@ -146,9 +146,7 @@ QVariant ContextAlbumsModel::AlbumIcon(const QModelIndex &index) {
}
void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
Q_UNUSED(cover_url);
void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result) {
if (!pending_art_.contains(id)) return;
@@ -161,13 +159,13 @@ void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_ur
pending_cache_keys_.remove(cache_key);
// Insert this image in the cache.
if (image.isNull()) {
if (result.image_scaled.isNull()) {
// Set the no_cover image so we don't continually try to load art.
QPixmapCache::insert(cache_key, no_cover_icon_);
}
else {
QPixmap image_pixmap;
image_pixmap = QPixmap::fromImage(image);
image_pixmap = QPixmap::fromImage(result.image_scaled);
QPixmapCache::insert(cache_key, image_pixmap);
}

View File

@@ -45,6 +45,7 @@
#include "collection/collectionitem.h"
#include "collection/sqlrow.h"
#include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h"
class QMimeData;
@@ -99,7 +100,7 @@ class ContextAlbumsModel : public SimpleTreeModel<CollectionItem> {
void LazyPopulate(CollectionItem *item, bool signal);
private slots:
void AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result);
private:
QueryResult RunQuery(CollectionItem *parent);

View File

@@ -321,11 +321,11 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
void ContextAlbumsView::Load() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
mime_data->clear_first_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->clear_first_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}
@@ -337,21 +337,21 @@ void ContextAlbumsView::AddToPlaylist() {
void ContextAlbumsView::AddToPlaylistEnqueue() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
mime_data->enqueue_now_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->enqueue_now_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}
void ContextAlbumsView::OpenInNewPlaylist() {
QMimeData *data = model()->mimeData(selectedIndexes());
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
mime_data->open_in_new_playlist_ = true;
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->open_in_new_playlist_ = true;
}
emit AddToPlaylistSignal(data);
emit AddToPlaylistSignal(q_mimedata);
}

View File

@@ -28,6 +28,7 @@
#include <QUrl>
#include <QImage>
#include <QIcon>
#include <QFont>
#include <QSize>
#include <QSizePolicy>
#include <QMenu>
@@ -80,6 +81,7 @@ ContextView::ContextView(QWidget *parent) :
action_show_output_(nullptr),
action_show_albums_(nullptr),
action_show_lyrics_(nullptr),
action_search_lyrics_(nullptr),
layout_container_(new QVBoxLayout()),
widget_scrollarea_(new QWidget(this)),
layout_scrollarea_(new QVBoxLayout()),
@@ -124,6 +126,7 @@ ContextView::ContextView(QWidget *parent) :
label_device_icon_(new QLabel(this)),
label_engine_icon_(new QLabel(this)),
spacer_bottom_(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding)),
lyrics_tried_(false),
lyrics_id_(-1),
prev_width_(0)
{
@@ -144,9 +147,10 @@ ContextView::ContextView(QWidget *parent) :
widget_scrollarea_->setLayout(layout_scrollarea_);
widget_scrollarea_->setContentsMargins(0, 0, 0, 0);
label_top_->setWordWrap(true);
label_top_->setAlignment(Qt::AlignTop|Qt::AlignLeft);
label_top_->setWordWrap(true);
label_top_->setMinimumHeight(50);
label_top_->setContentsMargins(0, 0, 32, 0);
layout_scrollarea_->setObjectName("context-layout-scrollarea");
layout_scrollarea_->setContentsMargins(15, 15, 15, 15);
@@ -241,6 +245,8 @@ ContextView::ContextView(QWidget *parent) :
label_play_lyrics_->setWordWrap(true);
label_play_lyrics_->setTextInteractionFlags(Qt::TextSelectableByMouse);
label_play_albums_->setWordWrap(true);
layout_play_->setContentsMargins(5, 0, 40, 0);
layout_play_->addWidget(widget_play_output_);
layout_play_->addSpacerItem(spacer_play_output_);
@@ -252,6 +258,30 @@ ContextView::ContextView(QWidget *parent) :
layout_play_->addWidget(label_play_lyrics_);
layout_play_->addSpacerItem(spacer_play_bottom_);
labels_play_ << label_engine_title_
<< label_device_title_
<< label_filetype_title_
<< label_length_title_
<< label_samplerate_title_
<< label_bitdepth_title_
<< label_bitrate_title_
<< label_play_albums_
<< label_play_lyrics_;
labels_play_data_ << label_engine_icon_
<< label_engine_
<< label_device_
<< label_device_icon_
<< label_filetype_
<< label_length_
<< label_samplerate_
<< label_bitdepth_
<< label_bitrate_
<< label_play_albums_
<< label_play_lyrics_;
labels_play_all_ = labels_play_ << labels_play_data_;
QFontDatabase::addApplicationFont(":/fonts/HumongousofEternitySt.ttf");
connect(widget_album_, SIGNAL(FadeStopFinished()), SLOT(FadeStopFinished()));
@@ -270,14 +300,14 @@ void ContextView::Init(Application *app, CollectionView *collectionview, AlbumCo
collectionview_ = collectionview;
album_cover_choice_controller_ = album_cover_choice_controller;
widget_album_->Init(album_cover_choice_controller_);
widget_album_->Init(this, album_cover_choice_controller_);
widget_albums_->Init(app_);
lyrics_fetcher_ = new LyricsFetcher(app_->lyrics_providers(), this);
connect(collectionview_, SIGNAL(TotalSongCountUpdated_()), this, SLOT(UpdateNoSong()));
connect(collectionview_, SIGNAL(TotalArtistCountUpdated_()), this, SLOT(UpdateNoSong()));
connect(collectionview_, SIGNAL(TotalAlbumCountUpdated_()), this, SLOT(UpdateNoSong()));
connect(lyrics_fetcher_, SIGNAL(LyricsFetched(const quint64, const QString&, const QString&)), this, SLOT(UpdateLyrics(const quint64, const QString&, const QString&)));
connect(lyrics_fetcher_, SIGNAL(LyricsFetched(quint64, QString, QString)), this, SLOT(UpdateLyrics(quint64, QString, QString)));
AddActions();
@@ -299,22 +329,22 @@ void ContextView::AddActions() {
action_show_albums_ = new QAction(tr("Show albums by artist"), this);
action_show_albums_->setCheckable(true);
action_show_albums_->setChecked(true);
action_show_albums_->setChecked(false);
action_show_lyrics_ = new QAction(tr("Show song lyrics"), this);
action_show_lyrics_->setCheckable(true);
action_show_lyrics_->setChecked(false);
action_show_lyrics_->setChecked(true);
action_search_lyrics_ = new QAction(tr("Automatically search for song lyrics"), this);
action_search_lyrics_->setCheckable(true);
action_search_lyrics_->setChecked(true);
menu_->addAction(action_show_album_);
menu_->addAction(action_show_data_);
menu_->addAction(action_show_output_);
menu_->addAction(action_show_albums_);
menu_->addAction(action_show_lyrics_);
menu_->addSeparator();
QList<QAction*> cover_actions = album_cover_choice_controller_->GetAllActions();
cover_actions.append(album_cover_choice_controller_->search_cover_auto_action());
menu_->addActions(cover_actions);
menu_->addAction(action_search_lyrics_);
menu_->addSeparator();
ReloadSettings();
@@ -324,6 +354,7 @@ void ContextView::AddActions() {
connect(action_show_output_, SIGNAL(triggered()), this, SLOT(ActionShowOutput()));
connect(action_show_albums_, SIGNAL(triggered()), this, SLOT(ActionShowAlbums()));
connect(action_show_lyrics_, SIGNAL(triggered()), this, SLOT(ActionShowLyrics()));
connect(action_search_lyrics_, SIGNAL(triggered()), this, SLOT(ActionSearchLyrics()));
}
@@ -338,8 +369,15 @@ void ContextView::ReloadSettings() {
action_show_output_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ENGINE_AND_DEVICE], true).toBool());
action_show_albums_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ALBUMS_BY_ARTIST], false).toBool());
action_show_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS], true).toBool());
action_search_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SEARCH_LYRICS], true).toBool());
font_headline_ = s.value("font_headline", font().family()).toString();
font_normal_ = s.value("font_normal", font().family()).toString();
font_size_headline_ = s.value("font_size_headline", ContextSettingsPage::kDefaultFontSizeHeadline).toReal();
font_size_normal_ = s.value("font_size_normal", font().pointSizeF()).toReal();
s.endGroup();
UpdateFonts();
if (widget_stacked_->currentWidget() == widget_stop_) {
NoSong();
}
@@ -355,7 +393,7 @@ void ContextView::Stopped() {
song_playing_ = Song();
song_prev_ = Song();
lyrics_ = QString();
lyrics_.clear();
image_original_ = QImage();
widget_album_->SetImage();
@@ -365,19 +403,28 @@ void ContextView::Error() {}
void ContextView::SongChanged(const Song &song) {
if (widget_stacked_->currentWidget() == widget_play_ && song_playing_.is_valid() && song == song_playing_) {
if (widget_stacked_->currentWidget() == widget_play_ && song_playing_.is_valid() && song == song_playing_ && song.title() == song_playing_.title() && song.album() == song_playing_.album() && song.artist() == song_playing_.artist()) {
UpdateSong(song);
}
else {
song_prev_ = song_playing_;
song_playing_ = song;
lyrics_ = song.lyrics();
lyrics_id_ = -1;
song_playing_ = song;
lyrics_tried_ = false;
SetSong();
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && !song.artist().isEmpty() && !song.title().isEmpty()) {
lyrics_fetcher_->Clear();
lyrics_id_ = lyrics_fetcher_->Search(song.effective_albumartist(), song.album(), song.title());
}
}
SearchLyrics();
}
void ContextView::SearchLyrics() {
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && action_search_lyrics_->isChecked() && !song_playing_.artist().isEmpty() && !song_playing_.title().isEmpty() && !lyrics_tried_ && lyrics_id_ == -1) {
lyrics_fetcher_->Clear();
lyrics_tried_ = true;
lyrics_id_ = lyrics_fetcher_->Search(song_playing_.effective_albumartist(), song_playing_.album(), song_playing_.title());
}
}
@@ -421,14 +468,23 @@ void ContextView::NoSong() {
else html += tr("%1 albums").arg(collectionview_->TotalAlbums());
html += "<br />";
label_stop_summary_->setStyleSheet("font: 12pt; font-weight: regular;");
label_stop_summary_->setStyleSheet(QString("font: %1pt \"%2\"; font-weight: regular;").arg(font_size_normal_).arg(font_normal_));
label_stop_summary_->setText(html);
}
void ContextView::UpdateFonts() {
for (QLabel *l: labels_play_all_) {
l->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_normal_).arg(font_size_normal_));
}
label_play_albums_->setStyleSheet(QString("background-color: #3DADE8; color: rgb(255, 255, 255); font: %1pt \"%2\"; font-weight: regular;").arg(font_size_normal_).arg(font_normal_));
}
void ContextView::SetSong() {
label_top_->setStyleSheet("font: 11pt; font-weight: regular;");
label_top_->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_headline_).arg(font_size_headline_));
label_top_->setText(QString("<b>%1</b><br/>%2").arg(Utilities::ReplaceMessage(title_fmt_, song_playing_, "<br/>"), Utilities::ReplaceMessage(summary_fmt_, song_playing_, "<br/>")));
label_stop_summary_->clear();
@@ -447,7 +503,16 @@ void ContextView::SetSong() {
if (action_show_data_->isChecked()) {
widget_play_data_->show();
label_filetype_->setText(song_playing_.TextForFiletype());
label_length_->setText(Utilities::PrettyTimeNanosec(song_playing_.length_nanosec()));
if (song_playing_.length_nanosec() <= 0) {
label_length_title_->hide();
label_length_->hide();
label_length_->clear();
}
else {
label_length_title_->show();
label_length_->show();
label_length_->setText(Utilities::PrettyTimeNanosec(song_playing_.length_nanosec()));
}
if (song_playing_.samplerate() <= 0) {
label_samplerate_title_->hide();
label_samplerate_->hide();
@@ -496,7 +561,7 @@ void ContextView::SetSong() {
if (app_->player()->engine()) enginetype = app_->player()->engine()->type();
QIcon icon_engine = IconLoader::Load(EngineName(enginetype), 32);
label_engine_icon_->setPixmap(icon_engine.pixmap(icon_engine.availableSizes().last()));
label_engine_icon_->setPixmap(icon_engine.pixmap(QSize(32, 32)));
label_engine_->setText(EngineDescription(enginetype));
spacer_play_output_->changeSize(20, 20, QSizePolicy::Fixed);
@@ -513,7 +578,7 @@ void ContextView::SetSong() {
label_device_icon_->show();
label_device_->show();
QIcon icon_device = IconLoader::Load(device.iconname, 32);
label_device_icon_->setPixmap(icon_device.pixmap(icon_device.availableSizes().last()));
label_device_icon_->setPixmap(icon_device.pixmap(QSize(32, 32)));
label_device_->setText(device.description);
}
else {
@@ -542,7 +607,6 @@ void ContextView::SetSong() {
label_play_albums_->show();
widget_albums_->show();
label_play_albums_->setText("<b>" + tr("Albums by %1").arg( song_playing_.artist().toHtmlEscaped()) + "</b>");
label_play_albums_->setStyleSheet("background-color: #3DADE8; color: rgb(255, 255, 255); font: 11pt;");
for (CollectionBackend::Album album : albumlist) {
SongList songs = app_->collection_backend()->GetSongs(song_playing_.artist(), album.album_name, opt);
widget_albums_->albums_model()->AddSongs(songs);
@@ -583,7 +647,18 @@ void ContextView::UpdateSong(const Song &song) {
if (action_show_data_->isChecked()) {
if (song.filetype() != song_playing_.filetype()) label_filetype_->setText(song.TextForFiletype());
if (song.length_nanosec() != song_playing_.length_nanosec()) label_length_->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
if (song.length_nanosec() != song_playing_.length_nanosec()){
if (song.length_nanosec() <= 0) {
label_length_title_->hide();
label_length_->hide();
label_length_->clear();
}
else {
label_length_title_->show();
label_length_->show();
label_length_->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
}
}
if (song.samplerate() != song_playing_.samplerate()) {
if (song.samplerate() <= 0) {
label_samplerate_title_->hide();
@@ -628,21 +703,7 @@ void ContextView::UpdateSong(const Song &song) {
void ContextView::ResetSong() {
QList <QLabel *> labels_play_data;
labels_play_data << label_engine_icon_
<< label_engine_
<< label_device_
<< label_device_icon_
<< label_filetype_
<< label_length_
<< label_samplerate_
<< label_bitdepth_
<< label_bitrate_
<< label_play_albums_
<< label_play_lyrics_;
for (QLabel *l: labels_play_data) {
for (QLabel *l: labels_play_data_) {
l->clear();
}
@@ -661,7 +722,7 @@ void ContextView::UpdateLyrics(const quint64 id, const QString &provider, const
}
void ContextView::contextMenuEvent(QContextMenuEvent *e) {
if (menu_ && widget_stacked_->currentWidget() == widget_play_) menu_->popup(mapToGlobal(e->pos()));
if (menu_) menu_->popup(mapToGlobal(e->pos()));
}
void ContextView::dragEnterEvent(QDragEnterEvent *e) {
@@ -684,9 +745,7 @@ void ContextView::dropEvent(QDropEvent *e) {
}
void ContextView::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
Q_UNUSED(cover_url);
void ContextView::AlbumCoverLoaded(const Song &song, const QImage &image) {
if (song != song_playing_ || image == image_original_) return;
@@ -742,11 +801,22 @@ void ContextView::ActionShowLyrics() {
s.beginGroup(ContextSettingsPage::kSettingsGroup);
s.setValue(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS], action_show_lyrics_->isChecked());
s.endGroup();
if (song_playing_.is_valid()) SetSong();
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && !song_playing_.artist().isEmpty() && !song_playing_.title().isEmpty()) {
lyrics_fetcher_->Clear();
lyrics_id_ = lyrics_fetcher_->Search(song_playing_.artist(), song_playing_.album(), song_playing_.title());
}
SearchLyrics();
}
void ContextView::ActionSearchLyrics() {
QSettings s;
s.beginGroup(ContextSettingsPage::kSettingsGroup);
s.setValue(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SEARCH_LYRICS], action_search_lyrics_->isChecked());
s.endGroup();
if (song_playing_.is_valid()) SetSong();
SearchLyrics();
}

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