Compare commits

..

233 Commits
0.5.4 ... 0.6.2

Author SHA1 Message Date
Jonas Kvinge
10c57cf6da Release 0.6.2 2019-08-03 13:57:54 +02:00
Jonas Kvinge
e65c5eeab1 Release 0.6.1 2019-08-03 13:29:22 +02:00
Jonas Kvinge
85fad35dc2 Update README.md 2019-08-03 13:15:43 +02:00
Jonas Kvinge
c992768efe Remove ChartLyrics (service is down) 2019-08-03 13:08:14 +02:00
Jonas Kvinge
7b13c0d059 Fix watching new subdirs in collection watcher 2019-08-02 23:58:47 +02:00
Jonas Kvinge
2d3f41da6f Automatically remove devices with old schemas when upgrading 2019-08-02 22:58:30 +02:00
Jonas Kvinge
43b9941dc8 Make sqlite3 fts5 check fatal 2019-08-02 21:12:18 +02:00
Jonas Kvinge
dcf27f54aa Add rpm syntax for mageia 2019-08-02 20:25:46 +02:00
Jonas Kvinge
fbf6b69e75 Update Changelog 2019-08-01 22:01:27 +02:00
Jonas Kvinge
0bfebd90da Add CMAKE_REQUIRED_FLAGS --std=c++11 to check_cxx_source_runs 2019-08-01 21:49:19 +02:00
Jonas Kvinge
e7c3dafa36 Handle a case where the playing widget is gets stuck when switch fast
between context and other widgets
2019-08-01 21:15:46 +02:00
Jonas Kvinge
e90a36da79 Fix track slider popup being stuck 2019-08-01 20:03:37 +02:00
Jonas Kvinge
93f33615ad Don't use check_cxx_source_runs when cross-compiling 2019-07-31 23:06:59 +02:00
Jonas Kvinge
99569081c9 Simply some song checks and make url always unique by using stream url
instead
2019-07-31 22:26:51 +02:00
Jonas Kvinge
588a0b3c41 Add cmake test for sqlite3 FTS5 2019-07-31 20:05:38 +02:00
Jonas Kvinge
4a1118ceb3 Fix macOS build 2019-07-31 20:03:24 +02:00
Jonas Kvinge
a65415bc10 Fix device schema 2019-07-30 22:56:33 +02:00
Jonas Kvinge
8a0e66bf11 Switch to FTS5 with unicode61 (#229)
* Switch to FTS5 with unicode61

* Update required sqlite version in README

* Update README

* Change back db file
2019-07-30 22:45:22 +02:00
Jonas Kvinge
02cda47c28 Disable trackslider popup on macos 2019-07-30 22:11:09 +02:00
Jonas Kvinge
d34a323a81 Handle cases where playlist background album gets stuck on error 2019-07-30 21:32:56 +02:00
Jonas Kvinge
4166ae8db0 Check HttpStatusCodeAttribute 2019-07-30 21:32:20 +02:00
Jonas Kvinge
955b906b52 Add Song() != operator 2019-07-30 21:31:26 +02:00
Jonas Kvinge
0d424aa81e Dont fetch lyrics again if only url is changed through url handler 2019-07-30 21:30:52 +02:00
Jonas Kvinge
80acbfa56a Update contributors 2019-07-30 21:30:08 +02:00
Jonas Kvinge
a7cac24004 Unref pipeline in moodbar on failure 2019-07-28 23:42:12 +02:00
Jonas Kvinge
2927bcf09d Merge branch 'master' of github.com:jonaski/strawberry 2019-07-28 14:58:52 +02:00
Jonas Kvinge
08dee6bb4f Fix error message from url handler 2019-07-28 14:58:34 +02:00
Jonas Kvinge
08c92f906a Update translations 2019-07-27 13:25:51 +02:00
Jonas Kvinge
8e9c9802d1 Change new line to unix 2019-07-27 12:34:27 +02:00
Jonas Kvinge
138df66d5e Use common nsi file 2019-07-27 12:32:28 +02:00
Jonas Kvinge
0a71347e9a Fix playlist shortcuts 2019-07-26 22:46:04 +02:00
Jonas Kvinge
2a541a7b9c Update README 2019-07-26 20:55:20 +02:00
Jonas Kvinge
705c12e8da Update README and Changelog 2019-07-26 20:52:47 +02:00
Jonas Kvinge
cf33df1339 Log system type on startup 2019-07-26 19:24:16 +02:00
Jonas Kvinge
87e543b5ef Fix collection query 2019-07-26 19:14:15 +02:00
Jonas Kvinge
81caec99b7 Fix closing databases 2019-07-25 17:56:28 +02:00
Jonas Kvinge
41484f8673 Fix exit 2019-07-24 23:29:09 +02:00
Jonas Kvinge
da0d61f36a Fix regression in playlist backend caused by previous commits 2019-07-24 21:37:09 +02:00
Jonas Kvinge
6f3bc74db0 Fix cross-compile for windows 2019-07-24 19:34:33 +02:00
Jonas Kvinge
af3bd6ec2f Use QNetworkAccessManager::supportedSchemes() 2019-07-24 19:27:00 +02:00
Jonas Kvinge
b5eb13449b Safely close database connections and delete backends
Also fix NewClosure leak caused by disconnected object signals
2019-07-24 19:16:51 +02:00
Jonas Kvinge
bd78e8c275 Fix memory leaks 2019-07-22 20:53:05 +02:00
Jonas Kvinge
2df21081a1 Fix pixmap cache in collection model
- Properly remove both from pixmap cache, pending art and pending cache keys when songs are deleted
- Increase default pixmap cache
- Clear pixmap cache when model is reset
2019-07-22 19:57:53 +02:00
Jonas Kvinge
ffebff4ea9 Fix uninitialized variable 2019-07-21 21:28:45 +02:00
Jonas Kvinge
2885bc99ca Fix memory leak in Database::BackupFile 2019-07-21 18:50:16 +02:00
Jonas Kvinge
2657b80adb Fix memory leak in tagreader 2019-07-21 15:12:28 +02:00
Jonas Kvinge
ebfc106701 Update libcdio 2019-07-21 13:19:27 +02:00
Jonas Kvinge
4d60ca951d Update Changelog 2019-07-21 00:05:54 +02:00
Jonas Kvinge
acf5c57599 Use InitArtManual in InitFromFilePartial 2019-07-20 22:53:01 +02:00
Jonas Kvinge
927df5ff39 Bump LSMinimumSystemVersion to 10.13.4 2019-07-20 15:26:36 +02:00
Jonas Kvinge
31fc031267 Fix missing qt plugins in macOS travis-ci build (#225) 2019-07-20 15:23:22 +02:00
Jonas Kvinge
02794e0ebd Add libzstd and libtasn1-6 2019-07-20 02:26:44 +02:00
Jonas Kvinge
ea6cce7068 Fix mtp device support 2019-07-19 19:56:37 +02:00
SamTShaw
e4cefeaa8f Ipod Support when listed from Udisks2 (#219)
Udisks2 didn't check to see if the device was actually an ipod, like
GIODeviceLister does.
2019-07-19 19:22:14 +02:00
Jonas Kvinge
d12d5fd8ae Update .travis.yml 2019-07-18 23:55:30 +02:00
Jonas Kvinge
0617c3fdc0 Update .travis.yml 2019-07-18 23:09:01 +02:00
Jonas Kvinge
f00eedf57e Update .travis.yml 2019-07-18 22:12:48 +02:00
Jonas Kvinge
6d36ae6197 Update .travis.yml 2019-07-18 21:35:07 +02:00
Martin Delille
45125abb8f Fix Finder icon (#216)
- Regenerate new strawberry.icns
- Fix Info.plist CFBundleIconFile
- Install Info.plist to strawberry.app
2019-07-17 23:13:15 +02:00
Jonas Kvinge
045b0cd075 Remove bogus svg 2019-07-17 22:35:19 +02:00
Martin Delille
ff3333e1bf Use create-dmg to generate MacOS release (#215) 2019-07-17 22:05:41 +02:00
Martin Delille
7663c5e149 MacOS CI improvement (#214)
* travis ci osx: simpler lib path

* Remove unnecessary sudo
2019-07-17 21:10:17 +02:00
Jonas Kvinge
4d4748a0a8 Update protobuf 2019-07-14 12:26:07 +02:00
Jonas Kvinge
f8f84ed09e Only replace non-ascii characters when not allowing extended ascii 2019-07-14 03:16:53 +02:00
Jonas Kvinge
e7de7ebbfa Use iconv to replace non-ascii characters 2019-07-14 03:08:19 +02:00
Jonas Kvinge
c9f01f4bc4 Remove old devicekit udisks backend 2019-07-13 23:00:25 +02:00
Jonas Kvinge
f2675adc05 Remove vlc, xine and phonon from deb 2019-07-13 22:52:05 +02:00
Jonas Kvinge
75beaa3684 Make sure device is valid before adding it 2019-07-13 18:28:29 +02:00
Jonas Kvinge
079495cc32 Remove usless include in cmake 2019-07-13 18:02:25 +02:00
Jonas Kvinge
c8bd89e56f Remove support for old imobiledevice uuid, it won't work anyway because
of other changes
2019-07-13 17:55:50 +02:00
Jonas Kvinge
b089ba2e04 Free memory of service descriptor and fix possible crashes 2019-07-13 17:33:58 +02:00
Jonas Kvinge
adbf8495c6 Add libgstaiff.so to macdeploy 2019-07-12 20:32:52 +02:00
Jonas Kvinge
ad062862d8 Add device url to mtp loader failure message 2019-07-12 20:32:30 +02:00
Gavin D. Howard
3a86a93154 Extend article sorting to artist and album artist (#210) 2019-07-11 16:51:25 +02:00
Jonas Kvinge
dcf0d6f72d Fix thread crash in mtpdevice 2019-07-11 00:28:19 +02:00
Jonas Kvinge
83d3725240 Fix MessageReply crash in tagreader 2019-07-10 22:40:30 +02:00
Jonas Kvinge
ce1dd69557 Change defaults in device schema 2019-07-10 20:04:05 +02:00
Jonas Kvinge
4081bdd752 Fix ctime in tagreader 2019-07-10 20:02:51 +02:00
Jonas Kvinge
c3f1e312b3 Change defaults in schemas 2019-07-10 20:02:21 +02:00
Jonas Kvinge
d820878b89 Fix oauth checkbox in tidal settings 2019-07-09 22:53:50 +02:00
Jonas Kvinge
7fa1461d5e Use QUrl::isLocalFile() 2019-07-09 21:43:56 +02:00
Jonas Kvinge
f4b1ef4d04 Set initial position of OSDPretty 2019-07-09 20:28:43 +02:00
Jonas Kvinge
656130a739 Replace QDesktopWidget in OSDPretty 2019-07-09 19:49:15 +02:00
Jonas Kvinge
aa8679dff5 Fix TryLoadPixmap and ShowCover 2019-07-09 01:14:58 +02:00
Jonas Kvinge
f94a3095fd Fix TryLoadPixmap and ShowCover 2019-07-09 01:05:42 +02:00
Jonas Kvinge
e11958dd58 Fix index in InternetSearchModel 2019-07-09 01:02:54 +02:00
Jonas Kvinge
a5a251a964 Remove use of QDesktopWidget in QSearchField 2019-07-09 00:05:08 +02:00
Jonas Kvinge
8cb1015a35 Remove use of QDesktopWidget in settingsdialog 2019-07-09 00:04:52 +02:00
Jonas Kvinge
b5dd90b2d5 Check QT_VERSION_CHECK for QImage::sizeInBytes() or QImage::byteCount() 2019-07-08 23:35:43 +02:00
Jonas Kvinge
5f7efee00e ifdef QFontMetrics::horizontalAdvance to make it work with older Qt 2019-07-08 23:27:45 +02:00
Jonas Kvinge
4150e3efde Use QT_VERSION to check whether to use QFileInfo::birthTime() or
QFileInfo::created()
2019-07-08 22:54:13 +02:00
Jonas Kvinge
8ebcb71e6e Replace all uses of QSignalMapper with lambda expressions 2019-07-08 22:27:45 +02:00
Jonas Kvinge
f3e852c042 Replace QImage::byteCount() with sizeInBytes() 2019-07-08 22:25:56 +02:00
Jonas Kvinge
5e2a07d144 Remove unused typedef 2019-07-08 22:24:47 +02:00
Jonas Kvinge
25f6231e9d Replace QString::null with QString() 2019-07-08 22:24:00 +02:00
Jonas Kvinge
beeba88ea5 Replace QModelIndex child() with index() 2019-07-08 22:23:15 +02:00
Jonas Kvinge
cc3d454d60 Add lyrics to edit tag dialog 2019-07-08 22:21:12 +02:00
Jonas Kvinge
afb583cff4 Remove unused typedef 2019-07-08 22:20:41 +02:00
Jonas Kvinge
561fa66393 Replace QFontMetrics::width with horizontalAdvance 2019-07-08 22:20:02 +02:00
Jonas Kvinge
870dc0d36f Replace QFontMetrics::width with horizontalAdvance, dark with darker, background() with window() and QString::null with QString() 2019-07-08 22:19:14 +02:00
Jonas Kvinge
51462dee1e Use QUrl::fromEncoded 2019-07-08 22:10:43 +02:00
Jonas Kvinge
c752d28c6a Change QFileInfo::created() to birthTime(), read lyrics from MP3 files 2019-07-08 22:01:34 +02:00
Jonas Kvinge
d5ca0ca283 Change compiler flags 2019-07-08 21:59:07 +02:00
Jonas Kvinge
f371b3a338 Fix tidal request 2019-07-08 17:08:10 +02:00
Jonas Kvinge
93fc4a2c86 Fix Tidal api URL 2019-07-08 08:10:52 +02:00
Jonas Kvinge
f10d3f86cc Fix Mpris2 AlbumCoverLoaded 2019-07-08 00:13:45 +02:00
Jonas Kvinge
af17b0015b Fix InitArtManual() to use album artist 2019-07-07 21:56:30 +02:00
Jonas Kvinge
61af1d1c72 Update file filter 2019-07-07 21:36:05 +02:00
Jonas Kvinge
65780e1672 Improve album cover searching and cover manager, use HttpStatusCodeAttribute and QSslError for services
- Improve album cover manager
- Change art_automatic and art_manual to QUrl
- Refresh collection album covers when new album covers are fetched
- Fix automatic album cover searching for local files outside of the collection
- Make all Json services check HttpStatusCodeAttribute
- Show detailed SSL errors for Subsonic, Tidal and Qobuz
2019-07-07 21:14:24 +02:00
Jonas Kvinge
c92a7967ea Change filename to url 2019-07-06 14:54:41 +02:00
Jonas Kvinge
60aed593b3 Fix download albumcovers setting 2019-07-06 00:16:13 +02:00
Jonas Kvinge
044f347729 Re-enable tidal oauth settings 2019-07-06 00:02:25 +02:00
Jonas Kvinge
aec9df1882 Switch to queue2 for probe queue (#204) 2019-07-05 23:50:57 +02:00
Jonas Kvinge
4f0a2515f8 Tweak the background image settings a bit
- Disable "do not cut" option when keep aspect ratio is unchecked
- Shorten text and add spacer to widget
2019-07-05 01:07:19 +02:00
Gavin D. Howard
5cde33711e Make playlist ignore articles when sorting (#202)
This is more correct, and the other way is driving me crazy.
2019-07-05 00:13:51 +02:00
Jonas Kvinge
64750025f6 Update libnettle 2019-07-04 22:51:17 +02:00
Jonas Kvinge
cd1cbfdffe Update libhogweed 2019-07-04 22:44:42 +02:00
Jonas Kvinge
d413f2c3a7 Revert "Try queue2 for probe queue"
This reverts commit a9c162476c.
2019-07-03 02:24:32 +02:00
Jonas Kvinge
ba314dd734 Set source in backends to fix losing source in InitFromFilePartial()
when updating path
2019-07-02 00:48:40 +02:00
Jonas Kvinge
9105b7615c Change to reference 2019-07-02 00:48:09 +02:00
Jonas Kvinge
a9c162476c Try queue2 for probe queue 2019-07-02 00:47:10 +02:00
Jonas Kvinge
732b37aca0 Use QMap::contains() 2019-07-01 19:20:57 +02:00
Jonas Kvinge
291b5fad7f Updated Changelog 2019-07-01 01:08:07 +02:00
Jonas Kvinge
c2a6def8b9 Rename cache album covers to download album covers and only do it for
favorite requests
2019-07-01 01:01:30 +02:00
Jonas Kvinge
9083c578cc Add live scanning (#199) 2019-06-30 21:06:07 +02:00
m4x3t
bcfd1d39bb Modify stretch background image functionality (#198)
* Modify stretch background image functionality

Changes the stretch functionality to fill out
the playlist background completely by zooming
the image (if keep aspect ratio is selected)
instead of filling it only height-wise.

* Add option to keep old background fill

* Fix playlist background image width and height

* Fix width calculation

* Remove old calculations
2019-06-30 19:37:05 +02:00
Jonas Kvinge
1185b910c4 Ops 2019-06-29 20:29:37 +02:00
Jonas Kvinge
540b6eba04 Fix hardcoded systemtray icon 2019-06-29 20:18:54 +02:00
Jonas Kvinge
47f4287e64 Merge remote-tracking branch 'origin/musicbrainz' 2019-06-29 19:58:10 +02:00
Jonas Kvinge
264c6e259b Respect rate limiting when fetching tags from musicbrainz 2019-06-29 19:57:20 +02:00
m4x3t
0bbe9838c4 Add option: notification on playback resume (#196)
* Add option: notification on playback resume

This adds an optional setting to show the
notification that is displayed when changing
the track when resuming playback as well.

* Modify resume notification calling

This adds a new signal "Resumed" that is emitted
when the player status is changed from Paused
to Playing.
The AlbumArtLoaded function will only be called
again when playback is manually resumed, and not
when the player is started for the first time
or when the track is changed.
2019-06-29 19:54:27 +02:00
Jonas Kvinge
2fe337eac3 Partial revert travis_terminate 2019-06-29 19:18:26 +02:00
Jonas Kvinge
5d7caafdf7 Terminate if one of the commands fail inside an if statement 2019-06-29 16:31:47 +02:00
Jonas Kvinge
f416ef925b Only create private key if DEPLOY_KEY_ENC is set 2019-06-29 15:57:30 +02:00
Jonas Kvinge
60bd90848b Add tests (#193) 2019-06-28 01:33:22 +02:00
Jonas Kvinge
b9f4407815 Change to const QString& 2019-06-23 18:34:03 +02:00
Jonas Kvinge
f9cd2639ff Remove annoying <year> Remaster from album and song titles 2019-06-23 18:32:15 +02:00
Jonas Kvinge
aeb36e8665 Simplify generating queries in lyrics providers 2019-06-23 16:45:00 +02:00
Jonas Kvinge
057482a3e5 Lower default search limits 2019-06-23 00:20:53 +02:00
Jonas Kvinge
15721da46e Read duration, samplerate and bit depth from stream url replies 2019-06-22 08:39:30 +02:00
Jonas Kvinge
f12b82b5ce Move checkboxes into preferences groupbox in Subsonic settings 2019-06-22 08:38:50 +02:00
Jonas Kvinge
10dc725942 Attempt to fix MessageReply crash when saving tags 2019-06-22 08:36:02 +02:00
Jonas Kvinge
5bd5cdf435 Make sure album_id is not null 2019-06-22 08:33:16 +02:00
Jonas Kvinge
84b3603c08 Fix initialization 2019-06-21 02:26:37 +02:00
Jonas Kvinge
8f59b96731 Update Changelog 2019-06-21 00:12:07 +02:00
Jonas Kvinge
e1de110dd7 Validate configuration better 2019-06-20 20:49:02 +02:00
Jonas Kvinge
8b6fd3d594 Make text selectable 2019-06-20 18:46:14 +02:00
Jonas Kvinge
d7761e8d79 Change parameters to const 2019-06-20 17:09:07 +02:00
Jonas Kvinge
751d652a2f Change title 2019-06-20 17:02:29 +02:00
Jonas Kvinge
647e7e708a Add confirmation box for opening songs in file browser 2019-06-20 17:00:10 +02:00
Jonas Kvinge
505c0eeae2 Set Unknown error if error is missing in Subsonic too 2019-06-20 16:37:37 +02:00
Jonas Kvinge
bf4001968e Change to const references, make search progress and status pass search id 2019-06-20 16:33:28 +02:00
Jonas Kvinge
9d222e2c57 Rename filename to url, change album_id to string and recreate songs tables (#182) 2019-06-20 02:14:44 +02:00
Jonas Kvinge
033300d659 Disable remove favorites from context menu in internetsongsview 2019-06-19 23:26:15 +02:00
Jonas Kvinge
4f2b04bd8f Enable login buttons when login attempt is complete 2019-06-19 23:15:15 +02:00
Jonas Kvinge
f8b9bb4b0f Remove user id and country code setting 2019-06-19 22:20:21 +02:00
Jonas Kvinge
8ce8e320c3 Change ids to qint64 2019-06-19 20:40:11 +02:00
Jonas Kvinge
7c0ab4212b Fix minor code issues with Qobuz 2019-06-19 12:57:12 +02:00
Jonas Kvinge
26633e0982 Fix compile error 2019-06-19 02:39:11 +02:00
Jonas Kvinge
d27a3f1f33 Set Subsonic API version to 1.15.0 2019-06-19 02:30:28 +02:00
Jonas Kvinge
89252d0dba Add Qobuz support (#181) 2019-06-19 02:22:11 +02:00
Jonas Kvinge
dbd2edf442 Fix minor code issues in tidal 2019-06-18 23:39:16 +02:00
Jonas Kvinge
dabd6f8284 Fix Subsonic API path 2019-06-18 23:25:10 +02:00
Jonas Kvinge
beb3ab463f Add missing subsonic fts songs table 2019-06-18 14:41:48 +02:00
Jonas Kvinge
1d67b623e0 Use single url setting instead for subsonic, check http code 2019-06-18 01:22:03 +02:00
Jonas Kvinge
2c8cde4d91 Add scheme setting for subsonic 2019-06-18 00:28:36 +02:00
Jonas Kvinge
8cc1d48115 Fix max concurrent requests in tidal 2019-06-18 00:02:43 +02:00
Jonas Kvinge
ec2468fb8d Remove unneeded include 2019-06-18 00:02:22 +02:00
Jonas Kvinge
7b54cef23b Add Subsonic support (#180) 2019-06-17 23:54:24 +02:00
Jonas Kvinge
a9da8811fc Turn off ssl-strict in gst pipeline 2019-06-17 23:01:38 +02:00
Jonas Kvinge
60e86b9881 Fix fading options 2019-06-17 02:23:51 +02:00
Jonas Kvinge
a6766f3c99 Fix gapless playback when using url handler 2019-06-15 19:32:26 +02:00
Jonas Kvinge
e59c3c6f70 Add MediaUrl function for playlistitems 2019-06-15 19:31:43 +02:00
Jonas Kvinge
49aa344d8b Change index to idx 2019-06-15 19:31:16 +02:00
Jonas Kvinge
4fed6ab298 Hide tidal oauth settings until streaming is possible 2019-06-14 23:02:57 +02:00
Jonas Kvinge
58eab4d3bc Fix verifying xml in tidal stream url 2019-06-14 23:02:33 +02:00
Jonas Kvinge
5ef5da687d Fix macOS build 2019-06-12 06:34:59 +02:00
Jonas Kvinge
4875d319dc Add love button 2019-06-12 00:38:52 +02:00
Jonas Kvinge
fb5a53435e Remove unused function 2019-06-11 19:28:48 +02:00
Jonas Kvinge
4f805d65b3 Fix need_login function 2019-06-11 19:26:00 +02:00
Jonas Kvinge
56ffb0deb1 Fix code challenge in tidal oauth 2019-06-10 02:29:57 +02:00
Jonas Kvinge
c0c1457073 Add optional oauth authentication for tidal 2019-06-09 19:29:25 +02:00
Jonas Kvinge
85a0748ad9 Add x-scheme-handler/tidal to desktop file 2019-06-09 03:10:37 +02:00
Jonas Kvinge
c1939a36dd Change CMakeLists.txt to use list APPEND for Qt5 2019-06-08 22:03:10 +02:00
Jonas Kvinge
b7c394b7a5 Disable fading when volume control is disabled 2019-06-08 12:04:04 +02:00
Jonas Kvinge
a070681f89 Move to private 2019-06-08 12:03:48 +02:00
Jonas Kvinge
d5e424eec8 Fix save/restore group by for internet collection 2019-06-08 00:15:54 +02:00
Jonas Kvinge
e0366d38f1 Change remove from favorites icon 2019-06-08 00:14:11 +02:00
Jonas Kvinge
cbf1d96b16 Avoid duplicate songs in the collection backend 2019-06-07 23:02:43 +02:00
Jonas Kvinge
7cc0d6bb5a Fix ItemFromSong() missing album id 2019-06-07 22:54:34 +02:00
Jonas Kvinge
e19b840ee6 Tidal artist id fixes 2019-06-07 21:02:28 +02:00
Jonas Kvinge
5c2ca1e3d9 Add tidal add/remove favorites + more tidal fixes 2019-06-07 20:23:05 +02:00
Jonas Kvinge
059c4beb30 Improve lyrics searcher 2019-06-06 18:22:41 +02:00
Jonas Kvinge
427808226f Change snap interface to network-manager-observe 2019-06-01 14:29:00 +02:00
Jonas Kvinge
5448245942 Update libprotobuf 2019-05-31 20:47:36 +02:00
Jonas Kvinge
34ab907007 Remove unused code 2019-05-31 20:47:15 +02:00
Jonas Kvinge
e5fde27859 Fix crash in tidal service 2019-05-31 02:32:01 +02:00
Jonas Kvinge
699e8e3ddb Fix schemas 2019-05-31 01:41:17 +02:00
Jonas Kvinge
28ee967371 Fix compile without xinescope 2019-05-31 01:29:56 +02:00
Jonas Kvinge
1b0b5f2554 Remove assert 2019-05-30 19:11:46 +02:00
Jonas Kvinge
1bcc86f989 Fix song search fetchalbums option 2019-05-30 18:46:17 +02:00
Jonas Kvinge
f26f932fd7 Queue tidal requests 2019-05-30 18:06:48 +02:00
Jonas Kvinge
2b7d48ce77 Distinguish albums with same name with album_id 2019-05-30 18:05:07 +02:00
Jonas Kvinge
111712fd6d Add artist_id, album_id and song id to songs 2019-05-30 18:04:30 +02:00
Jonas Kvinge
7609bc181e Implement offset to all Tidal requests 2019-05-29 17:39:51 +02:00
Jonas Kvinge
8b05af7ca3 Make xine analyzer optional 2019-05-28 18:37:51 +02:00
Jonas Kvinge
20f9108ebf Fix artists and albums limit 2019-05-28 17:34:44 +02:00
Jonas Kvinge
cecae7cdc3 Fix xine metronom compile 2019-05-27 21:56:07 +02:00
Jonas Kvinge
e5f3123567 Fix gst_pad_send_event block in ErrorMessageReceived() 2019-05-27 21:39:38 +02:00
Jonas Kvinge
27b0e27cfd initialize search id in the constructor. 2019-05-27 21:38:39 +02:00
Jonas Kvinge
890fba0f61 Add internet tabs view and tidal favorites (#167) 2019-05-27 21:10:37 +02:00
Jonas Kvinge
c4b732ff93 Add proper error handling to local redirectserver 2019-05-21 22:51:53 +02:00
Jonas Kvinge
b8fa2985d5 Fix Tidal SendLogin signal 2019-05-20 19:14:33 +02:00
Jonas Kvinge
ba741fbce8 Exclude version and path from singleapplication, dont start if message
could not be sent.
2019-05-20 18:41:12 +02:00
Jonas Kvinge
67d070c334 Increase default timeout 2019-05-20 18:40:34 +02:00
Jonas Kvinge
8576afe6f5 Fix return value of sendMessage() 2019-05-20 18:39:49 +02:00
Jonas Kvinge
36807fd376 Validate track duration 2019-05-14 19:07:02 +02:00
Jonas Kvinge
2ad1d27a59 Remove stream schema setting and add Add HI_RES option 2019-05-14 18:45:38 +02:00
Jonas Kvinge
7cc9c75d15 Make tidal token configurable 2019-05-13 23:49:09 +02:00
Jonas Kvinge
f33609bbf8 Compare artist and album case-insensitive 2019-05-13 22:38:24 +02:00
Jonas Kvinge
69eeb4b0f8 Move QSearchField to widgets and remove rest of qocoa 2019-05-08 23:34:44 +02:00
Jonas Kvinge
aa583ec1aa Set ContentTypeHeader for Tidal requests 2019-05-08 23:08:29 +02:00
Jonas Kvinge
2b9f153257 Add missing stage packages to snap 2019-05-07 21:04:52 +02:00
Jonas Kvinge
cb9b7fc917 Update appdata desktop file 2019-05-07 17:03:20 +02:00
Jonas Kvinge
74b36c8884 Remove some unneeded interfaces from the snap 2019-05-07 17:02:58 +02:00
Jonas Kvinge
89ff7d6dae Change api url of tidal cover provider 2019-05-06 18:18:31 +02:00
Jonas Kvinge
91df420cb4 Update Dockerfile 2019-05-05 23:51:59 +02:00
Jonas Kvinge
fc25c9f0bc Turn on git revision 2019-05-05 23:51:46 +02:00
Jonas Kvinge
12a27e3a8d Update snap version 2019-05-05 23:28:41 +02:00
Jonas Kvinge
125e32ff00 Release 0.5.5 2019-05-05 21:27:31 +02:00
Jonas Kvinge
4a110633e8 Use customized docker image for travis-ci 2019-05-05 21:20:39 +02:00
Jonas Kvinge
65648f8abd Change Tidal API url 2019-05-05 21:20:28 +02:00
Jonas Kvinge
50174861dc Turn back git revision 2019-05-05 21:20:05 +02:00
409 changed files with 23989 additions and 15137 deletions

View File

@@ -10,45 +10,50 @@ compiler:
- clang
before_install:
- echo $DEPLOY_KEY_ENC | base64 --decode | openssl aes-256-cbc -K $encrypted_83a41ac424a6_key -iv $encrypted_83a41ac424a6_iv -out ~/.ssh/id_rsa -d
- chmod 600 ~/.ssh/id_rsa
- if ! [ "$DEPLOY_KEY_ENC" == "" ]; then
echo $DEPLOY_KEY_ENC | base64 --decode | openssl aes-256-cbc -K $encrypted_83a41ac424a6_key -iv $encrypted_83a41ac424a6_iv -out ~/.ssh/id_rsa -d ;
chmod 600 ~/.ssh/id_rsa ;
fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
docker build -f Dockerfile -t strawberry-build .;
docker run --name build -itd strawberry-build /bin/bash;
docker build -f Dockerfile -t strawberry-build . || travis_terminate 1;
docker run --name build -itd strawberry-build /bin/bash || travis_terminate 1;
docker exec build git clone https://github.com/jonaski/strawberry;
fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
git fetch --unshallow;
git pull;
brew update;
brew unlink python;
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw;
brew install sqlite --with-fts;
brew install gstreamer gst-plugins-base;
brew install gst-plugins-good --with-flac;
brew install gst-plugins-bad gst-plugins-ugly gst-libav;
brew install chromaprint;
git fetch --unshallow || travis_terminate 1;
git pull || travis_terminate 1;
brew update || travis_terminate 1;
brew unlink python || travis_terminate 1;
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint;
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;
export Qt5_DIR=/usr/local/opt/qt5/lib/cmake;
export Qt5LinguistTools_DIR=/usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt | head -n1)/lib/cmake/Qt5LinguistTools;
export Qt5LinguistTools_DIR=/usr/local/opt/qt5/lib/cmake/Qt5LinguistTools;
export PATH="/usr/local/opt/gettext/bin:$PATH";
export PKG_CONFIG_PATH=/usr/local/Cellar/libffi/$(ls /usr/local/Cellar/libffi | head -n1)/lib/pkgconfig/:$PKG_CONFIG_PATH;
export PKG_CONFIG_PATH=/usr/local/opt/libffi/lib/pkgconfig/:$PKG_CONFIG_PATH;
ls /usr/local/lib/gstreamer-1.0;
ls /usr/local/lib/gio/modules;
fi
before_script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild -DENABLE_TRANSLATIONS=ON ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DENABLE_TRANSLATIONS=ON ; fi
- 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
script:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
make -j8;
sudo make install;
sudo ../dist/macos/macdeploy.py strawberry.app;
../dist/macos/create-dmg.sh strawberry.app $CC_FOR_BUILD;
make -j8 || travis_terminate 1;
make install || travis_terminate 1;
sudo make dmg;
fi
after_success:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ls -lh strawberry.dmg; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$TRAVIS_BRANCH" == "master" ]]; then rsync -e "ssh -o StrictHostKeyChecking=no" -va strawberry*.dmg travis@echoes.jkvinge.net:/home/travis/builds/macos; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ls -lh strawberry*.dmg; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$CC_FOR_BUILD" == "gcc" ]] && [ -f ~/.ssh/id_rsa ]; then
if [[ "$TRAVIS_BRANCH" == "master" ]]; then
rsync -e "ssh -o StrictHostKeyChecking=no" -va strawberry*.dmg travis@echoes.jkvinge.net:/home/travis/builds/macos;
elif [[ "$TRAVIS_BRANCH" == "macos" ]]; then
rsync -e "ssh -o StrictHostKeyChecking=no" -va strawberry*.dmg travis@echoes.jkvinge.net:/home/travis/builds/macos-test;
fi
fi
branches:
except:

8
3rdparty/README.md vendored
View File

@@ -42,14 +42,6 @@ This is 2 header files used by taglib, but kept in a seperate directory because
URL: http://utfcpp.sourceforge.net/
qocoa
-----
This is a small static library currently used for the search fields above the collection, playlist and in
the cover manager. It is slightly modified from original version.
URL: https://github.com/mikemcquaid/Qocoa
SPMediaKeyTap
-------------

View File

@@ -1,38 +0,0 @@
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__")
set(SOURCES)
set(HEADERS
qsearchfield.h
qbutton.h
qprogressindicatorspinning.h
)
qt5_wrap_cpp(MOC_SOURCES ${HEADERS})
if(APPLE)
list(APPEND SOURCES
qsearchfield_mac.mm
qbutton_mac.mm
qprogressindicatorspinning_mac.mm
)
else()
list(APPEND SOURCES
qsearchfield_nonmac.cpp
qbutton_nonmac.cpp
qprogressindicatorspinning_nonmac.cpp
)
set(RESOURCES
qsearchfield_nonmac.qrc
qprogressindicatorspinning_nonmac.qrc
)
qt5_add_resources(RESOURCES_SOURCES ${RESOURCES})
endif()
add_library(Qocoa STATIC ${SOURCES} ${MOC_SOURCES} ${RESOURCES_SOURCES})
target_link_libraries(Qocoa ${QT_LIBRARIES})

View File

@@ -1,19 +0,0 @@
Copyright (C) 2011 by Mike McQuaid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,38 +0,0 @@
# Qocoa
Qocoa is a collection of Qt wrappers for OSX's Cocoa widgets.
## Features
- basic fallback to sensible Qt types on non-OSX platforms
- shared class headers which expose no implementation details
- typical Qt signal/slot-based API
- trivial to import into projects (class header/implementation, [single shared global header](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h))
## Building
```
git clone git://github.com/mikemcquaid/Qocoa.git
cd Qocoa
qmake # or cmake .
make
```
## Status
I'm not personally working on this any more but will accept pull-requests.
[![Build Status](https://travis-ci.org/MikeMcQuaid/Qocoa.svg?branch=master)](https://travis-ci.org/MikeMcQuaid/Qocoa)
## Usage
For each class you want to use copy the [`qocoa_mac.h`](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h), `$CLASS.h`, `$CLASS_mac.*` and `$CLASS_nonmac.*` files into your source tree and add them to your buildsystem. Examples are provided for [CMake](https://github.com/mikemcquaid/Qocoa/blob/master/CMakeLists.txt) and [QMake](https://github.com/mikemcquaid/Qocoa/blob/master/Qocoa.pro).
## Contact
[Mike McQuaid](mailto:mike@mikemcquaid.com)
## License
Qocoa is licensed under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
The full license text is available in [LICENSE.txt](https://github.com/mikemcquaid/Qocoa/blob/master/LICENSE.txt).
Magnifier and EditClear icons taken from [QtCreator](http://qt-project.org/) and are licensed under the [LGPL](http://www.gnu.org/copyleft/lesser.html).
Other icons are taken from the [Oxygen Project](http://www.oxygen-icons.org/) and are licensed under the [Creative Commons Attribution-ShareAlike 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/).
## Gallery
![Qocoa Gallery](https://github.com/mikemcquaid/Qocoa/raw/master/gallery.png)

View File

@@ -1,13 +0,0 @@
Widgets I hope to implement (or at least investigate):
- NSTokenField
- NSSegmentedControl
- NSLevelIndicator
- NSPathControl
- NSSlider (Circular)
- NSSplitView
- NSTextFinder
- NSOutlineView in an NSScrollView (Source List)
- NSDrawer
- PDFView
- WebView

View File

@@ -1,49 +0,0 @@
#ifndef QBUTTON_H
#define QBUTTON_H
#include <QWidget>
#include <QPointer>
class QButtonPrivate;
class QButton : public QWidget
{
Q_OBJECT
public:
// Matches NSBezelStyle
enum BezelStyle {
Rounded = 1,
RegularSquare = 2,
Disclosure = 5,
ShadowlessSquare = 6,
Circular = 7,
TexturedSquare = 8,
HelpButton = 9,
SmallSquare = 10,
TexturedRounded = 11,
RoundRect = 12,
Recessed = 13,
RoundedDisclosure = 14,
#ifdef __MAC_10_7
Inline = 15
#endif
};
explicit QButton(QWidget *parent, BezelStyle bezelStyle = Rounded);
public slots:
void setText(const QString &text);
void setImage(const QPixmap &image);
void setChecked(bool checked);
public:
void setCheckable(bool checkable);
bool isChecked();
signals:
void clicked(bool checked = false);
private:
friend class QButtonPrivate;
QPointer<QButtonPrivate> pimpl;
};
#endif // QBUTTON_H

View File

@@ -1,229 +0,0 @@
/*
Copyright (C) 2011 by Mike McQuaid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "qbutton.h"
#include "qocoa_mac.h"
#import "Foundation/NSAutoreleasePool.h"
#import "AppKit/NSButton.h"
#import "AppKit/NSFont.h"
class QButtonPrivate : public QObject
{
public:
QButtonPrivate(QButton *qButton, NSButton *nsButton, QButton::BezelStyle bezelStyle)
: QObject(qButton), qButton(qButton), nsButton(nsButton)
{
switch(bezelStyle) {
case QButton::Disclosure:
case QButton::Circular:
#ifdef __MAC_10_7
case QButton::Inline:
#endif
case QButton::RoundedDisclosure:
case QButton::HelpButton:
[nsButton setTitle:@""];
default:
break;
}
NSFont* font = 0;
switch(bezelStyle) {
case QButton::RoundRect:
font = [NSFont fontWithName:@"Lucida Grande" size:12];
break;
case QButton::Recessed:
font = [NSFont fontWithName:@"Lucida Grande Bold" size:12];
break;
#ifdef __MAC_10_7
case QButton::Inline:
font = [NSFont boldSystemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
break;
#endif
default:
font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
break;
}
[nsButton setFont:font];
switch(bezelStyle) {
case QButton::Rounded:
qButton->setMinimumWidth(40);
qButton->setFixedHeight(24);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
break;
case QButton::RegularSquare:
case QButton::TexturedSquare:
qButton->setMinimumSize(14, 23);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
break;
case QButton::ShadowlessSquare:
qButton->setMinimumSize(5, 25);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
break;
case QButton::SmallSquare:
qButton->setMinimumSize(4, 21);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
break;
case QButton::TexturedRounded:
qButton->setMinimumSize(10, 22);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
break;
case QButton::RoundRect:
case QButton::Recessed:
qButton->setMinimumWidth(16);
qButton->setFixedHeight(18);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
break;
case QButton::Disclosure:
qButton->setMinimumWidth(13);
qButton->setFixedHeight(13);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
break;
case QButton::Circular:
qButton->setMinimumSize(16, 16);
qButton->setMaximumHeight(40);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
break;
case QButton::HelpButton:
case QButton::RoundedDisclosure:
qButton->setMinimumWidth(22);
qButton->setFixedHeight(22);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
break;
#ifdef __MAC_10_7
case QButton::Inline:
qButton->setMinimumWidth(10);
qButton->setFixedHeight(16);
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
break;
#endif
}
switch(bezelStyle) {
case QButton::Recessed:
[nsButton setButtonType:NSPushOnPushOffButton];
case QButton::Disclosure:
[nsButton setButtonType:NSOnOffButton];
default:
[nsButton setButtonType:NSMomentaryPushInButton];
}
[nsButton setBezelStyle:(__bridge NSBezelStyle)bezelStyle];
}
void clicked()
{
emit qButton->clicked(qButton->isChecked());
}
~QButtonPrivate() {
[[nsButton target] release];
[nsButton setTarget:nil];
}
QButton *qButton;
NSButton *nsButton;
};
@interface QButtonTarget : NSObject
{
@public
QPointer<QButtonPrivate> pimpl;
}
-(void)clicked;
@end
@implementation QButtonTarget
-(void)clicked {
Q_ASSERT(pimpl);
if (pimpl)
pimpl->clicked();
}
@end
QButton::QButton(QWidget *parent, BezelStyle bezelStyle) : QWidget(parent)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSButton *button = [[NSButton alloc] init];
pimpl = new QButtonPrivate(this, button, bezelStyle);
QButtonTarget *target = [[QButtonTarget alloc] init];
target->pimpl = pimpl;
[button setTarget:target];
[button setAction:@selector(clicked)];
setupLayout(button, this);
[button release];
[pool drain];
}
void QButton::setText(const QString &text)
{
Q_ASSERT(pimpl);
if (!pimpl)
return;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[pimpl->nsButton setTitle:fromQString(text)];
[pool drain];
}
void QButton::setImage(const QPixmap &image)
{
Q_ASSERT(pimpl);
if (pimpl)
[pimpl->nsButton setImage:fromQPixmap(image)];
}
void QButton::setChecked(bool checked)
{
Q_ASSERT(pimpl);
if (pimpl)
[pimpl->nsButton setState:checked];
}
void QButton::setCheckable(bool checkable)
{
const NSInteger cellMask = checkable ? NSChangeBackgroundCellMask : NSNoCellMask;
Q_ASSERT(pimpl);
if (pimpl)
[[pimpl->nsButton cell] setShowsStateBy:cellMask];
}
bool QButton::isChecked()
{
Q_ASSERT(pimpl);
if (!pimpl)
return false;
return [pimpl->nsButton state];
}

View File

@@ -1,89 +0,0 @@
/*
Copyright (C) 2011 by Mike McQuaid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "qbutton.h"
#include <QToolBar>
#include <QToolButton>
#include <QPushButton>
#include <QVBoxLayout>
class QButtonPrivate : public QObject
{
public:
QButtonPrivate(QButton *button, QAbstractButton *abstractButton)
: QObject(button), abstractButton(abstractButton) {}
QPointer<QAbstractButton> abstractButton;
};
QButton::QButton(QWidget *parent, BezelStyle) : QWidget(parent)
{
QAbstractButton *button = 0;
if (qobject_cast<QToolBar*>(parent))
button = new QToolButton(this);
else
button = new QPushButton(this);
connect(button, SIGNAL(clicked()),
this, SIGNAL(clicked()));
pimpl = new QButtonPrivate(this, button);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->addWidget(button);
}
void QButton::setText(const QString &text)
{
Q_ASSERT(pimpl);
if (pimpl)
pimpl->abstractButton->setText(text);
}
void QButton::setImage(const QPixmap &image)
{
Q_ASSERT(pimpl);
if (pimpl)
pimpl->abstractButton->setIcon(image);
}
void QButton::setChecked(bool checked)
{
Q_ASSERT(pimpl);
if (pimpl)
pimpl->abstractButton->setChecked(checked);
}
void QButton::setCheckable(bool checkable)
{
Q_ASSERT(pimpl);
if (pimpl)
pimpl->abstractButton->setCheckable(checkable);
}
bool QButton::isChecked()
{
Q_ASSERT(pimpl);
if (!pimpl)
return false;
return pimpl->abstractButton->isChecked();
}

View File

@@ -1,29 +0,0 @@
#ifndef QPROGRESSINDICATORSPINNING_H
#define QPROGRESSINDICATORSPINNING_H
#include <QWidget>
#include <QPointer>
class QProgressIndicatorSpinningPrivate;
class QProgressIndicatorSpinning : public QWidget
{
Q_OBJECT
public:
// Matches NSProgressIndicatorThickness
enum Thickness {
Default = 14,
Small = 10,
Large = 18,
Aqua = 12
};
explicit QProgressIndicatorSpinning(QWidget *parent,
Thickness thickness = Default);
public slots:
void animate(bool animate = true);
private:
friend class QProgressIndicatorSpinningPrivate;
QPointer<QProgressIndicatorSpinningPrivate> pimpl;
};
#endif // QPROGRESSINDICATORSPINNING_H

View File

@@ -1,70 +0,0 @@
/*
Copyright (C) 2011 by Mike McQuaid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "qprogressindicatorspinning.h"
#include "qocoa_mac.h"
#import "Foundation/NSAutoreleasePool.h"
#import "AppKit/NSProgressIndicator.h"
class QProgressIndicatorSpinningPrivate : public QObject
{
public:
QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning,
NSProgressIndicator *nsProgressIndicator)
: QObject(qProgressIndicatorSpinning), nsProgressIndicator(nsProgressIndicator) {}
NSProgressIndicator *nsProgressIndicator;
};
QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent,
Thickness thickness)
: QWidget(parent)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSProgressIndicator *progress = [[NSProgressIndicator alloc] init];
[progress setStyle:NSProgressIndicatorSpinningStyle];
pimpl = new QProgressIndicatorSpinningPrivate(this, progress);
setupLayout(progress, this);
setFixedSize(thickness, thickness);
[progress release];
[pool drain];
}
void QProgressIndicatorSpinning::animate(bool animate)
{
Q_ASSERT(pimpl);
if (!pimpl)
return;
if (animate)
[pimpl->nsProgressIndicator startAnimation:nil];
else
[pimpl->nsProgressIndicator stopAnimation:nil];
}

View File

@@ -1,72 +0,0 @@
/*
Copyright (C) 2011 by Mike McQuaid
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "qprogressindicatorspinning.h"
#include <QVBoxLayout>
#include <QMovie>
#include <QLabel>
class QProgressIndicatorSpinningPrivate : public QObject
{
public:
QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning,
QMovie *movie)
: QObject(qProgressIndicatorSpinning), movie(movie) {}
QPointer<QMovie> movie;
};
QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent,
Thickness thickness)
: QWidget(parent)
{
QVBoxLayout *layout = new QVBoxLayout(this);
layout->setMargin(0);
QSize size(thickness, thickness);
QMovie *movie = new QMovie(this);
movie->setFileName(":/Qocoa/qprogressindicatorspinning_nonmac.gif");
movie->setScaledSize(size);
// Roughly match OSX speed.
movie->setSpeed(200);
pimpl = new QProgressIndicatorSpinningPrivate(this, movie);
QLabel *label = new QLabel(this);
label->setMovie(movie);
layout->addWidget(label);
setFixedSize(size);
}
void QProgressIndicatorSpinning::animate(bool animate)
{
Q_ASSERT(pimpl && pimpl->movie);
if (!(pimpl && pimpl->movie))
return;
if (animate)
pimpl->movie->start();
else
pimpl->movie->stop();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,5 +0,0 @@
<RCC>
<qresource prefix="/Qocoa">
<file>qprogressindicatorspinning_nonmac.gif</file>
</qresource>
</RCC>

View File

@@ -1,7 +0,0 @@
<RCC>
<qresource prefix="/Qocoa">
<file>qsearchfield_nonmac_clear.png</file>
<file>qsearchfield_nonmac_magnifier_menu.png</file>
<file>qsearchfield_nonmac_magnifier.png</file>
</qresource>
</RCC>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 439 B

View File

@@ -2,7 +2,7 @@ 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 -Woverloaded-virtual -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-local-typedefs -fpermissive")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Woverloaded-virtual -Wno-sign-compare -fpermissive")
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)

View File

@@ -169,7 +169,7 @@ bool SingleApplication::sendMessage( QByteArray message, int timeout )
d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect );
d->socket->write( message );
bool dataWritten = d->socket->flush();
d->socket->waitForBytesWritten( timeout );
bool dataWritten = d->socket->waitForBytesWritten( timeout );
d->socket->flush();
return dataWritten;
}

View File

@@ -114,7 +114,7 @@ public:
* @note sendMessage() will return false if invoked from the primary
* instance.
*/
bool sendMessage( QByteArray message, int timeout = 100 );
bool sendMessage( QByteArray message, int timeout = 1000 );
Q_SIGNALS:
void instanceStarted();

View File

@@ -169,7 +169,7 @@ bool SingleCoreApplication::sendMessage( QByteArray message, int timeout )
d->connectToPrimary( timeout, SingleCoreApplicationPrivate::Reconnect );
d->socket->write( message );
bool dataWritten = d->socket->flush();
d->socket->waitForBytesWritten( timeout );
bool dataWritten = d->socket->waitForBytesWritten( timeout );
d->socket->flush();
return dataWritten;
}

View File

@@ -114,7 +114,7 @@ public:
* @note sendMessage() will return false if invoked from the primary
* instance.
*/
bool sendMessage( QByteArray message, int timeout = 100 );
bool sendMessage( QByteArray message, int timeout = 1000 );
Q_SIGNALS:
void instanceStarted();

View File

@@ -2,7 +2,7 @@ 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-deprecated-declarations -Wno-unused-local-typedefs -Wno-delete-non-virtual-dtor")
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")
set(TAGLIB_SOVERSION_CURRENT 17)
set(TAGLIB_SOVERSION_REVISION 0)

View File

@@ -21,6 +21,7 @@ if(CMAKE_VERSION VERSION_GREATER 3.0)
endif()
include(CheckCXXCompilerFlag)
include(CheckCXXSourceRuns)
include(CheckIncludeFiles)
include(FindPkgConfig)
include(cmake/C++11Compat.cmake)
@@ -105,7 +106,7 @@ pkg_check_modules(GSTREAMER_TAG gstreamer-tag-1.0)
pkg_check_modules(LIBXINE libxine)
pkg_check_modules(LIBVLC libvlc)
pkg_check_modules(PHONON phonon4qt5)
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7)
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.9)
pkg_check_modules(LIBPULSE libpulse)
pkg_check_modules(CHROMAPRINT libchromaprint)
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
@@ -122,34 +123,37 @@ endif(WIN32)
# QT
set(QT_MIN_VERSION 5.5)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql)
set(QT_COMPONENTS Core Concurrent Widgets Network Sql)
if(X11_FOUND)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras)
list(APPEND QT_COMPONENTS X11Extras)
endif()
if(DBUS_FOUND)
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS DBus)
list(APPEND QT_COMPONENTS DBus)
endif()
if(APPLE)
list(APPEND QT_COMPONENTS MacExtras)
endif()
if(WIN32)
list(APPEND QT_COMPONENTS WinExtras)
endif()
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED ${QT_COMPONENTS})
set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Concurrent_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Sql_LIBRARIES})
if(Qt5DBus_FOUND)
list(APPEND QT_LIBRARIES ${Qt5DBus_LIBRARIES})
get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION)
endif()
if(APPLE)
find_package(Qt5 REQUIRED COMPONENTS MacExtras)
if(Qt5X11Extras_FOUND)
list(APPEND QT_LIBRARIES ${Qt5X11Extras_LIBRARIES})
endif()
if(WIN32)
find_package(Qt5 REQUIRED COMPONENTS WinExtras)
if(Qt5MacExtras_FOUND)
list(APPEND QT_LIBRARIES ${Qt5MacExtras_LIBRARIES})
endif()
set(QT_LIBRARIES Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network Qt5::Sql)
if(DBUS_FOUND)
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::DBus)
endif()
if(X11_FOUND)
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::X11Extras)
endif()
if(APPLE)
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::MacExtras)
endif()
if(WIN32)
set(QT_LIBRARIES ${QT_LIBRARIES} Qt5::WinExtras)
if(Qt5WinExtras_FOUND)
list(APPEND QT_LIBRARIES ${Qt5WinExtras_LIBRARIES})
endif()
find_package(Qt5LinguistTools CONFIG)
@@ -236,10 +240,6 @@ else(USE_SYSTEM_SINGLEAPPLICATION)
unset(SINGLECOREAPPLICATION_LIBRARY_DIRS)
endif(USE_SYSTEM_SINGLEAPPLICATION)
# Qocoa
set(QOCOA_LIBRARIES Qocoa)
add_subdirectory(3rdparty/qocoa)
if (APPLE)
find_library(SPARKLE Sparkle)
add_subdirectory(3rdparty/SPMediaKeyTap)
@@ -307,10 +307,6 @@ optional_component(AUDIOCD ON "Devices: Audio CD support"
DEPENDS "libcdio" CDIO_FOUND
)
optional_component(DEVICEKIT ON "Devices: DeviceKit backend"
DEPENDS "D-Bus support" DBUS_FOUND
)
optional_component(UDISKS2 ON "Devices: UDisks2 backend"
DEPENDS "D-Bus support" DBUS_FOUND
)
@@ -346,6 +342,8 @@ optional_component(TRANSLATIONS ON "Translations"
)
optional_component(TIDAL ON "Tidal support")
optional_component(QOBUZ ON "Qobuz support")
optional_component(SUBSONIC ON "Subsonic support")
optional_component(MOODBAR ON "Moodbar"
DEPENDS "fftw3" FFTW3_FOUND
@@ -361,6 +359,41 @@ if (APPLE AND USE_BUNDLE AND NOT USE_BUNDLE_DIR)
set(USE_BUNDLE_DIR "../PlugIns")
endif()
# Check that we have sqlite3 with FTS5
if(NOT CMAKE_CROSSCOMPILING)
set(CMAKE_REQUIRED_FLAGS "--std=c++11")
set(CMAKE_REQUIRED_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Sql_LIBRARIES})
set(CMAKE_REQUIRED_INCLUDES ${Qt5Core_INCLUDE_DIRS} ${Qt5Sql_INCLUDE_DIRS})
check_cxx_source_runs("
#include <QSqlDatabase>
#include <QSqlQuery>
int main() {
QSqlDatabase db = QSqlDatabase::addDatabase(\"QSQLITE\");
db.setDatabaseName(\":memory:\");
if (!db.open()) { return 1; }
QSqlQuery q(db);
q.prepare(\"CREATE VIRTUAL TABLE test_fts USING fts5(test, tokenize = 'unicode61 remove_diacritics 0');\");
if (!q.exec()) return 1;
}
"
SQLITE3_FTS5
)
endif()
if(HAVE_XINE)
check_cxx_source_compiles("
#define METRONOM_INTERNAL
#include <iostream>
#include <xine/metronom.h>
int main() {
metronom_t metronom;
std::cout << metronom.pts_per_smpls;
return 0;
}
"
XINE_ANALYZER)
endif()
# Set up definitions and paths
@@ -374,13 +407,10 @@ include_directories(${GLIB_INCLUDE_DIRS})
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
include_directories(${TAGLIB_INCLUDE_DIRS})
if(HAVE_IMOBILEDEVICE AND LIBIMOBILEDEVICE_VERSION VERSION_GREATER 1.1.1)
set(IMOBILEDEVICE_USES_UDIDS ON)
endif()
# Subdirectories
add_subdirectory(src)
add_subdirectory(dist)
add_subdirectory(tests)
add_subdirectory(ext/libstrawberry-common)
add_subdirectory(ext/libstrawberry-tagreader)
add_subdirectory(ext/strawberry-tagreader)
@@ -404,3 +434,7 @@ if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON)
elseif(NOT HAVE_GSTREAMER)
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
endif()
if(NOT SQLITE3_FTS5 AND NOT CMAKE_CROSSCOMPILING)
message(WARNING "sqlite3 must be enabled with FTS5. See: https://www.sqlite.org/fts5.html")
endif()

View File

@@ -2,6 +2,60 @@ Strawberry Music Player
=======================
ChangeLog
Version 0.6.2:
* Disabled fatal error for FTS5 cmake test.
Version 0.6.1:
* Compare artist and album case-insensitive when generating score for album covers.
* Fixed broken return value of sendMessage() in SingleApplication causing application to be started twice.
* Improved error handling in local redirectserver.
* Added new tabs view with search and favorites to Tidal.
* Fixed gst_pad_send_event lock in gstreamer pipeline.
* Made Xine analyzer optional to fix compilation with newer Xine.
* Implemented offset and queue to all Tidal requests.
* Added new artist, album and song ids to songs schemas to add/remove favorites.
* Improved lyrics searcher.
* Fixed disabling fading option in backend settings when volume control is disabled.
* Added x-scheme-handler/tidal to desktop file to handle tidal songs and allow OAuth redirect url.
* Added love button for scrobblers.
* Fixed gapless playback when using url handler.
* Fixed enabling/disabling fading options in backend settings.
* Added support for Subsonic streaming.
* Added support for Qobuz streaming.
* Added confirmation box for opening songs in file browser to avoid users accidentally opening too many songs.
* Added OSD notification on playback resume option.
* Fixed MusicBrainz tag fetcher to respect rate limiting when fetching tags.
* Fixed hardcoded systemtray icon.
* Added live scanning and option to rescan songs.
* Added playlist background image stretch option to zoom image with cutting the height.
* Replaced use of QDesktopWidget with QDesktop
* Replaced all uses of QSignalMapper with lambda expressions
* Fixed collection album covers stuck to old ones when new album covers are fetched
* Fixed all Json services to check HttpStatusCodeAttribute in addition to checking network errors
* Fixed track change hang
* Fixed playlist sorting to ignore articles
* Fixed MessageReply crash in tagreader
* Fixed MTP support
* Fixed possible crashes with libimobiledevice devices
* Removed older devicekit udisks backend
* Using iconv to replace non-ascii characters when organising files
* Fixed IPod support when listed from UDisks2
* Fixed memory leaks when establishing database connections and in database backup.
* Fixed dangling database connections when loading collection, playlists and devices.
* Fixed closing and deleting backends to free memory and database connections on exit.
* Fixed dangling pointers causing crashes when loading new album covers in collection.
* Fixed playlist shortcuts being broken because they were hidden in playlist right click menu.
* Replaced FTS3 and custom tokenizer with FTS5 with unicode61.
* Fixed certain cases where track slider popup was stuck.
* Fixed certain cases where the playing widget gets stuck when switching fast between context and other widgets.
* Removed ChartLyrics provider (service have been down for a long time).
Version 0.5.5:
* Fixed Tidal API url
Version 0.5.4:
* Changed description for offline mode scrobbling for less confusion

View File

@@ -1,16 +1,4 @@
from opensuse/leap
run zypper --non-interactive --gpg-auto-import-keys ref
run zypper --non-interactive --gpg-auto-import-keys dup -l -y
run zypper --non-interactive --gpg-auto-import-keys install \
lsb-release git tar make cmake gcc gcc-c++ pkg-config gettext-tools \
glibc-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libpulse-devel libnotify-devel libgnutls-devel \
boost-devel protobuf-devel sqlite3-devel taglib-devel fftw3-devel \
gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel \
libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel \
libQt5DBus-devel libqt5-qtx11extras-devel libqt5-qtbase-common-devel libqt5-linguist-devel \
libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel
from jonaski/opensuse:tumbleweed
run mkdir -p /usr/src/app
workdir /usr/src/app

View File

@@ -20,30 +20,31 @@ Strawberry is a music player and music collection organizer. It is a fork of Cle
* Edit tags on music files
* Fetch tags from MusicBrainz
* Album cover art from Last.fm, Musicbrainz, Discogs, Deezer and Tidal
* Song lyrics from AudD and ChartLyrics
* Song lyrics from AudD
* Support for multiple backends
* Audio analyzer
* Audio equalizer
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
* Streaming support for Tidal
* Streaming support for Tidal, Qobuz and Subsonic
* Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
It has so far been tested to work on Linux, OpenBSD, macOS and Windows.
**We do not provide releases for macOS, only exprimental builds, they may have issues. There currently isn't any macOS developers actively working on this project.**
### :heavy_exclamation_mark: Requirements
To build Strawberry from source you need the following installed on your system with the additional development packages/headers:
* [GLib, GIO and GObject](https://developer.gnome.org/glib/)
* [POSIX thread (pthread) libraries](http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html)
* [CMake and Make tools](https://cmake.org/)
* [GCC](https://gcc.gnu.org/) or [clang](https://clang.llvm.org/) compiler
* [Boost](https://www.boost.org/)
* [POSIX thread (pthread)](http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html)
* [GLib](https://developer.gnome.org/glib/)
* [Protobuf library and compiler](https://developers.google.com/protocol-buffers/)
* [Boost development headers](https://www.boost.org/)
* [Qt 5 with components Core, Gui, Widgets, Concurrent, Network and Sql](https://www.qt.io/)
* [Qt 5.5 or higher with components Core, Gui, Widgets, Concurrent, Network and Sql](https://www.qt.io/)
* [Qt 5 components X11Extras and DBus for Linux/BSD, MacExtras for macOS and WinExtras for Windows](https://www.qt.io/)
* [SQLite3](https://www.sqlite.org)
* [TagLib 1.11.1 or higher](http://taglib.org/)
* [SQLite 3.9 or newer with FTS5](https://www.sqlite.org)
* [Chromaprint library](https://acoustid.org/chromaprint)
* [ALSA library (linux)](https://www.alsa-project.org/)
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
@@ -70,14 +71,12 @@ You should also install the gstreamer plugins base and good, and optionally bad
### Compile and install:
mkdir strawberry-build
cd strawberry-build
cmake ../strawberry
make -j8
cd strawberry
mkdir build && cd build
cmake ..
make -j4
sudo make install
(dont change to the source directory, if you created the build directory inside the source directory type: cmake .. instead).
### :penguin: Packaging status
[![Packaging status](https://repology.org/badge/vertical-allrepos/strawberry.svg)](https://repology.org/metapackage/strawberry/versions)

View File

@@ -1,4 +1,5 @@
add_custom_target(dmg
COMMAND sudo /usr/local/opt/qt5/bin/macdeployqt strawberry.app
COMMAND sudo ${CMAKE_SOURCE_DIR}/dist/macos/macdeploy.py strawberry.app
COMMAND sudo ${CMAKE_SOURCE_DIR}/dist/macos/create-dmg.sh strawberry.app
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}

View File

@@ -40,27 +40,27 @@ if (LSB_RELEASE_EXEC AND RPMBUILD_EXEC)
else()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
add_custom_target(rpm
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
)
elseif (${DIST_NAME} STREQUAL "fedora")
if (DIST_VERSION)
set(RPM_DISTRO "fc${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
else ()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
add_custom_target(rpm
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
)
elseif (${DIST_NAME} STREQUAL "mageia")
if (DIST_VERSION)
set(RPM_DISTRO "${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
else ()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
else()
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
endif()
message(STATUS "RPM Suffix: ${RPM_DISTRO}")
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
)
endif()
endif()

View File

@@ -1,6 +1,6 @@
set(STRAWBERRY_VERSION_MAJOR 0)
set(STRAWBERRY_VERSION_MINOR 5)
set(STRAWBERRY_VERSION_PATCH 4)
set(STRAWBERRY_VERSION_MINOR 6)
set(STRAWBERRY_VERSION_PATCH 2)
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
set(INCLUDE_GIT_REVISION OFF)

View File

@@ -4,6 +4,12 @@
<file>schema/schema-1.sql</file>
<file>schema/schema-2.sql</file>
<file>schema/schema-3.sql</file>
<file>schema/schema-4.sql</file>
<file>schema/schema-5.sql</file>
<file>schema/schema-6.sql</file>
<file>schema/schema-7.sql</file>
<file>schema/schema-8.sql</file>
<file>schema/schema-9.sql</file>
<file>schema/device-schema.sql</file>
<file>style/strawberry.css</file>
<file>html/playing-tooltip-plain.html</file>

View File

@@ -70,7 +70,6 @@
<file>icons/128x128/star-grey.png</file>
<file>icons/128x128/star.png</file>
<file>icons/128x128/strawberry.png</file>
<file>icons/128x128/strawberry.svg</file>
<file>icons/128x128/tools-wizard.png</file>
<file>icons/128x128/view-choose.png</file>
<file>icons/128x128/view-fullscreen.png</file>
@@ -83,10 +82,13 @@
<file>icons/128x128/xine.png</file>
<file>icons/128x128/zoom-in.png</file>
<file>icons/128x128/zoom-out.png</file>
<file>icons/128x128/tidal.png</file>
<file>icons/128x128/scrobble.png</file>
<file>icons/128x128/scrobble-disabled.png</file>
<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/128x128/qobuz.png</file>
<file>icons/64x64/albums.png</file>
<file>icons/64x64/alsa.png</file>
<file>icons/64x64/application-exit.png</file>
@@ -170,10 +172,13 @@
<file>icons/64x64/xine.png</file>
<file>icons/64x64/zoom-in.png</file>
<file>icons/64x64/zoom-out.png</file>
<file>icons/64x64/tidal.png</file>
<file>icons/64x64/scrobble.png</file>
<file>icons/64x64/scrobble-disabled.png</file>
<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/64x64/qobuz.png</file>
<file>icons/48x48/albums.png</file>
<file>icons/48x48/alsa.png</file>
<file>icons/48x48/application-exit.png</file>
@@ -260,10 +265,13 @@
<file>icons/48x48/xine.png</file>
<file>icons/48x48/zoom-in.png</file>
<file>icons/48x48/zoom-out.png</file>
<file>icons/48x48/tidal.png</file>
<file>icons/48x48/scrobble.png</file>
<file>icons/48x48/scrobble-disabled.png</file>
<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/48x48/qobuz.png</file>
<file>icons/32x32/albums.png</file>
<file>icons/32x32/alsa.png</file>
<file>icons/32x32/application-exit.png</file>
@@ -338,7 +346,6 @@
<file>icons/32x32/star-grey.png</file>
<file>icons/32x32/star.png</file>
<file>icons/32x32/strawberry.png</file>
<file>icons/32x32/strawberry.svg</file>
<file>icons/32x32/tools-wizard.png</file>
<file>icons/32x32/view-choose.png</file>
<file>icons/32x32/view-fullscreen.png</file>
@@ -351,10 +358,13 @@
<file>icons/32x32/xine.png</file>
<file>icons/32x32/zoom-in.png</file>
<file>icons/32x32/zoom-out.png</file>
<file>icons/32x32/tidal.png</file>
<file>icons/32x32/scrobble.png</file>
<file>icons/32x32/scrobble-disabled.png</file>
<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/32x32/qobuz.png</file>
<file>icons/22x22/albums.png</file>
<file>icons/22x22/alsa.png</file>
<file>icons/22x22/application-exit.png</file>
@@ -429,7 +439,6 @@
<file>icons/22x22/star-grey.png</file>
<file>icons/22x22/star.png</file>
<file>icons/22x22/strawberry.png</file>
<file>icons/22x22/strawberry.svg</file>
<file>icons/22x22/tools-wizard.png</file>
<file>icons/22x22/view-choose.png</file>
<file>icons/22x22/view-fullscreen.png</file>
@@ -442,9 +451,12 @@
<file>icons/22x22/xine.png</file>
<file>icons/22x22/zoom-in.png</file>
<file>icons/22x22/zoom-out.png</file>
<file>icons/22x22/tidal.png</file>
<file>icons/22x22/scrobble.png</file>
<file>icons/22x22/scrobble-disabled.png</file>
<file>icons/22x22/moodbar.png</file>
<file>icons/22x22/love.png</file>
<file>icons/22x22/subsonic.png</file>
<file>icons/22x22/tidal.png</file>
<file>icons/22x22/qobuz.png</file>
</qresource>
</RCC>

BIN
data/icons/128x128/love.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -1,454 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg3422"
version="1.1"
inkscape:version="0.91 r13725"
width="38.400002"
height="38.400002"
viewBox="0 0 38.400002 38.400002"
sodipodi:docname="strawberry.svg">
<metadata
id="metadata3428">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3426" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview3424"
showgrid="false"
inkscape:zoom="21.458332"
inkscape:cx="19.200001"
inkscape:cy="19.200001"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3422" />
<image
width="38.400002"
height="38.400002"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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
OjE5KzAxOjAw3I1jCwAAAABJRU5ErkJggg==
"
id="image3430"
x="0"
y="0" />
</svg>

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 964 B

View File

@@ -1,489 +0,0 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="22" height="22">
<circle cx="0" cy="0" r="1" fill="white"/>
<circle cx="1" cy="0" r="1" fill="white"/>
<circle cx="2" cy="0" r="1" fill="white"/>
<circle cx="3" cy="0" r="1" fill="white"/>
<circle cx="4" cy="0" r="1" fill="white"/>
<circle cx="5" cy="0" r="1" fill="white"/>
<circle cx="6" cy="0" r="1" fill="white"/>
<circle cx="7" cy="0" r="1" fill="white"/>
<circle cx="8" cy="0" r="1" fill="white"/>
<circle cx="9" cy="0" r="1" fill="white"/>
<circle cx="10" cy="0" r="1" fill="white"/>
<circle cx="11" cy="0" r="1" fill="white"/>
<circle cx="12" cy="0" r="1" fill="white"/>
<circle cx="13" cy="0" r="1" fill="white"/>
<circle cx="14" cy="0" r="1" fill="white"/>
<circle cx="15" cy="0" r="1" fill="white"/>
<circle cx="16" cy="0" r="1" fill="white"/>
<circle cx="17" cy="0" r="1" fill="white"/>
<circle cx="18" cy="0" r="1" fill="white"/>
<circle cx="19" cy="0" r="1" fill="white"/>
<circle cx="20" cy="0" r="1" fill="white"/>
<circle cx="21" cy="0" r="1" fill="white"/>
<circle cx="0" cy="1" r="1" fill="white"/>
<circle cx="1" cy="1" r="1" fill="white"/>
<circle cx="2" cy="1" r="1" fill="white"/>
<circle cx="3" cy="1" r="1" fill="white"/>
<circle cx="4" cy="1" r="1" fill="white"/>
<circle cx="5" cy="1" r="1" fill="white"/>
<circle cx="6" cy="1" r="1" fill="white"/>
<circle cx="7" cy="1" r="1" fill="white"/>
<circle cx="8" cy="1" r="1" fill="white"/>
<circle cx="9" cy="1" r="1" fill="white"/>
<circle cx="10" cy="1" r="1" fill="white"/>
<circle cx="11" cy="1" r="1" fill="srgba(254,255,254,1)"/>
<circle cx="12" cy="1" r="1" fill="srgba(250,252,247,1)"/>
<circle cx="13" cy="1" r="1" fill="srgba(254,254,254,1)"/>
<circle cx="14" cy="1" r="1" fill="white"/>
<circle cx="15" cy="1" r="1" fill="white"/>
<circle cx="16" cy="1" r="1" fill="white"/>
<circle cx="17" cy="1" r="1" fill="white"/>
<circle cx="18" cy="1" r="1" fill="white"/>
<circle cx="19" cy="1" r="1" fill="white"/>
<circle cx="20" cy="1" r="1" fill="white"/>
<circle cx="21" cy="1" r="1" fill="white"/>
<circle cx="0" cy="2" r="1" fill="white"/>
<circle cx="1" cy="2" r="1" fill="white"/>
<circle cx="2" cy="2" r="1" fill="white"/>
<circle cx="3" cy="2" r="1" fill="white"/>
<circle cx="4" cy="2" r="1" fill="white"/>
<circle cx="5" cy="2" r="1" fill="white"/>
<circle cx="6" cy="2" r="1" fill="white"/>
<circle cx="7" cy="2" r="1" fill="white"/>
<circle cx="8" cy="2" r="1" fill="white"/>
<circle cx="9" cy="2" r="1" fill="white"/>
<circle cx="10" cy="2" r="1" fill="srgba(255,251,251,1)"/>
<circle cx="11" cy="2" r="1" fill="srgba(255,242,241,1)"/>
<circle cx="12" cy="2" r="1" fill="srgba(198,208,154,1)"/>
<circle cx="13" cy="2" r="1" fill="srgba(191,213,150,1)"/>
<circle cx="14" cy="2" r="1" fill="srgba(236,245,222,1)"/>
<circle cx="15" cy="2" r="1" fill="srgba(249,251,247,1)"/>
<circle cx="16" cy="2" r="1" fill="srgba(198,209,191,1)"/>
<circle cx="17" cy="2" r="1" fill="srgba(232,237,229,1)"/>
<circle cx="18" cy="2" r="1" fill="white"/>
<circle cx="19" cy="2" r="1" fill="white"/>
<circle cx="20" cy="2" r="1" fill="white"/>
<circle cx="21" cy="2" r="1" fill="white"/>
<circle cx="0" cy="3" r="1" fill="white"/>
<circle cx="1" cy="3" r="1" fill="white"/>
<circle cx="2" cy="3" r="1" fill="white"/>
<circle cx="3" cy="3" r="1" fill="white"/>
<circle cx="4" cy="3" r="1" fill="white"/>
<circle cx="5" cy="3" r="1" fill="white"/>
<circle cx="6" cy="3" r="1" fill="white"/>
<circle cx="7" cy="3" r="1" fill="srgba(255,255,255,1)"/>
<circle cx="8" cy="3" r="1" fill="srgba(255,239,239,1)"/>
<circle cx="9" cy="3" r="1" fill="srgba(255,180,178,1)"/>
<circle cx="10" cy="3" r="1" fill="srgba(252,111,107,1)"/>
<circle cx="11" cy="3" r="1" fill="srgba(253,81,80,1)"/>
<circle cx="12" cy="3" r="1" fill="srgba(214,94,54,1)"/>
<circle cx="13" cy="3" r="1" fill="srgba(138,128,30,1)"/>
<circle cx="14" cy="3" r="1" fill="srgba(135,166,67,1)"/>
<circle cx="15" cy="3" r="1" fill="srgba(167,199,124,1)"/>
<circle cx="16" cy="3" r="1" fill="srgba(115,153,87,1)"/>
<circle cx="17" cy="3" r="1" fill="srgba(206,218,200,1)"/>
<circle cx="18" cy="3" r="1" fill="white"/>
<circle cx="19" cy="3" r="1" fill="white"/>
<circle cx="20" cy="3" r="1" fill="white"/>
<circle cx="21" cy="3" r="1" fill="white"/>
<circle cx="0" cy="4" r="1" fill="white"/>
<circle cx="1" cy="4" r="1" fill="white"/>
<circle cx="2" cy="4" r="1" fill="white"/>
<circle cx="3" cy="4" r="1" fill="white"/>
<circle cx="4" cy="4" r="1" fill="white"/>
<circle cx="5" cy="4" r="1" fill="white"/>
<circle cx="6" cy="4" r="1" fill="srgba(255,254,254,1)"/>
<circle cx="7" cy="4" r="1" fill="srgba(255,200,200,1)"/>
<circle cx="8" cy="4" r="1" fill="srgba(253,100,95,1)"/>
<circle cx="9" cy="4" r="1" fill="srgba(251,40,34,1)"/>
<circle cx="10" cy="4" r="1" fill="srgba(247,19,12,1)"/>
<circle cx="11" cy="4" r="1" fill="srgba(247,30,20,1)"/>
<circle cx="12" cy="4" r="1" fill="srgba(241,16,7,1)"/>
<circle cx="13" cy="4" r="1" fill="srgba(188,57,9,1)"/>
<circle cx="14" cy="4" r="1" fill="srgba(115,102,16,1)"/>
<circle cx="15" cy="4" r="1" fill="srgba(96,139,32,1)"/>
<circle cx="16" cy="4" r="1" fill="srgba(124,170,69,1)"/>
<circle cx="17" cy="4" r="1" fill="srgba(221,232,210,1)"/>
<circle cx="18" cy="4" r="1" fill="white"/>
<circle cx="19" cy="4" r="1" fill="white"/>
<circle cx="20" cy="4" r="1" fill="white"/>
<circle cx="21" cy="4" r="1" fill="white"/>
<circle cx="0" cy="5" r="1" fill="white"/>
<circle cx="1" cy="5" r="1" fill="white"/>
<circle cx="2" cy="5" r="1" fill="white"/>
<circle cx="3" cy="5" r="1" fill="white"/>
<circle cx="4" cy="5" r="1" fill="white"/>
<circle cx="5" cy="5" r="1" fill="white"/>
<circle cx="6" cy="5" r="1" fill="srgba(254,195,191,1)"/>
<circle cx="7" cy="5" r="1" fill="srgba(252,70,63,1)"/>
<circle cx="8" cy="5" r="1" fill="srgba(251,48,41,1)"/>
<circle cx="9" cy="5" r="1" fill="srgba(248,74,63,1)"/>
<circle cx="10" cy="5" r="1" fill="srgba(252,25,22,1)"/>
<circle cx="11" cy="5" r="1" fill="srgba(240,26,18,1)"/>
<circle cx="12" cy="5" r="1" fill="srgba(193,53,17,1)"/>
<circle cx="13" cy="5" r="1" fill="srgba(127,101,9,1)"/>
<circle cx="14" cy="5" r="1" fill="srgba(105,138,10,1)"/>
<circle cx="15" cy="5" r="1" fill="srgba(99,148,16,1)"/>
<circle cx="16" cy="5" r="1" fill="srgba(121,168,46,1)"/>
<circle cx="17" cy="5" r="1" fill="srgba(191,215,155,1)"/>
<circle cx="18" cy="5" r="1" fill="srgba(251,251,249,1)"/>
<circle cx="19" cy="5" r="1" fill="srgba(251,254,247,1)"/>
<circle cx="20" cy="5" r="1" fill="srgba(218,240,197,1)"/>
<circle cx="21" cy="5" r="1" fill="srgba(230,243,214,1)"/>
<circle cx="0" cy="6" r="1" fill="white"/>
<circle cx="1" cy="6" r="1" fill="white"/>
<circle cx="2" cy="6" r="1" fill="white"/>
<circle cx="3" cy="6" r="1" fill="white"/>
<circle cx="4" cy="6" r="1" fill="white"/>
<circle cx="5" cy="6" r="1" fill="srgba(254,201,200,1)"/>
<circle cx="6" cy="6" r="1" fill="srgba(252,64,60,1)"/>
<circle cx="7" cy="6" r="1" fill="srgba(248,62,54,1)"/>
<circle cx="8" cy="6" r="1" fill="srgba(252,90,83,1)"/>
<circle cx="9" cy="6" r="1" fill="srgba(249,90,82,1)"/>
<circle cx="10" cy="6" r="1" fill="srgba(248,66,62,1)"/>
<circle cx="11" cy="6" r="1" fill="srgba(241,78,69,1)"/>
<circle cx="12" cy="6" r="1" fill="srgba(242,60,55,1)"/>
<circle cx="13" cy="6" r="1" fill="srgba(200,21,5,1)"/>
<circle cx="14" cy="6" r="1" fill="srgba(150,59,5,1)"/>
<circle cx="15" cy="6" r="1" fill="srgba(116,117,9,1)"/>
<circle cx="16" cy="6" r="1" fill="srgba(109,153,20,1)"/>
<circle cx="17" cy="6" r="1" fill="srgba(124,169,59,1)"/>
<circle cx="18" cy="6" r="1" fill="srgba(181,214,145,1)"/>
<circle cx="19" cy="6" r="1" fill="srgba(163,207,125,1)"/>
<circle cx="20" cy="6" r="1" fill="srgba(150,192,116,1)"/>
<circle cx="21" cy="6" r="1" fill="srgba(221,232,209,1)"/>
<circle cx="0" cy="7" r="1" fill="white"/>
<circle cx="1" cy="7" r="1" fill="white"/>
<circle cx="2" cy="7" r="1" fill="white"/>
<circle cx="3" cy="7" r="1" fill="white"/>
<circle cx="4" cy="7" r="1" fill="srgba(255,229,229,1)"/>
<circle cx="5" cy="7" r="1" fill="srgba(250,95,90,1)"/>
<circle cx="6" cy="7" r="1" fill="srgba(247,57,50,1)"/>
<circle cx="7" cy="7" r="1" fill="srgba(247,95,87,1)"/>
<circle cx="8" cy="7" r="1" fill="srgba(247,97,90,1)"/>
<circle cx="9" cy="7" r="1" fill="srgba(248,102,95,1)"/>
<circle cx="10" cy="7" r="1" fill="srgba(253,88,85,1)"/>
<circle cx="11" cy="7" r="1" fill="srgba(251,62,58,1)"/>
<circle cx="12" cy="7" r="1" fill="srgba(249,33,28,1)"/>
<circle cx="13" cy="7" r="1" fill="srgba(223,20,12,1)"/>
<circle cx="14" cy="7" r="1" fill="srgba(209,9,3,1)"/>
<circle cx="15" cy="7" r="1" fill="srgba(146,68,15,1)"/>
<circle cx="16" cy="7" r="1" fill="srgba(105,140,31,1)"/>
<circle cx="17" cy="7" r="1" fill="srgba(99,146,41,1)"/>
<circle cx="18" cy="7" r="1" fill="srgba(93,144,46,1)"/>
<circle cx="19" cy="7" r="1" fill="srgba(161,186,139,1)"/>
<circle cx="20" cy="7" r="1" fill="srgba(236,239,233,1)"/>
<circle cx="21" cy="7" r="1" fill="srgba(255,255,255,1)"/>
<circle cx="0" cy="8" r="1" fill="white"/>
<circle cx="1" cy="8" r="1" fill="white"/>
<circle cx="2" cy="8" r="1" fill="white"/>
<circle cx="3" cy="8" r="1" fill="srgba(254,250,250,1)"/>
<circle cx="4" cy="8" r="1" fill="srgba(250,146,143,1)"/>
<circle cx="5" cy="8" r="1" fill="srgba(245,65,59,1)"/>
<circle cx="6" cy="8" r="1" fill="srgba(246,77,74,1)"/>
<circle cx="7" cy="8" r="1" fill="srgba(247,103,103,1)"/>
<circle cx="8" cy="8" r="1" fill="srgba(249,97,94,1)"/>
<circle cx="9" cy="8" r="1" fill="srgba(250,122,119,1)"/>
<circle cx="10" cy="8" r="1" fill="srgba(242,77,74,1)"/>
<circle cx="11" cy="8" r="1" fill="srgba(235,67,55,1)"/>
<circle cx="12" cy="8" r="1" fill="srgba(250,51,48,1)"/>
<circle cx="13" cy="8" r="1" fill="srgba(231,6,2,1)"/>
<circle cx="14" cy="8" r="1" fill="srgba(182,62,20,1)"/>
<circle cx="15" cy="8" r="1" fill="srgba(113,145,47,1)"/>
<circle cx="16" cy="8" r="1" fill="srgba(95,144,51,1)"/>
<circle cx="17" cy="8" r="1" fill="srgba(81,123,42,1)"/>
<circle cx="18" cy="8" r="1" fill="srgba(98,137,47,1)"/>
<circle cx="19" cy="8" r="1" fill="srgba(212,223,195,1)"/>
<circle cx="20" cy="8" r="1" fill="white"/>
<circle cx="21" cy="8" r="1" fill="white"/>
<circle cx="0" cy="9" r="1" fill="white"/>
<circle cx="1" cy="9" r="1" fill="white"/>
<circle cx="2" cy="9" r="1" fill="white"/>
<circle cx="3" cy="9" r="1" fill="srgba(252,186,185,1)"/>
<circle cx="4" cy="9" r="1" fill="srgba(246,67,61,1)"/>
<circle cx="5" cy="9" r="1" fill="srgba(244,91,84,1)"/>
<circle cx="6" cy="9" r="1" fill="srgba(238,89,83,1)"/>
<circle cx="7" cy="9" r="1" fill="srgba(243,127,124,1)"/>
<circle cx="8" cy="9" r="1" fill="srgba(243,127,128,1)"/>
<circle cx="9" cy="9" r="1" fill="srgba(240,112,109,1)"/>
<circle cx="10" cy="9" r="1" fill="srgba(248,110,109,1)"/>
<circle cx="11" cy="9" r="1" fill="srgba(248,64,60,1)"/>
<circle cx="12" cy="9" r="1" fill="srgba(244,29,26,1)"/>
<circle cx="13" cy="9" r="1" fill="srgba(192,32,13,1)"/>
<circle cx="14" cy="9" r="1" fill="srgba(122,124,45,1)"/>
<circle cx="15" cy="9" r="1" fill="srgba(92,141,55,1)"/>
<circle cx="16" cy="9" r="1" fill="srgba(81,106,43,1)"/>
<circle cx="17" cy="9" r="1" fill="srgba(78,98,24,1)"/>
<circle cx="18" cy="9" r="1" fill="srgba(94,136,29,1)"/>
<circle cx="19" cy="9" r="1" fill="srgba(195,215,159,1)"/>
<circle cx="20" cy="9" r="1" fill="white"/>
<circle cx="21" cy="9" r="1" fill="white"/>
<circle cx="0" cy="10" r="1" fill="white"/>
<circle cx="1" cy="10" r="1" fill="white"/>
<circle cx="2" cy="10" r="1" fill="srgba(253,218,215,1)"/>
<circle cx="3" cy="10" r="1" fill="srgba(243,90,82,1)"/>
<circle cx="4" cy="10" r="1" fill="srgba(238,53,47,1)"/>
<circle cx="5" cy="10" r="1" fill="srgba(239,77,73,1)"/>
<circle cx="6" cy="10" r="1" fill="srgba(243,83,82,1)"/>
<circle cx="7" cy="10" r="1" fill="srgba(246,99,100,1)"/>
<circle cx="8" cy="10" r="1" fill="srgba(245,96,92,1)"/>
<circle cx="9" cy="10" r="1" fill="srgba(244,109,100,1)"/>
<circle cx="10" cy="10" r="1" fill="srgba(245,102,102,1)"/>
<circle cx="11" cy="10" r="1" fill="srgba(234,52,46,1)"/>
<circle cx="12" cy="10" r="1" fill="srgba(240,32,28,1)"/>
<circle cx="13" cy="10" r="1" fill="srgba(186,20,8,1)"/>
<circle cx="14" cy="10" r="1" fill="srgba(131,44,18,1)"/>
<circle cx="15" cy="10" r="1" fill="srgba(124,39,17,1)"/>
<circle cx="16" cy="10" r="1" fill="srgba(128,23,9,1)"/>
<circle cx="17" cy="10" r="1" fill="srgba(103,82,6,1)"/>
<circle cx="18" cy="10" r="1" fill="srgba(92,142,12,1)"/>
<circle cx="19" cy="10" r="1" fill="srgba(171,203,107,1)"/>
<circle cx="20" cy="10" r="1" fill="srgba(251,253,247,1)"/>
<circle cx="21" cy="10" r="1" fill="white"/>
<circle cx="0" cy="11" r="1" fill="white"/>
<circle cx="1" cy="11" r="1" fill="srgba(254,246,245,1)"/>
<circle cx="2" cy="11" r="1" fill="srgba(247,117,110,1)"/>
<circle cx="3" cy="11" r="1" fill="srgba(243,38,34,1)"/>
<circle cx="4" cy="11" r="1" fill="srgba(243,81,76,1)"/>
<circle cx="5" cy="11" r="1" fill="srgba(243,75,69,1)"/>
<circle cx="6" cy="11" r="1" fill="srgba(239,46,42,1)"/>
<circle cx="7" cy="11" r="1" fill="srgba(241,68,63,1)"/>
<circle cx="8" cy="11" r="1" fill="srgba(240,48,47,1)"/>
<circle cx="9" cy="11" r="1" fill="srgba(236,56,51,1)"/>
<circle cx="10" cy="11" r="1" fill="srgba(242,51,47,1)"/>
<circle cx="11" cy="11" r="1" fill="srgba(239,58,50,1)"/>
<circle cx="12" cy="11" r="1" fill="srgba(229,41,36,1)"/>
<circle cx="13" cy="11" r="1" fill="srgba(193,17,9,1)"/>
<circle cx="14" cy="11" r="1" fill="srgba(174,8,6,1)"/>
<circle cx="15" cy="11" r="1" fill="srgba(164,2,2,1)"/>
<circle cx="16" cy="11" r="1" fill="srgba(155,8,2,1)"/>
<circle cx="17" cy="11" r="1" fill="srgba(107,89,5,1)"/>
<circle cx="18" cy="11" r="1" fill="srgba(97,145,11,1)"/>
<circle cx="19" cy="11" r="1" fill="srgba(127,172,34,1)"/>
<circle cx="20" cy="11" r="1" fill="srgba(219,235,188,1)"/>
<circle cx="21" cy="11" r="1" fill="white"/>
<circle cx="0" cy="12" r="1" fill="srgba(255,255,255,1)"/>
<circle cx="1" cy="12" r="1" fill="srgba(249,194,188,1)"/>
<circle cx="2" cy="12" r="1" fill="srgba(235,70,59,1)"/>
<circle cx="3" cy="12" r="1" fill="srgba(221,26,22,1)"/>
<circle cx="4" cy="12" r="1" fill="srgba(221,36,34,1)"/>
<circle cx="5" cy="12" r="1" fill="srgba(224,27,25,1)"/>
<circle cx="6" cy="12" r="1" fill="srgba(236,31,29,1)"/>
<circle cx="7" cy="12" r="1" fill="srgba(230,32,30,1)"/>
<circle cx="8" cy="12" r="1" fill="srgba(225,24,21,1)"/>
<circle cx="9" cy="12" r="1" fill="srgba(229,60,54,1)"/>
<circle cx="10" cy="12" r="1" fill="srgba(230,35,32,1)"/>
<circle cx="11" cy="12" r="1" fill="srgba(224,37,29,1)"/>
<circle cx="12" cy="12" r="1" fill="srgba(204,15,10,1)"/>
<circle cx="13" cy="12" r="1" fill="srgba(192,24,15,1)"/>
<circle cx="14" cy="12" r="1" fill="srgba(185,20,16,1)"/>
<circle cx="15" cy="12" r="1" fill="srgba(174,24,14,1)"/>
<circle cx="16" cy="12" r="1" fill="srgba(151,12,3,1)"/>
<circle cx="17" cy="12" r="1" fill="srgba(98,92,5,1)"/>
<circle cx="18" cy="12" r="1" fill="srgba(120,108,17,1)"/>
<circle cx="19" cy="12" r="1" fill="srgba(120,141,21,1)"/>
<circle cx="20" cy="12" r="1" fill="srgba(183,213,130,1)"/>
<circle cx="21" cy="12" r="1" fill="srgba(254,255,253,1)"/>
<circle cx="0" cy="13" r="1" fill="srgba(254,251,251,1)"/>
<circle cx="1" cy="13" r="1" fill="srgba(236,134,123,1)"/>
<circle cx="2" cy="13" r="1" fill="srgba(228,41,35,1)"/>
<circle cx="3" cy="13" r="1" fill="srgba(221,33,29,1)"/>
<circle cx="4" cy="13" r="1" fill="srgba(218,29,25,1)"/>
<circle cx="5" cy="13" r="1" fill="srgba(224,28,22,1)"/>
<circle cx="6" cy="13" r="1" fill="srgba(215,23,18,1)"/>
<circle cx="7" cy="13" r="1" fill="srgba(221,58,46,1)"/>
<circle cx="8" cy="13" r="1" fill="srgba(218,17,15,1)"/>
<circle cx="9" cy="13" r="1" fill="srgba(218,30,25,1)"/>
<circle cx="10" cy="13" r="1" fill="srgba(198,10,7,1)"/>
<circle cx="11" cy="13" r="1" fill="srgba(204,29,19,1)"/>
<circle cx="12" cy="13" r="1" fill="srgba(198,16,11,1)"/>
<circle cx="13" cy="13" r="1" fill="srgba(183,18,12,1)"/>
<circle cx="14" cy="13" r="1" fill="srgba(181,13,10,1)"/>
<circle cx="15" cy="13" r="1" fill="srgba(176,13,10,1)"/>
<circle cx="16" cy="13" r="1" fill="srgba(146,23,7,1)"/>
<circle cx="17" cy="13" r="1" fill="srgba(134,67,12,1)"/>
<circle cx="18" cy="13" r="1" fill="srgba(205,98,76,1)"/>
<circle cx="19" cy="13" r="1" fill="srgba(168,176,100,1)"/>
<circle cx="20" cy="13" r="1" fill="srgba(185,210,141,1)"/>
<circle cx="21" cy="13" r="1" fill="srgba(255,255,255,1)"/>
<circle cx="0" cy="14" r="1" fill="srgba(253,247,246,1)"/>
<circle cx="1" cy="14" r="1" fill="srgba(232,106,96,1)"/>
<circle cx="2" cy="14" r="1" fill="srgba(220,33,24,1)"/>
<circle cx="3" cy="14" r="1" fill="srgba(206,27,21,1)"/>
<circle cx="4" cy="14" r="1" fill="srgba(203,24,19,1)"/>
<circle cx="5" cy="14" r="1" fill="srgba(205,17,13,1)"/>
<circle cx="6" cy="14" r="1" fill="srgba(213,20,17,1)"/>
<circle cx="7" cy="14" r="1" fill="srgba(212,35,30,1)"/>
<circle cx="8" cy="14" r="1" fill="srgba(197,10,7,1)"/>
<circle cx="9" cy="14" r="1" fill="srgba(208,33,23,1)"/>
<circle cx="10" cy="14" r="1" fill="srgba(191,15,11,1)"/>
<circle cx="11" cy="14" r="1" fill="srgba(185,17,12,1)"/>
<circle cx="12" cy="14" r="1" fill="srgba(180,14,11,1)"/>
<circle cx="13" cy="14" r="1" fill="srgba(183,27,20,1)"/>
<circle cx="14" cy="14" r="1" fill="srgba(186,18,15,1)"/>
<circle cx="15" cy="14" r="1" fill="srgba(185,23,17,1)"/>
<circle cx="16" cy="14" r="1" fill="srgba(187,32,24,1)"/>
<circle cx="17" cy="14" r="1" fill="srgba(202,38,31,1)"/>
<circle cx="18" cy="14" r="1" fill="srgba(244,156,155,1)"/>
<circle cx="19" cy="14" r="1" fill="srgba(229,237,212,1)"/>
<circle cx="20" cy="14" r="1" fill="srgba(226,235,208,1)"/>
<circle cx="21" cy="14" r="1" fill="white"/>
<circle cx="0" cy="15" r="1" fill="srgba(254,248,248,1)"/>
<circle cx="1" cy="15" r="1" fill="srgba(230,110,102,1)"/>
<circle cx="2" cy="15" r="1" fill="srgba(207,29,20,1)"/>
<circle cx="3" cy="15" r="1" fill="srgba(192,28,21,1)"/>
<circle cx="4" cy="15" r="1" fill="srgba(191,24,19,1)"/>
<circle cx="5" cy="15" r="1" fill="srgba(190,17,14,1)"/>
<circle cx="6" cy="15" r="1" fill="srgba(182,16,11,1)"/>
<circle cx="7" cy="15" r="1" fill="srgba(188,29,21,1)"/>
<circle cx="8" cy="15" r="1" fill="srgba(177,11,8,1)"/>
<circle cx="9" cy="15" r="1" fill="srgba(180,12,10,1)"/>
<circle cx="10" cy="15" r="1" fill="srgba(176,13,10,1)"/>
<circle cx="11" cy="15" r="1" fill="srgba(184,25,18,1)"/>
<circle cx="12" cy="15" r="1" fill="srgba(181,16,13,1)"/>
<circle cx="13" cy="15" r="1" fill="srgba(184,20,17,1)"/>
<circle cx="14" cy="15" r="1" fill="srgba(187,21,18,1)"/>
<circle cx="15" cy="15" r="1" fill="srgba(192,31,26,1)"/>
<circle cx="16" cy="15" r="1" fill="srgba(193,30,25,1)"/>
<circle cx="17" cy="15" r="1" fill="srgba(201,73,71,1)"/>
<circle cx="18" cy="15" r="1" fill="srgba(249,228,228,1)"/>
<circle cx="19" cy="15" r="1" fill="srgba(254,255,254,1)"/>
<circle cx="20" cy="15" r="1" fill="srgba(254,254,253,1)"/>
<circle cx="21" cy="15" r="1" fill="white"/>
<circle cx="0" cy="16" r="1" fill="white"/>
<circle cx="1" cy="16" r="1" fill="srgba(239,172,167,1)"/>
<circle cx="2" cy="16" r="1" fill="srgba(204,49,39,1)"/>
<circle cx="3" cy="16" r="1" fill="srgba(184,32,23,1)"/>
<circle cx="4" cy="16" r="1" fill="srgba(179,18,14,1)"/>
<circle cx="5" cy="16" r="1" fill="srgba(178,23,16,1)"/>
<circle cx="6" cy="16" r="1" fill="srgba(179,23,17,1)"/>
<circle cx="7" cy="16" r="1" fill="srgba(178,13,12,1)"/>
<circle cx="8" cy="16" r="1" fill="srgba(178,19,14,1)"/>
<circle cx="9" cy="16" r="1" fill="srgba(174,11,8,1)"/>
<circle cx="10" cy="16" r="1" fill="srgba(173,15,11,1)"/>
<circle cx="11" cy="16" r="1" fill="srgba(180,18,16,1)"/>
<circle cx="12" cy="16" r="1" fill="srgba(184,25,21,1)"/>
<circle cx="13" cy="16" r="1" fill="srgba(187,29,25,1)"/>
<circle cx="14" cy="16" r="1" fill="srgba(196,40,35,1)"/>
<circle cx="15" cy="16" r="1" fill="srgba(196,35,31,1)"/>
<circle cx="16" cy="16" r="1" fill="srgba(200,60,59,1)"/>
<circle cx="17" cy="16" r="1" fill="srgba(234,188,188,1)"/>
<circle cx="18" cy="16" r="1" fill="srgba(255,255,255,1)"/>
<circle cx="19" cy="16" r="1" fill="white"/>
<circle cx="20" cy="16" r="1" fill="white"/>
<circle cx="21" cy="16" r="1" fill="white"/>
<circle cx="0" cy="17" r="1" fill="white"/>
<circle cx="1" cy="17" r="1" fill="srgba(254,247,246,1)"/>
<circle cx="2" cy="17" r="1" fill="srgba(234,172,167,1)"/>
<circle cx="3" cy="17" r="1" fill="srgba(199,80,73,1)"/>
<circle cx="4" cy="17" r="1" fill="srgba(182,43,35,1)"/>
<circle cx="5" cy="17" r="1" fill="srgba(185,32,25,1)"/>
<circle cx="6" cy="17" r="1" fill="srgba(190,29,25,1)"/>
<circle cx="7" cy="17" r="1" fill="srgba(192,34,28,1)"/>
<circle cx="8" cy="17" r="1" fill="srgba(189,26,23,1)"/>
<circle cx="9" cy="17" r="1" fill="srgba(187,26,22,1)"/>
<circle cx="10" cy="17" r="1" fill="srgba(187,30,24,1)"/>
<circle cx="11" cy="17" r="1" fill="srgba(189,29,26,1)"/>
<circle cx="12" cy="17" r="1" fill="srgba(190,35,31,1)"/>
<circle cx="13" cy="17" r="1" fill="srgba(195,38,35,1)"/>
<circle cx="14" cy="17" r="1" fill="srgba(195,44,41,1)"/>
<circle cx="15" cy="17" r="1" fill="srgba(208,95,94,1)"/>
<circle cx="16" cy="17" r="1" fill="srgba(238,200,200,1)"/>
<circle cx="17" cy="17" r="1" fill="srgba(255,254,254,1)"/>
<circle cx="18" cy="17" r="1" fill="white"/>
<circle cx="19" cy="17" r="1" fill="white"/>
<circle cx="20" cy="17" r="1" fill="white"/>
<circle cx="21" cy="17" r="1" fill="white"/>
<circle cx="0" cy="18" r="1" fill="white"/>
<circle cx="1" cy="18" r="1" fill="white"/>
<circle cx="2" cy="18" r="1" fill="srgba(255,253,253,1)"/>
<circle cx="3" cy="18" r="1" fill="srgba(248,233,232,1)"/>
<circle cx="4" cy="18" r="1" fill="srgba(235,194,191,1)"/>
<circle cx="5" cy="18" r="1" fill="srgba(228,158,157,1)"/>
<circle cx="6" cy="18" r="1" fill="srgba(229,149,147,1)"/>
<circle cx="7" cy="18" r="1" fill="srgba(228,151,149,1)"/>
<circle cx="8" cy="18" r="1" fill="srgba(228,146,144,1)"/>
<circle cx="9" cy="18" r="1" fill="srgba(220,129,126,1)"/>
<circle cx="10" cy="18" r="1" fill="srgba(219,119,117,1)"/>
<circle cx="11" cy="18" r="1" fill="srgba(219,119,117,1)"/>
<circle cx="12" cy="18" r="1" fill="srgba(220,126,125,1)"/>
<circle cx="13" cy="18" r="1" fill="srgba(224,149,148,1)"/>
<circle cx="14" cy="18" r="1" fill="srgba(236,190,189,1)"/>
<circle cx="15" cy="18" r="1" fill="srgba(250,238,238,1)"/>
<circle cx="16" cy="18" r="1" fill="white"/>
<circle cx="17" cy="18" r="1" fill="white"/>
<circle cx="18" cy="18" r="1" fill="white"/>
<circle cx="19" cy="18" r="1" fill="white"/>
<circle cx="20" cy="18" r="1" fill="white"/>
<circle cx="21" cy="18" r="1" fill="white"/>
<circle cx="0" cy="19" r="1" fill="white"/>
<circle cx="1" cy="19" r="1" fill="white"/>
<circle cx="2" cy="19" r="1" fill="white"/>
<circle cx="3" cy="19" r="1" fill="white"/>
<circle cx="4" cy="19" r="1" fill="white"/>
<circle cx="5" cy="19" r="1" fill="white"/>
<circle cx="6" cy="19" r="1" fill="white"/>
<circle cx="7" cy="19" r="1" fill="white"/>
<circle cx="8" cy="19" r="1" fill="white"/>
<circle cx="9" cy="19" r="1" fill="srgba(255,255,255,1)"/>
<circle cx="10" cy="19" r="1" fill="srgba(254,252,252,1)"/>
<circle cx="11" cy="19" r="1" fill="srgba(254,251,251,1)"/>
<circle cx="12" cy="19" r="1" fill="srgba(255,254,254,1)"/>
<circle cx="13" cy="19" r="1" fill="white"/>
<circle cx="14" cy="19" r="1" fill="white"/>
<circle cx="15" cy="19" r="1" fill="white"/>
<circle cx="16" cy="19" r="1" fill="white"/>
<circle cx="17" cy="19" r="1" fill="white"/>
<circle cx="18" cy="19" r="1" fill="white"/>
<circle cx="19" cy="19" r="1" fill="white"/>
<circle cx="20" cy="19" r="1" fill="white"/>
<circle cx="21" cy="19" r="1" fill="white"/>
<circle cx="0" cy="20" r="1" fill="white"/>
<circle cx="1" cy="20" r="1" fill="white"/>
<circle cx="2" cy="20" r="1" fill="white"/>
<circle cx="3" cy="20" r="1" fill="white"/>
<circle cx="4" cy="20" r="1" fill="white"/>
<circle cx="5" cy="20" r="1" fill="white"/>
<circle cx="6" cy="20" r="1" fill="white"/>
<circle cx="7" cy="20" r="1" fill="white"/>
<circle cx="8" cy="20" r="1" fill="white"/>
<circle cx="9" cy="20" r="1" fill="white"/>
<circle cx="10" cy="20" r="1" fill="white"/>
<circle cx="11" cy="20" r="1" fill="white"/>
<circle cx="12" cy="20" r="1" fill="white"/>
<circle cx="13" cy="20" r="1" fill="white"/>
<circle cx="14" cy="20" r="1" fill="white"/>
<circle cx="15" cy="20" r="1" fill="white"/>
<circle cx="16" cy="20" r="1" fill="white"/>
<circle cx="17" cy="20" r="1" fill="white"/>
<circle cx="18" cy="20" r="1" fill="white"/>
<circle cx="19" cy="20" r="1" fill="white"/>
<circle cx="20" cy="20" r="1" fill="white"/>
<circle cx="21" cy="20" r="1" fill="white"/>
<circle cx="0" cy="21" r="1" fill="white"/>
<circle cx="1" cy="21" r="1" fill="white"/>
<circle cx="2" cy="21" r="1" fill="white"/>
<circle cx="3" cy="21" r="1" fill="white"/>
<circle cx="4" cy="21" r="1" fill="white"/>
<circle cx="5" cy="21" r="1" fill="white"/>
<circle cx="6" cy="21" r="1" fill="white"/>
<circle cx="7" cy="21" r="1" fill="white"/>
<circle cx="8" cy="21" r="1" fill="white"/>
<circle cx="9" cy="21" r="1" fill="white"/>
<circle cx="10" cy="21" r="1" fill="white"/>
<circle cx="11" cy="21" r="1" fill="white"/>
<circle cx="12" cy="21" r="1" fill="white"/>
<circle cx="13" cy="21" r="1" fill="white"/>
<circle cx="14" cy="21" r="1" fill="white"/>
<circle cx="15" cy="21" r="1" fill="white"/>
<circle cx="16" cy="21" r="1" fill="white"/>
<circle cx="17" cy="21" r="1" fill="white"/>
<circle cx="18" cy="21" r="1" fill="white"/>
<circle cx="19" cy="21" r="1" fill="white"/>
<circle cx="20" cy="21" r="1" fill="white"/>
<circle cx="21" cy="21" r="1" fill="white"/>
</svg>

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 804 B

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

View File

@@ -1,454 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
id="svg3422"
version="1.1"
inkscape:version="0.91 r13725"
width="38.400002"
height="38.400002"
viewBox="0 0 38.400002 38.400002"
sodipodi:docname="strawberry.svg">
<metadata
id="metadata3428">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs3426" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview3424"
showgrid="false"
inkscape:zoom="21.458332"
inkscape:cx="19.200001"
inkscape:cy="19.200001"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1"
inkscape:current-layer="svg3422" />
<image
width="38.400002"
height="38.400002"
preserveAspectRatio="none"
xlink:href="data:image/png;base64,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
OjE5KzAxOjAw3I1jCwAAAABJRU5ErkJggg==
"
id="image3430"
x="0"
y="0" />
</svg>

Before

Width:  |  Height:  |  Size: 31 KiB

View File

@@ -27,25 +27,29 @@ CREATE TABLE device_%deviceid_songs (
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth 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,
filename TEXT NOT NULL,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL,
mtime INTEGER NOT NULL,
ctime INTEGER NOT NULL,
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 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
@@ -66,10 +70,9 @@ CREATE INDEX idx_device_%deviceid_songs_album ON device_%deviceid_songs (album);
CREATE INDEX idx_device_%deviceid_songs_comp_artist ON device_%deviceid_songs (compilation_effective, artist);
CREATE VIRTUAL TABLE device_%deviceid_fts USING fts3(
CREATE VIRTUAL TABLE device_%deviceid_fts USING fts5(
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
tokenize=unicode
tokenize = "unicode61 remove_diacritics 0"
);
UPDATE devices SET schema_version=0 WHERE ROWID=%deviceid;
UPDATE devices SET schema_version=1 WHERE ROWID=%deviceid;

205
data/schema/schema-4.sql Normal file
View File

@@ -0,0 +1,205 @@
CREATE TABLE IF NOT EXISTS tidal_artists_songs (
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,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
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 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,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
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 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,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
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 fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
UPDATE schema_version SET version=4;

31
data/schema/schema-5.sql Normal file
View File

@@ -0,0 +1,31 @@
ALTER TABLE songs ADD COLUMN artist_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE songs ADD COLUMN album_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE songs ADD COLUMN song_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_artists_songs ADD COLUMN artist_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_artists_songs ADD COLUMN album_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_artists_songs ADD COLUMN song_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_albums_songs ADD COLUMN artist_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_albums_songs ADD COLUMN album_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_albums_songs ADD COLUMN song_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_songs ADD COLUMN artist_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_songs ADD COLUMN album_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE tidal_songs ADD COLUMN song_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE playlist_items ADD COLUMN artist_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE playlist_items ADD COLUMN album_id INTEGER NOT NULL DEFAULT -1;
ALTER TABLE playlist_items ADD COLUMN song_id INTEGER NOT NULL DEFAULT -1;
UPDATE schema_version SET version=5;

73
data/schema/schema-6.sql Normal file
View File

@@ -0,0 +1,73 @@
CREATE TABLE IF NOT EXISTS subsonic_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id INTEGER NOT NULL DEFAULT -1,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
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 subsonic_songs_fts USING fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
UPDATE schema_version SET version=6;

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

@@ -0,0 +1,217 @@
CREATE TABLE IF NOT EXISTS qobuz_artists_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id INTEGER NOT NULL DEFAULT -1,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS qobuz_albums_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id INTEGER NOT NULL DEFAULT -1,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
art_automatic TEXT,
art_manual TEXT,
effective_albumartist TEXT,
effective_originalyear INTEGER NOT NULL DEFAULT 0,
cue_path TEXT
);
CREATE TABLE IF NOT EXISTS qobuz_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id INTEGER NOT NULL DEFAULT -1,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth INTEGER NOT NULL DEFAULT 0,
source INTEGER NOT NULL DEFAULT 0,
directory_id INTEGER NOT NULL,
filename TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL DEFAULT 0,
mtime INTEGER NOT NULL DEFAULT 0,
ctime INTEGER NOT NULL DEFAULT 0,
unavailable INTEGER DEFAULT 0,
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL 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,
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 qobuz_artists_songs_fts USING fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
CREATE VIRTUAL TABLE IF NOT EXISTS qobuz_albums_songs_fts USING fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
CREATE VIRTUAL TABLE IF NOT EXISTS qobuz_songs_fts USING fts3(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
);
UPDATE schema_version SET version=7;

595
data/schema/schema-8.sql Normal file
View File

@@ -0,0 +1,595 @@
ALTER TABLE songs RENAME TO songs_old;
ALTER TABLE playlist_items RENAME TO playlist_items_old;
ALTER TABLE tidal_artists_songs RENAME TO tidal_artists_songs_old;
ALTER TABLE tidal_albums_songs RENAME TO tidal_albums_songs_old;
ALTER TABLE tidal_songs RENAME TO tidal_songs_old;
ALTER TABLE qobuz_artists_songs RENAME TO qobuz_artists_songs_old;
ALTER TABLE qobuz_albums_songs RENAME TO qobuz_albums_songs_old;
ALTER TABLE qobuz_songs RENAME TO qobuz_songs_old;
ALTER TABLE subsonic_songs RENAME TO subsonic_songs_old;
DROP INDEX idx_filename;
CREATE TABLE songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 tidal_artists_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 tidal_albums_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 tidal_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 subsonic_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 qobuz_artists_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 qobuz_albums_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 qobuz_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 playlist_items (
playlist INTEGER NOT NULL,
type INTEGER NOT NULL DEFAULT 0,
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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,
url TEXT,
filetype INTEGER NOT NULL DEFAULT 0,
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,
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 (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 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, filename, 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;
INSERT INTO tidal_artists_songs (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 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, filename, 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 tidal_artists_songs_old;
DROP TABLE tidal_artists_songs_old;
INSERT INTO tidal_albums_songs (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 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, filename, 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 tidal_albums_songs_old;
DROP TABLE tidal_albums_songs_old;
INSERT INTO tidal_songs (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 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, filename, 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 tidal_songs_old;
DROP TABLE tidal_songs_old;
INSERT INTO qobuz_artists_songs (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 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, filename, 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 qobuz_artists_songs_old;
DROP TABLE qobuz_artists_songs_old;
INSERT INTO qobuz_albums_songs (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 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, filename, 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 qobuz_albums_songs_old;
DROP TABLE qobuz_albums_songs_old;
INSERT INTO qobuz_songs (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 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, filename, 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 qobuz_songs_old;
DROP TABLE qobuz_songs_old;
INSERT INTO subsonic_songs (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 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, filename, 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;
INSERT INTO playlist_items (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 playlist, type, collection_id, 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, filename, 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;
CREATE INDEX idx_url ON songs (url);
UPDATE schema_version SET version=8;

41
data/schema/schema-9.sql Normal file
View File

@@ -0,0 +1,41 @@
DROP TABLE %allsongstables_fts;
DROP TABLE playlist_items_fts_;
CREATE VIRTUAL TABLE %allsongstables_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE playlist_items_fts_ USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
INSERT INTO %allsongstables_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment FROM %allsongstables;
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=9;

View File

@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS schema_version (
DELETE FROM schema_version;
INSERT INTO schema_version (version) VALUES (3);
INSERT INTO schema_version (version) VALUES (9);
CREATE TABLE IF NOT EXISTS directories (
path TEXT NOT NULL,
@@ -35,25 +35,428 @@ CREATE TABLE IF NOT EXISTS songs (
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth 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,
filename TEXT NOT NULL,
directory_id INTEGER NOT NULL DEFAULT -1,
url TEXT NOT NULL,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER NOT NULL,
mtime INTEGER NOT NULL,
ctime INTEGER NOT NULL,
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 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 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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 subsonic_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 qobuz_artists_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 qobuz_albums_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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 qobuz_songs (
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,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
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,
@@ -86,7 +489,7 @@ CREATE TABLE IF NOT EXISTS playlist_items (
playlist INTEGER NOT NULL,
type INTEGER NOT NULL DEFAULT 0,
collection_id INTEGER,
url TEXT,
playlist_url TEXT,
title TEXT NOT NULL,
album TEXT NOT NULL,
@@ -104,16 +507,20 @@ CREATE TABLE IF NOT EXISTS playlist_items (
comment TEXT NOT NULL,
lyrics TEXT NOT NULL,
artist_id INTEGER NOT NULL DEFAULT -1,
album_id TEXT NOT NULL,
song_id INTEGER NOT NULL DEFAULT -1,
beginning INTEGER NOT NULL DEFAULT 0,
length INTEGER NOT NULL DEFAULT 0,
bitrate INTEGER NOT NULL DEFAULT 0,
samplerate INTEGER NOT NULL DEFAULT 0,
bitdepth 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,
filename TEXT,
url TEXT,
filetype INTEGER NOT NULL DEFAULT 0,
filesize INTEGER,
mtime INTEGER,
@@ -122,7 +529,7 @@ CREATE TABLE IF NOT EXISTS playlist_items (
playcount INTEGER NOT NULL DEFAULT 0,
skipcount INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT 0,
lastplayed INTEGER NOT NULL DEFAULT -1,
compilation_detected INTEGER DEFAULT 0,
compilation_on INTEGER NOT NULL DEFAULT 0,
@@ -149,17 +556,21 @@ CREATE TABLE IF NOT EXISTS devices (
transcode_format NOT NULL DEFAULT 5
);
CREATE INDEX IF NOT EXISTS idx_filename ON songs (filename);
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 IF NOT EXISTS 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 VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts3(
CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5(
ftstitle,
ftsalbum,
@@ -170,11 +581,11 @@ CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts3(
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS playlist_items_fts_ USING fts3(
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
ftstitle,
ftsalbum,
@@ -185,11 +596,11 @@ CREATE VIRTUAL TABLE IF NOT EXISTS playlist_items_fts_ USING fts3(
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS %allsongstables_fts USING fts3(
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
ftstitle,
ftsalbum,
@@ -200,13 +611,111 @@ CREATE VIRTUAL TABLE IF NOT EXISTS %allsongstables_fts USING fts3(
ftsgrouping,
ftsgenre,
ftscomment,
tokenize=unicode
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
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;
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
INSERT INTO %allsongstables_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment FROM %allsongstables;
);
CREATE VIRTUAL TABLE IF NOT EXISTS subsonic_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS qobuz_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 qobuz_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 qobuz_songs_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS playlist_items_fts_ USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);
CREATE VIRTUAL TABLE IF NOT EXISTS %allsongstables_fts USING fts5(
ftstitle,
ftsalbum,
ftsartist,
ftsalbumartist,
ftscomposer,
ftsperformer,
ftsgrouping,
ftsgenre,
ftscomment,
tokenize = "unicode61 remove_diacritics 0"
);

7
debian/control vendored
View File

@@ -24,9 +24,6 @@ Build-Depends: debhelper (>= 7),
libqt5x11extras5-dev,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
libxine2-dev,
libvlc-dev,
libphonon4qt5-dev,
libcdio-dev,
libgpod-dev,
libimobiledevice-dev,
@@ -61,12 +58,12 @@ Description: Audio player and music collection organizer
- Edit tags on music files
- Fetch tags from MusicBrainz
- Album cover art from Lastfm, Musicbrainz, Discogs, Deezer and Tidal
- Song lyrics from AudD and ChartLyrics
- Song lyrics from AudD
- Support for multiple backends
- Audio analyzer
- Audio equalizer
- Transfer music to iPod, iPhone, MTP or mass-storage USB player
- Streaming support for Tidal
- Streaming support for Tidal, Qobuz and Subsonic
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
.
It is a fork of Clementine. The name is inspired by the band Strawbs.

14
debian/copyright vendored
View File

@@ -58,9 +58,11 @@ Files: src/core/main.h
src/lyrics/*
src/scrobbler/*
src/tidal/*
src/qobuz/*
src/subsonic/*
src/transcoder/transcoderoptionswavpack.cpp
src/transcoder/transcoderoptionswavpack.h
Copyright: 2012-2014, 2017-2018, Jonas Kvinge <jonas@jkvinge.net>
Copyright: 2012-2014, 2017-2019, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/core/main.cpp
@@ -292,15 +294,17 @@ Copyright: 1999 Erik Walthinsen <omega@cse.ogi.edu>
2007-2009 Sebastian Dröge <sebastian.droege@collabora.co.uk>
License: GPL-2+
Files: src/widgets/qsearchfield_nonmac.cpp
src/widgets/qsearchfield_mac.mm
src/widgets/qsearchfield.h
Copyright: 2011, Mike McQuaid <mike@mikemcquaid.com>
License: Expat
Files: 3rdparty/SPMediaKeyTap/*
Copyright: 2010, Spotify AB
2011, Joachim Bengtsson
License: BSD-3-clause
Files: 3rdparty/qocoa/*
Copyright: 2011, Mike McQuaid <mike@mikemcquaid.com>
License: Expat
Files: 3rdparty/singleapplication/*
Copyright: 2015-2018, Itay Grudev
License: MIT

7
dist/CMakeLists.txt vendored
View File

@@ -9,21 +9,18 @@ configure_file(${CMAKE_SOURCE_DIR}/debian/changelog.in ${CMAKE_SOURCE_DIR}/debia
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/create-dmg.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/create-dmg.sh)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-x86.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-x86.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-x64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-x64.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-x86.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-x86.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-x64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-x64.nsi @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi @ONLY)
if (UNIX AND NOT APPLE)
install(FILES ../data/icons/48x48/strawberry.png DESTINATION share/icons/hicolor/48x48/apps/)
install(FILES ../data/icons/64x64/strawberry.png DESTINATION share/icons/hicolor/64x64/apps/)
install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/)
install(FILES ../data/icons/128x128/strawberry.svg DESTINATION share/icons/hicolor/scalable/apps/)
install(FILES unix/org.strawbs.strawberry.desktop DESTINATION share/applications)
install(FILES unix/org.strawbs.strawberry.appdata.xml DESTINATION share/metainfo)
install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1)
endif()
if (APPLE)
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../dist/macos/Info.plist" DESTINATION "${CMAKE_BINARY_DIR}/strawberry.app/Contents")
install(FILES "${CMAKE_CURRENT_SOURCE_DIR}/../dist/macos/strawberry.icns" DESTINATION "${CMAKE_BINARY_DIR}/strawberry.app/Contents/Resources")
endif (APPLE)

View File

@@ -11,7 +11,7 @@
<key>CFBundleGetInfoString</key>
<string>Strawberry ${STRAWBERRY_VERSION_DISPLAY}</string>
<key>CFBundleIconFile</key>
<string>strawberry</string>
<string>strawberry.icns</string>
<key>CFBundleIdentifier</key>
<string>org.strawberry.strawberry</string>
<key>CFBundleInfoDictionaryVersion</key>
@@ -33,7 +33,7 @@
<key>LSApplicationCategoryType</key>
<string>public.app-category.music</string>
<key>LSMinimumSystemVersion</key>
<string>10.7.0</string>
<string>10.13.4</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>

View File

@@ -20,14 +20,5 @@ rm -rf "$temp_dir"
rm -f "$output_file"
mkdir -p "$temp_dir"
#mkdir -p "$temp_dir/.background"
#cp ../dist/macos/dmg_background.png "$temp_dir/.background/background.png"
#cp ../dist/macos/DS_Store.in "$temp_dir/.DS_Store"
#chmod go-rwx "$temp_dir/.DS_Store"
ln -s /Applications "$temp_dir/Applications"
# Copies the prepared bundle into the dir that will become the DMG
cp -R "$bundle_dir" "$temp_dir"
# Create dmg
hdiutil makehybrid -hfs -hfs-volume-name "$name" -hfs-openfolder "$temp_dir" "$temp_dir" -o tmp.dmg
hdiutil convert -format UDZO -imagekey zlib-level=9 tmp.dmg -o "$output_file"
/usr/local/bin/create-dmg --volname "$name" --background "@CMAKE_SOURCE_DIR@/dist/macos/dmg_background.png" --app-drop-link 450 218 --icon $bundle_dir 150 218 --window-size 600 450 $output_file $bundle_dir

BIN
dist/macos/dmg_background.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@@ -36,13 +36,23 @@ FRAMEWORK_SEARCH_PATH = [
QT_PLUGINS = [
'platforms/libqcocoa.dylib',
'platforminputcontexts/libqtvirtualkeyboardplugin.dylib',
'styles/libqmacstyle.dylib',
'sqldrivers/libqsqlite.dylib',
'bearer/libqgenericbearer.dylib'
'iconengines/libqsvgicon.dylib'
'imageformats/libqgif.dylib',
'imageformats/libqicns.dylib',
'imageformats/libqico.dylib',
'imageformats/libqjpeg.dylib',
'imageformats/libqsvg.dylib',
'imageformats/libqtiff.dylib',
'printsupport/libcocoaprintersupport.dylib',
'virtualkeyboard/libqtvirtualkeyboard_hangul.dylib',
'virtualkeyboard/libqtvirtualkeyboard_openwnn.dylib',
'virtualkeyboard/libqtvirtualkeyboard_pinyin.dylib',
'virtualkeyboard/libqtvirtualkeyboard_tcime.dylib',
'virtualkeyboard/libqtvirtualkeyboard_thai.dylib',
]
QT_PLUGINS_SEARCH_PATH = [
@@ -100,8 +110,8 @@ GSTREAMER_PLUGINS = [
'libgsttaglib.so',
'libgstvorbis.so',
'libgstisomp4.so',
'libgstlame.so',
'libgstlibav.so',
'libgstaiff.so',
]
@@ -458,22 +468,22 @@ def FindGioModule(name):
def main():
logging.basicConfig(filename='macdeploy.log', level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s')
FixBinary(binary)
for plugin in GSTREAMER_PLUGINS:
FixPlugin(FindGstreamerPlugin(plugin), 'gstreamer')
FixPlugin(FindGstreamerPlugin('gst-plugin-scanner'), '.')
FixPlugin(FindGioModule('libgiognutls.so'), 'gio-modules')
FixPlugin(FindGioModule('libgiognomeproxy.so'), 'gio-modules')
#FixBinary(binary)
try:
FixPlugin('strawberry-tagreader', '.')
except:
print 'Failed to find blob: %s' % traceback.format_exc()
for plugin in QT_PLUGINS:
FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
for plugin in GSTREAMER_PLUGINS:
FixPlugin(FindGstreamerPlugin(plugin), 'gstreamer')
FixPlugin(FindGstreamerPlugin('gst-plugin-scanner'), '.')
FixPlugin(FindGioModule('libgiognutls.so'), 'gio-modules')
#FixPlugin(FindGioModule('libgiognomeproxy.so'), 'gio-modules')
#for plugin in QT_PLUGINS:
#FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
if len(sys.argv) <= 2:
print 'Would run %d commands:' % len(commands)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 1.5 MiB

View File

@@ -27,7 +27,7 @@ Features:
.br
- Album cover art from Lastfm, Musicbrainz, Discogs, Deezer and Tidal
.br
- Song lyrics from AudD and ChartLyrics
- Song lyrics from AudD
.br
- Support for multiple backends
.br
@@ -37,7 +37,7 @@ Features:
.br
- Transfer music to iPod, iPhone, MTP or mass-storage USB player
.br
- Integrated Tidal support
- Streaming from Tidal, Qobuz and Subsonic
.TP
It is a fork of Clementine. The name is inspired by the band Strawbs.
.SH OPTIONS

View File

@@ -44,7 +44,7 @@ BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(gnutls)
BuildRequires: pkgconfig(alsa)
BuildRequires: pkgconfig(protobuf)
BuildRequires: pkgconfig(sqlite3)
BuildRequires: pkgconfig(sqlite3) >= 3.9
%if ! 0%{?centos} && ! 0%{?mageia}
BuildRequires: pkgconfig(taglib)
%endif
@@ -57,6 +57,7 @@ BuildRequires: pkgconfig(Qt5Network)
BuildRequires: pkgconfig(Qt5Sql)
BuildRequires: pkgconfig(Qt5X11Extras)
BuildRequires: pkgconfig(Qt5DBus)
BuildRequires: pkgconfig(Qt5Test)
BuildRequires: pkgconfig(gstreamer-1.0)
BuildRequires: pkgconfig(gstreamer-app-1.0)
BuildRequires: pkgconfig(gstreamer-audio-1.0)
@@ -101,12 +102,12 @@ Features:
- Edit tags on music files
- Fetch tags from MusicBrainz
- Album cover art from Last.fm, Musicbrainz, Discogs, Deezer and Tidal
- Song lyrics from AudD and ChartLyrics
- Song lyrics from AudD
- Support for multiple backends
- Audio analyzer
- Audio equalizer
- Transfer music to iPod, iPhone, MTP or mass-storage USB player
- Streaming support for Tidal
- Streaming support for Tidal, Qobuz and Subsonic
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
%prep

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<component>
<id>org.strawbs.strawberry</id>
<launchable type="desktop-id">strawberry.desktop</launchable>
<launchable type="desktop-id">org.strawbs.strawberry.desktop</launchable>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-3.0+</project_license>
<provides>
@@ -34,7 +34,7 @@
<li>Audio analyzer</li>
<li>Audio equalizer</li>
<li>Transfer music to iPod, iPhone, MTP or mass-storage USB player</li>
<li>Streaming support for Tidal</li>
<li>Streaming support for Tidal, Qobuz and Subsonic</li>
<li>Scrobbler with support for Last.fm, Libre.fm and ListenBrainz</li>
</ul>
</description>

View File

@@ -10,4 +10,4 @@ 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;

View File

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

View File

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

View File

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

View File

@@ -1,14 +1,55 @@
!define PRODUCT_NAME "Strawberry"
!define PRODUCT_PUBLISHER "Strawberry"
!if "@ARCH@" == x86
!define arch_x86
!endif
!if "@ARCH@" == i686-w64-mingw32.shared
!define arch_x86
!endif
!if "@ARCH@" == x86_64
!define arch_x64
!endif
!if "@ARCH@" == x86_64-w64-mingw32.shared
!define arch_x64
!endif
!if "@CMAKE_BUILD_TYPE@" == Debug
!define debug
!endif
!ifdef debug
!define PRODUCT_NAME "Strawberry Music Player Debug"
!define PRODUCT_NAME_SHORT "Strawberry"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME_SHORT}Debug"
!ifdef arch_x86
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player Debug"
!endif
!ifdef arch_x64
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES64\Strawberry Music Player Debug"
!endif
!else
!define PRODUCT_NAME "Strawberry Music Player"
!define PRODUCT_NAME_SHORT "Strawberry"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME_SHORT}"
!ifdef arch_x86
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
!endif
!ifdef arch_x64
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES64\Strawberry Music Player"
!endif
!endif
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
!define PRODUCT_PUBLISHER "Jonas Kvinge"
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
; Set Application Capabilities info
!define CAPABILITIES_NAME "Strawberry Music Player"
@@ -22,6 +63,7 @@
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
SetCompressor /SOLID lzma
!addplugindir nsisplugins
!include "MUI2.nsh"
!include "FileAssociation.nsh"
@@ -42,13 +84,28 @@ SetCompressor /SOLID lzma
; Uninstaller pages
!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
Name "${PRODUCT_NAME}"
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
!ifdef arch_x86
!ifdef debug
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x86.exe"
!else
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-x86.exe"
!endif
!endif
!ifdef arch_x64
!ifdef debug
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
!else
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-x64.exe"
!endif
!endif
InstallDir "${PRODUCT_INSTALL_DIR}"
; Get the path where Strawberry was installed previously and set it as default path
@@ -102,15 +159,13 @@ Section "Strawberry" Strawberry
File "strawberry.ico"
File "libbz2.dll"
File "libcdio-18.dll"
File "libcdio-19.dll"
File "libchromaprint.dll"
File "libcrypto-3-x64.dll"
File "libfaad-2.dll"
File "libffi-6.dll"
File "libfftw3-3.dll"
File "libFLAC-8.dll"
File "libfreetype-6.dll"
File "libgcc_s_seh-1.dll"
File "libgio-2.0-0.dll"
File "libglib-2.0-0.dll"
File "libgmodule-2.0-0.dll"
@@ -131,34 +186,30 @@ Section "Strawberry" Strawberry
File "libgsttag-1.0-0.dll"
File "libgstvideo-1.0-0.dll"
File "libharfbuzz-0.dll"
File "libhogweed-4.dll"
File "libhogweed-5.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 "libmpcdec-5.dll"
File "libnettle-6.dll"
File "libnettle-7.dll"
File "libogg-0.dll"
File "libopus-0.dll"
File "libpcre-1.dll"
File "libpcre2-16-0.dll"
File "libpng16-16.dll"
File "libprotobuf-18.dll"
File "libprotobuf-20.dll"
File "libsoup-2.4-1.dll"
File "libspeex-1.dll"
File "libsqlite3-0.dll"
File "libssl-3-x64.dll"
File "libstdc++-6.dll"
File "libtag.dll"
File "libtheora-0.dll"
File "libunistring-2.dll"
File "libvorbis-0.dll"
File "libvorbisenc-2.dll"
File "libwavpack-1.dll"
File "libwinpthread-1.dll"
File "libxine-2.dll"
File "libxml2-2.dll"
File "Qt5Concurrent.dll"
File "Qt5Core.dll"
@@ -168,6 +219,26 @@ Section "Strawberry" Strawberry
File "Qt5Widgets.dll"
File "Qt5WinExtras.dll"
File "zlib1.dll"
File "libzstd.dll"
File "libtasn1-6.dll"
!ifdef arch_x86
File "libgcc_s_sjlj-1.dll"
File "libcrypto-3.dll"
File "libssl-3.dll"
!endif
!ifdef arch_x64
File "libgcc_s_seh-1.dll"
File "libcrypto-3-x64.dll"
File "libssl-3-x64.dll"
!endif
!ifdef debug
File "libmpcdec-5.dll"
File "libtheora-0.dll"
File "libxine-2.dll"
!endif
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@@ -265,6 +336,7 @@ Section "Gstreamer plugins" gstreamer-plugins
SectionEnd
!ifdef debug
Section "Xine plugins" xine-plugins
SetOutPath "$INSTDIR\xine-plugins"
File "/oname=xineplug_ao_out_directx2.dll" "xine-plugins\xineplug_ao_out_directx2.dll"
@@ -293,8 +365,8 @@ Section "Xine plugins" xine-plugins
File "/oname=xineplug_post_switch.dll" "xine-plugins\xineplug_post_switch.dll"
File "/oname=xineplug_post_tvtime.dll" "xine-plugins\xineplug_post_tvtime.dll"
File "/oname=xineplug_post_visualizations.dll" "xine-plugins\xineplug_post_visualizations.dll"
SectionEnd
!endif
Section "Start menu items" startmenu
; Create Start Menu folders and shortcuts.
@@ -352,15 +424,13 @@ Section "Uninstall"
Delete "$INSTDIR\strawberry-tagreader.exe"
Delete "$INSTDIR\libbz2.dll"
Delete "$INSTDIR\libcdio-18.dll"
Delete "$INSTDIR\libcdio-19.dll"
Delete "$INSTDIR\libchromaprint.dll"
Delete "$INSTDIR\libcrypto-3-x64.dll"
Delete "$INSTDIR\libfaad-2.dll"
Delete "$INSTDIR\libffi-6.dll"
Delete "$INSTDIR\libfftw3-3.dll"
Delete "$INSTDIR\libFLAC-8.dll"
Delete "$INSTDIR\libfreetype-6.dll"
Delete "$INSTDIR\libgcc_s_seh-1.dll"
Delete "$INSTDIR\libgio-2.0-0.dll"
Delete "$INSTDIR\libglib-2.0-0.dll"
Delete "$INSTDIR\libgmodule-2.0-0.dll"
@@ -381,34 +451,30 @@ Section "Uninstall"
Delete "$INSTDIR\libgsttag-1.0-0.dll"
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
Delete "$INSTDIR\libharfbuzz-0.dll"
Delete "$INSTDIR\libhogweed-4.dll"
Delete "$INSTDIR\libhogweed-5.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\libmpcdec-5.dll"
Delete "$INSTDIR\libnettle-6.dll"
Delete "$INSTDIR\libnettle-7.dll"
Delete "$INSTDIR\libogg-0.dll"
Delete "$INSTDIR\libopus-0.dll"
Delete "$INSTDIR\libpcre-1.dll"
Delete "$INSTDIR\libpcre2-16-0.dll"
Delete "$INSTDIR\libpng16-16.dll"
Delete "$INSTDIR\libprotobuf-18.dll"
Delete "$INSTDIR\libprotobuf-20.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\libspeex-1.dll"
Delete "$INSTDIR\libsqlite3-0.dll"
Delete "$INSTDIR\libssl-3-x64.dll"
Delete "$INSTDIR\libstdc++-6.dll"
Delete "$INSTDIR\libtag.dll"
Delete "$INSTDIR\libtheora-0.dll"
Delete "$INSTDIR\libunistring-2.dll"
Delete "$INSTDIR\libvorbis-0.dll"
Delete "$INSTDIR\libvorbisenc-2.dll"
Delete "$INSTDIR\libwavpack-1.dll"
Delete "$INSTDIR\libwinpthread-1.dll"
Delete "$INSTDIR\libxine-2.dll"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\Qt5Concurrent.dll"
Delete "$INSTDIR\Qt5Core.dll"
@@ -418,6 +484,26 @@ Section "Uninstall"
Delete "$INSTDIR\Qt5Widgets.dll"
Delete "$INSTDIR\Qt5WinExtras.dll"
Delete "$INSTDIR\zlib1.dll"
Delete "$INSTDIR\libzstd.dll"
Delete "$INSTDIR\libtasn1-6.dll"
!ifdef arch_x86
Delete "$INSTDIR\libgcc_s_sjlj-1.dll"
Delete "$INSTDIR\libcrypto-3.dll"
Delete "$INSTDIR\libssl-3.dll"
!endif
!ifdef arch_x64
Delete "$INSTDIR\libgcc_s_seh-1.dll"
Delete "$INSTDIR\libcrypto-3-x64.dll"
Delete "$INSTDIR\libssl-3-x64.dll"
!endif
!ifdef debug
Delete "$INSTDIR\libmpcdec-5.dll"
Delete "$INSTDIR\libtheora-0.dll"
Delete "$INSTDIR\libxine-2.dll"
!endif
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
@@ -468,33 +554,6 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\libgstasfmux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx2.dll"
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_dts.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_dvaudio.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_faad.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_gsm610.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_lpcm.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_mad.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpc.dll"
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpeg2.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_asf.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_audio.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_playlist.dll"
Delete "$INSTDIR\xine-plugins\xineplug_dmx_slave.dll"
Delete "$INSTDIR\xine-plugins\xineplug_flac.dll"
Delete "$INSTDIR\xine-plugins\xineplug_wavpack.dll"
Delete "$INSTDIR\xine-plugins\xineplug_xiph.dll"
Delete "$INSTDIR\xine-plugins\xineplug_inp_cdda.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_audio_filters.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_goom.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_mosaico.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_planar.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_switch.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_tvtime.dll"
Delete "$INSTDIR\xine-plugins\xineplug_post_visualizations.dll"
Delete "$INSTDIR\Uninstall.exe"
; Remove the installation folders.

View File

@@ -2,13 +2,14 @@ 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 -Woverloaded-virtual -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-local-typedefs -fpermissive")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Woverloaded-virtual -Wno-sign-compare -fpermissive")
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})
include_directories(${GSTREAMER_AUDIO_INCLUDE_DIRS})
include_directories(${FFTW3_INCLUDE_DIR})
set(SOURCES gstfastspectrum.cpp gstmoodbarplugin.cpp)

View File

@@ -22,6 +22,9 @@
#include <cstring>
#include <cmath>
#include <gst/gst.h>
#include <gst/audio/gstaudiofilter.h>
#include <QMutex>
#include <QMutexLocker>

View File

@@ -5,7 +5,7 @@ include_directories(${CMAKE_SOURCE_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 -Woverloaded-virtual -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-local-typedefs -fpermissive")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Woverloaded-virtual -Wno-sign-compare -fpermissive")
set(SOURCES
core/closure.cpp

View File

@@ -22,6 +22,7 @@
#include "closure.h"
#include "core/logging.h"
#include "core/timeconstants.h"
namespace _detail {
@@ -30,8 +31,7 @@ ClosureBase::ClosureBase(ObjectHelper *helper)
: helper_(helper) {
}
ClosureBase::~ClosureBase() {
}
ClosureBase::~ClosureBase() {}
CallbackClosure::CallbackClosure(QObject *sender, const char *signal, std::function<void()> callback)
: ClosureBase(new ObjectHelper(sender, signal, this)),
@@ -53,6 +53,8 @@ ObjectHelper::ObjectHelper(QObject *sender, const char *signal, ClosureBase *clo
}
ObjectHelper::~ObjectHelper() {}
void ObjectHelper::Invoked() {
closure_->Invoke();
deleteLater();

View File

@@ -34,6 +34,8 @@
#include <QList>
#include <QTimer>
#include "core/logging.h"
namespace _detail {
class ObjectHelper;
@@ -62,6 +64,7 @@ class ObjectHelper : public QObject {
Q_OBJECT
public:
ObjectHelper(QObject *parent, const char *signal, ClosureBase *closure);
~ObjectHelper();
private slots:
void Invoked();

View File

@@ -150,10 +150,9 @@ bool AbstractMessageHandler<MT>::RawMessageArrived(const QByteArray &data) {
return false;
}
ReplyType *reply = pending_replies_.take(message.id());
if (reply) {
if (pending_replies_.contains(message.id())) {
// This is a reply to a message that we created earlier.
ReplyType *reply = pending_replies_.take(message.id());
reply->SetReply(message);
}
else {

View File

@@ -80,15 +80,18 @@ MessageReply<MessageType>::MessageReply(const MessageType& request_message, QObj
template<typename MessageType>
void MessageReply<MessageType>::SetReply(const MessageType& message) {
Q_ASSERT(!finished_);
reply_message_.MergeFrom(message);
finished_ = true;
success_ = true;
emit Finished(success_);
qLog(Debug) << "Releasing ID" << id() << "(finished)";
semaphore_.release();
emit Finished(success_);
}
#endif // MESSAGEREPLY_H

View File

@@ -7,7 +7,7 @@ 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 -Woverloaded-virtual -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-local-typedefs -fpermissive")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Woverloaded-virtual -Wno-sign-compare -fpermissive")
set(MESSAGES
tagreadermessages.proto

View File

@@ -136,7 +136,13 @@ const char *kASF_OriginalYear_ID = "WM/OriginalReleaseYear";
TagReader::TagReader() :
factory_(new TagLibFileRefFactory),
network_(new QNetworkAccessManager),
kEmbeddedCover("(embedded)") {}
kEmbeddedCover("(embedded)") {
}
TagReader::~TagReader() {
delete network_;
delete factory_;
}
pb::tagreader::SongMetadata_FileType TagReader::GuessFileType(TagLib::FileRef *fileref) const {
@@ -174,7 +180,11 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
song->set_url(url.constData(), url.size());
song->set_filesize(info.size());
song->set_mtime(info.lastModified().toTime_t());
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
song->set_ctime(info.birthTime().isValid() ? info.birthTime().toTime_t() : info.lastModified().toTime_t());
#else
song->set_ctime(info.created().toTime_t());
#endif
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
if (fileref->isNull()) {
@@ -273,6 +283,12 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
song->set_originalyear(map["TORY"].front()->toString().substr(0, 4).toInt());
}
if (!map["USLT"].isEmpty()) {
Decode(map["USLT"].front()->toString(), nullptr, song->mutable_lyrics());
}
else if (!map["SYLT"].isEmpty()) {
Decode(map["SYLT"].front()->toString(), nullptr, song->mutable_lyrics());
}
if (!map["APIC"].isEmpty()) song->set_art_automatic(kEmbeddedCover);

View File

@@ -60,6 +60,7 @@ class FileRefFactory;
class TagReader {
public:
TagReader();
~TagReader();
pb::tagreader::SongMetadata_FileType GuessFileType(TagLib::FileRef *fileref) const;

View File

@@ -9,7 +9,7 @@ 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 -Woverloaded-virtual -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-local-typedefs -fpermissive")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Woverloaded-virtual -Wno-sign-compare -fpermissive")
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})

View File

@@ -1,5 +1,5 @@
name: strawberry
version: '0.5.3+git'
version: '0.6.2+git'
summary: music player and collection organizer
description: |
Strawberry is a music player and collection organizer.
@@ -148,6 +148,10 @@ parts:
- libdb5.3
- libglu1
- libslang2
- libatk1.0-0
- libatk-bridge2.0-0
- libatk1.0-data
- libatk-adaptor
- dbus-x11
- libgstreamer1.0-0
- libgstreamer-plugins-base1.0-0
@@ -167,13 +171,10 @@ apps:
ALSA_CONFIG_PATH: /snap/$SNAPCRAFT_PROJECT_NAME/current/usr/share/alsa/alsa.conf
LD_LIBRARY_PATH: $LD_LIBRARY_PATH:$SNAP/usr/lib/$SNAPCRAFT_ARCH_TRIPLET/pulseaudio
plugs:
- system-observe
- system-trace
- home
- udisks2
- network
- network-control
- network-manager
- network-manager-observe
- network-bind
- desktop
- desktop-legacy
@@ -181,8 +182,6 @@ apps:
- wayland
- alsa
- pulseaudio
- mount-observe
- fuse-support
- removable-media
- optical-drive
- raw-usb
@@ -196,6 +195,5 @@ apps:
command: strawberry-tagreader
plugs:
- network
- network-control
- network-manager
- network-manager-observe
- network-bind

View File

@@ -16,9 +16,9 @@
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 -Woverloaded-virtual -Wno-sign-compare -Wno-deprecated-declarations -Wno-unused-local-typedefs -fpermissive")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Woverloaded-virtual -Wno-sign-compare -fpermissive")
option(BUILD_WERROR "Build with -Werror" ON)
option(BUILD_WERROR "Build with -Werror" OFF)
if(BUILD_WERROR)
if (LINUX)
@@ -45,7 +45,6 @@ include_directories(${GLIBCONFIG_INCLUDE_DIRS})
include_directories(${GOBJECT_INCLUDE_DIRS})
include_directories(${GNUTLS_INCLUDE_DIR})
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${LIBXML_INCLUDE_DIRS})
include_directories(${CHROMAPRINT_INCLUDE_DIRS})
if (X11_FOUND)
@@ -113,6 +112,7 @@ set(SOURCES
core/windows7thumbbar.cpp
core/screensaver.cpp
core/scopedtransaction.cpp
core/translations.cpp
engine/enginetype.cpp
engine/enginebase.cpp
@@ -138,6 +138,7 @@ set(SOURCES
collection/collectionbackend.cpp
collection/collectionwatcher.cpp
collection/collectionview.cpp
collection/collectionitemdelegate.cpp
collection/collectionviewcontainer.cpp
collection/collectiondirectorymodel.cpp
collection/collectionfilterwidget.cpp
@@ -195,7 +196,7 @@ set(SOURCES
covermanager/coversearchstatistics.cpp
covermanager/coversearchstatisticsdialog.cpp
covermanager/coverexportrunnable.cpp
covermanager/currentartloader.cpp
covermanager/currentalbumcoverloader.cpp
covermanager/coverfromurldialog.cpp
covermanager/lastfmcoverprovider.cpp
covermanager/musicbrainzcoverprovider.cpp
@@ -207,7 +208,6 @@ set(SOURCES
lyrics/lyricsfetcher.cpp
lyrics/lyricsfetchersearch.cpp
lyrics/auddlyricsprovider.cpp
lyrics/chartlyricsprovider.cpp
settings/settingsdialog.cpp
settings/settingspage.cpp
@@ -263,6 +263,11 @@ set(SOURCES
internet/internetsearchsortmodel.cpp
internet/internetsearchitemdelegate.cpp
internet/localredirectserver.cpp
internet/internetsongsview.cpp
internet/internettabsview.cpp
internet/internetcollectionview.cpp
internet/internetcollectionviewcontainer.cpp
internet/internetsearchview.cpp
scrobbler/audioscrobbler.cpp
scrobbler/scrobblerservices.cpp
@@ -322,6 +327,7 @@ set(HEADERS
collection/collectionbackend.h
collection/collectionwatcher.h
collection/collectionview.h
collection/collectionitemdelegate.h
collection/collectionviewcontainer.h
collection/collectiondirectorymodel.h
collection/collectionfilterwidget.h
@@ -371,7 +377,7 @@ set(HEADERS
covermanager/coverproviders.h
covermanager/coversearchstatisticsdialog.h
covermanager/coverexportrunnable.h
covermanager/currentartloader.h
covermanager/currentalbumcoverloader.h
covermanager/coverfromurldialog.h
covermanager/lastfmcoverprovider.h
covermanager/musicbrainzcoverprovider.h
@@ -383,7 +389,6 @@ set(HEADERS
lyrics/lyricsfetcher.h
lyrics/lyricsfetchersearch.h
lyrics/auddlyricsprovider.h
lyrics/chartlyricsprovider.h
settings/settingsdialog.h
settings/settingspage.h
@@ -425,6 +430,7 @@ set(HEADERS
widgets/tracksliderpopup.h
widgets/tracksliderslider.h
widgets/loginstatewidget.h
widgets/qsearchfield.h
musicbrainz/acoustidclient.h
musicbrainz/musicbrainzclient.h
@@ -436,6 +442,11 @@ set(HEADERS
internet/internetsearchview.h
internet/internetsearchmodel.h
internet/localredirectserver.h
internet/internetsongsview.h
internet/internettabsview.h
internet/internetcollectionview.h
internet/internetcollectionviewcontainer.h
internet/internetsearchview.h
scrobbler/audioscrobbler.h
scrobbler/scrobblerservices.h
@@ -501,6 +512,8 @@ set(UI
widgets/fileview.ui
widgets/loginstatewidget.ui
internet/internettabsview.ui
internet/internetcollectionviewcontainer.ui
internet/internetsearchview.ui
organise/organisedialog.ui
@@ -513,6 +526,11 @@ set(OTHER_SOURCES)
option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON)
if(NOT APPLE)
set(NOT_APPLE ON)
optional_source(NOT_APPLE SOURCES widgets/qsearchfield_nonmac.cpp)
endif()
if(HAVE_GLOBALSHORTCUTS)
optional_source(HAVE_GLOBALSHORTCUTS
SOURCES globalshortcuts/globalshortcuts.cpp globalshortcuts/globalshortcutbackend.cpp globalshortcuts/globalshortcutgrabber.cpp settings/shortcutssettingspage.cpp
@@ -558,9 +576,12 @@ optional_source(HAVE_GSTREAMER
# Xine
optional_source(HAVE_XINE
SOURCES engine/xineengine.cpp engine/xinescope.c
SOURCES engine/xineengine.cpp
HEADERS engine/xineengine.h
)
optional_source(XINE_ANALYZER
SOURCES engine/xinescope.c
)
# VLC
optional_source(HAVE_VLC
@@ -582,10 +603,6 @@ if(UNIX AND HAVE_DBUS)
SOURCES core/mpris.cpp core/mpris2.cpp core/dbusscreensaver.cpp
HEADERS core/mpris.h core/mpris2.h
)
optional_source(HAVE_DEVICEKIT
SOURCES device/devicekitlister.cpp
HEADERS device/devicekitlister.h
)
optional_source(HAVE_UDISKS2
SOURCES device/udisks2lister.cpp
HEADERS device/udisks2lister.h
@@ -645,20 +662,6 @@ if(UNIX AND HAVE_DBUS)
list(APPEND HEADERS ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup.h)
list(APPEND SOURCES ${CMAKE_CURRENT_BINARY_DIR}/dbus/avahientrygroup.cpp)
# DeviceKit DBUS interfaces
if(HAVE_DEVICEKIT)
set_source_files_properties(dbus/org.freedesktop.UDisks.xml
PROPERTIES NO_NAMESPACE dbus/udisks)
set_source_files_properties(dbus/org.freedesktop.UDisks.Device.xml
PROPERTIES NO_NAMESPACE dbus/udisksdevice)
qt5_add_dbus_interface(SOURCES
dbus/org.freedesktop.UDisks.xml
dbus/udisks)
qt5_add_dbus_interface(SOURCES
dbus/org.freedesktop.UDisks.Device.xml
dbus/udisksdevice)
endif(HAVE_DEVICEKIT)
if(HAVE_UDISKS2)
set_source_files_properties(dbus/org.freedesktop.DBus.ObjectManager.xml
PROPERTIES NO_NAMESPACE dbus/objectmanager INCLUDE dbus/metatypes.h)
@@ -839,6 +842,7 @@ optional_source(APPLE
core/macscreensaver.cpp
core/macfslistener.mm
widgets/osd_mac.mm
widgets/qsearchfield_mac.mm
engine/macosdevicefinder.cpp
globalshortcuts/globalshortcutbackend-macos.mm
globalshortcuts/globalshortcutgrabber.mm
@@ -868,17 +872,63 @@ 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
)
optional_source(HAVE_QOBUZ
SOURCES
qobuz/qobuzservice.cpp
qobuz/qobuzurlhandler.cpp
qobuz/qobuzbaserequest.cpp
qobuz/qobuzrequest.cpp
qobuz/qobuzstreamurlrequest.cpp
qobuz/qobuzfavoriterequest.cpp
settings/qobuzsettingspage.cpp
HEADERS
qobuz/qobuzservice.h
qobuz/qobuzurlhandler.h
qobuz/qobuzbaserequest.h
qobuz/qobuzrequest.h
qobuz/qobuzstreamurlrequest.h
qobuz/qobuzfavoriterequest.h
settings/qobuzsettingspage.h
UI
settings/qobuzsettingspage.ui
)
optional_source(HAVE_SUBSONIC
SOURCES
subsonic/subsonicservice.cpp
subsonic/subsonicurlhandler.cpp
subsonic/subsonicbaserequest.cpp
subsonic/subsonicrequest.cpp
settings/subsonicsettingspage.cpp
HEADERS
subsonic/subsonicservice.h
subsonic/subsonicurlhandler.h
subsonic/subsonicbaserequest.h
subsonic/subsonicrequest.h
settings/subsonicsettingspage.h
UI
settings/subsonicsettingspage.ui
)
# Moodbar
optional_source(HAVE_MOODBAR
SOURCES
@@ -963,7 +1013,6 @@ target_link_libraries(strawberry_lib
${TAGLIB_LIBRARIES}
${SINGLEAPPLICATION_LIBRARIES}
${SINGLECOREAPPLICATION_LIBRARIES}
${QOCOA_LIBRARIES}
z
)

View File

@@ -23,13 +23,12 @@
#include <QWidget>
#include <QVariant>
#include <QString>
#include <QMenu>
#include <QAction>
#include <QActionGroup>
#include <QTimer>
#include <QBoxLayout>
#include <QLayout>
#include <QSignalMapper>
#include <QMenu>
#include <QAction>
#include <QActionGroup>
#include <QSettings>
#include <QtEvents>
#include <QtDebug>
@@ -60,8 +59,6 @@ AnalyzerContainer::AnalyzerContainer(QWidget *parent)
context_menu_framerate_(new QMenu(tr("Framerate"), this)),
group_(new QActionGroup(this)),
group_framerate_(new QActionGroup(this)),
mapper_(new QSignalMapper(this)),
mapper_framerate_(new QSignalMapper(this)),
visualisation_action_(nullptr),
double_click_timer_(new QTimer(this)),
ignore_next_click_(false),
@@ -77,7 +74,6 @@ AnalyzerContainer::AnalyzerContainer(QWidget *parent)
AddFramerate(tr("Medium (%1 fps)").arg(kMediumFramerate), kMediumFramerate);
AddFramerate(tr("High (%1 fps)").arg(kHighFramerate), kHighFramerate);
AddFramerate(tr("Super high (%1 fps)").arg(kSuperHighFramerate), kSuperHighFramerate);
connect(mapper_framerate_, SIGNAL(mapped(int)), SLOT(ChangeFramerate(int)));
context_menu_->addMenu(context_menu_framerate_);
context_menu_->addSeparator();
@@ -87,7 +83,6 @@ AnalyzerContainer::AnalyzerContainer(QWidget *parent)
AddAnalyzerType<Rainbow::NyanCatAnalyzer>();
AddAnalyzerType<Rainbow::RainbowDashAnalyzer>();
connect(mapper_, SIGNAL(mapped(int)), SLOT(ChangeAnalyzer(int)));
disable_action_ = context_menu_->addAction(tr("No analyzer"), this, SLOT(DisableAnalyzer()));
disable_action_->setCheckable(true);
group_->addAction(disable_action_);
@@ -250,10 +245,10 @@ void AnalyzerContainer::Save() {
void AnalyzerContainer::AddFramerate(const QString& name, int framerate) {
QAction *action = context_menu_framerate_->addAction(name, mapper_framerate_, SLOT(map()));
mapper_framerate_->setMapping(action, framerate);
QAction *action = context_menu_framerate_->addAction(name);
group_framerate_->addAction(action);
framerate_list_ << framerate;
action->setCheckable(true);
connect(action, &QAction::triggered, [this, framerate]() { ChangeFramerate(framerate); } );
}

View File

@@ -24,7 +24,6 @@
#include <stdbool.h>
#include <QObject>
#include <QWidget>
#include <QList>
#include <QString>
@@ -32,12 +31,10 @@
#include <QMenu>
#include <QAction>
#include <QActionGroup>
#include <QSignalMapper>
#include <QTimer>
#include <QtEvents>
#include "engine/engine_fwd.h"
class QTimer;
class QMouseEvent;
class QWheelEvent;
@@ -90,8 +87,6 @@ signals:
QMenu *context_menu_framerate_;
QActionGroup *group_;
QActionGroup *group_framerate_;
QSignalMapper *mapper_;
QSignalMapper *mapper_framerate_;
QList<const QMetaObject*> analyzer_types_;
QList<int> framerate_list_;
@@ -110,14 +105,16 @@ signals:
template <typename T>
void AnalyzerContainer::AddAnalyzerType() {
int id = analyzer_types_.count();
analyzer_types_ << &T::staticMetaObject;
QAction *action = context_menu_->addAction(tr(T::kName), mapper_, SLOT(map()));
QAction *action = context_menu_->addAction(tr(T::kName));
group_->addAction(action);
mapper_->setMapping(action, id);
action->setCheckable(true);
actions_ << action;
connect(action, &QAction::triggered, [this, id]() { ChangeAnalyzer(id); } );
}
#endif // ANALYZERCONTAINER_H

View File

@@ -345,12 +345,12 @@ 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).dark(112);
const QColor bg = 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).dark(150).getHsv(&h, &s, &v);
palette().color(QPalette::Background).darker(150).getHsv(&h, &s, &v);
const QColor fg(QColor::fromHsv(h + 120, s, v));
const double dr = fg.red() - bg.red();
@@ -380,7 +380,7 @@ void BlockAnalyzer::drawBackground() {
}
const QColor bg = palette().color(QPalette::Background);
const QColor bgdark = bg.dark(112);
const QColor bgdark = bg.darker(112);
background_.fill(bg);

View File

@@ -21,6 +21,7 @@
#include "config.h"
#include <stdbool.h>
#include <unistd.h>
#include <QObject>
#include <QThread>
@@ -50,12 +51,15 @@ SCollection::SCollection(Application *app, QObject *parent)
backend_(nullptr),
model_(nullptr),
watcher_(nullptr),
watcher_thread_(nullptr) {
watcher_thread_(nullptr),
original_thread_(nullptr) {
original_thread_ = thread();
backend_ = new CollectionBackend();
backend()->moveToThread(app->database()->thread());
backend_->Init(app->database(), kSongsTable, kDirsTable, kSubdirsTable, kFtsTable);
backend_->Init(app->database(), Song::Source_Collection, kSongsTable, kDirsTable, kSubdirsTable, kFtsTable);
model_ = new CollectionModel(backend_, app_, this);
@@ -64,10 +68,17 @@ SCollection::SCollection(Application *app, QObject *parent)
}
SCollection::~SCollection() {
watcher_->Stop();
watcher_->deleteLater();
watcher_thread_->exit();
watcher_thread_->wait(5000 /* five seconds */);
if (watcher_) {
watcher_->Stop();
watcher_->deleteLater();
}
if (watcher_thread_) {
watcher_thread_->exit();
watcher_thread_->wait(5000 /* five seconds */);
}
backend_->deleteLater();
}
void SCollection::Init() {
@@ -97,12 +108,46 @@ void SCollection::Init() {
// This will start the watcher checking for updates
backend_->LoadDirectoriesAsync();
}
void SCollection::Exit() {
wait_for_exit_ << backend_ << watcher_;
disconnect(backend_, 0, watcher_, 0);
disconnect(watcher_, 0, backend_, 0);
connect(backend_, SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
connect(watcher_, SIGNAL(ExitFinished()), this, SLOT(ExitReceived()));
backend_->ExitAsync();
watcher_->ExitAsync();
}
void SCollection::ExitReceived() {
QObject *obj = static_cast<QObject*>(sender());
disconnect(obj, 0, this, 0);
qLog(Debug) << obj << "successfully exited.";
wait_for_exit_.removeAll(obj);
if (wait_for_exit_.isEmpty()) emit ExitFinished();
}
void SCollection::IncrementalScan() { watcher_->IncrementalScanAsync(); }
void SCollection::FullScan() { watcher_->FullScanAsync(); }
void SCollection::AbortScan() { watcher_->Stop(); }
void SCollection::Rescan(const SongList &songs) {
qLog(Debug) << "Rescan" << songs.size() << "songs";
if (!songs.isEmpty()) watcher_->RescanTracksAsync(songs);
}
void SCollection::PauseWatcher() { watcher_->SetRescanPausedAsync(true); }
void SCollection::ResumeWatcher() { watcher_->SetRescanPausedAsync(false); }

View File

@@ -49,6 +49,7 @@ class SCollection : public QObject {
static const char *kFtsTable;
void Init();
void Exit();
CollectionBackend *backend() const { return backend_; }
CollectionModel *model() const { return model_; }
@@ -66,14 +67,21 @@ class SCollection : public QObject {
void ResumeWatcher();
void FullScan();
void AbortScan();
void Rescan(const SongList &songs);
private slots:
void ExitReceived();
void IncrementalScan();
void CurrentSongChanged(const Song &song);
void SongsStatisticsChanged(const SongList& songs);
void Stopped();
signals:
void ExitFinished();
private:
Application *app_;
CollectionBackend *backend_;
@@ -81,9 +89,12 @@ class SCollection : public QObject {
CollectionWatcher *watcher_;
Thread *watcher_thread_;
QThread *original_thread_;
// DB schema versions which should trigger a full collection rescan (each of those with a short reason why).
QHash<int, QString> full_rescan_revisions_;
QList<QObject*> wait_for_exit_;
};
#endif

View File

@@ -20,8 +20,12 @@
#include "config.h"
#include <assert.h>
#include <QtGlobal>
#include <QObject>
#include <QApplication>
#include <QThread>
#include <QMutex>
#include <QSet>
#include <QMap>
@@ -31,6 +35,7 @@
#include <QVariant>
#include <QString>
#include <QStringList>
#include <QRegExp>
#include <QUrl>
#include <QSqlDatabase>
#include <QSqlQuery>
@@ -51,16 +56,47 @@ const char *CollectionBackend::kSettingsGroup = "Collection";
CollectionBackend::CollectionBackend(QObject *parent) :
CollectionBackendInterface(parent),
db_(nullptr) {}
db_(nullptr),
original_thread_(nullptr) {
void CollectionBackend::Init(Database *db, const QString &songs_table, const QString &dirs_table, const QString &subdirs_table, const QString &fts_table) {
original_thread_ = thread();
}
CollectionBackend::~CollectionBackend() {}
void CollectionBackend::Init(Database *db, const Song::Source source, const QString &songs_table, const QString &dirs_table, const QString &subdirs_table, const QString &fts_table) {
db_ = db;
source_ = source;
songs_table_ = songs_table;
dirs_table_ = dirs_table;
subdirs_table_ = subdirs_table;
fts_table_ = fts_table;
}
void CollectionBackend::Close() {
if (db_) {
QMutexLocker l(db_->Mutex());
db_->Close();
}
}
void CollectionBackend::ExitAsync() {
metaObject()->invokeMethod(this, "Exit", Qt::QueuedConnection);
}
void CollectionBackend::Exit() {
assert(QThread::currentThread() == thread());
Close();
moveToThread(original_thread_);
emit ExitFinished();
}
void CollectionBackend::LoadDirectoriesAsync() {
metaObject()->invokeMethod(this, "LoadDirectories", Qt::QueuedConnection);
}
@@ -136,7 +172,7 @@ void CollectionBackend::ChangeDirPath(int id, const QString &old_path, const QSt
// Do the songs table
{
QSqlQuery q(db);
q.prepare(QString("UPDATE %1 SET filename=:path || substr(filename, %2) WHERE directory=:id").arg(songs_table_).arg(path_len));
q.prepare(QString("UPDATE %1 SET url=:path || substr(url, %2) WHERE directory=:id").arg(songs_table_).arg(path_len));
q.bindValue(":path", new_url);
q.bindValue(":id", id);
q.exec();
@@ -328,6 +364,7 @@ void CollectionBackend::SongPathChanged(const Song &song, const QFileInfo &new_f
// Take a song and update its path
Song updated_song = song;
updated_song.InitFromFilePartial(new_file.absoluteFilePath());
updated_song.set_source(source_);
SongList updated_songs;
updated_songs << updated_song;
AddOrUpdateSongs(updated_songs);
@@ -405,6 +442,7 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
SongList deleted_songs;
for (const Song &song : songs) {
// Do a sanity check first - make sure the song's directory still exists
// This is to fix a possible race condition when a directory is removed while CollectionWatcher is scanning it.
if (!dirs_table_.isEmpty()) {
@@ -415,28 +453,8 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
if (!check_dir.next()) continue; // Directory didn't exist
}
if (song.id() == -1) {
// Create
if (song.id() != -1) { // This song exists in the DB.
// Insert the row and create a new ID
song.BindToQuery(&add_song);
add_song.exec();
if (db_->CheckErrors(add_song)) continue;
// Get the new ID
const int id = add_song.lastInsertId().toInt();
// Add to the FTS index
add_song_fts.bindValue(":id", id);
song.BindToFtsQuery(&add_song_fts);
add_song_fts.exec();
if (db_->CheckErrors(add_song_fts)) continue;
Song copy(song);
copy.set_id(id);
added_songs << copy;
}
else {
// Get the previous song data first
Song old_song(GetSongById(song.id()));
if (!old_song.is_valid()) continue;
@@ -454,7 +472,59 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
deleted_songs << old_song;
added_songs << song;
continue;
}
else if (song.song_id() != -1) { // Song has a unique id, check if the song exists.
// Get the previous song data first
Song old_song(GetSongBySongId(song.song_id()));
if (old_song.is_valid() && old_song.id() != -1) {
Song new_song = song;
new_song.set_id(old_song.id());
// Update
new_song.BindToQuery(&update_song);
update_song.bindValue(":id", new_song.id());
update_song.exec();
if (db_->CheckErrors(update_song)) continue;
new_song.BindToFtsQuery(&update_song_fts);
update_song_fts.bindValue(":id", new_song.id());
update_song_fts.exec();
if (db_->CheckErrors(update_song_fts)) continue;
deleted_songs << old_song;
added_songs << new_song;
continue;
}
}
// Create new song
// Insert the row and create a new ID
song.BindToQuery(&add_song);
add_song.exec();
if (db_->CheckErrors(add_song)) continue;
// Get the new ID
const int id = add_song.lastInsertId().toInt();
// Add to the FTS index
add_song_fts.bindValue(":id", id);
song.BindToFtsQuery(&add_song_fts);
add_song_fts.exec();
if (db_->CheckErrors(add_song_fts)) continue;
Song copy(song);
copy.set_id(id);
added_songs << copy;
}
transaction.Commit();
@@ -571,7 +641,7 @@ QStringList CollectionBackend::GetAllArtistsWithAlbums(const QueryOptions &opt)
query.AddCompilationRequirement(false);
query.AddWhere("album", "", "!=");
// Albums with no 'albumartist' (extract 'artist'):
// Albums with no 'albumartist' (extract 'artist'):
CollectionQuery query2(opt);
query2.SetColumnSpec("DISTINCT artist");
query2.AddCompilationRequirement(false);
@@ -715,7 +785,7 @@ Song CollectionBackend::GetSongByUrl(const QUrl &url, qint64 beginning) {
CollectionQuery query;
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
query.AddWhere("filename", url.toString());
query.AddWhere("url", url.toString());
query.AddWhere("beginning", beginning);
Song song;
@@ -730,7 +800,7 @@ SongList CollectionBackend::GetSongsByUrl(const QUrl &url) {
CollectionQuery query;
query.SetColumnSpec("%songs_table.ROWID, " + Song::kColumnSpec);
query.AddWhere("filename", url.toString());
query.AddWhere("url", url.toString());
SongList songlist;
if (ExecQuery(&query)) {
@@ -744,6 +814,57 @@ SongList CollectionBackend::GetSongsByUrl(const QUrl &url) {
}
Song CollectionBackend::GetSongBySongId(int 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);
if (list.isEmpty()) return Song();
return list.first();
}
SongList CollectionBackend::GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db) {
QString in = song_ids.join(",");
QSqlQuery q(db);
q.prepare(QString("SELECT ROWID, " + Song::kColumnSpec + " FROM %1 WHERE SONG_ID IN (%2)").arg(songs_table_, in));
q.exec();
if (db_->CheckErrors(q)) return SongList();
SongList ret;
while (q.next()) {
Song song;
song.InitFromQuery(q, true);
ret << song;
}
return ret;
}
CollectionBackend::AlbumList CollectionBackend::GetCompilationAlbums(const QueryOptions &opt) {
return GetAlbums(QString(), true, opt);
}
@@ -776,7 +897,7 @@ void CollectionBackend::UpdateCompilations() {
// Look for albums that have songs by more than one 'effective album artist' in the same directory
QSqlQuery q(db);
q.prepare(QString("SELECT effective_albumartist, album, filename, compilation_detected FROM %1 WHERE unavailable = 0 ORDER BY album").arg(songs_table_));
q.prepare(QString("SELECT effective_albumartist, album, url, compilation_detected FROM %1 WHERE unavailable = 0 ORDER BY album").arg(songs_table_));
q.exec();
if (db_->CheckErrors(q)) return;
@@ -864,7 +985,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
AlbumList ret;
CollectionQuery query(opt);
query.SetColumnSpec("album, artist, albumartist, compilation, compilation_detected, art_automatic, art_manual, filename");
query.SetColumnSpec("album, artist, albumartist, compilation, compilation_detected, art_automatic, art_manual, url");
query.SetOrderBy("album");
if (compilation) {
@@ -890,10 +1011,24 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
info.artist = compilation ? QString() : query.Value(1).toString();
info.album_artist = compilation ? QString() : query.Value(2).toString();
info.album_name = query.Value(0).toString();
info.art_automatic = query.Value(5).toString();
info.art_manual = query.Value(6).toString();
info.first_url = QUrl::fromEncoded(query.Value(7).toByteArray());
QString art_automatic = query.Value(5).toString();
if (art_automatic.contains(QRegExp("..+:.*"))) {
info.art_automatic = QUrl::fromEncoded(art_automatic.toUtf8());
}
else {
info.art_automatic = QUrl::fromLocalFile(art_automatic.toUtf8());
}
QString art_manual = query.Value(6).toString();
if (art_manual.contains(QRegExp("..+:.*"))) {
info.art_manual = QUrl::fromEncoded(art_manual.toUtf8());
}
else {
info.art_manual = QUrl::fromLocalFile(art_manual.toUtf8());
}
if ((info.artist == last_artist || info.album_artist == last_album_artist) && info.album_name == last_album)
continue;
@@ -916,7 +1051,7 @@ CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &artist, c
ret.album_artist = albumartist;
CollectionQuery query = CollectionQuery(QueryOptions());
query.SetColumnSpec("art_automatic, art_manual, filename");
query.SetColumnSpec("art_automatic, art_manual, url");
if (!albumartist.isEmpty()) {
query.AddWhere("albumartist", albumartist);
}
@@ -929,8 +1064,8 @@ CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &artist, c
if (!ExecQuery(&query)) return ret;
if (query.Next()) {
ret.art_automatic = query.Value(0).toString();
ret.art_manual = query.Value(1).toString();
ret.art_automatic = query.Value(0).toUrl();
ret.art_manual = query.Value(1).toUrl();
ret.first_url = QUrl::fromEncoded(query.Value(2).toByteArray());
}
@@ -938,13 +1073,13 @@ CollectionBackend::Album CollectionBackend::GetAlbumArt(const QString &artist, c
}
void CollectionBackend::UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art) {
void CollectionBackend::UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url) {
metaObject()->invokeMethod(this, "UpdateManualAlbumArt", Qt::QueuedConnection, Q_ARG(QString, artist), Q_ARG(QString, albumartist), Q_ARG(QString, album), Q_ARG(QString, art));
metaObject()->invokeMethod(this, "UpdateManualAlbumArt", Qt::QueuedConnection, Q_ARG(QString, artist), Q_ARG(QString, albumartist), Q_ARG(QString, album), Q_ARG(QUrl, cover_url));
}
void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QString &art) {
void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
@@ -954,10 +1089,10 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QStrin
query.SetColumnSpec("ROWID, " + Song::kColumnSpec);
query.AddWhere("album", album);
if (!albumartist.isNull() && !albumartist.isEmpty()) {
if (!albumartist.isEmpty()) {
query.AddWhere("albumartist", albumartist);
}
else if (!artist.isNull()) {
else if (!artist.isEmpty()) {
query.AddWhere("artist", artist);
}
@@ -971,7 +1106,7 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QStrin
}
// Update the songs
QString sql(QString("UPDATE %1 SET art_manual = :art WHERE album = :album AND unavailable = 0").arg(songs_table_));
QString sql(QString("UPDATE %1 SET art_manual = :cover WHERE album = :album AND unavailable = 0").arg(songs_table_));
if (!albumartist.isNull() && !albumartist.isEmpty()) {
sql += " AND albumartist = :albumartist";
@@ -982,12 +1117,12 @@ void CollectionBackend::UpdateManualAlbumArt(const QString &artist, const QStrin
QSqlQuery q(db);
q.prepare(sql);
q.bindValue(":art", art);
q.bindValue(":cover", cover_url);
q.bindValue(":album", album);
if (!albumartist.isNull() && !albumartist.isEmpty()) {
if (!albumartist.isEmpty()) {
q.bindValue(":albumartist", albumartist);
}
else if (!artist.isNull()) {
else if (!artist.isEmpty()) {
q.bindValue(":artist", artist);
}
@@ -1143,4 +1278,3 @@ void CollectionBackend::DeleteAll() {
emit DatabaseReset();
}

View File

@@ -41,6 +41,7 @@
#include "collectionquery.h"
#include "directory.h"
class QThread;
class Database;
class CollectionBackendInterface : public QObject {
@@ -52,7 +53,7 @@ class CollectionBackendInterface : public QObject {
struct Album {
Album() {}
Album(const QString &_artist, const QString &_album_artist, const QString &_album_name, const QString &_art_automatic, const QString &_art_manual, const QUrl &_first_url) :
Album(const QString &_artist, const QString &_album_artist, const QString &_album_name, const QUrl &_art_automatic, const QUrl &_art_manual, const QUrl &_first_url) :
artist(_artist),
album_artist(_album_artist),
album_name(_album_name),
@@ -68,8 +69,8 @@ class CollectionBackendInterface : public QObject {
QString album_artist;
QString album_name;
QString art_automatic;
QString art_manual;
QUrl art_automatic;
QUrl art_manual;
QUrl first_url;
};
typedef QList<Album> AlbumList;
@@ -99,7 +100,7 @@ class CollectionBackendInterface : public QObject {
virtual AlbumList GetAlbumsByArtist(const QString &artist, const QueryOptions &opt = QueryOptions()) = 0;
virtual AlbumList GetCompilationAlbums(const QueryOptions &opt = QueryOptions()) = 0;
virtual void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art) = 0;
virtual void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url) = 0;
virtual Album GetAlbumArt(const QString &artist, const QString &albumartist, const QString &album) = 0;
virtual Song GetSongById(int id) = 0;
@@ -123,7 +124,12 @@ class CollectionBackend : public CollectionBackendInterface {
static const char *kSettingsGroup;
Q_INVOKABLE CollectionBackend(QObject *parent = nullptr);
void Init(Database *db, const QString &songs_table, const QString &dirs_table, const QString &subdirs_table, const QString &fts_table);
~CollectionBackend();
void Init(Database *db, const Song::Source source, const QString &songs_table, const QString &dirs_table, const QString &subdirs_table, const QString &fts_table);
void Close();
void ExitAsync();
Database *db() const { return db_; }
@@ -155,7 +161,7 @@ class CollectionBackend : public CollectionBackendInterface {
AlbumList GetCompilationAlbums(const QueryOptions &opt = QueryOptions());
AlbumList GetAlbumsByArtist(const QString &artist, const QueryOptions &opt = QueryOptions());
void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QString &art);
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);
@@ -178,7 +184,12 @@ class CollectionBackend : public CollectionBackendInterface {
void DeleteAll();
Song GetSongBySongId(int song_id);
SongList GetSongsBySongId(const QList<int> &song_ids);
SongList GetSongsBySongId(const QStringList &song_ids);
public slots:
void Exit();
void LoadDirectories();
void UpdateTotalSongCount();
void UpdateTotalArtistCount();
@@ -189,14 +200,14 @@ class CollectionBackend : public CollectionBackendInterface {
void MarkSongsUnavailable(const SongList &songs, bool unavailable = true);
void AddOrUpdateSubdirs(const SubdirectoryList &subdirs);
void UpdateCompilations();
void UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QString &art);
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 SongPathChanged(const Song &song, const QFileInfo &new_file);
signals:
signals:
void DirectoryDiscovered(const Directory &dir, const SubdirectoryList &subdirs);
void DirectoryDeleted(const Directory &dir);
@@ -210,6 +221,8 @@ signals:
void TotalArtistCountUpdated(int total);
void TotalAlbumCountUpdated(int total);
void ExitFinished();
private:
struct CompilationInfo {
CompilationInfo() : has_compilation_detected(false), has_not_compilation_detected(false) {}
@@ -229,12 +242,17 @@ signals:
Song GetSongById(int id, QSqlDatabase &db);
SongList GetSongsById(const QStringList &ids, QSqlDatabase &db);
Song GetSongBySongId(int song_id, QSqlDatabase &db);
SongList GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db);
private:
Database *db_;
Song::Source source_;
QString songs_table_;
QString dirs_table_;
QString subdirs_table_;
QString fts_table_;
QThread *original_thread_;
};

View File

@@ -37,7 +37,6 @@
#include <QTimer>
#include <QMenu>
#include <QSettings>
#include <QSignalMapper>
#include <QToolButton>
#include <QtEvents>
@@ -87,20 +86,12 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
filter_age_menu_ = new QMenu(tr("Show"), this);
filter_age_menu_->addActions(filter_age_group->actions());
filter_age_mapper_ = new QSignalMapper(this);
filter_age_mapper_->setMapping(ui_->filter_age_all, -1);
filter_age_mapper_->setMapping(ui_->filter_age_today, 60 * 60 * 24);
filter_age_mapper_->setMapping(ui_->filter_age_week, 60 * 60 * 24 * 7);
filter_age_mapper_->setMapping(ui_->filter_age_month, 60 * 60 * 24 * 30);
filter_age_mapper_->setMapping(ui_->filter_age_three_months, 60 * 60 * 24 * 30 * 3);
filter_age_mapper_->setMapping(ui_->filter_age_year, 60 * 60 * 24 * 365);
connect(ui_->filter_age_all, SIGNAL(triggered()), filter_age_mapper_, SLOT(map()));
connect(ui_->filter_age_today, SIGNAL(triggered()), filter_age_mapper_, SLOT(map()));
connect(ui_->filter_age_week, SIGNAL(triggered()), filter_age_mapper_, SLOT(map()));
connect(ui_->filter_age_month, SIGNAL(triggered()), filter_age_mapper_, SLOT(map()));
connect(ui_->filter_age_three_months, SIGNAL(triggered()), filter_age_mapper_, SLOT(map()));
connect(ui_->filter_age_year, SIGNAL(triggered()), filter_age_mapper_, SLOT(map()));
filter_ages_[ui_->filter_age_all] = -1;
filter_ages_[ui_->filter_age_today] = 60 * 60 * 24;
filter_ages_[ui_->filter_age_week] = 60 * 60 * 24 * 7;
filter_ages_[ui_->filter_age_month] = 60 * 60 * 24 * 30;
filter_ages_[ui_->filter_age_three_months] = 60 * 60 * 24 * 30 * 3;
filter_ages_[ui_->filter_age_year] = 60 * 60 * 24 * 365;
// "Group by ..."
group_by_group_ = CreateGroupByActions(this);
@@ -128,6 +119,19 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
CollectionFilterWidget::~CollectionFilterWidget() { delete ui_; }
QString CollectionFilterWidget::group_by() {
if (settings_prefix_.isEmpty()) {
return QString("group_by");
}
else {
return QString("%1_group_by").arg(settings_prefix_);
}
}
QString CollectionFilterWidget::group_by(const int number) { return group_by() + QString::number(number); }
void CollectionFilterWidget::UpdateGroupByActions() {
if (group_by_group_) {
@@ -231,7 +235,9 @@ void CollectionFilterWidget::SetCollectionModel(CollectionModel *model) {
disconnect(model_, 0, this, 0);
disconnect(model_, 0, group_by_dialog_.get(), 0);
disconnect(group_by_dialog_.get(), 0, model_, 0);
disconnect(filter_age_mapper_, 0, model_, 0);
for (QAction *action : filter_ages_.keys()) {
disconnect(action, &QAction::triggered, model_, 0);
}
}
model_ = model;
@@ -240,16 +246,20 @@ void CollectionFilterWidget::SetCollectionModel(CollectionModel *model) {
connect(model_, SIGNAL(GroupingChanged(CollectionModel::Grouping)), group_by_dialog_.get(), SLOT(CollectionGroupingChanged(CollectionModel::Grouping)));
connect(model_, SIGNAL(GroupingChanged(CollectionModel::Grouping)), SLOT(GroupingChanged(CollectionModel::Grouping)));
connect(group_by_dialog_.get(), SIGNAL(Accepted(CollectionModel::Grouping)), model_, SLOT(SetGroupBy(CollectionModel::Grouping)));
connect(filter_age_mapper_, SIGNAL(mapped(int)), model_, SLOT(SetFilterAge(int)));
for (QAction *action : filter_ages_.keys()) {
int age = filter_ages_[action];
connect(action, &QAction::triggered, [this, age]() { model_->SetFilterAge(age); } );
}
// Load settings
if (!settings_group_.isEmpty()) {
QSettings s;
s.beginGroup(settings_group_);
model_->SetGroupBy(CollectionModel::Grouping(
CollectionModel::GroupBy(s.value("group_by1", int(CollectionModel::GroupBy_AlbumArtist)).toInt()),
CollectionModel::GroupBy(s.value("group_by2", int(CollectionModel::GroupBy_Album)).toInt()),
CollectionModel::GroupBy(s.value("group_by3", int(CollectionModel::GroupBy_None)).toInt())));
CollectionModel::GroupBy(s.value(group_by(1), int(CollectionModel::GroupBy_AlbumArtist)).toInt()),
CollectionModel::GroupBy(s.value(group_by(2), int(CollectionModel::GroupBy_Album)).toInt()),
CollectionModel::GroupBy(s.value(group_by(3), int(CollectionModel::GroupBy_None)).toInt())));
}
}
@@ -270,9 +280,9 @@ void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping &g)
// Save the settings
QSettings s;
s.beginGroup(settings_group_);
s.setValue("group_by1", int(g[0]));
s.setValue("group_by2", int(g[1]));
s.setValue("group_by3", int(g[2]));
s.setValue(group_by(1), int(g[0]));
s.setValue(group_by(2), int(g[1]));
s.setValue(group_by(3), int(g[2]));
}
// Now make sure the correct action is checked

View File

@@ -28,17 +28,17 @@
#include <QWidget>
#include <QObject>
#include <QMap>
#include <QString>
#include <QMenu>
#include <QSignalMapper>
#include <QTimer>
#include <QAction>
#include <QActionGroup>
#include <QtEvents>
#include "collectionquery.h"
#include "collectionmodel.h"
class QTimer;
class QMenu;
class QAction;
class QActionGroup;
class QKeyEvent;
class GroupByDialog;
@@ -76,8 +76,12 @@ class CollectionFilterWidget : public QWidget {
void AddMenuAction(QAction *action);
void SetSettingsGroup(const QString &group) { settings_group_ = group; }
void SetSettingsPrefix(const QString &prefix) { settings_prefix_ = prefix; }
void SetCollectionModel(CollectionModel *model);
QString group_by();
QString group_by(const int number);
public slots:
void SetQueryMode(QueryOptions::QueryMode view);
void FocusOnFilter(QKeyEvent *e);
@@ -116,7 +120,7 @@ signals:
QMenu *group_by_menu_;
QMenu *collection_menu_;
QActionGroup *group_by_group_;
QSignalMapper *filter_age_mapper_;
QMap<QAction*, int> filter_ages_;
QTimer *filter_delay_;
@@ -124,6 +128,8 @@ signals:
DelayBehaviour delay_behaviour_;
QString settings_group_;
QString settings_prefix_;
};
#endif // COLLECTIONFILTERWIDGET_H

View File

@@ -122,7 +122,7 @@
<customwidget>
<class>QSearchField</class>
<extends>QWidget</extends>
<header>3rdparty/qocoa/qsearchfield.h</header>
<header>widgets/qsearchfield.h</header>
</customwidget>
</customwidgets>
<resources/>

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