Compare commits

..

176 Commits

Author SHA1 Message Date
Jonas Kvinge
4eb11c32b0 Release 0.6.11 2020-05-16 14:40:35 +02:00
Jonas Kvinge
25457bc09a Release 0.6.11 2020-05-16 14:39:53 +02:00
Jonas Kvinge
d5cfb5f733 Merge branch 'master' of github.com:strawberrymusicplayer/strawberry 2020-05-16 14:14:34 +02:00
Jonas Kvinge
79ba6e628e Use art id from the API as cover filename for Subsonic
Fixes #433
2020-05-16 14:13:22 +02:00
King_DuckZ
ef73add05a Warning fix on gcc 8.3.0 (#439)
Fixes warning:
assuming signed overflow does not occur when
simplifying conditional to constant [-Wstrict-overflow]

Signed-off-by: Michele Santullo <m.santullo@posteo.net>

Co-authored-by: Michele Santullo <m.santullo@posteo.net>
2020-05-16 13:34:42 +02:00
Strawbs Bot
ec3d11fb27 Update translations 2020-05-16 01:03:55 +02:00
Jonas Kvinge
3fbc7031b5 Update about dialog 2020-05-16 00:45:15 +02:00
Jonas Kvinge
40beb5e428 Update Changelog 2020-05-15 23:54:15 +02:00
Jonas Kvinge
0f608c8ef0 Update debian/copyright 2020-05-15 23:48:44 +02:00
Jonas Kvinge
8509cb4743 Spotify: Fix clearing access token 2020-05-15 23:36:01 +02:00
Jonas Kvinge
f4429e8c4a Make Musicbrainz cover provider respect rate limiting 2020-05-15 22:53:21 +02:00
Jonas Kvinge
e9e0829cdc Remove end dash from title 2020-05-15 22:15:52 +02:00
Strawbs Bot
93f0230423 Update translations 2020-05-15 01:03:01 +02:00
plonibarploni
f26a0df4a4 strip directory from OpenInFileManager command (#436) 2020-05-14 22:19:26 +02:00
Jonas Kvinge
c7d4624282 Update README.md 2020-05-14 22:12:55 +02:00
Jonas Kvinge
b03eee2a22 Update Changelog 2020-05-14 22:10:18 +02:00
Jonas Kvinge
7d4d72e706 Make Discogs provider respect rate limiting 2020-05-14 19:31:40 +02:00
Jonas Kvinge
e3c367984b Make it possible to receive SearchResults before SearchFinished 2020-05-14 19:30:29 +02:00
Jonas Kvinge
0ebfa10d32 Update details in playing widget 2020-05-14 19:29:34 +02:00
Jonas Kvinge
16d9a077f0 emit SearchCoverInProgress before SearchCoverAutomatically 2020-05-14 19:29:07 +02:00
Strawbs Bot
a9d8bbad42 Update translations 2020-05-14 01:03:53 +02:00
Jonas Kvinge
d78bb94af3 Fix Tidal OAuth login 2020-05-13 21:56:11 +02:00
Jonas Kvinge
b139c0a824 Dont use song count from backend for CDDA devices 2020-05-13 19:42:13 +02:00
Jonas Kvinge
5b0b924d34 Fix crash in CD songloader 2020-05-13 19:00:57 +02:00
Strawbs Bot
f75acf820c Update translations 2020-05-13 01:05:26 +02:00
Jonas Kvinge
43a47f33ac Dont link chromaprint unless its enabled
Fixes #432
2020-05-12 22:39:56 +02:00
Jonas Kvinge
fcea3a0877 Add option to scrobbler setting for showing login error
Fixes #430
2020-05-12 22:25:00 +02:00
Jonas Kvinge
a950ec3bd5 Adjust login state widget placement for covers and lyrics settings 2020-05-12 22:15:53 +02:00
Jonas Kvinge
e35501ff0a Delete remaining network replies and local redirct server in destructor 2020-05-12 21:28:42 +02:00
Jonas Kvinge
4bfad9dad8 Fix use of QString::right() 2020-05-12 21:12:08 +02:00
Jonas Kvinge
c5c7a07c12 Add QImageReader::imageFormatsForMimeType replacement function 2020-05-12 19:48:37 +02:00
Jonas Kvinge
7e22e0e552 Use original image format when saving images from Subsonic and Tidal
Fixes #435
2020-05-12 18:50:57 +02:00
Jonas Kvinge
84ec4bdc79 Check content type for image in album cover fetcher search 2020-05-12 18:47:32 +02:00
Jonas Kvinge
2bcad9b637 Do AddOrUpdateSongs in database thread 2020-05-12 18:45:24 +02:00
Jonas Kvinge
c8d5f03070 Dont use reference in AlbumSongsReplyReceived 2020-05-12 15:58:36 +02:00
Jonas Kvinge
168e101a5a Subsonic: Disconnect signal/slots 2020-05-12 15:55:13 +02:00
Jonas Kvinge
b4bc7333d9 Use album id as cover filename for Subsonic
Fixes #433
2020-05-12 15:53:15 +02:00
Strawbs Bot
e8b58c940e Update translations 2020-05-11 01:03:48 +02:00
Jonas Kvinge
ec7202e3f6 Use refresh token for ListenBrainz 2020-05-11 00:51:18 +02:00
Jonas Kvinge
9a740f7962 Change variable name 2020-05-11 00:49:54 +02:00
Jonas Kvinge
9210fdee0d Make spotify refresh login 2020-05-10 17:10:20 +02:00
Jonas Kvinge
d7661f0964 Fix possible crash in album cover fetcher 2020-05-10 16:54:14 +02:00
Jonas Kvinge
139e148912 Use shared_ptr for scrobbler cache items 2020-05-10 14:59:04 +02:00
Jonas Kvinge
1b8dedb4ed Clear access token when login is expired 2020-05-10 14:53:40 +02:00
Jonas Kvinge
5d6b0fa329 Reset last played song when playlist is finished 2020-05-10 13:08:29 +02:00
Jonas Kvinge
f35bbd89c9 Initialize QNetworkReply pointer 2020-05-10 12:56:12 +02:00
Jonas Kvinge
538a9e42f4 Remove these 2020-05-10 12:50:37 +02:00
Jonas Kvinge
623147dea7 Add Json cover provider class 2020-05-10 12:49:11 +02:00
Jonas Kvinge
dfecd0cd12 Show Json parse error 2020-05-10 12:48:48 +02:00
Jonas Kvinge
fe3af3a676 Clear albums on close in cover manager 2020-05-10 11:50:05 +02:00
Strawbs Bot
25f60331ed Update translations 2020-05-10 01:04:15 +02:00
Jonas Kvinge
d4860a3426 Use defaults from context UI 2020-05-09 18:37:43 +02:00
Jonas Kvinge
e7e77ed86b Add automatically search for album cover to context settings 2020-05-09 18:31:10 +02:00
Jonas Kvinge
dc80459c59 Remove debug print 2020-05-09 02:30:32 +02:00
Jonas Kvinge
2f2de59234 Fix AuthError function 2020-05-09 02:07:51 +02:00
Jonas Kvinge
7bccc21878 Add setting for cover providers 2020-05-09 01:48:08 +02:00
Strawbs Bot
40f9dafa44 Update translations 2020-05-09 01:04:23 +02:00
Jonas Kvinge
355d436d29 Sort settings pages 2020-05-08 20:25:02 +02:00
Jonas Kvinge
079b684388 Remove duplicate include 2020-05-08 20:17:33 +02:00
Jonas Kvinge
fd11f46d30 Add album cover provider from Musixmatch 2020-05-08 20:14:16 +02:00
Jonas Kvinge
cb7099199a Fix memory include 2020-05-08 18:47:55 +02:00
Jonas Kvinge
8566d91e89 Remove some unneeded includes, etc 2020-05-08 18:44:07 +02:00
Jonas Kvinge
f44ce49ea7 Add setting for lyric providers and add more providers
Fixes #335
2020-05-08 18:35:36 +02:00
Jonas Kvinge
6ef69f6b32 Format code 2020-05-08 18:34:33 +02:00
Strawbs Bot
f5983d5f10 Update translations 2020-05-07 01:03:30 +02:00
Jonas Kvinge
54cce5e089 Use album grouping function 2020-05-06 22:35:55 +02:00
Jonas Kvinge
4e4e596a1e Change some parameters to const 2020-05-06 22:26:29 +02:00
Jonas Kvinge
727a1f5ad1 Sort songs in collection by song title instead of track if previous
grouping is not the album.

Fixes #295
2020-05-06 22:14:59 +02:00
Jonas Kvinge
85fa86625b Fix infinite loop in stylesheetloader
Fixes #361
2020-05-06 21:43:44 +02:00
Jonas Kvinge
2c91877f83 Add option to show/hide sidebar
Fixes #393
2020-05-06 18:15:17 +02:00
Jonas Kvinge
7d1fac44e9 Update non collection songs with manually unset cover 2020-05-05 23:57:37 +02:00
Jonas Kvinge
2e34abfc0d Fix mpris:artUrl when using embedded cover
Fixes #426
2020-05-04 23:23:24 +02:00
Jonas Kvinge
81ba63e247 Turn on git revision 2020-05-02 15:18:39 +02:00
Strawbs Bot
8b11a65522 Update translations 2020-05-02 01:01:45 +02:00
Jonas Kvinge
7190ad1d15 Remove styles directory when uninstalling 2020-05-01 19:55:45 +02:00
Jonas Kvinge
1c9bae5df5 Update libnettle dll in nsi 2020-05-01 18:41:36 +02:00
Jonas Kvinge
cc7fd73916 Update libhogweed dll in nsi 2020-05-01 16:55:58 +02:00
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
355 changed files with 23372 additions and 9836 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,72 @@ Strawberry Music Player
=======================
ChangeLog
0.6.11:
Bugfixes:
* Fixed MPRIS missing art url when playing albums with embedded cover.
* Fixed updating local non collection songs when manually unsetting cover.
* Fixed infinite loop and preceding crash when CSS background-color was set in qt5ct.
* Fixed UI freeze when updating the database from a large Subsonic or Tidal collection.
* Fixed crash when CD loading fails in devices.
* Fixed CD devices showing up with having 0 songs after loading.
* Fixed the album cover loading indicator being stuck if no cover providers were available.
* Fixed the playing widget not updating artist, album or title after metadata has changed for a song when no album cover was loaded.
Enhancements:
* Sort songs in collection by song title instead of track if previous grouping is not the album.
* Added option to switch on/off automatically searching for album covers to context settings.
* Reset last played song when playlist is finished.
* Checking content type of received HTTP request for image when receiving album covers.
* Added option to scrobbler setting for turning off login error popup.
* Made MusicBrainz and Discogs cover providers respect rate limiting.
New features:
* Added option to show/hide sidebar.
* Added settings for selecting album cover and lyrics providers.
* Added album covers from Musixmatch and Spotify.
* Added lyrics from Genius, Musixmatch and ChartLyrics.
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

@@ -17,7 +17,7 @@ Resources:
* PPA: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry
* Translations: https://translate.zanata.org/iteration/view/strawberry/master
The program is free software, released under GPL. If you like this program and can make use of it, consider sponsoring or donating to help funding the project.
The program is free software, released under GPL. If you like this program and can make use of it, consider sponsoring or donating to help fund the project.
To sponsor, visit [my GitHub sponsors profile](https://github.com/sponsors/jonaski).
Funding developers through GitHub Sponsors is one more way to contribute to open source projects you appreciate, it helps developers get the resources they need, and recognize contributors working behind the scenes to make open source better for everyone.
You can also make a one-time payment through [paypal.me/jonaskvinge](https://paypal.me/jonaskvinge)
@@ -32,19 +32,19 @@ You can also make a one-time payment through [paypal.me/jonaskvinge](https://pay
* Advanced audio output and device configuration for bit-perfect playback on Linux
* Edit tags on music files
* Fetch tags from MusicBrainz
* Album cover art from [Last.fm](https://www.last.fm/), [Musicbrainz](https://musicbrainz.org/), [Discogs](https://www.discogs.com/) and [Deezer](https://www.deezer.com/)
* Song lyrics from [AudD](https://audd.io/), [lyrics.ovh](https://lyrics.ovh/) and [lololyrics.com](https://www.lololyrics.com/)
* Album cover art from [Last.fm](https://www.last.fm/), [Musicbrainz](https://musicbrainz.org/), [Discogs](https://www.discogs.com/), [Musixmatch](https://www.musixmatch.com/), [Deezer](https://www.deezer.com/), [Tidal](https://www.tidal.com/), [Qobuz](https://www.qobuz.com/) and [Spotify](https://www.spotify.com/)
* Song lyrics from [AudD](https://audd.io/), [Genius](https://genius.com/), [Musixmatch](https://www.musixmatch.com/), [ChartLyrics](http://www.chartlyrics.com/), [lyrics.ovh](https://lyrics.ovh/) and [lololyrics.com](https://www.lololyrics.com/)
* Support for multiple backends
* Audio analyzer
* Audio equalizer
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
* Scrobbler with support for [Last.fm](https://www.last.fm/), [Libre.fm](https://libre.fm/) and [ListenBrainz](https://listenbrainz.org/)
* Subsonic streaming support
* Subsonic and Tidal streaming support
It has so far been tested to work on Linux, OpenBSD and Windows.
**We currently do not provide releases for macOS because there aren't any macOS developers actively working on this project. It is still possible to compile by following the instructions in the Wiki**
**We currently do not provide releases for macOS because there aren't any macOS developers actively working on this project. Development builds are available**
### :heavy_exclamation_mark: Requirements
@@ -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 11)
#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)

4
debian/control vendored
View File

@@ -55,8 +55,8 @@ Description: Audio player and music collection organizer
- Advanced audio output and device configuration for bit-perfect playback on Linux
- Edit tags on music files
- Fetch tags from MusicBrainz
- Album cover art from Lastfm, Musicbrainz, Discogs and Deezer
- Song lyrics from AudD, lyrics.ovh and lololyrics.com
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify
- Song lyrics from AudD, Genius, Musixmatch, ChartLyrics, lyrics.ovh and lololyrics.com
- Support for multiple backends
- Audio analyzer
- Audio equalizer

41
debian/copyright vendored
View File

@@ -24,6 +24,8 @@ Files: src/core/main.h
src/version.h.in
src/context/contextview.cpp
src/context/contextview.h
src/context/contextalbum.cpp
src/context/contextalbum.h
src/engine/enginetype.cpp
src/engine/enginetype.h
src/engine/alsadevicefinder.cpp
@@ -34,22 +36,40 @@ 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
src/internet/internettabsview.h
src/internet/internetsongsview.cpp
src/internet/internetsongsview.h
src/settings/backendsettingspage.cpp
src/settings/backendsettingspage.h
src/settings/coverssettingspage.cpp
src/settings/coverssettingspage.h
src/settings/lyricssettingspage.cpp
src/settings/lyricssettingspage.h
src/settings/scrobblersettingspage.cpp
src/settings/scrobblersettingspage.h
src/settings/subsonicsettingspage.cpp
src/settings/subsonicsettingspage.h
src/settings/tidalsettingspage.cpp
src/settings/tidalsettingspage.h
src/covermanager/jsoncoverprovider.cpp
src/covermanager/jsoncoverprovider.h
src/covermanager/lastfmcoverprovider.cpp
src/covermanager/lastfmcoverprovider.h
src/covermanager/musicbrainzcoverprovider.cpp
src/covermanager/musicbrainzcoverprovider.h
src/covermanager/deezercoverprovider.cpp
src/covermanager/deezercoverprovider.h
src/covermanager/tidalcoverprovider.cpp
src/covermanager/tidalcoverprovider.h
src/covermanager/qobuzcoverprovider.cpp
src/covermanager/qobuzcoverprovider.h
src/covermanager/spotifycoverprovider.cpp
src/covermanager/spotifycoverprovider.h
src/covermanager/musixmatchcoverprovider.cpp
src/covermanager/musixmatchcoverprovider.h
src/globalshortcuts/globalshortcutbackend-system.cpp
src/globalshortcuts/globalshortcutbackend-system.h
src/globalshortcuts/globalshortcut.cpp
@@ -61,9 +81,10 @@ Files: src/core/main.h
src/lyrics/*
src/scrobbler/*
src/subsonic/*
src/tidal/*
src/transcoder/transcoderoptionswavpack.cpp
src/transcoder/transcoderoptionswavpack.h
Copyright: 2012-2014, 2017-2019, Jonas Kvinge <jonas@jkvinge.net>
Copyright: 2012-2014, 2017-2020, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/core/main.cpp
@@ -160,8 +181,20 @@ Files: src/core/main.cpp
src/transcoder/transcoder.h
src/musicbrainz/musicbrainzclient.cpp
src/musicbrainz/musicbrainzclient.h
src/covermanager/albumcoverloader.cpp
src/covermanager/albumcoverloader.h
src/covermanager/currentalbumcoverloader.cpp
src/covermanager/currentalbumcoverloader.h
src/covermanager/albumcoverchoicecontroller.cpp
src/covermanager/albumcoverchoicecontroller.h
src/covermanager/albumcoverfetchersearch.cpp
src/covermanager/albumcoverfetchersearch.h
src/covermanager/coverproviders.cpp
src/covermanager/coverproviders.h
src/covermanager/coverprovider.cpp
src/covermanager/coverprovider.h
Copyright: 2010, 2012-2014 David Sansome <me@davidsansome.com>
2012-2014, 2017-2019 Jonas Kvinge <jonas@jkvinge.net>
2012-2014, 2017-2020 Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/engine/enginebase.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

@@ -26,8 +26,8 @@
<li>Advanced audio output and device configuration for bit-perfect playback on Linux</li>
<li>Edit tags on music files</li>
<li>Fetch tags from MusicBrainz</li>
<li>Album cover art from Last.fm, Musicbrainz and Discogs</li>
<li>Song lyrics from AudD, lyrics.ovh and lololyrics.com</li>
<li>Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify</li>
<li>Song lyrics from AudD, Genius, Musixmatch, ChartLyrics, lyrics.ovh and lololyrics.com</li>
<li>Support for multiple backends</li>
<li>Audio analyzer and equalizer</li>
<li>Transfer music to iPod, iPhone, MTP or mass-storage USB player</li>

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

@@ -25,9 +25,9 @@ Features:
.br
- Fetch tags from MusicBrainz
.br
- Album cover art from Lastfm, Musicbrainz, Discogs and Deezer
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify
.br
- Song lyrics from AudD, lyrics.ovh and lololyrics.com
- Song lyrics from AudD, Genius, Musixmatch, ChartLyrics, lyrics.ovh and lololyrics.com
.br
- Support for multiple backends
.br

View File

@@ -104,8 +104,8 @@ Features:
- Advanced audio output and device configuration for bit-perfect playback on Linux
- Edit tags on music files
- Fetch tags from MusicBrainz
- Album cover art from Last.fm, Musicbrainz, Discogs and Deezer
- Song lyrics from AudD, lyrics.ovh and lololyrics.com
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify
- Song lyrics from AudD, Genius, Musixmatch, ChartLyrics, lyrics.ovh and lololyrics.com
- Support for multiple backends
- Audio analyzer
- Audio equalizer

View File

@@ -183,14 +183,14 @@ Section "Strawberry" Strawberry
File "libgsttag-1.0-0.dll"
File "libgstvideo-1.0-0.dll"
File "libharfbuzz-0.dll"
File "libhogweed-5.dll"
File "libhogweed-6.dll"
File "libiconv-2.dll"
File "libidn2-0.dll"
File "libintl-8.dll"
File "libjpeg-9.dll"
File "liblzma-5.dll"
File "libmp3lame-0.dll"
File "libnettle-7.dll"
File "libnettle-8.dll"
File "libogg-0.dll"
File "libopus-0.dll"
File "libpcre-1.dll"
@@ -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"
@@ -447,14 +447,14 @@ Section "Uninstall"
Delete "$INSTDIR\libgsttag-1.0-0.dll"
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
Delete "$INSTDIR\libharfbuzz-0.dll"
Delete "$INSTDIR\libhogweed-5.dll"
Delete "$INSTDIR\libhogweed-6.dll"
Delete "$INSTDIR\libiconv-2.dll"
Delete "$INSTDIR\libidn2-0.dll"
Delete "$INSTDIR\libintl-8.dll"
Delete "$INSTDIR\libjpeg-9.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libmp3lame-0.dll"
Delete "$INSTDIR\libnettle-7.dll"
Delete "$INSTDIR\libnettle-8.dll"
Delete "$INSTDIR\libogg-0.dll"
Delete "$INSTDIR\libopus-0.dll"
Delete "$INSTDIR\libpcre-1.dll"
@@ -592,6 +592,7 @@ Section "Uninstall"
; Remove the installation folders.
RMDir "$INSTDIR\platforms"
RMDir "$INSTDIR\styles"
RMDir "$INSTDIR\sqldrivers"
RMDir "$INSTDIR\imageformats"
RMDir "$INSTDIR\gio-modules"

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.11+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
@@ -223,10 +182,14 @@ set(SOURCES
covermanager/coverexportrunnable.cpp
covermanager/currentalbumcoverloader.cpp
covermanager/coverfromurldialog.cpp
covermanager/jsoncoverprovider.cpp
covermanager/lastfmcoverprovider.cpp
covermanager/musicbrainzcoverprovider.cpp
covermanager/discogscoverprovider.cpp
covermanager/deezercoverprovider.cpp
covermanager/qobuzcoverprovider.cpp
covermanager/musixmatchcoverprovider.cpp
covermanager/spotifycoverprovider.cpp
lyrics/lyricsproviders.cpp
lyrics/lyricsprovider.cpp
@@ -236,24 +199,30 @@ set(SOURCES
lyrics/auddlyricsprovider.cpp
lyrics/ovhlyricsprovider.cpp
lyrics/lololyricsprovider.cpp
lyrics/geniuslyricsprovider.cpp
lyrics/musixmatchlyricsprovider.cpp
lyrics/chartlyricsprovider.cpp
settings/settingsdialog.cpp
settings/settingspage.cpp
settings/behavioursettingspage.cpp
settings/collectionsettingspage.cpp
settings/backendsettingspage.cpp
settings/contextsettingspage.cpp
settings/playlistsettingspage.cpp
settings/scrobblersettingspage.cpp
settings/coverssettingspage.cpp
settings/lyricssettingspage.cpp
settings/networkproxysettingspage.cpp
settings/appearancesettingspage.cpp
settings/contextsettingspage.cpp
settings/notificationssettingspage.cpp
settings/scrobblersettingspage.cpp
dialogs/about.cpp
dialogs/console.cpp
dialogs/errordialog.cpp
dialogs/edittagdialog.cpp
dialogs/trackselectiondialog.cpp
dialogs/addstreamdialog.cpp
widgets/autoexpandingtreeview.cpp
widgets/busyindicator.cpp
@@ -286,7 +255,6 @@ set(SOURCES
internet/internetservices.cpp
internet/internetservice.cpp
internet/internetplaylistitem.cpp
internet/internetsearch.cpp
internet/internetsearchview.cpp
internet/internetsearchmodel.cpp
internet/internetsearchsortmodel.cpp
@@ -334,6 +302,7 @@ set(HEADERS
core/standarditemiconloader.h
core/systemtrayicon.h
core/mimedata.h
core/stylesheetloader.h
engine/enginebase.h
engine/devicefinders.h
@@ -409,10 +378,14 @@ set(HEADERS
covermanager/coverexportrunnable.h
covermanager/currentalbumcoverloader.h
covermanager/coverfromurldialog.h
covermanager/jsoncoverprovider.h
covermanager/lastfmcoverprovider.h
covermanager/musicbrainzcoverprovider.h
covermanager/discogscoverprovider.h
covermanager/deezercoverprovider.h
covermanager/qobuzcoverprovider.h
covermanager/musixmatchcoverprovider.h
covermanager/spotifycoverprovider.h
lyrics/lyricsproviders.h
lyrics/lyricsprovider.h
@@ -422,24 +395,30 @@ set(HEADERS
lyrics/auddlyricsprovider.h
lyrics/ovhlyricsprovider.h
lyrics/lololyricsprovider.h
lyrics/geniuslyricsprovider.h
lyrics/musixmatchlyricsprovider.h
lyrics/chartlyricsprovider.h
settings/settingsdialog.h
settings/settingspage.h
settings/behavioursettingspage.h
settings/collectionsettingspage.h
settings/backendsettingspage.h
settings/contextsettingspage.h
settings/playlistsettingspage.h
settings/scrobblersettingspage.h
settings/coverssettingspage.h
settings/lyricssettingspage.h
settings/networkproxysettingspage.h
settings/appearancesettingspage.h
settings/contextsettingspage.h
settings/notificationssettingspage.h
settings/scrobblersettingspage.h
dialogs/about.h
dialogs/errordialog.h
dialogs/console.h
dialogs/edittagdialog.h
dialogs/trackselectiondialog.h
dialogs/addstreamdialog.h
widgets/autoexpandingtreeview.h
widgets/busyindicator.h
@@ -472,7 +451,6 @@ set(HEADERS
internet/internetservices.h
internet/internetservice.h
internet/internetsongmimedata.h
internet/internetsearch.h
internet/internetsearchview.h
internet/internetsearchmodel.h
internet/localredirectserver.h
@@ -526,10 +504,12 @@ set(UI
settings/backendsettingspage.ui
settings/contextsettingspage.ui
settings/playlistsettingspage.ui
settings/scrobblersettingspage.ui
settings/coverssettingspage.ui
settings/lyricssettingspage.ui
settings/networkproxysettingspage.ui
settings/appearancesettingspage.ui
settings/notificationssettingspage.ui
settings/scrobblersettingspage.ui
equalizer/equalizer.ui
equalizer/equalizerslider.ui
@@ -539,6 +519,7 @@ set(UI
dialogs/console.ui
dialogs/edittagdialog.ui
dialogs/trackselectiondialog.ui
dialogs/addstreamdialog.ui
widgets/trackslider.ui
widgets/osdpretty.ui
@@ -622,12 +603,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 +898,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
@@ -1002,7 +1000,6 @@ target_link_libraries(strawberry_lib
${GOBJECT_LIBRARIES}
${GNUTLS_LIBRARIES}
${QT_LIBRARIES}
${CHROMAPRINT_LIBRARIES}
${SQLITE_LIBRARIES}
${TAGLIB_LIBRARIES}
${SINGLEAPPLICATION_LIBRARIES}
@@ -1026,6 +1023,10 @@ if(HAVE_GSTREAMER)
target_link_libraries(strawberry_lib ${GSTREAMER_LIBRARIES} ${GSTREAMER_BASE_LIBRARIES} ${GSTREAMER_AUDIO_LIBRARIES} ${GSTREAMER_APP_LIBRARIES} ${GSTREAMER_TAG_LIBRARIES} ${GSTREAMER_PBUTILS_LIBRARIES})
endif()
if(HAVE_CHROMAPRINT)
target_link_libraries(strawberry_lib ${CHROMAPRINT_LIBRARIES})
endif()
if(HAVE_XINE)
target_link_libraries(strawberry_lib ${LIBXINE_LIBRARIES})
endif()
@@ -1034,10 +1035,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 +1048,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 +1076,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 +1098,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 +1128,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

@@ -411,6 +411,10 @@ void CollectionBackend::AddOrUpdateSubdirs(const SubdirectoryList &subdirs) {
}
void CollectionBackend::AddOrUpdateSongsAsync(const SongList &songs) {
metaObject()->invokeMethod(this, "AddOrUpdateSongs", Qt::QueuedConnection, Q_ARG(SongList, songs));
}
void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
QMutexLocker l(db_->Mutex());
@@ -467,7 +471,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 +826,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 +999,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 +1007,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 +1024,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,18 +175,19 @@ 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;
void AddOrUpdateSongsAsync(const SongList &songs);
public slots:
void Exit();
void LoadDirectories();
@@ -200,10 +201,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 +217,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 +235,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)));
@@ -149,7 +149,7 @@ CollectionModel::~CollectionModel() {
delete root_;
}
void CollectionModel::set_pretty_covers(bool use_pretty_covers) {
void CollectionModel::set_pretty_covers(const bool use_pretty_covers) {
if (use_pretty_covers != use_pretty_covers_) {
use_pretty_covers_ = use_pretty_covers;
@@ -157,7 +157,7 @@ void CollectionModel::set_pretty_covers(bool use_pretty_covers) {
}
}
void CollectionModel::set_show_dividers(bool show_dividers) {
void CollectionModel::set_show_dividers(const bool show_dividers) {
if (show_dividers != show_dividers_) {
show_dividers_ = show_dividers;
@@ -187,19 +187,19 @@ 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) {
void CollectionModel::Init(const bool async) {
if (async) {
// Show a loading indicator in the model.
@@ -338,7 +338,7 @@ void CollectionModel::SongsSlightlyChanged(const SongList &songs) {
}
CollectionItem *CollectionModel::CreateCompilationArtistNode(bool signal, CollectionItem *parent) {
CollectionItem *CollectionModel::CreateCompilationArtistNode(const bool signal, CollectionItem *parent) {
if (signal) beginInsertRows(ItemToIndex(parent), parent->children.count(), parent->children.count());
@@ -354,7 +354,7 @@ CollectionItem *CollectionModel::CreateCompilationArtistNode(bool signal, Collec
}
QString CollectionModel::DividerKey(GroupBy type, CollectionItem *item) const {
QString CollectionModel::DividerKey(const GroupBy type, CollectionItem *item) const {
// Items which are to be grouped under the same divider must produce the same divider key. This will only get called for top-level items.
@@ -408,7 +408,7 @@ QString CollectionModel::DividerKey(GroupBy type, CollectionItem *item) const {
}
QString CollectionModel::DividerDisplayText(GroupBy type, const QString &key) const {
QString CollectionModel::DividerDisplayText(const GroupBy type, const QString &key) const {
// Pretty display text for the dividers.
@@ -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);
}
}
@@ -660,7 +658,7 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url,
}
QVariant CollectionModel::data(const QModelIndex &idx, int role) const {
QVariant CollectionModel::data(const QModelIndex &idx, const int role) const {
const CollectionItem *item = IndexToItem(idx);
@@ -672,11 +670,7 @@ QVariant CollectionModel::data(const QModelIndex &idx, int role) const {
bool is_album_node = false;
if (role == Qt::DecorationRole && item->type == CollectionItem::Type_Container) {
GroupBy container_type = group_by_[item->container_level];
is_album_node = container_type == GroupBy_Album ||
container_type == GroupBy_AlbumDisc ||
container_type == GroupBy_YearAlbum ||
container_type == GroupBy_YearAlbumDisc ||
container_type == GroupBy_OriginalYearAlbum;
is_album_node = IsAlbumGrouping(container_type);
}
if (is_album_node) {
// It has const behaviour some of the time - that's ok right?
@@ -688,7 +682,7 @@ QVariant CollectionModel::data(const QModelIndex &idx, int role) const {
}
QVariant CollectionModel::data(const CollectionItem *item, int role) const {
QVariant CollectionModel::data(const CollectionItem *item, const int role) const {
GroupBy container_type = item->type == CollectionItem::Type_Container ? group_by_[item->container_level] : GroupBy_None;
@@ -828,7 +822,7 @@ CollectionModel::QueryResult CollectionModel::RunQuery(CollectionItem *parent) {
}
void CollectionModel::PostQuery(CollectionItem *parent, const CollectionModel::QueryResult &result, bool signal) {
void CollectionModel::PostQuery(CollectionItem *parent, const CollectionModel::QueryResult &result, const bool signal) {
// Information about what we want the children to be
int child_level = parent == root_ ? 0 : parent->container_level + 1;
@@ -852,7 +846,7 @@ void CollectionModel::PostQuery(CollectionItem *parent, const CollectionModel::Q
}
void CollectionModel::LazyPopulate(CollectionItem *parent, bool signal) {
void CollectionModel::LazyPopulate(CollectionItem *parent, const bool signal) {
if (parent->lazy_loaded) return;
parent->lazy_loaded = true;
@@ -920,7 +914,7 @@ void CollectionModel::Reset() {
}
void CollectionModel::InitQuery(GroupBy type, CollectionQuery *q) {
void CollectionModel::InitQuery(const GroupBy type, CollectionQuery *q) {
// Say what type of thing we want to get back from the database.
switch (type) {
@@ -988,7 +982,7 @@ void CollectionModel::InitQuery(GroupBy type, CollectionQuery *q) {
}
void CollectionModel::FilterQuery(GroupBy type, CollectionItem *item, CollectionQuery *q) {
void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, CollectionQuery *q) {
// Say how we want the query to be filtered. This is done once for each parent going up the tree.
@@ -1081,7 +1075,7 @@ void CollectionModel::FilterQuery(GroupBy type, CollectionItem *item, Collection
}
CollectionItem *CollectionModel::InitItem(GroupBy type, bool signal, CollectionItem *parent, int container_level) {
CollectionItem *CollectionModel::InitItem(const GroupBy type, const bool signal, CollectionItem *parent, const int container_level) {
CollectionItem::Type item_type = type == GroupBy_None ? CollectionItem::Type_Song : CollectionItem::Type_Container;
@@ -1096,7 +1090,7 @@ CollectionItem *CollectionModel::InitItem(GroupBy type, bool signal, CollectionI
}
CollectionItem *CollectionModel::ItemFromQuery(GroupBy type, bool signal, bool create_divider, CollectionItem *parent, const SqlRow &row, int container_level) {
CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const SqlRow &row, const int container_level) {
CollectionItem *item = InitItem(type, signal, parent, container_level);
@@ -1219,7 +1213,12 @@ CollectionItem *CollectionModel::ItemFromQuery(GroupBy type, bool signal, bool c
item->metadata.InitFromQuery(row, true);
item->key = item->metadata.title();
item->display_text = item->metadata.TitleWithCompilationArtist();
item->sort_text = SortTextForSong(item->metadata);
if (item->container_level == 1 && !IsAlbumGrouping(group_by_[0])) {
item->sort_text = SortText(item->metadata.title());
}
else {
item->sort_text = SortTextForSong(item->metadata);
}
break;
}
@@ -1229,7 +1228,7 @@ CollectionItem *CollectionModel::ItemFromQuery(GroupBy type, bool signal, bool c
}
CollectionItem *CollectionModel::ItemFromSong(GroupBy type, bool signal, bool create_divider, CollectionItem *parent, const Song &s, int container_level) {
CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const Song &s, const int container_level) {
CollectionItem *item = InitItem(type, signal, parent, container_level);
@@ -1360,7 +1359,12 @@ CollectionItem *CollectionModel::ItemFromSong(GroupBy type, bool signal, bool cr
item->metadata = s;
item->key = s.title();
item->display_text = s.TitleWithCompilationArtist();
item->sort_text = SortTextForSong(s);
if (item->container_level == 1 && !IsAlbumGrouping(group_by_[0])) {
item->sort_text = SortText(s.title());
}
else {
item->sort_text = SortTextForSong(s);
}
break;
}
@@ -1371,7 +1375,7 @@ CollectionItem *CollectionModel::ItemFromSong(GroupBy type, bool signal, bool cr
}
void CollectionModel::FinishItem(GroupBy type, bool signal, bool create_divider, CollectionItem *parent, CollectionItem *item) {
void CollectionModel::FinishItem(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, CollectionItem *item) {
if (type == GroupBy_None) item->lazy_loaded = true;
@@ -1463,19 +1467,19 @@ QString CollectionModel::SortTextForArtist(QString artist) {
}
QString CollectionModel::SortTextForNumber(int number) {
QString CollectionModel::SortTextForNumber(const int number) {
return QString("%1").arg(number, 4, 10, QChar('0'));
}
QString CollectionModel::SortTextForYear(int year) {
QString CollectionModel::SortTextForYear(const int year) {
QString str = QString::number(year);
return QString("0").repeated(qMax(0, 4 - str.length())) + str;
}
QString CollectionModel::SortTextForBitrate(int bitrate) {
QString CollectionModel::SortTextForBitrate(const int bitrate) {
QString str = QString::number(bitrate);
return QString("0").repeated(qMax(0, 3 - str.length())) + str;
@@ -1541,9 +1545,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 {
@@ -1599,7 +1603,7 @@ SongList CollectionModel::GetChildSongs(const QModelIndex &idx) const {
return GetChildSongs(QModelIndexList() << idx);
}
void CollectionModel::SetFilterAge(int age) {
void CollectionModel::SetFilterAge(const int age) {
query_options_.set_max_age(age);
ResetAsync();
}
@@ -1634,7 +1638,7 @@ void CollectionModel::SetGroupBy(const Grouping &g) {
}
const CollectionModel::GroupBy &CollectionModel::Grouping::operator[](int i) const {
const CollectionModel::GroupBy &CollectionModel::Grouping::operator[](const int i) const {
switch (i) {
case 0: return first;
@@ -1646,7 +1650,7 @@ const CollectionModel::GroupBy &CollectionModel::Grouping::operator[](int i) con
}
CollectionModel::GroupBy &CollectionModel::Grouping::operator[](int i) {
CollectionModel::GroupBy &CollectionModel::Grouping::operator[](const int i) {
switch (i) {
case 0: return first;
@@ -1660,21 +1664,21 @@ CollectionModel::GroupBy &CollectionModel::Grouping::operator[](int i) {
}
void CollectionModel::TotalSongCountUpdatedSlot(int count) {
void CollectionModel::TotalSongCountUpdatedSlot(const int count) {
total_song_count_ = count;
emit TotalSongCountUpdated(count);
}
void CollectionModel::TotalArtistCountUpdatedSlot(int count) {
void CollectionModel::TotalArtistCountUpdatedSlot(const int count) {
total_artist_count_ = count;
emit TotalArtistCountUpdated(count);
}
void CollectionModel::TotalAlbumCountUpdatedSlot(int count) {
void CollectionModel::TotalAlbumCountUpdatedSlot(const int count) {
total_album_count_ = count;
emit TotalAlbumCountUpdated(count);

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;
@@ -113,8 +114,8 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
GroupBy second;
GroupBy third;
const GroupBy &operator[](int i) const;
GroupBy &operator[](int i);
const GroupBy &operator[](const int i) const;
GroupBy &operator[](const int i);
bool operator==(const Grouping &other) const {
return first == other.first && second == other.second && third == other.third;
}
@@ -132,7 +133,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
CollectionDirectoryModel *directory_model() const { return dir_model_; }
// Call before Init()
void set_show_various_artists(bool show_various_artists) { show_various_artists_ = show_various_artists; }
void set_show_various_artists(const bool show_various_artists) { show_various_artists_ = show_various_artists; }
// Get information about the collection
void GetChildSongs(CollectionItem *item, QList<QUrl> *urls, SongList *songs, QSet<int> *song_ids) const;
@@ -145,18 +146,18 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
int total_album_count() const { return total_album_count_; }
// QAbstractItemModel
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const;
QVariant data(const QModelIndex &idx, const int role = Qt::DisplayRole) const;
Qt::ItemFlags flags(const QModelIndex &idx) const;
QStringList mimeTypes() const;
QMimeData *mimeData(const QModelIndexList &indexes) const;
bool canFetchMore(const QModelIndex &parent) const;
// Whether or not to use album cover art, if it exists, in the collection view
void set_pretty_covers(bool use_pretty_covers);
void set_pretty_covers(const bool use_pretty_covers);
bool use_pretty_covers() const { return use_pretty_covers_; }
// Whether or not to show letters heading in the collection view
void set_show_dividers(bool show_dividers);
void set_show_dividers(const bool show_dividers);
// Save the current grouping
void SaveGrouping(QString name);
@@ -170,53 +171,57 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
static QString PrettyAlbumDisc(const QString &album, const int disc);
static QString PrettyYearAlbumDisc(const int year, const QString &album, const int disc);
static QString SortText(QString text);
static QString SortTextForNumber(int year);
static QString SortTextForNumber(const int year);
static QString SortTextForArtist(QString artist);
static QString SortTextForSong(const Song &song);
static QString SortTextForYear(int year);
static QString SortTextForBitrate(int bitrate);
static QString SortTextForYear(const int year);
static QString SortTextForBitrate(const int bitrate);
signals:
void TotalSongCountUpdated(int count);
void TotalArtistCountUpdated(int count);
void TotalAlbumCountUpdated(int count);
quint64 icon_cache_disk_size() { return sIconCache->cacheSize(); }
static bool IsAlbumGrouping(const GroupBy group_by) { return group_by == GroupBy_Album || group_by == GroupBy_YearAlbum || group_by == GroupBy_OriginalYearAlbum || group_by == GroupBy_AlbumDisc || group_by == GroupBy_YearAlbumDisc; }
signals:
void TotalSongCountUpdated(const int count);
void TotalArtistCountUpdated(const int count);
void TotalAlbumCountUpdated(const int count);
void GroupingChanged(const CollectionModel::Grouping &g);
public slots:
void SetFilterAge(int age);
void SetFilterAge(const int age);
void SetFilterText(const QString &text);
void SetFilterQueryMode(QueryOptions::QueryMode query_mode);
void SetGroupBy(const CollectionModel::Grouping &g);
const CollectionModel::Grouping &GetGroupBy() const { return group_by_; }
void Init(bool async = true);
void Init(const bool async = true);
void Reset();
void ResetAsync();
protected:
void LazyPopulate(CollectionItem *item) { LazyPopulate(item, true); }
void LazyPopulate(CollectionItem *item, bool signal);
void LazyPopulate(CollectionItem *item, const bool signal);
private slots:
// From CollectionBackend
void SongsDiscovered(const SongList &songs);
void SongsDeleted(const SongList &songs);
void SongsSlightlyChanged(const SongList &songs);
void TotalSongCountUpdatedSlot(int count);
void TotalArtistCountUpdatedSlot(int count);
void TotalAlbumCountUpdatedSlot(int count);
void TotalSongCountUpdatedSlot(const int count);
void TotalArtistCountUpdatedSlot(const int count);
void TotalAlbumCountUpdatedSlot(const int count);
void ClearDiskCache();
// 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.
// This gets called a lot when filtering the playlist, so it's nice to be able to do it in a background thread.
QueryResult RunQuery(CollectionItem *parent);
void PostQuery(CollectionItem *parent, const QueryResult &result, bool signal);
void PostQuery(CollectionItem *parent, const QueryResult &result, const bool signal);
bool HasCompilations(const CollectionQuery &query);
@@ -225,29 +230,29 @@ signals:
// Functions for working with queries and creating items.
// When the model is reset or when a node is lazy-loaded the Collection constructs a database query to populate the items.
// Filters are added for each parent item, restricting the songs returned to a particular album or artist for example.
static void InitQuery(GroupBy type, CollectionQuery *q);
void FilterQuery(GroupBy type, CollectionItem *item, CollectionQuery *q);
static void InitQuery(const GroupBy type, CollectionQuery *q);
void FilterQuery(const GroupBy type, CollectionItem *item, CollectionQuery *q);
// Items can be created either from a query that's been run to populate a node, or by a spontaneous SongsDiscovered emission from the backend.
CollectionItem *ItemFromQuery(GroupBy type, bool signal, bool create_divider, CollectionItem *parent, const SqlRow &row, int container_level);
CollectionItem *ItemFromSong(GroupBy type, bool signal, bool create_divider, CollectionItem *parent, const Song &s, int container_level);
CollectionItem *ItemFromQuery(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const SqlRow &row, const int container_level);
CollectionItem *ItemFromSong(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, const Song &s, const int container_level);
// The "Various Artists" node is an annoying special case.
CollectionItem *CreateCompilationArtistNode(bool signal, CollectionItem *parent);
CollectionItem *CreateCompilationArtistNode(const bool signal, CollectionItem *parent);
// Helpers for ItemFromQuery and ItemFromSong
CollectionItem *InitItem(GroupBy type, bool signal, CollectionItem *parent, int container_level);
void FinishItem(GroupBy type, bool signal, bool create_divider, CollectionItem *parent, CollectionItem *item);
CollectionItem *InitItem(const GroupBy type, const bool signal, CollectionItem *parent, const int container_level);
void FinishItem(const GroupBy type, const bool signal, const bool create_divider, CollectionItem *parent, CollectionItem *item);
QString DividerKey(GroupBy type, CollectionItem *item) const;
QString DividerDisplayText(GroupBy type, const QString &key) const;
QString DividerKey(const GroupBy type, CollectionItem *item) const;
QString DividerDisplayText(const GroupBy type, const QString &key) const;
// Helpers
QString AlbumIconPixmapCacheKey(const QModelIndex &idx) const;
QVariant AlbumIcon(const QModelIndex &idx);
QVariant data(const CollectionItem *item, int role) const;
QVariant data(const CollectionItem *item, const 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);

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