Compare commits

..

152 Commits
1.0.2 ... 1.0.5

Author SHA1 Message Date
Jonas Kvinge
2770384f1f Release 1.0.5 2022-06-10 21:50:35 +02:00
Jonas Kvinge
f4e5b83039 Replace use of C-style casts 2022-06-10 02:30:39 +02:00
Jonas Kvinge
124681605b Change -Wno-old-style-cast to -Wold-style-cast 2022-06-10 01:23:55 +02:00
Jonas Kvinge
a217faae7c OSDPretty: Remove use of C-style cast 2022-06-10 00:47:11 +02:00
Jonas Kvinge
184c39bbb7 Update Changelog 2022-06-10 00:01:21 +02:00
Jonas Kvinge
508e2a70bb Update Changelog 2022-06-09 23:38:25 +02:00
Jonas Kvinge
5aac56fe96 ContextView: Cleanup spacers 2022-06-09 23:09:41 +02:00
Strawbs Bot
dab7dad966 Update translations 2022-06-09 01:02:32 +02:00
Jonas Kvinge
25e48d6cae Add option for disabling bars on currently playing track
Fixes #972
2022-06-09 00:50:21 +02:00
Jonas Kvinge
9b743e55d1 ContextView: Update album width from context 2022-06-09 00:46:39 +02:00
Jonas Kvinge
dc1f9edfaf Organize: Only notify song path changed for collection and device songs 2022-06-07 22:43:39 +02:00
Strawbs Bot
b6b68edf1e Update translations 2022-06-07 01:01:51 +02:00
Jonas Kvinge
a2320b99ae ContextView: Use fixed size to avoid scrollbar issues 2022-06-06 20:54:15 +02:00
Jonas Kvinge
be01e28068 ContextAlbum: Use sizeHint() 2022-06-06 18:24:00 +02:00
Jonas Kvinge
d6084083a5 Update data/style/strawberry.css 2022-06-06 18:23:34 +02:00
Jonas Kvinge
019bf5102c ResizableTextEdit: Add Q_OBJECT macro 2022-06-06 18:23:12 +02:00
Jonas Kvinge
a1633224d1 CI: Add g++ for debian/ubuntu 2022-06-06 18:22:06 +02:00
Strawbs Bot
e62bd26cb9 Update translations 2022-06-06 01:26:37 +02:00
Jonas Kvinge
c29f517292 Update debian/control.in 2022-06-05 23:47:04 +02:00
Jonas Kvinge
d80144f80c Remove -fpermissive 2022-06-05 23:19:40 +02:00
Jonas Kvinge
4733c84a86 ContextAlbum: Move rescaling back to paintevent 2022-06-05 19:02:34 +02:00
Jonas Kvinge
23f3d2095b ContextAlbum: Improve album cover fading 2022-06-05 18:20:44 +02:00
Jonas Kvinge
4f1f2b6fc6 ContextView: Change condition for showing context menu 2022-06-05 18:19:14 +02:00
Jonas Kvinge
1ea70b085f Context: Remove albums 2022-06-05 11:58:53 +02:00
Jonas Kvinge
6c0b395f4a Add option for overwriting playcounts
Fixes #962
2022-06-05 04:59:50 +02:00
Jonas Kvinge
0ee67f186f Remove widgets/resizabletextedit.h from CMakeLists.txt 2022-06-05 04:57:58 +02:00
Jonas Kvinge
d133addbaa Context: Use custom textedits instead of labels
Also improve album cover scaling

Fixes #965
2022-06-05 04:41:36 +02:00
Jonas Kvinge
683991b1c9 Add ResizableTextEdit 2022-06-05 04:41:36 +02:00
Strawbs Bot
32ac02007b Update translations 2022-06-05 01:01:44 +02:00
Jonas Kvinge
d716617ae0 FancyTabWidget: Make sure context menu does not popup outside of tabbar 2022-06-05 00:25:48 +02:00
Jonas Kvinge
26e1f015d2 Add streaming to description in CMakeLists.txt 2022-06-04 16:16:19 +02:00
Jonas Kvinge
1c94093a4b Update debian/copyright 2022-06-04 16:16:19 +02:00
Strawbs Bot
27eccd456a Update translations 2022-06-04 01:02:03 +02:00
Jonas Kvinge
eed4447560 Update protobuf in nsi 2022-05-31 19:02:31 +02:00
Jonas Kvinge
3c8d0ebd52 CollectionModel: Use grouping in all album groupings 2022-05-31 00:53:47 +02:00
Jonas Kvinge
7ec0d2f2cc Update fftw3 in nsi 2022-05-22 02:14:07 +02:00
Strawbs Bot
35da91a997 Update translations 2022-05-22 01:02:14 +02:00
Jonas Kvinge
788747c071 MainWindow: Remove unnecessary hide() 2022-05-21 19:12:53 +02:00
Jonas Kvinge
36eb131289 MainWindow: Remove QEvent::spontaneous() check in close event
Fixes #964
2022-05-21 19:12:53 +02:00
Jonas Kvinge
f231f28818 Move QGuiApplication::setQuitOnLastWindowClosed before QApplication 2022-05-21 19:12:53 +02:00
Strawbs Bot
aebdc89f77 Update translations 2022-05-20 01:04:44 +02:00
Jonas Kvinge
4a3a379871 Increase icons to include 128x128 and set global application icon
Fixes #954
2022-05-19 22:02:35 +02:00
Jonas Kvinge
a7f27add2d Combine definitions 2022-05-17 23:40:53 +02:00
Strawbs Bot
cd1d4247cf Update translations 2022-05-16 01:01:29 +02:00
Strawbs Bot
6d618c4b78 Update translations 2022-05-14 01:11:35 +02:00
Jonas Kvinge
ad469531ff SPFParser: Use percent-encoding for image too 2022-05-13 23:36:38 +02:00
Jonas Kvinge
cf9b4b1246 XSPFParser: Use percent-encoding when loading and saving playlists
Fixes #821
2022-05-13 23:32:35 +02:00
Jonas Kvinge
18a2692dc1 PlaylistParser: Refactor code and exclude CUE from save playlist filters
Fixes #953
2022-05-13 23:14:56 +02:00
Jonas Kvinge
a2dad982f8 Move sqlrow to core 2022-05-13 18:15:04 +02:00
Jonas Kvinge
8f27b6a4c9 CI: Update Fedora 2022-05-10 01:06:04 +02:00
Jonas Kvinge
21c4022fca PlaylistView: Fix invalidating cached pixmap on scroll
Fixes #952
2022-05-09 23:46:33 +02:00
Jonas Kvinge
237933855a Remove unused PKGBUILD file 2022-05-06 18:31:32 +02:00
Jonas Kvinge
dff7068a03 Move debian configuration to separate CMakeLists.txt 2022-05-06 18:26:46 +02:00
Jonas Kvinge
8f28a85a6d RadioParadiseService: Change URLs to https 2022-05-06 18:07:20 +02:00
Jonas Kvinge
2414eb2598 GstEnginePipeline: Replace char with int8_t in HandoffCallback 2022-05-06 17:42:08 +02:00
Strawbs Bot
4851f6bffd Update translations 2022-05-06 01:01:57 +02:00
Jonas Kvinge
948be36d3c SmartPlaylistSearchTerm: Move value assigment
Mistake done in commit 3f3ae7c38f
2022-05-05 20:41:30 +02:00
Jonas Kvinge
edd088927d macdeployqt: List missing gstreamer plugins instead of failing
Fixes #936
2022-05-04 23:11:53 +02:00
Jonas Kvinge
4cfe8dd95e nsi: Fix pcre2 dll for debug 2022-05-03 20:08:40 +02:00
Jonas Kvinge
e1ce81c5bf Update pcre2 filename in nsi 2022-04-30 21:03:09 +02:00
Jonas Kvinge
0f40b5f022 VLCEngine: Fix track progress
Fixes #941
2022-04-29 00:09:29 +02:00
FireFragment
94c5ffa92e Allow setting blur amount of background image up to 100px 2022-04-27 20:53:29 +02:00
FireFragment
3c9bf56767 Improve CMake error message in case of missing libvlc
When running CMake with VLC installed, but without libvlc there pops out following error message:
 > You need to have eithoer GStreamer or VLC to compile!

This may be confusing for some users, because they might have VLC already installed, but not libvlc. This commit fixes it.
2022-04-26 17:39:07 +02:00
Jonas Kvinge
9024acb16e debian: Add qt6-qpa-plugins to depends
Fixes #937
2022-04-23 23:48:16 +02:00
Jonas Kvinge
7732402122 Add ffmpeg to MSVC 2022-04-23 18:06:38 +02:00
Jonas Kvinge
2059bce6a7 Add Qt 6 support to debian files 2022-04-23 02:15:22 +02:00
Jonas Kvinge
499c86a8b8 Add safe git directory 2022-04-20 01:23:02 +02:00
Strawbs Bot
ef084eb145 Update translations 2022-04-20 01:02:20 +02:00
Jonas Kvinge
3f3ae7c38f SmartPlaylistSearchTerm: Fix filetype search 2022-04-19 23:11:13 +02:00
Strawbs Bot
83d762287f Update translations 2022-04-18 01:01:58 +02:00
Strawbs Bot
5af0acf147 Update translations 2022-04-16 01:05:16 +02:00
Jonas Kvinge
907dfee6f7 Utilities: Use inconv with MSVC 2022-04-15 17:44:04 +02:00
Strawbs Bot
d587d24603 Update translations 2022-04-15 01:03:02 +02:00
Jonas Kvinge
c246b8f164 GstEngine: Show debug information in error dialog 2022-04-14 20:56:57 +02:00
Strawbs Bot
deecafa053 Update translations 2022-04-11 01:02:28 +02:00
Jonas Kvinge
f8810106a2 Turn on git revision 2022-04-10 17:34:26 +02:00
Jonas Kvinge
8e35fbe532 Release 1.0.4 2022-04-10 14:08:25 +02:00
Jonas Kvinge
b1fdccde6e ContextView: Specify alternative fonts for no song playing 2022-04-10 14:05:51 +02:00
Jonas Kvinge
6741f100a1 Update Changelog 2022-04-10 12:19:23 +02:00
Jonas Kvinge
e05e9ea1b2 timeconstants: Use constexpr 2022-04-08 17:35:44 +02:00
Jonas Kvinge
197341de5e Update debian/copyright-scan-patterns.yml 2022-04-08 17:35:31 +02:00
Jonas Kvinge
2933482be3 Update debian/copyright 2022-04-08 17:35:23 +02:00
Jonas Kvinge
c7ce23239f Disable gstwasapi2 in nsi 2022-04-07 23:18:08 +02:00
Jonas Kvinge
79115f7439 Update README and issue template 2022-04-07 01:22:21 +02:00
Jonas Kvinge
4457103672 Add pcre2 to nsi for MSVC 2022-04-06 23:23:20 +02:00
Jonas Kvinge
d204875f72 globalshortcut-x11: Fix minor code issues 2022-04-06 21:22:10 +02:00
Strawbs Bot
c690e73b1a Update translations 2022-04-05 01:02:10 +02:00
Jonas Kvinge
b5d39c5f21 Context: Remove use of custom font
Fixes #932
2022-04-04 20:26:38 +02:00
Strawbs Bot
7f8834cb04 Update translations 2022-04-04 01:02:50 +02:00
Jonas Kvinge
0dab7e293c GstEngine: Append "2" to wasapi2sink output description 2022-04-02 01:37:43 +02:00
Jonas Kvinge
8f016880af globalshortcut-win: Register 0-9 as num keys too 2022-04-02 00:43:41 +02:00
Jonas Kvinge
f471462a84 AnalyzerBase: Refactor code 2022-04-01 22:30:22 +02:00
Strawbs Bot
58eec8df1e Update translations 2022-03-30 01:02:21 +02:00
Jonas Kvinge
2655b8b43a TagReaderTagLib: Replace use of QByteArray::count() 2022-03-29 01:43:07 +02:00
Jonas Kvinge
ea86c043a4 AlsaPCMDeviceFinder: Fix use of deleted memory 2022-03-29 01:23:35 +02:00
Strawbs Bot
c1faa616bc Update translations 2022-03-29 01:04:21 +02:00
Strawbs Bot
a68bf5a30d Update translations 2022-03-28 01:02:14 +02:00
Jonas Kvinge
9568b8e0e5 Add hls to nsi 2022-03-28 00:34:20 +02:00
Jonas Kvinge
b34321ef87 GlobalShortcutsManager: Translate shortcuts
Fixes #928
2022-03-27 14:31:58 +02:00
Strawbs Bot
4971f1c5bf Update translations 2022-03-27 01:04:49 +01:00
Maxime Haselbauer
962b52bd5b Add save all playlists action 2022-03-26 22:38:21 +01:00
Jonas Kvinge
9449bfa414 Update protobuf in nsi 2022-03-26 21:02:56 +01:00
Strawbs Bot
5b8e9066c6 Update translations 2022-03-26 01:03:00 +01:00
Jonas Kvinge
8690be7fd2 Use separate sparkle feed for mingw and msvc 2022-03-25 21:38:37 +01:00
Jonas Kvinge
497267016b Turn on git revision 2022-03-25 01:22:31 +01:00
Jonas Kvinge
0468f850c2 Release 1.0.3 2022-03-24 21:23:36 +01:00
Jonas Kvinge
b9e7d4e30c Update Changelog 2022-03-24 21:21:24 +01:00
Jonas Kvinge
0e7734b555 Update README.md 2022-03-24 20:32:50 +01:00
Jonas Kvinge
e81dcce5b3 Update nsi for msvc dependencies 2022-03-23 19:13:40 +01:00
Strawbs Bot
38bd1f7e1c Update translations 2022-03-23 01:16:48 +01:00
Jonas Kvinge
36ad9704a2 Update libspeex for msvc in nsi 2022-03-22 21:24:54 +01:00
Jonas Kvinge
a6c05df362 Formatting 2022-03-22 21:19:59 +01:00
Jonas Kvinge
f6b70fda71 Formatting 2022-03-22 21:09:05 +01:00
Jonas Kvinge
8cb4e75f70 Update nsi for msvc dependencies 2022-03-22 17:32:49 +01:00
Jonas Kvinge
da1815ac2b Qobuz: Fix albums request limited to 50 albums
Fixes #922
2022-03-21 21:54:27 +01:00
Jonas Kvinge
f7357f2d10 Add libbrotlienc.dll to nsi 2022-03-21 21:30:33 +01:00
Jonas Kvinge
d9c92c5ddd CI: Use new MSVC dependencies 2022-03-21 18:37:31 +01:00
Jonas Kvinge
c82bdb6405 Add musepack, bs2b, faac and faad to nsi for msvc 2022-03-19 20:15:56 +01:00
Jonas Kvinge
eec8ee5830 Add qtsparkle for msvc in nsi 2022-03-17 14:46:12 +01:00
Strawbs Bot
e67eb3c0d8 Update translations 2022-03-17 01:02:02 +01:00
Jonas Kvinge
9c101759f6 CI: Update CI for MSVC dependencies 2022-03-17 00:06:18 +01:00
Jonas Kvinge
a55ee92590 Update nsi for MSVC library changes 2022-03-17 00:05:27 +01:00
Jonas Kvinge
5ccfc97dab Database: Fix schema update with Windows line-endings 2022-03-17 00:04:12 +01:00
Jonas Kvinge
d6dd88ec3d Add registry inetc plugin to nsi 2022-03-14 22:13:14 +01:00
Strawbs Bot
8557d83599 Update translations 2022-03-13 01:02:01 +01:00
Jonas Kvinge
94cf1f8698 macdeployqt: Remove optional plugins 2022-03-11 20:45:15 +01:00
Strawbs Bot
9ada35c3a3 Update translations 2022-03-11 01:03:01 +01:00
Jonas Kvinge
79b0c906fa CI: Fix path to gst-plugin-scanner for macOS 2022-03-10 22:14:51 +01:00
Jonas Kvinge
a0688f1dba CI: Fix path to gst-plugin-scanner for macOS 2022-03-10 21:09:12 +01:00
Jonas Kvinge
f91e8fecee CI: Reduce installed macports packages 2022-03-10 16:24:01 +01:00
Jonas Kvinge
1b363babe2 Use our own macOS dependencies 2022-03-10 15:51:07 +01:00
Jonas Kvinge
73843cb54d Switch back to libsoup 2 in nsi
libsoup 3.0 currently has issues with gstreamer
2022-03-08 21:53:10 +01:00
Jonas Kvinge
a2ccfc2116 Add libgioopenssl.dll to nsi 2022-03-07 22:32:50 +01:00
Jonas Kvinge
fe104e2bad Update gstreamer plugins in nsi 2022-03-07 19:28:38 +01:00
Jonas Kvinge
35e3e9f4ff RPM spec: Update release for OpenMandriva 2022-03-06 14:05:07 +01:00
Jonas Kvinge
b2a1cd9716 CI: Add openSUSE Leap 15.4 2022-03-05 21:26:51 +01:00
Jonas Kvinge
14f58eae4b CI: Add Fedora 36 2022-03-05 21:26:24 +01:00
Jonas Kvinge
5cec000618 Add fdk-aac to nsi 2022-03-05 12:15:48 +01:00
Jonas Kvinge
4805a5287d CI: Remove Ubuntu Hirsute 2022-03-05 03:27:09 +01:00
Jonas Kvinge
4789dc5b30 Add bs2b to nsi 2022-03-05 01:55:05 +01:00
Jonas Kvinge
5a35099043 Add support for bs2b
Improve headphone listening of stereo audio records
2022-03-05 01:30:49 +01:00
Strawbs Bot
4cd0128919 Update translations 2022-03-02 01:02:32 +01:00
Jonas Kvinge
61e9b80f67 Song: Remove playlists from accepted file extensions
Fixes #909
2022-03-01 21:26:08 +01:00
Strawbs Bot
dcd881ba6c Update translations 2022-02-23 01:02:20 +01:00
Strawbs Bot
d40a67ce68 Update translations 2022-02-22 01:02:35 +01:00
Jonas Kvinge
1c1e7ca62a nsi: Move libmpg123-0.dll to common files 2022-02-21 20:47:11 +01:00
Jonas Kvinge
d3831d511b nsi: Move libmpg123-0.dll to common files 2022-02-21 20:45:26 +01:00
Jonas Kvinge
0942e93144 Add mpg123 plugin to nsi 2022-02-21 20:33:10 +01:00
Jonas Kvinge
98d3eba8e8 AlbumCoverLoader: Use char for QString::remove() 2022-02-21 20:22:47 +01:00
Jonas Kvinge
ff3db03696 AlbumCoverLoader: Remove slash and backslash from cover filename
Fixes #903
2022-02-21 20:21:06 +01:00
Strawbs Bot
3608c31d22 Update translations 2022-02-21 01:03:09 +01:00
Jonas Kvinge
8d504d9cee Turn on git revision 2022-02-20 21:47:24 +01:00
243 changed files with 15265 additions and 13814 deletions

View File

@@ -7,7 +7,8 @@ assignees: ''
---
For technical issues, questions and feature suggestions/requests please use the forum on https://forum.strawberrymusicplayer.org/
For technical issues, questions and discussion please use the forum on https://forum.strawberrymusicplayer.org/
Any issues related to feature requests will be closed. See the README for more details.
Check the Changelog to see if the issue is already fixed:
https://github.com/strawberrymusicplayer/strawberry/blob/master/Changelog

File diff suppressed because it is too large Load Diff

1
.gitignore vendored
View File

@@ -105,7 +105,6 @@ Thumbs.db
# Stuff in dist
maketarball.sh
changelog
PKGBUILD
# Translations
translations.pot

View File

@@ -1214,28 +1214,42 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
// GIO modules
{
QString sourcePath = qgetenv("GIO_EXTRA_MODULES");
if (sourcePath.isEmpty()) {
if (QFileInfo::exists("/usr/local/lib/gio/modules/libgiognutls.so")) {
sourcePath = "/usr/local/lib/gio/modules/libgiognutls.so";
QString giomodule_path = qgetenv("GIO_EXTRA_MODULES");
if (giomodule_path.isEmpty()) {
if (QDir().exists("/usr/local/lib/gio/modules")) {
giomodule_path = "/usr/local/lib/gio/modules";
}
else if (QFileInfo::exists("/opt/local/lib/gio/modules/libgiognutls.so")) {
sourcePath = "/opt/local/lib/gio/modules/libgiognutls.so";
else if (QDir().exists("/opt/local/lib/gio/modules")) {
giomodule_path = "/opt/local/lib/gio/modules";
}
else {
qFatal("Missing GIO_EXTRA_MODULES");
}
}
else {
sourcePath = sourcePath + "/libgiognutls.so";
const QStringList giomodules = QStringList() << "libgiognutls.so" << "libgioopenssl.so";
bool have_giomodule = false;
for (const QString &giomodule : giomodules) {
const QString sourcePath = giomodule_path + "/" + giomodule;
QFileInfo fileinfo(sourcePath);
if (!fileinfo.exists()) {
LogError() << "Missing GIO module" << fileinfo.baseName();
continue;
}
have_giomodule = true;
const QString destinationPath = appBundleInfo.path + "/Contents/PlugIns/gio-modules/" + giomodule;
QDir dir;
if (dir.mkpath(QFileInfo(destinationPath).path()) && copyFilePrintStatus(sourcePath, destinationPath)) {
runStrip(destinationPath);
QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, appBundleInfo.path, deploymentInfo.rpathsUsed, useDebugLibs);
deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath);
}
}
const QString destinationPath = appBundleInfo.path + "/Contents/PlugIns/gio-modules/libgiognutls.so";
QDir dir;
if (dir.mkpath(QFileInfo(destinationPath).path()) && copyFilePrintStatus(sourcePath, destinationPath)) {
runStrip(destinationPath);
QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, appBundleInfo.path, deploymentInfo.rpathsUsed, useDebugLibs);
deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath);
if (!have_giomodule) {
qFatal("Missing GIO modules.");
}
}
// gst-plugin-scanner
@@ -1262,8 +1276,12 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
}
// GStreamer plugins.
QStringList gstreamer_plugins = QStringList() << "libgstapetag.dylib"
QStringList gstreamer_plugins = QStringList()
<< "libgstaiff.dylib"
<< "libgstapetag.dylib"
<< "libgstapp.dylib"
<< "libgstasf.dylib"
<< "libgstasfmux.dylib"
<< "libgstaudioconvert.dylib"
<< "libgstaudiofx.dylib"
<< "libgstaudiomixer.dylib"
@@ -1271,48 +1289,46 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
<< "libgstaudiorate.dylib"
<< "libgstaudioresample.dylib"
<< "libgstaudiotestsrc.dylib"
<< "libgstaudiovisualizers.dylib"
<< "libgstauparse.dylib"
<< "libgstautoconvert.dylib"
<< "libgstautodetect.dylib"
<< "libgstbs2b.dylib"
<< "libgstcdio.dylib"
<< "libgstcoreelements.dylib"
<< "libgstdash.dylib"
<< "libgstequalizer.dylib"
<< "libgstflac.dylib"
<< "libgstfaac.dylib"
<< "libgstfaad.dylib"
<< "libgstfdkaac.dylib"
<< "libgstgio.dylib"
<< "libgsticydemux.dylib"
<< "libgstid3demux.dylib"
<< "libgstlevel.dylib"
<< "libgstisomp4.dylib"
<< "libgstlame.dylib"
<< "libgstlibav.dylib"
<< "libgstmpg123.dylib"
<< "libgstmusepack.dylib"
<< "libgstogg.dylib"
<< "libgstopenmpt.dylib"
<< "libgstopus.dylib"
<< "libgstopusparse.dylib"
<< "libgstosxaudio.dylib"
<< "libgstplayback.dylib"
<< "libgstrawparse.dylib"
<< "libgstreplaygain.dylib"
<< "libgstsoup.dylib"
<< "libgstspectrum.dylib"
<< "libgsttypefindfunctions.dylib"
<< "libgstvolume.dylib"
<< "libgstxingmux.dylib"
<< "libgsttcp.dylib"
<< "libgstudp.dylib"
<< "libgstpbtypes.dylib"
<< "libgstplayback.dylib"
<< "libgstreplaygain.dylib"
<< "libgstrtp.dylib"
<< "libgstrtsp.dylib"
<< "libgstflac.dylib"
<< "libgstwavparse.dylib"
<< "libgstfaad.dylib"
<< "libgstogg.dylib"
<< "libgstopus.dylib"
<< "libgstasf.dylib"
<< "libgstsoup.dylib"
<< "libgstspectrum.dylib"
<< "libgstspeex.dylib"
<< "libgsttaglib.dylib"
<< "libgsttcp.dylib"
<< "libgsttypefindfunctions.dylib"
<< "libgstudp.dylib"
<< "libgstvolume.dylib"
<< "libgstvorbis.dylib"
<< "libgstisomp4.dylib"
<< "libgstlibav.dylib"
<< "libgstaiff.dylib"
<< "libgstlame.dylib";
// macports does not have these.
QStringList gstreamer_plugins_optional = QStringList() << "libgstopusparse.dylib"
<< "libgstfaac.dylib"
<< "libgstmusepack.dylib";
<< "libgstwavpack.dylib"
<< "libgstwavparse.dylib"
<< "libgstxingmux.dylib";
QString gstreamer_plugins_dir = qgetenv("GST_PLUGIN_PATH");
if (gstreamer_plugins_dir.isEmpty()) {
@@ -1327,13 +1343,16 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
}
}
QStringList missing_gst_plugins;
for (const QString &plugin : gstreamer_plugins) {
QFileInfo info(gstreamer_plugins_dir + "/" + plugin);
if (!info.exists()) {
info.setFile(gstreamer_plugins_dir + "/" + info.baseName() + QString(".so"));
if (!info.exists()) {
LogError() << "Missing gstreamer plugin" << info.baseName();
qFatal("Missing %s", info.baseName().toUtf8().constData());
missing_gst_plugins << info.baseName();
continue;
}
}
const QString &sourcePath = info.filePath();
@@ -1345,22 +1364,8 @@ void deployPlugins(const ApplicationBundleInfo &appBundleInfo, const QString &pl
}
}
for (const QString &plugin : gstreamer_plugins_optional) {
QFileInfo info(gstreamer_plugins_dir + "/" + plugin);
if (!info.exists()) {
info.setFile(gstreamer_plugins_dir + "/" + info.baseName() + QString(".so"));
if (!info.exists()) {
LogWarning() << "Skip missing gstreamer plugin" << info.baseName();
continue;
}
}
const QString &sourcePath = info.filePath();
const QString destinationPath = appBundleInfo.path + "/Contents/PlugIns/gstreamer/" + info.fileName();
if (QDir().mkpath(QFileInfo(destinationPath).path()) && copyFilePrintStatus(sourcePath, destinationPath)) {
runStrip(destinationPath);
QList<FrameworkInfo> frameworks = getQtFrameworks(destinationPath, appBundleInfo.path, deploymentInfo.rpathsUsed, useDebugLibs);
deployQtFrameworks(frameworks, appBundleInfo.path, QStringList() << destinationPath, useDebugLibs, deploymentInfo.useLoaderPath);
}
if (!missing_gst_plugins.isEmpty()) {
LogError() << "Missing gstreamer plugins" << missing_gst_plugins;
}
}

View File

@@ -58,8 +58,7 @@ else()
-Wformat=2
-Wdisabled-optimization
$<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>
$<$<COMPILE_LANGUAGE:CXX>:-Wno-old-style-cast>
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
$<$<COMPILE_LANGUAGE:CXX>:-Wold-style-cast>
)
endif()
@@ -427,9 +426,9 @@ endif()
option(INSTALL_TRANSLATIONS "Install translations" OFF)
optional_component(SUBSONIC ON "Subsonic support")
optional_component(TIDAL ON "Tidal support")
optional_component(QOBUZ ON "Qobuz support")
optional_component(SUBSONIC ON "Streaming: Subsonic")
optional_component(TIDAL ON "Streaming: Tidal")
optional_component(QOBUZ ON "Streaming: Qobuz")
optional_component(MOODBAR ON "Moodbar"
DEPENDS "fftw3" FFTW3_FOUND
@@ -490,12 +489,13 @@ endif()
# Set up definitions
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_STRICT_ITERATORS)
add_definitions(-DQT_USE_QSTRINGBUILDER)
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
add_definitions(-DQT_NO_CAST_TO_ASCII)
add_definitions(
-DBOOST_BIND_NO_PLACEHOLDERS
-DQT_STRICT_ITERATORS
-DQT_USE_QSTRINGBUILDER
-DQT_NO_URL_CAST_FROM_STRING
-DQT_NO_CAST_TO_ASCII
)
if(WIN32)
add_definitions(-DUNICODE)
@@ -518,6 +518,10 @@ if(GTest_FOUND AND GMOCK_LIBRARY AND QtTest_LIBRARIES)
add_subdirectory(tests)
endif()
if(LINUX AND LSB_RELEASE_EXEC AND DPKG_BUILDPACKAGE)
add_subdirectory(debian)
endif()
# Uninstall support
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
@@ -526,7 +530,7 @@ add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/c
# Show a summary of what we have enabled
summary_show()
if(NOT HAVE_GSTREAMER AND NOT HAVE_VLC)
message(FATAL_ERROR "You need to have either GStreamer or VLC to compile!")
message(FATAL_ERROR "You need to have either GStreamer or libvlc to compile!")
elseif(NOT HAVE_GSTREAMER)
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
endif()

View File

@@ -2,6 +2,57 @@ Strawberry Music Player
=======================
ChangeLog
Version 1.0.5 (2022.06.10)
BugFixes:
* Fixed smart playlist filetype search.
* Fixed Radio Paradise URLs to use HTTPS instead of HTTP.
* Fixed horizontal scrolling not affecting currently playing track (#952).
* Fixed keep running in the background when window is closed with Wayland (#964).
* Fixed percent-encoding of URLs when loading and saving XSPF playlists (#821).
* Fixed fancy tabbar context menu showing on right clicks outside of tabbar when a song is playing.
* Fixed possible duplicating songs in the database when moving songs to the collection using the organize feature.
* (Windows|MSVC) Fixed moodbar fftw3 crash with (older) CPU's that does not support AVX2 (#944).
* (Windows|MSVC) Fixed using libiconv for converting characters when organizing files like with MinGW.
Enhancements
* Show more details in error dialog on GStreamer errors (#958).
* Allow setting blur amount of playlist background image up to 100px (#939).
* Include 128x128 icon sizes (#954).
* Show right click copy context menu in context view on top text and lyrics (#965).
* Improve fading between album covers in context view.
* Added option for overwriting database playcounts in collection settings (#962).
* Added option for disabling bar on currently playing track (#972).
* (Debian) Added Qt 6 support to debian files and build with Qt 6 for Debian Bookworm, Ubuntu Jammy and newer.
* (Windows|MSVC) Added libav/ffmpeg plugin.
Version 1.0.4 (2022.04.10)
Bugfixes:
* Fixed use-after-free memory in ALSA PCM device finder.
* Translate global shortcuts.
* (Windows) Fixed registering 0-9 numpad keys in global shortcuts.
Enhancements
* Added save all playlists action.
* (Windows) Made updater support both MSVC and MinGW.
* (Windows) Added HLS support.
Other:
* Removed use of custom font in context.
Version 1.0.3 (2022.03.24)
Bugfixes:
* Remove slash and backslash from filenames when saving album covers using album directory cover filenames (#903).
* Remove playlist file-extensions from accepted audio file extensions (#909).
* Fixed Qobuz requests only receiving the first 50 albums (#922).
* (Windows|MinGW) Fixed streaming stopping at the end of each track. libsoup downgraded from 3.0 to 2.74.
* (Windows|MSVC) Fixed initial database schema failure caused by CRLF line-endings in schema files.
New features
* Added support for bs2b (Improved headphone listening of stereo audio records using Bauer stereophonic-to-binaural DSP) (#249).
Version 1.0.2 (2022.02.20)
Bugfixes:

View File

@@ -23,7 +23,8 @@ Resources:
### :bangbang: Opening an issue:
* Search for the issue to see if it is already solved, or if there is an open issue for it already. If there is an open issue already, you can comment on it if you have additional information that could be useful to us.
* For technical problems, questions and feature requests please use our forum on https://forum.strawberrymusicplayer.org/ that is better suited for discussion. It also better allows answers from the community instead of just the developers on GitHub.
* For technical problems, discussion, questions and feature suggestions use the forum (https://forum.strawberrymusicplayer.org/) instead. The forum is better suited for discussion.
* We do not take feature requests from users on GitHub. Any issues related to feature requests will be closed. This does not necessarily mean that we won't add new features, but we don't have time to take feature requests or answer questions about new features from users. It is still possible to suggest or discuss new features on the forum (https://forum.strawberrymusicplayer.org/).
### :moneybag: Sponsoring:
@@ -66,15 +67,14 @@ It has so far been tested to work on Linux, OpenBSD, FreeBSD, macOS and Windows.
To build Strawberry from source you need the following installed on your system with the additional development packages/headers:
* [CMake](https://cmake.org/)
* [GNU Make](https://www.gnu.org/software/make/)
* [GCC](https://gcc.gnu.org/) or [clang](https://clang.llvm.org/) compiler
* [GCC](https://gcc.gnu.org/), [Clang](https://clang.llvm.org/) or [MSVC](https://visualstudio.microsoft.com/vs/features/cplusplus/) compiler
* [Boost](https://www.boost.org/)
* [GLib](https://developer.gnome.org/glib/)
* [Protobuf](https://developers.google.com/protocol-buffers/)
* [Qt 5.9 or higher (or Qt 6) with components Core, Gui, Widgets, Concurrent, Network and Sql](https://www.qt.io/)
* [SQLite 3.9 or newer with FTS5](https://www.sqlite.org)
* [ALSA (Linux required)](https://www.alsa-project.org/)
* [D-Bus (Linux required)](https://www.freedesktop.org/wiki/Software/dbus/)
* [Protobuf](https://developers.google.com/protocol-buffers/)
* [ALSA (Required on Linux)](https://www.alsa-project.org/)
* [D-Bus (Required on Linux)](https://www.freedesktop.org/wiki/Software/dbus/)
* [GStreamer](https://gstreamer.freedesktop.org/) or [VLC](https://www.videolan.org)
* [GnuTLS](https://www.gnutls.org/)
* [TagLib 1.11.1 or higher](https://www.taglib.org/) or [TagParser](https://github.com/Martchus/tagparser)
@@ -88,8 +88,7 @@ Optional dependencies:
* MTP devices: [libmtp](http://libmtp.sourceforge.net/)
* iPod Classic devices: [libgpod](http://www.gtkpod.org/libgpod/)
Either GStreamer or VLC engine is required, but only GStreamer is fully implemented, and works best, it is therefore recommended to use GStreamer.
You should also install the gstreamer plugins base and good, and optionally bad, ugly and libav.
You should also install the gstreamer plugins base and good, and optionally bad, ugly and libav to support all audio formats.
### :wrench: Compiling from source
@@ -101,13 +100,13 @@ You should also install the gstreamer plugins base and good, and optionally bad,
cd strawberry
mkdir build && cd build
cmake ..
cmake .. -DBUILD_WITH_QT6=ON
make -j$(nproc)
sudo make install
To compile with Qt 6 use:
cmake .. -DBUILD_WITH_QT6=ON
Strawberry is backwards compatible with Qt 5, to compile with Qt 5 use:
cmake .. -DBUILD_WITH_QT5=ON
### :penguin: Packaging status

View File

@@ -2,18 +2,5 @@ find_program(LSB_RELEASE_EXEC lsb_release)
find_program(DPKG_BUILDPACKAGE dpkg-buildpackage)
if (LSB_RELEASE_EXEC AND DPKG_BUILDPACKAGE)
execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -cs"
OUTPUT_VARIABLE DEB_CODENAME
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if (DEB_CODENAME AND DEB_DATE)
add_custom_target(deb
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
COMMAND ${DPKG_BUILDPACKAGE} -b -d -uc -us
)
endif()
add_custom_target(deb WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} COMMAND ${DPKG_BUILDPACKAGE} -b -d -uc -us)
endif()

View File

@@ -21,10 +21,7 @@ if(MACDEPLOYQT_EXECUTABLE)
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/strawberry.app/Contents/{Frameworks,Resources}
COMMAND cp -v ${CMAKE_SOURCE_DIR}/dist/macos/Info.plist ${CMAKE_BINARY_DIR}/strawberry.app/Contents/
COMMAND cp -v ${CMAKE_SOURCE_DIR}/dist/macos/strawberry.icns ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Resources/
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -verbose=3
-executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
-executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/gio-modules/libgiognutls.so
#-executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/gst-plugin-scanner
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -verbose=3 -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
DEPENDS strawberry strawberry-tagreader copy_gstreamer_plugins macdeployqt
)

View File

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

View File

@@ -46,7 +46,6 @@
<file>pictures/rainbowdash.png</file>
<file>pictures/star-on.png</file>
<file>pictures/star-off.png</file>
<file>fonts/HumongousofEternitySt.ttf</file>
<file>mood/sample.mood</file>
<file>text/ghosts.txt</file>
</qresource>

Binary file not shown.

View File

@@ -24,6 +24,7 @@
<file>icons/128x128/document-open-folder.png</file>
<file>icons/128x128/document-open.png</file>
<file>icons/128x128/document-save.png</file>
<file>icons/128x128/document-save-all.png</file>
<file>icons/128x128/document-search.png</file>
<file>icons/128x128/download.png</file>
<file>icons/128x128/edit-clear-list.png</file>
@@ -120,6 +121,7 @@
<file>icons/64x64/document-open-folder.png</file>
<file>icons/64x64/document-open.png</file>
<file>icons/64x64/document-save.png</file>
<file>icons/64x64/document-save-all.png</file>
<file>icons/64x64/document-search.png</file>
<file>icons/64x64/download.png</file>
<file>icons/64x64/edit-clear-list.png</file>
@@ -218,6 +220,7 @@
<file>icons/48x48/document-open-remote.png</file>
<file>icons/48x48/document-open.png</file>
<file>icons/48x48/document-save.png</file>
<file>icons/48x48/document-save-all.png</file>
<file>icons/48x48/document-search.png</file>
<file>icons/48x48/download.png</file>
<file>icons/48x48/edit-clear-list.png</file>
@@ -319,6 +322,7 @@
<file>icons/32x32/document-open-remote.png</file>
<file>icons/32x32/document-open.png</file>
<file>icons/32x32/document-save.png</file>
<file>icons/32x32/document-save-all.png</file>
<file>icons/32x32/document-search.png</file>
<file>icons/32x32/download.png</file>
<file>icons/32x32/edit-clear-list.png</file>
@@ -420,6 +424,7 @@
<file>icons/22x22/document-open-remote.png</file>
<file>icons/22x22/document-open.png</file>
<file>icons/22x22/document-save.png</file>
<file>icons/22x22/document-save-all.png</file>
<file>icons/22x22/document-search.png</file>
<file>icons/22x22/download.png</file>
<file>icons/22x22/edit-clear-list.png</file>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

@@ -31,6 +31,10 @@
background-color: %palette-base;
}
#context-scrollarea {
background-color: %palette-base;
}
QToolButton {
border: 2px solid transparent;
border-radius: 3px;

22
debian/CMakeLists.txt vendored Normal file
View File

@@ -0,0 +1,22 @@
if(LSB_RELEASE_EXEC AND DPKG_BUILDPACKAGE)
execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -cs" OUTPUT_VARIABLE DEB_CODENAME OUTPUT_STRIP_TRAILING_WHITESPACE)
if(DEB_CODENAME AND DEB_DATE)
if(BUILD_WITH_QT5)
set(DEBIAN_BUILD_DEPENDS_QT_PACKAGES qtbase5-dev,qtbase5-dev-tools,qttools5-dev,qttools5-dev-tools,libqt5x11extras5-dev)
set(DEBIAN_DEPENDS_QT_PACKAGES libqt5sql5-sqlite)
endif()
if(BUILD_WITH_QT6)
set(DEBIAN_BUILD_DEPENDS_QT_PACKAGES qt6-base-dev,qt6-base-dev-tools,qt6-tools-dev,qt6-tools-dev-tools,qt6-l10n-tools)
set(DEBIAN_DEPENDS_QT_PACKAGES libqt6sql6-sqlite,qt6-qpa-plugins)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/control.in ${CMAKE_CURRENT_SOURCE_DIR}/control @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/changelog.in ${CMAKE_CURRENT_SOURCE_DIR}/changelog)
endif()
endif()

View File

@@ -6,6 +6,7 @@ Build-Depends: debhelper (>= 11),
make,
cmake,
gcc,
g++,
protobuf-compiler,
libglib2.0-dev,
libdbus-1-dev,
@@ -16,11 +17,7 @@ Build-Depends: debhelper (>= 11),
libasound2-dev,
libpulse-dev,
libtag1-dev,
qtbase5-dev,
qtbase5-private-dev,
qtbase5-dev-tools,
qttools5-dev,
libqt5x11extras5-dev,
@DEBIAN_BUILD_DEPENDS_QT_PACKAGES@,
libgstreamer1.0-dev,
libgstreamer-plugins-base1.0-dev,
libcdio-dev,
@@ -28,20 +25,19 @@ Build-Depends: debhelper (>= 11),
libmtp-dev,
libchromaprint-dev,
libfftw3-dev
Standards-Version: 4.2.1
Standards-Version: 4.6.1
Package: strawberry
Architecture: any
Depends: ${shlibs:Depends},
${misc:Depends},
libsqlite3-0,
libqt5sql5-sqlite,
@DEBIAN_DEPENDS_QT_PACKAGES@,
gstreamer1.0-plugins-base,
gstreamer1.0-plugins-good,
gstreamer1.0-alsa,
gstreamer1.0-pulseaudio
Homepage: http://www.strawberrymusicplayer.org/
Description: Audio player and music collection organizer
Description: music player and music collection organizer
Strawberry is a music player aimed at music collectors and audiophiles.
.
Features:
@@ -49,14 +45,13 @@ Description: Audio player and music collection organizer
- Supports WAV, FLAC, WavPack, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF
- Audio CD playback
- Native desktop notifications
- Playlist management
- Playlists in multiple formats
- Playlist management and playlists in multiple formats
- Smart and dynamic playlists
- Advanced audio output and device configuration for bit-perfect playback on Linux
- Edit tags on audio files
- Automatically retrieve tags from MusicBrainz
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify
- Song lyrics from AudD, Genius, Musixmatch, ChartLyrics, lyrics.ovh and lololyrics.com
- Support for multiple backends
- Audio analyzer
- Audio equalizer
- Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic

183
debian/copyright vendored
View File

@@ -1,10 +1,11 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: strawberry
Upstream-Contact: Jonas Kvinge <jonas@jkvinge.net>
Source: https://www.strawberrymusicplayer.org/
Source: https://github.com/strawberrymusicplayer/strawberry
Files: *
Copyright: 2010-2015, David Sansome <me@davidsansome.com>
2012-2014, 2017-2022 Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/core/timeconstants.h
@@ -13,14 +14,13 @@ Files: src/core/timeconstants.h
ext/libstrawberry-common/core/messagehandler.cpp
ext/libstrawberry-common/core/messagehandler.h
Copyright: 2011, 2012, David Sansome <me@davidsansome.com>
2018-2022, Jonas Kvinge <jonas@jkvinge.net>
License: Apache-2.0
Files: src/core/main.h
src/core/iconloader.cpp
src/core/iconloader.h
src/core/iconmapper.h
src/config.h.in
src/version.h.in
src/context/contextview.cpp
src/context/contextview.h
src/context/contextalbum.cpp
@@ -29,6 +29,8 @@ Files: src/core/main.h
src/engine/enginetype.h
src/engine/alsadevicefinder.cpp
src/engine/alsadevicefinder.h
src/engine/alsapcmdevicefinder.cpp
src/engine/alsapcmdevicefinder.h
src/engine/mmdevicefinder.cpp
src/engine/mmdevicefinder.h
src/engine/devicefinder.cpp
@@ -69,11 +71,17 @@ Files: src/core/main.h
src/covermanager/spotifycoverprovider.h
src/covermanager/musixmatchcoverprovider.cpp
src/covermanager/musixmatchcoverprovider.h
src/globalshortcuts/globalshortcutsbackend-system.cpp
src/globalshortcuts/globalshortcutsbackend-system.h
src/globalshortcuts/globalshortcutsbackend-kde.cpp
src/globalshortcuts/globalshortcutsbackend-kde.h
src/globalshortcuts/globalshortcutsbackend-mate.cpp
src/globalshortcuts/globalshortcutsbackend-mate.h
src/globalshortcuts/globalshortcutsbackend-x11.cpp
src/globalshortcuts/globalshortcutsbackend-x11.h
src/globalshortcuts/globalshortcutsbackend-win.cpp
src/globalshortcuts/globalshortcutsbackend-win.h
src/globalshortcuts/globalshortcut.cpp
src/globalshortcuts/globalshortcut.h
src/globalshortcuts/globalshortcut-X11.cpp
src/globalshortcuts/globalshortcut-x11.cpp
src/globalshortcuts/globalshortcut-win.cpp
src/globalshortcuts/keymapper_x11.h
src/globalshortcuts/keymapper_win.h
@@ -81,132 +89,21 @@ Files: src/core/main.h
src/scrobbler/*
src/subsonic/*
src/tidal/*
src/qobuz/*
src/radios/*
src/transcoder/transcoderoptionswavpack.cpp
src/transcoder/transcoderoptionswavpack.h
Copyright: 2012-2014, 2017-2020, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/core/main.cpp
src/core/mainwindow.cpp
src/core/mainwindow.h
src/core/player.cpp
src/core/player.h
src/core/song.cpp
src/core/song.h
src/core/songloader.cpp
src/core/songloader.h
src/core/urlhandler.cpp
src/core/urlhandler.h
src/core/utilities.cpp
src/core/utilities.h
src/core/networkaccessmanager.cpp
src/core/networkaccessmanager.h
src/core/threadsafenetworkdiskcache.cpp
src/core/threadsafenetworkdiskcache.h
src/core/filesystemmusicstorage.cpp
src/core/filesystemmusicstorage.h
src/core/stylesheetloader.cpp
src/core/stylesheetloader.h
src/engine/gstenginepipeline.cpp
src/engine/gstenginepipeline.h
src/engine/vlcengine.cpp
src/engine/vlcengine.h
src/collection/collectionwatcher.cpp
src/collection/collectionwatcher.h
src/collection/collectionbackend.cpp
src/collection/collectionbackend.h
src/collection/collectionmodel.cpp
src/collection/collectionmodel.h
src/context/contextalbumsmodel.cpp
src/context/contextalbumsview.cpp
src/context/contextalbumsmodel.h
src/context/contextalbumsview.h
src/widgets/playingwidget.cpp
src/widgets/playingwidget.h
src/osd/osdbase.cpp
src/osd/osdbase.h
src/osd/osdpretty.cpp
src/osd/osdpretty.h
src/osd/osddbus.cpp
src/osd/osddbus.h
src/osd/osdmac.cpp
src/osd/osdmac.h
src/dialogs/about.cpp
src/dialogs/about.h
src/playlist/playlist.cpp
src/playlist/playlist.h
src/playlist/playlistitem.cpp
src/playlist/playlistitem.h
src/playlist/playlistdelegates.cpp
src/playlist/playlistdelegates.h
src/playlist/playlistbackend.cpp
src/playlist/playlistbackend.h
src/playlist/playlistview.cpp
src/playlist/playlistview.h
src/playlist/songplaylistitem.cpp
src/playlist/songplaylistitem.h
src/internet/internetplaylistitem.cpp
src/internet/internetsearch.cpp
src/internet/internetsearch.h
src/internet/internetsearchview.cpp
src/internet/internetsearchview.h
src/internet/internetservices.cpp
src/internet/internetservices.h
src/internet/internetsongsview.cpp
src/internet/internetsongsview.h
src/internet/internetcollectionview.cpp
src/internet/internetcollectionview.h
ext/libstrawberry-tagreader/tagreader.cpp
ext/libstrawberry-tagreader/tagreader.h
src/device/devicemanager.cpp
src/device/devicemanager.h
src/device/deviceinfo.cpp
src/device/deviceinfo.h
src/device/deviceproperties.cpp
src/device/deviceproperties.h
src/device/deviceview.cpp
src/device/deviceview.h
src/device/connecteddevice.cpp
src/device/connecteddevice.h
src/device/mtpconnection.cpp
src/device/mtpconnection.h
src/device/mtpdevice.cpp
src/device/mtpdevice.h
src/globalshortcuts/globalshortcutsmanager.cpp
src/globalshortcuts/globalshortcutsmanager.h
src/settings/shortcutssettingspage.cpp
src/settings/shortcutssettingspage.h
src/settings/appearancesettingspage.cpp
src/settings/appearancesettingspage.h
src/organize/organize.cpp
src/organize/organize.h
src/organize/organizedialog.cpp
src/organize/organizedialog.h
src/organize/organizeerrordialog.cpp
src/organize/organizeerrordialog.h
src/transcoder/transcoder.cpp
src/transcoder/transcoder.h
src/musicbrainz/musicbrainzclient.cpp
src/musicbrainz/musicbrainzclient.h
src/covermanager/albumcoverloader.cpp
src/covermanager/albumcoverloader.h
src/covermanager/currentalbumcoverloader.cpp
src/covermanager/currentalbumcoverloader.h
src/covermanager/albumcoverchoicecontroller.cpp
src/covermanager/albumcoverchoicecontroller.h
src/covermanager/albumcoverfetchersearch.cpp
src/covermanager/albumcoverfetchersearch.h
src/covermanager/coverproviders.cpp
src/covermanager/coverproviders.h
src/covermanager/coverprovider.cpp
src/covermanager/coverprovider.h
Copyright: 2010, 2012-2014 David Sansome <me@davidsansome.com>
2012-2014, 2017-2020 Jonas Kvinge <jonas@jkvinge.net>
ext/libstrawberry-tagreader/tagreadertagparser.cpp
ext/libstrawberry-tagreader/tagreadertagparser.h
ext/macdeploycheck/*
widgets/resizabletextedit.cpp
widgets/resizabletextedit.h
Copyright: 2012-2014, 2017-2022, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/engine/enginebase.cpp
src/engine/enginebase.h
Copyright: 2017, 2018, Jonas Kvinge <jonas@jkvinge.net>
Copyright: 2017-2021, Jonas Kvinge <jonas@jkvinge.net>
2010, David Sansome <me@davidsansome.com>
2004, 2005, Max Howell, <max.howell@methylblue.com>
2003, Mark Kretschmann <markey@web.de>
@@ -214,7 +111,7 @@ License: GPL-3+
Files: src/engine/gstengine.cpp
src/engine/gstengine.h
Copyright: 2017, 2018, Jonas Kvinge <jonas@jkvinge.net>
Copyright: 2017-2021, Jonas Kvinge <jonas@jkvinge.net>
2006, Paul Cifarelli <paul@cifarelli.net>
2005, Jakub Stachowski <qbast@go2.pl>
2003-2005, Mark Kretschmann <markey@web.de>
@@ -230,7 +127,7 @@ Files: src/core/application.cpp
src/core/application.h
Copyright: 2012, David Sansome <me@davidsansome.com>
2012, 2014, John Maguire <john.maguire@gmail.com>
2018, Jonas Kvinge <jonas@jkvinge.net>
2018-2021, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/core/appearance.cpp
@@ -244,13 +141,7 @@ Copyright: 2012, Martin Björklund <mbj4668@gmail.com>
2016, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: ext/libstrawberry-common/core/arraysize.h
ext/libstrawberry-common/core/scoped_nsautorelease_pool.h
ext/libstrawberry-common/core/scoped_nsautorelease_pool.mm
Copyright: 2010, 2011, 2014, The Chromium Authors.
License: BSD-style
Files: ext/libstrawberry-common/core/lazy.h
Files: src/core/lazy.h
Copyright: 2016, John Maguire <john.maguire@gmail.com>
License: GPL-3+
@@ -298,12 +189,17 @@ Copyright: 2011, Tyler Rhodes <tyler.s.rhodes@gmail.com>
2015, Arun Narayanankutty <n.arun.lifescience@gmail.com>
License: GPL-2+
Files: src/collection/savedgroupingmanager.h
Files: src/collection/savedgroupingmanager.*
Copyright: 2015, Nick Lanham <nick@afternight.org>
2019-2021 Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/core/scoped_cftyperef.h
Files:
src/core/arraysize.h
src/core/scoped_cftyperef.h
src/core/scoped_nsobject.h
src/core/scoped_nsautorelease_pool.h
src/core/scoped_nsautorelease_pool.mm
Copyright: 2010, 2011, 2014, The Chromium Authors.
License: BSD-style
@@ -322,7 +218,7 @@ Files: src/internet/localredirectserver.cpp
src/internet/localredirectserver.h
Copyright: 2012, 2014, John Maguire <john.maguire@gmail.com>
2014, Krzysztof Sobiecki <sobkas@gmail.com>
2018-2019, Jonas Kvinge <jonas@jkvinge.net>
2018-2021, Jonas Kvinge <jonas@jkvinge.net>
License: GPL-3+
Files: src/transcoder/transcoderoptionsopus.cpp
@@ -337,12 +233,16 @@ Files: src/widgets/clickablelabel.cpp
Copyright: 2010, 2011, Andrea Decorte <adecorte@gmail.com>
License: GPL-3+
Files: src/widgets/sliderwidget.cpp
src/widgets/sliderwidget.h
Files: src/widgets/volumeslider.cpp
src/widgets/volumeslider.h
Copyright: 2005, Gábor Lehel
2003, Mark Kretschmann <markey@web.de>
License: GPL-2+
Files: src/scrobbler/subsonicscrobbler.*
Copyright: 2018-2021 Jonas Kvinge <jonas@jkvinge.net>
2020 Pascal Below <spezifisch@below.fr>
Files: src/core/stylehelper.cpp
src/core/stylehelper.h
Copyright: 2016 The Qt Company Ltd.
@@ -358,6 +258,7 @@ License: GPL-2+
Files: src/widgets/qsearchfield_nonmac.cpp
src/widgets/qsearchfield_mac.mm
src/widgets/qsearchfield.h
src/widgets/qocoa_mac.h
Copyright: 2011, Mike McQuaid <mike@mikemcquaid.com>
License: Expat
@@ -367,7 +268,7 @@ Copyright: 2010, Spotify AB
License: BSD-3-clause
Files: 3rdparty/singleapplication/*
Copyright: 2015-2018, Itay Grudev
Copyright: 2015-2022, Itay Grudev
License: MIT

View File

@@ -4,14 +4,14 @@ ignore:
- Changelog
- COPYING
- CMakeLists.txt
- Dockerfile
- cmake_uninstall.cmake.in
- .clang-format
- .gitignore
- .travis.yml
- .github
- /debian/
- /cmake/
- /data/
- /dist/
- /snap/
suffixes:
- jpg

1
debian/rules vendored
View File

@@ -5,7 +5,6 @@
override_dh_auto_clean:
rm -f dist/macos/Info.plist
rm -f dist/unix/PKGBUILD
rm -f dist/unix/strawberry.spec
rm -f dist/scripts/maketarball.sh
rm -f dist/windows/strawberry.nsi

4
dist/CMakeLists.txt vendored
View File

@@ -2,10 +2,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CUR
if(RPM_DISTRO AND RPM_DATE)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unix/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/unix/strawberry.spec @ONLY)
endif(RPM_DISTRO AND RPM_DATE)
if(DEB_CODENAME AND DEB_DATE)
configure_file(${CMAKE_SOURCE_DIR}/debian/changelog.in ${CMAKE_SOURCE_DIR}/debian/changelog)
endif(DEB_CODENAME AND DEB_DATE)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD @ONLY)
if(APPLE)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)

View File

@@ -39,8 +39,12 @@ fi
cp -v -f "${GST_PLUGIN_SCANNER}" "${bundledir}/Contents/PlugIns/" || exit 1
gst_plugins="
libgstaes.dylib
libgstaiff.dylib
libgstapetag.dylib
libgstapp.dylib
libgstasf.dylib
libgstasfmux.dylib
libgstaudioconvert.dylib
libgstaudiofx.dylib
libgstaudiomixer.dylib
@@ -48,46 +52,46 @@ libgstaudioparsers.dylib
libgstaudiorate.dylib
libgstaudioresample.dylib
libgstaudiotestsrc.dylib
libgstaudiovisualizers.dylib
libgstauparse.dylib
libgstautoconvert.dylib
libgstautodetect.dylib
libgstbs2b.dylib
libgstcdio.dylib
libgstcoreelements.dylib
libgstdash.dylib
libgstequalizer.dylib
libgstflac.dylib
libgstfaac.dylib
libgstfaad.dylib
libgstfdkaac.dylib
libgstgio.dylib
libgsticydemux.dylib
libgstid3demux.dylib
libgstlevel.dylib
libgstisomp4.dylib
libgstlame.dylib
libgstlibav.dylib
libgstmpg123.dylib
libgstmusepack.dylib
libgstogg.dylib
libgstopenmpt.dylib
libgstopus.dylib
libgstopusparse.dylib
libgstosxaudio.dylib
libgstplayback.dylib
libgstrawparse.dylib
libgstreplaygain.dylib
libgstsoup.dylib
libgstspectrum.dylib
libgsttypefindfunctions.dylib
libgstvolume.dylib
libgstxingmux.dylib
libgsttcp.dylib
libgstudp.dylib
libgstpbtypes.dylib
libgstplayback.dylib
libgstreplaygain.dylib
libgstrtp.dylib
libgstrtsp.dylib
libgstflac.dylib
libgstwavparse.dylib
libgstfaad.dylib
libgstogg.dylib
libgstopus.dylib
libgstasf.dylib
libgstsoup.dylib
libgstspectrum.dylib
libgstspeex.dylib
libgsttaglib.dylib
libgsttcp.dylib
libgsttypefindfunctions.dylib
libgstudp.dylib
libgstvolume.dylib
libgstvorbis.dylib
libgstisomp4.dylib
libgstlibav.dylib
libgstaiff.dylib
libgstlame.dylib
libgstopusparse.dylib
libgstfaac.dylib
libgstmusepack.dylib
libgstwavpack.dylib
libgstwavparse.dylib
libgstxingmux.dylib;
"
gst_plugins=$(echo "$gst_plugins" | tr '\n' ' ' | sed -e 's/^ //g' | sed -e 's/ / /g')

View File

@@ -60,7 +60,6 @@ ${TAR} -cJf $name-$version.tar.xz \
--exclude="$root/.zanata-cache" \
--exclude="$root/debian/changelog" \
--exclude="$root/dist/scripts/maketarball.sh" \
--exclude="$root/dist/unix/PKGBUILD" \
--exclude="$root/dist/macos/Info.plist" \
--exclude="$root/dist/windows/windres.rc" \
--exclude="$root/src/translations/translations.pot" \

56
dist/unix/PKGBUILD.in vendored
View File

@@ -1,56 +0,0 @@
# Maintainer: Jonas Kvinge <jonas@jkvinge.net>
pkgname=strawberry
pkgver=@STRAWBERRY_VERSION_PAC_V@
pkgrel=@STRAWBERRY_VERSION_PAC_R@
pkgdesc="A music player aimed at audio enthusiasts and music collectors"
arch=(x86_64)
url="https://www.strawberrymusicplayer.org/"
license=(GPL3)
makedepends=(git cmake make gcc boost gettext qt5-tools)
depends=(
desktop-file-utils
hicolor-icon-theme
gnutls
udisks2
protobuf
qt5-base
qt5-x11extras
sqlite3
alsa-lib
libpulse
dbus
taglib
gstreamer
gst-plugins-base
gst-plugins-good
vlc
chromaprint
libgpod
libcdio
libmtp
fftw
)
optdepends=(
gst-plugins-bad
gst-plugins-ugly
gst-libav
)
provides=(strawberry)
conflicts=(strawberry)
source=("strawberry-@STRAWBERRY_VERSION_PACKAGE@.tar.xz")
sha256sums=('SKIP')
prepare() {
mkdir -p build
}
build() {
cd build
cmake ../${pkgname}-@STRAWBERRY_VERSION_PACKAGE@ -DCMAKE_INSTALL_PREFIX=/usr
make -j$(nproc)
}
package() {
cd build
make DESTDIR="${pkgdir}" install
}

View File

@@ -1,6 +1,6 @@
Name: strawberry
Version: @STRAWBERRY_VERSION_RPM_V@
%if 0%{?fedora} || 0%{?rhel_version} || 0%{?centos}
%if 0%{?fedora} || 0%{?rhel_version} || 0%{?centos} || "%{?_vendor}" == "openmandriva"
Release: @STRAWBERRY_VERSION_RPM_R@%{?dist}
%else
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@

186
dist/windows/Registry.nsh vendored Normal file
View File

@@ -0,0 +1,186 @@
!define registry::Open `!insertmacro registry::Open`
!macro registry::Open _PATH _OPTIONS _HANDLE
registry::_Open /NOUNLOAD `${_PATH}` `${_OPTIONS}`
Pop ${_HANDLE}
!macroend
!define registry::Find `!insertmacro registry::Find`
!macro registry::Find _HANDLE _PATH _VALUEORKEY _STRING _TYPE
registry::_Find /NOUNLOAD `${_HANDLE}`
Pop ${_PATH}
Pop ${_VALUEORKEY}
Pop ${_STRING}
Pop ${_TYPE}
!macroend
!define registry::Close `!insertmacro registry::Close`
!macro registry::Close _HANDLE
registry::_Close /NOUNLOAD `${_HANDLE}`
!macroend
!define registry::KeyExists `!insertmacro registry::KeyExists`
!macro registry::KeyExists _PATH _ERR
registry::_KeyExists /NOUNLOAD `${_PATH}`
Pop ${_ERR}
!macroend
!define registry::Read `!insertmacro registry::Read`
!macro registry::Read _PATH _VALUE _STRING _TYPE
registry::_Read /NOUNLOAD `${_PATH}` `${_VALUE}`
Pop ${_STRING}
Pop ${_TYPE}
!macroend
!define registry::Write `!insertmacro registry::Write`
!macro registry::Write _PATH _VALUE _STRING _TYPE _ERR
registry::_Write /NOUNLOAD `${_PATH}` `${_VALUE}` `${_STRING}` `${_TYPE}`
Pop ${_ERR}
!macroend
!define registry::ReadExtra `!insertmacro registry::ReadExtra`
!macro registry::ReadExtra _PATH _VALUE _NUMBER _STRING _TYPE
registry::_ReadExtra /NOUNLOAD `${_PATH}` `${_VALUE}` `${_NUMBER}`
Pop ${_STRING}
Pop ${_TYPE}
!macroend
!define registry::WriteExtra `!insertmacro registry::WriteExtra`
!macro registry::WriteExtra _PATH _VALUE _STRING _ERR
registry::_WriteExtra /NOUNLOAD `${_PATH}` `${_VALUE}` `${_STRING}`
Pop ${_ERR}
!macroend
!define registry::CreateKey `!insertmacro registry::CreateKey`
!macro registry::CreateKey _PATH _ERR
registry::_CreateKey /NOUNLOAD `${_PATH}`
Pop ${_ERR}
!macroend
!define registry::DeleteValue `!insertmacro registry::DeleteValue`
!macro registry::DeleteValue _PATH _VALUE _ERR
registry::_DeleteValue /NOUNLOAD `${_PATH}` `${_VALUE}`
Pop ${_ERR}
!macroend
!define registry::DeleteKey `!insertmacro registry::DeleteKey`
!macro registry::DeleteKey _PATH _ERR
registry::_DeleteKey /NOUNLOAD `${_PATH}`
Pop ${_ERR}
!macroend
!define registry::DeleteKeyEmpty `!insertmacro registry::DeleteKeyEmpty`
!macro registry::DeleteKeyEmpty _PATH _ERR
registry::_DeleteKeyEmpty /NOUNLOAD `${_PATH}`
Pop ${_ERR}
!macroend
!define registry::CopyValue `!insertmacro registry::CopyValue`
!macro registry::CopyValue _PATH_SOURCE _VALUE_SOURCE _PATH_TARGET _VALUE_TARGET _ERR
registry::_CopyValue /NOUNLOAD `${_PATH_SOURCE}` `${_VALUE_SOURCE}` `${_PATH_TARGET}` `${_VALUE_TARGET}`
Pop ${_ERR}
!macroend
!define registry::MoveValue `!insertmacro registry::MoveValue`
!macro registry::MoveValue _PATH_SOURCE _VALUE_SOURCE _PATH_TARGET _VALUE_TARGET _ERR
registry::_MoveValue /NOUNLOAD `${_PATH_SOURCE}` `${_VALUE_SOURCE}` `${_PATH_TARGET}` `${_VALUE_TARGET}`
Pop ${_ERR}
!macroend
!define registry::CopyKey `!insertmacro registry::CopyKey`
!macro registry::CopyKey _PATH_SOURCE _PATH_TARGET _ERR
registry::_CopyKey /NOUNLOAD `${_PATH_SOURCE}` `${_PATH_TARGET}`
Pop ${_ERR}
!macroend
!define registry::MoveKey `!insertmacro registry::MoveKey`
!macro registry::MoveKey _PATH_SOURCE _PATH_TARGET _ERR
registry::_MoveKey /NOUNLOAD `${_PATH_SOURCE}` `${_PATH_TARGET}`
Pop ${_ERR}
!macroend
!define registry::SaveKey `!insertmacro registry::SaveKey`
!macro registry::SaveKey _PATH _FILE _OPTIONS _ERR
registry::_SaveKey /NOUNLOAD `${_PATH}` `${_FILE}` `${_OPTIONS}`
Pop ${_ERR}
!macroend
!define registry::RestoreKey `!insertmacro registry::RestoreKey`
!macro registry::RestoreKey _FILE _ERR
registry::_RestoreKey /NOUNLOAD `${_FILE}`
Pop ${_ERR}
!macroend
!define registry::StrToHex `!insertmacro registry::StrToHexA`
!define registry::StrToHexA `!insertmacro registry::StrToHexA`
!macro registry::StrToHexA _STRING _HEX_STRING
registry::_StrToHexA /NOUNLOAD `${_STRING}`
Pop ${_HEX_STRING}
!macroend
!define registry::StrToHexW `!insertmacro registry::StrToHexW`
!macro registry::StrToHexW _STRING _HEX_STRING
registry::_StrToHexW /NOUNLOAD `${_STRING}`
Pop ${_HEX_STRING}
!macroend
!define registry::HexToStr `!insertmacro registry::HexToStrA`
!define registry::HexToStrA `!insertmacro registry::HexToStrA`
!macro registry::HexToStrA _HEX_STRING _STRING
registry::_HexToStrA /NOUNLOAD `${_HEX_STRING}`
Pop ${_STRING}
!macroend
!define registry::HexToStrW `!insertmacro registry::HexToStrW`
!macro registry::HexToStrW _HEX_STRING _STRING
registry::_HexToStrW /NOUNLOAD `${_HEX_STRING}`
Pop ${_STRING}
!macroend
!define registry::Unload `!insertmacro registry::Unload`
!macro registry::Unload
registry::_Unload
!macroend

View File

@@ -38,6 +38,10 @@
!define compiler "msvc"
!endif
!if "@CMAKE_BUILD_TYPE@" == "Release"
!define release
!endif
!if "@CMAKE_BUILD_TYPE@" == "Debug"
!define debug
!undef build_type
@@ -96,6 +100,7 @@ SetCompressor /SOLID lzma
!include "FileAssociation.nsh"
!include "Capabilities.nsh"
!include LogicLib.nsh
!include Registry.nsh
!include x64.nsh
!define MUI_ICON "strawberry.ico"
@@ -105,11 +110,15 @@ SetCompressor /SOLID lzma
!ifdef mingw
ReserveFile "${NSISDIR}/Plugins/x86-unicode/LockedList.dll"
ReserveFile "${NSISDIR}/Plugins/LockedList64.dll"
ReserveFile "${NSISDIR}/Plugins/registry.dll"
ReserveFile "${NSISDIR}/Plugins/x86-unicode/INetC.dll"
!endif
!ifdef msvc
ReserveFile "${NSISDIR}\Plugins\x86-unicode\LockedList.dll"
ReserveFile "${NSISDIR}\Plugins\LockedList64.dll"
ReserveFile "${NSISDIR}\Plugins\registry.dll"
ReserveFile "${NSISDIR}\Plugins\x86-unicode\INetC.dll"
!endif
!define LockedListPATH $InstallDir
@@ -192,9 +201,7 @@ Section "Strawberry" Strawberry
File "strawberry.exe"
File "strawberry-tagreader.exe"
File "strawberry.ico"
!ifdef mingw
File "sqlite3.exe"
!endif
File "gst-launch-1.0.exe"
File "gst-discoverer-1.0.exe"
@@ -219,14 +226,18 @@ Section "Strawberry" Strawberry
File "avutil-57.dll"
File "libbrotlicommon.dll"
File "libbrotlidec.dll"
File "libbrotlienc.dll"
File "libbs2b-0.dll"
File "libbz2.dll"
File "libcdio-19.dll"
File "libchromaprint.dll"
File "libdl.dll"
File "libfdk-aac-2.dll"
File "libffi-8.dll"
File "libFLAC-8.dll"
File "libfreetype-6.dll"
File "libfaac-0.dll"
File "libfaad-2.dll"
File "libffi-8.dll"
File "libfreetype-6.dll"
File "libgio-2.0-0.dll"
File "libglib-2.0-0.dll"
File "libgmodule-2.0-0.dll"
@@ -252,30 +263,39 @@ Section "Strawberry" Strawberry
File "libgstvideo-1.0-0.dll"
File "libharfbuzz-0.dll"
File "libhogweed-6.dll"
File "libiconv-2.dll"
File "libidn2-0.dll"
File "libintl-8.dll"
File "libjpeg-9.dll"
File "liblzma-5.dll"
File "libmp3lame-0.dll"
File "libmpcdec.dll"
File "libmpg123-0.dll"
File "libnettle-8.dll"
File "libnghttp2.dll"
File "libogg-0.dll"
File "libopenmpt-0.dll"
File "libopus-0.dll"
File "liborc-0.4-0.dll"
File "libpcre-1.dll"
File "libpcre2-16-0.dll"
File "libpng16-16.dll"
File "libprotobuf-30.dll"
File "libprotobuf-32.dll"
File "libpsl-5.dll"
File "libqtsparkle-qt6.dll"
File "libsoup-3.0-0.dll"
File "libsoup-2.4-1.dll"
File "libspeex-1.dll"
File "libsqlite3-0.dll"
File "libssp-0.dll"
File "libstdc++-6.dll"
File "libtag.dll"
File "libtasn1-6.dll"
File "libunistring-2.dll"
File "libvorbis-0.dll"
File "libvorbisenc-2.dll"
File "libvorbisfile-3.dll"
File "libwavpack-1.dll"
File "libwinpthread-1.dll"
File "libxml2-2.dll"
File "libzstd.dll"
File "postproc-56.dll"
File "swresample-4.dll"
@@ -287,8 +307,11 @@ Section "Strawberry" Strawberry
File "libexpat-1.dll"
File "libmman.dll"
File "libmpfr-6.dll"
File "libpcre2-16d.dll"
File "libreadline8.dll"
File "libtermcap.dll"
!else
File "libpcre2-16.dll"
!endif
!endif ; MinGW
@@ -298,21 +321,26 @@ Section "Strawberry" Strawberry
!ifdef msvc
!ifdef arch_x86
File "libcrypto-1_1.dll"
File "libssl-1_1.dll"
File "libcrypto-3.dll"
File "libssl-3.dll"
!endif
!ifdef arch_x64
File "libcrypto-1_1-x64.dll"
File "libssl-1_1-x64.dll"
File "libcrypto-3-x64.dll"
File "libssl-3-x64.dll"
!endif
File "avcodec-58.dll"
File "avfilter-7.dll"
File "avformat-58.dll"
File "avresample-4.dll"
File "avutil-56.dll"
File "bz2.dll"
File "brotlicommon.dll"
File "brotlidec.dll"
File "chromaprint.dll"
File "faad.dll"
File "fdk-aac.dll"
File "ffi-7.dll"
File "FLAC.dll"
File "gio-2.0-0.dll"
File "glib-2.0-0.dll"
File "gmodule-2.0-0.dll"
@@ -321,6 +349,7 @@ Section "Strawberry" Strawberry
File "gstadaptivedemux-1.0-0.dll"
File "gstapp-1.0-0.dll"
File "gstaudio-1.0-0.dll"
File "gstbadaudio-1.0-0.dll"
File "gstbase-1.0-0.dll"
File "gstfft-1.0-0.dll"
File "gstisoff-1.0-0.dll"
@@ -336,36 +365,65 @@ Section "Strawberry" Strawberry
File "gstvideo-1.0-0.dll"
File "gstwinrt-1.0-0.dll"
File "intl-8.dll"
File "libprotobuf.dll"
File "opus-0.dll"
File "libbs2b.dll"
File "libfaac_dll.dll"
File "libiconv.dll"
File "liblzma.dll"
File "libmp3lame.dll"
File "libopenmpt.dll"
File "libspeex.dll"
File "mpcdec.dll"
File "mpg123.dll"
File "ogg.dll"
File "opus.dll"
File "orc-0.4-0.dll"
File "postproc-55.dll"
File "psl-5.dll"
File "qtsparkle-qt6.dll"
File "soup-2.4-1.dll"
File "sqlite3-0.dll"
File "sqlite3.dll"
File "swresample-3.dll"
File "swscale-5.dll"
File "tag.dll"
File "z-1.dll"
File "vorbis.dll"
File "vorbisfile.dll"
File "wavpackdll.dll"
!ifdef release
File "libpng16.dll"
File "libprotobuf.dll"
File "libxml2.dll"
File "pcre2-16.dll"
File "zlib.dll"
!endif
!ifdef debug
File "libpng16d.dll"
File "libprotobufd.dll"
File "libxml2d.dll"
File "pcre2-16d.dll"
File "zlibd.dll"
!endif
!endif ; MSVC
; Common files
File "libfftw3-3.dll"
File "libFLAC-8.dll"
File "libiconv-2.dll"
File "libmp3lame-0.dll"
File "libogg-0.dll"
File "libspeex-1.dll"
File "libvorbis-0.dll"
File "libvorbisenc-2.dll"
File "libwinpthread-1.dll"
File "libxml2-2.dll"
!ifdef msvc && debug
File "Qt6Concurrentd.dll"
File "Qt6Cored.dll"
File "Qt6Guid.dll"
File "Qt6Networkd.dll"
File "Qt6Sqld.dll"
File "Qt6Widgetsd.dll"
!else
File "Qt6Concurrent.dll"
File "Qt6Core.dll"
File "Qt6Gui.dll"
File "Qt6Network.dll"
File "Qt6Sql.dll"
File "Qt6Widgets.dll"
!endif
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@@ -403,43 +461,70 @@ Section "GIO modules" gio-modules
SetOutPath "$INSTDIR\gio-modules"
!ifdef mingw
File "/oname=libgiognutls.dll" "gio-modules\libgiognutls.dll"
File "/oname=libgioopenssl.dll" "gio-modules\libgioopenssl.dll"
!endif
!ifdef msvc
File "/oname=giognutls.dll" "gio-modules\giognutls.dll"
File "/oname=gioopenssl.dll" "gio-modules\gioopenssl.dll"
!endif
SectionEnd
Section "Qt Platform plugins" platforms
SetOutPath "$INSTDIR\platforms"
!ifdef msvc && debug
File "/oname=qwindowsd.dll" "platforms\qwindowsd.dll"
!else
File "/oname=qwindows.dll" "platforms\qwindows.dll"
!endif
SectionEnd
Section "Qt styles" styles
SetOutPath "$INSTDIR\styles"
!ifdef msvc && debug
File "/oname=qwindowsvistastyled.dll" "styles\qwindowsvistastyled.dll"
!else
File "/oname=qwindowsvistastyle.dll" "styles\qwindowsvistastyle.dll"
!endif
SectionEnd
Section "Qt TLS plugins" tls
SetOutPath "$INSTDIR\tls"
!ifdef msvc && debug
File "/oname=qschannelbackendd.dll" "tls\qschannelbackendd.dll"
File "/oname=qopensslbackendd.dll" "tls\qopensslbackendd.dll"
!else
File "/oname=qschannelbackend.dll" "tls\qschannelbackend.dll"
File "/oname=qopensslbackend.dll" "tls\qopensslbackend.dll"
!endif
SectionEnd
Section "Qt SQL Drivers" sqldrivers
SetOutPath "$INSTDIR\sqldrivers"
!ifdef msvc && debug
File "/oname=qsqlited.dll" "sqldrivers\qsqlited.dll"
!else
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
!endif
SectionEnd
Section "Qt imageformats" imageformats
SetOutPath "$INSTDIR\imageformats"
!ifdef msvc && debug
File "/oname=qgifd.dll" "imageformats\qgifd.dll"
File "/oname=qicod.dll" "imageformats\qicod.dll"
File "/oname=qjpegd.dll" "imageformats\qjpegd.dll"
!else
File "/oname=qgif.dll" "imageformats\qgif.dll"
File "/oname=qico.dll" "imageformats\qico.dll"
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
!endif
SectionEnd
Section "Gstreamer plugins" gstreamer-plugins
SetOutPath "$INSTDIR\gstreamer-plugins"
!ifdef mingw
File "/oname=libgstaes.dll" "gstreamer-plugins\libgstaes.dll"
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
@@ -453,20 +538,25 @@ Section "Gstreamer plugins" gstreamer-plugins
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=libgstbs2b.dll" "gstreamer-plugins\libgstbs2b.dll"
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
File "/oname=libgstdash.dll" "gstreamer-plugins\libgstdash.dll"
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
File "/oname=libgstfaac.dll" "gstreamer-plugins\libgstfaac.dll"
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
File "/oname=libgstfdkaac.dll" "gstreamer-plugins\libgstfdkaac.dll"
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
File "/oname=libgsthls.dll" "gstreamer-plugins\libgsthls.dll"
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
File "/oname=libgstmpg123.dll" "gstreamer-plugins\libgstmpg123.dll"
File "/oname=libgstmusepack.dll" "gstreamer-plugins\libgstmusepack.dll"
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
File "/oname=libgstopenmpt.dll" "gstreamer-plugins\libgstopenmpt.dll"
File "/oname=libgstopus.dll" "gstreamer-plugins\libgstopus.dll"
@@ -505,34 +595,42 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=gstaudioresample.dll" "gstreamer-plugins\gstaudioresample.dll"
File "/oname=gstaudiotestsrc.dll" "gstreamer-plugins\gstaudiotestsrc.dll"
File "/oname=gstautodetect.dll" "gstreamer-plugins\gstautodetect.dll"
File "/oname=gstbs2b.dll" "gstreamer-plugins\gstbs2b.dll"
File "/oname=gstcoreelements.dll" "gstreamer-plugins\gstcoreelements.dll"
File "/oname=gstdash.dll" "gstreamer-plugins\gstdash.dll"
File "/oname=gstdirectsound.dll" "gstreamer-plugins\gstdirectsound.dll"
File "/oname=gstequalizer.dll" "gstreamer-plugins\gstequalizer.dll"
File "/oname=gstfaac.dll" "gstreamer-plugins\gstfaac.dll"
File "/oname=gstfaad.dll" "gstreamer-plugins\gstfaad.dll"
File "/oname=gstfdkaac.dll" "gstreamer-plugins\gstfdkaac.dll"
File "/oname=gstflac.dll" "gstreamer-plugins\gstflac.dll"
File "/oname=gstgio.dll" "gstreamer-plugins\gstgio.dll"
File "/oname=gsthls.dll" "gstreamer-plugins\gsthls.dll"
File "/oname=gsticydemux.dll" "gstreamer-plugins\gsticydemux.dll"
File "/oname=gstid3demux.dll" "gstreamer-plugins\gstid3demux.dll"
File "/oname=gstisomp4.dll" "gstreamer-plugins\gstisomp4.dll"
File "/oname=gstlame.dll" "gstreamer-plugins\gstlame.dll"
File "/oname=gstlibav.dll" "gstreamer-plugins\gstlibav.dll"
File "/oname=gstmpg123.dll" "gstreamer-plugins\gstmpg123.dll"
File "/oname=gstmusepack.dll" "gstreamer-plugins\gstmusepack.dll"
File "/oname=gstogg.dll" "gstreamer-plugins\gstogg.dll"
File "/oname=gstopenmpt.dll" "gstreamer-plugins\gstopenmpt.dll"
File "/oname=gstopus.dll" "gstreamer-plugins\gstopus.dll"
File "/oname=gstopusparse.dll" "gstreamer-plugins\gstopusparse.dll"
File "/oname=gstplayback.dll" "gstreamer-plugins\gstplayback.dll"
File "/oname=gstreplaygain.dll" "gstreamer-plugins\gstreplaygain.dll"
File "/oname=gstrtp.dll" "gstreamer-plugins\gstrtp.dll"
File "/oname=gstrtsp.dll" "gstreamer-plugins\gstrtsp.dll"
File "/oname=gstspeex.dll" "gstreamer-plugins\gstspeex.dll"
File "/oname=gstsoup.dll" "gstreamer-plugins\gstsoup.dll"
File "/oname=gstspectrum.dll" "gstreamer-plugins\gstspectrum.dll"
File "/oname=gstspeex.dll" "gstreamer-plugins\gstspeex.dll"
File "/oname=gsttcp.dll" "gstreamer-plugins\gsttcp.dll"
File "/oname=gsttypefindfunctions.dll" "gstreamer-plugins\gsttypefindfunctions.dll"
File "/oname=gstudp.dll" "gstreamer-plugins\gstudp.dll"
File "/oname=gstvolume.dll" "gstreamer-plugins\gstvolume.dll"
File "/oname=gstvorbis.dll" "gstreamer-plugins\gstvorbis.dll"
File "/oname=gstwasapi.dll" "gstreamer-plugins\gstwasapi.dll"
File "/oname=gstwasapi2.dll" "gstreamer-plugins\gstwasapi2.dll"
;File "/oname=gstwasapi2.dll" "gstreamer-plugins\gstwasapi2.dll"
File "/oname=gstwavpack.dll" "gstreamer-plugins\gstwavpack.dll"
File "/oname=gstwavparse.dll" "gstreamer-plugins\gstwavparse.dll"
File "/oname=gstxingmux.dll" "gstreamer-plugins\gstxingmux.dll"
@@ -578,9 +676,7 @@ Section "Uninstall"
Delete "$INSTDIR\strawberry.exe"
Delete "$INSTDIR\strawberry-tagreader.exe"
Delete "$INSTDIR\strawberry.ico"
!ifdef mingw
Delete "$INSTDIR\sqlite3.exe"
!endif
Delete "$INSTDIR\gst-launch-1.0.exe"
Delete "$INSTDIR\gst-discoverer-1.0.exe"
@@ -606,14 +702,18 @@ Section "Uninstall"
Delete "$INSTDIR\avutil-57.dll"
Delete "$INSTDIR\libbrotlicommon.dll"
Delete "$INSTDIR\libbrotlidec.dll"
Delete "$INSTDIR\libbrotlienc.dll"
Delete "$INSTDIR\libbs2b-0.dll"
Delete "$INSTDIR\libbz2.dll"
Delete "$INSTDIR\libcdio-19.dll"
Delete "$INSTDIR\libchromaprint.dll"
Delete "$INSTDIR\libdl.dll"
Delete "$INSTDIR\libfdk-aac-2.dll"
Delete "$INSTDIR\libffi-8.dll"
Delete "$INSTDIR\libFLAC-8.dll"
Delete "$INSTDIR\libfreetype-6.dll"
Delete "$INSTDIR\libfaac-0.dll"
Delete "$INSTDIR\libfaad-2.dll"
Delete "$INSTDIR\libffi-8.dll"
Delete "$INSTDIR\libfreetype-6.dll"
Delete "$INSTDIR\libgio-2.0-0.dll"
Delete "$INSTDIR\libglib-2.0-0.dll"
Delete "$INSTDIR\libgmodule-2.0-0.dll"
@@ -639,30 +739,39 @@ Section "Uninstall"
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
Delete "$INSTDIR\libharfbuzz-0.dll"
Delete "$INSTDIR\libhogweed-6.dll"
Delete "$INSTDIR\libiconv-2.dll"
Delete "$INSTDIR\libidn2-0.dll"
Delete "$INSTDIR\libintl-8.dll"
Delete "$INSTDIR\libjpeg-9.dll"
Delete "$INSTDIR\liblzma-5.dll"
Delete "$INSTDIR\libmp3lame-0.dll"
Delete "$INSTDIR\libmpcdec.dll"
Delete "$INSTDIR\libmpg123-0.dll"
Delete "$INSTDIR\libnettle-8.dll"
Delete "$INSTDIR\libnghttp2.dll"
Delete "$INSTDIR\libogg-0.dll"
Delete "$INSTDIR\libopenmpt-0.dll"
Delete "$INSTDIR\libopus-0.dll"
Delete "$INSTDIR\liborc-0.4-0.dll"
Delete "$INSTDIR\libpcre-1.dll"
Delete "$INSTDIR\libpcre2-16-0.dll"
Delete "$INSTDIR\libpng16-16.dll"
Delete "$INSTDIR\libprotobuf-30.dll"
Delete "$INSTDIR\libprotobuf-32.dll"
Delete "$INSTDIR\libpsl-5.dll"
Delete "$INSTDIR\libqtsparkle-qt6.dll"
Delete "$INSTDIR\libsoup-3.0-0.dll"
Delete "$INSTDIR\libsoup-2.4-1.dll"
Delete "$INSTDIR\libspeex-1.dll"
Delete "$INSTDIR\libsqlite3-0.dll"
Delete "$INSTDIR\libssp-0.dll"
Delete "$INSTDIR\libstdc++-6.dll"
Delete "$INSTDIR\libtag.dll"
Delete "$INSTDIR\libtasn1-6.dll"
Delete "$INSTDIR\libunistring-2.dll"
Delete "$INSTDIR\libvorbis-0.dll"
Delete "$INSTDIR\libvorbisenc-2.dll"
Delete "$INSTDIR\libvorbisfile-3.dll"
Delete "$INSTDIR\libwavpack-1.dll"
Delete "$INSTDIR\libwinpthread-1.dll"
Delete "$INSTDIR\libxml2-2.dll"
Delete "$INSTDIR\libzstd.dll"
Delete "$INSTDIR\postproc-56.dll"
Delete "$INSTDIR\swresample-4.dll"
@@ -674,8 +783,11 @@ Section "Uninstall"
Delete "$INSTDIR\libexpat-1.dll"
Delete "$INSTDIR\libmman.dll"
Delete "$INSTDIR\libmpfr-6.dll"
Delete "$INSTDIR\libpcre2-16d.dll"
Delete "$INSTDIR\libreadline8.dll"
Delete "$INSTDIR\libtermcap.dll"
!else
Delete "$INSTDIR\libpcre2-16.dll"
!endif
!endif ; MinGW
@@ -685,21 +797,26 @@ Section "Uninstall"
!ifdef msvc
!ifdef arch_x86
Delete "$INSTDIR\libcrypto-1_1.dll"
Delete "$INSTDIR\libssl-1_1.dll"
Delete "$INSTDIR\libcrypto-3.dll"
Delete "$INSTDIR\libssl-3.dll"
!endif
!ifdef arch_x64
Delete "$INSTDIR\libcrypto-1_1-x64.dll"
Delete "$INSTDIR\libssl-1_1-x64.dll"
Delete "$INSTDIR\libcrypto-3-x64.dll"
Delete "$INSTDIR\libssl-3-x64.dll"
!endif
Delete "$INSTDIR\avcodec-58.dll"
Delete "$INSTDIR\avfilter-7.dll"
Delete "$INSTDIR\avformat-58.dll"
Delete "$INSTDIR\avresample-4.dll"
Delete "$INSTDIR\avutil-56.dll"
Delete "$INSTDIR\bz2.dll"
Delete "$INSTDIR\brotlicommon.dll"
Delete "$INSTDIR\brotlidec.dll"
Delete "$INSTDIR\chromaprint.dll"
Delete "$INSTDIR\faad.dll"
Delete "$INSTDIR\fdk-aac.dll"
Delete "$INSTDIR\ffi-7.dll"
Delete "$INSTDIR\FLAC.dll"
Delete "$INSTDIR\gio-2.0-0.dll"
Delete "$INSTDIR\glib-2.0-0.dll"
Delete "$INSTDIR\gmodule-2.0-0.dll"
@@ -708,6 +825,7 @@ Section "Uninstall"
Delete "$INSTDIR\gstadaptivedemux-1.0-0.dll"
Delete "$INSTDIR\gstapp-1.0-0.dll"
Delete "$INSTDIR\gstaudio-1.0-0.dll"
Delete "$INSTDIR\gstbadaudio-1.0-0.dll"
Delete "$INSTDIR\gstbase-1.0-0.dll"
Delete "$INSTDIR\gstfft-1.0-0.dll"
Delete "$INSTDIR\gstisoff-1.0-0.dll"
@@ -723,56 +841,99 @@ Section "Uninstall"
Delete "$INSTDIR\gstvideo-1.0-0.dll"
Delete "$INSTDIR\gstwinrt-1.0-0.dll"
Delete "$INSTDIR\intl-8.dll"
Delete "$INSTDIR\libprotobuf.dll"
Delete "$INSTDIR\opus-0.dll"
Delete "$INSTDIR\libbs2b.dll"
Delete "$INSTDIR\libfaac_dll.dll"
Delete "$INSTDIR\libiconv.dll"
Delete "$INSTDIR\liblzma.dll"
Delete "$INSTDIR\libmp3lame.dll"
Delete "$INSTDIR\libopenmpt.dll"
Delete "$INSTDIR\libspeex.dll"
Delete "$INSTDIR\mpcdec.dll"
Delete "$INSTDIR\mpg123.dll"
Delete "$INSTDIR\ogg.dll"
Delete "$INSTDIR\opus.dll"
Delete "$INSTDIR\orc-0.4-0.dll"
Delete "$INSTDIR\postproc-55.dll"
Delete "$INSTDIR\psl-5.dll"
Delete "$INSTDIR\qtsparkle-qt6.dll"
Delete "$INSTDIR\soup-2.4-1.dll"
Delete "$INSTDIR\sqlite3-0.dll"
Delete "$INSTDIR\sqlite3.dll"
Delete "$INSTDIR\swresample-3.dll"
Delete "$INSTDIR\swscale-5.dll"
Delete "$INSTDIR\tag.dll"
Delete "$INSTDIR\z-1.dll"
Delete "$INSTDIR\vorbis.dll"
Delete "$INSTDIR\vorbisfile.dll"
Delete "$INSTDIR\wavpackdll.dll"
!ifdef release
Delete "$INSTDIR\libpng16.dll"
Delete "$INSTDIR\libprotobuf.dll"
Delete "$INSTDIR\libxml2.dll"
Delete "$INSTDIR\pcre2-16.dll"
Delete "$INSTDIR\zlib.dll"
!endif
!ifdef debug
Delete "$INSTDIR\libpng16d.dll"
Delete "$INSTDIR\libprotobufd.dll"
Delete "$INSTDIR\libxml2d.dll"
Delete "$INSTDIR\pcre2-16d.dll"
Delete "$INSTDIR\zlibd.dll"
!endif
!endif ; MSVC
; Common files
Delete "$INSTDIR\libfftw3-3.dll"
Delete "$INSTDIR\libFLAC-8.dll"
Delete "$INSTDIR\libiconv-2.dll"
Delete "$INSTDIR\libmp3lame-0.dll"
Delete "$INSTDIR\libogg-0.dll"
Delete "$INSTDIR\libspeex-1.dll"
Delete "$INSTDIR\libvorbis-0.dll"
Delete "$INSTDIR\libvorbisenc-2.dll"
Delete "$INSTDIR\libwinpthread-1.dll"
Delete "$INSTDIR\libxml2-2.dll"
!ifdef msvc && debug
Delete "$INSTDIR\Qt6Concurrentd.dll"
Delete "$INSTDIR\Qt6Cored.dll"
Delete "$INSTDIR\Qt6Guid.dll"
Delete "$INSTDIR\Qt6Networkd.dll"
Delete "$INSTDIR\Qt6Sqld.dll"
Delete "$INSTDIR\Qt6Widgetsd.dll"
!else
Delete "$INSTDIR\Qt6Concurrent.dll"
Delete "$INSTDIR\Qt6Core.dll"
Delete "$INSTDIR\Qt6Gui.dll"
Delete "$INSTDIR\Qt6Network.dll"
Delete "$INSTDIR\Qt6Sql.dll"
Delete "$INSTDIR\Qt6Widgets.dll"
!endif
!ifdef mingw
Delete "$INSTDIR\gio-modules\libgiognutls.dll"
Delete "$INSTDIR\gio-modules\libgioopenssl.dll"
!endif
!ifdef msvc
Delete "$INSTDIR\gio-modules\giognutls.dll"
Delete "$INSTDIR\gio-modules\gioopenssl.dll"
!endif
!ifdef msvc && debug
Delete "$INSTDIR\platforms\qwindowsd.dll"
Delete "$INSTDIR\styles\qwindowsvistastyled.dll"
Delete "$INSTDIR\tls\qschannelbackendd.dll"
Delete "$INSTDIR\tls\qopensslbackendd.dll"
Delete "$INSTDIR\sqldrivers\qsqlited.dll"
Delete "$INSTDIR\imageformats\qgifd.dll"
Delete "$INSTDIR\imageformats\qicod.dll"
Delete "$INSTDIR\imageformats\qjpegd.dll"
!else
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\styles\qwindowsvistastyle.dll"
Delete "$INSTDIR\tls\qschannelbackend.dll"
Delete "$INSTDIR\tls\qopensslbackend.dll"
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
Delete "$INSTDIR\imageformats\qgif.dll"
Delete "$INSTDIR\imageformats\qico.dll"
Delete "$INSTDIR\imageformats\qjpeg.dll"
!endif
; MinGW GStreamer plugins
!ifdef mingw
Delete "$INSTDIR\gstreamer-plugins\libgstaes.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
@@ -786,20 +947,25 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstbs2b.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdash.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfaac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfdkaac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsthls.dll"
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmpg123.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmusepack.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstopenmpt.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstopus.dll"
@@ -840,27 +1006,35 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\gstaudioresample.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudiotestsrc.dll"
Delete "$INSTDIR\gstreamer-plugins\gstautodetect.dll"
Delete "$INSTDIR\gstreamer-plugins\gstbs2b.dll"
Delete "$INSTDIR\gstreamer-plugins\gstcoreelements.dll"
Delete "$INSTDIR\gstreamer-plugins\gstdash.dll"
Delete "$INSTDIR\gstreamer-plugins\gstdirectsound.dll"
Delete "$INSTDIR\gstreamer-plugins\gstequalizer.dll"
Delete "$INSTDIR\gstreamer-plugins\gstfaac.dll"
Delete "$INSTDIR\gstreamer-plugins\gstfaad.dll"
Delete "$INSTDIR\gstreamer-plugins\gstfdkaac.dll"
Delete "$INSTDIR\gstreamer-plugins\gstflac.dll"
Delete "$INSTDIR\gstreamer-plugins\gstgio.dll"
Delete "$INSTDIR\gstreamer-plugins\gsthls.dll"
Delete "$INSTDIR\gstreamer-plugins\gsticydemux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstid3demux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstisomp4.dll"
Delete "$INSTDIR\gstreamer-plugins\gstlame.dll"
Delete "$INSTDIR\gstreamer-plugins\gstlibav.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmpg123.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmusepack.dll"
Delete "$INSTDIR\gstreamer-plugins\gstogg.dll"
Delete "$INSTDIR\gstreamer-plugins\gstopenmpt.dll"
Delete "$INSTDIR\gstreamer-plugins\gstopus.dll"
Delete "$INSTDIR\gstreamer-plugins\gstopusparse.dll"
Delete "$INSTDIR\gstreamer-plugins\gstplayback.dll"
Delete "$INSTDIR\gstreamer-plugins\gstreplaygain.dll"
Delete "$INSTDIR\gstreamer-plugins\gstrtp.dll"
Delete "$INSTDIR\gstreamer-plugins\gstrtsp.dll"
Delete "$INSTDIR\gstreamer-plugins\gstspeex.dll"
Delete "$INSTDIR\gstreamer-plugins\gstsoup.dll"
Delete "$INSTDIR\gstreamer-plugins\gstspectrum.dll"
Delete "$INSTDIR\gstreamer-plugins\gstspeex.dll"
Delete "$INSTDIR\gstreamer-plugins\gsttcp.dll"
Delete "$INSTDIR\gstreamer-plugins\gsttypefindfunctions.dll"
Delete "$INSTDIR\gstreamer-plugins\gstudp.dll"

View File

@@ -50,7 +50,10 @@ enum {
} // namespace
#define gst_fastspectrum_parent_class parent_class
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wold-style-cast"
G_DEFINE_TYPE(GstFastSpectrum, gst_fastspectrum, GST_TYPE_AUDIO_FILTER)
#pragma GCC diagnostic pop
static void gst_fastspectrum_finalize(GObject *object);
static void gst_fastspectrum_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec);

View File

@@ -61,7 +61,7 @@ static const char *kMessageHandlerMagic = "__logging_message__";
static const size_t kMessageHandlerMagicLength = strlen(kMessageHandlerMagic);
static QtMessageHandler sOriginalMessageHandler = nullptr;
template <class T>
template<class T>
static T CreateLogger(Level level, const QString &class_name, int line, const char *category);
void GLog(const char *domain, int level, const char *message, void*) {
@@ -88,7 +88,7 @@ void GLog(const char *domain, int level, const char *message, void*) {
}
template <class T>
template<class T>
class DebugBase : public QDebug {
public:
DebugBase() : QDebug(sNullDevice) {}
@@ -314,11 +314,11 @@ QString LinuxDemangle(const QString &symbol) {
QString DarwinDemangle(const QString &symbol);
QString DarwinDemangle(const QString &symbol) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
QStringList split = symbol.split(' ', Qt::SkipEmptyParts);
#else
# else
QStringList split = symbol.split(' ', QString::SkipEmptyParts);
#endif
# endif
QString mangled_function = split[3];
return CXXDemangle(mangled_function);
@@ -379,7 +379,7 @@ QDebug CreateLoggerError(int line, const char *pretty_function, const char *cate
namespace {
template <typename T>
template<typename T>
QString print_duration(T duration, const std::string &unit) {
return QString("%1%2").arg(duration.count()).arg(unit.c_str());
}

View File

@@ -79,7 +79,7 @@ class _MessageHandlerBase : public QObject {
// Reads and writes uint32 length encoded MessageType messages to a socket.
// You should subclass this and implement the MessageArrived(MessageType) method.
template <typename MT>
template<typename MT>
class AbstractMessageHandler : public _MessageHandlerBase {
public:
AbstractMessageHandler(QIODevice *device, QObject *parent);
@@ -115,11 +115,11 @@ class AbstractMessageHandler : public _MessageHandlerBase {
QMap<int, ReplyType*> pending_replies_;
};
template <typename MT>
template<typename MT>
AbstractMessageHandler<MT>::AbstractMessageHandler(QIODevice *device, QObject *parent)
: _MessageHandlerBase(device, parent) {}
template <typename MT>
template<typename MT>
void AbstractMessageHandler<MT>::SendMessage(const MessageType &message) {
Q_ASSERT(QThread::currentThread() == thread());
@@ -127,7 +127,7 @@ void AbstractMessageHandler<MT>::SendMessage(const MessageType &message) {
WriteMessage(QByteArray(data.data(), data.size()));
}
template <typename MT>
template<typename MT>
void AbstractMessageHandler<MT>::SendMessageAsync(const MessageType &message) {
std::string data = message.SerializeAsString();
QMetaObject::invokeMethod(this, "WriteMessage", Qt::QueuedConnection, Q_ARG(QByteArray, QByteArray(data.data(), data.size())));

View File

@@ -56,7 +56,7 @@ class _MessageReplyBase : public QObject {
};
// A reply future class that is returned immediately for requests that will occur in the background. Similar to QNetworkReply.
template <typename MessageType>
template<typename MessageType>
class MessageReply : public _MessageReplyBase {
public:
explicit MessageReply(const MessageType &request_message, QObject *parent = nullptr);

View File

@@ -70,7 +70,7 @@ class _WorkerPoolBase : public QObject {
// A local socket server is started for each process, and the address is passed to the process as argv[1].
// The process is expected to connect back to the socket server, and when it does a HandlerType is created for it.
// Instances of HandlerType are created in the WorkerPool's thread.
template <typename HandlerType>
template<typename HandlerType>
class WorkerPool : public _WorkerPoolBase {
public:
explicit WorkerPool(QObject *parent = nullptr);
@@ -121,9 +121,9 @@ class WorkerPool : public _WorkerPoolBase {
// Must only ever be called on my thread.
void StartOneWorker(Worker *worker);
template <typename T>
template<typename T>
Worker *FindWorker(T Worker::*member, T value) {
for (typename QList<Worker>::iterator it = workers_.begin() ; it != workers_.end() ; ++it) {
for (typename QList<Worker>::iterator it = workers_.begin(); it != workers_.end(); ++it) {
if ((*it).*member == value) {
return &(*it);
}
@@ -131,7 +131,7 @@ class WorkerPool : public _WorkerPoolBase {
return nullptr;
}
template <typename T>
template<typename T>
void DeleteQObjectPointerLater(T **p) {
if (*p) {
(*p)->deleteLater();
@@ -158,15 +158,15 @@ class WorkerPool : public _WorkerPoolBase {
QAtomicInt next_id_;
QMutex message_queue_mutex_;
QQueue<ReplyType*> message_queue_;
QQueue<ReplyType *> message_queue_;
};
template <typename HandlerType>
template<typename HandlerType>
WorkerPool<HandlerType>::WorkerPool(QObject *parent)
: _WorkerPoolBase(parent),
next_worker_(0),
next_id_(0) {
: _WorkerPoolBase(parent),
next_worker_(0),
next_id_(0) {
worker_count_ = qBound(1, QThread::idealThreadCount() / 2, 4);
local_server_name_ = qApp->applicationName().toLower();
@@ -177,7 +177,7 @@ WorkerPool<HandlerType>::WorkerPool(QObject *parent)
}
template <typename HandlerType>
template<typename HandlerType>
WorkerPool<HandlerType>::~WorkerPool() {
for (const Worker &worker : workers_) {
@@ -208,30 +208,30 @@ WorkerPool<HandlerType>::~WorkerPool() {
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::SetWorkerCount(const int count) {
Q_ASSERT(workers_.isEmpty());
worker_count_ = count;
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::SetLocalServerName(const QString &local_server_name) {
Q_ASSERT(workers_.isEmpty());
local_server_name_ = local_server_name;
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::SetExecutableName(const QString &executable_name) {
Q_ASSERT(workers_.isEmpty());
executable_name_ = executable_name;
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::Start() {
QMetaObject::invokeMethod(this, "DoStart");
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::DoStart() {
Q_ASSERT(workers_.isEmpty());
@@ -270,7 +270,7 @@ void WorkerPool<HandlerType>::DoStart() {
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::StartOneWorker(Worker *worker) {
Q_ASSERT(QThread::currentThread() == thread());
@@ -311,10 +311,9 @@ void WorkerPool<HandlerType>::StartOneWorker(Worker *worker) {
#endif
worker->process_->start(executable_path_, QStringList() << worker->local_server_->fullServerName());
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::NewConnection() {
Q_ASSERT(QThread::currentThread() == thread());
@@ -342,7 +341,7 @@ void WorkerPool<HandlerType>::NewConnection() {
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::ProcessError(QProcess::ProcessError error) {
Q_ASSERT(QThread::currentThread() == thread());
@@ -370,7 +369,7 @@ void WorkerPool<HandlerType>::ProcessError(QProcess::ProcessError error) {
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::ProcessReadyReadStandardOutput() {
Q_ASSERT(QThread::currentThread() == thread());
@@ -383,7 +382,7 @@ void WorkerPool<HandlerType>::ProcessReadyReadStandardOutput() {
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::ProcessReadyReadStandardError() {
Q_ASSERT(QThread::currentThread() == thread());
@@ -426,7 +425,7 @@ WorkerPool<HandlerType>::SendMessageWithReply(MessageType *message) {
}
template <typename HandlerType>
template<typename HandlerType>
void WorkerPool<HandlerType>::SendQueuedMessages() {
QMutexLocker l(&message_queue_mutex_);
@@ -448,7 +447,7 @@ void WorkerPool<HandlerType>::SendQueuedMessages() {
}
template <typename HandlerType>
template<typename HandlerType>
HandlerType *WorkerPool<HandlerType>::NextHandler() const {
for (int i = 0; i < workers_.count(); ++i) {

View File

@@ -113,6 +113,7 @@ class TagLibFileRefFactory : public FileRefFactory {
return new TagLib::FileRef(QFile::encodeName(filename).constData());
#endif
}
private:
Q_DISABLE_COPY(TagLibFileRefFactory)
};
@@ -130,11 +131,11 @@ TagLib::String QStringToTaglibString(const QString &s) {
} // namespace
namespace {
const char *kMP4_OriginalYear_ID = "----:com.apple.iTunes:ORIGINAL YEAR";
const char *kMP4_OriginalYear_ID = "----:com.apple.iTunes:ORIGINAL YEAR";
const char *kMP4_FMPS_Playcount_ID = "----:com.apple.iTunes:FMPS_Playcount";
const char *kMP4_FMPS_Rating_ID = "----:com.apple.iTunes:FMPS_Rating";
const char *kASF_OriginalDate_ID = "WM/OriginalReleaseTime";
const char *kASF_OriginalYear_ID = "WM/OriginalReleaseYear";
const char *kMP4_FMPS_Rating_ID = "----:com.apple.iTunes:FMPS_Rating";
const char *kASF_OriginalDate_ID = "WM/OriginalReleaseTime";
const char *kASF_OriginalYear_ID = "WM/OriginalReleaseYear";
} // namespace
@@ -265,7 +266,7 @@ void TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
if (tag) Decode(tag->comment(), song->mutable_comment());
}
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File *>(fileref->file())) {
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
song->set_bitdepth(file_wavpack->audioProperties()->bitsPerSample());
if (file_wavpack->APETag()) {
ParseAPETag(file_wavpack->APETag()->itemListMap(), &disc, &compilation, song);
@@ -306,7 +307,9 @@ void TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
if (!map["TCMP"].isEmpty()) compilation = TStringToQString(map["TCMP"].front()->toString()).trimmed();
if (!map["TDOR"].isEmpty()) { song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt()); }
if (!map["TDOR"].isEmpty()) {
song->set_originalyear(map["TDOR"].front()->toString().substr(0, 4).toInt());
}
else if (!map["TORY"].isEmpty()) {
song->set_originalyear(map["TORY"].front()->toString().substr(0, 4).toInt());
}
@@ -321,7 +324,7 @@ void TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
if (!map["APIC"].isEmpty()) song->set_art_automatic(kEmbeddedCover);
// Find a suitable comment tag. For now we ignore iTunNORM comments.
for (uint i = 0 ; i < map["COMM"].size() ; ++i) {
for (uint i = 0; i < map["COMM"].size(); ++i) {
const TagLib::ID3v2::CommentsFrame *frame = dynamic_cast<const TagLib::ID3v2::CommentsFrame*>(map["COMM"][i]);
if (frame && TStringToQString(frame->description()) != "iTunNORM") {
@@ -450,7 +453,7 @@ void TagReaderTagLib::ReadFile(const QString &filename, spb::tagreader::SongMeta
}
if (attributes_map.contains("FMPS/Rating")) {
const TagLib::ASF::AttributeList& attributes = attributes_map["FMPS/Rating"];
const TagLib::ASF::AttributeList &attributes = attributes_map["FMPS/Rating"];
if (!attributes.isEmpty()) {
float rating = TStringToQString(attributes.front().toString()).toFloat();
if (song->rating() <= 0 && rating > 0) {
@@ -679,7 +682,7 @@ bool TagReaderTagLib::SaveFile(const QString &filename, const spb::tagreader::So
else if (TagLib::MP4::File *file_mp4 = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
TagLib::MP4::Tag *tag = file_mp4->tag();
if (!tag) return false;
tag->setItem("disk", TagLib::MP4::Item(song.disc() <= 0 -1 ? 0 : song.disc(), 0));
tag->setItem("disk", TagLib::MP4::Item(song.disc() <= 0 - 1 ? 0 : song.disc(), 0));
tag->setItem("\251wrt", TagLib::StringList(TagLib::String(song.composer(), TagLib::String::UTF8)));
tag->setItem("\251grp", TagLib::StringList(TagLib::String(song.grouping(), TagLib::String::UTF8)));
tag->setItem("\251lyr", TagLib::StringList(TagLib::String(song.lyrics(), TagLib::String::UTF8)));
@@ -743,7 +746,7 @@ void TagReaderTagLib::SetTextFrame(const char *id, const std::string &value, Tag
}
// Update and add the frames
for (int i = 0 ; i < frames_buffer.size() ; ++i) {
for (int i = 0; i < frames_buffer.size(); ++i) {
TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame(frames_buffer.at(i));
if (i == 0) {
frame->setText(StdStringToTaglibString(value));
@@ -799,7 +802,7 @@ void TagReaderTagLib::SetUnsyncLyricsFrame(const std::string &value, TagLib::ID3
}
// Update and add the frames
for (int i = 0 ; i < frames_buffer.size() ; ++i) {
for (int i = 0; i < frames_buffer.size(); ++i) {
TagLib::ID3v2::UnsynchronizedLyricsFrame *frame = new TagLib::ID3v2::UnsynchronizedLyricsFrame(frames_buffer.at(i));
if (i == 0) {
frame->setText(StdStringToTaglibString(value));
@@ -983,7 +986,7 @@ bool TagReaderTagLib::SaveEmbeddedArt(const QString &filename, const QByteArray
// Remove existing covers
TagLib::ID3v2::FrameList apiclist = tag->frameListMap()["APIC"];
for (TagLib::ID3v2::FrameList::ConstIterator it = apiclist.begin() ; it != apiclist.end() ; ++it ) {
for (TagLib::ID3v2::FrameList::ConstIterator it = apiclist.begin(); it != apiclist.end(); ++it) {
TagLib::ID3v2::AttachedPictureFrame *frame = dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(*it);
tag->removeFrame(frame, false);
}
@@ -994,7 +997,7 @@ bool TagReaderTagLib::SaveEmbeddedArt(const QString &filename, const QByteArray
frontcover = new TagLib::ID3v2::AttachedPictureFrame("APIC");
frontcover->setType(TagLib::ID3v2::AttachedPictureFrame::FrontCover);
frontcover->setMimeType("image/jpeg");
frontcover->setPicture(TagLib::ByteVector(data.constData(), data.count()));
frontcover->setPicture(TagLib::ByteVector(data.constData(), data.size()));
tag->addFrame(frontcover);
}
}
@@ -1008,7 +1011,7 @@ bool TagReaderTagLib::SaveEmbeddedArt(const QString &filename, const QByteArray
if (tag->contains("covr")) tag->removeItem("covr");
}
else {
covers.append(TagLib::MP4::CoverArt(TagLib::MP4::CoverArt::JPEG, TagLib::ByteVector(data.constData(), data.count())));
covers.append(TagLib::MP4::CoverArt(TagLib::MP4::CoverArt::JPEG, TagLib::ByteVector(data.constData(), data.size())));
tag->setItem("covr", covers);
}
}

View File

@@ -75,13 +75,13 @@ class TagReaderTagLib : public TagReaderBase {
void SetTextFrame(const char *id, const std::string &value, TagLib::ID3v2::Tag *tag) const;
void SetUserTextFrame(const QString &description, const QString &value, TagLib::ID3v2::Tag *tag) const;
void SetUserTextFrame(const std::string &description, const std::string &value, TagLib::ID3v2::Tag *tag) const;
void SetUnsyncLyricsFrame(const std::string& value, TagLib::ID3v2::Tag* tag) const;
void SetUnsyncLyricsFrame(const std::string &value, TagLib::ID3v2::Tag *tag) const;
QByteArray LoadEmbeddedAPEArt(const TagLib::APE::ItemListMap &map) const;
static float ConvertPOPMRating(const int POPM_rating);
static int ConvertToPOPMRating(const float rating);
static TagLib::ID3v2::PopularimeterFrame *GetPOPMFrameFromTag(TagLib::ID3v2::Tag* tag);
static TagLib::ID3v2::PopularimeterFrame *GetPOPMFrameFromTag(TagLib::ID3v2::Tag *tag);
private:
FileRefFactory *factory_;

View File

@@ -151,7 +151,7 @@ void TagReaderTagParser::ReadFile(const QString &filename, spb::tagreader::SongM
const auto tracks = taginfo.tracks();
for (const auto track : tracks) {
switch(track->format().general) {
switch (track->format().general) {
case TagParser::GeneralMediaFormat::Flac:
song->set_filetype(spb::tagreader::SongMetadata_FileType::SongMetadata_FileType_FLAC);
break;
@@ -174,7 +174,7 @@ void TagReaderTagParser::ReadFile(const QString &filename, spb::tagreader::SongM
song->set_filetype(spb::tagreader::SongMetadata_FileType::SongMetadata_FileType_OGGSPEEX);
break;
case TagParser::GeneralMediaFormat::Mpeg1Audio:
switch(track->format().sub) {
switch (track->format().sub) {
case TagParser::SubFormats::Mpeg1Layer3:
song->set_filetype(spb::tagreader::SongMetadata_FileType::SongMetadata_FileType_MPEG);
break;

View File

@@ -99,7 +99,7 @@ int main(int argc, char **argv) {
QRegularExpressionMatch match = regexp.match(output_line);
if (match.hasMatch()) {
QString library = match.captured(1);
if (QFileInfo(library).fileName() == QFileInfo(filepath).fileName()) { // It's this.
if (QFileInfo(library).fileName() == QFileInfo(filepath).fileName()) { // It's this.
continue;
}
else if (library.startsWith("@executable_path")) {
@@ -113,7 +113,7 @@ int main(int argc, char **argv) {
else if (library.startsWith("@rpath")) {
QString real_path = library;
real_path = real_path.replace("@rpath", bundle_path + "/Contents/Frameworks");
if (!QFile(real_path).exists() && !real_path.endsWith("QtSvg")) { // FIXME: Ignore broken svg image plugin.
if (!QFile(real_path).exists() && !real_path.endsWith("QtSvg")) { // FIXME: Ignore broken svg image plugin.
qLog(Error) << real_path << "does not exist for" << filepath;
success = false;
}
@@ -127,7 +127,7 @@ int main(int argc, char **argv) {
success = false;
}
}
else if (library.startsWith("/System/Library/") || library.startsWith("/usr/lib/")) { // System library
else if (library.startsWith("/System/Library/") || library.startsWith("/usr/lib/")) { // System library
continue;
}
else if (library.endsWith("libgcc_s.1.dylib")) { // fftw points to it for some reason.

View File

@@ -21,7 +21,7 @@
#include <QtGlobal>
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
#include <sys/time.h>
# include <sys/time.h>
#endif
#include <iostream>

View File

@@ -28,7 +28,7 @@
#include "tagreaderworker.h"
TagReaderWorker::TagReaderWorker(QIODevice *socket, QObject *parent)
: AbstractMessageHandler<spb::tagreader::Message>(socket, parent) {}
: AbstractMessageHandler<spb::tagreader::Message>(socket, parent) {}
void TagReaderWorker::MessageArrived(const spb::tagreader::Message &message) {

View File

@@ -12,6 +12,7 @@ set(SOURCES
core/commandlineoptions.cpp
core/database.cpp
core/sqlquery.cpp
core/sqlrow.cpp
core/metatypes.cpp
core/deletefiles.cpp
core/filesystemmusicstorage.cpp
@@ -59,8 +60,6 @@ set(SOURCES
context/contextview.cpp
context/contextalbum.cpp
context/contextalbumsmodel.cpp
context/contextalbumsview.cpp
collection/collection.cpp
collection/collectionmodel.cpp
@@ -73,7 +72,6 @@ set(SOURCES
collection/collectionfilterwidget.cpp
collection/collectionplaylistitem.cpp
collection/collectionquery.cpp
collection/sqlrow.cpp
collection/savedgroupingmanager.cpp
collection/groupbydialog.cpp
collection/collectiontask.cpp
@@ -212,6 +210,7 @@ set(SOURCES
widgets/tracksliderslider.cpp
widgets/loginstatewidget.cpp
widgets/ratingwidget.cpp
widgets/resizabletextedit.cpp
osd/osdbase.cpp
osd/osdpretty.cpp
@@ -298,8 +297,6 @@ set(HEADERS
context/contextview.h
context/contextalbum.h
context/contextalbumsmodel.h
context/contextalbumsview.h
collection/collection.h
collection/collectionmodel.h
@@ -445,6 +442,7 @@ set(HEADERS
widgets/qsearchfield.h
widgets/ratingwidget.h
widgets/forcescrollperpixel.h
widgets/resizabletextedit.h
osd/osdbase.h
osd/osdpretty.h

View File

@@ -32,10 +32,11 @@
#include <QVector>
#include <QPainter>
#include <QPalette>
#include <QBasicTimer>
#include <QShowEvent>
#include <QHideEvent>
#include <QTimerEvent>
#include <QtEvents>
#include "core/logging.h"
#include "engine/enginebase.h"
// INSTRUCTIONS Base2D
@@ -51,16 +52,34 @@
Analyzer::Base::Base(QWidget *parent, const uint scopeSize)
: QWidget(parent),
timeout_(40),
fht_(new FHT(scopeSize)),
engine_(nullptr),
lastscope_(512),
new_frame_(false),
is_playing_(false) {}
is_playing_(false),
timeout_(40) {}
void Analyzer::Base::hideEvent(QHideEvent*) { timer_.stop(); }
Analyzer::Base::~Base() {
delete fht_;
}
void Analyzer::Base::showEvent(QShowEvent*) { timer_.start(timeout(), this); }
void Analyzer::Base::showEvent(QShowEvent*) {
timer_.start(timeout(), this);
}
void Analyzer::Base::hideEvent(QHideEvent*) {
timer_.stop();
}
void Analyzer::Base::ChangeTimeout(const int timeout) {
timeout_ = timeout;
if (timer_.isActive()) {
timer_.stop();
timer_.start(timeout_, this);
}
}
void Analyzer::Base::transform(Scope &scope) {
@@ -154,7 +173,7 @@ int Analyzer::Base::resizeForBands(const int bands) {
}
else {
exp = 9;
}
}
resizeExponent(exp);
return fht_->size() / 2;
@@ -186,10 +205,6 @@ void Analyzer::Base::demo(QPainter &p) {
}
void Analyzer::Base::polishEvent() {
init();
}
void Analyzer::interpolate(const Scope &inVec, Scope &outVec) {
double pos = 0.0;

View File

@@ -44,8 +44,8 @@
class QHideEvent;
class QShowEvent;
class QTimerEvent;
class QPaintEvent;
class QTimerEvent;
namespace Analyzer {
@@ -55,19 +55,13 @@ class Base : public QWidget {
Q_OBJECT
public:
~Base() override { delete fht_; }
~Base() override;
int timeout() const { return timeout_; }
void set_engine(EngineBase *engine) { engine_ = engine; }
void changeTimeout(int newTimeout) {
timeout_ = newTimeout;
if (timer_.isActive()) {
timer_.stop();
timer_.start(timeout_, this);
}
}
void ChangeTimeout(const int timeout);
virtual void framerateChanged() {}
@@ -76,10 +70,8 @@ class Base : public QWidget {
void hideEvent(QHideEvent*) override;
void showEvent(QShowEvent*) override;
void paintEvent(QPaintEvent*) override;
void timerEvent(QTimerEvent*) override;
void polishEvent();
void paintEvent(QPaintEvent *e) override;
void timerEvent(QTimerEvent *e) override;
int resizeExponent(int);
int resizeForBands(const int);
@@ -90,13 +82,13 @@ class Base : public QWidget {
protected:
QBasicTimer timer_;
int timeout_;
FHT *fht_;
EngineBase *engine_;
Scope lastscope_;
bool new_frame_;
bool is_playing_;
int timeout_;
};
void interpolate(const Scope&, Scope&);

View File

@@ -153,7 +153,7 @@ void AnalyzerContainer::ChangeAnalyzer(const int id) {
current_analyzer_->set_engine(engine_);
// Even if it is not supposed to happen, I don't want to get a dbz error
current_framerate_ = current_framerate_ == 0 ? kMediumFramerate : current_framerate_;
current_analyzer_->changeTimeout(1000 / current_framerate_);
current_analyzer_->ChangeTimeout(1000 / current_framerate_);
layout()->addWidget(current_analyzer_);
@@ -166,7 +166,7 @@ void AnalyzerContainer::ChangeFramerate(int new_framerate) {
if (current_analyzer_) {
// Even if it is not supposed to happen, I don't want to get a dbz error
new_framerate = new_framerate == 0 ? kMediumFramerate : new_framerate;
current_analyzer_->changeTimeout(1000 / new_framerate);
current_analyzer_->ChangeTimeout(1000 / new_framerate);
// notify the current analyzer that the framerate has changed
current_analyzer_->framerateChanged();

View File

@@ -74,7 +74,7 @@ class AnalyzerContainer : public QWidget {
void Load();
void Save();
void SaveFramerate(const int framerate);
template <typename T>
template<typename T>
void AddAnalyzerType();
void AddFramerate(const QString &name, const int framerate);
@@ -96,10 +96,9 @@ class AnalyzerContainer : public QWidget {
Analyzer::Base *current_analyzer_;
EngineBase *engine_;
};
template <typename T>
template<typename T>
void AnalyzerContainer::AddAnalyzerType() {
int id = analyzer_types_.count();

View File

@@ -63,8 +63,7 @@ BlockAnalyzer::BlockAnalyzer(QWidget *parent)
setMaximumWidth(kMaxColumns * (kWidth + 1) - 1);
// mxcl says null pixmaps cause crashes, so let's play it safe
std::fill(fade_bars_.begin(), fade_bars_.end(), QPixmap(1, 1));
std::fill(fade_bars_.begin(), fade_bars_.end(), QPixmap(1, 1));
}
void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
@@ -89,7 +88,7 @@ void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
if (rows_ != oldRows) {
barpixmap_ = QPixmap(kWidth, rows_ * (kHeight + 1));
std::fill(fade_bars_.begin(), fade_bars_.end(), QPixmap(kWidth, rows_ * (kHeight + 1)));
std::fill(fade_bars_.begin(), fade_bars_.end(), QPixmap(kWidth, rows_ * (kHeight + 1)));
yscale_.resize(rows_ + 1);

View File

@@ -65,14 +65,14 @@ class BlockAnalyzer : public Analyzer::Base {
private:
QPixmap *bar() { return &barpixmap_; }
int columns_, rows_; // number of rows and columns of blocks
int y_; // y-offset from top of widget
int columns_, rows_; // number of rows and columns of blocks
int y_; // y-offset from top of widget
QPixmap barpixmap_;
QPixmap topbarpixmap_;
QPixmap background_;
QPixmap canvas_;
Analyzer::Scope scope_; // so we don't create a vector every frame
QVector<double> store_; // current bar heights
Analyzer::Scope scope_; // so we don't create a vector every frame
QVector<double> store_; // current bar heights
QVector<double> yscale_;
QVector<QPixmap> fade_bars_;

View File

@@ -43,12 +43,12 @@
using Analyzer::Scope;
const int Rainbow::RainbowAnalyzer::kHeight[] = {21, 33};
const int Rainbow::RainbowAnalyzer::kWidth[] = {34, 53};
const int Rainbow::RainbowAnalyzer::kFrameCount[] = {6, 16};
const int Rainbow::RainbowAnalyzer::kRainbowHeight[] = {21, 16};
const int Rainbow::RainbowAnalyzer::kRainbowOverlap[] = {13, 15};
const int Rainbow::RainbowAnalyzer::kSleepingHeight[] = {24, 33};
const int Rainbow::RainbowAnalyzer::kHeight[] = { 21, 33 };
const int Rainbow::RainbowAnalyzer::kWidth[] = { 34, 53 };
const int Rainbow::RainbowAnalyzer::kFrameCount[] = { 6, 16 };
const int Rainbow::RainbowAnalyzer::kRainbowHeight[] = { 21, 16 };
const int Rainbow::RainbowAnalyzer::kRainbowOverlap[] = { 13, 15 };
const int Rainbow::RainbowAnalyzer::kSleepingHeight[] = { 24, 33 };
const char *Rainbow::NyanCatAnalyzer::kName = "Nyanalyzer Cat";
const char *Rainbow::RainbowDashAnalyzer::kName = "Rainbow Dash";

View File

@@ -93,7 +93,7 @@ class RainbowAnalyzer : public Analyzer::Base {
private:
// "constants" that get initialized in the constructor
float band_scale_[kRainbowBands]{};
float band_scale_[kRainbowBands] {};
QPen colors_[kRainbowBands];
// Rainbow Nyancat & Dash
@@ -104,7 +104,7 @@ class RainbowAnalyzer : public Analyzer::Base {
int frame_;
// The y positions of each point on the rainbow.
float history_[kHistorySize * kRainbowBands]{};
float history_[kHistorySize * kRainbowBands] {};
// A cache of the last frame's rainbow,
// so it can be used in the next frame.
@@ -142,6 +142,6 @@ class RainbowDashAnalyzer : public RainbowAnalyzer {
static const char *kName;
};
}
} // namespace Rainbow
#endif // RAINBOWANALYZER_H

View File

@@ -47,10 +47,10 @@
#include "core/database.h"
#include "core/scopedtransaction.h"
#include "core/song.h"
#include "core/sqlrow.h"
#include "smartplaylists/smartplaylistsearch.h"
#include "directory.h"
#include "sqlrow.h"
#include "collectionbackend.h"
#include "collectionquery.h"
#include "collectiontask.h"
@@ -335,8 +335,8 @@ void CollectionBackend::AddDirectory(const QString &path) {
q.prepare(QString("INSERT INTO %1 (path, subdirs) VALUES (:path, 1)").arg(dirs_table_));
q.BindValue(":path", db_path);
if (!q.Exec()) {
db_->ReportErrors(q);
return;
db_->ReportErrors(q);
return;
}
Directory dir;
@@ -634,15 +634,13 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
added_songs << new_song;
continue;
}
}
// Create new song
int id = -1;
{ // Insert the row and create a new ID
{ // Insert the row and create a new ID
SqlQuery q(db);
q.prepare(QString("INSERT INTO %1 (" + Song::kColumnSpec + ") VALUES (" + Song::kBindSpec + ")").arg(songs_table_));
song.BindToQuery(&q);
@@ -656,7 +654,7 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
if (id == -1) return;
{ // Add to the FTS index
{ // Add to the FTS index
SqlQuery q(db);
q.prepare(QString("INSERT INTO %1 (ROWID, " + Song::kFtsColumnSpec + ") VALUES (:id, " + Song::kFtsBindSpec + ")").arg(fts_table_));
q.BindValue(":id", id);
@@ -1345,7 +1343,7 @@ void CollectionBackend::CompilationsNeedUpdating() {
if (album.isEmpty()) continue;
// Find the directory the song is in
QString directory = url.toString(QUrl::PreferLocalFile|QUrl::RemoveFilename);
QString directory = url.toString(QUrl::PreferLocalFile | QUrl::RemoveFilename);
CompilationInfo &info = compilation_info[directory + album];
info.urls << url;

View File

@@ -68,24 +68,23 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
QString available_fields = Song::kFtsColumns.join(", ").replace(QRegularExpression("\\bfts"), "");
ui_->search_field->setToolTip(
QString("<html><head/><body><p>") +
tr("Prefix a word with a field name to limit the search to that field, e.g.:") +
QString(" ") +
QString("<span style=\"font-weight:600;\">") +
tr("artist") +
QString(":") +
QString("</span><span style=\"font-style:italic;\">Strawbs</span>") +
QString(" ") +
tr("searches the collection for all artists that contain the word") +
QString(" Strawbs.") +
QString("</p><p><span style=\"font-weight:600;\">") +
tr("Available fields") +
QString(": ") +
"</span><span style=\"font-style:italic;\">" +
available_fields +
QString("</span>.") +
QString("</p></body></html>")
);
QString("<html><head/><body><p>") +
tr("Prefix a word with a field name to limit the search to that field, e.g.:") +
QString(" ") +
QString("<span style=\"font-weight:600;\">") +
tr("artist") +
QString(":") +
QString("</span><span style=\"font-style:italic;\">Strawbs</span>") +
QString(" ") +
tr("searches the collection for all artists that contain the word") +
QString(" Strawbs.") +
QString("</p><p><span style=\"font-weight:600;\">") +
tr("Available fields") +
QString(": ") +
"</span><span style=\"font-style:italic;\">" +
available_fields +
QString("</span>.") +
QString("</p></body></html>"));
QObject::connect(ui_->search_field, &QSearchField::returnPressed, this, &CollectionFilterWidget::ReturnPressed);
QObject::connect(filter_delay_, &QTimer::timeout, this, &CollectionFilterWidget::FilterDelayTimeout);
@@ -177,16 +176,15 @@ void CollectionFilterWidget::Init(CollectionModel *model) {
if (s.contains(group_by_version())) version = s.value(group_by_version(), 0).toInt();
if (version == 1) {
model_->SetGroupBy(CollectionModel::Grouping(
CollectionModel::GroupBy(s.value(group_by(1), static_cast<int>(CollectionModel::GroupBy_AlbumArtist)).toInt()),
CollectionModel::GroupBy(s.value(group_by(2), static_cast<int>(CollectionModel::GroupBy_AlbumDisc)).toInt()),
CollectionModel::GroupBy(s.value(group_by(3), static_cast<int>(CollectionModel::GroupBy_None)).toInt())));
CollectionModel::GroupBy(s.value(group_by(1), static_cast<int>(CollectionModel::GroupBy_AlbumArtist)).toInt()),
CollectionModel::GroupBy(s.value(group_by(2), static_cast<int>(CollectionModel::GroupBy_AlbumDisc)).toInt()),
CollectionModel::GroupBy(s.value(group_by(3), static_cast<int>(CollectionModel::GroupBy_None)).toInt())));
}
else {
model_->SetGroupBy(CollectionModel::Grouping(CollectionModel::GroupBy_AlbumArtist, CollectionModel::GroupBy_AlbumDisc, CollectionModel::GroupBy_None));
}
s.endGroup();
}
}
void CollectionFilterWidget::ReloadSettings() {

View File

@@ -100,7 +100,7 @@ void CollectionItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem
// Draw the line under the item
QColor line_color = opt.palette.color(QPalette::Text);
QLinearGradient grad_color(opt.rect.bottomLeft(), opt.rect.bottomRight());
const double fade_start_end = (opt.rect.width()/3.0)/opt.rect.width();
const double fade_start_end = (opt.rect.width() / 3.0) / opt.rect.width();
line_color.setAlphaF(0.0);
grad_color.setColorAt(0, line_color);
line_color.setAlphaF(0.5);

View File

@@ -59,12 +59,12 @@
#include "core/iconloader.h"
#include "core/logging.h"
#include "core/taskmanager.h"
#include "core/sqlrow.h"
#include "collectionquery.h"
#include "collectionbackend.h"
#include "collectiondirectorymodel.h"
#include "collectionitem.h"
#include "collectionmodel.h"
#include "sqlrow.h"
#include "playlist/playlistmanager.h"
#include "playlist/songmimedata.h"
#include "covermanager/albumcoverloader.h"
@@ -325,26 +325,32 @@ QString CollectionModel::ContainerKey(const GroupBy type, const Song &song) {
case GroupBy_Album:
key = TextOrUnknown(song.album());
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
break;
case GroupBy_AlbumDisc:
key = PrettyAlbumDisc(song.album(), song.disc());
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
break;
case GroupBy_YearAlbum:
key = PrettyYearAlbum(song.year(), song.album());
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
break;
case GroupBy_YearAlbumDisc:
key = PrettyYearAlbumDisc(song.year(), song.album(), song.disc());
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
break;
case GroupBy_OriginalYearAlbum:
key = PrettyYearAlbum(song.effective_originalyear(), song.album());
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
break;
case GroupBy_OriginalYearAlbumDisc:
key = PrettyYearAlbumDisc(song.effective_originalyear(), song.album(), song.disc());
if (!song.album_id().isEmpty()) key.append("-" + song.album_id());
if (!song.grouping().isEmpty()) key.append("-" + song.grouping());
break;
case GroupBy_Disc:
key = PrettyDisc(song.disc());
@@ -476,7 +482,7 @@ QString CollectionModel::DividerDisplayText(const GroupBy type, const QString &k
case GroupBy_Genre:
case GroupBy_FileType:
case GroupBy_Format:
if (key == "0") return "0-9";
if (key == "0") return "0-9";
return key.toUpper();
case GroupBy_YearAlbum:
@@ -1008,22 +1014,22 @@ void CollectionModel::InitQuery(const GroupBy type, CollectionQuery *q) {
q->SetColumnSpec("DISTINCT artist");
break;
case GroupBy_Album:
q->SetColumnSpec("DISTINCT album, album_id");
q->SetColumnSpec("DISTINCT album, album_id, grouping");
break;
case GroupBy_AlbumDisc:
q->SetColumnSpec("DISTINCT album, album_id, disc");
q->SetColumnSpec("DISTINCT album, album_id, disc, grouping");
break;
case GroupBy_YearAlbum:
q->SetColumnSpec("DISTINCT year, album, album_id, grouping");
break;
case GroupBy_YearAlbumDisc:
q->SetColumnSpec("DISTINCT year, album, album_id, disc");
q->SetColumnSpec("DISTINCT year, album, album_id, disc, grouping");
break;
case GroupBy_OriginalYearAlbum:
q->SetColumnSpec("DISTINCT year, originalyear, album, album_id, grouping");
break;
case GroupBy_OriginalYearAlbumDisc:
q->SetColumnSpec("DISTINCT year, originalyear, album, album_id, disc");
q->SetColumnSpec("DISTINCT year, originalyear, album, album_id, disc, grouping");
break;
case GroupBy_Disc:
q->SetColumnSpec("DISTINCT disc");
@@ -1097,11 +1103,13 @@ void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, Coll
case GroupBy_Album:
q->AddWhere("album", item->metadata.album());
q->AddWhere("album_id", item->metadata.album_id());
q->AddWhere("grouping", item->metadata.grouping());
break;
case GroupBy_AlbumDisc:
q->AddWhere("album", item->metadata.album());
q->AddWhere("album_id", item->metadata.album_id());
q->AddWhere("disc", item->metadata.disc());
q->AddWhere("grouping", item->metadata.grouping());
break;
case GroupBy_YearAlbum:
q->AddWhere("year", item->metadata.year());
@@ -1114,6 +1122,7 @@ void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, Coll
q->AddWhere("album", item->metadata.album());
q->AddWhere("album_id", item->metadata.album_id());
q->AddWhere("disc", item->metadata.disc());
q->AddWhere("grouping", item->metadata.grouping());
break;
case GroupBy_OriginalYearAlbum:
q->AddWhere("year", item->metadata.year());
@@ -1128,6 +1137,7 @@ void CollectionModel::FilterQuery(const GroupBy type, CollectionItem *item, Coll
q->AddWhere("album", item->metadata.album());
q->AddWhere("album_id", item->metadata.album_id());
q->AddWhere("disc", item->metadata.disc());
q->AddWhere("grouping", item->metadata.grouping());
break;
case GroupBy_Disc:
q->AddWhere("disc", item->metadata.disc());
@@ -1216,6 +1226,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
case GroupBy_Album:{
item->metadata.set_album(row.value(0).toString());
item->metadata.set_album_id(row.value(1).toString());
item->metadata.set_grouping(row.value(2).toString());
item->key.append(ContainerKey(type, item->metadata));
item->display_text = TextOrUnknown(item->metadata.album());
item->sort_text = SortTextForArtist(item->metadata.album());
@@ -1225,6 +1236,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
item->metadata.set_album(row.value(0).toString());
item->metadata.set_album_id(row.value(1).toString());
item->metadata.set_disc(row.value(2).toInt());
item->metadata.set_grouping(row.value(3).toString());
item->key.append(ContainerKey(type, item->metadata));
item->display_text = PrettyAlbumDisc(item->metadata.album(), item->metadata.disc());
item->sort_text = item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
@@ -1245,6 +1257,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
item->metadata.set_album(row.value(1).toString());
item->metadata.set_album_id(row.value(2).toString());
item->metadata.set_disc(row.value(3).toInt());
item->metadata.set_grouping(row.value(4).toString());
item->key.append(ContainerKey(type, item->metadata));
item->display_text = PrettyYearAlbumDisc(item->metadata.year(), item->metadata.album(), item->metadata.disc());
item->sort_text = SortTextForNumber(qMax(0, item->metadata.year())) + item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
@@ -1267,6 +1280,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy type, const bool si
item->metadata.set_album(row.value(2).toString());
item->metadata.set_album_id(row.value(3).toString());
item->metadata.set_disc(row.value(4).toInt());
item->metadata.set_grouping(row.value(5).toString());
item->key.append(ContainerKey(type, item->metadata));
item->display_text = PrettyYearAlbumDisc(item->metadata.effective_originalyear(), item->metadata.album(), item->metadata.disc());
item->sort_text = SortTextForNumber(qMax(0, item->metadata.effective_originalyear())) + item->metadata.album() + SortTextForNumber(qMax(0, item->metadata.disc()));
@@ -1411,6 +1425,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
case GroupBy_Album:{
item->metadata.set_album(s.album());
item->metadata.set_album_id(s.album_id());
item->metadata.set_grouping(s.grouping());
item->key.append(ContainerKey(type, s));
item->display_text = TextOrUnknown(s.album());
item->sort_text = SortTextForArtist(s.album());
@@ -1420,6 +1435,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
item->metadata.set_album(s.album());
item->metadata.set_album_id(s.album_id());
item->metadata.set_disc(s.disc());
item->metadata.set_grouping(s.grouping());
item->key.append(ContainerKey(type, s));
item->display_text = PrettyAlbumDisc(s.album(), s.disc());
item->sort_text = s.album() + SortTextForNumber(qMax(0, s.disc()));
@@ -1440,6 +1456,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy type, const bool sig
item->metadata.set_album(s.album());
item->metadata.set_album_id(s.album_id());
item->metadata.set_disc(s.disc());
item->metadata.set_grouping(s.grouping());
item->key.append(ContainerKey(type, s));
item->display_text = PrettyYearAlbumDisc(s.year(), s.album(), s.disc());
item->sort_text = SortTextForNumber(qMax(0, s.year())) + s.album() + SortTextForNumber(qMax(0, s.disc()));

View File

@@ -45,10 +45,10 @@
#include "core/simpletreemodel.h"
#include "core/song.h"
#include "core/sqlrow.h"
#include "covermanager/albumcoverloader.h"
#include "collectionquery.h"
#include "collectionitem.h"
#include "sqlrow.h"
#include "covermanager/albumcoverloaderoptions.h"
class QSettings;

View File

@@ -155,11 +155,11 @@ void CollectionQuery::AddWhere(const QString &column, const QVariant &value, con
}
else if (
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
value.metaType().id() == QMetaType::QString
value.metaType().id() == QMetaType::QString
#else
value.type() == QVariant::String
value.type() == QVariant::String
#endif
&& value.toString().isNull()) {
&& value.toString().isNull()) {
where_clauses_ << QString("%1 %2 ?").arg(column, op);
bound_values_ << QString("");
}

View File

@@ -125,4 +125,4 @@ class CollectionQuery : public QSqlQuery {
int limit_;
};
#endif // COLLECTIONQUERY_H
#endif // COLLECTIONQUERY_H

View File

@@ -82,6 +82,7 @@ CollectionWatcher::CollectionWatcher(Song::Source source, QObject *parent)
song_tracking_(false),
mark_songs_unavailable_(source_ == Song::Source_Collection),
expire_unavailable_songs_days_(60),
overwrite_playcount_(false),
overwrite_rating_(false),
stop_requested_(false),
abort_requested_(false),
@@ -153,6 +154,7 @@ void CollectionWatcher::ReloadSettings() {
mark_songs_unavailable_ = false;
}
expire_unavailable_songs_days_ = s.value("expire_unavailable_songs", 60).toInt();
overwrite_playcount_ = s.value("overwrite_playcount", false).toBool();
overwrite_rating_ = s.value("overwrite_rating", false).toBool();
s.endGroup();
@@ -734,7 +736,7 @@ void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file,
const Song matching_cue_song = sections_map[new_cue_song.beginning_nanosec()];
new_cue_song.set_id(matching_cue_song.id());
if (!new_cue_song.has_embedded_cover()) new_cue_song.set_art_automatic(image);
new_cue_song.MergeUserSetData(matching_cue_song, true);
new_cue_song.MergeUserSetData(matching_cue_song, true, true);
AddChangedSong(file, matching_cue_song, new_cue_song, t);
used_ids.insert(matching_cue_song.id());
}
@@ -777,7 +779,7 @@ void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file,
song_on_disk.set_id(matching_song.id());
song_on_disk.set_fingerprint(fingerprint);
if (!song_on_disk.has_embedded_cover()) song_on_disk.set_art_automatic(image);
song_on_disk.MergeUserSetData(matching_song, !overwrite_rating_);
song_on_disk.MergeUserSetData(matching_song, !overwrite_playcount_, !overwrite_rating_);
AddChangedSong(file, matching_song, song_on_disk, t);
}

View File

@@ -218,6 +218,7 @@ class CollectionWatcher : public QObject {
bool song_tracking_;
bool mark_songs_unavailable_;
int expire_unavailable_songs_days_;
bool overwrite_playcount_;
bool overwrite_rating_;
bool stop_requested_;

View File

@@ -1,6 +1,6 @@
/*
* Strawberry Music Player
* Copyright 2020-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2020-2022, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -43,7 +43,7 @@
#include "contextview.h"
#include "contextalbum.h"
const int ContextAlbum::kWidgetSpacing = 40;
const int ContextAlbum::kFadeTimeLineMs = 1000;
ContextAlbum::ContextAlbum(QWidget *parent)
: QWidget(parent),
@@ -51,23 +51,26 @@ ContextAlbum::ContextAlbum(QWidget *parent)
context_view_(nullptr),
album_cover_choice_controller_(nullptr),
downloading_covers_(false),
timeline_fade_(new QTimeLine(1000, this)),
timeline_fade_(new QTimeLine(kFadeTimeLineMs, this)),
image_strawberry_(":/pictures/strawberry.png"),
image_original_(image_strawberry_),
pixmap_previous_opacity_(0),
prev_width_(width()) {
pixmap_current_opacity_(1.0) {
setObjectName("context-widget-album");
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
cover_loader_options_.desired_height_ = 600;
cover_loader_options_.desired_height_ = width();
cover_loader_options_.pad_output_image_ = true;
cover_loader_options_.scale_output_image_ = true;
QImage image = ImageUtils::ScaleAndPad(image_strawberry_, cover_loader_options_.scale_output_image_, cover_loader_options_.pad_output_image_, cover_loader_options_.desired_height_);
if (!image.isNull()) pixmap_current_ = QPixmap::fromImage(image);
if (!image.isNull()) {
pixmap_current_ = QPixmap::fromImage(image);
}
QObject::connect(timeline_fade_, &QTimeLine::valueChanged, this, &ContextAlbum::FadePreviousTrack);
timeline_fade_->setDirection(QTimeLine::Backward); // 1.0 -> 0.0
timeline_fade_->setDirection(QTimeLine::Forward);
QObject::connect(timeline_fade_, &QTimeLine::valueChanged, this, &ContextAlbum::FadeCurrentCover);
QObject::connect(timeline_fade_, &QTimeLine::finished, this, &ContextAlbum::FadeCurrentCoverFinished);
}
@@ -86,8 +89,21 @@ void ContextAlbum::Init(ContextView *context_view, AlbumCoverChoiceController *a
}
void ContextAlbum::contextMenuEvent(QContextMenuEvent *e) {
if (menu_ && image_original_ != image_strawberry_) menu_->popup(mapToGlobal(e->pos()));
QSize ContextAlbum::sizeHint() const {
return QSize(pixmap_current_.width(), pixmap_current_.height());
}
void ContextAlbum::paintEvent(QPaintEvent*) {
QPainter p(this);
p.setRenderHint(QPainter::SmoothPixmapTransform);
DrawPreviousCovers(&p);
DrawImage(&p, pixmap_current_, pixmap_current_opacity_);
DrawSpinner(&p);
p.end();
}
void ContextAlbum::mouseDoubleClickEvent(QMouseEvent *e) {
@@ -99,93 +115,146 @@ void ContextAlbum::mouseDoubleClickEvent(QMouseEvent *e) {
}
void ContextAlbum::paintEvent(QPaintEvent*) {
void ContextAlbum::contextMenuEvent(QContextMenuEvent *e) {
QPainter p(this);
DrawImage(&p);
// Draw the previous track's image if we're fading
if (!pixmap_previous_.isNull()) {
p.setOpacity(pixmap_previous_opacity_);
p.drawPixmap(0, 0, pixmap_previous_);
if (menu_ && image_original_ != image_strawberry_) {
menu_->popup(mapToGlobal(e->pos()));
}
else {
QWidget::contextMenuEvent(e);
}
}
void ContextAlbum::DrawImage(QPainter *p) {
p->setRenderHint(QPainter::SmoothPixmapTransform);
void ContextAlbum::UpdateWidth(const int new_width) {
if (width() != prev_width_) {
cover_loader_options_.desired_height_ = width() - kWidgetSpacing;
QImage image = ImageUtils::ScaleAndPad(image_original_, cover_loader_options_.scale_output_image_, cover_loader_options_.pad_output_image_, cover_loader_options_.desired_height_);
if (image.isNull()) pixmap_current_ = QPixmap();
else pixmap_current_ = QPixmap::fromImage(image);
prev_width_ = width();
if (new_width != cover_loader_options_.desired_height_) {
cover_loader_options_.desired_height_ = new_width;
ScaleCover();
ScalePreviousCovers();
updateGeometry();
}
p->drawPixmap(0, 0, width() - kWidgetSpacing, width() - kWidgetSpacing, pixmap_current_);
if (downloading_covers_ && spinner_animation_) {
p->drawPixmap(50, 50, 16, 16, spinner_animation_->currentPixmap());
}
}
void ContextAlbum::FadePreviousTrack(const qreal value) {
pixmap_previous_opacity_ = value;
if (qFuzzyCompare(pixmap_previous_opacity_, qreal(0.0))) {
image_previous_ = QImage();
pixmap_previous_ = QPixmap();
}
update();
if (value == 0 && image_original_ == image_strawberry_) {
emit FadeStopFinished();
}
}
void ContextAlbum::ScaleCover() {
cover_loader_options_.desired_height_ = width() - kWidgetSpacing;
QImage image = ImageUtils::ScaleAndPad(image_original_, cover_loader_options_.scale_output_image_, cover_loader_options_.pad_output_image_, cover_loader_options_.desired_height_);
if (image.isNull()) pixmap_current_ = QPixmap();
else pixmap_current_ = QPixmap::fromImage(image);
prev_width_ = width();
update();
}
void ContextAlbum::SetImage(QImage image) {
if (image.isNull()) image = image_strawberry_;
if (image.isNull()) {
image = image_strawberry_;
}
if (downloading_covers_) {
downloading_covers_ = false;
spinner_animation_.reset();
}
// Cache the current pixmap so we can fade between them
pixmap_previous_ = QPixmap(width() - kWidgetSpacing, width() - kWidgetSpacing);
pixmap_previous_.fill(palette().window().color());
pixmap_previous_opacity_ = 1.0;
QImage image_previous = image_original_;
QPixmap pixmap_previous = pixmap_current_;
qreal opacity_previous = pixmap_current_opacity_;
QPainter p(&pixmap_previous_);
DrawImage(&p);
p.end();
image_previous_ = image_original_;
image_original_ = image;
pixmap_current_opacity_ = 0.0;
ScaleCover();
// Were we waiting for this cover to load before we started fading?
if (!pixmap_previous_.isNull() && timeline_fade_) {
if (!pixmap_previous.isNull()) {
std::shared_ptr<PreviousCover> previous_cover = std::make_shared<PreviousCover>();
previous_cover->image = image_previous;
previous_cover->pixmap = pixmap_previous;
previous_cover->opacity = opacity_previous;
previous_cover->timeline.reset(new QTimeLine(kFadeTimeLineMs), [](QTimeLine *timeline) { timeline->deleteLater(); });
previous_cover->timeline->setDirection(QTimeLine::Backward);
previous_cover->timeline->setCurrentTime(timeline_fade_->state() == QTimeLine::Running ? timeline_fade_->currentTime() : kFadeTimeLineMs);
QObject::connect(previous_cover->timeline.get(), &QTimeLine::valueChanged, this, [this, previous_cover]() { FadePreviousCover(previous_cover); });
QObject::connect(previous_cover->timeline.get(), &QTimeLine::finished, this, [this, previous_cover]() { FadePreviousCoverFinished(previous_cover); });
previous_covers_ << previous_cover;
previous_cover->timeline->start();
}
if (timeline_fade_->state() == QTimeLine::Running) {
timeline_fade_->stop();
timeline_fade_->setDirection(QTimeLine::Backward); // 1.0 -> 0.0
timeline_fade_->start();
}
timeline_fade_->start();
}
void ContextAlbum::DrawImage(QPainter *p, const QPixmap &pixmap, const qreal opacity) {
if (qFuzzyCompare(opacity, qreal(0.0))) return;
p->setOpacity(opacity);
p->drawPixmap(0, 0, pixmap.width(), pixmap.height(), pixmap);
}
void ContextAlbum::DrawSpinner(QPainter *p) {
if (downloading_covers_) {
p->drawPixmap(50, 50, 16, 16, spinner_animation_->currentPixmap());
}
}
void ContextAlbum::DrawPreviousCovers(QPainter *p) {
for (std::shared_ptr<PreviousCover> previous_cover : previous_covers_) {
DrawImage(p, previous_cover->pixmap, previous_cover->opacity);
}
}
void ContextAlbum::FadeCurrentCover(const qreal value) {
if (value <= pixmap_current_opacity_) return;
pixmap_current_opacity_ = value;
update();
}
void ContextAlbum::FadeCurrentCoverFinished() {
if (image_original_ == image_strawberry_) {
emit FadeStopFinished();
}
}
void ContextAlbum::FadePreviousCover(std::shared_ptr<PreviousCover> previous_cover) {
if (previous_cover->timeline->currentValue() >= previous_cover->opacity) return;
previous_cover->opacity = previous_cover->timeline->currentValue();
}
void ContextAlbum::FadePreviousCoverFinished(std::shared_ptr<PreviousCover> previous_cover) {
previous_covers_.removeAll(previous_cover);
}
void ContextAlbum::ScaleCover() {
QImage image = ImageUtils::ScaleAndPad(image_original_, cover_loader_options_.scale_output_image_, cover_loader_options_.pad_output_image_, cover_loader_options_.desired_height_);
if (image.isNull()) {
pixmap_current_ = QPixmap();
}
else {
pixmap_current_ = QPixmap::fromImage(image);
}
}
void ContextAlbum::ScalePreviousCovers() {
for (std::shared_ptr<PreviousCover> previous_cover : previous_covers_) {
QImage image = ImageUtils::ScaleAndPad(previous_cover->image, cover_loader_options_.scale_output_image_, cover_loader_options_.pad_output_image_, cover_loader_options_.desired_height_);
if (image.isNull()) {
previous_cover->pixmap = QPixmap();
}
else {
previous_cover->pixmap = QPixmap::fromImage(image);
}
}
}

View File

@@ -1,6 +1,6 @@
/*
* Strawberry Music Player
* Copyright 2020-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2020-2022, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -27,6 +27,7 @@
#include <QtGlobal>
#include <QObject>
#include <QWidget>
#include <QList>
#include <QString>
#include <QImage>
#include <QPixmap>
@@ -50,15 +51,31 @@ class ContextAlbum : public QWidget {
void Init(ContextView *context_view, AlbumCoverChoiceController *album_cover_choice_controller);
void SetImage(QImage image = QImage());
void UpdateWidth(const int width);
protected:
QSize sizeHint() const override;
void paintEvent(QPaintEvent*) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void mouseDoubleClickEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
private:
void DrawImage(QPainter *p);
struct PreviousCover {
PreviousCover() : opacity(0.0) {}
QImage image;
QPixmap pixmap;
qreal opacity;
std::shared_ptr<QTimeLine> timeline;
};
QList<std::shared_ptr<PreviousCover>> previous_covers_;
void DrawImage(QPainter *p, const QPixmap &pixmap, const qreal opacity);
void DrawSpinner(QPainter *p);
void DrawPreviousCovers(QPainter *p);
void ScaleCover();
void ScalePreviousCovers();
void GetCoverAutomatically();
signals:
@@ -67,13 +84,16 @@ class ContextAlbum : public QWidget {
private slots:
void Update() { update(); }
void AutomaticCoverSearchDone();
void FadePreviousTrack(const qreal value);
void FadeCurrentCover(const qreal value);
void FadeCurrentCoverFinished();
void FadePreviousCover(std::shared_ptr<PreviousCover> previouscover);
void FadePreviousCoverFinished(std::shared_ptr<PreviousCover> previouscover);
public slots:
void SearchCoverInProgress();
private:
static const int kWidgetSpacing;
static const int kFadeTimeLineMs;
private:
QMenu *menu_;
@@ -84,12 +104,9 @@ class ContextAlbum : public QWidget {
QTimeLine *timeline_fade_;
QImage image_strawberry_;
QImage image_original_;
QImage image_previous_;
QPixmap pixmap_current_;
QPixmap pixmap_previous_;
qreal pixmap_previous_opacity_;
qreal pixmap_current_opacity_;
std::unique_ptr<QMovie> spinner_animation_;
int prev_width_;
};
#endif // CONTEXTALBUM_H

View File

@@ -1,390 +0,0 @@
/*
* Strawberry Music Player
* This code was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <functional>
#include <algorithm>
#include <QObject>
#include <QtGlobal>
#include <QMutex>
#include <QMimeData>
#include <QMetaType>
#include <QVariant>
#include <QList>
#include <QSet>
#include <QRegularExpression>
#include <QString>
#include <QStringList>
#include <QUrl>
#include <QImage>
#include <QPixmapCache>
#include "core/application.h"
#include "core/database.h"
#include "core/iconloader.h"
#include "collection/collectionquery.h"
#include "collection/collectionbackend.h"
#include "collection/collectionmodel.h"
#include "collection/collectionitem.h"
#include "playlist/playlistmanager.h"
#include "playlist/songmimedata.h"
#include "covermanager/albumcoverloader.h"
#include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h"
#include "contextalbumsmodel.h"
const int ContextAlbumsModel::kPrettyCoverSize = 32;
ContextAlbumsModel::ContextAlbumsModel(CollectionBackend *backend, Application *app, QObject *parent)
: SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent),
backend_(backend),
app_(app),
album_icon_(IconLoader::Load("cdcase")) {
root_->lazy_loaded = true;
cover_loader_options_.get_image_data_ = false;
cover_loader_options_.scale_output_image_ = true;
cover_loader_options_.pad_output_image_ = true;
cover_loader_options_.desired_height_ = kPrettyCoverSize;
QObject::connect(app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &ContextAlbumsModel::AlbumCoverLoaded);
QIcon nocover = IconLoader::Load("cdcase");
QList<QSize> nocover_sizes = nocover.availableSizes();
no_cover_icon_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
ContextAlbumsModel::~ContextAlbumsModel() { delete root_; }
void ContextAlbumsModel::AddSongs(const SongList &songs) {
for (const Song &song : songs) {
if (song_nodes_.contains(song.id())) continue;
QString key = CollectionModel::ContainerKey(CollectionModel::GroupBy_Album, song);
CollectionItem *container = nullptr;
if (container_nodes_.contains(key)) {
container = container_nodes_[key];
}
else {
container = ItemFromSong(CollectionItem::Type_Container, true, root_, song, 0);
container_nodes_.insert(key, container);
}
song_nodes_[song.id()] = ItemFromSong(CollectionItem::Type_Song, true, container, song, -1);
}
}
QString ContextAlbumsModel::AlbumIconPixmapCacheKey(const QModelIndex &idx) {
QStringList path;
QModelIndex index_copy(idx);
while (index_copy.isValid()) {
path.prepend(index_copy.data().toString());
index_copy = index_copy.parent();
}
return "contextalbumsart:" + path.join("/");
}
QVariant ContextAlbumsModel::AlbumIcon(const QModelIndex &idx) {
CollectionItem *item = IndexToItem(idx);
if (!item) return no_cover_icon_;
// Check the cache for a pixmap we already loaded.
const QString cache_key = AlbumIconPixmapCacheKey(idx);
QPixmap cached_pixmap;
if (QPixmapCache::find(cache_key, &cached_pixmap)) {
return cached_pixmap;
}
// Maybe we're loading a pixmap already?
if (pending_cache_keys_.contains(cache_key)) {
return no_cover_icon_;
}
// No art is cached and we're not loading it already. Load art for the first song in the album.
SongList songs = GetChildSongs(idx);
if (!songs.isEmpty()) {
const quint64 id = app_->album_cover_loader()->LoadImageAsync(cover_loader_options_, songs.first());
pending_art_.insert(id, ItemAndCacheKey(item, cache_key));
pending_cache_keys_.insert(cache_key);
}
return no_cover_icon_;
}
void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result) {
if (!pending_art_.contains(id)) return;
ItemAndCacheKey item_and_cache_key = pending_art_.take(id);
CollectionItem *item = item_and_cache_key.first;
if (!item) return;
const QString &cache_key = item_and_cache_key.second;
if (pending_cache_keys_.contains(cache_key)) {
pending_cache_keys_.remove(cache_key);
}
// Insert this image in the cache.
if (!result.success || result.image_scaled.isNull() || result.type == AlbumCoverLoaderResult::Type_ManuallyUnset) {
// Set the no_cover image so we don't continually try to load art.
QPixmapCache::insert(cache_key, no_cover_icon_);
}
else {
QPixmap image_pixmap;
image_pixmap = QPixmap::fromImage(result.image_scaled);
QPixmapCache::insert(cache_key, image_pixmap);
}
const QModelIndex idx = ItemToIndex(item);
emit dataChanged(idx, idx);
}
QVariant ContextAlbumsModel::data(const QModelIndex &idx, int role) const {
const CollectionItem *item = IndexToItem(idx);
if (role == Qt::DecorationRole && item->type == CollectionItem::Type_Container && item->container_level == 0) {
return const_cast<ContextAlbumsModel*>(this)->AlbumIcon(idx);
}
return data(item, role);
}
QVariant ContextAlbumsModel::data(const CollectionItem *item, int role) const {
switch (role) {
case Qt::DisplayRole:
case Qt::ToolTipRole:
return item->DisplayText();
case Qt::DecorationRole:
switch (item->type) {
case CollectionItem::Type_Container:
if (item->type == CollectionItem::Type_Container && item->container_level == 0) { return album_icon_; }
break;
default:
break;
}
break;
case Role_Type:
return item->type;
case Role_ContainerType:
return item->type;
case Role_Key:
return item->key;
case Role_Artist:
return item->metadata.artist();
case Role_Editable:
if (item->type == CollectionItem::Type_Container) {
// if we have even one non editable item as a child, we ourselves are not available for edit
if (!item->children.isEmpty()) {
for (CollectionItem *child : item->children) {
if (!data(child, role).toBool()) {
return false;
}
}
return true;
}
else {
return false;
}
}
else if (item->type == CollectionItem::Type_Song) {
return item->metadata.IsEditable();
}
else {
return false;
}
case Role_SortText:
return item->SortText();
default:
return QVariant();
}
return QVariant();
}
void ContextAlbumsModel::Reset() {
for (QMap<QString, CollectionItem*>::const_iterator it = container_nodes_.constBegin(); it != container_nodes_.constEnd(); ++it) {
const QString cache_key = AlbumIconPixmapCacheKey(ItemToIndex(it.value()));
QPixmapCache::remove(cache_key);
}
beginResetModel();
delete root_;
song_nodes_.clear();
container_nodes_.clear();
pending_art_.clear();
pending_cache_keys_.clear();
root_ = new CollectionItem(this);
root_->lazy_loaded = true;
endResetModel();
}
CollectionItem *ContextAlbumsModel::ItemFromSong(CollectionItem::Type item_type, const bool signal, CollectionItem *parent, const Song &s, const int container_level) {
if (signal) beginInsertRows(ItemToIndex(parent), static_cast<int>(parent->children.count()), static_cast<int>(parent->children.count()));
CollectionItem *item = new CollectionItem(item_type, parent);
item->container_level = container_level;
item->lazy_loaded = true;
if (item_type == CollectionItem::Type_Container) {
item->key = CollectionModel::ContainerKey(CollectionModel::GroupBy_Album, s);
item->display_text = CollectionModel::TextOrUnknown(s.album());
item->sort_text = CollectionModel::SortTextForArtist(s.album());
}
else {
item->key = s.album() + " " + s.title();
item->display_text = CollectionModel::TextOrUnknown(s.title());
item->sort_text = CollectionModel::SortTextForSong(s);
item->metadata = s;
}
if (signal) endInsertRows();
return item;
}
Qt::ItemFlags ContextAlbumsModel::flags(const QModelIndex &idx) const {
switch (IndexToItem(idx)->type) {
case CollectionItem::Type_Song:
case CollectionItem::Type_Container:
return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsDragEnabled;
case CollectionItem::Type_Root:
case CollectionItem::Type_LoadingIndicator:
default:
return Qt::ItemIsEnabled;
}
}
QStringList ContextAlbumsModel::mimeTypes() const {
return QStringList() << "text/uri-list";
}
QMimeData *ContextAlbumsModel::mimeData(const QModelIndexList &indexes) const {
if (indexes.isEmpty()) return nullptr;
SongMimeData *data = new SongMimeData;
QList<QUrl> urls;
QSet<int> song_ids;
data->backend = backend_;
for (const QModelIndex &idx : indexes) {
GetChildSongs(IndexToItem(idx), &urls, &data->songs, &song_ids);
}
data->setUrls(urls);
data->name_for_new_playlist_ = PlaylistManager::GetNameForNewPlaylist(data->songs);
return data;
}
bool ContextAlbumsModel::CompareItems(const CollectionItem *a, const CollectionItem *b) const {
QVariant left(data(a, ContextAlbumsModel::Role_SortText));
QVariant right(data(b, ContextAlbumsModel::Role_SortText));
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (left.metaType().id() == QMetaType::Int)
#else
if (left.type() == QVariant::Int)
#endif
return left.toInt() < right.toInt();
else return left.toString() < right.toString();
}
void ContextAlbumsModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls, SongList *songs, QSet<int> *song_ids) const {
switch (item->type) {
case CollectionItem::Type_Container:{
QList<CollectionItem*> children = item->children;
std::sort(children.begin(), children.end(), std::bind(&ContextAlbumsModel::CompareItems, this, std::placeholders::_1, std::placeholders::_2));
for (CollectionItem *child : children) {
GetChildSongs(child, urls, songs, song_ids);
}
break;
}
case CollectionItem::Type_Song:
urls->append(item->metadata.url());
if (!song_ids->contains(item->metadata.id())) {
songs->append(item->metadata);
song_ids->insert(item->metadata.id());
}
break;
default:
break;
}
}
SongList ContextAlbumsModel::GetChildSongs(const QModelIndexList &indexes) const {
QList<QUrl> dontcare;
SongList ret;
QSet<int> song_ids;
for (const QModelIndex &idx : indexes) {
GetChildSongs(IndexToItem(idx), &dontcare, &ret, &song_ids);
}
return ret;
}
SongList ContextAlbumsModel::GetChildSongs(const QModelIndex &idx) const {
return GetChildSongs(QModelIndexList() << idx);
}

View File

@@ -1,111 +0,0 @@
/*
* Strawberry Music Player
* This code was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONTEXTALBUMSMODEL_H
#define CONTEXTALBUMSMODEL_H
#include "config.h"
#include <QtGlobal>
#include <QObject>
#include <QAbstractItemModel>
#include <QPair>
#include <QSet>
#include <QList>
#include <QMap>
#include <QVariant>
#include <QString>
#include <QStringList>
#include <QUrl>
#include <QImage>
#include <QPixmap>
#include <QIcon>
#include "core/simpletreemodel.h"
#include "core/song.h"
#include "collection/collectionquery.h"
#include "collection/collectionitem.h"
#include "covermanager/albumcoverloaderoptions.h"
#include "covermanager/albumcoverloaderresult.h"
class QMimeData;
class Application;
class CollectionBackend;
class CollectionItem;
class ContextAlbumsModel : public SimpleTreeModel<CollectionItem> {
Q_OBJECT
public:
explicit ContextAlbumsModel(CollectionBackend *backend, Application *app, QObject *parent = nullptr);
~ContextAlbumsModel() override;
static const int kPrettyCoverSize;
enum Role {
Role_Type = Qt::UserRole + 1,
Role_ContainerType,
Role_SortText,
Role_Key,
Role_Artist,
Role_Editable,
LastRole
};
void GetChildSongs(CollectionItem *item, QList<QUrl> *urls, SongList *songs, QSet<int> *song_ids) const;
SongList GetChildSongs(const QModelIndex &idx) const;
SongList GetChildSongs(const QModelIndexList &indexes) const;
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const override;
Qt::ItemFlags flags(const QModelIndex &idx) const override;
QStringList mimeTypes() const override;
QMimeData *mimeData(const QModelIndexList &indexes) const override;
void Reset();
void AddSongs(const SongList &songs);
private slots:
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result);
private:
CollectionItem *ItemFromSong(CollectionItem::Type item_type, const bool signal, CollectionItem *parent, const Song &s, const int container_level);
static QString AlbumIconPixmapCacheKey(const QModelIndex &idx);
QVariant AlbumIcon(const QModelIndex &idx);
QVariant data(const CollectionItem *item, int role) const;
bool CompareItems(const CollectionItem *a, const CollectionItem *b) const;
private:
CollectionBackend *backend_;
Application *app_;
QueryOptions query_options_;
QMap<QString, CollectionItem*> container_nodes_;
QMap<int, CollectionItem*> song_nodes_;
QIcon album_icon_;
QPixmap no_cover_icon_;
AlbumCoverLoaderOptions cover_loader_options_;
typedef QPair<CollectionItem*, QString> ItemAndCacheKey;
QMap<quint64, ItemAndCacheKey> pending_art_;
QSet<QString> pending_cache_keys_;
};
#endif // CONTEXTALBUMSMODEL_H

View File

@@ -1,434 +0,0 @@
/*
* Strawberry Music Player
* This code was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "config.h"
#include <memory>
#include <qcoreevent.h>
#include <QtGlobal>
#include <QTreeView>
#include <QItemSelectionModel>
#include <QSortFilterProxyModel>
#include <QAbstractItemView>
#include <QStyleOptionViewItem>
#include <QAbstractScrollArea>
#include <QMimeData>
#include <QList>
#include <QVariant>
#include <QString>
#include <QUrl>
#include <QLocale>
#include <QMessageBox>
#include <QMenu>
#include <QAction>
#include <QRect>
#include <QSize>
#include <QToolTip>
#include <QWhatsThis>
#include "core/application.h"
#include "core/iconloader.h"
#include "core/mimedata.h"
#include "core/utilities.h"
#include "collection/collectiondirectorymodel.h"
#include "collection/collectionmodel.h"
#include "collection/collectionitem.h"
#ifndef Q_OS_WIN
# include "device/devicemanager.h"
# include "device/devicestatefiltermodel.h"
#endif
#include "dialogs/edittagdialog.h"
#include "organize/organizedialog.h"
#include "contextalbumsmodel.h"
#include "contextalbumsview.h"
ContextItemDelegate::ContextItemDelegate(QObject *parent) : QStyledItemDelegate(parent) {}
bool ContextItemDelegate::helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &idx) {
return true;
Q_UNUSED(option);
if (!event || !view) return false;
QString text = displayText(idx.data(), QLocale::system());
if (text.isEmpty() || !event) return false;
switch (event->type()) {
case QEvent::ToolTip: {
QSize real_text = sizeHint(option, idx);
QRect displayed_text = view->visualRect(idx);
bool is_elided = displayed_text.width() < real_text.width();
if (is_elided) {
QToolTip::showText(event->globalPos(), text, view);
}
else if (idx.data(Qt::ToolTipRole).isValid()) {
// If the item has a tooltip text, display it
QString tooltip_text = idx.data(Qt::ToolTipRole).toString();
QToolTip::showText(event->globalPos(), tooltip_text, view);
}
else {
// in case that another text was previously displayed
QToolTip::hideText();
}
return true;
}
case QEvent::QueryWhatsThis:
return true;
case QEvent::WhatsThis:
QWhatsThis::showText(event->globalPos(), text, view);
return true;
default:
break;
}
return false;
}
ContextAlbumsView::ContextAlbumsView(QWidget *parent)
: AutoExpandingTreeView(parent),
app_(nullptr),
context_menu_(nullptr),
load_(nullptr),
add_to_playlist_(nullptr),
add_to_playlist_enqueue_(nullptr),
open_in_new_playlist_(nullptr),
organize_(nullptr),
#ifndef Q_OS_WIN
copy_to_device_(nullptr),
#endif
edit_track_(nullptr),
edit_tracks_(nullptr),
show_in_browser_(nullptr),
is_in_keyboard_search_(false),
model_(nullptr) {
setStyleSheet("border: none;");
setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
setItemDelegate(new ContextItemDelegate(this));
setAttribute(Qt::WA_MacShowFocusRect, false);
setHeaderHidden(true);
setAllColumnsShowFocus(true);
setDragEnabled(true);
setDragDropMode(QAbstractItemView::DragOnly);
setSelectionMode(QAbstractItemView::ExtendedSelection);
SetAddOnDoubleClick(false);
}
ContextAlbumsView::~ContextAlbumsView() = default;
void ContextAlbumsView::SaveFocus() {
QModelIndex current = currentIndex();
QVariant type = model()->data(current, ContextAlbumsModel::Role_Type);
if (!type.isValid() || !(type.toInt() == CollectionItem::Type_Song || type.toInt() == CollectionItem::Type_Container || type.toInt() == CollectionItem::Type_Divider)) {
return;
}
last_selected_path_.clear();
last_selected_song_ = Song();
last_selected_container_ = QString();
switch (type.toInt()) {
case CollectionItem::Type_Song: {
QModelIndex index = current;
SongList songs = model_->GetChildSongs(index);
if (!songs.isEmpty()) {
last_selected_song_ = songs.last();
}
break;
}
case CollectionItem::Type_Container:
case CollectionItem::Type_Divider: {
break;
}
default:
return;
}
SaveContainerPath(current);
}
void ContextAlbumsView::SaveContainerPath(const QModelIndex &child) {
QModelIndex current = model()->parent(child);
QVariant type = model()->data(current, ContextAlbumsModel::Role_Type);
if (!type.isValid() || !(type.toInt() == CollectionItem::Type_Container || type.toInt() == CollectionItem::Type_Divider)) {
return;
}
QString text = model()->data(current, ContextAlbumsModel::Role_SortText).toString();
last_selected_path_ << text;
SaveContainerPath(current);
}
void ContextAlbumsView::RestoreFocus() {
if (last_selected_container_.isEmpty() && last_selected_song_.url().isEmpty()) {
return;
}
RestoreLevelFocus();
}
bool ContextAlbumsView::RestoreLevelFocus(const QModelIndex &parent) {
if (model()->canFetchMore(parent)) {
model()->fetchMore(parent);
}
int rows = model()->rowCount(parent);
for (int i = 0; i < rows; i++) {
QModelIndex current = model()->index(i, 0, parent);
QVariant type = model()->data(current, ContextAlbumsModel::Role_Type);
switch (type.toInt()) {
case CollectionItem::Type_Song:
if (!last_selected_song_.url().isEmpty()) {
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
const SongList songs = model_->GetChildSongs(index);
if (std::any_of(songs.begin(), songs.end(), [this](const Song &song) { return song == last_selected_song_; })) {
setCurrentIndex(current);
return true;
}
}
break;
}
}
return false;
}
void ContextAlbumsView::Init(Application *app) {
app_ = app;
model_ = new ContextAlbumsModel(app_->collection_backend(), app_, this);
model_->Reset();
setModel(model_);
QObject::connect(model_, &ContextAlbumsModel::modelAboutToBeReset, this, &ContextAlbumsView::SaveFocus);
QObject::connect(model_, &ContextAlbumsModel::modelReset, this, &ContextAlbumsView::RestoreFocus);
}
void ContextAlbumsView::paintEvent(QPaintEvent *event) {
QTreeView::paintEvent(event);
}
void ContextAlbumsView::mouseReleaseEvent(QMouseEvent *e) {
QTreeView::mouseReleaseEvent(e);
}
void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
if (!context_menu_) {
context_menu_ = new QMenu(this);
add_to_playlist_ = context_menu_->addAction(IconLoader::Load("media-playback-start"), tr("Append to current playlist"), this, &ContextAlbumsView::AddToPlaylist);
load_ = context_menu_->addAction(IconLoader::Load("media-playback-start"), tr("Replace current playlist"), this, &ContextAlbumsView::Load);
open_in_new_playlist_ = context_menu_->addAction(IconLoader::Load("document-new"), tr("Open in new playlist"), this, &ContextAlbumsView::OpenInNewPlaylist);
context_menu_->addSeparator();
add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, &ContextAlbumsView::AddToPlaylistEnqueue);
context_menu_->addSeparator();
organize_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, &ContextAlbumsView::Organize);
#ifndef Q_OS_WIN
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, &ContextAlbumsView::CopyToDevice);
#endif
context_menu_->addSeparator();
edit_track_ = context_menu_->addAction(IconLoader::Load("edit-rename"), tr("Edit track information..."), this, &ContextAlbumsView::EditTracks);
edit_tracks_ = context_menu_->addAction(IconLoader::Load("edit-rename"), tr("Edit tracks information..."), this, &ContextAlbumsView::EditTracks);
show_in_browser_ = context_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, &ContextAlbumsView::ShowInBrowser);
context_menu_->addSeparator();
#ifndef Q_OS_WIN
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
QObject::connect(app_->device_manager()->connected_devices_model(), &DeviceStateFilterModel::IsEmptyChanged, copy_to_device_, &QAction::setDisabled);
#endif
}
context_menu_index_ = indexAt(e->pos());
if (!context_menu_index_.isValid()) return;
QModelIndexList selected_indexes = selectionModel()->selectedRows();
int regular_elements = 0;
int regular_editable = 0;
for (const QModelIndex &idx : selected_indexes) {
regular_elements++;
if (model_->data(idx, ContextAlbumsModel::Role_Editable).toBool()) {
regular_editable++;
}
}
// TODO: check if custom plugin actions should be enabled / visible
const int songs_selected = regular_elements;
const bool regular_elements_only = songs_selected == regular_elements && regular_elements > 0;
// in all modes
load_->setEnabled(songs_selected > 0);
add_to_playlist_->setEnabled(songs_selected > 0);
open_in_new_playlist_->setEnabled(songs_selected > 0);
add_to_playlist_enqueue_->setEnabled(songs_selected > 0);
// if neither edit_track not edit_tracks are available, we show disabled edit_track element
edit_track_->setVisible(regular_editable <= 1);
edit_track_->setEnabled(regular_editable == 1);
organize_->setVisible(regular_elements_only);
#ifndef Q_OS_WIN
copy_to_device_->setVisible(regular_elements_only);
#endif
// only when all selected items are editable
organize_->setEnabled(regular_elements == regular_editable);
#ifndef Q_OS_WIN
copy_to_device_->setEnabled(regular_elements == regular_editable);
#endif
context_menu_->popup(e->globalPos());
}
void ContextAlbumsView::Load() {
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->clear_first_ = true;
}
emit AddToPlaylistSignal(q_mimedata);
}
void ContextAlbumsView::AddToPlaylist() {
emit AddToPlaylistSignal(model()->mimeData(selectedIndexes()));
}
void ContextAlbumsView::AddToPlaylistEnqueue() {
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->enqueue_now_ = true;
}
emit AddToPlaylistSignal(q_mimedata);
}
void ContextAlbumsView::OpenInNewPlaylist() {
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
mimedata->open_in_new_playlist_ = true;
}
emit AddToPlaylistSignal(q_mimedata);
}
void ContextAlbumsView::scrollTo(const QModelIndex &idx, ScrollHint hint) {
if (is_in_keyboard_search_) {
QTreeView::scrollTo(idx, QAbstractItemView::PositionAtTop);
}
else {
QTreeView::scrollTo(idx, hint);
}
}
SongList ContextAlbumsView::GetSelectedSongs() const {
QModelIndexList selected_indexes = selectionModel()->selectedRows();
return model_->GetChildSongs(selected_indexes);
}
void ContextAlbumsView::Organize() {
if (!organize_dialog_) {
organize_dialog_ = std::make_unique<OrganizeDialog>(app_->task_manager(), app_->collection_backend(), this);
}
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
organize_dialog_->SetCopy(false);
if (organize_dialog_->SetSongs(GetSelectedSongs())) {
organize_dialog_->show();
}
else {
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
}
}
void ContextAlbumsView::EditTracks() {
if (!edit_tag_dialog_) {
edit_tag_dialog_ = std::make_unique<EditTagDialog>(app_, this);
}
edit_tag_dialog_->SetSongs(GetSelectedSongs());
edit_tag_dialog_->show();
}
void ContextAlbumsView::CopyToDevice() {
#ifndef Q_OS_WIN
if (!organize_dialog_) {
organize_dialog_ = std::make_unique<OrganizeDialog>(app_->task_manager(), nullptr, this);
}
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
organize_dialog_->SetCopy(true);
organize_dialog_->SetSongs(GetSelectedSongs());
organize_dialog_->show();
#endif
}
void ContextAlbumsView::ShowInBrowser() const {
const SongList songs = GetSelectedSongs();
QList<QUrl> urls;
urls.reserve(songs.count());
for (const Song &song : songs) {
urls << song.url();
}
Utilities::OpenInFileBrowser(urls);
}

View File

@@ -1,137 +0,0 @@
/*
* Strawberry Music Player
* This code was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Strawberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONTEXTALBUMSVIEW_H
#define CONTEXTALBUMSVIEW_H
#include "config.h"
#include <memory>
#include <QObject>
#include <QAbstractItemModel>
#include <QAbstractItemView>
#include <QStyledItemDelegate>
#include <QStyleOption>
#include <QSet>
#include <QString>
#include "core/song.h"
#include "widgets/autoexpandingtreeview.h"
class QWidget;
class QMenu;
class QAction;
class QContextMenuEvent;
class QHelpEvent;
class QMouseEvent;
class QPaintEvent;
class Application;
class ContextAlbumsModel;
class EditTagDialog;
class OrganizeDialog;
class ContextItemDelegate : public QStyledItemDelegate {
Q_OBJECT
public:
explicit ContextItemDelegate(QObject *parent);
public slots:
bool helpEvent(QHelpEvent *event, QAbstractItemView *view, const QStyleOptionViewItem &option, const QModelIndex &idx) override;
};
class ContextAlbumsView : public AutoExpandingTreeView {
Q_OBJECT
public:
explicit ContextAlbumsView(QWidget *parent = nullptr);
~ContextAlbumsView() override;
// Returns Songs currently selected in the collection view.
// Please note that the selection is recursive meaning that if for example an album is selected this will return all of it's songs.
SongList GetSelectedSongs() const;
void Init(Application *app);
// QTreeView
void scrollTo(const QModelIndex &idx, ScrollHint hint = EnsureVisible) override;
ContextAlbumsModel *albums_model() { return model_; }
public slots:
void SaveFocus();
void RestoreFocus();
protected:
// QWidget
void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override;
private slots:
void Load();
void AddToPlaylist();
void AddToPlaylistEnqueue();
void OpenInNewPlaylist();
void Organize();
void CopyToDevice();
void EditTracks();
void ShowInBrowser() const;
private:
void RecheckIsEmpty();
bool RestoreLevelFocus(const QModelIndex &parent = QModelIndex());
void SaveContainerPath(const QModelIndex &child);
private:
Application *app_;
QMenu *context_menu_;
QModelIndex context_menu_index_;
QAction *load_;
QAction *add_to_playlist_;
QAction *add_to_playlist_enqueue_;
QAction *open_in_new_playlist_;
QAction *organize_;
#ifndef Q_OS_WIN
QAction *copy_to_device_;
#endif
QAction *edit_track_;
QAction *edit_tracks_;
QAction *show_in_browser_;
std::unique_ptr<OrganizeDialog> organize_dialog_;
std::unique_ptr<EditTagDialog> edit_tag_dialog_;
bool is_in_keyboard_search_;
// Save focus
Song last_selected_song_;
QString last_selected_container_;
QSet<QString> last_selected_path_;
ContextAlbumsModel *model_;
};
#endif // CONTEXTALBUMSVIEW_H

View File

@@ -1,6 +1,6 @@
/*
* Strawberry Music Player
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2013-2022, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -41,6 +41,7 @@
#include <QScrollArea>
#include <QSpacerItem>
#include <QLabel>
#include <QTextEdit>
#include <QSettings>
#include <QResizeEvent>
#include <QContextMenuEvent>
@@ -52,6 +53,7 @@
#include "core/song.h"
#include "core/utilities.h"
#include "core/iconloader.h"
#include "widgets/resizabletextedit.h"
#include "engine/engine_fwd.h"
#include "engine/enginebase.h"
#include "engine/enginetype.h"
@@ -66,8 +68,8 @@
#include "contextview.h"
#include "contextalbum.h"
#include "contextalbumsmodel.h"
#include "contextalbumsview.h"
const int ContextView::kWidgetSpacing = 50;
ContextView::ContextView(QWidget *parent)
: QWidget(parent),
@@ -75,18 +77,17 @@ ContextView::ContextView(QWidget *parent)
collectionview_(nullptr),
album_cover_choice_controller_(nullptr),
lyrics_fetcher_(nullptr),
menu_(new QMenu(this)),
menu_options_(new QMenu(this)),
action_show_album_(nullptr),
action_show_data_(nullptr),
action_show_output_(nullptr),
action_show_albums_(nullptr),
action_show_lyrics_(nullptr),
action_search_lyrics_(nullptr),
layout_container_(new QVBoxLayout()),
widget_scrollarea_(new QWidget(this)),
layout_scrollarea_(new QVBoxLayout()),
scrollarea_(new QScrollArea(this)),
label_top_(new QLabel(this)),
textedit_top_(new ResizableTextEdit(this)),
widget_album_(new ContextAlbum(this)),
widget_stacked_(new QStackedWidget(this)),
widget_stop_(new QWidget(this)),
@@ -94,19 +95,13 @@ ContextView::ContextView(QWidget *parent)
layout_stop_(new QVBoxLayout()),
layout_play_(new QVBoxLayout()),
label_stop_summary_(new QLabel(this)),
spacer_stop_bottom_(new QSpacerItem(0, 20, QSizePolicy::Expanding, QSizePolicy::Expanding)),
widget_play_data_(new QWidget(this)),
widget_play_output_(new QWidget(this)),
layout_play_data_(new QGridLayout()),
layout_play_output_(new QGridLayout()),
label_play_albums_(new QLabel(this)),
label_play_lyrics_(new QLabel(this)),
widget_albums_(new ContextAlbumsView(this)),
//spacer_play_album_(new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed)),
textedit_play_lyrics_(new ResizableTextEdit(this)),
spacer_play_output_(new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed)),
spacer_play_data_(new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed)),
spacer_play_albums_(new QSpacerItem(20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed)),
spacer_play_bottom_(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding)),
label_filetype_title_(new QLabel(this)),
label_length_title_(new QLabel(this)),
label_samplerate_title_(new QLabel(this)),
@@ -125,12 +120,10 @@ ContextView::ContextView(QWidget *parent)
label_engine_(new QLabel(this)),
label_device_icon_(new QLabel(this)),
label_engine_icon_(new QLabel(this)),
spacer_bottom_(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding)),
lyrics_tried_(false),
lyrics_id_(-1),
font_size_headline_(0),
font_size_normal_(0),
prev_width_(0) {
font_size_normal_(0) {
setLayout(layout_container_);
@@ -143,23 +136,21 @@ ContextView::ContextView(QWidget *parent)
scrollarea_->setWidget(widget_scrollarea_);
scrollarea_->setContentsMargins(0, 0, 0, 0);
scrollarea_->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
scrollarea_->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
widget_scrollarea_->setObjectName("context-widget-scrollarea");
widget_scrollarea_->setLayout(layout_scrollarea_);
widget_scrollarea_->setContentsMargins(0, 0, 0, 0);
label_top_->setAlignment(Qt::AlignTop|Qt::AlignLeft);
label_top_->setWordWrap(true);
label_top_->setMinimumHeight(50);
label_top_->setContentsMargins(0, 0, 32, 0);
label_top_->setTextInteractionFlags(Qt::TextSelectableByMouse);
textedit_top_->setReadOnly(true);
textedit_top_->setFrameShape(QFrame::NoFrame);
layout_scrollarea_->setObjectName("context-layout-scrollarea");
layout_scrollarea_->setContentsMargins(15, 15, 15, 15);
layout_scrollarea_->addWidget(label_top_);
layout_scrollarea_->addWidget(textedit_top_);
layout_scrollarea_->addWidget(widget_album_);
layout_scrollarea_->addWidget(widget_stacked_);
layout_scrollarea_->addSpacerItem(spacer_bottom_);
layout_scrollarea_->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding));
widget_stacked_->setContentsMargins(0, 0, 0, 0);
widget_stacked_->addWidget(widget_stop_);
@@ -176,9 +167,10 @@ ContextView::ContextView(QWidget *parent)
// Stopped
layout_stop_->setContentsMargins(5, 0, 40, 0);
label_stop_summary_->setAlignment(Qt::AlignLeft | Qt::AlignTop);
layout_stop_->setContentsMargins(0, 0, 0, 0);
layout_stop_->addWidget(label_stop_summary_);
layout_stop_->addSpacerItem(spacer_stop_bottom_);
// Playing
@@ -244,33 +236,25 @@ ContextView::ContextView(QWidget *parent)
widget_play_data_->setLayout(layout_play_data_);
label_play_lyrics_->setWordWrap(true);
label_play_lyrics_->setTextInteractionFlags(Qt::TextSelectableByMouse);
textedit_play_lyrics_->setReadOnly(true);
textedit_play_lyrics_->setFrameShape(QFrame::NoFrame);
textedit_play_lyrics_->hide();
widget_albums_->hide();
label_play_albums_->setWordWrap(true);
label_play_albums_->hide();
layout_play_->setContentsMargins(5, 0, 40, 0);
layout_play_->setContentsMargins(0, 0, 0, 0);
layout_play_->addWidget(widget_play_output_);
layout_play_->addSpacerItem(spacer_play_output_);
layout_play_->addWidget(widget_play_data_);
layout_play_->addSpacerItem(spacer_play_data_);
layout_play_->addWidget(label_play_albums_);
layout_play_->addWidget(widget_albums_);
layout_play_->addSpacerItem(spacer_play_albums_);
layout_play_->addWidget(label_play_lyrics_);
layout_play_->addSpacerItem(spacer_play_bottom_);
layout_play_->addWidget(textedit_play_lyrics_);
layout_play_->addSpacerItem(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding));
labels_play_ << label_engine_title_
<< label_device_title_
<< label_filetype_title_
<< label_length_title_
<< label_samplerate_title_
<< label_bitdepth_title_
<< label_bitrate_title_
<< label_play_albums_
<< label_play_lyrics_;
labels_play_ << label_engine_title_
<< label_device_title_
<< label_filetype_title_
<< label_length_title_
<< label_samplerate_title_
<< label_bitdepth_title_
<< label_bitrate_title_;
labels_play_data_ << label_engine_icon_
<< label_engine_
@@ -280,27 +264,16 @@ ContextView::ContextView(QWidget *parent)
<< label_length_
<< label_samplerate_
<< label_bitdepth_
<< label_bitrate_
<< label_play_albums_
<< label_play_lyrics_;
<< label_bitrate_;
labels_play_all_ = labels_play_ << labels_play_data_;
QFontDatabase::addApplicationFont(":/fonts/HumongousofEternitySt.ttf");
textedit_play_ << textedit_play_lyrics_;
QObject::connect(widget_album_, &ContextAlbum::FadeStopFinished, this, &ContextView::FadeStopFinished);
}
void ContextView::resizeEvent(QResizeEvent*) {
if (width() != prev_width_) {
widget_album_->setFixedSize(width() - 15, width());
prev_width_ = width();
}
}
void ContextView::Init(Application *app, CollectionView *collectionview, AlbumCoverChoiceController *album_cover_choice_controller) {
app_ = app;
@@ -308,7 +281,6 @@ void ContextView::Init(Application *app, CollectionView *collectionview, AlbumCo
album_cover_choice_controller_ = album_cover_choice_controller;
widget_album_->Init(this, album_cover_choice_controller_);
widget_albums_->Init(app_);
lyrics_fetcher_ = new LyricsFetcher(app_->lyrics_providers(), this);
QObject::connect(collectionview_, &CollectionView::TotalSongCountUpdated_, this, &ContextView::UpdateNoSong);
@@ -334,10 +306,6 @@ void ContextView::AddActions() {
action_show_output_->setCheckable(true);
action_show_output_->setChecked(true);
action_show_albums_ = new QAction(tr("Show albums by artist"), this);
action_show_albums_->setCheckable(true);
action_show_albums_->setChecked(false);
action_show_lyrics_ = new QAction(tr("Show song lyrics"), this);
action_show_lyrics_->setCheckable(true);
action_show_lyrics_->setChecked(true);
@@ -346,20 +314,18 @@ void ContextView::AddActions() {
action_search_lyrics_->setCheckable(true);
action_search_lyrics_->setChecked(true);
menu_->addAction(action_show_album_);
menu_->addAction(action_show_data_);
menu_->addAction(action_show_output_);
menu_->addAction(action_show_albums_);
menu_->addAction(action_show_lyrics_);
menu_->addAction(action_search_lyrics_);
menu_->addSeparator();
menu_options_->addAction(action_show_album_);
menu_options_->addAction(action_show_data_);
menu_options_->addAction(action_show_output_);
menu_options_->addAction(action_show_lyrics_);
menu_options_->addAction(action_search_lyrics_);
menu_options_->addSeparator();
ReloadSettings();
QObject::connect(action_show_album_, &QAction::triggered, this, &ContextView::ActionShowAlbums);
QObject::connect(action_show_album_, &QAction::triggered, this, &ContextView::ActionShowAlbum);
QObject::connect(action_show_data_, &QAction::triggered, this, &ContextView::ActionShowData);
QObject::connect(action_show_output_, &QAction::triggered, this, &ContextView::ActionShowOutput);
QObject::connect(action_show_albums_, &QAction::triggered, this, &ContextView::ActionShowAlbums);
QObject::connect(action_show_lyrics_, &QAction::triggered, this, &ContextView::ActionShowLyrics);
QObject::connect(action_search_lyrics_, &QAction::triggered, this, &ContextView::ActionSearchLyrics);
@@ -374,12 +340,11 @@ void ContextView::ReloadSettings() {
action_show_album_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ALBUM], true).toBool());
action_show_data_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::TECHNICAL_DATA], false).toBool());
action_show_output_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ENGINE_AND_DEVICE], false).toBool());
action_show_albums_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ALBUMS_BY_ARTIST], false).toBool());
action_show_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS], true).toBool());
action_search_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SEARCH_LYRICS], true).toBool());
font_headline_ = s.value("font_headline", font().family()).toString();
font_normal_ = s.value("font_normal", font().family()).toString();
font_size_headline_ = s.value("font_size_headline", ContextSettingsPage::kDefaultFontSizeHeadline).toReal();
font_size_headline_ = s.value("font_size_headline", ContextSettingsPage::kDefaultFontSizeHeadline).toReal();
font_size_normal_ = s.value("font_size_normal", font().pointSizeF()).toReal();
s.endGroup();
@@ -394,6 +359,16 @@ void ContextView::ReloadSettings() {
}
void ContextView::resizeEvent(QResizeEvent *e) {
if (e->size().width() != e->oldSize().width()) {
widget_album_->UpdateWidth(width() - kWidgetSpacing);
}
QWidget::resizeEvent(e);
}
void ContextView::Playing() {}
void ContextView::Stopped() {
@@ -441,6 +416,7 @@ void ContextView::FadeStopFinished() {
widget_stacked_->setCurrentWidget(widget_stop_);
NoSong();
ResetSong();
widget_stacked_->updateGeometry();
}
@@ -458,9 +434,8 @@ void ContextView::NoSong() {
widget_album_->show();
}
label_top_->setStyleSheet("font: 20pt \"Humongous of Eternity St\"; font-weight: Regular;");
label_top_->setText(tr("No song playing"));
textedit_top_->setStyleSheet("font: 20pt 'Open Sans', 'FreeSans', 'FreeSerif', 'Liberation Serif'; font-weight: Regular;");
textedit_top_->setText(tr("No song playing"));
QString html;
if (collectionview_->TotalSongs() == 1) html += tr("%1 song").arg(collectionview_->TotalSongs());
@@ -482,17 +457,20 @@ void ContextView::NoSong() {
void ContextView::UpdateFonts() {
QString font_style = QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_normal_).arg(font_size_normal_);
for (QLabel *l : labels_play_all_) {
l->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_normal_).arg(font_size_normal_));
l->setStyleSheet(font_style);
}
for (QTextEdit *e : textedit_play_) {
e->setStyleSheet(font_style);
}
label_play_albums_->setStyleSheet(QString("background-color: #3DADE8; color: rgb(255, 255, 255); font: %1pt \"%2\"; font-weight: regular;").arg(font_size_normal_).arg(font_normal_));
}
void ContextView::SetSong() {
label_top_->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_headline_).arg(font_size_headline_));
label_top_->setText(QString("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song_playing_, "<br />", true), Utilities::ReplaceMessage(summary_fmt_, song_playing_, "<br />", true)));
textedit_top_->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_headline_).arg(font_size_headline_));
textedit_top_->setText(QString("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song_playing_, "<br />", true), Utilities::ReplaceMessage(summary_fmt_, song_playing_, "<br />", true)));
label_stop_summary_->clear();
@@ -605,51 +583,23 @@ void ContextView::SetSong() {
spacer_play_output_->changeSize(0, 0, QSizePolicy::Fixed);
}
if (action_show_albums_->isChecked() && song_prev_.artist() != song_playing_.artist()) {
CollectionBackend::AlbumList albumlist;
widget_albums_->albums_model()->Reset();
albumlist = app_->collection_backend()->GetAlbumsByArtist(song_playing_.effective_albumartist());
if (albumlist.count() > 1) {
label_play_albums_->show();
widget_albums_->show();
label_play_albums_->setText("<b>" + tr("Albums by %1").arg(song_playing_.effective_albumartist().toHtmlEscaped()) + "</b>");
for (const CollectionBackend::Album &album : albumlist) {
SongList songs = app_->collection_backend()->GetAlbumSongs(song_playing_.effective_albumartist(), album.album);
widget_albums_->albums_model()->AddSongs(songs);
}
spacer_play_albums_->changeSize(20, 10, QSizePolicy::Fixed);
}
else {
label_play_albums_->hide();
widget_albums_->hide();
label_play_albums_->clear();
spacer_play_albums_->changeSize(0, 0, QSizePolicy::Fixed);
}
}
else if (!action_show_albums_->isChecked()) {
label_play_albums_->hide();
widget_albums_->hide();
label_play_albums_->clear();
widget_albums_->albums_model()->Reset();
spacer_play_albums_->changeSize(0, 0, QSizePolicy::Fixed);
}
if (action_show_lyrics_->isChecked()) {
label_play_lyrics_->show();
label_play_lyrics_->setText(lyrics_);
if (action_show_lyrics_->isChecked() && !lyrics_.isEmpty()) {
textedit_play_lyrics_->setText(lyrics_);
textedit_play_lyrics_->show();
}
else {
label_play_lyrics_->hide();
label_play_lyrics_->clear();
textedit_play_lyrics_->clear();
textedit_play_lyrics_->hide();
}
widget_stacked_->setCurrentWidget(widget_play_);
widget_stacked_->updateGeometry();
}
void ContextView::UpdateSong(const Song &song) {
label_top_->setText(QString("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song, "<br />", true), Utilities::ReplaceMessage(summary_fmt_, song, "<br />", true)));
textedit_top_->setText(QString("<b>%1</b><br />%2").arg(Utilities::ReplaceMessage(title_fmt_, song, "<br />", true), Utilities::ReplaceMessage(summary_fmt_, song, "<br />", true)));
if (action_show_data_->isChecked()) {
if (song.filetype() != song_playing_.filetype()) label_filetype_->setText(song.TextForFiletype());
@@ -713,22 +663,43 @@ void ContextView::ResetSong() {
l->clear();
}
for (QTextEdit *l : textedit_play_) {
l->clear();
}
widget_play_output_->hide();
widget_play_data_->hide();
textedit_play_lyrics_->hide();
}
void ContextView::UpdateLyrics(const quint64 id, const QString &provider, const QString &lyrics) {
if (static_cast<qint64>(id) != lyrics_id_) return;
lyrics_ = lyrics + "\n\n(Lyrics from " + provider + ")\n";
lyrics_id_ = -1;
if (action_show_lyrics_->isChecked()) {
label_play_lyrics_->setText(lyrics_);
if (action_show_lyrics_->isChecked() && !lyrics_.isEmpty()) {
textedit_play_lyrics_->setText(lyrics_);
textedit_play_lyrics_->show();
}
else {
textedit_play_lyrics_->clear();
textedit_play_lyrics_->hide();
}
else label_play_lyrics_->clear();
}
void ContextView::contextMenuEvent(QContextMenuEvent *e) {
if (menu_) menu_->popup(mapToGlobal(e->pos()));
if (menu_options_ && widget_stacked_->currentWidget() == widget_stop_) {
menu_options_->popup(mapToGlobal(e->pos()));
}
else {
QWidget::contextMenuEvent(e);
}
}
void ContextView::dragEnterEvent(QDragEnterEvent *e) {
@@ -790,17 +761,6 @@ void ContextView::ActionShowOutput() {
}
void ContextView::ActionShowAlbums() {
QSettings s;
s.beginGroup(ContextSettingsPage::kSettingsGroup);
s.setValue(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ALBUMS_BY_ARTIST], action_show_albums_->isChecked());
s.endGroup();
song_prev_ = Song();
if (song_playing_.is_valid()) SetSong();
}
void ContextView::ActionShowLyrics() {
QSettings s;

View File

@@ -1,6 +1,6 @@
/*
* Strawberry Music Player
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2013-2022, Jonas Kvinge <jonas@jkvinge.net>
*
* Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -45,10 +45,10 @@ class QContextMenuEvent;
class QDragEnterEvent;
class QDropEvent;
class ResizableTextEdit;
class Application;
class CollectionView;
class AlbumCoverChoiceController;
class ContextAlbumsView;
class LyricsFetcher;
class ContextView : public QWidget {
@@ -60,12 +60,11 @@ class ContextView : public QWidget {
void Init(Application *app, CollectionView *collectionview, AlbumCoverChoiceController *album_cover_choice_controller);
ContextAlbum *album_widget() const { return widget_album_; }
ContextAlbumsView *albums_widget() const { return widget_albums_; }
bool album_enabled() const { return action_show_album_->isChecked(); }
Song song_playing() const { return song_playing_; }
protected:
void resizeEvent(QResizeEvent*) override;
void resizeEvent(QResizeEvent *e) override;
void contextMenuEvent(QContextMenuEvent*) override;
void dragEnterEvent(QDragEnterEvent*) override;
void dropEvent(QDropEvent*) override;
@@ -88,7 +87,6 @@ class ContextView : public QWidget {
void ActionShowAlbum();
void ActionShowData();
void ActionShowOutput();
void ActionShowAlbums();
void ActionShowLyrics();
void ActionSearchLyrics();
void UpdateNoSong();
@@ -104,16 +102,17 @@ class ContextView : public QWidget {
void AlbumCoverLoaded(const Song &song, const QImage &image);
private:
static const int kWidgetSpacing;
Application *app_;
CollectionView *collectionview_;
AlbumCoverChoiceController *album_cover_choice_controller_;
LyricsFetcher *lyrics_fetcher_;
QMenu *menu_;
QMenu *menu_options_;
QAction *action_show_album_;
QAction *action_show_data_;
QAction *action_show_output_;
QAction *action_show_albums_;
QAction *action_show_lyrics_;
QAction *action_search_lyrics_;
@@ -121,7 +120,7 @@ class ContextView : public QWidget {
QWidget *widget_scrollarea_;
QVBoxLayout *layout_scrollarea_;
QScrollArea *scrollarea_;
QLabel *label_top_;
ResizableTextEdit *textedit_top_;
ContextAlbum *widget_album_;
QStackedWidget *widget_stacked_;
QWidget *widget_stop_;
@@ -129,20 +128,14 @@ class ContextView : public QWidget {
QVBoxLayout *layout_stop_;
QVBoxLayout *layout_play_;
QLabel *label_stop_summary_;
QSpacerItem *spacer_stop_bottom_;
QWidget *widget_play_data_;
QWidget *widget_play_output_;
QGridLayout *layout_play_data_;
QGridLayout *layout_play_output_;
QLabel *label_play_albums_;
QLabel *label_play_lyrics_;
ContextAlbumsView *widget_albums_;
ResizableTextEdit *textedit_play_lyrics_;
//QSpacerItem *spacer_play_album_;
QSpacerItem *spacer_play_output_;
QSpacerItem *spacer_play_data_;
QSpacerItem *spacer_play_albums_;
QSpacerItem *spacer_play_bottom_;
QLabel *label_filetype_title_;
QLabel *label_length_title_;
@@ -165,8 +158,6 @@ class ContextView : public QWidget {
QLabel *label_device_icon_;
QLabel *label_engine_icon_;
QSpacerItem *spacer_bottom_;
Song song_playing_;
Song song_prev_;
QImage image_original_;
@@ -181,11 +172,10 @@ class ContextView : public QWidget {
qreal font_size_normal_;
QList<QLabel*> labels_play_;
QList<ResizableTextEdit*> textedit_play_;
QList<QLabel*> labels_play_data_;
QList<QLabel*> labels_play_all_;
int prev_width_;
};
#endif // CONTEXTVIEW_H

View File

@@ -20,14 +20,14 @@
// This template function declaration is used in defining arraysize.
// Note that the function doesn't need an implementation, as we only
// use its type.
template <typename T, size_t N>
template<typename T, size_t N>
char (&ArraySizeHelper(T (&array)[N]))[N];
// That gcc wants both of these prototypes seems mysterious. VC, for
// its part, can't decide which to use (another mystery). Matching of
// template overloads: the final frontier.
#ifndef _MSC_VER
template <typename T, size_t N>
template<typename T, size_t N>
char (&ArraySizeHelper(const T (&array)[N]))[N];
#endif

View File

@@ -401,15 +401,21 @@ void Database::ExecSchemaCommandsFromFile(QSqlDatabase &db, const QString &filen
qFatal("Couldn't open schema file %s for reading: %s", filename.toUtf8().constData(), schema_file.errorString().toUtf8().constData());
return;
}
ExecSchemaCommands(db, QString::fromUtf8(schema_file.readAll()), schema_version, in_transaction);
QByteArray data = schema_file.readAll();
QString schema = QString::fromUtf8(data);
if (schema.contains("\r\n")) {
schema = schema.replace("\r\n", "\n");
}
schema_file.close();
ExecSchemaCommands(db, schema, schema_version, in_transaction);
}
void Database::ExecSchemaCommands(QSqlDatabase &db, const QString &schema, int schema_version, bool in_transaction) {
// Run each command
const QStringList commands(schema.split(QRegularExpression("; *\n\n")));
QStringList commands;
commands = schema.split(QRegularExpression("; *\n\n"));
// We don't want this list to reflect possible DB schema changes so we initialize it before executing any statements.
// If no outer transaction is provided the song tables need to be queried before beginning an inner transaction! Otherwise

View File

@@ -109,12 +109,12 @@ bool FilesystemMusicStorage::DeleteFromStorage(const DeleteJob &job) {
if (job.use_trash_) {
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
if (fileInfo.isDir()) {
return Utilities::MoveToTrashRecursive(path);
}
else {
return QFile::moveToTrash(path);
}
if (fileInfo.isDir()) {
return Utilities::MoveToTrashRecursive(path);
}
else {
return QFile::moveToTrash(path);
}
#else
return false;
#endif

View File

@@ -63,7 +63,7 @@ QIcon IconLoader::Load(const QString &name, const int fixed_size, const int min_
QList<int> sizes;
if (fixed_size == 0) {
sizes << 22 << 32 << 48 << 64;
sizes << 22 << 32 << 48 << 64 << 128;
}
else {
sizes << fixed_size;

View File

@@ -25,7 +25,7 @@
// Usage:
// Lazy<Foo> my_lazy_object([]() { return new Foo; });
template <typename T>
template<typename T>
class Lazy {
public:
explicit Lazy(std::function<T*()> init) : init_(init) {}

View File

@@ -67,7 +67,7 @@
QDebug operator<<(QDebug dbg, NSObject *object) {
QString ns_format = [ [NSString stringWithFormat:@"%@", object] UTF8String];
QString ns_format = [[NSString stringWithFormat:@"%@", object] UTF8String];
dbg.nospace() << ns_format;
return dbg.space();
@@ -149,11 +149,12 @@ QDebug operator<<(QDebug dbg, NSObject *object) {
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:self andSelector:@selector(handleURLEvent:withReplyEvent:) forEventClass:kInternetEventClass andEventID:kAEGetURL];
key_tap_ = [ [SPMediaKeyTap alloc] initWithDelegate:self];
key_tap_ = [[SPMediaKeyTap alloc] initWithDelegate:self];
if ([SPMediaKeyTap usesGlobalMediaKeyTap]) {
if ([key_tap_ startWatchingMediaKeys]) {
qLog(Debug) << "Media key monitoring started";
} else {
}
else {
qLog(Warning) << "Failed to start media key monitoring";
}
}
@@ -181,7 +182,7 @@ QDebug operator<<(QDebug dbg, NSObject *object) {
qLog(Debug) << "Wants to open:" << filenames;
[filenames enumerateObjectsUsingBlock:^(id object, NSUInteger, BOOL*) {
[self application:app openFile:(NSString*)object];
[self application:app openFile:reinterpret_cast<NSString*>(object)];
}];
}
@@ -254,7 +255,7 @@ QDebug operator<<(QDebug dbg, NSObject *object) {
- (void)SetApplicationHandler:(PlatformInterface*)handler {
delegate_ = [ [AppDelegate alloc] initWithHandler:handler];
delegate_ = [[AppDelegate alloc] initWithHandler:handler];
// App-shortcut-handler set before delegate is set.
// this makes sure the delegate's shortcut_handler is set
[delegate_ setShortcutHandler:shortcut_handler_];
@@ -263,7 +264,7 @@ QDebug operator<<(QDebug dbg, NSObject *object) {
// FIXME
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
[ [NSUserNotificationCenter defaultUserNotificationCenter]setDelegate:delegate_];
[[NSUserNotificationCenter defaultUserNotificationCenter]setDelegate:delegate_];
#pragma GCC diagnostic pop
}
@@ -402,7 +403,7 @@ QKeySequence KeySequenceFromNSEvent(NSEvent *event) {
void DumpDictionary(CFDictionaryRef dict) {
NSDictionary *d = (NSDictionary*)dict;
NSDictionary *d = reinterpret_cast<NSDictionary*>(dict);
NSLog(@"%@", d);
}

View File

@@ -120,7 +120,6 @@
#include "widgets/trackslider.h"
#include "osd/osdbase.h"
#include "context/contextview.h"
#include "context/contextalbumsview.h"
#include "collection/collection.h"
#include "collection/collectionbackend.h"
#include "collection/collectiondirectorymodel.h"
@@ -221,6 +220,18 @@ const int kTrackSliderUpdateTimeMs = 200;
const int kTrackPositionUpdateTimeMs = 1000;
} // namespace
#ifdef HAVE_QTSPARKLE
# ifdef _MSC_VER
constexpr char QTSPARKLE_URL[] = "https://www.strawberrymusicplayer.org/sparkle-windows-msvc-x64";
# else
# ifdef __x86_64__
constexpr char QTSPARKLE_URL[] = "https://www.strawberrymusicplayer.org/sparkle-windows-mingw-x64";
# else
constexpr char QTSPARKLE_URL[] = "https://www.strawberrymusicplayer.org/sparkle-windows-mingw-x86";
# endif
# endif
#endif
MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_icon, OSDBase *osd, const CommandlineOptions &options, QWidget *parent)
: QMainWindow(parent),
ui_(new Ui_MainWindow),
@@ -324,7 +335,8 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
hidden_(false),
exit_(false),
exit_count_(0),
delete_files_(false) {
delete_files_(false),
ignore_close_(false) {
qLog(Debug) << "Starting";
@@ -334,6 +346,8 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
// Initialize the UI
ui_->setupUi(this);
setWindowIcon(IconLoader::Load("strawberry"));
album_cover_choice_controller_->Init(app);
ui_->multi_loading_indicator->SetTaskManager(app_->task_manager());
@@ -446,6 +460,7 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
ui_->action_remove_duplicates->setIcon(IconLoader::Load("list-remove"));
ui_->action_remove_unavailable->setIcon(IconLoader::Load("list-remove"));
ui_->action_remove_from_playlist->setIcon(IconLoader::Load("list-remove"));
ui_->action_save_all_playlists->setIcon(IconLoader::Load("document-save-all"));
// Configure
@@ -476,9 +491,9 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
QObject::connect(file_view_, &FileView::CopyToCollection, this, &MainWindow::CopyFilesToCollection);
QObject::connect(file_view_, &FileView::MoveToCollection, this, &MainWindow::MoveFilesToCollection);
QObject::connect(file_view_, &FileView::EditTags, this, &MainWindow::EditFileTags);
#ifndef Q_OS_WIN
# ifndef Q_OS_WIN
QObject::connect(file_view_, &FileView::CopyToDevice, this, &MainWindow::CopyFilesToDevice);
#endif
# endif
#endif
file_view_->SetTaskManager(app_->task_manager());
@@ -536,8 +551,8 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
QObject::connect(app_->scrobbler(), &AudioScrobbler::ErrorMessage, this, &MainWindow::ShowErrorDialog);
// Playlist view actions
ui_->action_next_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString("Ctrl+Tab")<< QKeySequence::fromString("Ctrl+PgDown"));
ui_->action_previous_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString("Ctrl+Shift+Tab")<< QKeySequence::fromString("Ctrl+PgUp"));
ui_->action_next_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString("Ctrl+Tab") << QKeySequence::fromString("Ctrl+PgDown"));
ui_->action_previous_playlist->setShortcuts(QList<QKeySequence>() << QKeySequence::fromString("Ctrl+Shift+Tab") << QKeySequence::fromString("Ctrl+PgUp"));
// Actions for switching tabs will be global to the entire window, so adding them here
addAction(ui_->action_next_playlist);
@@ -551,8 +566,7 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
ui_->button_scrobble->setDefaultAction(ui_->action_toggle_scrobbling);
ui_->button_love->setDefaultAction(ui_->action_love);
ui_->playlist->SetActions(ui_->action_new_playlist, ui_->action_load_playlist, ui_->action_save_playlist, ui_->action_clear_playlist, ui_->action_next_playlist, /* These two actions aren't associated */ ui_->action_previous_playlist /* to a button but to the main window */ );
ui_->playlist->SetActions(ui_->action_new_playlist, ui_->action_load_playlist, ui_->action_save_playlist, ui_->action_clear_playlist, ui_->action_next_playlist, /* These two actions aren't associated */ ui_->action_previous_playlist /* to a button but to the main window */, ui_->action_save_all_playlists);
// Add the shuffle and repeat action groups to the menu
ui_->action_shuffle_mode->setMenu(ui_->playlist_sequence->shuffle_menu());
ui_->action_repeat_mode->setMenu(ui_->playlist_sequence->repeat_menu());
@@ -680,7 +694,7 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
QObject::connect(tidal_view_->albums_collection_view(), &InternetCollectionView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
QObject::connect(tidal_view_->songs_collection_view(), &InternetCollectionView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
QObject::connect(tidal_view_->search_view(), &InternetSearchView::AddToPlaylist, this, &MainWindow::AddToPlaylist);
if (TidalService *tidalservice = qobject_cast<TidalService*> (app_->internet_services()->ServiceBySource(Song::Source_Tidal))) {
if (TidalService *tidalservice = qobject_cast<TidalService*>(app_->internet_services()->ServiceBySource(Song::Source_Tidal))) {
QObject::connect(this, &MainWindow::AuthorizationUrlReceived, tidalservice, &TidalService::AuthorizationUrlReceived);
}
#endif
@@ -818,7 +832,6 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
QObject::connect(this, &MainWindow::AlbumCoverReady, context_view_, &ContextView::AlbumCoverLoaded);
QObject::connect(this, &MainWindow::SearchCoverInProgress, context_view_->album_widget(), &ContextAlbum::SearchCoverInProgress);
QObject::connect(context_view_, &ContextView::AlbumEnabledChanged, this, &MainWindow::TabSwitched);
QObject::connect(context_view_->albums_widget(), &ContextAlbumsView::AddToPlaylistSignal, this, &MainWindow::AddToPlaylist);
// Analyzer
QObject::connect(ui_->analyzer, &AnalyzerContainer::WheelEvent, this, &MainWindow::VolumeWheelEvent);
@@ -948,7 +961,6 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
break;
case BehaviourSettingsPage::Startup_Hide:
if (tray_icon_->IsSystemTrayAvailable() && tray_icon_->isVisible()) {
hide();
break;
}
// fallthrough
@@ -968,7 +980,9 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
}
else {
hidden_ = settings_.value("hidden", false).toBool();
setVisible(!hidden_);
if (!hidden_) {
show();
}
}
break;
}
@@ -1000,12 +1014,7 @@ MainWindow::MainWindow(Application *app, std::shared_ptr<SystemTrayIcon> tray_ic
}
#ifdef HAVE_QTSPARKLE
QUrl sparkle_url;
#if defined(Q_OS_MACOS)
sparkle_url.setUrl("https://www.strawberrymusicplayer.org/sparkle-macos");
#elif defined(Q_OS_WIN)
sparkle_url.setUrl("https://www.strawberrymusicplayer.org/sparkle-windows");
#endif
QUrl sparkle_url(QTSPARKLE_URL);
if (!sparkle_url.isEmpty()) {
qLog(Debug) << "Creating Qt Sparkle updater";
qtsparkle::Updater *updater = new qtsparkle::Updater(sparkle_url, this);
@@ -1215,7 +1224,8 @@ void MainWindow::Exit() {
QObject::connect(app_->player()->engine(), &EngineBase::FadeoutFinishedSignal, this, &MainWindow::DoExit);
if (app_->player()->GetState() == Engine::Playing) {
app_->player()->Stop();
hide();
ignore_close_ = true;
close();
if (tray_icon_->IsSystemTrayAvailable()) {
tray_icon_->setVisible(false);
}
@@ -1543,16 +1553,13 @@ void MainWindow::VolumeWheelEvent(const int delta) {
void MainWindow::ToggleShowHide() {
if (hidden_) {
show();
SetHiddenInTray(false);
}
else if (isActiveWindow()) {
hide();
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
SetHiddenInTray(true);
}
else if (isMinimized()) {
hide();
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
SetHiddenInTray(false);
}
@@ -1587,8 +1594,14 @@ void MainWindow::showEvent(QShowEvent *e) {
void MainWindow::closeEvent(QCloseEvent *e) {
if (ignore_close_) {
ignore_close_ = false;
QMainWindow::closeEvent(e);
return;
}
if (!exit_) {
if (!hidden_ && keep_running_ && e->spontaneous() && tray_icon_->IsSystemTrayAvailable()) {
if (!hidden_ && keep_running_ && tray_icon_->IsSystemTrayAvailable()) {
SetHiddenInTray(true);
}
else {
@@ -1609,7 +1622,8 @@ void MainWindow::SetHiddenInTray(const bool hidden) {
if (hidden) {
was_maximized_ = isMaximized();
was_minimized_ = isMinimized();
hide();
ignore_close_ = true;
close();
}
else {
if (was_minimized_) {
@@ -2183,7 +2197,7 @@ void MainWindow::AddFile() {
PlaylistParser parser(app_->collection_backend());
// Show dialog
QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter, parser.filters(), tr(kAllFilesFilterSpec)));
QStringList file_names = QFileDialog::getOpenFileNames(this, tr("Add file"), directory, QString("%1 (%2);;%3;;%4").arg(tr("Music"), FileView::kFileFilter, parser.filters(PlaylistParser::Type_Load), tr(kAllFilesFilterSpec)));
if (file_names.isEmpty()) return;
@@ -2274,7 +2288,7 @@ void MainWindow::PlaylistRemoveCurrent() {
void MainWindow::PlaylistClearCurrent() {
if (app_->playlist_manager()->current()->rowCount() > Playlist::kUndoItemLimit) {
QMessageBox messagebox(QMessageBox::Warning, tr("Clear playlist"), tr("Playlist has %1 songs, too large to undo, are you sure you want to clear the playlist?").arg(app_->playlist_manager()->current()->rowCount()), QMessageBox::Ok|QMessageBox::Cancel);
QMessageBox messagebox(QMessageBox::Warning, tr("Clear playlist"), tr("Playlist has %1 songs, too large to undo, are you sure you want to clear the playlist?").arg(app_->playlist_manager()->current()->rowCount()), QMessageBox::Ok | QMessageBox::Cancel);
messagebox.setTextFormat(Qt::RichText);
int result = messagebox.exec();
switch (result) {
@@ -2874,22 +2888,20 @@ void MainWindow::Raise() {
show();
activateWindow();
hidden_ = false;
}
#ifdef Q_OS_WIN
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) {
#else
# else
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) {
#endif
# endif
if (exit_count_ == 0 && message) {
MSG *msg = static_cast<MSG*>(message);
thumbbar_->HandleWinEvent(msg);
}
return QMainWindow::nativeEvent(eventType, message, result);
}
#endif // Q_OS_WIN

View File

@@ -120,11 +120,11 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void closeEvent(QCloseEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
#ifdef Q_OS_WIN
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
#else
# else
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
#endif
# endif
#endif
// PlatformInterface
@@ -395,6 +395,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
bool exit_;
int exit_count_;
bool delete_files_;
bool ignore_close_;
};

View File

@@ -15,7 +15,7 @@
</property>
<property name="windowIcon">
<iconset resource="../../data/icons.qrc">
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
<normaloff>:/icons/128x128/strawberry.png</normaloff>:/icons/128x128/strawberry.png</iconset>
</property>
<widget class="QWidget" name="centralWidget">
<layout class="QVBoxLayout" name="layout_centralWidget">
@@ -483,6 +483,7 @@
<addaction name="action_new_playlist"/>
<addaction name="action_save_playlist"/>
<addaction name="action_load_playlist"/>
<addaction name="action_save_all_playlists"/>
<addaction name="separator"/>
<addaction name="action_jump"/>
<addaction name="action_clear_playlist"/>
@@ -747,6 +748,11 @@
<string>Ctrl+Shift+O</string>
</property>
</action>
<action name="action_save_all_playlists">
<property name="text">
<string>&amp;Save all playlists</string>
</property>
</action>
<action name="action_next_playlist">
<property name="text">
<string>Go to next playlist tab</string>

View File

@@ -75,7 +75,7 @@
#include "radios/radiochannel.h"
#ifdef HAVE_LIBMTP
#include "device/mtpconnection.h"
# include "device/mtpconnection.h"
#endif
void RegisterMetaTypes() {

View File

@@ -113,7 +113,7 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
Engine::EngineType use_enginetype(Engine::None);
for (int i = 0; use_enginetype == Engine::None; i++) {
switch(enginetype) {
switch (enginetype) {
case Engine::None:
#ifdef HAVE_GSTREAMER
case Engine::GStreamer:{
@@ -126,18 +126,20 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
#endif
#ifdef HAVE_VLC
case Engine::VLC:
use_enginetype=Engine::VLC;
use_enginetype = Engine::VLC;
engine_ = std::make_shared<VLCEngine>(app_->task_manager());
break;
#endif
default:
if (i > 0) { qFatal("No engine available!"); }
if (i > 0) {
qFatal("No engine available!");
}
enginetype = Engine::None;
break;
}
}
if (use_enginetype != enginetype) { // Engine was set to something else. Reset output and device.
if (use_enginetype != enginetype) { // Engine was set to something else. Reset output and device.
QSettings s;
s.beginGroup(BackendSettingsPage::kSettingsGroup);
s.setValue("engine", EngineName(use_enginetype));
@@ -167,7 +169,9 @@ void Player::Init() {
CreateEngine(enginetype);
}
if (!engine_->Init()) { qFatal("Error initializing audio engine"); }
if (!engine_->Init()) {
qFatal("Error initializing audio engine");
}
analyzer_->SetEngine(engine_.get());
@@ -426,7 +430,7 @@ void Player::PlayPlaylistInternal(const Engine::TrackChangeFlags change, const P
if (playlist == nullptr) {
qLog(Warning) << "Playlist '" << playlist_name << "' not found.";
return;
}
}
app_->playlist_manager()->SetActivePlaylist(playlist->id());
app_->playlist_manager()->SetCurrentPlaylist(playlist->id());
@@ -515,7 +519,7 @@ void Player::UnPause() {
const Song &song = current_item_->Metadata();
if (url_handlers_.contains(song.url().scheme()) && song.stream_url_can_expire()) {
const quint64 time = QDateTime::currentDateTime().toSecsSinceEpoch() - pause_time_.toSecsSinceEpoch();
if (time >= 30) { // Stream URL might be expired.
if (time >= 30) { // Stream URL might be expired.
qLog(Debug) << "Re-requesting stream URL for" << song.url();
play_offset_nanosec_ = engine_->position_nanosec();
HandleLoadResult(url_handlers_[song.url().scheme()]->StartLoading(song.url()));

View File

@@ -17,7 +17,7 @@
// caller must own the object it gives to ScopedCFTypeRef<>, and relinquishes
// an ownership claim to that object. ScopedCFTypeRef<> does not call
// CFRetain().
template <typename CFT>
template<typename CFT>
class ScopedCFTypeRef {
public:
typedef CFT element_type;

View File

@@ -27,7 +27,7 @@
#include <QtDebug>
template <typename T>
template<typename T>
class ScopedGObject {
public:
ScopedGObject() : object_(nullptr) {}

View File

@@ -30,7 +30,7 @@
#include "simpletreemodel.h"
template <typename T>
template<typename T>
class SimpleTreeItem {
public:
explicit SimpleTreeItem(int _type, SimpleTreeModel<T> *_model); // For the root item
@@ -64,7 +64,7 @@ class SimpleTreeItem {
SimpleTreeModel<T> *model;
};
template <typename T>
template<typename T>
SimpleTreeItem<T>::SimpleTreeItem(int _type, SimpleTreeModel<T> *_model)
: type(_type),
row(0),
@@ -73,7 +73,7 @@ SimpleTreeItem<T>::SimpleTreeItem(int _type, SimpleTreeModel<T> *_model)
child_model(nullptr),
model(_model) {}
template <typename T>
template<typename T>
SimpleTreeItem<T>::SimpleTreeItem(int _type, const QString &_key, T *_parent)
: type(_type),
key(_key),
@@ -87,7 +87,7 @@ SimpleTreeItem<T>::SimpleTreeItem(int _type, const QString &_key, T *_parent)
}
}
template <typename T>
template<typename T>
SimpleTreeItem<T>::SimpleTreeItem(int _type, T *_parent)
: type(_type),
lazy_loaded(false),
@@ -100,7 +100,7 @@ SimpleTreeItem<T>::SimpleTreeItem(int _type, T *_parent)
}
}
template <typename T>
template<typename T>
void SimpleTreeItem<T>::InsertNotify(T *_parent) {
parent = _parent;
model = parent->model;
@@ -111,7 +111,7 @@ void SimpleTreeItem<T>::InsertNotify(T *_parent) {
model->EndInsert();
}
template <typename T>
template<typename T>
void SimpleTreeItem<T>::DeleteNotify(int child_row) {
model->BeginDelete(static_cast<T*>(this), child_row);
delete children.takeAt(child_row);
@@ -121,7 +121,7 @@ void SimpleTreeItem<T>::DeleteNotify(int child_row) {
model->EndDelete();
}
template <typename T>
template<typename T>
void SimpleTreeItem<T>::ClearNotify() {
if (children.count()) {
model->BeginDelete(static_cast<T*>(this), 0, children.count() - 1);
@@ -133,17 +133,17 @@ void SimpleTreeItem<T>::ClearNotify() {
}
}
template <typename T>
template<typename T>
void SimpleTreeItem<T>::ChangedNotify() {
model->EmitDataChanged(static_cast<T*>(this));
}
template <typename T>
template<typename T>
SimpleTreeItem<T>::~SimpleTreeItem() {
qDeleteAll(children);
}
template <typename T>
template<typename T>
void SimpleTreeItem<T>::Delete(int child_row) {
delete children.takeAt(child_row);
@@ -151,7 +151,7 @@ void SimpleTreeItem<T>::Delete(int child_row) {
for (int i = child_row; i < children.count(); ++i) children[i]->row--;
}
template <typename T>
template<typename T>
T *SimpleTreeItem<T>::ChildByKey(const QString &_key) const {
for (T *child : children) {
if (child->key == _key) return child;

View File

@@ -27,7 +27,7 @@
#include <QObject>
#include <QAbstractItemModel>
template <typename T>
template<typename T>
class SimpleTreeModel : public QAbstractItemModel {
public:
explicit SimpleTreeModel(T *root = nullptr, QObject *parent = nullptr);
@@ -59,17 +59,17 @@ class SimpleTreeModel : public QAbstractItemModel {
T *root_;
};
template <typename T>
template<typename T>
SimpleTreeModel<T>::SimpleTreeModel(T *root, QObject *parent)
: QAbstractItemModel(parent), root_(root) {}
template <typename T>
template<typename T>
T *SimpleTreeModel<T>::IndexToItem(const QModelIndex &idx) const {
if (!idx.isValid()) return root_;
return reinterpret_cast<T*>(idx.internalPointer());
}
template <typename T>
template<typename T>
QModelIndex SimpleTreeModel<T>::ItemToIndex(T *item) const {
if (!item || !item->parent) return QModelIndex();
return createIndex(item->row, 0, item);
@@ -80,7 +80,7 @@ int SimpleTreeModel<T>::columnCount(const QModelIndex&) const {
return 1;
}
template <typename T>
template<typename T>
QModelIndex SimpleTreeModel<T>::index(int row, int, const QModelIndex &parent) const {
T *parent_item = IndexToItem(parent);
@@ -91,18 +91,18 @@ QModelIndex SimpleTreeModel<T>::index(int row, int, const QModelIndex &parent) c
}
template <typename T>
template<typename T>
QModelIndex SimpleTreeModel<T>::parent(const QModelIndex &idx) const {
return ItemToIndex(IndexToItem(idx)->parent);
}
template <typename T>
template<typename T>
int SimpleTreeModel<T>::rowCount(const QModelIndex &parent) const {
T *item = IndexToItem(parent);
return item->children.count();
}
template <typename T>
template<typename T>
bool SimpleTreeModel<T>::hasChildren(const QModelIndex &parent) const {
T *item = IndexToItem(parent);
if (item->lazy_loaded)
@@ -111,13 +111,13 @@ bool SimpleTreeModel<T>::hasChildren(const QModelIndex &parent) const {
return true;
}
template <typename T>
template<typename T>
bool SimpleTreeModel<T>::canFetchMore(const QModelIndex &parent) const {
T *item = IndexToItem(parent);
return !item->lazy_loaded;
}
template <typename T>
template<typename T>
void SimpleTreeModel<T>::fetchMore(const QModelIndex &parent) {
T *item = IndexToItem(parent);
if (!item->lazy_loaded) {
@@ -125,29 +125,29 @@ void SimpleTreeModel<T>::fetchMore(const QModelIndex &parent) {
}
}
template <typename T>
template<typename T>
void SimpleTreeModel<T>::BeginInsert(T *parent, int start, int end) {
if (end == -1) end = start;
beginInsertRows(ItemToIndex(parent), start, end);
}
template <typename T>
template<typename T>
void SimpleTreeModel<T>::EndInsert() {
endInsertRows();
}
template <typename T>
template<typename T>
void SimpleTreeModel<T>::BeginDelete(T *parent, int start, int end) {
if (end == -1) end = start;
beginRemoveRows(ItemToIndex(parent), start, end);
}
template <typename T>
template<typename T>
void SimpleTreeModel<T>::EndDelete() {
endRemoveRows();
}
template <typename T>
template<typename T>
void SimpleTreeModel<T>::EmitDataChanged(T *item) {
QModelIndex index(ItemToIndex(item));
emit dataChanged(index, index);

View File

@@ -62,7 +62,7 @@
#include "application.h"
#include "sqlquery.h"
#include "mpris_common.h"
#include "collection/sqlrow.h"
#include "sqlrow.h"
#include "tagreadermessages.pb.h"
const QStringList Song::kColumns = QStringList() << "title"
@@ -156,7 +156,6 @@ const QStringList Song::kArticles = QStringList() << "the " << "a " << "an ";
const QStringList Song::kAcceptedExtensions = QStringList() << "wav" << "flac" << "wv" << "ogg" << "oga" << "opus" << "spx" << "ape" << "mpc"
<< "mp2" << "mp3" << "m4a" << "mp4" << "aac" << "asf" << "asx" << "wma"
<< "aif << aiff" << "mka" << "tta" << "dsf" << "dsd"
<< "cue" << "m3u" << "m3u8" << "pls" << "xspf" << "asxini"
<< "ac3" << "dts";
struct Song::Private : public QSharedData {
@@ -179,7 +178,7 @@ struct Song::Private : public QSharedData {
int year_;
int originalyear_;
QString genre_;
bool compilation_; // From the file tag
bool compilation_; // From the file tag
QString composer_;
QString performer_;
QString grouping_;
@@ -1118,7 +1117,7 @@ void Song::ToItdb(Itdb_Track *track) const {
track->type1 = (d->filetype_ == FileType_MPEG ? 1 : 0);
track->type2 = (d->filetype_ == FileType_MPEG ? 1 : 0);
track->mediatype = 1; // Audio
track->mediatype = 1; // Audio
track->size = static_cast<uint>(d->filesize_);
track->time_modified = d->mtime_;
track->time_added = d->ctime_;
@@ -1542,9 +1541,9 @@ void Song::ToXesam(QVariantMap *map) const {
}
void Song::MergeUserSetData(const Song &other, const bool merge_rating) {
void Song::MergeUserSetData(const Song &other, const bool merge_playcount, const bool merge_rating) {
if (other.playcount() > 0) {
if (merge_playcount && other.playcount() > 0) {
set_playcount(other.playcount());
}

View File

@@ -187,7 +187,7 @@ class Song {
// Copies important statistics from the other song to this one, overwriting any data that already exists.
// Useful when you want updated tags from disk but you want to keep user stats.
void MergeUserSetData(const Song &other, const bool merge_rating);
void MergeUserSetData(const Song &other, const bool merge_playcount, const bool merge_rating);
// Save
void BindToQuery(SqlQuery *query) const;

View File

@@ -53,11 +53,11 @@
#include "songloader.h"
#include "tagreaderclient.h"
#include "database.h"
#include "sqlrow.h"
#include "engine/enginetype.h"
#include "engine/enginebase.h"
#include "collection/collectionbackend.h"
#include "collection/collectionquery.h"
#include "collection/sqlrow.h"
#include "playlistparsers/cueparser.h"
#include "playlistparsers/parserbase.h"
#include "playlistparsers/playlistparser.h"
@@ -290,7 +290,7 @@ SongLoader::Result SongLoader::LoadLocalAsync(const QString &filename) {
ParserBase *parser = playlist_parser_->ParserForMagic(data);
if (!parser) {
// Check the file extension as well, maybe the magic failed, or it was a basic M3U file which is just a plain list of filenames.
parser = playlist_parser_->ParserForExtension(fileinfo.suffix().toLower());
parser = playlist_parser_->ParserForExtension(PlaylistParser::Type_Load, fileinfo.suffix().toLower());
}
if (parser) { // It's a playlist!

View File

@@ -367,7 +367,7 @@ QPixmap StyleHelper::disabledSideBarIcon(const QPixmap &enabledicon) {
for (int y = 0; y < im.height(); ++y) {
auto scanLine = reinterpret_cast<QRgb*>(im.scanLine(y));
for (int x=0; x<im.width(); ++x) {
for (int x = 0; x < im.width(); ++x) {
QRgb pixel = *scanLine;
char intensity = static_cast<char>(qGray(pixel));
*scanLine = qRgba(intensity, intensity, intensity, qAlpha(pixel));
@@ -390,34 +390,33 @@ void StyleHelper::drawCornerImage(const QImage &img, QPainter *painter, const QR
const qreal bottomDIP = bottom * imagePixelRatio;
const QSize size = img.size();
if (top > 0) { //top
painter->drawImage(QRectF(rect.left() + left, rect.top(), rect.width() -right - left, top), img, QRectF(leftDIP, 0, size.width() - rightDIP - leftDIP, topDIP));
if (left > 0) { //top-left
if (top > 0) { //top
painter->drawImage(QRectF(rect.left() + left, rect.top(), rect.width() - right - left, top), img, QRectF(leftDIP, 0, size.width() - rightDIP - leftDIP, topDIP));
if (left > 0) { //top-left
painter->drawImage(QRectF(rect.left(), rect.top(), left, top), img, QRectF(0, 0, leftDIP, topDIP));
}
if (right > 0) { //top-right
if (right > 0) { //top-right
painter->drawImage(QRectF(rect.left() + rect.width() - right, rect.top(), right, top), img, QRectF(size.width() - rightDIP, 0, rightDIP, topDIP));
}
}
//left
if (left > 0) {
painter->drawImage(QRectF(rect.left(), rect.top()+top, left, rect.height() - top - bottom), img, QRectF(0, topDIP, leftDIP, size.height() - bottomDIP - topDIP));
painter->drawImage(QRectF(rect.left(), rect.top() + top, left, rect.height() - top - bottom), img, QRectF(0, topDIP, leftDIP, size.height() - bottomDIP - topDIP));
}
//center
painter->drawImage(QRectF(rect.left() + left, rect.top()+top, rect.width() -right - left, rect.height() - bottom - top), img, QRectF(leftDIP, topDIP, size.width() - rightDIP - leftDIP, size.height() - bottomDIP - topDIP));
if (right > 0) { //right
painter->drawImage(QRectF(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), img, QRectF(size.width() - rightDIP, topDIP, rightDIP, size.height() - bottomDIP - topDIP));
painter->drawImage(QRectF(rect.left() + left, rect.top() + top, rect.width() - right - left, rect.height() - bottom - top), img, QRectF(leftDIP, topDIP, size.width() - rightDIP - leftDIP, size.height() - bottomDIP - topDIP));
if (right > 0) { //right
painter->drawImage(QRectF(rect.left() + rect.width() - right, rect.top() + top, right, rect.height() - top - bottom), img, QRectF(size.width() - rightDIP, topDIP, rightDIP, size.height() - bottomDIP - topDIP));
}
if (bottom > 0) { //bottom
painter->drawImage(QRectF(rect.left() +left, rect.top() + rect.height() - bottom, rect.width() - right - left, bottom), img, QRectF(leftDIP, size.height() - bottomDIP, size.width() - rightDIP - leftDIP, bottomDIP));
if (left > 0) { //bottom-left
if (bottom > 0) { //bottom
painter->drawImage(QRectF(rect.left() + left, rect.top() + rect.height() - bottom, rect.width() - right - left, bottom), img, QRectF(leftDIP, size.height() - bottomDIP, size.width() - rightDIP - leftDIP, bottomDIP));
if (left > 0) { //bottom-left
painter->drawImage(QRectF(rect.left(), rect.top() + rect.height() - bottom, left, bottom), img, QRectF(0, size.height() - bottomDIP, leftDIP, bottomDIP));
}
if (right > 0) { //bottom-right
if (right > 0) { //bottom-right
painter->drawImage(QRectF(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), img, QRectF(size.width() - rightDIP, size.height() - bottomDIP, rightDIP, bottomDIP));
}
}
}
// Tints an image with tintColor, while preserving alpha and lightness
@@ -485,7 +484,6 @@ QList<int> StyleHelper::availableImageResolutions(const QString &fileName) {
}
}
return result;
}
} // namespace Utils
} // namespace Utils

View File

@@ -41,67 +41,66 @@ QT_END_NAMESPACE
// Helper class holding all custom color values
namespace Utils {
class StyleHelper
{
public:
static const unsigned int DEFAULT_BASE_COLOR = 0x666666;
static const int progressFadeAnimationDuration = 600;
class StyleHelper {
public:
static const unsigned int DEFAULT_BASE_COLOR = 0x666666;
static const int progressFadeAnimationDuration = 600;
// Height of the project explorer navigation bar
static int navigationWidgetHeight() { return 24; }
static qreal sidebarFontSize();
static QPalette sidebarFontPalette(const QPalette &original);
// Height of the project explorer navigation bar
static int navigationWidgetHeight() { return 24; }
static qreal sidebarFontSize();
static QPalette sidebarFontPalette(const QPalette &original);
// This is our color table, all colors derive from baseColor
static QColor requestedBaseColor() { return m_requestedBaseColor; }
static QColor baseColor(bool lightColored = false);
static QColor panelTextColor(bool lightColored = false);
static QColor highlightColor(bool lightColored = false);
static QColor shadowColor(bool lightColored = false);
static QColor borderColor(bool lightColored = false);
static QColor toolBarBorderColor();
static QColor buttonTextColor() { return QColor(0x4c4c4c); }
static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50);
static QColor alphaBlendedColors(const QColor &colorA, const QColor &colorB);
// This is our color table, all colors derive from baseColor
static QColor requestedBaseColor() { return m_requestedBaseColor; }
static QColor baseColor(bool lightColored = false);
static QColor panelTextColor(bool lightColored = false);
static QColor highlightColor(bool lightColored = false);
static QColor shadowColor(bool lightColored = false);
static QColor borderColor(bool lightColored = false);
static QColor toolBarBorderColor();
static QColor buttonTextColor() { return QColor(0x4c4c4c); }
static QColor mergedColors(const QColor &colorA, const QColor &colorB, int factor = 50);
static QColor alphaBlendedColors(const QColor &colorA, const QColor &colorB);
static QColor sidebarHighlight() { return QColor(255, 255, 255, 40); }
static QColor sidebarShadow() { return QColor(0, 0, 0, 40); }
static QColor sidebarHighlight() { return QColor(255, 255, 255, 40); }
static QColor sidebarShadow() { return QColor(0, 0, 0, 40); }
static QColor toolBarDropShadowColor() { return QColor(0, 0, 0, 70); }
static QColor toolBarDropShadowColor() { return QColor(0, 0, 0, 70); }
static QColor notTooBrightHighlightColor();
static QColor notTooBrightHighlightColor();
// Sets the base color and makes sure all top level widgets are updated
static void setBaseColor(const QColor &color);
// Sets the base color and makes sure all top level widgets are updated
static void setBaseColor(const QColor &color);
// Draws a shaded anti-aliased arrow
static void drawArrow(QStyle::PrimitiveElement element, QPainter *painter, const QStyleOption *option);
// Draws a shaded anti-aliased arrow
static void drawArrow(QStyle::PrimitiveElement element, QPainter *painter, const QStyleOption *option);
// Gradients used for panels
static void horizontalGradient(QPainter *painter, const QRect spanRect, const QRect clipRect, bool lightColored = false);
static void verticalGradient(QPainter *painter, const QRect spanRect, const QRect clipRect, bool lightColored = false);
static void menuGradient(QPainter *painter, const QRect spanRect, const QRect clipRect);
static bool usePixmapCache() { return true; }
// Gradients used for panels
static void horizontalGradient(QPainter *painter, const QRect spanRect, const QRect clipRect, bool lightColored = false);
static void verticalGradient(QPainter *painter, const QRect spanRect, const QRect clipRect, bool lightColored = false);
static void menuGradient(QPainter *painter, const QRect spanRect, const QRect clipRect);
static bool usePixmapCache() { return true; }
static QPixmap disabledSideBarIcon(const QPixmap &enabledicon);
static void drawCornerImage(const QImage &img, QPainter *painter, const QRect rect, int left = 0, int top = 0, int right = 0, int bottom = 0);
static QPixmap disabledSideBarIcon(const QPixmap &enabledicon);
static void drawCornerImage(const QImage &img, QPainter *painter, const QRect rect, int left = 0, int top = 0, int right = 0, int bottom = 0);
static void tintImage(QImage &img, const QColor &tintColor);
static QLinearGradient statusBarGradient(const QRect statusBarRect);
static void tintImage(QImage &img, const QColor &tintColor);
static QLinearGradient statusBarGradient(const QRect statusBarRect);
static QString dpiSpecificImageFile(const QString &fileName);
static QString imageFileWithResolution(const QString &fileName, int dpr);
static QList<int> availableImageResolutions(const QString &fileName);
static QString dpiSpecificImageFile(const QString &fileName);
static QString imageFileWithResolution(const QString &fileName, int dpr);
static QList<int> availableImageResolutions(const QString &fileName);
private:
static QColor m_baseColor;
static QColor m_requestedBaseColor;
static QColor m_IconsBaseColor;
static QColor m_IconsDisabledColor;
static QColor m_ProgressBarTitleColor;
private:
static QColor m_baseColor;
static QColor m_requestedBaseColor;
static QColor m_IconsBaseColor;
static QColor m_IconsDisabledColor;
static QColor m_ProgressBarTitleColor;
};
} // namespace Utils
} // namespace Utils
using Utils::StyleHelper;
#endif // STYLEHELPER_H
#endif // STYLEHELPER_H

View File

@@ -37,7 +37,7 @@
class QThread;
class Song;
template <typename HandlerType> class WorkerPool;
template<typename HandlerType> class WorkerPool;
class TagReaderClient : public QObject {
Q_OBJECT
@@ -58,8 +58,8 @@ class TagReaderClient : public QObject {
ReplyType *IsMediaFile(const QString &filename);
ReplyType *LoadEmbeddedArt(const QString &filename);
ReplyType *SaveEmbeddedArt(const QString &filename, const QByteArray &data);
ReplyType* UpdateSongPlaycount(const Song &metadata);
ReplyType* UpdateSongRating(const Song &metadata);
ReplyType *UpdateSongPlaycount(const Song &metadata);
ReplyType *UpdateSongRating(const Song &metadata);
// Convenience functions that call the above functions and wait for a response.
// These block the calling thread with a semaphore, and must NOT be called from the TagReaderClient's thread.

View File

@@ -20,13 +20,13 @@
#include <QtGlobal>
// Use these to convert between time units
const qint64 kMsecPerSec = 1000ll;
const qint64 kUsecPerMsec = 1000ll;
const qint64 kUsecPerSec = 1000000ll;
const qint64 kNsecPerUsec = 1000ll;
const qint64 kNsecPerMsec = 1000000ll;
const qint64 kNsecPerSec = 1000000000ll;
constexpr qint64 kMsecPerSec = 1000ll;
constexpr qint64 kUsecPerMsec = 1000ll;
constexpr qint64 kUsecPerSec = 1000000ll;
constexpr qint64 kNsecPerUsec = 1000ll;
constexpr qint64 kNsecPerMsec = 1000000ll;
constexpr qint64 kNsecPerSec = 1000000000ll;
const qint64 kSecsPerDay = 24 * 60 * 60;
constexpr qint64 kSecsPerDay = 24 * 60 * 60;
#endif // TIMECONSTANTS_H

View File

@@ -376,11 +376,11 @@ void OpenInFileManager(const QString &path, const QUrl &url) {
QString cmd = setting.value("Exec").toString();
if (cmd.isEmpty()) break;
cmd = cmd.remove(QRegularExpression("[%][a-zA-Z]*( |$)", QRegularExpression::CaseInsensitiveOption));
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
# if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
command_params = cmd.split(' ', Qt::SkipEmptyParts);
#else
# else
command_params = cmd.split(' ', QString::SkipEmptyParts);
#endif
# endif
command = command_params.first();
command_params.removeFirst();
}
@@ -786,19 +786,7 @@ QString DesktopEnvironment() {
}
QString UnicodeToAscii(QString unicode) {
#ifdef _MSC_VER
return unicode
.replace(QChar(229), "a")
.replace(QChar(197), 'A')
.replace(QChar(230), "ae")
.replace(QChar(198), "AE")
.replace(QChar(248), 'o')
.replace(QChar(216), 'O');
#else
QString UnicodeToAscii(const QString &unicode) {
#ifdef LC_ALL
setlocale(LC_ALL, "");
@@ -829,9 +817,6 @@ QString UnicodeToAscii(QString unicode) {
delete[] output_ptr;
return ret;
#endif // _MSC_VER
}
QString MacAddress() {
@@ -988,9 +973,9 @@ HRGN qt_RectToHRGN(const QRect &rc) {
HRGN toHRGN(const QRegion &region);
HRGN toHRGN(const QRegion &region) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
return region.toHRGN();
#else
# else
const int rect_count = region.rectCount();
if (rect_count == 0) {
@@ -1009,13 +994,12 @@ HRGN toHRGN(const QRegion &region) {
return resultRgn;
#endif // Qt 6
# endif // Qt 6
}
void enableBlurBehindWindow(QWindow *window, const QRegion &region) {
DWM_BLURBEHIND dwmbb = {0, 0, nullptr, 0};
DWM_BLURBEHIND dwmbb = { 0, 0, nullptr, 0 };
dwmbb.dwFlags = DWM_BB_ENABLE;
dwmbb.fEnable = TRUE;
HRGN rgn = nullptr;

View File

@@ -115,11 +115,11 @@ enum IoPriority {
IOPRIO_CLASS_BE,
IOPRIO_CLASS_IDLE,
};
enum {
IOPRIO_WHO_PROCESS = 1,
IOPRIO_WHO_PGRP,
IOPRIO_WHO_USER,
};
enum {
IOPRIO_WHO_PROCESS = 1,
IOPRIO_WHO_PGRP,
IOPRIO_WHO_USER,
};
static const int IOPRIO_CLASS_SHIFT = 13;
long SetThreadIOPriority(const IoPriority priority);
@@ -132,7 +132,7 @@ QString GetRandomString(const int len, const QString &UseCharacters);
QString DesktopEnvironment();
QString UnicodeToAscii(QString unicode);
QString UnicodeToAscii(const QString &unicode);
QString MacAddress();
@@ -157,10 +157,10 @@ class ScopedWCharArray {
QString ToString() const { return QString::fromWCharArray(data_.get()); }
wchar_t *get() const { return data_.get(); }
explicit operator wchar_t*() const { return get(); }
explicit operator wchar_t *() const { return get(); }
qint64 characters() const { return chars_; }
qint64 bytes() const { return (chars_ + 1) *sizeof(wchar_t); }
qint64 bytes() const { return (chars_ + 1) * sizeof(wchar_t); }
private:
Q_DISABLE_COPY(ScopedWCharArray)

View File

@@ -30,7 +30,7 @@
#include <QtDebug>
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
# define _WIN32_WINNT 0x0600
#endif
#include <windows.h>
@@ -77,18 +77,18 @@ ITaskbarList3 *Windows7ThumbBar::CreateTaskbarList() {
ITaskbarList3 *taskbar_list = nullptr;
// Copied from win7 SDK shobjidl.h
static const GUID CLSID_ITaskbarList = { 0x56FDF344,0xFD6D,0x11d0,{0x95,0x8A,0x00,0x60,0x97,0xC9,0xA0,0x90}};
static const GUID CLSID_ITaskbarList = { 0x56FDF344, 0xFD6D, 0x11d0, { 0x95, 0x8A, 0x00, 0x60, 0x97, 0xC9, 0xA0, 0x90 } };
// Create the taskbar list
HRESULT hr = CoCreateInstance(CLSID_ITaskbarList, nullptr, CLSCTX_ALL, IID_ITaskbarList3, reinterpret_cast<void**>(&taskbar_list));
if (hr != S_OK) {
qLog(Warning) << "Error creating the ITaskbarList3 interface" << Qt::hex << DWORD (hr);
qLog(Warning) << "Error creating the ITaskbarList3 interface" << Qt::hex << DWORD(hr);
return nullptr;
}
hr = taskbar_list->HrInit();
if (hr != S_OK) {
qLog(Warning) << "Error initializing taskbar list" << Qt::hex << DWORD (hr);
qLog(Warning) << "Error initializing taskbar list" << Qt::hex << DWORD(hr);
taskbar_list->Release();
return nullptr;
}
@@ -145,7 +145,7 @@ void Windows7ThumbBar::HandleWinEvent(MSG *msg) {
qLog(Debug) << "Adding" << actions_.count() << "buttons";
HRESULT hr = taskbar_list->ThumbBarAddButtons(reinterpret_cast<HWND>(widget_->winId()), actions_.count(), buttons);
if (hr != S_OK) {
qLog(Debug) << "Failed to add buttons" << Qt::hex << DWORD (hr);
qLog(Debug) << "Failed to add buttons" << Qt::hex << DWORD(hr);
}
for (int i = 0; i < actions_.count(); ++i) {
@@ -188,12 +188,11 @@ void Windows7ThumbBar::ActionChanged() {
button->iId = i;
SetupButton(action, button);
}
HRESULT hr = taskbar_list->ThumbBarUpdateButtons(reinterpret_cast<HWND>(widget_->winId()), actions_.count(), buttons);
if (hr != S_OK) {
qLog(Debug) << "Failed to update buttons" << Qt::hex << DWORD (hr);
qLog(Debug) << "Failed to update buttons" << Qt::hex << DWORD(hr);
}
for (int i = 0; i < actions_.count(); ++i) {

View File

@@ -211,7 +211,7 @@ QUrl AlbumCoverChoiceController::LoadCoverFromFile(Song *song) {
if (QImage(cover_file).isNull()) return QUrl();
switch(get_save_album_cover_type()) {
switch (get_save_album_cover_type()) {
case CollectionSettingsPage::SaveCoverType_Embedded:
if (song->save_embedded_cover_supported()) {
SaveCoverEmbeddedAutomatic(*song, cover_file);

View File

@@ -106,8 +106,8 @@ void AlbumCoverLoader::ReloadSettings() {
QString AlbumCoverLoader::AlbumCoverFilename(QString artist, QString album, const QString &extension) {
artist.remove('/');
album.remove('/');
artist.remove('/').remove('\\');
album.remove('/').remove('\\');
QString filename = artist + "-" + album;
filename = Utilities::UnicodeToAscii(filename.toLower());
@@ -157,7 +157,7 @@ QString AlbumCoverLoader::CoverFilePath(const Song::Source source, const QString
save_cover_filename_ == CollectionSettingsPage::SaveCoverFilename_Pattern &&
!cover_pattern_.isEmpty()) {
filename = CoverFilenameFromVariable(artist, album);
filename.remove(OrganizeFormat::kInvalidFatCharacters);
filename.remove(OrganizeFormat::kInvalidFatCharacters).remove('/').remove('\\');
if (cover_lowercase_) filename = filename.toLower();
if (cover_replace_spaces_) filename.replace(QRegularExpression("\\s"), "-");
if (!extension.isEmpty()) {
@@ -673,7 +673,7 @@ void AlbumCoverLoader::SaveEmbeddedCover(const quint64 id, const QList<QUrl> &ur
}
if (!file.open(QIODevice::ReadOnly)) {
qLog(Error) << "Failed to open cover file" << cover_filename << "for reading:" << file.errorString();
qLog(Error) << "Failed to open cover file" << cover_filename << "for reading:" << file.errorString();
emit SaveEmbeddedCoverAsyncFinished(id, false, false);
return;
}

View File

@@ -71,9 +71,9 @@
#include "core/imageutils.h"
#include "core/tagreaderclient.h"
#include "core/database.h"
#include "core/sqlrow.h"
#include "widgets/forcescrollperpixel.h"
#include "widgets/qsearchfield.h"
#include "collection/sqlrow.h"
#include "collection/collectionbackend.h"
#include "collection/collectionquery.h"
#include "playlist/songmimedata.h"

View File

@@ -33,7 +33,7 @@ CoverSearchStatistics::CoverSearchStatistics()
chosen_width_(0),
chosen_height_(0) {}
CoverSearchStatistics &CoverSearchStatistics::operator +=(const CoverSearchStatistics &other) {
CoverSearchStatistics &CoverSearchStatistics::operator+=(const CoverSearchStatistics &other) {
network_requests_made_ += other.network_requests_made_;
bytes_transferred_ += other.bytes_transferred_;

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