Compare commits

..

138 Commits

Author SHA1 Message Date
Jonas Kvinge
ac31d79294 Release 1.2.16 2025-12-17 00:08:06 +01:00
Jonas Kvinge
4ffebd77b1 Update Changelog 2025-12-17 00:07:41 +01:00
Strawberry Bot
6682efae2f New translations 2025-12-16 22:41:10 +01:00
Jonas Kvinge
480161c6b7 Update Changelog 2025-12-16 22:38:55 +01:00
Jonas Kvinge
a8ba420d72 ErrorDialog: Use QApplication::activeWindow 2025-12-16 22:32:11 +01:00
dependabot[bot]
fc0ec91652 Bump actions/download-artifact from 6 to 7
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 18:15:02 +01:00
dependabot[bot]
0701b97324 Bump actions/upload-artifact from 5 to 6
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-15 18:14:44 +01:00
Jonas Kvinge
3867932e1e PlaylistView: Don't automatically scroll on dynamic playlists
Fixes #1427
2025-12-14 04:55:20 +01:00
Jonas Kvinge
e2907f6051 PlaylistView: Use Qt::CopyAction for drag
Fixes #1815
2025-12-14 04:41:58 +01:00
Jonas Kvinge
0827ec7f16 PlaylistSequence: Fix icon size
Fixes #1838
2025-12-14 04:28:25 +01:00
Jonas Kvinge
24d2adf363 PlaylistView: Set current index when automatically selecting track
Fixes #1825
2025-12-14 04:02:40 +01:00
Jonas Kvinge
592729d00b SliderSlider: Use SC_SliderGroove
Fixes #1675
2025-12-14 01:57:47 +01:00
Jonas Kvinge
c4a564bb56 NetworkAccessManager: Use full application name for user agent 2025-12-14 01:36:53 +01:00
Jonas Kvinge
812a02a3a1 Update Changelog 2025-12-14 01:04:45 +01:00
Strawberry Bot
944936914b New translations 2025-12-14 01:01:06 +01:00
Jonas Kvinge
e7c901d4f3 Update Changelog 2025-12-14 00:59:42 +01:00
Jonas Kvinge
8e996119af Make using sort tags optional 2025-12-14 00:52:19 +01:00
Jonas Kvinge
4348a654ca TagReaderResult: Fix file save error message 2025-12-14 00:52:19 +01:00
dependabot[bot]
f0be1c782a Bump vmactions/openbsd-vm from 1.2.4 to 1.2.5
Bumps [vmactions/openbsd-vm](https://github.com/vmactions/openbsd-vm) from 1.2.4 to 1.2.5.
- [Release notes](https://github.com/vmactions/openbsd-vm/releases)
- [Commits](https://github.com/vmactions/openbsd-vm/compare/v1.2.4...v1.2.5)

---
updated-dependencies:
- dependency-name: vmactions/openbsd-vm
  dependency-version: 1.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-11 00:36:57 +01:00
dependabot[bot]
e9898d08bc Bump vmactions/freebsd-vm from 1.2.9 to 1.3.0
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.9 to 1.3.0.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.9...v1.3.0)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-11 00:36:24 +01:00
Jonas Kvinge
1ad13cd3b0 Add lyrics from lrclib.net 2025-12-09 18:45:57 +01:00
Jonas Kvinge
5c640e0e36 LyricsFetcherSearch: Improve handling timeout 2025-12-09 18:41:55 +01:00
Jonas Kvinge
059def8d0c Add duration to lyrics search request 2025-12-09 18:40:45 +01:00
Jonas Kvinge
cf15a1f423 CDDALister: Add Q_UNUSED 2025-12-09 01:33:13 +01:00
Jonas Kvinge
5d35b0eedd BlockAnalyzer: Formatting 2025-12-09 01:19:02 +01:00
Jonas Kvinge
5fcb71d08f Formatting 2025-12-09 01:16:41 +01:00
Jonas Kvinge
15c2237d4a AlbumCoverChoiceController: Fix incorrectly formatted switch 2025-12-08 23:55:13 +01:00
Jonas Kvinge
93af866185 Formatting 2025-12-08 23:49:48 +01:00
dependabot[bot]
109ff90401 Bump vmactions/freebsd-vm from 1.2.8 to 1.2.9
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.8 to 1.2.9.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.8...v1.2.9)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.9
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-08 17:11:17 +01:00
Jonas Kvinge
d4b06289c3 clang-format: Add new KeepEmptyLines option 2025-12-07 01:20:39 +01:00
dependabot[bot]
4351c555a0 Bump apple-actions/import-codesign-certs from 5 to 6
Bumps [apple-actions/import-codesign-certs](https://github.com/apple-actions/import-codesign-certs) from 5 to 6.
- [Release notes](https://github.com/apple-actions/import-codesign-certs/releases)
- [Commits](https://github.com/apple-actions/import-codesign-certs/compare/v5...v6)

---
updated-dependencies:
- dependency-name: apple-actions/import-codesign-certs
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-07 00:51:50 +01:00
Strawberry Bot
ce4db40983 New translations 2025-12-07 00:06:44 +01:00
Jonas Kvinge
d37fb7410c ResizableTextEdit: Set word wrap 2025-12-01 23:23:23 +01:00
Jonas Kvinge
f1cdd71494 ResizableTextEdit: Move updateGeometry after resize 2025-12-01 23:23:05 +01:00
Jonas Kvinge
000ba997fb Playlist: Preserve track order in album shuffle mode
Fixes #1623
2025-12-01 22:47:12 +01:00
dependabot[bot]
579efffd14 Bump vmactions/openbsd-vm from 1.2.3 to 1.2.4
Bumps [vmactions/openbsd-vm](https://github.com/vmactions/openbsd-vm) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/vmactions/openbsd-vm/releases)
- [Commits](https://github.com/vmactions/openbsd-vm/compare/v1.2.3...v1.2.4)

---
updated-dependencies:
- dependency-name: vmactions/openbsd-vm
  dependency-version: 1.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 19:47:08 +01:00
dependabot[bot]
3a098c8a0c Bump vmactions/freebsd-vm from 1.2.7 to 1.2.8
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.7 to 1.2.8.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.7...v1.2.8)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-12-01 18:46:03 +01:00
bastimeyer
5bce0ae87f GlobalShortcutsBackendKGlobalAccel: Add globalShortcutRepeated signal 2025-11-30 18:25:26 +01:00
Jonas Kvinge
afe6967c46 GstEnginePipeline: Handle "missing-plugin" messages 2025-11-30 18:13:30 +01:00
Jonas Kvinge
e91bab6d42 GstEngine: Only emit error for debugstr if it's set 2025-11-30 18:13:30 +01:00
Jonas Kvinge
5a64247761 PlaylistView: Use lamda in sort 2025-11-30 16:58:08 +01:00
Jonas Kvinge
9ed89afdb2 SpotifyService: Use 127.0.0.1 in redirect URL 2025-11-30 16:32:56 +01:00
Jonas Kvinge
0ac338026c About: Update sponsor info 2025-11-30 02:47:39 +01:00
Jonas Kvinge
4e5f84a7b7 RichPresence: Use pretty title 2025-11-26 19:14:16 +01:00
Jonas Kvinge
320a3c6815 RichPresence: Add copyright 2025-11-26 19:14:05 +01:00
Jonas Kvinge
72dd1d783a Turn on git revision 2025-11-25 21:13:00 +01:00
Jonas Kvinge
d2205cfe81 Release 1.2.15 2025-11-25 02:50:34 +01:00
Jonas Kvinge
5830f247f6 Update Changelog 2025-11-25 02:05:26 +01:00
Jonas Kvinge
8b4c57d933 GroupedIconView: Remove deprecated QStyle::State_Editing 2025-11-23 03:14:57 +01:00
Jonas Kvinge
67cec09176 gitignore: Add .qtcreator 2025-11-23 03:14:24 +01:00
Jonas Kvinge
2df658e1f3 ListenBrainzScrobbler: Ignore connection closed 2025-11-23 01:11:59 +01:00
Jonas Kvinge
f3bc9b151c README: Update OBS URL's 2025-11-23 00:47:56 +01:00
Jonas Kvinge
b06b59d0c5 nsi: Bump ffmpeg for msvc x86_64 2025-11-22 14:20:40 +01:00
Jonas Kvinge
99d75ade06 CI: Bump MSVC SDK version 2025-11-22 02:15:20 +01:00
Jonas Kvinge
3f63246068 Add macos-15-intel runner 2025-11-22 00:47:30 +01:00
dependabot[bot]
b205a5f964 Bump actions/checkout from 5 to 6
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 19:46:25 +01:00
dependabot[bot]
aeaef12dd4 Bump vmactions/freebsd-vm from 1.2.6 to 1.2.7
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.6 to 1.2.7.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.6...v1.2.7)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-21 19:45:43 +01:00
Jonas Kvinge
02d76f17f7 CollectionModel: Make SortText static 2025-11-15 22:10:55 +01:00
Strawberry Bot
e4e12c6fa6 New translations 2025-11-13 23:25:27 +01:00
uninstall-your-browser
270ae6085b FilterParser: Convert number to nanoseconds for length filter 2025-11-13 23:23:19 +01:00
Jonas Kvinge
7065a405a5 CI: Remove macos-13 2025-11-12 01:10:19 +01:00
Jonas Kvinge
d8c72c3dd9 ParserBase: Remove use of QString::removeFirst 2025-11-11 21:37:19 +01:00
Jonas Kvinge
b65502e167 XSPFParser: Handle platform and url 2025-11-11 00:56:36 +01:00
Jonas Kvinge
132f8df853 ParserBase: Convert spotify URLs 2025-11-11 00:56:13 +01:00
Jonas Kvinge
12e3cffe63 CI: Fix ssh command 2025-11-10 20:43:09 +01:00
dependabot[bot]
56a637682d Bump vmactions/freebsd-vm from 1.2.5 to 1.2.6
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.5...v1.2.6)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 20:01:38 +01:00
dependabot[bot]
d9b105f89e Bump vmactions/openbsd-vm from 1.2.2 to 1.2.3
Bumps [vmactions/openbsd-vm](https://github.com/vmactions/openbsd-vm) from 1.2.2 to 1.2.3.
- [Release notes](https://github.com/vmactions/openbsd-vm/releases)
- [Commits](https://github.com/vmactions/openbsd-vm/compare/v1.2.2...v1.2.3)

---
updated-dependencies:
- dependency-name: vmactions/openbsd-vm
  dependency-version: 1.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-10 17:26:57 +01:00
dependabot[bot]
bd6b45e43f Bump vmactions/freebsd-vm from 1.2.4 to 1.2.5
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.4 to 1.2.5.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.4...v1.2.5)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 18:54:16 +01:00
dependabot[bot]
539172fb70 Bump vmactions/openbsd-vm from 1.2.1 to 1.2.2
Bumps [vmactions/openbsd-vm](https://github.com/vmactions/openbsd-vm) from 1.2.1 to 1.2.2.
- [Release notes](https://github.com/vmactions/openbsd-vm/releases)
- [Commits](https://github.com/vmactions/openbsd-vm/compare/v1.2.1...v1.2.2)

---
updated-dependencies:
- dependency-name: vmactions/openbsd-vm
  dependency-version: 1.2.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-11-03 18:11:33 +01:00
Jonas Kvinge
ebd92b3a7f nsi: Bump ffmpeg 2025-11-01 12:22:43 +01:00
Jonas Kvinge
b00ae5b210 nsi: Bump icu 2025-10-31 23:47:49 +01:00
Jonas Kvinge
c8e3cf981b main: Try different language codes for QtSparkle 2025-10-31 23:06:00 +01:00
Jonas Kvinge
038f69779f CI: Manually codesign libbrotli 2025-10-30 23:56:17 +01:00
Jonas Kvinge
a4de7559ac Fix loading language from system UI languages
Fixes #1847
2025-10-30 23:54:42 +01:00
dependabot[bot]
0537b072fe Bump actions/download-artifact from 5 to 6
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-30 01:36:11 +01:00
dependabot[bot]
2657c9f96a Bump actions/upload-artifact from 4 to 5
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-30 01:35:56 +01:00
Jonas Kvinge
7e178b1f1a PlaylistView: Always keep EditKeyPressed 2025-10-30 01:35:30 +01:00
Jonas Kvinge
dd8513d02c PlaylistView: Disable EditKeyPressed when inline metadata editing is disabled 2025-10-27 20:19:50 +01:00
Andrew Tribick
5f0175094b Support unofficial::getopt-win32::getopt as a getopt library target
Handles the vcpkg case
2025-10-26 13:06:11 +01:00
Jonas Kvinge
b4c5b9e1e1 Turn on git revision 2025-10-26 13:05:56 +01:00
Jonas Kvinge
2ce0ed2ef8 Release 1.2.14 2025-10-25 23:03:51 +02:00
dependabot[bot]
176768f7f8 Bump vmactions/openbsd-vm from 1.2.0 to 1.2.1
Bumps [vmactions/openbsd-vm](https://github.com/vmactions/openbsd-vm) from 1.2.0 to 1.2.1.
- [Release notes](https://github.com/vmactions/openbsd-vm/releases)
- [Commits](https://github.com/vmactions/openbsd-vm/compare/v1.2.0...v1.2.1)

---
updated-dependencies:
- dependency-name: vmactions/openbsd-vm
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-25 02:03:03 +02:00
Jonas Kvinge
50b954034c OpenTidalCoverProvider: Check for already finished 2025-10-23 00:39:40 +02:00
Jonas Kvinge
cab7b6c335 Update Changelog 2025-10-23 00:34:46 +02:00
Jonas Kvinge
fce1dacafc OpenTidalCoverProvider: Adapt to new API 2025-10-23 00:34:06 +02:00
Jonas Kvinge
94aa6fb940 MusicBrainzClient: Add missing clear 2025-10-22 20:44:22 +02:00
Jonas Kvinge
0cfd4aaad1 Update Changelog 2025-10-22 20:29:54 +02:00
Strawberry Bot
9e72b4fe80 New translations strawberry_en_us.ts (Swedish) 2025-10-20 21:28:23 +02:00
Jiří Pinkava
1151443372 Add support to play webm media files 2025-10-20 21:28:00 +02:00
Jonas Kvinge
8f6993e7c8 nsi: Add libgstwasapi2 for mingw 2025-10-20 20:39:38 +02:00
Jonas Kvinge
a6ab1a7689 GstEngine: Enable exclusive mode for wasapi2sink 2025-10-19 19:09:49 +02:00
Jonas Kvinge
098b21d818 Use MMDeviceFinder for wasapi2sink 2025-10-19 18:32:42 +02:00
Jonas Kvinge
d61adeb595 Add option not to remove "Remastered", etc from song titles 2025-10-18 19:57:38 +02:00
Cesar Enrique Garcia Dabo
8bfc3bc41c SubsonicRequest: Use coverArt from album 2025-10-08 21:49:04 +02:00
Jonas Kvinge
0dda2feec3 Improve README.md 2025-10-06 00:17:29 +02:00
Jonas Kvinge
1d0d03ed83 Rewrite MusicBrainzClient
Use Json instead of XML, make Disc ID requests respect rate limiting, handle sort names.
2025-10-05 21:42:14 +02:00
Jonas Kvinge
330284f03e CollectionModel: Log when song already exists 2025-10-05 21:33:41 +02:00
Jonas Kvinge
fc3ed3a2ce CollectionModel: Avoid duplicate resets 2025-10-05 21:33:22 +02:00
dependabot[bot]
6a656036fe Bump vmactions/freebsd-vm from 1.2.3 to 1.2.4
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.3...v1.2.4)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.4
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-09-22 18:26:55 +02:00
Jonas Kvinge
5c76c633a5 CI: Use copydlldeps for msvc arm64 too 2025-09-21 20:59:16 +02:00
Jonas Kvinge
d487c3ea07 nsi: Remove gstwinrt-1.0-0.dll 2025-09-21 20:58:39 +02:00
Jonas Kvinge
83dca405af CI: Remove copy of liblzma.dll 2025-09-19 21:29:34 +02:00
Strawberry Bot
acd0b6d3ea New translations 2025-09-19 20:43:20 +02:00
Jonas Kvinge
159242aff4 nsi: Remove liblzma.dll 2025-09-19 01:51:28 +02:00
Jonas Kvinge
4b014253cf Remove libre.fm 2025-09-18 00:22:11 +02:00
Jonas Kvinge
1ec6b5582e nsi: Move files 2025-09-12 22:02:39 +02:00
Jonas Kvinge
08b8d04500 nsi: Use gnutls with static deps 2025-09-12 21:28:49 +02:00
7xnl
54679b1d57 discord: fixed timestamp update when seeking
When seeking in a song, `RichPresence::Seeked()` receives the new
position in microseconds and is supposed to update the RPC timestamp
with the new position in seconds. However, it actually converts the
value to milliseconds, meaning that if, for example, you seek to 0:05 in
a song, Discord will think you seeked to 83:20, or 5000 seconds from the
beginning of the song.

This commit fixes this by simply dividing the microseconds value by one
million instead of one thousand.
2025-09-11 23:40:40 +02:00
Jonas Kvinge
8d648e668e nsi: Update to new MSVC gnutls dependencies 2025-09-10 18:30:51 +02:00
Jonas Kvinge
5897e786dc Remove unused macversion script 2025-09-08 22:06:32 +02:00
Jonas Kvinge
7f549aa991 CI: Fix ssh command for MSVC rsync 2025-09-07 17:08:19 +02:00
Jonas Kvinge
792e7b6274 BackendSettingsPage: Remove unused errordialog.h include 2025-09-07 16:46:41 +02:00
Jonas Kvinge
92c58b0b60 Fix showing error dialog minimized when main window is not active
Fixes #1739
2025-09-07 15:46:26 +02:00
Jonas Kvinge
5fac9a1c8d BackendSettingsPage: Remove unused ErrorDialog 2025-09-07 14:22:42 +02:00
Jonas Kvinge
7f4f715003 ContextView: Remove EBU R 128
It breaks wordwrap
2025-09-07 13:53:59 +02:00
Jonas Kvinge
75d1d4098e CI: Install KDSingleApplication on Ubuntu 2025-09-01 23:50:16 +02:00
Jonas Kvinge
30e80068a3 CI: Add Ubuntu Questing 2025-09-01 23:49:50 +02:00
Jonas Kvinge
5fe9a1528f CI: Only build KDSingleApplication on bookworm 2025-09-01 23:45:49 +02:00
Jonas Kvinge
7777eda115 CI: Add Debian Forky 2025-09-01 23:45:17 +02:00
Jonas Kvinge
ce4f2ece93 CI: Add openSUSE Leap 16.0 2025-09-01 21:36:46 +02:00
Strawberry Bot
52399d73fe New translations 2025-09-01 00:27:28 +02:00
Jonas Kvinge
6e98166148 Turn on git revision 2025-09-01 00:26:22 +02:00
Jonas Kvinge
c658a77b05 Release 1.2.13 2025-08-31 22:33:48 +02:00
Jonas Kvinge
1880dc8153 Update Changelog 2025-08-31 22:27:00 +02:00
7xnl
b5fd3d5717 Add settings customize Discord status text
The new settings let you customize the "Listening to" status text, according to the [status display types](https://discord.com/developers/docs/events/gateway-events#activity-object).

Fixes #1796.
2025-08-31 22:11:59 +02:00
Jonas Kvinge
3c3480fb84 SystemTrayIcon: Respect device aspect ratio
Fixes #1782
2025-08-31 02:34:13 +02:00
Jonas Kvinge
f628914173 MainWindow: Rename systemtrayicon 2025-08-31 00:37:09 +02:00
Jonas Kvinge
c100fb1bb8 TagReaderTagLib: Fallback to "Other" cover type
Fixes #1793
2025-08-31 00:20:00 +02:00
Jonas Kvinge
8c804c4fba Refactor CDDA loading signal/slots
Fixes #1803
2025-08-31 00:01:55 +02:00
Jonas Kvinge
912a7c7da9 MusicBrainzClient: Fix typo 2025-08-30 23:55:27 +02:00
Jonas Kvinge
0a5815c82e StyleSheetLoader: Set alpha on other platforms than macOS
Fixes #1806
2025-08-26 22:48:58 +02:00
Jonas Kvinge
6513b3032b CMake: Check additional names for getopt 2025-08-24 22:36:13 +02:00
Jonas Kvinge
8c51401bdc MacOsDeviceLister: Fix build without MTP
Fixes #1804
2025-08-24 01:28:22 +02:00
dependabot[bot]
45fc9c83d4 Bump vmactions/openbsd-vm from 1.1.8 to 1.2.0
Bumps [vmactions/openbsd-vm](https://github.com/vmactions/openbsd-vm) from 1.1.8 to 1.2.0.
- [Release notes](https://github.com/vmactions/openbsd-vm/releases)
- [Commits](https://github.com/vmactions/openbsd-vm/compare/v1.1.8...v1.2.0)

---
updated-dependencies:
- dependency-name: vmactions/openbsd-vm
  dependency-version: 1.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-20 23:57:47 +02:00
dependabot[bot]
be57d8147a Bump vmactions/freebsd-vm from 1.2.1 to 1.2.3
Bumps [vmactions/freebsd-vm](https://github.com/vmactions/freebsd-vm) from 1.2.1 to 1.2.3.
- [Release notes](https://github.com/vmactions/freebsd-vm/releases)
- [Commits](https://github.com/vmactions/freebsd-vm/compare/v1.2.1...v1.2.3)

---
updated-dependencies:
- dependency-name: vmactions/freebsd-vm
  dependency-version: 1.2.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-08-19 18:25:13 +02:00
Jonas Kvinge
a97908fb6b CI: Bump msvc sdk 2025-08-17 13:44:57 +02:00
Lars Wendler
c0417d4bb3 cdda: fix build without musicbrainz
With -DENABLE_MUSICBRAINZ=NO the following build error occurs since 1.2.12:

/var/tmp/portage/media-sound/strawberry-1.2.12_pre/work/strawberry-1.2.12/src/de
vice/cddasongloader.cpp:58:91: error: ‘LoadMusicBrainzCDTags’ is not a member of
 ‘CDDASongLoader’
   58 |   QObject::connect(this, &CDDASongLoader::MusicBrainzDiscIdLoaded, this,
 &CDDASongLoader::LoadMusicBrainzCDTags);
      |
                  ^~~~~~~~~~~~~~~~~~~~~
2025-08-13 19:49:41 +02:00
Jonas Kvinge
062e2cfb84 Turn on git revision 2025-08-13 00:20:05 +02:00
383 changed files with 12934 additions and 4719 deletions

View File

@@ -130,7 +130,10 @@ InsertBraces: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
KeepEmptyLines:
AtEndOfFile: true
AtStartOfBlock: true
AtStartOfFile: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''

View File

@@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
opensuse_version: [ 'tumbleweed', 'leap:15.6' ]
opensuse_version: [ 'tumbleweed', 'leap:15.6', 'leap:16.0' ]
container:
image: opensuse/${{matrix.opensuse_version}}
steps:
@@ -27,11 +27,11 @@ jobs:
- name: Upgrade packages (Leap)
if: matrix.opensuse_version != 'tumbleweed'
run: zypper -n --gpg-auto-import-keys up
- name: Install gcc (Tumbleweed)
if: matrix.opensuse_version == 'tumbleweed'
- name: Install gcc
if: matrix.opensuse_version != 'leap:15.6'
run: zypper -n --gpg-auto-import-keys in gcc gcc-c++
- name: Install gcc (Leap)
if: matrix.opensuse_version != 'tumbleweed'
- name: Install gcc (leap:15.6)
if: matrix.opensuse_version == 'leap:15.6'
run: zypper -n --gpg-auto-import-keys in gcc14 gcc14-c++
- name: Install packages
run: >
@@ -83,7 +83,7 @@ jobs:
sparsehash-devel
rapidjson-devel
- name: Install kdsingleapplication-qt6-devel
if: matrix.opensuse_version == 'tumbleweed'
if: matrix.opensuse_version != 'leap:15.6'
run: zypper -n --gpg-auto-import-keys in kdsingleapplication-qt6-devel
- name: Build and install KDSingleApplication
if: matrix.opensuse_version == 'leap:15.6'
@@ -97,7 +97,7 @@ jobs:
cmake --build build --config Release --parallel 4
cmake --install build
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -115,14 +115,14 @@ jobs:
- name: Copy source tarball
working-directory: build
run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
- name: Build RPM (Tumbleweed)
if: matrix.opensuse_version == 'tumbleweed'
- name: Build RPM
if: matrix.opensuse_version != 'leap:15.6'
env:
RPM_BUILD_NCPUS: 4
working-directory: build
run: rpmbuild -ba strawberry.spec
- name: Build RPM (Leap)
if: matrix.opensuse_version != 'tumbleweed'
- name: Build RPM (leap:15.6)
if: matrix.opensuse_version == 'leap:15.6'
env:
RPM_BUILD_NCPUS: 4
CC: gcc-14
@@ -134,14 +134,14 @@ jobs:
run: echo "subdir=$(echo ${{matrix.opensuse_version}} | sed 's/leap:/lp/g' | sed 's/\.//g')" > $GITHUB_OUTPUT
- name: Upload source
if: matrix.opensuse_version == 'tumbleweed'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: source
path: |
/usr/src/packages/SOURCES/*.xz
- name: Upload rpm
if: matrix.opensuse_version != 'tumbleweed'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: opensuse-${{steps.set-subdir.outputs.subdir}}
path: |
@@ -209,7 +209,7 @@ jobs:
sparsehash-devel
rapidjson-devel
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -234,7 +234,7 @@ jobs:
working-directory: build
run: rpmbuild -ba strawberry.spec
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: fedora-${{matrix.fedora_version}}
path: |
@@ -307,7 +307,7 @@ jobs:
- name: Remove files
run: rm -rf /usr/lib64/qt6/lib/cmake/Qt6Sql/{Qt6QMYSQL*,Qt6QODBCD*,Qt6QPSQL*,Qt6QIBase*}
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -333,7 +333,7 @@ jobs:
run: rpmbuild -ba strawberry.spec
- name: Upload artifacts
if: matrix.openmandriva_version != 'cooker'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: openmandriva-${{matrix.openmandriva_version}}
path: |
@@ -409,7 +409,7 @@ jobs:
cmake --build build --config Release --parallel 4
cmake --install build
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -434,7 +434,7 @@ jobs:
working-directory: build
run: rpmbuild -ba strawberry.spec
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: mageia-${{matrix.mageia_version}}
path: |
@@ -449,7 +449,7 @@ jobs:
strategy:
fail-fast: false
matrix:
debian_version: [ 'bookworm', 'trixie' ]
debian_version: [ 'bookworm', 'trixie', 'forky' ]
container:
image: debian:${{matrix.debian_version}}
steps:
@@ -499,7 +499,11 @@ jobs:
qt6-tools-dev-tools
qt6-l10n-tools
rapidjson-dev
- name: Install KDSingleApplication
if: matrix.debian_version != 'bookworm'
run: apt install -y libkdsingleapplication-qt6-dev
- name: Build and install KDSingleApplication
if: matrix.debian_version == 'bookworm'
run: |
git clone --depth 1 --recurse-submodules https://github.com/KDAB/KDSingleApplication
cd KDSingleApplication
@@ -507,7 +511,7 @@ jobs:
cmake --build build --config Release --parallel 4
cmake --install build
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -524,7 +528,7 @@ jobs:
- name: Copy deb
run: cp ../*.deb .
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: debian-${{matrix.debian_version}}
path: |
@@ -538,7 +542,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ubuntu_version: [ 'noble', 'plucky' ]
ubuntu_version: [ 'noble', 'plucky', 'questing' ]
container:
image: ubuntu:${{matrix.ubuntu_version}}
steps:
@@ -591,7 +595,11 @@ jobs:
qt6-tools-dev-tools
qt6-l10n-tools
rapidjson-dev
- name: Install KDSingleApplication
if: matrix.ubuntu_version != 'noble' && matrix.ubuntu_version != 'plucky'
run: apt install -y libkdsingleapplication-qt6-dev
- name: Build and install KDSingleApplication
if: matrix.ubuntu_version == 'noble' || matrix.ubuntu_version == 'plucky'
run: |
git clone --depth 1 --recurse-submodules https://github.com/KDAB/KDSingleApplication
cd KDSingleApplication
@@ -599,7 +607,7 @@ jobs:
cmake --build build --config Release --parallel 4
cmake --install build
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -616,7 +624,7 @@ jobs:
- name: Copy deb
run: cp ../*.deb ../*.ddeb .
- name: Upload artifacts
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: ubuntu-${{matrix.ubuntu_version}}
path: |
@@ -631,7 +639,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ubuntu_version: [ 'noble', 'plucky' ]
ubuntu_version: [ 'noble', 'plucky', 'questing' ]
container:
image: ubuntu:${{matrix.ubuntu_version}}
steps:
@@ -691,7 +699,7 @@ jobs:
DEBIAN_FRONTEND: noninteractive
run: apt install -y keyboxd
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -727,13 +735,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Build FreeBSD
id: build-freebsd
uses: vmactions/freebsd-vm@v1.2.1
uses: vmactions/freebsd-vm@v1.3.0
with:
usesh: true
mem: 4096
@@ -752,13 +760,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Build OpenBSD
id: build-openbsd
uses: vmactions/openbsd-vm@v1.1.8
uses: vmactions/openbsd-vm@v1.2.5
with:
usesh: true
mem: 4096
@@ -779,7 +787,7 @@ jobs:
strategy:
fail-fast: false
matrix:
runner: [ 'macos-13', 'macos-15' ]
runner: [ 'macos-15-intel', 'macos-15' ]
buildtype: [ 'release' ]
runs-on: ${{ matrix.runner }}
@@ -818,20 +826,20 @@ jobs:
rm -f uninstall.sh
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
- name: Import certificate file
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false
uses: apple-actions/import-codesign-certs@v5
uses: apple-actions/import-codesign-certs@v6
with:
p12-file-base64: ${{ secrets.APPLE_DEVELOPER_ID_CERTIFICATE }}
p12-password: ${{ secrets.APPLE_DEVELOPER_ID_CERTIFICATE_PASSWORD }}
- name: Download macOS dependencies
run: curl -f -O -L https://github.com/strawberrymusicplayer/strawberry-macos-dependencies/releases/latest/download/strawberry-macos-${{env.arch}}-${{env.buildtype}}.tar.xz
run: curl -f -O -L https://github.com/strawberrymusicplayer/strawberry-macos-dependencies$(test "${{env.arch}}" = "x86_64" && echo "-intel" || echo "")/releases/latest/download/strawberry-macos-${{env.arch}}-${{env.buildtype}}.tar.xz
- name: Extract macOS dependencies
run: sudo tar -C / -xf strawberry-macos-${{env.arch}}-${{env.buildtype}}.tar.xz
@@ -882,9 +890,9 @@ jobs:
run: make deploy
- name: Manually Codesign
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && matrix.runner == 'macos-13'
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && matrix.runner == 'macos-15-intel'
working-directory: build
run: codesign -s 383J84DVB6 -f strawberry.app/Contents/Frameworks/{libpcre2-8.0.dylib,libpcre2-16.0.dylib,libpng16.16.dylib,libfreetype.6.dylib,libzstd.1.dylib} strawberry.app/Contents/Frameworks/png.framework/png strawberry.app
run: codesign -s 383J84DVB6 -f strawberry.app/Contents/Frameworks/{libpcre2-8.0.dylib,libpcre2-16.0.dylib,libpng16.16.dylib,libfreetype.6.dylib,libzstd.1.dylib,libbrotlicommon.1.dylib,libbrotlienc.1.dylib} strawberry.app/Contents/Frameworks/png.framework/png strawberry.app
- name: Manually Codesign
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && matrix.runner == 'macos-15'
@@ -969,7 +977,7 @@ jobs:
run: echo "cmake_buildtype=$(echo ${{env.buildtype}} | awk '{print toupper(substr($0,0,1))tolower(substr($0,2))}')" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -1072,7 +1080,7 @@ jobs:
run: echo "cmake_buildtype=$(echo ${{matrix.buildtype}} | sed 's/.*/\u&/')" >> $GITHUB_ENV
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -1295,6 +1303,20 @@ jobs:
shell: bash
run: echo "cmake_buildtype=$(echo ${{matrix.buildtype}} | sed 's/.*/\u&/')" >> $GITHUB_ENV
- name: Show SDK versions
shell: bash
run: ls -la "c:/Program Files (x86)/Windows Kits/10/include"
- name: Set SDK version
if: matrix.arch != 'arm64'
shell: bash
run: echo "sdk_version=10.0.22621.0" >> $GITHUB_ENV
- name: Set SDK version
if: matrix.arch == 'arm64'
shell: bash
run: echo "sdk_version=10.0.26100.0" >> $GITHUB_ENV
- name: Install rsync
shell: cmd
run: choco install --no-progress rsync
@@ -1323,7 +1345,9 @@ jobs:
- name: Copy bin files
shell: bash
run: cp /c/strawberry/c/bin/{patch.exe,strip.exe,strings.exe,objdump.exe} ${{env.prefix_path_unix}}/bin
run: |
cp /c/mingw64/bin/{strip.exe,strings.exe,objdump.exe} ${{env.prefix_path_unix}}/bin
cp /c/strawberry/c/bin/patch.exe ${{env.prefix_path_unix}}/bin
- name: Delete conflicting files
shell: bash
@@ -1377,11 +1401,11 @@ jobs:
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{matrix.arch}}
sdk: 10.0.20348.0
sdk: ${{env.sdk_version}}
vsversion: 2022
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
submodules: recursive
@@ -1493,14 +1517,11 @@ jobs:
run: copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\*.dll .\gstreamer-plugins\
- name: Download copydlldeps.sh
if: matrix.arch != 'arm64'
shell: bash
working-directory: build
run: curl -f -O -L https://raw.githubusercontent.com/strawberrymusicplayer/strawberry-mxe/master/tools/copydlldeps.sh
- name: Copy dependencies
# copydlldeps.sh doesn't work with arm64 binaries.
if: matrix.arch != 'arm64'
shell: bash
working-directory: build
run: >
@@ -1517,12 +1538,6 @@ jobs:
-F ./gstreamer-plugins
-R ${{env.prefix_path_unix}}/bin
- name: Copy dependencies
if: matrix.arch == 'arm64'
shell: bash
working-directory: build
run: cp -v ${{env.prefix_path_unix}}/bin/{avcodec*.dll,avfilter*.dll,avformat*.dll,avutil*.dll,brotlicommon.dll,brotlidec.dll,chromaprint.dll,ebur128.dll,faad-2.dll,fdk-aac.dll,ffi-7.dll,FLAC.dll,freetype*.dll,getopt.dll,gio-2.0-0.dll,glib-2.0-0.dll,gme.dll,gmodule-2.0-0.dll,gobject-2.0-0.dll,gst-discoverer-1.0.exe,gst-launch-1.0.exe,gst-play-1.0.exe,gstadaptivedemux-1.0-0.dll,gstapp-1.0-0.dll,gstaudio-1.0-0.dll,gstbadaudio-1.0-0.dll,gstbase-1.0-0.dll,gstcodecparsers-1.0-0.dll,gstfft-1.0-0.dll,gstisoff-1.0-0.dll,gstmpegts-1.0-0.dll,gstnet-1.0-0.dll,gstpbutils-1.0-0.dll,gstreamer-1.0-0.dll,gstriff-1.0-0.dll,gstrtp-1.0-0.dll,gstrtsp-1.0-0.dll,gstsdp-1.0-0.dll,gsttag-1.0-0.dll,gsturidownloader-1.0-0.dll,gstvideo-1.0-0.dll,gstwinrt-1.0-0.dll,harfbuzz.dll,icudt*.dll,icuin*.dll,icuuc*.dll,intl-8.dll,jpeg62.dll,kdsingleapplication*.dll,libbs2b.dll,libcrypto-3-*.dll,fftw3.dll,libiconv*.dll,liblzma.dll,libmp3lame.dll,libopenmpt.dll,libpng16*.dll,libspeex*.dll,libssl-3-*.dll,libxml2*.dll,mpcdec.dll,mpg123.dll,nghttp2.dll,ogg.dll,opus.dll,orc-0.4-0.dll,pcre2-16*.dll,pcre2-8*.dll,postproc*.dll,psl-5.dll,Qt6Concurrent*.dll,Qt6Core*.dll,Qt6Gui*.dll,Qt6Network*.dll,Qt6Sql*.dll,Qt6Widgets*.dll,qtsparkle-qt6.dll,soup-3.0-0.dll,sqlite3.dll,sqlite3.exe,swresample*.dll,swscale*.dll,tag.dll,vorbis.dll,vorbisfile.dll,wavpackdll.dll,zlib*.dll} .
- name: Copy nsis files
shell: cmd
working-directory: build
@@ -1623,11 +1638,11 @@ jobs:
DEBIAN_FRONTEND: noninteractive
run: sudo apt install -y git rsync
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Download artifacts
uses: actions/download-artifact@v5
uses: actions/download-artifact@v7
with:
path: artifacts
- name: SSH Setup
@@ -1671,7 +1686,7 @@ jobs:
DEBIAN_FRONTEND: noninteractive
run: sudo apt install -y git jq gh
- name: Checkout
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
fetch-depth: 0
- name: Show release assets
@@ -1679,7 +1694,7 @@ jobs:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: gh release view "${{github.event.release.tag_name}}" --json assets | jq -r '.assets[].name'
- name: Download artifacts
uses: actions/download-artifact@v5
uses: actions/download-artifact@v7
with:
path: artifacts
- name: Add artifacts to release

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
/build
/bin
/CMakeLists.txt.user
/.qtcreator
/.kdev4
/strawberry.kdev4
/.vscode

View File

@@ -35,7 +35,7 @@ int GetProcessId();
struct BaseConnection {
static BaseConnection *Create();
static void Destroy(BaseConnection *&);
static void Destroy(BaseConnection*&);
bool isOpen = false;
bool Open();
bool Close();

View File

@@ -39,11 +39,11 @@ int GetProcessId() {
}
struct BaseConnectionUnix : public BaseConnection {
int sock { -1 };
int sock{ -1 };
};
static BaseConnectionUnix Connection;
static sockaddr_un PipeAddr {};
static sockaddr_un PipeAddr{};
#ifdef MSG_NOSIGNAL
static int MsgFlags = MSG_NOSIGNAL;
#else
@@ -105,7 +105,7 @@ bool BaseConnection::Open() {
bool BaseConnection::Close() {
auto self = reinterpret_cast<BaseConnectionUnix *>(this);
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
if (self->sock == -1) {
return false;
}

View File

@@ -38,7 +38,7 @@ int GetProcessId() {
}
struct BaseConnectionWin : public BaseConnection {
HANDLE pipe { INVALID_HANDLE_VALUE };
HANDLE pipe{ INVALID_HANDLE_VALUE };
};
static BaseConnectionWin Connection;
@@ -57,10 +57,10 @@ void BaseConnection::Destroy(BaseConnection *&c) {
bool BaseConnection::Open() {
wchar_t pipeName[] { L"\\\\?\\pipe\\discord-ipc-0" };
wchar_t pipeName[]{ L"\\\\?\\pipe\\discord-ipc-0" };
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
pipeName[pipeDigit] = L'0';
auto self = reinterpret_cast<BaseConnectionWin *>(this);
auto self = reinterpret_cast<BaseConnectionWin*>(this);
for (;;) {
self->pipe = ::CreateFileW(pipeName, GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, 0, nullptr);
if (self->pipe != INVALID_HANDLE_VALUE) {
@@ -88,7 +88,7 @@ bool BaseConnection::Open() {
bool BaseConnection::Close() {
auto self = reinterpret_cast<BaseConnectionWin *>(this);
auto self = reinterpret_cast<BaseConnectionWin*>(this);
::CloseHandle(self->pipe);
self->pipe = INVALID_HANDLE_VALUE;
self->isOpen = false;
@@ -102,7 +102,7 @@ bool BaseConnection::Write(const void *data, size_t length) {
if (length == 0) {
return true;
}
auto self = reinterpret_cast<BaseConnectionWin *>(this);
auto self = reinterpret_cast<BaseConnectionWin*>(this);
assert(self);
if (!self) {
return false;
@@ -127,7 +127,7 @@ bool BaseConnection::Read(void *data, size_t length) {
if (!data) {
return false;
}
auto self = reinterpret_cast<BaseConnectionWin *>(this);
auto self = reinterpret_cast<BaseConnectionWin*>(this);
assert(self);
if (!self) {
return false;

View File

@@ -34,9 +34,9 @@ namespace discord_rpc {
template<typename ElementType, std::size_t QueueSize>
class MsgQueue {
ElementType queue_[QueueSize];
std::atomic_uint nextAdd_ { 0 };
std::atomic_uint nextSend_ { 0 };
std::atomic_uint pendingSends_ { 0 };
std::atomic_uint nextAdd_{ 0 };
std::atomic_uint nextSend_{ 0 };
std::atomic_uint pendingSends_{ 0 };
public:
MsgQueue() {}

View File

@@ -163,4 +163,3 @@ extern "C" void Discord_Register(const char *applicationId, const char *command)
Discord_RegisterW(appId, wcommand);
}

View File

@@ -40,9 +40,9 @@ static void Discord_UpdateConnection();
namespace {
constexpr size_t MaxMessageSize { 16 * 1024 };
constexpr size_t MessageQueueSize { 8 };
constexpr size_t JoinQueueSize { 8 };
constexpr size_t MaxMessageSize{ 16 * 1024 };
constexpr size_t MessageQueueSize{ 8 };
constexpr size_t JoinQueueSize{ 8 };
struct QueuedMessage {
size_t length;
@@ -70,24 +70,24 @@ struct User {
// Rounded way up because I'm paranoid about games breaking from future changes in these sizes
};
static RpcConnection *Connection { nullptr };
static DiscordEventHandlers QueuedHandlers {};
static DiscordEventHandlers Handlers {};
static std::atomic_bool WasJustConnected { false };
static std::atomic_bool WasJustDisconnected { false };
static std::atomic_bool GotErrorMessage { false };
static std::atomic_bool WasJoinGame { false };
static std::atomic_bool WasSpectateGame { false };
static std::atomic_bool UpdatePresence { false };
static RpcConnection *Connection{ nullptr };
static DiscordEventHandlers QueuedHandlers{};
static DiscordEventHandlers Handlers{};
static std::atomic_bool WasJustConnected{ false };
static std::atomic_bool WasJustDisconnected{ false };
static std::atomic_bool GotErrorMessage{ false };
static std::atomic_bool WasJoinGame{ false };
static std::atomic_bool WasSpectateGame{ false };
static std::atomic_bool UpdatePresence{ false };
static char JoinGameSecret[256];
static char SpectateGameSecret[256];
static int LastErrorCode { 0 };
static int LastErrorCode{ 0 };
static char LastErrorMessage[256];
static int LastDisconnectErrorCode { 0 };
static int LastDisconnectErrorCode{ 0 };
static char LastDisconnectErrorMessage[256];
static std::mutex PresenceMutex;
static std::mutex HandlerMutex;
static QueuedMessage QueuedPresence {};
static QueuedMessage QueuedPresence{};
static MsgQueue<QueuedMessage, MessageQueueSize> SendQueue;
static MsgQueue<User, JoinQueueSize> JoinAskQueue;
static User connectedUser;
@@ -95,12 +95,12 @@ static User connectedUser;
// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential backoff from 0.5 seconds to 1 minute
static Backoff ReconnectTimeMs(500, 60 * 1000);
static auto NextConnect = std::chrono::system_clock::now();
static int Pid { 0 };
static int Nonce { 1 };
static int Pid{ 0 };
static int Nonce{ 1 };
class IoThreadHolder {
private:
std::atomic_bool keepRunning { true };
std::atomic_bool keepRunning{ true };
std::mutex waitForIOMutex;
std::condition_variable waitForIOActivity;
std::thread ioThread;
@@ -109,14 +109,14 @@ class IoThreadHolder {
void Start() {
keepRunning.store(true);
ioThread = std::thread([&]() {
const std::chrono::duration<int64_t, std::milli> maxWait { 500LL };
Discord_UpdateConnection();
while (keepRunning.load()) {
std::unique_lock<std::mutex> lock(waitForIOMutex);
waitForIOActivity.wait_for(lock, maxWait);
const std::chrono::duration<int64_t, std::milli> maxWait { 500LL };
Discord_UpdateConnection();
}
});
while (keepRunning.load()) {
std::unique_lock<std::mutex> lock(waitForIOMutex);
waitForIOActivity.wait_for(lock, maxWait);
Discord_UpdateConnection();
}
});
}
void Notify() { waitForIOActivity.notify_all(); }
@@ -132,7 +132,7 @@ class IoThreadHolder {
~IoThreadHolder() { Stop(); }
};
static IoThreadHolder *IoThread { nullptr };
static IoThreadHolder *IoThread{ nullptr };
static void UpdateReconnectTime() {
@@ -429,7 +429,7 @@ extern "C" void Discord_RunCallbacks() {
if (WasJustConnected.exchange(false)) {
std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.ready) {
DiscordUser du { connectedUser.userId, connectedUser.username, connectedUser.discriminator, connectedUser.avatar };
DiscordUser du{ connectedUser.userId, connectedUser.username, connectedUser.discriminator, connectedUser.avatar };
Handlers.ready(&du);
}
}
@@ -465,7 +465,7 @@ extern "C" void Discord_RunCallbacks() {
{
std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.joinRequest) {
DiscordUser du { req->userId, req->username, req->discriminator, req->avatar };
DiscordUser du{ req->userId, req->username, req->discriminator, req->avatar };
Handlers.joinRequest(&du);
}
}
@@ -486,12 +486,12 @@ extern "C" void Discord_UpdateHandlers(DiscordEventHandlers *newHandlers) {
if (newHandlers) {
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \
if (!Handlers.handler_name && newHandlers->handler_name) { \
RegisterForEvent(event); \
} \
else if (Handlers.handler_name && !newHandlers->handler_name) { \
DeregisterForEvent(event); \
}
if (!Handlers.handler_name && newHandlers->handler_name) { \
RegisterForEvent(event); \
} \
else if (Handlers.handler_name && !newHandlers->handler_name) { \
DeregisterForEvent(event); \
}
std::lock_guard<std::mutex> guard(HandlerMutex);
HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN")

View File

@@ -32,6 +32,7 @@ extern "C" {
typedef struct DiscordRichPresence {
int type;
int status_display_type;
const char *name; /* max 128 bytes */
const char *state; /* max 128 bytes */
const char *details; /* max 128 bytes */

View File

@@ -63,17 +63,17 @@ struct RpcConnection {
Connected,
};
BaseConnection *connection { nullptr };
State state { State::Disconnected };
BaseConnection *connection{ nullptr };
State state{ State::Disconnected };
void (*onConnect)(JsonDocument &message) { nullptr };
void (*onDisconnect)(int errorCode, const char *message) { nullptr };
char appId[64] {};
int lastErrorCode { 0 };
char lastErrorMessage[256] {};
char appId[64]{};
int lastErrorCode{ 0 };
char lastErrorMessage[256]{};
RpcConnection::MessageFrame sendFrame;
static RpcConnection *Create(const char *applicationId);
static void Destroy(RpcConnection *&);
static void Destroy(RpcConnection*&);
inline bool IsOpen() const { return state == State::Connected; }

View File

@@ -128,6 +128,9 @@ size_t JsonWriteRichPresenceObj(char *dest, const size_t maxLen, const int nonce
if (presence->type >= 0 && presence->type <= 5) {
WriteKey(writer, "type");
writer.Int(presence->type);
WriteKey(writer, "status_display_type");
writer.Int(presence->status_display_type);
}
WriteOptionalString(writer, "name", presence->name);

View File

@@ -259,7 +259,18 @@ if(APPLE)
endif()
if(WIN32)
find_package(getopt-win REQUIRED)
find_package(getopt NAMES getopt getopt-win unofficial-getopt-win32 REQUIRED)
if(TARGET getopt::getopt)
set(GETOPT_LIBRARIES getopt::getopt)
elseif(TARGET getopt-win::getopt)
set(GETOPT_LIBRARIES getopt-win::getopt)
elseif(TARGET getopt::getopt_shared)
set(GETOPT_LIBRARIES getopt::getopt_shared)
elseif(TARGET unofficial::getopt-win32::getopt)
set(GETOPT_LIBRARIES unofficial::getopt-win32::getopt)
else()
message(FATAL_ERROR "Missing getopt")
endif()
endif()
if(APPLE OR WIN32)
@@ -690,6 +701,7 @@ set(SOURCES
src/lyrics/elyricsnetlyricsprovider.cpp
src/lyrics/letraslyricsprovider.cpp
src/lyrics/lyricfindlyricsprovider.cpp
src/lyrics/lrcliblyricsprovider.cpp
src/settings/settingsdialog.cpp
src/settings/settingspage.cpp
@@ -783,9 +795,7 @@ set(SOURCES
src/scrobbler/scrobblercache.cpp
src/scrobbler/scrobblercacheitem.cpp
src/scrobbler/scrobblemetadata.cpp
src/scrobbler/scrobblingapi20.cpp
src/scrobbler/lastfmscrobbler.cpp
src/scrobbler/librefmscrobbler.cpp
src/scrobbler/listenbrainzscrobbler.cpp
src/scrobbler/lastfmimport.cpp
@@ -988,6 +998,7 @@ set(HEADERS
src/lyrics/elyricsnetlyricsprovider.h
src/lyrics/letraslyricsprovider.h
src/lyrics/lyricfindlyricsprovider.h
src/lyrics/lrcliblyricsprovider.h
src/settings/settingsdialog.h
src/settings/settingspage.h
@@ -1076,9 +1087,7 @@ set(HEADERS
src/scrobbler/scrobblersettingsservice.h
src/scrobbler/scrobblerservice.h
src/scrobbler/scrobblercache.h
src/scrobbler/scrobblingapi20.h
src/scrobbler/lastfmscrobbler.h
src/scrobbler/librefmscrobbler.h
src/scrobbler/listenbrainzscrobbler.h
src/scrobbler/lastfmimport.h
@@ -1554,7 +1563,7 @@ target_link_libraries(strawberry_lib PUBLIC
$<$<BOOL:${HAVE_MTP}>:PkgConfig::LIBMTP>
$<$<BOOL:${HAVE_GPOD}>:PkgConfig::LIBGPOD PkgConfig::GDK_PIXBUF>
$<$<BOOL:${HAVE_QTSPARKLE}>:qtsparkle-qt${QT_VERSION_MAJOR}::qtsparkle>
$<$<BOOL:${WIN32}>:dsound dwmapi getopt-win::getopt>
$<$<BOOL:${WIN32}>:dsound dwmapi ${GETOPT_LIBRARIES}>
$<$<BOOL:${MSVC}>:WindowsApp>
KDAB::kdsingleapplication
$<$<BOOL:${HAVE_DISCORD_RPC}>:discord-rpc>

View File

@@ -2,6 +2,62 @@ Strawberry Music Player
=======================
ChangeLog
Version 1.2.16 (2025.12.16):
* Make Discord Rich presence use filename if song title is missing
* Added better error message when a GStreamer plugin is missing
* Preserve track order in album shuffle mode when restarting playback (#1623)
* Possible fixes for context word wrap
* Added lyrics from lrclib.net
* Added option to turn off the use of sort tags for the collection
* Fixed Spotify login
* Fixed error dialog shown minimized if another Strawberry window than the mainwindow was active
* Fixed seeking to the end of the track and back causing seeking to stop working (#1675)
* Set current index when automatically selecting track (#1825)
* Make icon size for shuffle and repeat buttons adjust to screen resolution (#1838)
* Fixed song being removed from playlist when dragging to another application (#1815)
* Don't automatically scroll on dynamic playlists (#1427)
Version 1.2.15 (2025.11.25):
* Fixed system default language not respected
* Fixed length filter search
* Fixed playlist parser converting Spotify URL's
* Removed use of deprecated QStyle::State_Editing
* Ignore connection closed errors for ListenBrainz
* (Windows) Support building with vcpkg unofficial::getopt-win32::getopt
Version 1.2.14 (2025.10.25):
Bugfixes:
* Fixed showing error dialog minimized when main window is not current active window (#1739)
* Fixed Discord timestamp update when seeking (#1813)
* Fixed CD metadata lookup to respect MusicBrainz rate limiting
* Fixed Tidal Open API cover provider
* (Windows) Fixed device selection with WASAPI2
Enhancements/Other:
* Removed libre.fm support
* Rewrote MusicBrainzClient to use Json instead of XML
* Subsonic will now use cover art from album when available
* Added option to remove "Remastered", etc from song titles for Tidal, Qobuz and Spotify
* Added webm to supported file extensions
* (Windows|MinGW) Added WASAPI2 support
* (Windows) Added experimental exclusive mode for WASAPI2
Version 1.2.13 (2025.08.31):
Bugfixes:
* Fixed playlist alternating row colors no longer working with some styles (#1806)
* Fixed "Open Audio CD" no longer working (#1803)
* Fixed systemtray icon playback status not working with scaling (#1782)
* Fixed build without MusicBrainz (#1799)
* Fixed build without MTP (#1804)
Enhancements:
* Added Discord status text option (#1796)
* Read Vorbis/FLAC "Other" embedded covers if front cover is not available (#1793)
Version 1.2.12 (2025.08.12):
Bugfixes:

171
README.md
View File

@@ -1,118 +1,137 @@
:strawberry: Strawberry Music Player [![Build Status](https://github.com/strawberrymusicplayer/strawberry/workflows/Build/badge.svg)](https://github.com/strawberrymusicplayer/strawberry/actions)
=======================
# :strawberry: Strawberry Music Player [![Build Status](https://github.com/strawberrymusicplayer/strawberry/workflows/Build/badge.svg)](https://github.com/strawberrymusicplayer/strawberry/actions)
[![Sponsor](https://img.shields.io/badge/-Sponsor-green?logo=github)](https://github.com/sponsors/jonaski)
[![Patreon](https://img.shields.io/badge/patreon-donate-green.svg)](https://patreon.com/jonaskvinge)
[![PayPal](https://img.shields.io/badge/Donate-PayPal-green.svg)](https://paypal.me/jonaskvinge)
Strawberry is a music player and music collection organizer. It is a fork of Clementine released in 2018 aimed at music collectors and audiophiles. It's written in C++ using the Qt framework.
Strawberry is a **music player and music collection organizer**, originally forked from *Clementine* in 2018.
Its written in **C++ using the Qt framework**, designed for **audiophiles and music collectors**.
![Browse](https://raw.githubusercontent.com/strawberrymusicplayer/strawberry/master/data/screenshot/screenshot.png)
![Screenshot of Strawberry Music Player](https://raw.githubusercontent.com/strawberrymusicplayer/strawberry/master/data/screenshot/screenshot.png)
Resources:
---
* Website: https://www.strawberrymusicplayer.org/
* Wiki: https://wiki.strawberrymusicplayer.org/
* Forum: https://forum.strawberrymusicplayer.org/
* Github: https://github.com/strawberrymusicplayer/strawberry
* Latest builds: https://builds.strawberrymusicplayer.org/
* openSUSE buildservice: https://build.opensuse.org/package/show/home:jonaski:audio/strawberry
* Ubuntu PPA: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry
* Ubuntu Unstable PPA: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry-unstable
* Translations: https://crowdin.com/project/strawberrymusicplayer/
## :globe_with_meridians: Resources
### :bangbang: Opening an issue
- **Website:** https://www.strawberrymusicplayer.org
- **Wiki:** https://wiki.strawberrymusicplayer.org
- **Forum:** https://forum.strawberrymusicplayer.org
- **GitHub:** https://github.com/strawberrymusicplayer/strawberry
- **Latest builds:** https://builds.strawberrymusicplayer.org
- **openSUSE Build Service:**
- Stable: https://build.opensuse.org/package/show/home:jonaski:strawberry/strawberry
- Unstable: https://build.opensuse.org/package/show/home:jonaski:strawberry-dev/strawberry
- **Ubuntu PPAs:**
- Stable: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry
- Unstable: https://launchpad.net/~jonaski/+archive/ubuntu/strawberry-unstable
- **Translations:** https://crowdin.com/project/strawberrymusicplayer
* Read the FAQ: https://wiki.strawberrymusicplayer.org/wiki/FAQ
* 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, 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/).
* We do not maintain the Flatpak package. Do not report issues related to Flatpak unless the issue can be reproduced with a native package, use Flatpak support instead https://flatpak.org/about/
---
### :moneybag: Sponsoring
## :warning: Opening an Issue
The program is free software, released under GPL. If you like this program and can make use of it, consider sponsoring or donating to help fund the project.
There are currently 4 options for sponsoring:
Before creating a new GitHub issue:
1. **Read the [FAQ](https://wiki.strawberrymusicplayer.org/wiki/FAQ)**.
2. **Search existing issues** to avoid duplicates. If one already exists, comment there with any additional information.
3. **Use the [forum](https://forum.strawberrymusicplayer.org/)** for technical problems, discussions or feature suggestions — its better suited for back-and-forth conversation.
4. **Feature requests are not accepted on GitHub.** Issues created for feature requests will be closed. You can still discuss ideas on the forum.
5. **Flatpak users:** We do **not** maintain the Flatpak package. Report Flatpak-specific issues via [Flatpak support](https://flatpak.org/about/).
---
## :moneybag: Sponsoring
Strawberry is **free software released under the GPL**.
If you enjoy using it, please consider **supporting development** through sponsorship or donation.
**Sponsorship options:**
1. [Patreon](https://www.patreon.com/jonaskvinge)
2. [GitHub](https://github.com/sponsors/jonaski)
3. [Ko-fi](https://ko-fi.com/jonaskvinge)
4. [PayPal](https://paypal.me/jonaskvinge)
Funding developers is a way to contribute to open source projects you appreciate, it helps developers get the resources they need, and recognize contributors working behind the scenes to make open source better for everyone.
Supporting open-source developers helps ensure continued maintenance and improvements.
### :heavy_check_mark: Features
---
* Play and organize music
* Supports WAV, FLAC, WavPack, Ogg FLAC, Ogg Vorbis, Ogg Opus, Ogg Speex, MPC, TrueAudio, AIFF, MP4, MP3, ASF and Monkey's Audio.
* Audio CD playback
* Native desktop notifications
* Playlist management
* Smart and dynamic playlists
* Advanced audio output and device configuration for bit-perfect playback on Linux
* In-player song loudness analysis and song playback loudness normalization, as per EBU R 128
* Edit tags on audio files
* Fetch tags from MusicBrainz
* Album cover art from [Last.fm](https://www.last.fm/), [Musicbrainz](https://musicbrainz.org/), [Discogs](https://www.discogs.com/), [Musixmatch](https://www.musixmatch.com/), [Deezer](https://www.deezer.com/), [Tidal](https://www.tidal.com/), [Qobuz](https://www.qobuz.com/) and [Spotify](https://www.spotify.com/)
* Song lyrics from [Genius](https://genius.com/), [Musixmatch](https://www.musixmatch.com/), [ChartLyrics](http://www.chartlyrics.com/), [lyrics.ovh](https://lyrics.ovh/), [lololyrics.com](https://www.lololyrics.com/), [songlyrics.com](https://www.songlyrics.com/), [azlyrics.com](https://www.azlyrics.com/), [elyrics.net](https://www.elyrics.net/), [letras.mus.br](https://www.letras.mus.br) and [LyricFind](https://lyrics.lyricfind.com)
* Support for multiple backends
* Audio analyzer
* Audio equalizer
* Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic
* Scrobbler with support for [Last.fm](https://www.last.fm/), [Libre.fm](https://libre.fm/) and [ListenBrainz](https://listenbrainz.org/)
* Streaming from Subsonic compatible servers
* Unofficial Tidal, Spotify and Qobuz integration
* Discord rich presence
## :white_check_mark: Features
- Play and organize your music collection
- Supports formats: WAV, FLAC, WavPack, Ogg Vorbis, Opus, MPC, TrueAudio, AIFF, MP4, MP3, ASF, and Monkeys Audio
- Audio CD playback
- Bit-perfect playback on Linux
- Native desktop notifications
- Advanced playlist management
- Smart and dynamic playlists
- Loudness analysis and EBU R128 normalization
- Editing tags and fetching missing tags via [MusicBrainz](https://musicbrainz.org/)
- Album art from: [Last.fm](https://www.last.fm/), [MusicBrainz](https://musicbrainz.org/), [Discogs](https://www.discogs.com/), [Musixmatch](https://www.musixmatch.com/), [Deezer](https://www.deezer.com/), [Tidal](https://www.tidal.com/), [Qobuz](https://www.qobuz.com/), [Spotify](https://www.spotify.com/)
- Lyrics from: [Genius](https://genius.com/), [Musixmatch](https://www.musixmatch.com/), [ChartLyrics](http://www.chartlyrics.com/), [lyrics.ovh](https://lyrics.ovh/), [lololyrics](https://www.lololyrics.com/), [songlyrics](https://www.songlyrics.com/), [azlyrics](https://www.azlyrics.com/), [elyrics](https://www.elyrics.net/), [letras](https://www.letras.mus.br), [LyricFind](https://lyrics.lyricfind.com) and [lrclib.net](https://lrclib.net/)
- Audio analyzer and equalizer
- Transfer music to USB, MTP and iPod devices
- Scrobbling to [Last.fm](https://www.last.fm/) and [ListenBrainz](https://listenbrainz.org/)
- Streaming from Subsonic-compatible servers
- Unofficial integrations: Tidal, Spotify, and Qobuz
- Discord Rich Presence
It has so far been tested to work on Linux, OpenBSD, FreeBSD, macOS and Windows.
---
**Access to macOS and Windows releases are currently restricted to sponsors, a 5 USD monthly sponsorship is required. You can sponsor strawberry through <a href="https://www.patreon.com/jonaskvinge">Patreon</a> for direct access to new releases. If you are sponsoring through GitHub, Ko-fi or PayPal, please e-mail support AT strawberrymusicplayer.org for access to downloads.**
:white_check_mark: Tested on **Linux**, **OpenBSD**, **FreeBSD**, **macOS**, and **Windows**.
### :heavy_exclamation_mark: Requirements
> **Note:** macOS and Windows releases are currently **available to sponsors only**.
> A monthly sponsorship via [Patreon](https://www.patreon.com/jonaskvinge) grants direct access to new releases.
To build Strawberry from source you need the following installed on your system with the additional development packages/headers:
---
* [CMake 3.13 or higher](https://cmake.org/)
* C/C++ compiler ([GCC](https://gcc.gnu.org/), [Clang](https://clang.llvm.org/) or [MSVC](https://visualstudio.microsoft.com/vs/features/cplusplus/))
* [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) or [pkgconf](https://github.com/pkgconf/pkgconf)
* [Boost](https://www.boost.org/)
* [GLib](https://developer.gnome.org/glib/)
* [Qt 6.4.0 or higher with components Core, Concurrent, Gui, Widgets, Network, Sql and D-Bus](https://www.qt.io/)
* [SQLite 3.9 or newer](https://www.sqlite.org)
* [ALSA (Required on Linux)](https://www.alsa-project.org/)
* [GStreamer](https://gstreamer.freedesktop.org/)
* [TagLib 1.12 or higher](https://www.taglib.org/)
* [ICU](https://unicode-org.github.io/icu/)
* [KDSingleApplication 1.1.0 or higher](https://github.com/KDAB/KDSingleApplication)
## :gear: Requirements
Optional dependencies:
To build Strawberry from source, youll need:
* Song fingerprinting and MusicBrainz tagging: [Chromaprint](https://acoustid.org/chromaprint)
* Moodbar: [fftw3](http://www.fftw.org/)
* PulseAudio integration: [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
* Audio CD: [libcdio](https://www.gnu.org/software/libcdio/)
* MTP devices: [libmtp](http://libmtp.sourceforge.net/)
* iPod Classic devices: [libgpod](http://www.gtkpod.org/libgpod/)
* EBU R 128 loudness normalization [libebur128](https://github.com/jiixyj/libebur128)
* Discord rich presence [RapidJSON](https://rapidjson.org/)
**Dependencies:**
- [CMake ≥= 3.13](https://cmake.org/)
- C/C++ compiler ([GCC](https://gcc.gnu.org/), [Clang](https://clang.llvm.org/), or [MSVC](https://visualstudio.microsoft.com/vs/features/cplusplus/))
- [pkg-config](https://www.freedesktop.org/wiki/Software/pkg-config/) or [pkgconf](https://github.com/pkgconf/pkgconf)
- [Boost](https://www.boost.org/)
- [GLib](https://developer.gnome.org/glib/)
- [Qt ≥= 6.4](https://www.qt.io/) (Core, Concurrent, Gui, Widgets, Network, SQL, D-Bus)
- [SQLite ≥= 3.9](https://www.sqlite.org)
- [ALSA (Linux only)](https://www.alsa-project.org/)
- [GStreamer](https://gstreamer.freedesktop.org/)
- [TagLib ≥= 1.12](https://www.taglib.org/)
- [ICU](https://unicode-org.github.io/icu/)
- [KDSingleApplication ≥= 1.1.0](https://github.com/KDAB/KDSingleApplication)
You should also install the gstreamer plugins base and good, and optionally bad, ugly and libav to support all audio formats.
**Dependencies for optional features:**
- Fingerprinting & tagging: [Chromaprint](https://acoustid.org/chromaprint)
- Moodbar: [FFTW3](http://www.fftw.org/)
- PulseAudio integration: [PulseAudio](https://www.freedesktop.org/wiki/Software/PulseAudio/)
- Audio CD support: [libcdio](https://www.gnu.org/software/libcdio/)
- MTP devices: [libmtp](http://libmtp.sourceforge.net/)
- iPod Classic: [libgpod](http://www.gtkpod.org/libgpod/)
- EBU R128 normalization: [libebur128](https://github.com/jiixyj/libebur128)
- Discord presence: [RapidJSON](https://rapidjson.org/)
### :wrench: Build from source
Also install GStreamer plugins **base**, **good**, and optionally **bad**, **ugly** and **libav** for full codec support.
### Get the code:
---
## :wrench: Build from Source
**Get the code:**
git clone --recursive https://github.com/strawberrymusicplayer/strawberry
### Build and install:
**Build and install:**
cd strawberry
cmake -S . -B build
cmake --build build --parallel $(nproc)
sudo cmake --install build
To build on Windows with Visual Studio 2022, see https://github.com/strawberrymusicplayer/strawberry-msvc
For building on Windows with Visual Studio 2022, see: :point_right: https://github.com/strawberrymusicplayer/strawberry-msvc
### :penguin: Packaging status
---
## :package: Packaging status
[![Packaging status](https://repology.org/badge/vertical-allrepos/strawberry.svg?columns=3&header=Strawberry&exclude_unsupported=1)](https://repology.org/metapackage/strawberry/versions)

View File

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

4
debian/control vendored
View File

@@ -60,11 +60,11 @@ Description: music player and music collection organizer
- 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 Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com, elyrics.net, letras.mus.br and LyricFind
- Lyrics from multiple sources
- Audio analyzer
- Audio equalizer
- Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
- Scrobbler with support for Last.fm and ListenBrainz
- Streaming support for Subsonic-compatible servers
- Unofficial streaming support for Tidal and Qobuz
.

View File

@@ -1,22 +0,0 @@
#!/bin/sh
macos_version=$(sw_vers -productVersion)
macos_version_major=$(echo $macos_version | awk -F '[.]' '{print $1}')
macos_version_minor=$(echo $macos_version | awk -F '[.]' '{print $2}')
if [ "${macos_version_major}" = "10" ]; then
macos_codenames=(
["13"]="highsierra"
["14"]="mojave"
["15"]="catalina"
)
if [[ -n "${macos_codenames[$macos_version_minor]}" ]]; then
echo "${macos_codenames[$macos_version_minor]}"
else
echo "unknown"
fi
elif [ "${macos_version_major}" = "11" ]; then
echo "bigsur"
else
echo "unknown"
fi

View File

@@ -31,10 +31,10 @@
<li>Edit tags on audio files</li>
<li>Automatically retrieve tags from MusicBrainz</li>
<li>Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify</li>
<li>Song lyrics from Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com, elyrics.net, letras.mus.br and LyricFind</li>
<li>Lyrics from multiple sources</li>
<li>Audio analyzer and equalizer</li>
<li>Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic</li>
<li>Scrobbler with support for Last.fm, Libre.fm and ListenBrainz</li>
<li>Scrobbler with support for Last.fm and ListenBrainz</li>
<li>Streaming support for Subsonic-compatible servers</li>
<li>Unofficial streaming support for Tidal, Spotify and Qobuz</li>
</ul>
@@ -51,6 +51,10 @@
</screenshots>
<update_contact>eclipseo@fedoraproject.org</update_contact>
<releases>
<release version="1.2.16" date="2025-12-16"/>
<release version="1.2.15" date="2025-11-25"/>
<release version="1.2.14" date="2025-10-25"/>
<release version="1.2.13" date="2025-08-31"/>
<release version="1.2.12" date="2025-08-12"/>
<release version="1.2.11" date="2025-05-15"/>
<release version="1.2.10" date="2025-04-18"/>

View File

@@ -29,9 +29,7 @@ Features:
.br
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify
.br
- Song lyrics from Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com, elyrics.net, letras.mus.br and LyricFind
.br
- Support for multiple backends
- Lyrics from multiple sources
.br
- Audio analyzer
.br
@@ -39,7 +37,7 @@ Features:
.br
- Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic
.br
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
- Scrobbler with support for Last.fm and ListenBrainz
.br
- Streaming support for Subsonic-compatible servers
.br

View File

@@ -93,16 +93,15 @@ Features:
- 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 Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com, elyrics.net, letras.mus.br and LyricFind
- Support for multiple backends
- Lyrics from multiple sources
- Audio analyzer
- Audio equalizer
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
- Scrobbler with support for Last.fm and ListenBrainz
- Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic
- Streaming support for Subsonic-compatible servers
- Unofficial streaming support for Tidal and Qobuz
%if 0%{?suse_version} && 0%{?suse_version} <= 1600
%if 0%{?suse_version} && 0%{?suse_version} < 1600
%debug_package
%endif

View File

@@ -395,9 +395,6 @@ Section "Strawberry" Strawberry
File "glib-2.0-0.dll"
File "gme.dll"
File "gmodule-2.0-0.dll"
!ifndef arch_arm64
File "gnutls.dll"
!endif
File "gobject-2.0-0.dll"
File "gstadaptivedemux-1.0-0.dll"
File "gstapp-1.0-0.dll"
@@ -418,18 +415,11 @@ Section "Strawberry" Strawberry
File "gsttag-1.0-0.dll"
File "gsturidownloader-1.0-0.dll"
File "gstvideo-1.0-0.dll"
!ifdef arch_arm64
File "gstwinrt-1.0-0.dll"
!endif
File "harfbuzz.dll"
File "intl-8.dll"
File "jpeg62.dll"
File "kdsingleapplication-qt6.dll"
File "libbs2b.dll"
!ifndef arch_arm64
File "libfaac_dll.dll"
!endif
File "liblzma.dll"
File "libmp3lame.dll"
File "libopenmpt.dll"
File "mpcdec.dll"
@@ -447,6 +437,11 @@ Section "Strawberry" Strawberry
File "vorbisfile.dll"
File "wavpackdll.dll"
!ifndef arch_arm64
File "gnutls.dll"
File "libfaac_dll.dll"
!endif
!ifdef release
File "freetype.dll"
File "libiconv.dll"
@@ -454,10 +449,10 @@ Section "Strawberry" Strawberry
File "libspeex.dll"
File "pcre2-8.dll"
File "pcre2-16.dll"
File "zlib1.dll"
!ifndef arch_arm64
File "twolame.dll"
!endif
File "zlib1.dll"
!endif
!ifdef debug
File "freetyped.dll"
@@ -466,10 +461,10 @@ Section "Strawberry" Strawberry
File "libspeexd.dll"
File "pcre2-8d.dll"
File "pcre2-16d.dll"
File "zlibd1.dll"
!ifndef arch_arm64
File "twolamed.dll"
!endif
File "zlibd1.dll"
!endif
; Used by libfftw3-3.dll because fftw is compiled with MinGW.
@@ -482,15 +477,15 @@ Section "Strawberry" Strawberry
; Common files
File "icudt77.dll"
File "icudt78.dll"
!ifdef msvc && arch_arm64
File "fftw3.dll"
!else
File "libfftw3-3.dll"
!endif
!ifdef msvc && debug
File "icuin77d.dll"
File "icuuc77d.dll"
File "icuin78d.dll"
File "icuuc78d.dll"
File "libxml2d.dll"
File "Qt6Concurrentd.dll"
File "Qt6Cored.dll"
@@ -499,8 +494,8 @@ Section "Strawberry" Strawberry
File "Qt6Sqld.dll"
File "Qt6Widgetsd.dll"
!else
File "icuin77.dll"
File "icuuc77.dll"
File "icuin78.dll"
File "icuuc78.dll"
File "libxml2.dll"
File "Qt6Concurrent.dll"
File "Qt6Core.dll"
@@ -510,6 +505,7 @@ Section "Strawberry" Strawberry
File "Qt6Widgets.dll"
!endif
!ifdef msvc && arch_x86
File "avcodec-61.dll"
File "avfilter-10.dll"
File "avformat-61.dll"
@@ -517,6 +513,14 @@ Section "Strawberry" Strawberry
File "postproc-58.dll"
File "swresample-5.dll"
File "swscale-8.dll"
!else
File "avcodec-62.dll"
File "avfilter-11.dll"
File "avformat-62.dll"
File "avutil-60.dll"
File "swresample-6.dll"
File "swscale-9.dll"
!endif
; Register Strawberry with Default Programs
Var /GLOBAL AppIcon
@@ -677,6 +681,7 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
File "/oname=libgstwasapi.dll" "gstreamer-plugins\libgstwasapi.dll"
File "/oname=libgstwasapi2.dll" "gstreamer-plugins\libgstwasapi2.dll"
File "/oname=libgstwaveform.dll" "gstreamer-plugins\libgstwaveform.dll"
File "/oname=libgstwavenc.dll" "gstreamer-plugins\libgstwavenc.dll"
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
@@ -942,9 +947,6 @@ Section "Uninstall"
Delete "$INSTDIR\glib-2.0-0.dll"
Delete "$INSTDIR\gme.dll"
Delete "$INSTDIR\gmodule-2.0-0.dll"
!ifndef arch_arm64
Delete "$INSTDIR\gnutls.dll"
!endif
Delete "$INSTDIR\gobject-2.0-0.dll"
Delete "$INSTDIR\gstadaptivedemux-1.0-0.dll"
Delete "$INSTDIR\gstapp-1.0-0.dll"
@@ -965,18 +967,11 @@ Section "Uninstall"
Delete "$INSTDIR\gsttag-1.0-0.dll"
Delete "$INSTDIR\gsturidownloader-1.0-0.dll"
Delete "$INSTDIR\gstvideo-1.0-0.dll"
!ifdef arch_arm64
Delete "$INSTDIR\gstwinrt-1.0-0.dll"
!endif
Delete "$INSTDIR\harfbuzz.dll"
Delete "$INSTDIR\intl-8.dll"
Delete "$INSTDIR\jpeg62.dll"
Delete "$INSTDIR\kdsingleapplication-qt6.dll"
Delete "$INSTDIR\libbs2b.dll"
!ifndef arch_arm64
Delete "$INSTDIR\libfaac_dll.dll"
!endif
Delete "$INSTDIR\liblzma.dll"
Delete "$INSTDIR\libmp3lame.dll"
Delete "$INSTDIR\libopenmpt.dll"
Delete "$INSTDIR\mpcdec.dll"
@@ -994,6 +989,11 @@ Section "Uninstall"
Delete "$INSTDIR\vorbisfile.dll"
Delete "$INSTDIR\wavpackdll.dll"
!ifndef arch_arm64
Delete "$INSTDIR\gnutls.dll"
Delete "$INSTDIR\libfaac_dll.dll"
!endif
!ifdef release
Delete "$INSTDIR\freetype.dll"
Delete "$INSTDIR\libiconv.dll"
@@ -1001,10 +1001,10 @@ Section "Uninstall"
Delete "$INSTDIR\libspeex.dll"
Delete "$INSTDIR\pcre2-8.dll"
Delete "$INSTDIR\pcre2-16.dll"
Delete "$INSTDIR\zlib1.dll"
!ifndef arch_arm64
Delete "$INSTDIR\twolame.dll"
!endif
Delete "$INSTDIR\zlib1.dll"
!endif
!ifdef debug
Delete "$INSTDIR\freetyped.dll"
@@ -1013,10 +1013,10 @@ Section "Uninstall"
Delete "$INSTDIR\libspeexd.dll"
Delete "$INSTDIR\pcre2-8d.dll"
Delete "$INSTDIR\pcre2-16d.dll"
Delete "$INSTDIR\zlibd1.dll"
!ifndef arch_arm64
Delete "$INSTDIR\twolamed.dll"
!endif
Delete "$INSTDIR\zlibd1.dll"
!endif
!ifdef arch_x86
@@ -1028,15 +1028,15 @@ Section "Uninstall"
; Common files
Delete "$INSTDIR\icudt77.dll"
Delete "$INSTDIR\icudt78.dll"
!ifdef msvc && arch_arm64
Delete "$INSTDIR\fftw3.dll"
!else
Delete "$INSTDIR\libfftw3-3.dll"
!endif
!ifdef msvc && debug
Delete "$INSTDIR\icuin77d.dll"
Delete "$INSTDIR\icuuc77d.dll"
Delete "$INSTDIR\icuin78d.dll"
Delete "$INSTDIR\icuuc78d.dll"
Delete "$INSTDIR\libxml2d.dll"
Delete "$INSTDIR\Qt6Concurrentd.dll"
Delete "$INSTDIR\Qt6Cored.dll"
@@ -1045,8 +1045,8 @@ Section "Uninstall"
Delete "$INSTDIR\Qt6Sqld.dll"
Delete "$INSTDIR\Qt6Widgetsd.dll"
!else
Delete "$INSTDIR\icuin77.dll"
Delete "$INSTDIR\icuuc77.dll"
Delete "$INSTDIR\icuin78.dll"
Delete "$INSTDIR\icuuc78.dll"
Delete "$INSTDIR\libxml2.dll"
Delete "$INSTDIR\Qt6Concurrent.dll"
Delete "$INSTDIR\Qt6Core.dll"
@@ -1056,6 +1056,7 @@ Section "Uninstall"
Delete "$INSTDIR\Qt6Widgets.dll"
!endif
!ifdef msvc && arch_x86
Delete "$INSTDIR\avcodec-61.dll"
Delete "$INSTDIR\avfilter-10.dll"
Delete "$INSTDIR\avformat-61.dll"
@@ -1063,6 +1064,14 @@ Section "Uninstall"
Delete "$INSTDIR\postproc-58.dll"
Delete "$INSTDIR\swresample-5.dll"
Delete "$INSTDIR\swscale-8.dll"
!else
Delete "$INSTDIR\avcodec-62.dll"
Delete "$INSTDIR\avfilter-11.dll"
Delete "$INSTDIR\avformat-62.dll"
Delete "$INSTDIR\avutil-60.dll"
Delete "$INSTDIR\swresample-6.dll"
Delete "$INSTDIR\swscale-9.dll"
!endif
!ifdef mingw
Delete "$INSTDIR\gio-modules\libgiognutls.dll"
@@ -1156,6 +1165,7 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwasapi.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwasapi2.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwaveform.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavenc.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"

View File

@@ -18,7 +18,7 @@
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"

View File

@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef ANALYZERBASE_H
#define ANALYZERBASE_H
@@ -90,4 +90,3 @@ class AnalyzerBase : public QWidget {
};
#endif // ANALYZERBASE_H

View File

@@ -15,7 +15,7 @@
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"
@@ -61,7 +61,7 @@ constexpr int kLowFramerate = 20;
constexpr int kMediumFramerate = 25;
constexpr int kHighFramerate = 30;
constexpr int kSuperHighFramerate = 60;
} // namespace
} // namespace
AnalyzerContainer::AnalyzerContainer(QWidget *parent)
: QWidget(parent),

View File

@@ -15,7 +15,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef ANALYZERCONTAINER_H
#define ANALYZERCONTAINER_H
@@ -101,8 +101,7 @@ void AnalyzerContainer::AddAnalyzerType() {
group_->addAction(action);
action->setCheckable(true);
actions_ << action;
QObject::connect(action, &QAction::triggered, [this, id]() { ChangeAnalyzer(id); } );
QObject::connect(action, &QAction::triggered, [this, id]() { ChangeAnalyzer(id); });
}
#endif // ANALYZERCONTAINER_H

View File

@@ -19,7 +19,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "blockanalyzer.h"
@@ -61,11 +61,12 @@ BlockAnalyzer::BlockAnalyzer(QWidget *parent)
fade_intensity_(1 << 8, 32),
step_(0) {
setMinimumSize(kMinColumns * (kWidth + 1) - 1, kMinRows * (kHeight + 1) - 1); //-1 is padding, no drawing takes place there
setMinimumSize(kMinColumns * (kWidth + 1) - 1, kMinRows * (kHeight + 1) - 1); // -1 is padding, no drawing takes place there
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));
}
void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
@@ -237,7 +238,7 @@ static inline void adjustToLimits(const int b, int &f, int &amount) {
* Clever contrast function
*
* It will try to adjust the foreground color such that it contrasts well with
*the background
* the background
* It won't modify the hue of fg unless absolutely necessary
* @return the adjusted form of fg
*/

View File

@@ -19,7 +19,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef BLOCKANALYZER_H
#define BLOCKANALYZER_H
@@ -41,14 +41,14 @@ class BlockAnalyzer : public AnalyzerBase {
Q_OBJECT
public:
Q_INVOKABLE explicit BlockAnalyzer(QWidget*);
Q_INVOKABLE explicit BlockAnalyzer(QWidget *parent);
static const char *kName;
protected:
void transform(Scope&) override;
void transform(Scope &s) override;
void analyze(QPainter &p, const Scope &s, const bool new_frame) override;
void resizeEvent(QResizeEvent*) override;
void resizeEvent(QResizeEvent *e) override;
virtual void paletteChange(const QPalette &_palette);
void framerateChanged() override;

View File

@@ -20,7 +20,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "boomanalyzer.h"
@@ -143,7 +143,7 @@ void BoomAnalyzer::analyze(QPainter &p, const Scope &scope, const bool new_frame
bar_height_[i] = std::max(0.0, bar_height_[i]);
}
peak_handling:
peak_handling:
if (peak_height_[i] > 0.0) {
peak_height_[i] -= peak_speed_[i];

View File

@@ -20,7 +20,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef BOOMANALYZER_H
#define BOOMANALYZER_H
@@ -40,7 +40,7 @@ class BoomAnalyzer : public AnalyzerBase {
Q_OBJECT
public:
Q_INVOKABLE explicit BoomAnalyzer(QWidget*);
Q_INVOKABLE explicit BoomAnalyzer(QWidget *parent);
static const char *kName;
@@ -70,7 +70,6 @@ class BoomAnalyzer : public AnalyzerBase {
QPixmap barPixmap_;
QPixmap canvas_;
};
#endif // BOOMANALYZER_H

View File

@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "fht.h"

View File

@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef FHT_H
#define FHT_H
@@ -55,20 +55,20 @@ class FHT {
/**
* Recursive in-place Hartley transform. For internal use only!
*/
void _transform(float*, int, int);
void _transform(float *p, int n, int k);
public:
/**
* Prepare transform for data sets with @f$2^n@f$ numbers, whereby @f$n@f$
* should be at least 3. Values of more than 3 need a trigonometry table.
* @see makeCasTable()
*/
* Prepare transform for data sets with @f$2^n@f$ numbers, whereby @f$n@f$
* should be at least 3. Values of more than 3 need a trigonometry table.
* @see makeCasTable()
*/
explicit FHT(uint);
~FHT();
int sizeExp() const;
int size() const;
void scale(float*, float) const;
void scale(float *p, float d) const;
/**
* Exponentially Weighted Moving Average (EWMA) filter.
@@ -90,12 +90,12 @@ class FHT {
/**
* Semi-logarithmic audio spectrum.
*/
void semiLogSpectrum(float*);
void semiLogSpectrum(float *p);
/**
* Fourier spectrum.
*/
void spectrum(float*);
void spectrum(float *p);
/**
* Calculates a mathematically correct FFT power spectrum.
@@ -103,7 +103,7 @@ class FHT {
* and factor the 0.5 in the final scaling factor.
* @see FHT::power2()
*/
void power(float*);
void power(float *p);
/**
* Calculates an FFT power spectrum with doubled values as a
@@ -112,14 +112,14 @@ class FHT {
* of @f$2^n@f$ input values. This is the fastest transform.
* @see FHT::power()
*/
void power2(float*);
void power2(float *p);
/**
* Discrete Hartley transform of data sets with 8 values.
*/
static void transform8(float*);
static void transform8(float *p);
void transform(float*);
void transform(float *p);
};
#endif // FHT_H

View File

@@ -21,7 +21,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "rainbowanalyzer.h"

View File

@@ -21,7 +21,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef RAINBOWANALYZER_H
#define RAINBOWANALYZER_H
@@ -85,7 +85,7 @@ class RainbowAnalyzer : public AnalyzerBase {
private:
// "constants" that get initialized in the constructor
float band_scale_[kRainbowBands] {};
float band_scale_[kRainbowBands]{};
QPen colors_[kRainbowBands];
// Rainbow Nyancat & Dash
@@ -96,7 +96,7 @@ class RainbowAnalyzer : public AnalyzerBase {
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.

View File

@@ -19,7 +19,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef SONOGRAMANALYZER_H
#define SONOGRAMANALYZER_H

View File

@@ -20,7 +20,7 @@
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include "config.h"
@@ -70,7 +70,7 @@ void TurbineAnalyzer::analyze(QPainter &p, const Scope &scope, const bool new_fr
bar_height_[i] = std::max(0.0, bar_height_[i]);
}
peak_handling:
peak_handling:
if (peak_height_[i] > 0.0) {
peak_height_[i] -= peak_speed_[i];
peak_speed_[i] *= F_peakSpeed_; // 1.12

View File

@@ -18,7 +18,7 @@
You should have received a copy of the GNU General Public License
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#ifndef TURBINEANALYZER_H
#define TURBINEANALYZER_H

View File

@@ -14,7 +14,7 @@
You should have received a copy of the GNU General Public License
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
*/
*/
#include <QPixmap>

View File

@@ -140,7 +140,6 @@ class CollectionBackend : public CollectionBackendInterface {
Q_OBJECT
public:
Q_INVOKABLE explicit CollectionBackend(QObject *parent = nullptr);
~CollectionBackend();
@@ -331,4 +330,3 @@ class CollectionBackend : public CollectionBackendInterface {
};
#endif // COLLECTIONBACKEND_H

View File

@@ -26,7 +26,6 @@
class CollectionFilterOptions {
public:
explicit CollectionFilterOptions();
// Filter mode:

View File

@@ -135,4 +135,3 @@ class CollectionFilterWidget : public QWidget {
};
#endif // COLLECTIONFILTERWIDGET_H

View File

@@ -212,6 +212,7 @@ void CollectionModel::ReloadSettings() {
const bool show_various_artists = settings.value(CollectionSettings::kVariousArtists, true).toBool();
const bool sort_skip_articles_for_artists = settings.value(CollectionSettings::kSkipArticlesForArtists, true).toBool();
const bool sort_skip_articles_for_albums = settings.value(CollectionSettings::kSkipArticlesForAlbums, false).toBool();
const bool use_sort_tags = settings.value(CollectionSettings::kUseSortTags, true).toBool();
use_disk_cache_ = settings.value(CollectionSettings::kSettingsDiskCacheEnable, false).toBool();
QPixmapCache::setCacheLimit(static_cast<int>(MaximumCacheSize(&settings, CollectionSettings::kSettingsCacheSize, CollectionSettings::kSettingsCacheSizeUnit, CollectionSettings::kSettingsCacheSizeDefault) / 1024));
@@ -227,12 +228,14 @@ void CollectionModel::ReloadSettings() {
show_dividers != options_current_.show_dividers ||
show_various_artists != options_current_.show_various_artists ||
sort_skip_articles_for_artists != options_current_.sort_skip_articles_for_artists ||
sort_skip_articles_for_albums != options_current_.sort_skip_articles_for_albums) {
sort_skip_articles_for_albums != options_current_.sort_skip_articles_for_albums ||
use_sort_tags != options_current_.use_sort_tags) {
options_current_.show_pretty_covers = show_pretty_covers;
options_current_.show_dividers = show_dividers;
options_current_.show_various_artists = show_various_artists;
options_current_.sort_skip_articles_for_artists = sort_skip_articles_for_artists;
options_current_.sort_skip_articles_for_albums = sort_skip_articles_for_albums;
options_current_.use_sort_tags = use_sort_tags;
ScheduleReset();
}
@@ -427,6 +430,8 @@ void CollectionModel::ScheduleUpdate(const CollectionModelUpdate::Type type, con
void CollectionModel::ScheduleReset() {
if (!updates_.isEmpty() && updates_.first().type == CollectionModelUpdate::Type::Reset) return;
ScheduleUpdate(CollectionModelUpdate::Type::Reset);
}
@@ -540,7 +545,10 @@ void CollectionModel::AddSongsInternal(const SongList &songs) {
// Sanity check to make sure we don't add songs that are outside the user's filter
if (!options_active_.filter_options.Matches(song)) continue;
if (song_nodes_.contains(song.id())) continue;
if (song_nodes_.contains(song.id())) {
qLog(Debug) << song.id() << song.title() << "already exists, skipping";
continue;
}
// Before we can add each song we need to make sure the required container items already exist in the tree.
// These depend on which "group by" settings the user has on the collection.
@@ -681,8 +689,8 @@ void CollectionModel::RemoveSongsInternal(const SongList &songs) {
if (!divider_nodes_.contains(divider_key)) continue;
// Look to see if there are any other items still under this divider
QList<CollectionItem*> container_nodes = container_nodes_[0].values();
if (std::any_of(container_nodes.begin(), container_nodes.end(), [this, divider_key](CollectionItem *node){ return DividerKey(options_active_.group_by[0], node->metadata, node->sort_text) == divider_key; })) {
QList<CollectionItem *> container_nodes = container_nodes_[0].values();
if (std::any_of(container_nodes.begin(), container_nodes.end(), [this, divider_key](CollectionItem *node) { return DividerKey(options_active_.group_by[0], node->metadata, node->sort_text) == divider_key; })) {
continue;
}
@@ -700,7 +708,7 @@ CollectionItem *CollectionModel::CreateContainerItem(const GroupBy group_by, con
QString divider_key;
if (options_active_.show_dividers && container_level == 0) {
divider_key = DividerKey(group_by, song, SortText(group_by, song, options_active_.sort_skip_articles_for_artists, options_active_.sort_skip_articles_for_albums));
divider_key = DividerKey(group_by, song, SortText(group_by, song, options_active_.sort_skip_articles_for_artists, options_active_.sort_skip_articles_for_albums, options_active_.use_sort_tags));
if (!divider_key.isEmpty()) {
if (!divider_nodes_.contains(divider_key)) {
CreateDividerItem(divider_key, DividerDisplayText(group_by, divider_key), parent);
@@ -714,7 +722,7 @@ CollectionItem *CollectionModel::CreateContainerItem(const GroupBy group_by, con
item->container_level = container_level;
item->container_key = container_key;
item->display_text = DisplayText(group_by, song);
item->sort_text = SortText(group_by, song, options_active_.sort_skip_articles_for_artists, options_active_.sort_skip_articles_for_albums);
item->sort_text = SortText(group_by, song, options_active_.sort_skip_articles_for_artists, options_active_.sort_skip_articles_for_albums, options_active_.use_sort_tags);
if (!divider_key.isEmpty()) {
item->sort_text.prepend(divider_key + QLatin1Char(' '));
}
@@ -1069,37 +1077,37 @@ QString CollectionModel::PrettyFormat(const Song &song) {
}
QString CollectionModel::SortText(const GroupBy group_by, const Song &song, const bool sort_skip_articles_for_artists, const bool sort_skip_articles_for_albums) {
QString CollectionModel::SortText(const GroupBy group_by, const Song &song, const bool sort_skip_articles_for_artists, const bool sort_skip_articles_for_albums, const bool use_sort_tags) {
switch (group_by) {
case GroupBy::AlbumArtist:
return SortTextForName(song.effective_albumartistsort(), sort_skip_articles_for_artists);
return SortTextForName(use_sort_tags ? song.effective_albumartistsort() : song.effective_albumartist(), sort_skip_articles_for_artists);
case GroupBy::Artist:
return SortTextForName(song.effective_artistsort(), sort_skip_articles_for_artists);
return SortTextForName(use_sort_tags ? song.effective_artistsort() : song.artist(), sort_skip_articles_for_artists);
case GroupBy::Album:
return SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums);
return SortTextForName(use_sort_tags ? song.effective_albumsort() : song.album(), sort_skip_articles_for_albums);
case GroupBy::AlbumDisc:
return SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc()));
return SortTextForName(use_sort_tags ? song.effective_albumsort() : song.album(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc()));
case GroupBy::YearAlbum:
return SortTextForNumber(std::max(0, song.year())) + song.grouping() + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums);
return SortTextForYear(song.year()) + song.grouping() + SortTextForName(use_sort_tags ? song.effective_albumsort() : song.album(), sort_skip_articles_for_albums);
case GroupBy::YearAlbumDisc:
return SortTextForNumber(std::max(0, song.year())) + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc()));
return SortTextForYear(song.year()) + SortTextForName(use_sort_tags ? song.effective_albumsort() : song.album(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc()));
case GroupBy::OriginalYearAlbum:
return SortTextForNumber(std::max(0, song.effective_originalyear())) + song.grouping() + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums);
return SortTextForYear(song.effective_originalyear()) + song.grouping() + SortTextForName(use_sort_tags ? song.effective_albumsort() : song.album(), sort_skip_articles_for_albums);
case GroupBy::OriginalYearAlbumDisc:
return SortTextForNumber(std::max(0, song.effective_originalyear())) + SortTextForName(song.effective_albumsort(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc()));
return SortTextForYear(song.effective_originalyear()) + SortTextForName(use_sort_tags ? song.effective_albumsort() : song.album(), sort_skip_articles_for_albums) + SortTextForNumber(std::max(0, song.disc()));
case GroupBy::Disc:
return SortTextForNumber(std::max(0, song.disc()));
case GroupBy::Year:
return SortTextForNumber(std::max(0, song.year())) + QLatin1Char(' ');
return SortTextForYear(song.year()) + QLatin1Char(' ');
case GroupBy::OriginalYear:
return SortTextForNumber(std::max(0, song.effective_originalyear())) + QLatin1Char(' ');
return SortTextForYear(song.effective_originalyear()) + QLatin1Char(' ');
case GroupBy::Genre:
return SortText(song.genre());
case GroupBy::Composer:
return SortTextForName(song.effective_composersort(), sort_skip_articles_for_artists);
return SortTextForName(use_sort_tags ? song.effective_composersort() : song.composer(), sort_skip_articles_for_artists);
case GroupBy::Performer:
return SortTextForName(song.effective_performersort(), sort_skip_articles_for_artists);
return SortTextForName(use_sort_tags ? song.effective_performersort() : song.performer(), sort_skip_articles_for_artists);
case GroupBy::Grouping:
return SortText(song.grouping());
case GroupBy::FileType:
@@ -1157,14 +1165,14 @@ QString CollectionModel::SortTextForSong(const Song &song) {
QString CollectionModel::SortTextForYear(const int year) {
QString str = QString::number(year);
const QString str = QString::number(std::max(year, 0));
return QStringLiteral("0").repeated(qMax(0, 4 - str.length())) + str;
}
QString CollectionModel::SortTextForBitrate(const int bitrate) {
QString str = QString::number(bitrate);
const QString str = QString::number(bitrate);
return QStringLiteral("0").repeated(qMax(0, 3 - str.length())) + str;
}
@@ -1201,39 +1209,50 @@ QString CollectionModel::ContainerKey(const GroupBy group_by, const Song &song,
switch (group_by) {
case GroupBy::AlbumArtist:
key = TextOrUnknown(song.effective_albumartist());
if (!song.effective_albumartistsort().isEmpty() && song.effective_albumartistsort() != song.effective_albumartist()) key.append(QLatin1Char('-') + TextOrUnknown(song.effective_albumartistsort()));
has_unique_album_identifier = true;
break;
case GroupBy::Artist:
key = TextOrUnknown(song.artist());
if (!song.artistsort().isEmpty() && song.artistsort() != song.artist()) key.append(QLatin1Char('-') + TextOrUnknown(song.artistsort()));
has_unique_album_identifier = true;
break;
case GroupBy::Album:
key = TextOrUnknown(song.album());
if (!song.albumsort().isEmpty() && song.albumsort() != song.album()) key.append(QLatin1Char('-') + TextOrUnknown(song.albumsort()));
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
if (options_active_.separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
break;
case GroupBy::AlbumDisc:
key = PrettyAlbumDisc(song.album(), song.disc());
key = TextOrUnknown(song.album());
if (!song.albumsort().isEmpty() && song.albumsort() != song.album()) key.append(QLatin1Char('-') + TextOrUnknown(song.albumsort()));
key.append(QLatin1Char('-') + SortTextForNumber(song.disc()));
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
if (options_active_.separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
break;
case GroupBy::YearAlbum:
key = PrettyYearAlbum(song.year(), song.album());
key = SortTextForYear(song.year()) + QLatin1Char('-') + TextOrUnknown(song.album());
if (!song.albumsort().isEmpty() && song.albumsort() != song.album()) key.append(QLatin1Char('-') + TextOrUnknown(song.albumsort()));
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
if (options_active_.separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
break;
case GroupBy::YearAlbumDisc:
key = PrettyYearAlbumDisc(song.year(), song.album(), song.disc());
key = SortTextForYear(song.year()) + QLatin1Char('-') + TextOrUnknown(song.album());
if (!song.albumsort().isEmpty() && song.albumsort() != song.album()) key.append(QLatin1Char('-') + TextOrUnknown(song.albumsort()));
key.append(QLatin1Char('-') + SortTextForNumber(song.disc()));
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
if (options_active_.separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
break;
case GroupBy::OriginalYearAlbum:
key = PrettyYearAlbum(song.effective_originalyear(), song.album());
key = SortTextForYear(song.effective_originalyear()) + QLatin1Char('-') + TextOrUnknown(song.album());
if (!song.albumsort().isEmpty() && song.albumsort() != song.album()) key.append(QLatin1Char('-') + TextOrUnknown(song.albumsort()));
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
if (options_active_.separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
break;
case GroupBy::OriginalYearAlbumDisc:
key = PrettyYearAlbumDisc(song.effective_originalyear(), song.album(), song.disc());
key = SortTextForYear(song.effective_originalyear()) + QLatin1Char('-') + TextOrUnknown(song.album());
if (!song.albumsort().isEmpty() && song.albumsort() != song.album()) key.append(QLatin1Char('-') + TextOrUnknown(song.albumsort()));
key.append(QLatin1Char('-') + SortTextForNumber(song.disc()));
if (!song.album_id().isEmpty()) key.append(QLatin1Char('-') + song.album_id());
if (options_active_.separate_albums_by_grouping && !song.grouping().isEmpty()) key.append(QLatin1Char('-') + song.grouping());
break;
@@ -1241,20 +1260,22 @@ QString CollectionModel::ContainerKey(const GroupBy group_by, const Song &song,
key = PrettyDisc(song.disc());
break;
case GroupBy::Year:
key = QString::number(std::max(0, song.year()));
key = SortTextForYear(song.year());
break;
case GroupBy::OriginalYear:
key = QString::number(std::max(0, song.effective_originalyear()));
key = SortTextForYear(song.effective_originalyear());
break;
case GroupBy::Genre:
key = TextOrUnknown(song.genre());
break;
case GroupBy::Composer:
key = TextOrUnknown(song.composer());
if (!song.composersort().isEmpty() && song.composersort() != song.composer()) key.append(QLatin1Char('-') + song.composersort());
has_unique_album_identifier = true;
break;
case GroupBy::Performer:
key = TextOrUnknown(song.performer());
if (!song.performersort().isEmpty() && song.performersort() != song.performer()) key.append(QLatin1Char('-') + song.performersort());
has_unique_album_identifier = true;
break;
case GroupBy::Grouping:
@@ -1336,7 +1357,7 @@ QString CollectionModel::DividerKey(const GroupBy group_by, const Song &song, co
case GroupBy::Bitdepth:
return SortTextForNumber(song.bitdepth());
case GroupBy::Bitrate:
return SortTextForNumber(song.bitrate());
return SortTextForBitrate(song.bitrate());
case GroupBy::None:
case GroupBy::GroupByCount:
return QString();

View File

@@ -131,6 +131,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
show_various_artists(true),
sort_skip_articles_for_artists(false),
sort_skip_articles_for_albums(false),
use_sort_tags(true),
separate_albums_by_grouping(false) {}
Grouping group_by;
@@ -139,6 +140,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
bool show_various_artists;
bool sort_skip_articles_for_artists;
bool sort_skip_articles_for_albums;
bool use_sort_tags;
bool separate_albums_by_grouping;
CollectionFilterOptions filter_options;
};
@@ -178,14 +180,14 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
QMimeData *mimeData(const QModelIndexList &indexes) const override;
// Utility functions for manipulating text
QString DisplayText(const GroupBy group_by, const Song &song);
static QString DisplayText(const GroupBy group_by, const Song &song);
static QString TextOrUnknown(const QString &text);
static QString PrettyYearAlbum(const int year, const QString &album);
static QString PrettyAlbumDisc(const QString &album, const int disc);
static QString PrettyYearAlbumDisc(const int year, const QString &album, const int disc);
static QString PrettyDisc(const int disc);
static QString PrettyFormat(const Song &song);
QString SortText(const GroupBy group_by, const Song &song, const bool sort_skip_articles_for_artists, const bool sort_skip_articles_for_albums);
static QString SortText(const GroupBy group_by, const Song &song, const bool sort_skip_articles_for_artists, const bool sort_skip_articles_for_albums, const bool use_sort_tags);
static QString SortText(QString text);
static QString SortTextForName(const QString &name, const bool sort_skip_articles);
static QString SortTextForNumber(const int number);

View File

@@ -58,4 +58,3 @@ class CollectionPlaylistItem : public PlaylistItem {
};
#endif // COLLECTIONPLAYLISTITEM_H

View File

@@ -101,9 +101,9 @@ void CollectionQuery::AddCompilationRequirement(const bool compilation) {
QString CollectionQuery::GetInnerQuery() const {
return duplicates_only_
? QStringLiteral(" INNER JOIN (select * from duplicated_songs) dsongs "
"ON (%songs_table.artist = dsongs.dup_artist "
"AND %songs_table.album = dsongs.dup_album "
"AND %songs_table.title = dsongs.dup_title) ")
"ON (%songs_table.artist = dsongs.dup_artist "
"AND %songs_table.album = dsongs.dup_album "
"AND %songs_table.title = dsongs.dup_title) ")
: QString();
}

View File

@@ -137,7 +137,7 @@ class CollectionWatcher : public QObject {
QStringList files_changed_path_;
private:
ScanTransaction &operator=(const ScanTransaction&) { return *this; }
ScanTransaction &operator=(const ScanTransaction &transaction) { Q_UNUSED(transaction); return *this; }
int task_id_;
quint64 progress_;
@@ -261,7 +261,6 @@ class CollectionWatcher : public QObject {
static QStringList sValidImages;
qint64 last_scan_time_;
};
inline QString CollectionWatcher::NoExtensionPart(const QString &fileName) {

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 APPEARANCESETTINGS_H
#define APPEARANCESETTINGS_H
@@ -70,6 +70,6 @@ enum class BackgroundImagePosition {
BottomRight = 5
};
} // namespace
} // namespace AppearanceSettings
#endif // APPEARANCESETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 BACKENDSETTINGS_H
#define BACKENDSETTINGS_H
@@ -63,6 +63,6 @@ constexpr qint64 kDefaultBufferDuration = 4000;
constexpr double kDefaultBufferLowWatermark = 0.33;
constexpr double kDefaultBufferHighWatermark = 0.99;
} // namespace
} // namespace BackendSettings
#endif // BACKENDSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 BEHAVIOURSETTINGS_H
#define BEHAVIOURSETTINGS_H
@@ -71,6 +71,6 @@ constexpr char kDoubleClickPlaylistAddMode[] = "doubleclick_playlist_addmode";
constexpr char kSeekStepSec[] = "seek_step_sec";
constexpr char kVolumeIncrement[] = "volume_increment";
} // namespace
} // namespace BehaviourSettings
#endif // BEHAVIOURSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024-2025, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024-2025, 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 COLLECTIONSETTINGS_H
#define COLLECTIONSETTINGS_H
@@ -37,7 +37,7 @@ constexpr char kPrettyCovers[] = "pretty_covers";
constexpr char kVariousArtists[] = "various_artists";
constexpr char kSkipArticlesForArtists[] = "skip_articles_for_artists";
constexpr char kSkipArticlesForAlbums[] = "skip_articles_for_albums";
constexpr char kShowSortText[] = "show_sort_text";
constexpr char kUseSortTags[] = "use_short_tags";
constexpr char kSettingsCacheSize[] = "cache_size";
constexpr char kSettingsCacheSizeUnit[] = "cache_size_unit";
constexpr char kSettingsDiskCacheEnable[] = "disk_cache_enable";
@@ -59,6 +59,6 @@ enum class CacheSizeUnit {
TB
};
} // namespace
} // namespace CollectionSettings
#endif // COLLECTIONSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 CONTEXTSETTINGS_H
#define CONTEXTSETTINGS_H
@@ -43,6 +43,6 @@ constexpr char kSettingsSummaryFmt[] = "SummaryFmt";
constexpr char kDefaultFontFamily[] = "Noto Sans";
constexpr qreal kDefaultFontSizeHeadline = 11;
} // namespace
} // namespace ContextSettings
#endif // CONTEXTSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 COVERSSETTINGS_H
#define COVERSSETTINGS_H
@@ -32,6 +32,6 @@ constexpr char kSaveOverwrite[] = "save_overwrite";
constexpr char kSaveLowercase[] = "save_lowercase";
constexpr char kSaveReplaceSpaces[] = "save_replace_spaces";
} // namespace
} // namespace CoversSettings
#endif // COVERSSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 FILEFILTERCONSTANTS_H
#define FILEFILTERCONSTANTS_H
@@ -27,7 +27,7 @@ constexpr char kAllFilesFilterSpec[] = QT_TRANSLATE_NOOP("FileFilter", "All File
constexpr char kFileFilter[] =
"*.wav *.flac *.wv *.ogg *.oga *.opus *.spx *.ape *.mpc "
"*.mp2 *.mp3 *.m4a *.mp4 *.aac *.asf *.asx *.wma "
"*.aif *.aiff *.mka *.tta *.dsf *.dsd "
"*.aif *.aiff *.mka *.tta *.dsf *.dsd *.webm "
"*.cue *.m3u *.m3u8 *.pls *.xspf *.asxini "
"*.ac3 *.dts "
"*.mod *.s3m *.xm *.it "

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2023, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2023, 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 FILENAMECONSTANTS_H
#define FILENAMECONSTANTS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2025, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2025, 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 FILESYSTEMCONSTANTS_H
#define FILESYSTEMCONSTANTS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 GLOBALSHORTCUTSSETTINGS_H
#define GLOBALSHORTCUTSSETTINGS_H
@@ -26,6 +26,6 @@ constexpr char kSettingsGroup[] = "GlobalShortcuts";
constexpr char kUseKGlobalAccel[] = "use_kglobalaccel";
constexpr char kUseX11[] = "use_x11";
} // namespace
} // namespace GlobalShortcutsSettings
#endif // GLOBALSHORTCUTSSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 LYRICSSETTINGS_H
#define LYRICSSETTINGS_H
@@ -25,6 +25,6 @@ namespace LyricsSettings {
constexpr char kSettingsGroup[] = "Lyrics";
constexpr char kProviders[] = "providers";
} // namespace
} // namespace LyricsSettings
#endif // LYRICSSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 MAINWINDOWSETTINGS_H
#define MAINWINDOWSETTINGS_H
@@ -32,6 +32,6 @@ constexpr char kGeometry[] = "geometry";
constexpr char kSplitterState[] = "splitter_state";
constexpr char kDoNotShowSponsorMessage[] = "do_not_show_sponsor_message";
} // namespace
} // namespace MainWindowSettings
#endif // MAINWINDOWSETTINGS_H
#endif // MAINWINDOWSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 MOODBARSETTINGS_H
#define MOODBARSETTINGS_H
@@ -38,6 +38,6 @@ constexpr char kShow[] = "show";
constexpr char kStyle[] = "style";
constexpr char kSave[] = "save";
} // namespace
} // namespace MoodbarSettings
#endif // MOODBARSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 NETWORKPROXYSETTINGS_H
#define NETWORKPROXYSETTINGS_H
@@ -32,6 +32,6 @@ constexpr char kUsername[] = "username";
constexpr char kPassword[] = "password";
constexpr char kEngine[] = "engine";
} // namespace
} // namespace NetworkProxySettings
#endif // NETWORKPROXYSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 NOTIFICATIONSSETTINGS_H
#define NOTIFICATIONSSETTINGS_H
@@ -45,7 +45,7 @@ constexpr char kCustomTextEnabled[] = "CustomTextEnabled";
constexpr char kCustomText1[] = "CustomText1";
constexpr char kCustomText2[] = "CustomText2";
} // namespace
} // namespace OSDSettings
namespace OSDPrettySettings {
@@ -63,7 +63,7 @@ constexpr char kFading[] = "fading";
constexpr QRgb kPresetBlue = qRgb(102, 150, 227);
constexpr QRgb kPresetRed = qRgb(202, 22, 16);
} // namespace
} // namespace OSDPrettySettings
namespace DiscordRPCSettings {
@@ -71,6 +71,14 @@ constexpr char kSettingsGroup[] = "DiscordRPC";
constexpr char kEnabled[] = "enabled";
} // namespace
constexpr char kStatusDisplayType[] = "StatusDisplayType";
enum class StatusDisplayType {
App = 0,
Artist,
Song
};
} // namespace DiscordRPCSettings
#endif // NOTIFICATIONSSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 PLAYLISTSETTINGS_H
#define PLAYLISTSETTINGS_H
@@ -63,7 +63,7 @@ constexpr char kLastSaveExtension[] = "last_save_extension";
constexpr char kLastSaveAllPath[] = "last_save_all_path";
constexpr char kLastSaveAllExtension[] = "last_save_all_extension";
} // namespace
} // namespace PlaylistSettings
Q_DECLARE_METATYPE(PlaylistSettings::PathType)

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 QOBUZSETTINGS_H
#define QOBUZSETTINGS_H
@@ -36,12 +36,13 @@ constexpr char kAlbumsSearchLimit[] = "albumssearchlimit";
constexpr char kSongsSearchLimit[] = "songssearchlimit";
constexpr char kBase64Secret[] = "base64secret";
constexpr char kDownloadAlbumCovers[] = "downloadalbumcovers";
constexpr char kRemoveRemastered[] = "remove_remastered";
constexpr char kUserId[] = "user_id";
constexpr char kCredentialsId[] = "credentials_id";
constexpr char kDeviceId[] = "device_id";
constexpr char kUserAuthToken[] = "user_auth_token";
} // namespace
} // namespace QobuzSettings
#endif // QOBUZSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 SCROBBLERSETTINGS_H
#define SCROBBLERSETTINGS_H
@@ -35,6 +35,6 @@ constexpr char kStripRemastered[] = "strip_remastered";
constexpr char kSources[] = "sources";
constexpr char kUserToken[] = "user_token";
} // namespace
} // namespace ScrobblerSettings
#endif // SCROBBLERSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 SPOTIFYSETTINGS_H
#define SPOTIFYSETTINGS_H
@@ -31,12 +31,13 @@ constexpr char kAlbumsSearchLimit[] = "albumssearchlimit";
constexpr char kSongsSearchLimit[] = "songssearchlimit";
constexpr char kFetchAlbums[] = "fetchalbums";
constexpr char kDownloadAlbumCovers[] = "downloadalbumcovers";
constexpr char kRemoveRemastered[] = "remove_remastered";
constexpr char kAccessToken[] = "access_token";
constexpr char kRefreshToken[] = "refresh_token";
constexpr char kExpiresIn[] = "expires_in";
constexpr char kLoginTime[] = "login_time";
} // namespace
} // namespace SpotifySettings
#endif // SPOTIFYSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 SUBSONICETTINGS_H
@@ -41,6 +41,6 @@ constexpr char kUseAlbumIdForAlbumCovers[] = "usealbumidforalbumcovers";
constexpr char kServerSideScrobbling[] = "serversidescrobbling";
constexpr char kAuthMethod[] = "authmethod";
} // namespace
} // namespace SubsonicSettings
#endif // SUBSONICETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 TIDALSETTINGS_H
#define TIDALSETTINGS_H
@@ -40,6 +40,7 @@ constexpr char kDownloadAlbumCovers[] = "downloadalbumcovers";
constexpr char kCoverSize[] = "coversize";
constexpr char kStreamUrl[] = "streamurl";
constexpr char kAlbumExplicit[] = "album_explicit";
constexpr char kRemoveRemastered[] = "remove_remastered";
enum class StreamUrlMethod {
StreamUrl,
@@ -47,6 +48,6 @@ enum class StreamUrlMethod {
PlaybackInfoPostPaywall
};
}
} // namespace TidalSettings
#endif // TIDALSETTINGS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 TIMECONSTANTS_H
#define TIMECONSTANTS_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2024, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2024, 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 TRANSCODERSETTINGS_H
@@ -26,4 +26,3 @@ constexpr char kSettingsGroup[] = "Transcoder";
}
#endif // TRANSCODERSETTINGS_H

View File

@@ -61,7 +61,6 @@ class ContextAlbum : public QWidget {
void contextMenuEvent(QContextMenuEvent *e) override;
private:
struct PreviousCover {
explicit PreviousCover() : opacity(0.0) {}
QImage image;

View File

@@ -1,6 +1,6 @@
/*
* Strawberry Music Player
* Copyright 2013-2022, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2013-2025, 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
@@ -59,6 +59,7 @@
#include "covermanager/albumcoverchoicecontroller.h"
#include "lyrics/lyricsfetcher.h"
#include "constants/contextsettings.h"
#include "constants/timeconstants.h"
#include "contextview.h"
#include "contextalbum.h"
@@ -100,15 +101,11 @@ ContextView::ContextView(QWidget *parent)
label_samplerate_title_(new QLabel(this)),
label_bitdepth_title_(new QLabel(this)),
label_bitrate_title_(new QLabel(this)),
label_ebur128_integrated_loudness_title_(new QLabel(this)),
label_ebur128_loudness_range_title_(new QLabel(this)),
label_filetype_(new QLabel(this)),
label_length_(new QLabel(this)),
label_samplerate_(new QLabel(this)),
label_bitdepth_(new QLabel(this)),
label_bitrate_(new QLabel(this)),
label_ebur128_integrated_loudness_(new QLabel(this)),
label_ebur128_loudness_range_(new QLabel(this)),
lyrics_tried_(false),
lyrics_id_(-1) {
@@ -166,24 +163,18 @@ ContextView::ContextView(QWidget *parent)
label_samplerate_title_->setText(tr("Samplerate"));
label_bitdepth_title_->setText(tr("Bit depth"));
label_bitrate_title_->setText(tr("Bitrate"));
label_ebur128_integrated_loudness_title_->setText(tr("EBU R 128 Integrated Loudness"));
label_ebur128_loudness_range_title_->setText(tr("EBU R 128 Loudness Range"));
label_filetype_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_length_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_samplerate_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_bitdepth_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_bitrate_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_ebur128_integrated_loudness_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_ebur128_loudness_range_title_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
label_filetype_->setWordWrap(true);
label_length_->setWordWrap(true);
label_samplerate_->setWordWrap(true);
label_bitdepth_->setWordWrap(true);
label_bitrate_->setWordWrap(true);
label_ebur128_integrated_loudness_->setWordWrap(true);
label_ebur128_loudness_range_->setWordWrap(true);
layout_play_data_->setContentsMargins(0, 0, 0, 0);
layout_play_data_->addWidget(label_filetype_title_, 0, 0);
@@ -197,11 +188,6 @@ ContextView::ContextView(QWidget *parent)
layout_play_data_->addWidget(label_bitrate_title_, 4, 0);
layout_play_data_->addWidget(label_bitrate_, 4, 1);
layout_play_data_->addWidget(label_ebur128_integrated_loudness_title_, 5, 0);
layout_play_data_->addWidget(label_ebur128_integrated_loudness_, 5, 1);
layout_play_data_->addWidget(label_ebur128_loudness_range_title_, 6, 0);
layout_play_data_->addWidget(label_ebur128_loudness_range_, 6, 1);
widget_play_data_->setLayout(layout_play_data_);
textedit_play_lyrics_->setReadOnly(true);
@@ -218,17 +204,13 @@ ContextView::ContextView(QWidget *parent)
<< label_length_title_
<< label_samplerate_title_
<< label_bitdepth_title_
<< label_bitrate_title_
<< label_ebur128_integrated_loudness_title_
<< label_ebur128_loudness_range_title_;
<< label_bitrate_title_;
labels_play_data_ << label_filetype_
<< label_length_
<< label_samplerate_
<< label_bitdepth_
<< label_bitrate_
<< label_ebur128_integrated_loudness_
<< label_ebur128_loudness_range_;
<< label_bitrate_;
labels_play_all_ = labels_play_ << labels_play_data_;
@@ -372,7 +354,7 @@ void ContextView::SearchLyrics() {
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && action_search_lyrics_->isChecked() && !song_playing_.artist().isEmpty() && !song_playing_.title().isEmpty() && !lyrics_tried_ && lyrics_id_ == -1) {
lyrics_fetcher_->Clear();
lyrics_tried_ = true;
lyrics_id_ = static_cast<qint64>(lyrics_fetcher_->Search(song_playing_.effective_albumartist(), song_playing_.artist(), song_playing_.album(), song_playing_.title()));
lyrics_id_ = static_cast<qint64>(lyrics_fetcher_->Search(song_playing_.effective_albumartist(), song_playing_.artist(), song_playing_.album(), song_playing_.title(), song_playing_.length_nanosec() / kNsecPerSec));
}
}
@@ -493,26 +475,6 @@ void ContextView::SetSong() {
label_bitrate_->show();
SetLabelText(label_bitrate_, song_playing_.bitrate(), tr("kbps"));
}
if (!song_playing_.ebur128_integrated_loudness_lufs()) {
label_ebur128_integrated_loudness_title_->hide();
label_ebur128_integrated_loudness_->hide();
label_ebur128_integrated_loudness_->clear();
}
else {
label_ebur128_integrated_loudness_title_->show();
label_ebur128_integrated_loudness_->show();
label_ebur128_integrated_loudness_->setText(song_playing_.Ebur128LoudnessLUFSToText());
}
if (!song_playing_.ebur128_loudness_range_lu()) {
label_ebur128_loudness_range_title_->hide();
label_ebur128_loudness_range_->hide();
label_ebur128_loudness_range_->clear();
}
else {
label_ebur128_loudness_range_title_->show();
label_ebur128_loudness_range_->show();
label_ebur128_loudness_range_->setText(song_playing_.Ebur128LoudnessRangeLUToText());
}
spacer_play_data_->changeSize(20, 20, QSizePolicy::Fixed);
}
else {
@@ -522,8 +484,6 @@ void ContextView::SetSong() {
label_samplerate_->clear();
label_bitdepth_->clear();
label_bitrate_->clear();
label_ebur128_integrated_loudness_->clear();
label_ebur128_loudness_range_->clear();
spacer_play_data_->changeSize(0, 0, QSizePolicy::Fixed);
}
@@ -598,12 +558,6 @@ void ContextView::UpdateSong(const Song &song) {
SetLabelText(label_bitrate_, song.bitrate(), tr("kbps"));
}
}
if (song.ebur128_integrated_loudness_lufs() != song_playing_.ebur128_integrated_loudness_lufs()) {
label_ebur128_integrated_loudness_->setText(song_playing_.Ebur128LoudnessLUFSToText());
}
if (song.ebur128_loudness_range_lu() != song_playing_.ebur128_loudness_range_lu()) {
label_ebur128_loudness_range_->setText(song_playing_.Ebur128LoudnessRangeLUToText());
}
}
song_playing_ = song;

View File

@@ -1,6 +1,6 @@
/*
* Strawberry Music Player
* Copyright 2013-2022, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2013-2025, 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
@@ -65,9 +65,9 @@ class ContextView : public QWidget {
protected:
void resizeEvent(QResizeEvent *e) override;
void contextMenuEvent(QContextMenuEvent*) override;
void dragEnterEvent(QDragEnterEvent*) override;
void dropEvent(QDropEvent*) override;
void contextMenuEvent(QContextMenuEvent *e) override;
void dragEnterEvent(QDragEnterEvent *e) override;
void dropEvent(QDropEvent *e) override;
private:
void AddActions();
@@ -135,18 +135,12 @@ class ContextView : public QWidget {
QLabel *label_bitdepth_title_;
QLabel *label_bitrate_title_;
QLabel *label_ebur128_integrated_loudness_title_;
QLabel *label_ebur128_loudness_range_title_;
QLabel *label_filetype_;
QLabel *label_length_;
QLabel *label_samplerate_;
QLabel *label_bitdepth_;
QLabel *label_bitrate_;
QLabel *label_ebur128_integrated_loudness_;
QLabel *label_ebur128_loudness_range_;
Song song_playing_;
Song song_prev_;
QImage image_original_;

View File

@@ -74,10 +74,10 @@
#include "lyrics/elyricsnetlyricsprovider.h"
#include "lyrics/letraslyricsprovider.h"
#include "lyrics/lyricfindlyricsprovider.h"
#include "lyrics/lrcliblyricsprovider.h"
#include "scrobbler/audioscrobbler.h"
#include "scrobbler/lastfmscrobbler.h"
#include "scrobbler/librefmscrobbler.h"
#include "scrobbler/listenbrainzscrobbler.h"
#include "scrobbler/lastfmimport.h"
#ifdef HAVE_SUBSONIC
@@ -118,8 +118,8 @@ using namespace std::chrono_literals;
class ApplicationImpl {
public:
explicit ApplicationImpl(Application *app) :
tagreader_client_([app](){
explicit ApplicationImpl(Application *app)
: tagreader_client_([app]() {
TagReaderClient *client = new TagReaderClient();
app->MoveToNewThread(client);
return client;
@@ -183,6 +183,7 @@ class ApplicationImpl {
lyrics_providers->AddProvider(new ElyricsNetLyricsProvider(lyrics_providers->network()));
lyrics_providers->AddProvider(new LetrasLyricsProvider(lyrics_providers->network()));
lyrics_providers->AddProvider(new LyricFindLyricsProvider(lyrics_providers->network()));
lyrics_providers->AddProvider(new LrcLibLyricsProvider(lyrics_providers->network()));
lyrics_providers->ReloadSettings();
return lyrics_providers;
}),
@@ -206,7 +207,6 @@ class ApplicationImpl {
scrobbler_([app]() {
AudioScrobbler *scrobbler = new AudioScrobbler(app);
scrobbler->AddService(make_shared<LastFMScrobbler>(scrobbler->settings(), app->network()));
scrobbler->AddService(make_shared<LibreFMScrobbler>(scrobbler->settings(), app->network()));
scrobbler->AddService(make_shared<ListenBrainzScrobbler>(scrobbler->settings(), app->network()));
#ifdef HAVE_SUBSONIC
scrobbler->AddService(make_shared<SubsonicScrobbler>(scrobbler->settings(), app->network(), app->streaming_services()->Service<SubsonicService>(), app));
@@ -266,7 +266,7 @@ Application::Application(QObject *parent)
Application::~Application() {
qLog(Debug) << "Terminating application";
qLog(Debug) << "Terminating application";
for (QThread *thread : std::as_const(threads_)) {
thread->quit();

View File

@@ -204,7 +204,7 @@ bool CommandlineOptions::Parse() {
{ "version", no_argument, nullptr, LongOptions::Version },
{ nullptr, 0, nullptr, 0 }
#endif
};
};
// Parse the arguments
bool ok = false;

View File

@@ -61,8 +61,8 @@ constexpr char kMagicAllSongsTables[] = "%allsongstables";
int Database::sNextConnectionId = 1;
QMutex Database::sNextConnectionIdMutex;
Database::Database(SharedPtr<TaskManager> task_manager, QObject *parent, const QString &database_name) :
QObject(parent),
Database::Database(SharedPtr<TaskManager> task_manager, QObject *parent, const QString &database_name)
: QObject(parent),
task_manager_(task_manager),
injected_database_name_(database_name),
query_hash_(0),
@@ -134,7 +134,7 @@ QSqlDatabase Database::Connect() {
return db;
}
db.setConnectOptions(u"QSQLITE_BUSY_TIMEOUT=30000"_s);
//qLog(Debug) << "Opened database with connection id" << connection_id;
// qLog(Debug) << "Opened database with connection id" << connection_id;
if (injected_database_name_.isNull()) {
db.setDatabaseName(directory_ + u'/' + QLatin1String(kDatabaseFilename));
@@ -210,7 +210,7 @@ void Database::Close() {
QSqlDatabase db = QSqlDatabase::database(connection_id);
if (db.isOpen()) {
db.close();
//qLog(Debug) << "Closed database with connection id" << connection_id;
// qLog(Debug) << "Closed database with connection id" << connection_id;
}
}
QSqlDatabase::removeDatabase(connection_id);
@@ -503,7 +503,9 @@ bool Database::IntegrityCheck(const QSqlDatabase &db) {
break;
}
else {
if (!error_reported) { Q_EMIT Error(tr("Database corruption detected.")); }
if (!error_reported) {
Q_EMIT Error(tr("Database corruption detected."));
}
Q_EMIT Error(u"Database: "_s + message);
error_reported = true;
}
@@ -594,8 +596,7 @@ void Database::BackupFile(const QString &filename) {
ret = sqlite3_backup_step(backup, 16);
const int page_count = sqlite3_backup_pagecount(backup);
task_manager_->SetTaskProgress(task_id, static_cast<quint64>(page_count - sqlite3_backup_remaining(backup)), static_cast<quint64>(page_count));
}
while (ret == SQLITE_OK);
} while (ret == SQLITE_OK);
if (ret != SQLITE_DONE) {
qLog(Error) << "Database backup failed";

View File

@@ -128,7 +128,6 @@ class Database : public QObject {
int startup_schema_version_;
QThread *original_thread_;
};
#endif // DATABASE_H

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2018-2023, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2018-2023, 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 "enginemetadata.h"
#include "core/song.h"

View File

@@ -1,21 +1,21 @@
/*
* Strawberry Music Player
* Copyright 2018-2023, 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/>.
*
*/
* Strawberry Music Player
* Copyright 2018-2023, 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 ENGINEMETADATA_H
#define ENGINEMETADATA_H

View File

@@ -93,7 +93,7 @@ QNetworkReply *HttpBaseRequest::CreateGetRequest(const QUrl &url, const QUrlQuer
QObject::connect(reply, &QNetworkReply::sslErrors, this, &HttpBaseRequest::HandleSSLErrors);
replies_ << reply;
//qLog(Debug) << service_name() << "Sending get request" << request_url;
// qLog(Debug) << service_name() << "Sending get request" << request_url;
return reply;
@@ -111,7 +111,7 @@ QNetworkReply *HttpBaseRequest::CreatePostRequest(const QUrl &url, const QByteAr
QObject::connect(reply, &QNetworkReply::sslErrors, this, &HttpBaseRequest::HandleSSLErrors);
replies_ << reply;
//qLog(Debug) << service_name() << "Sending post request" << url << data;
// qLog(Debug) << service_name() << "Sending post request" << url << data;
return reply;

View File

@@ -27,6 +27,7 @@ class IconLoader {
public:
static void Init();
static QIcon Load(const QString &name, const bool system_icon = true, const int fixed_size = 0, const int min_size = 0, const int max_size = 0);
private:
explicit IconLoader() {}
static bool system_icons_;

View File

@@ -155,11 +155,7 @@ void LocalRedirectServer::WriteTemplate() const {
QBuffer image_buffer;
if (image_buffer.open(QIODevice::ReadWrite)) {
QApplication::style()
->standardIcon(QStyle::SP_DialogOkButton)
.pixmap(16)
.toImage()
.save(&image_buffer, "PNG");
QApplication::style()->standardIcon(QStyle::SP_DialogOkButton).pixmap(16).toImage().save(&image_buffer, "PNG");
page_data.replace("@IMAGE_DATA@"_L1, QString::fromUtf8(image_buffer.data().toBase64()));
image_buffer.close();
}

View File

@@ -13,7 +13,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
*/
#include <QtGlobal>
@@ -257,7 +257,7 @@ static QString ParsePrettyFunction(const char *pretty_function) {
}
template <class T>
template<class T>
static T CreateLogger(Level level, const QString &class_name, int line, const char *category) {
// Map the level to a string

View File

@@ -13,7 +13,7 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
*/
#ifndef LOGGING_H
#define LOGGING_H
@@ -67,10 +67,10 @@ enum Level {
Level_Debug,
};
void Init();
void SetLevels(const QString &levels);
void Init();
void SetLevels(const QString &levels);
void DumpStackTrace();
void DumpStackTrace();
QDebug CreateLoggerFatal(const int line, const char *pretty_function, const char *category);
QDebug CreateLoggerError(const int line, const char *pretty_function, const char *category);

View File

@@ -2,7 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2013-2025, 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
@@ -220,7 +220,7 @@
#endif
#ifdef HAVE_SPARKLE
#include "core/sparkleupdater.h"
# include "core/sparkleupdater.h"
#endif
#ifdef HAVE_QTSPARKLE
@@ -228,7 +228,7 @@
#endif // HAVE_QTSPARKLE
#ifdef HAVE_DISCORD_RPC
#include "discord/richpresence.h"
# include "discord/richpresence.h"
#endif
using std::make_unique;
@@ -272,14 +272,14 @@ constexpr char QTSPARKLE_URL[] = "https://www.strawberrymusicplayer.org/sparkle-
# endif
# else
# error "Unsupported OS for QtSparkle"
# endif // OS
# error "Unsupported OS for QtSparkle"
# endif // OS
} // namespace
#endif // HAVE_QTSPARKLE
MainWindow::MainWindow(Application *app,
SharedPtr<SystemTrayIcon> tray_icon, OSDBase *osd,
SharedPtr<SystemTrayIcon> systemtrayicon, OSDBase *osd,
#ifdef HAVE_DISCORD_RPC
discord::RichPresence *discord_rich_presence,
#endif
@@ -291,7 +291,7 @@ MainWindow::MainWindow(Application *app,
thumbbar_(new Windows7ThumbBar(this)),
#endif
app_(app),
tray_icon_(tray_icon),
systemtrayicon_(systemtrayicon),
osd_(osd),
#ifdef HAVE_DISCORD_RPC
discord_rich_presence_(discord_rich_presence),
@@ -408,6 +408,8 @@ MainWindow::MainWindow(Application *app,
setWindowIcon(IconLoader::Load(u"strawberry"_s));
}
systemtrayicon_->SetDevicePixelRatioF(devicePixelRatioF());
QObject::connect(&*app->database(), &Database::Error, this, &MainWindow::ShowErrorDialog);
album_cover_choice_controller_->Init(app->network(), app->tagreader_client(), app->collection()->backend(), app->albumcover_loader(), app->current_albumcover_loader(), app->cover_providers(), app->streaming_services());
@@ -846,14 +848,14 @@ MainWindow::MainWindow(Application *app,
mac::SetApplicationHandler(this);
#endif
// Tray icon
tray_icon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause, ui_->action_stop, ui_->action_stop_after_this_track, ui_->action_next_track, ui_->action_mute, ui_->action_love, ui_->action_quit);
QObject::connect(&*tray_icon_, &SystemTrayIcon::PlayPause, &*app_->player(), &Player::PlayPauseHelper);
QObject::connect(&*tray_icon_, &SystemTrayIcon::SeekForward, &*app_->player(), &Player::SeekForward);
QObject::connect(&*tray_icon_, &SystemTrayIcon::SeekBackward, &*app_->player(), &Player::SeekBackward);
QObject::connect(&*tray_icon_, &SystemTrayIcon::NextTrack, &*app_->player(), &Player::Next);
QObject::connect(&*tray_icon_, &SystemTrayIcon::PreviousTrack, &*app_->player(), &Player::Previous);
QObject::connect(&*tray_icon_, &SystemTrayIcon::ShowHide, this, &MainWindow::ToggleShowHide);
QObject::connect(&*tray_icon_, &SystemTrayIcon::ChangeVolume, this, &MainWindow::VolumeWheelEvent);
systemtrayicon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause, ui_->action_stop, ui_->action_stop_after_this_track, ui_->action_next_track, ui_->action_mute, ui_->action_love, ui_->action_quit);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::PlayPause, &*app_->player(), &Player::PlayPauseHelper);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::SeekForward, &*app_->player(), &Player::SeekForward);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::SeekBackward, &*app_->player(), &Player::SeekBackward);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::NextTrack, &*app_->player(), &Player::Next);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::PreviousTrack, &*app_->player(), &Player::Previous);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::ShowHide, this, &MainWindow::ToggleShowHide);
QObject::connect(&*systemtrayicon_, &SystemTrayIcon::ChangeVolume, this, &MainWindow::VolumeWheelEvent);
// Windows 7 thumbbar buttons
#ifdef Q_OS_WIN32
@@ -1031,7 +1033,7 @@ MainWindow::MainWindow(Application *app,
show();
break;
case BehaviourSettings::StartupBehaviour::Hide:
if (tray_icon_->IsSystemTrayAvailable() && tray_icon_->isVisible()) {
if (systemtrayicon_->IsSystemTrayAvailable() && systemtrayicon_->isVisible()) {
break;
}
[[fallthrough]];
@@ -1044,7 +1046,7 @@ MainWindow::MainWindow(Application *app,
was_minimized_ = settings_.value(MainWindowSettings::kMinimized, false).toBool();
if (was_minimized_) setWindowState(windowState() | Qt::WindowMinimized);
if (!tray_icon_->IsSystemTrayAvailable() || !tray_icon_->isVisible() || !settings_.value(MainWindowSettings::kHidden, false).toBool()) {
if (!systemtrayicon_->IsSystemTrayAvailable() || !systemtrayicon_->isVisible() || !settings_.value(MainWindowSettings::kHidden, false).toBool()) {
show();
}
break;
@@ -1156,13 +1158,13 @@ void MainWindow::ReloadSettings() {
#ifdef Q_OS_MACOS
constexpr bool keeprunning_available = true;
#else
const bool systemtray_available = tray_icon_->IsSystemTrayAvailable();
const bool systemtray_available = systemtrayicon_->IsSystemTrayAvailable();
s.beginGroup(BehaviourSettings::kSettingsGroup);
const bool showtrayicon = s.value(BehaviourSettings::kShowTrayIcon, systemtray_available).toBool();
s.endGroup();
const bool keeprunning_available = systemtray_available && showtrayicon;
if (systemtray_available) {
tray_icon_->setVisible(showtrayicon);
systemtrayicon_->setVisible(showtrayicon);
}
if ((!showtrayicon || !systemtray_available) && !isVisible()) {
show();
@@ -1187,7 +1189,7 @@ void MainWindow::ReloadSettings() {
int iconsize = s.value(AppearanceSettings::kIconSizePlayControlButtons, 32).toInt();
s.endGroup();
tray_icon_->SetTrayiconProgress(trayicon_progress);
systemtrayicon_->SetTrayiconProgress(trayicon_progress);
#ifdef HAVE_DBUS
if (taskbar_progress_ && !taskbar_progress) {
@@ -1209,11 +1211,11 @@ void MainWindow::ReloadSettings() {
ui_->volume->SetEnabled(volume_control);
if (volume_control) {
if (!ui_->action_mute->isVisible()) ui_->action_mute->setVisible(true);
if (!tray_icon_->MuteEnabled()) tray_icon_->SetMuteEnabled(true);
if (!systemtrayicon_->MuteEnabled()) systemtrayicon_->SetMuteEnabled(true);
}
else {
if (ui_->action_mute->isVisible()) ui_->action_mute->setVisible(false);
if (tray_icon_->MuteEnabled()) tray_icon_->SetMuteEnabled(false);
if (systemtrayicon_->MuteEnabled()) systemtrayicon_->SetMuteEnabled(false);
}
}
@@ -1365,8 +1367,8 @@ void MainWindow::Exit() {
if (app_->player()->GetState() == EngineBase::State::Playing) {
app_->player()->Stop();
hide();
if (tray_icon_->IsSystemTrayAvailable()) {
tray_icon_->setVisible(false);
if (systemtrayicon_->IsSystemTrayAvailable()) {
systemtrayicon_->setVisible(false);
}
return; // Don't quit the application now: wait for the fadeout finished signal
}
@@ -1423,7 +1425,7 @@ void MainWindow::MediaStopped() {
ui_->action_love->setEnabled(false);
ui_->button_love->setEnabled(false);
tray_icon_->LoveStateChanged(false);
systemtrayicon_->LoveStateChanged(false);
if (track_position_timer_->isActive()) {
track_position_timer_->stop();
@@ -1432,8 +1434,8 @@ void MainWindow::MediaStopped() {
track_slider_timer_->stop();
}
ui_->track_slider->SetStopped();
tray_icon_->SetProgress(0);
tray_icon_->SetStopped();
systemtrayicon_->SetProgress(0);
systemtrayicon_->SetStopped();
#ifdef HAVE_DBUS
if (taskbar_progress_) {
@@ -1465,7 +1467,7 @@ void MainWindow::MediaPaused() {
track_slider_timer_->start();
}
tray_icon_->SetPaused();
systemtrayicon_->SetPaused();
}
@@ -1486,7 +1488,7 @@ void MainWindow::MediaPlaying() {
}
ui_->action_play_pause->setEnabled(enable_play_pause);
ui_->track_slider->SetCanSeek(can_seek);
tray_icon_->SetPlaying(enable_play_pause);
systemtrayicon_->SetPlaying(enable_play_pause);
if (!track_position_timer_->isActive()) {
track_position_timer_->start();
@@ -1507,14 +1509,14 @@ void MainWindow::SendNowPlaying() {
app_->scrobbler()->UpdateNowPlaying(playlist->current_item()->EffectiveMetadata());
ui_->action_love->setEnabled(true);
ui_->button_love->setEnabled(true);
tray_icon_->LoveStateChanged(true);
systemtrayicon_->LoveStateChanged(true);
}
}
void MainWindow::VolumeChanged(const uint volume) {
ui_->action_mute->setChecked(volume == 0);
tray_icon_->MuteButtonStateChanged(volume == 0);
systemtrayicon_->MuteButtonStateChanged(volume == 0);
}
void MainWindow::SongChanged(const Song &song) {
@@ -1524,7 +1526,7 @@ void MainWindow::SongChanged(const Song &song) {
song_playing_ = song;
song_ = song;
setWindowTitle(song.PrettyTitleWithArtist());
tray_icon_->SetProgress(0);
systemtrayicon_->SetProgress(0);
#ifdef HAVE_DBUS
if (taskbar_progress_) {
@@ -1682,17 +1684,6 @@ void MainWindow::StopAfterCurrent() {
Q_EMIT StopAfterToggled(app_->playlist_manager()->active()->stop_after_current());
}
void MainWindow::showEvent(QShowEvent *e) {
if (error_dialog_ && error_dialog_->isVisible() && error_dialog_->isMinimized()) {
error_dialog_->raise();
error_dialog_->activateWindow();
}
QMainWindow::showEvent(e);
}
void MainWindow::hideEvent(QHideEvent *e) {
// Some window managers don't remember maximized state between
@@ -1707,7 +1698,7 @@ void MainWindow::hideEvent(QHideEvent *e) {
void MainWindow::closeEvent(QCloseEvent *e) {
if (!exit_ && (!tray_icon_->IsSystemTrayAvailable() || !tray_icon_->isVisible() || !keep_running_)) {
if (!exit_ && (!systemtrayicon_->IsSystemTrayAvailable() || !systemtrayicon_->isVisible() || !keep_running_)) {
Exit();
}
@@ -1715,10 +1706,20 @@ void MainWindow::closeEvent(QCloseEvent *e) {
}
void MainWindow::changeEvent(QEvent *e) {
if (e->type() == QEvent::Show || e->type() == QEvent::WindowStateChange || e->type() == QEvent::WindowActivate) {
CheckShowErrorDialog();
}
QMainWindow::changeEvent(e);
}
void MainWindow::SetHiddenInTray(const bool hidden) {
if (hidden && isVisible()) {
if (tray_icon_->IsSystemTrayAvailable() && tray_icon_->isVisible() && keep_running_) {
if (systemtrayicon_->IsSystemTrayAvailable() && systemtrayicon_->isVisible() && keep_running_) {
close();
}
else {
@@ -1735,6 +1736,7 @@ void MainWindow::SetHiddenInTray(const bool hidden) {
else {
show();
}
CheckShowErrorDialog();
}
}
@@ -1747,7 +1749,7 @@ void MainWindow::Seeked(const qint64 microseconds) {
const qint64 position = microseconds / kUsecPerSec;
const qint64 length = app_->player()->GetCurrentItem()->EffectiveMetadata().length_nanosec() / kNsecPerSec;
tray_icon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0));
systemtrayicon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0));
#ifdef HAVE_DBUS
if (taskbar_progress_) {
@@ -1767,7 +1769,7 @@ void MainWindow::UpdateTrackPosition() {
const int position = std::floor(static_cast<float>(app_->player()->engine()->position_nanosec()) / static_cast<float>(kNsecPerSec) + 0.5);
// Update the tray icon every 10 seconds
if (position % 10 == 0) tray_icon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0));
if (position % 10 == 0) systemtrayicon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0));
#ifdef HAVE_DBUS
if (taskbar_progress_) {
@@ -2988,6 +2990,14 @@ void MainWindow::ShowErrorDialog(const QString &message) {
error_dialog_->ShowMessage(message);
}
void MainWindow::CheckShowErrorDialog() {
if (isVisible() && !isMinimized() && error_dialog_ && error_dialog_->isVisible() && !error_dialog_->isActiveWindow()) {
error_dialog_->ShowDialog();
}
}
void MainWindow::CheckFullRescanRevisions() {
int from = app_->database()->startup_schema_version();
@@ -3259,7 +3269,7 @@ void MainWindow::LoveButtonVisibilityChanged(const bool value) {
else
ui_->widget_love->hide();
tray_icon_->LoveVisibilityChanged(value);
systemtrayicon_->LoveVisibilityChanged(value);
}
@@ -3282,7 +3292,7 @@ void MainWindow::Love() {
app_->scrobbler()->Love();
ui_->button_love->setEnabled(false);
ui_->action_love->setEnabled(false);
tray_icon_->LoveStateChanged(false);
systemtrayicon_->LoveStateChanged(false);
}

View File

@@ -2,7 +2,7 @@
* Strawberry Music Player
* This file was part of Clementine.
* Copyright 2010, David Sansome <me@davidsansome.com>
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
* Copyright 2013-2025, 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
@@ -111,7 +111,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
public:
explicit MainWindow(Application *app,
SharedPtr<SystemTrayIcon> tray_icon,
SharedPtr<SystemTrayIcon> systemtrayicon,
OSDBase *osd,
#ifdef HAVE_DISCORD_RPC
discord::RichPresence *discord_rich_presence,
@@ -124,9 +124,9 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void CommandlineOptionsReceived(const CommandlineOptions &options);
protected:
void showEvent(QShowEvent *e) override;
void hideEvent(QHideEvent *e) override;
void closeEvent(QCloseEvent *e) override;
void changeEvent(QEvent *e) override;
void keyPressEvent(QKeyEvent *e) override;
#ifdef Q_OS_WIN32
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
@@ -236,6 +236,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void ShowAboutDialog();
void ShowErrorDialog(const QString &message);
void CheckShowErrorDialog();
void ShowTranscodeDialog();
SettingsDialog *CreateSettingsDialog();
EditTagDialog *CreateEditTagDialog();
@@ -284,7 +285,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void Raise();
private:
void SaveSettings();
static void ApplyAddBehaviour(const BehaviourSettings::AddBehaviour b, MimeData *mimedata);
@@ -310,11 +310,12 @@ class MainWindow : public QMainWindow, public PlatformInterface {
#endif
Application *app_;
SharedPtr<SystemTrayIcon> tray_icon_;
SharedPtr<SystemTrayIcon> systemtrayicon_;
OSDBase *osd_;
#ifdef HAVE_DISCORD_RPC
discord::RichPresence *discord_rich_presence_;
#endif
Lazy<ErrorDialog> error_dialog_;
Lazy<About> about_dialog_;
Lazy<Console> console_;
Lazy<EditTagDialog> edit_tag_dialog_;
@@ -329,7 +330,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
PlaylistListContainer *playlist_list_;
QueueView *queue_view_;
Lazy<ErrorDialog> error_dialog_;
Lazy<SettingsDialog> settings_dialog_;
Lazy<AlbumCoverManager> cover_manager_;
SharedPtr<Equalizer> equalizer_;
@@ -414,7 +414,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
bool playlists_loaded_;
bool delete_files_;
std::optional<CommandlineOptions> options_;
};
#endif // MAINWINDOW_H

View File

@@ -22,7 +22,7 @@
using namespace Qt::Literals::StringLiterals;
MemoryDatabase::MemoryDatabase(SharedPtr<TaskManager> task_manager, QObject *parent)
: Database(task_manager, parent, u":memory:"_s) {}
: Database(task_manager, parent, u":memory:"_s) {}
MemoryDatabase::~MemoryDatabase() {
// Make sure Qt doesn't reuse the same database

View File

@@ -26,13 +26,13 @@
#include "mimedata.h"
MimeData::MimeData(const bool clear, const bool play_now, const bool enqueue, const bool enqueue_next_now, const bool open_in_new_playlist, QObject *parent)
: override_user_settings_(false),
clear_first_(clear),
play_now_(play_now),
enqueue_now_(enqueue),
enqueue_next_now_(enqueue_next_now),
open_in_new_playlist_(open_in_new_playlist),
from_doubleclick_(false) {
: override_user_settings_(false),
clear_first_(clear),
play_now_(play_now),
enqueue_now_(enqueue),
enqueue_next_now_(enqueue_next_now),
open_in_new_playlist_(open_in_new_playlist),
from_doubleclick_(false) {
Q_UNUSED(parent);

View File

@@ -57,7 +57,7 @@ class MusicStorage {
Transcode_Unsupported = 3,
};
using ProgressFunction = std::function<void(float progress)>;
using ProgressFunction = std::function<void (float progress)>;
struct CopyJob {
CopyJob() : overwrite_(false), remove_original_(false), albumcover_(false) {}

View File

@@ -50,7 +50,7 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR
user_agent = network_request.header(QNetworkRequest::UserAgentHeader).toByteArray();
}
else {
user_agent = QStringLiteral("%1 %2").arg(QCoreApplication::applicationName(), QCoreApplication::applicationVersion()).toUtf8();
user_agent = "Strawberry Music Player";
}
QNetworkRequest new_network_request(network_request);

View File

@@ -121,8 +121,8 @@ class Player : public PlayerInterface {
void PlayPlaylistInternal(const EngineBase::TrackChangeFlags, const Playlist::AutoScroll autoscroll, const QString &playlist_name);
void FatalError();
void ValidSongRequested(const QUrl&);
void InvalidSongRequested(const QUrl&);
void ValidSongRequested(const QUrl &url);
void InvalidSongRequested(const QUrl &url);
void HandleLoadResult(const UrlHandler::LoadResult &result);

View File

@@ -40,7 +40,6 @@ class QtFSListener : public FileSystemWatcherInterface {
private:
QFileSystemWatcher watcher_;
};
#endif // QTFSLISTENER_H

View File

@@ -9,7 +9,7 @@
#if defined(__OBJC__)
@class NSAutoreleasePool;
#else // __OBJC__
#else // __OBJC__
class NSAutoreleasePool;
#endif // __OBJC__
@@ -28,8 +28,9 @@ class ScopedNSAutoreleasePool {
// Only use then when you're certain the items currently in the pool are
// no longer needed.
void Recycle();
private:
NSAutoreleasePool* autorelease_pool_;
NSAutoreleasePool *autorelease_pool_;
private:
Q_DISABLE_COPY(ScopedNSAutoreleasePool);

View File

@@ -70,7 +70,7 @@ QModelIndex SimpleTreeModel<T>::ItemToIndex(T *item) const {
return createIndex(item->row, 0, item);
}
template <typename T>
template<typename T>
int SimpleTreeModel<T>::columnCount(const QModelIndex&) const {
return 1;
}

View File

@@ -243,6 +243,7 @@ const QStringList Song::kAcceptedExtensions = QStringList() << u"wav"_s
<< u"tta"_s
<< u"dsf"_s
<< u"dsd"_s
<< u"webm"_s
<< u"ac3"_s
<< u"dts"_s
<< u"spc"_s
@@ -719,17 +720,17 @@ bool Song::write_tags_supported() const {
bool Song::additional_tags_supported() const {
return d->filetype_ == FileType::FLAC ||
d->filetype_ == FileType::WavPack ||
d->filetype_ == FileType::OggFlac ||
d->filetype_ == FileType::OggVorbis ||
d->filetype_ == FileType::OggOpus ||
d->filetype_ == FileType::OggSpeex ||
d->filetype_ == FileType::MPEG ||
d->filetype_ == FileType::MP4 ||
d->filetype_ == FileType::MPC ||
d->filetype_ == FileType::APE ||
d->filetype_ == FileType::WAV ||
d->filetype_ == FileType::AIFF;
d->filetype_ == FileType::WavPack ||
d->filetype_ == FileType::OggFlac ||
d->filetype_ == FileType::OggVorbis ||
d->filetype_ == FileType::OggOpus ||
d->filetype_ == FileType::OggSpeex ||
d->filetype_ == FileType::MPEG ||
d->filetype_ == FileType::MP4 ||
d->filetype_ == FileType::MPC ||
d->filetype_ == FileType::APE ||
d->filetype_ == FileType::WAV ||
d->filetype_ == FileType::AIFF;
}
@@ -744,16 +745,16 @@ bool Song::composer_supported() const {
bool Song::performer_supported() const {
return d->filetype_ == FileType::FLAC ||
d->filetype_ == FileType::WavPack ||
d->filetype_ == FileType::OggFlac ||
d->filetype_ == FileType::OggVorbis ||
d->filetype_ == FileType::OggOpus ||
d->filetype_ == FileType::OggSpeex ||
d->filetype_ == FileType::MPEG ||
d->filetype_ == FileType::MPC ||
d->filetype_ == FileType::APE ||
d->filetype_ == FileType::WAV ||
d->filetype_ == FileType::AIFF;
d->filetype_ == FileType::WavPack ||
d->filetype_ == FileType::OggFlac ||
d->filetype_ == FileType::OggVorbis ||
d->filetype_ == FileType::OggOpus ||
d->filetype_ == FileType::OggSpeex ||
d->filetype_ == FileType::MPEG ||
d->filetype_ == FileType::MPC ||
d->filetype_ == FileType::APE ||
d->filetype_ == FileType::WAV ||
d->filetype_ == FileType::AIFF;
}
@@ -772,18 +773,18 @@ bool Song::compilation_supported() const {
bool Song::rating_supported() const {
return d->filetype_ == FileType::FLAC ||
d->filetype_ == FileType::WavPack ||
d->filetype_ == FileType::OggFlac ||
d->filetype_ == FileType::OggVorbis ||
d->filetype_ == FileType::OggOpus ||
d->filetype_ == FileType::OggSpeex ||
d->filetype_ == FileType::MPEG ||
d->filetype_ == FileType::MP4 ||
d->filetype_ == FileType::ASF ||
d->filetype_ == FileType::MPC ||
d->filetype_ == FileType::APE ||
d->filetype_ == FileType::WAV ||
d->filetype_ == FileType::AIFF;
d->filetype_ == FileType::WavPack ||
d->filetype_ == FileType::OggFlac ||
d->filetype_ == FileType::OggVorbis ||
d->filetype_ == FileType::OggOpus ||
d->filetype_ == FileType::OggSpeex ||
d->filetype_ == FileType::MPEG ||
d->filetype_ == FileType::MP4 ||
d->filetype_ == FileType::ASF ||
d->filetype_ == FileType::MPC ||
d->filetype_ == FileType::APE ||
d->filetype_ == FileType::WAV ||
d->filetype_ == FileType::AIFF;
}
@@ -823,12 +824,12 @@ bool Song::titlesort_supported() const {
bool Song::save_embedded_cover_supported(const FileType filetype) {
return filetype == FileType::FLAC ||
filetype == FileType::OggVorbis ||
filetype == FileType::OggOpus ||
filetype == FileType::MPEG ||
filetype == FileType::MP4 ||
filetype == FileType::WAV ||
filetype == FileType::AIFF;
filetype == FileType::OggVorbis ||
filetype == FileType::OggOpus ||
filetype == FileType::MPEG ||
filetype == FileType::MP4 ||
filetype == FileType::WAV ||
filetype == FileType::AIFF;
}
@@ -1443,7 +1444,7 @@ Song::FileType Song::FiletypeByExtension(const QString &ext) {
if (ext.compare("ape"_L1, Qt::CaseInsensitive) == 0) return FileType::APE;
if (ext.compare("mod"_L1, Qt::CaseInsensitive) == 0 ||
ext.compare("module"_L1, Qt::CaseInsensitive) == 0 ||
ext.compare("nst"_L1, Qt::CaseInsensitive) == 0||
ext.compare("nst"_L1, Qt::CaseInsensitive) == 0 ||
ext.compare("wow"_L1, Qt::CaseInsensitive) == 0) return FileType::MOD;
if (ext.compare("s3m"_L1, Qt::CaseInsensitive) == 0) return FileType::S3M;
if (ext.compare("xm"_L1, Qt::CaseInsensitive) == 0) return FileType::XM;
@@ -1688,7 +1689,7 @@ void Song::InitFromItdb(Itdb_Track *track, const QString &prefix) {
d->bitrate_ = track->bitrate;
d->samplerate_ = track->samplerate;
d->bitdepth_ = -1; //track->bitdepth;
d->bitdepth_ = -1; // track->bitdepth;
d->source_ = Source::Device;
QString filename = QString::fromLocal8Bit(track->ipod_path);
@@ -2149,4 +2150,3 @@ QString Song::GetNameForNewPlaylist(const SongList &songs) {
return result;
}

View File

@@ -179,8 +179,10 @@ SongLoader::Result SongLoader::LoadAudioCD() {
#ifdef HAVE_AUDIOCD
CDDASongLoader *cdda_song_loader = new CDDASongLoader(QUrl(), this);
QObject::connect(cdda_song_loader, &CDDASongLoader::SongsDurationLoaded, this, &SongLoader::AudioCDTracksLoadFinishedSlot);
QObject::connect(cdda_song_loader, &CDDASongLoader::SongsMetadataLoaded, this, &SongLoader::AudioCDTracksTagsLoaded);
QObject::connect(cdda_song_loader, &CDDASongLoader::LoadError, this, &SongLoader::AudioCDTracksLoadErrorSlot);
QObject::connect(cdda_song_loader, &CDDASongLoader::SongsLoaded, this, &SongLoader::AudioCDTracksLoadedSlot);
QObject::connect(cdda_song_loader, &CDDASongLoader::SongsUpdated, this, &SongLoader::AudioCDTracksUpdatedSlot);
QObject::connect(cdda_song_loader, &CDDASongLoader::LoadingFinished, this, &SongLoader::AudioCDLoadingFinishedSlot);
cdda_song_loader->LoadSongs();
return Result::Success;
#else
@@ -192,23 +194,38 @@ SongLoader::Result SongLoader::LoadAudioCD() {
#ifdef HAVE_AUDIOCD
void SongLoader::AudioCDTracksLoadFinishedSlot(const SongList &songs, const QString &error) {
void SongLoader::AudioCDTracksLoadErrorSlot(const QString &error) {
songs_ = songs;
errors_ << error;
Q_EMIT AudioCDTracksLoadFinished();
}
void SongLoader::AudioCDTracksTagsLoaded(const SongList &songs) {
void SongLoader::AudioCDTracksLoadedSlot(const SongList &songs) {
songs_ = songs;
Q_EMIT AudioCDTracksLoaded();
}
void SongLoader::AudioCDTracksUpdatedSlot(const SongList &songs) {
songs_ = songs;
Q_EMIT AudioCDTracksUpdated();
}
void SongLoader::AudioCDLoadingFinishedSlot() {
CDDASongLoader *cdda_song_loader = qobject_cast<CDDASongLoader*>(sender());
cdda_song_loader->deleteLater();
songs_ = songs;
Q_EMIT LoadAudioCDFinished(true);
Q_EMIT AudioCDLoadingFinished(true);
}
#endif
#endif // HAVE_AUDIOCD
SongLoader::Result SongLoader::LoadLocal(const QString &filename) {
@@ -650,9 +667,9 @@ void SongLoader::EndOfStreamReached() {
// Do the magic on the data we have already
MagicReady();
if (state_ == State::Finished) break;
// It looks like a playlist, so parse it
// It looks like a playlist, so parse it
[[fallthrough]];
[[fallthrough]];
case State::WaitingForData:
// It's a playlist and we've got all the data - finish and parse it
StopTypefindAsync(true);
@@ -767,4 +784,3 @@ void SongLoader::CleanupPipeline() {
state_ = State::Finished;
}

View File

@@ -90,17 +90,21 @@ class SongLoader : public QObject {
QStringList errors() { return errors_; }
Q_SIGNALS:
void AudioCDTracksLoadFinished();
void LoadAudioCDFinished(const bool success);
void AudioCDTracksLoaded();
void AudioCDTracksUpdated();
void AudioCDLoadingFinished(const bool success);
void LoadRemoteFinished();
private Q_SLOTS:
void ScheduleTimeout();
void Timeout();
void StopTypefind();
#ifdef HAVE_AUDIOCD
void AudioCDTracksLoadFinishedSlot(const SongList &songs, const QString &error);
void AudioCDTracksTagsLoaded(const SongList &songs);
void AudioCDTracksLoadErrorSlot(const QString &error);
void AudioCDTracksLoadedSlot(const SongList &songs);
void AudioCDTracksUpdatedSlot(const SongList &songs);
void AudioCDLoadingFinishedSlot();
#endif // HAVE_AUDIOCD
private:
@@ -167,7 +171,6 @@ class SongLoader : public QObject {
QStringList errors_;
bool success_;
};
#endif // SONGLOADER_H

View File

@@ -41,4 +41,3 @@ class SongMimeData : public MimeData {
};
#endif // SONGMIMEDATA_H

View File

@@ -383,30 +383,30 @@ void StyleHelper::drawCornerImage(const QImage &img, QPainter *painter, const QR
const qreal bottomDIP = bottom * imagePixelRatio;
const QSize size = img.size();
if (top > 0) { //top
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 (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
// 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));
}
//center
// 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
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
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 (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));
}
}

View File

@@ -32,6 +32,7 @@
#include <QFile>
#include <QString>
#include <QPalette>
#include <QColor>
#include <QEvent>
#include "includes/shared_ptr.h"
@@ -79,13 +80,13 @@ void StyleSheetLoader::UpdateStyleSheet(QWidget *widget, SharedPtr<StyleSheetDat
// Replace %palette-role with actual colours
QPalette p(widget->palette());
{
QColor color_altbase = p.color(QPalette::AlternateBase);
QColor color_altbase = p.color(QPalette::AlternateBase);
#ifdef Q_OS_MACOS
color_altbase.setAlpha(color_altbase.lightness() > 180 ? 130 : 16);
color_altbase.setAlpha(color_altbase.alpha() >= 180 ? (color_altbase.lightness() > 180 ? 130 : 16) : color_altbase.alpha());
#else
color_altbase.setAlpha(color_altbase.alpha() >= 180 ? 116 : color_altbase.alpha());
#endif
stylesheet.replace("%palette-alternate-base"_L1, QStringLiteral("rgba(%1,%2,%3,%4)").arg(color_altbase.red()).arg(color_altbase.green()).arg(color_altbase.blue()).arg(color_altbase.alpha()));
}
stylesheet.replace("%palette-alternate-base"_L1, QStringLiteral("rgba(%1,%2,%3,%4)").arg(color_altbase.red()).arg(color_altbase.green()).arg(color_altbase.blue()).arg(color_altbase.alpha()));
ReplaceColor(&stylesheet, u"Window"_s, p, QPalette::Window);
ReplaceColor(&stylesheet, u"Background"_s, p, QPalette::Window);

View File

@@ -36,4 +36,4 @@ class TemporaryFile {
QString filename_;
};
#endif // TEMPORARYFILE_H
#endif // TEMPORARYFILE_H

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