Compare commits
80 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ac31d79294 | ||
|
|
4ffebd77b1 | ||
|
|
6682efae2f | ||
|
|
480161c6b7 | ||
|
|
a8ba420d72 | ||
|
|
fc0ec91652 | ||
|
|
0701b97324 | ||
|
|
3867932e1e | ||
|
|
e2907f6051 | ||
|
|
0827ec7f16 | ||
|
|
24d2adf363 | ||
|
|
592729d00b | ||
|
|
c4a564bb56 | ||
|
|
812a02a3a1 | ||
|
|
944936914b | ||
|
|
e7c901d4f3 | ||
|
|
8e996119af | ||
|
|
4348a654ca | ||
|
|
f0be1c782a | ||
|
|
e9898d08bc | ||
|
|
1ad13cd3b0 | ||
|
|
5c640e0e36 | ||
|
|
059def8d0c | ||
|
|
cf15a1f423 | ||
|
|
5d35b0eedd | ||
|
|
5fcb71d08f | ||
|
|
15c2237d4a | ||
|
|
93af866185 | ||
|
|
109ff90401 | ||
|
|
d4b06289c3 | ||
|
|
4351c555a0 | ||
|
|
ce4db40983 | ||
|
|
d37fb7410c | ||
|
|
f1cdd71494 | ||
|
|
000ba997fb | ||
|
|
579efffd14 | ||
|
|
3a098c8a0c | ||
|
|
5bce0ae87f | ||
|
|
afe6967c46 | ||
|
|
e91bab6d42 | ||
|
|
5a64247761 | ||
|
|
9ed89afdb2 | ||
|
|
0ac338026c | ||
|
|
4e5f84a7b7 | ||
|
|
320a3c6815 | ||
|
|
72dd1d783a | ||
|
|
d2205cfe81 | ||
|
|
5830f247f6 | ||
|
|
8b4c57d933 | ||
|
|
67cec09176 | ||
|
|
2df658e1f3 | ||
|
|
f3bc9b151c | ||
|
|
b06b59d0c5 | ||
|
|
99d75ade06 | ||
|
|
3f63246068 | ||
|
|
b205a5f964 | ||
|
|
aeaef12dd4 | ||
|
|
02d76f17f7 | ||
|
|
e4e12c6fa6 | ||
|
|
270ae6085b | ||
|
|
7065a405a5 | ||
|
|
d8c72c3dd9 | ||
|
|
b65502e167 | ||
|
|
132f8df853 | ||
|
|
12e3cffe63 | ||
|
|
56a637682d | ||
|
|
d9b105f89e | ||
|
|
bd6b45e43f | ||
|
|
539172fb70 | ||
|
|
ebd92b3a7f | ||
|
|
b00ae5b210 | ||
|
|
c8e3cf981b | ||
|
|
038f69779f | ||
|
|
a4de7559ac | ||
|
|
0537b072fe | ||
|
|
2657c9f96a | ||
|
|
7e178b1f1a | ||
|
|
dd8513d02c | ||
|
|
5f0175094b | ||
|
|
b4c5b9e1e1 |
@@ -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: ''
|
||||
|
||||
70
.github/workflows/build.yml
vendored
70
.github/workflows/build.yml
vendored
@@ -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
|
||||
@@ -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: |
|
||||
@@ -511,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
|
||||
@@ -528,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: |
|
||||
@@ -607,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
|
||||
@@ -624,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: |
|
||||
@@ -699,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
|
||||
@@ -735,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.4
|
||||
uses: vmactions/freebsd-vm@v1.3.0
|
||||
with:
|
||||
usesh: true
|
||||
mem: 4096
|
||||
@@ -760,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.2.1
|
||||
uses: vmactions/openbsd-vm@v1.2.5
|
||||
with:
|
||||
usesh: true
|
||||
mem: 4096
|
||||
@@ -787,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 }}
|
||||
@@ -826,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
|
||||
@@ -890,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'
|
||||
@@ -977,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
|
||||
@@ -1080,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
|
||||
@@ -1310,7 +1310,7 @@ jobs:
|
||||
- name: Set SDK version
|
||||
if: matrix.arch != 'arm64'
|
||||
shell: bash
|
||||
run: echo "sdk_version=10.0.19041.0" >> $GITHUB_ENV
|
||||
run: echo "sdk_version=10.0.22621.0" >> $GITHUB_ENV
|
||||
|
||||
- name: Set SDK version
|
||||
if: matrix.arch == 'arm64'
|
||||
@@ -1321,10 +1321,6 @@ jobs:
|
||||
shell: cmd
|
||||
run: choco install --no-progress rsync
|
||||
|
||||
- name: Set SSH command
|
||||
shell: bash
|
||||
run: echo "ssh_command=/c/ProgramData/chocolatey/lib/rsync/tools/$(ls -1 /c/ProgramData/chocolatey/lib/rsync/tools/ | grep -v '\.zip$' | grep '^cwrsync' | tail -1)/bin/ssh.exe" >> $GITHUB_ENV
|
||||
|
||||
- name: Cleanup PATH
|
||||
uses: egor-tensin/cleanup-path@v4
|
||||
with:
|
||||
@@ -1409,7 +1405,7 @@ jobs:
|
||||
vsversion: 2022
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
submodules: recursive
|
||||
@@ -1623,7 +1619,7 @@ jobs:
|
||||
- name: rsync
|
||||
if: steps.set-upload-path.outputs.upload_path != ''
|
||||
shell: bash
|
||||
run: rsync -e "${{env.ssh_command}} -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/StrawberrySetup*.exe ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{steps.set-upload-path.outputs.upload_path}}/
|
||||
run: rsync -e "/c/ProgramData/chocolatey/lib/rsync/tools/bin/ssh.exe -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/StrawberrySetup*.exe ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{steps.set-upload-path.outputs.upload_path}}/
|
||||
|
||||
|
||||
upload:
|
||||
@@ -1642,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
|
||||
@@ -1690,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
|
||||
@@ -1698,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
1
.gitignore
vendored
@@ -1,6 +1,7 @@
|
||||
/build
|
||||
/bin
|
||||
/CMakeLists.txt.user
|
||||
/.qtcreator
|
||||
/.kdev4
|
||||
/strawberry.kdev4
|
||||
/.vscode
|
||||
|
||||
@@ -163,4 +163,3 @@ extern "C" void Discord_Register(const char *applicationId, const char *command)
|
||||
Discord_RegisterW(appId, wcommand);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -266,6 +266,8 @@ if(WIN32)
|
||||
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()
|
||||
@@ -699,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
|
||||
@@ -995,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
|
||||
|
||||
25
Changelog
25
Changelog
@@ -2,6 +2,31 @@ 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:
|
||||
|
||||
@@ -17,7 +17,9 @@ It’s written in **C++ using the Qt framework**, designed for **audiophiles and
|
||||
- **Forum:** https://forum.strawberrymusicplayer.org
|
||||
- **GitHub:** https://github.com/strawberrymusicplayer/strawberry
|
||||
- **Latest builds:** https://builds.strawberrymusicplayer.org
|
||||
- **openSUSE Build Service:** https://build.opensuse.org/package/show/home:jonaski:audio/strawberry
|
||||
- **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
|
||||
@@ -64,7 +66,7 @@ Supporting open-source developers helps ensure continued maintenance and improve
|
||||
- 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)
|
||||
- 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/)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(STRAWBERRY_VERSION_MAJOR 1)
|
||||
set(STRAWBERRY_VERSION_MINOR 2)
|
||||
set(STRAWBERRY_VERSION_PATCH 14)
|
||||
set(STRAWBERRY_VERSION_PATCH 16)
|
||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||
|
||||
set(INCLUDE_GIT_REVISION OFF)
|
||||
|
||||
2
debian/control
vendored
2
debian/control
vendored
@@ -60,7 +60,7 @@ 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
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
<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 and ListenBrainz</li>
|
||||
@@ -51,6 +51,8 @@
|
||||
</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"/>
|
||||
|
||||
4
dist/unix/strawberry.1
vendored
4
dist/unix/strawberry.1
vendored
@@ -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
|
||||
|
||||
3
dist/unix/strawberry.spec.in
vendored
3
dist/unix/strawberry.spec.in
vendored
@@ -93,8 +93,7 @@ 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 and ListenBrainz
|
||||
|
||||
38
dist/windows/strawberry.nsi.in
vendored
38
dist/windows/strawberry.nsi.in
vendored
@@ -477,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"
|
||||
@@ -494,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"
|
||||
@@ -505,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"
|
||||
@@ -512,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
|
||||
@@ -1019,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"
|
||||
@@ -1036,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"
|
||||
@@ -1047,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"
|
||||
@@ -1054,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"
|
||||
|
||||
@@ -90,4 +90,3 @@ class AnalyzerBase : public QWidget {
|
||||
};
|
||||
|
||||
#endif // ANALYZERBASE_H
|
||||
|
||||
|
||||
@@ -102,7 +102,6 @@ void AnalyzerContainer::AddAnalyzerType() {
|
||||
action->setCheckable(true);
|
||||
actions_ << action;
|
||||
QObject::connect(action, &QAction::triggered, [this, id]() { ChangeAnalyzer(id); });
|
||||
|
||||
}
|
||||
|
||||
#endif // ANALYZERCONTAINER_H
|
||||
|
||||
@@ -66,6 +66,7 @@ BlockAnalyzer::BlockAnalyzer(QWidget *parent)
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -55,7 +55,7 @@ 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:
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ class FHT {
|
||||
~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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
class CollectionFilterOptions {
|
||||
public:
|
||||
|
||||
explicit CollectionFilterOptions();
|
||||
|
||||
// Filter mode:
|
||||
|
||||
@@ -135,4 +135,3 @@ class CollectionFilterWidget : public QWidget {
|
||||
};
|
||||
|
||||
#endif // COLLECTIONFILTERWIDGET_H
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -705,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);
|
||||
@@ -719,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(' '));
|
||||
}
|
||||
@@ -1074,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:
|
||||
@@ -1162,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;
|
||||
|
||||
}
|
||||
@@ -1206,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;
|
||||
@@ -1246,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:
|
||||
@@ -1341,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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -58,4 +58,3 @@ class CollectionPlaylistItem : public PlaylistItem {
|
||||
};
|
||||
|
||||
#endif // COLLECTIONPLAYLISTITEM_H
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -70,6 +70,6 @@ enum class BackgroundImagePosition {
|
||||
BottomRight = 5
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace AppearanceSettings
|
||||
|
||||
#endif // APPEARANCESETTINGS_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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -43,6 +43,6 @@ constexpr char kSettingsSummaryFmt[] = "SummaryFmt";
|
||||
constexpr char kDefaultFontFamily[] = "Noto Sans";
|
||||
constexpr qreal kDefaultFontSizeHeadline = 11;
|
||||
|
||||
} // namespace
|
||||
} // namespace ContextSettings
|
||||
|
||||
#endif // CONTEXTSETTINGS_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
|
||||
|
||||
@@ -26,6 +26,6 @@ constexpr char kSettingsGroup[] = "GlobalShortcuts";
|
||||
constexpr char kUseKGlobalAccel[] = "use_kglobalaccel";
|
||||
constexpr char kUseX11[] = "use_x11";
|
||||
|
||||
} // namespace
|
||||
} // namespace GlobalShortcutsSettings
|
||||
|
||||
#endif // GLOBALSHORTCUTSSETTINGS_H
|
||||
|
||||
@@ -25,6 +25,6 @@ namespace LyricsSettings {
|
||||
constexpr char kSettingsGroup[] = "Lyrics";
|
||||
constexpr char kProviders[] = "providers";
|
||||
|
||||
} // namespace
|
||||
} // namespace LyricsSettings
|
||||
|
||||
#endif // LYRICSSETTINGS_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
|
||||
|
||||
@@ -38,6 +38,6 @@ constexpr char kShow[] = "show";
|
||||
constexpr char kStyle[] = "style";
|
||||
constexpr char kSave[] = "save";
|
||||
|
||||
} // namespace
|
||||
} // namespace MoodbarSettings
|
||||
|
||||
#endif // MOODBARSETTINGS_H
|
||||
|
||||
@@ -32,6 +32,6 @@ constexpr char kUsername[] = "username";
|
||||
constexpr char kPassword[] = "password";
|
||||
constexpr char kEngine[] = "engine";
|
||||
|
||||
} // namespace
|
||||
} // namespace NetworkProxySettings
|
||||
|
||||
#endif // NETWORKPROXYSETTINGS_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 {
|
||||
|
||||
@@ -79,6 +79,6 @@ enum class StatusDisplayType {
|
||||
Song
|
||||
};
|
||||
|
||||
} // namespace
|
||||
} // namespace DiscordRPCSettings
|
||||
|
||||
#endif // NOTIFICATIONSSETTINGS_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)
|
||||
|
||||
|
||||
@@ -43,6 +43,6 @@ constexpr char kCredentialsId[] = "credentials_id";
|
||||
constexpr char kDeviceId[] = "device_id";
|
||||
constexpr char kUserAuthToken[] = "user_auth_token";
|
||||
|
||||
} // namespace
|
||||
} // namespace QobuzSettings
|
||||
|
||||
#endif // QOBUZSETTINGS_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
|
||||
|
||||
@@ -38,6 +38,6 @@ constexpr char kRefreshToken[] = "refresh_token";
|
||||
constexpr char kExpiresIn[] = "expires_in";
|
||||
constexpr char kLoginTime[] = "login_time";
|
||||
|
||||
} // namespace
|
||||
} // namespace SpotifySettings
|
||||
|
||||
#endif // SPOTIFYSETTINGS_H
|
||||
|
||||
@@ -41,6 +41,6 @@ constexpr char kUseAlbumIdForAlbumCovers[] = "usealbumidforalbumcovers";
|
||||
constexpr char kServerSideScrobbling[] = "serversidescrobbling";
|
||||
constexpr char kAuthMethod[] = "authmethod";
|
||||
|
||||
} // namespace
|
||||
} // namespace SubsonicSettings
|
||||
|
||||
#endif // SUBSONICETTINGS_H
|
||||
|
||||
@@ -48,6 +48,6 @@ enum class StreamUrlMethod {
|
||||
PlaybackInfoPostPaywall
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace TidalSettings
|
||||
|
||||
#endif // TIDALSETTINGS_H
|
||||
|
||||
@@ -26,4 +26,3 @@ constexpr char kSettingsGroup[] = "Transcoder";
|
||||
}
|
||||
|
||||
#endif // TRANSCODERSETTINGS_H
|
||||
|
||||
|
||||
@@ -61,7 +61,6 @@ class ContextAlbum : public QWidget {
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
|
||||
private:
|
||||
|
||||
struct PreviousCover {
|
||||
explicit PreviousCover() : opacity(0.0) {}
|
||||
QImage image;
|
||||
|
||||
@@ -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"
|
||||
@@ -353,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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
#include "lyrics/elyricsnetlyricsprovider.h"
|
||||
#include "lyrics/letraslyricsprovider.h"
|
||||
#include "lyrics/lyricfindlyricsprovider.h"
|
||||
#include "lyrics/lrcliblyricsprovider.h"
|
||||
|
||||
#include "scrobbler/audioscrobbler.h"
|
||||
#include "scrobbler/lastfmscrobbler.h"
|
||||
@@ -117,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;
|
||||
@@ -182,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;
|
||||
}),
|
||||
|
||||
@@ -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),
|
||||
@@ -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";
|
||||
|
||||
@@ -128,7 +128,6 @@ class Database : public QObject {
|
||||
int startup_schema_version_;
|
||||
|
||||
QThread *original_thread_;
|
||||
|
||||
};
|
||||
|
||||
#endif // DATABASE_H
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -296,9 +296,6 @@ MainWindow::MainWindow(Application *app,
|
||||
#ifdef HAVE_DISCORD_RPC
|
||||
discord_rich_presence_(discord_rich_presence),
|
||||
#endif
|
||||
error_dialog_([this]() {
|
||||
return new ErrorDialog(this);
|
||||
}),
|
||||
console_([app, this]() {
|
||||
Console *console = new Console(app->database());
|
||||
QObject::connect(console, &Console::Error, this, &MainWindow::ShowErrorDialog);
|
||||
|
||||
@@ -285,7 +285,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
void Raise();
|
||||
|
||||
private:
|
||||
|
||||
void SaveSettings();
|
||||
|
||||
static void ApplyAddBehaviour(const BehaviourSettings::AddBehaviour b, MimeData *mimedata);
|
||||
@@ -415,7 +414,6 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
bool playlists_loaded_;
|
||||
bool delete_files_;
|
||||
std::optional<CommandlineOptions> options_;
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -40,7 +40,6 @@ class QtFSListener : public FileSystemWatcherInterface {
|
||||
|
||||
private:
|
||||
QFileSystemWatcher watcher_;
|
||||
|
||||
};
|
||||
|
||||
#endif // QTFSLISTENER_H
|
||||
|
||||
@@ -28,6 +28,7 @@ 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_;
|
||||
|
||||
|
||||
@@ -2150,4 +2150,3 @@ QString Song::GetNameForNewPlaylist(const SongList &songs) {
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -784,4 +784,3 @@ void SongLoader::CleanupPipeline() {
|
||||
state_ = State::Finished;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,6 @@ class SongLoader : public QObject {
|
||||
QStringList errors_;
|
||||
|
||||
bool success_;
|
||||
|
||||
};
|
||||
|
||||
#endif // SONGLOADER_H
|
||||
|
||||
@@ -41,4 +41,3 @@ class SongMimeData : public MimeData {
|
||||
};
|
||||
|
||||
#endif // SONGMIMEDATA_H
|
||||
|
||||
|
||||
@@ -41,17 +41,19 @@ Translations::~Translations() {
|
||||
|
||||
}
|
||||
|
||||
void Translations::LoadTranslation(const QString &prefix, const QString &path, const QString &language) {
|
||||
bool Translations::LoadTranslation(const QString &prefix, const QString &path, const QString &language) {
|
||||
|
||||
const QString basefilename = prefix + u'_' + language;
|
||||
QTranslator *t = new QTranslator;
|
||||
if (t->load(basefilename, path)) {
|
||||
if (!t->load(basefilename, path)) {
|
||||
delete t;
|
||||
return false;
|
||||
}
|
||||
|
||||
qLog(Debug) << "Tranlations loaded from" << basefilename;
|
||||
QCoreApplication::installTranslator(t);
|
||||
translations_ << t;
|
||||
}
|
||||
else {
|
||||
delete t;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ class Translations {
|
||||
public:
|
||||
explicit Translations();
|
||||
~Translations();
|
||||
void LoadTranslation(const QString &prefix, const QString &path, const QString &language);
|
||||
bool LoadTranslation(const QString &prefix, const QString &path, const QString &language);
|
||||
|
||||
private:
|
||||
QList<QTranslator*> translations_;
|
||||
|
||||
@@ -53,4 +53,3 @@ UrlHandler::LoadResult::LoadResult(const QUrl &media_url, const Type type, const
|
||||
bit_depth_(-1),
|
||||
length_nanosec_(-1),
|
||||
error_(error) {}
|
||||
|
||||
|
||||
@@ -89,7 +89,6 @@ class UrlHandler : public QObject {
|
||||
|
||||
Q_SIGNALS:
|
||||
void AsyncLoadComplete(const UrlHandler::LoadResult &result);
|
||||
|
||||
};
|
||||
|
||||
#endif // URLHANDLER_H
|
||||
|
||||
@@ -812,8 +812,8 @@ QUrl AlbumCoverChoiceController::SaveCoverAutomatic(Song *song, const AlbumCover
|
||||
SaveCoverEmbeddedToCollectionSongs(*song, result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
[[fallthrough]];
|
||||
}
|
||||
case CoverOptions::CoverType::Cache:
|
||||
case CoverOptions::CoverType::Album:{
|
||||
cover_url = SaveCoverToFileAutomatic(song, result);
|
||||
|
||||
@@ -75,4 +75,3 @@ class AlbumCoverExporter : public QObject {
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVEREXPORTER_H
|
||||
|
||||
|
||||
@@ -113,7 +113,6 @@ class AlbumCoverFetcherSearch : public QObject {
|
||||
SharedPtr<NetworkAccessManager> network_;
|
||||
|
||||
bool cancel_requested_;
|
||||
|
||||
};
|
||||
|
||||
#endif // ALBUMCOVERFETCHERSEARCH_H
|
||||
|
||||
@@ -58,5 +58,4 @@ AlbumCoverLoaderOptions::Types AlbumCoverLoaderOptions::LoadTypes() {
|
||||
s.endGroup();
|
||||
|
||||
return cover_types;
|
||||
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ class AlbumCoverLoaderResult {
|
||||
const AlbumCoverImageResult &_album_cover = AlbumCoverImageResult(),
|
||||
const QImage &_image_scaled = QImage(),
|
||||
const QUrl &_art_manual_updated = QUrl(),
|
||||
const QUrl &_art_automatic_updated = QUrl()) :
|
||||
success(_success),
|
||||
const QUrl &_art_automatic_updated = QUrl())
|
||||
: success(_success),
|
||||
type(_type),
|
||||
album_cover(_album_cover),
|
||||
image_scaled(_image_scaled),
|
||||
|
||||
@@ -102,7 +102,7 @@ using std::make_shared;
|
||||
namespace {
|
||||
constexpr char kSettingsGroup[] = "CoverManager";
|
||||
constexpr int kThumbnailSize = 120;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
AlbumCoverManager::AlbumCoverManager(const SharedPtr<NetworkAccessManager> network,
|
||||
const SharedPtr<CollectionBackend> collection_backend,
|
||||
@@ -604,10 +604,7 @@ void AlbumCoverManager::AlbumCoverFetched(const quint64 id, const AlbumCoverImag
|
||||
|
||||
void AlbumCoverManager::UpdateStatusText() {
|
||||
|
||||
QString message = tr("Got %1 covers out of %2 (%3 failed)")
|
||||
.arg(fetch_statistics_.chosen_images_)
|
||||
.arg(jobs_)
|
||||
.arg(fetch_statistics_.missing_images_);
|
||||
QString message = tr("Got %1 covers out of %2 (%3 failed)").arg(fetch_statistics_.chosen_images_).arg(jobs_).arg(fetch_statistics_.missing_images_);
|
||||
|
||||
if (fetch_statistics_.bytes_transferred_ > 0) {
|
||||
message += ", "_L1 + tr("%1 transferred").arg(Utilities::PrettySize(fetch_statistics_.bytes_transferred_));
|
||||
@@ -1083,10 +1080,7 @@ void AlbumCoverManager::UpdateExportStatus(const int exported, const int skipped
|
||||
|
||||
progress_bar_->setValue(exported);
|
||||
|
||||
QString message = tr("Exported %1 covers out of %2 (%3 skipped)")
|
||||
.arg(exported)
|
||||
.arg(max)
|
||||
.arg(skipped);
|
||||
QString message = tr("Exported %1 covers out of %2 (%3 skipped)").arg(exported).arg(max).arg(skipped);
|
||||
statusBar()->showMessage(message);
|
||||
|
||||
// End of the current process
|
||||
@@ -1131,4 +1125,3 @@ void AlbumCoverManager::SaveEmbeddedCoverFinished(TagReaderReplyPtr reply, Album
|
||||
LoadAlbumCoverAsync(album_item);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ class AlbumCoverSearcher : public QDialog {
|
||||
AlbumCoverImageResult Exec(const QString &artist, const QString &album);
|
||||
|
||||
protected:
|
||||
void keyPressEvent(QKeyEvent*) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void Search();
|
||||
|
||||
@@ -45,8 +45,7 @@ CoverSearchStatisticsDialog::CoverSearchStatisticsDialog(QWidget *parent)
|
||||
details_layout_ = new QVBoxLayout(ui_->details);
|
||||
details_layout_->setSpacing(0);
|
||||
|
||||
setStyleSheet(
|
||||
u"#details {"
|
||||
setStyleSheet(u"#details {"
|
||||
" background-color: palette(base);"
|
||||
"}"
|
||||
"#details QLabel[type=\"label\"] {"
|
||||
@@ -67,10 +66,7 @@ void CoverSearchStatisticsDialog::Show(const CoverSearchStatistics &statistics)
|
||||
QStringList providers(statistics.total_images_by_provider_.keys());
|
||||
std::sort(providers.begin(), providers.end());
|
||||
|
||||
ui_->summary->setText(tr("Got %1 covers out of %2 (%3 failed)")
|
||||
.arg(statistics.chosen_images_)
|
||||
.arg(statistics.chosen_images_ + statistics.missing_images_)
|
||||
.arg(statistics.missing_images_));
|
||||
ui_->summary->setText(tr("Got %1 covers out of %2 (%3 failed)").arg(statistics.chosen_images_).arg(statistics.chosen_images_ + statistics.missing_images_).arg(statistics.missing_images_));
|
||||
|
||||
for (const QString &provider : std::as_const(providers)) {
|
||||
AddLine(tr("Covers from %1").arg(provider), QString::number(statistics.chosen_images_by_provider_[provider]));
|
||||
|
||||
@@ -138,4 +138,3 @@ void CDDADevice::SongLoadingFinished() {
|
||||
WatchForDiscChanges(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -159,3 +159,11 @@ bool CDDALister::Init() {
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool CDDALister::AskForScan(const QString &id) const {
|
||||
|
||||
Q_UNUSED(id)
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@@ -47,11 +47,11 @@ class CDDALister : public DeviceLister {
|
||||
quint64 DeviceCapacity(const QString &id) override;
|
||||
quint64 DeviceFreeSpace(const QString &id) override;
|
||||
QVariantMap DeviceHardwareInfo(const QString &id) override;
|
||||
bool AskForScan(const QString&) const override { return false; }
|
||||
QString MakeFriendlyName(const QString&) override;
|
||||
QList<QUrl> MakeDeviceUrls(const QString&) override;
|
||||
void UnmountDevice(const QString&) override;
|
||||
void UpdateDeviceFreeSpace(const QString&) override;
|
||||
bool AskForScan(const QString &id) const override;
|
||||
QString MakeFriendlyName(const QString &id) override;
|
||||
QList<QUrl> MakeDeviceUrls(const QString &id) override;
|
||||
void UnmountDevice(const QString &id) override;
|
||||
void UpdateDeviceFreeSpace(const QString &id) override;
|
||||
bool Init() override;
|
||||
bool CopyMusic() override { return false; }
|
||||
|
||||
|
||||
@@ -227,8 +227,7 @@ void DeviceDatabaseBackend::SetDeviceOptions(const int id, const QString &friend
|
||||
QSqlDatabase db(db_->Connect());
|
||||
|
||||
SqlQuery q(db);
|
||||
q.prepare(QStringLiteral(
|
||||
"UPDATE devices"
|
||||
q.prepare(QStringLiteral("UPDATE devices"
|
||||
" SET friendly_name=:friendly_name,"
|
||||
" icon=:icon_name,"
|
||||
" transcode_mode=:transcode_mode,"
|
||||
|
||||
@@ -77,7 +77,6 @@ class DeviceDatabaseBackend : public QObject {
|
||||
private:
|
||||
SharedPtr<Database> db_;
|
||||
QThread *original_thread_;
|
||||
|
||||
};
|
||||
|
||||
#endif // DEVICEDATABASEBACKEND_H
|
||||
|
||||
@@ -61,7 +61,6 @@ class DeviceItemDelegate : public CollectionItemDelegate {
|
||||
static const int kIconPadding;
|
||||
|
||||
void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &idx) const override;
|
||||
|
||||
};
|
||||
|
||||
class DeviceView : public AutoExpandingTreeView {
|
||||
@@ -80,7 +79,7 @@ class DeviceView : public AutoExpandingTreeView {
|
||||
bool CanRecursivelyExpand(const QModelIndex &idx) const override;
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent*) override;
|
||||
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||
void mouseDoubleClickEvent(QMouseEvent *e) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
|
||||
@@ -160,7 +160,10 @@ QVariantList GioLister::DeviceIcons(const QString &id) {
|
||||
|
||||
}
|
||||
|
||||
QString GioLister::DeviceManufacturer(const QString &id) { Q_UNUSED(id); return QString(); }
|
||||
QString GioLister::DeviceManufacturer(const QString &id) {
|
||||
Q_UNUSED(id);
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString GioLister::DeviceModel(const QString &id) {
|
||||
|
||||
|
||||
@@ -119,8 +119,8 @@ class GioLister : public DeviceLister {
|
||||
static void VolumeAddedCallback(GVolumeMonitor *volume_monitor, GVolume *volume, gpointer instance);
|
||||
static void VolumeRemovedCallback(GVolumeMonitor *volume_monitor, GVolume *volume, gpointer instance);
|
||||
|
||||
static void MountAddedCallback(GVolumeMonitor *volume_monitor, GMount*, gpointer instance);
|
||||
static void MountChangedCallback(GVolumeMonitor *volume_monitor, GMount*, gpointer instance);
|
||||
static void MountAddedCallback(GVolumeMonitor *volume_monitor, GMount *mount, gpointer instance);
|
||||
static void MountChangedCallback(GVolumeMonitor *volume_monitor, GMount *mount, gpointer instance);
|
||||
static void MountRemovedCallback(GVolumeMonitor *volume_monitor, GMount *mount, gpointer instance);
|
||||
|
||||
static void VolumeMountFinished(GObject *object, GAsyncResult *result, gpointer instance);
|
||||
|
||||
@@ -64,7 +64,6 @@ class MtpLoader : public QObject {
|
||||
ScopedPtr<MtpConnection> connection_;
|
||||
QThread *original_thread_;
|
||||
bool abort_;
|
||||
|
||||
};
|
||||
|
||||
#endif // MTPLOADER_H
|
||||
|
||||
@@ -411,10 +411,7 @@ Udisks2Lister::PartitionData Udisks2Lister::ReadPartitionData(const QDBusObjectP
|
||||
}
|
||||
|
||||
QString Udisks2Lister::PartitionData::unique_id() const {
|
||||
return u"Udisks2/%1/%2/%3/%4/%5"_s
|
||||
.arg(serial, vendor, model)
|
||||
.arg(capacity)
|
||||
.arg(uuid);
|
||||
return u"Udisks2/%1/%2/%3/%4/%5"_s.arg(serial, vendor, model).arg(capacity).arg(uuid);
|
||||
}
|
||||
|
||||
Udisks2Lister::Udisks2Job::Udisks2Job() : is_mount(true) {}
|
||||
|
||||
@@ -127,8 +127,9 @@ QString About::MainHtml() const {
|
||||
ret += "<p>"_L1;
|
||||
ret += tr("If you like Strawberry and can make use of it, consider sponsoring or donating.");
|
||||
ret += "<br />"_L1;
|
||||
ret += tr("You can sponsor the author on %1. You can also make a one-time payment through %2.").arg(
|
||||
QStringLiteral("<a style=\"color:%1;\" href=\"https://github.com/sponsors/jonaski\">GitHub sponsors</a>").arg(palette().text().color().name()),
|
||||
ret += tr("You can sponsor the author on %1 or %2. You can also make a one-time payment through %3.").arg(
|
||||
QStringLiteral("<a style=\"color:%1;\" href=\"https://www.patreon.com/jonaskvinge\">Patreon</a>").arg(palette().text().color().name()),
|
||||
QStringLiteral("<a style=\"color:%1;\" href=\"https://github.com/sponsors/jonaski\">GitHub</a>").arg(palette().text().color().name()),
|
||||
QStringLiteral("<a style=\"color:%1;\" href=\"https://paypal.me/jonaskvinge\">paypal.me/jonaskvinge</a>").arg(palette().text().color().name())
|
||||
);
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
#include <QSettings>
|
||||
#include <QMimeData>
|
||||
|
||||
#include "constants/timeconstants.h"
|
||||
#include "core/iconloader.h"
|
||||
#include "core/logging.h"
|
||||
#include "core/settings.h"
|
||||
@@ -1520,7 +1521,7 @@ void EditTagDialog::FetchLyrics() {
|
||||
const Song song = data_.value(ui_->song_list->selectionModel()->selectedIndexes().first().row()).current_;
|
||||
lyrics_fetcher_->Clear();
|
||||
ui_->lyrics->setPlainText(tr("loading..."));
|
||||
lyrics_id_ = static_cast<qint64>(lyrics_fetcher_->Search(song.effective_albumartist(), song.artist(), song.album(), song.title()));
|
||||
lyrics_id_ = static_cast<qint64>(lyrics_fetcher_->Search(song.effective_albumartist(), song.artist(), song.album(), song.title(), song.length_nanosec() / kNsecPerSec));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include <QWidget>
|
||||
#include <QApplication>
|
||||
#include <QString>
|
||||
#include <QIcon>
|
||||
#include <QPalette>
|
||||
@@ -40,9 +41,8 @@
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
|
||||
ErrorDialog::ErrorDialog(QWidget *mainwindow, QWidget *parent)
|
||||
ErrorDialog::ErrorDialog(QWidget *parent)
|
||||
: QDialog(parent),
|
||||
mainwindow_(mainwindow),
|
||||
ui_(new Ui_ErrorDialog) {
|
||||
|
||||
ui_->setupUi(this);
|
||||
@@ -64,8 +64,9 @@ ErrorDialog::~ErrorDialog() {
|
||||
|
||||
void ErrorDialog::ShowDialog() {
|
||||
|
||||
if (screen() && mainwindow_->screen() && screen() != mainwindow_->screen()) {
|
||||
Utilities::CenterWidgetOnScreen(mainwindow_->screen(), this);
|
||||
QWidget *active_window = QApplication::activeWindow();
|
||||
if (active_window && screen() && active_window->screen() && screen() != active_window->screen()) {
|
||||
Utilities::CenterWidgetOnScreen(active_window->screen(), this);
|
||||
}
|
||||
setWindowState((windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
|
||||
show();
|
||||
@@ -81,7 +82,7 @@ void ErrorDialog::ShowMessage(const QString &message) {
|
||||
current_messages_ << message;
|
||||
UpdateContent();
|
||||
|
||||
if (mainwindow_->isActiveWindow()) {
|
||||
if (QApplication::activeWindow()) {
|
||||
ShowDialog();
|
||||
}
|
||||
else if (!isVisible()) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class ErrorDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ErrorDialog(QWidget *mainwindow, QWidget *parent = nullptr);
|
||||
explicit ErrorDialog(QWidget *parent = nullptr);
|
||||
~ErrorDialog() override;
|
||||
|
||||
public Q_SLOTS:
|
||||
@@ -50,7 +50,6 @@ class ErrorDialog : public QDialog {
|
||||
private:
|
||||
void UpdateContent();
|
||||
|
||||
QWidget *mainwindow_;
|
||||
Ui_ErrorDialog *ui_;
|
||||
|
||||
QStringList current_messages_;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
@@ -105,7 +106,7 @@ void RichPresence::CurrentSongChanged(const Song &song) {
|
||||
|
||||
SetTimestamp(0LL);
|
||||
activity_.length_secs = song.length_nanosec() / kNsecPerSec;
|
||||
activity_.title = song.title();
|
||||
activity_.title = song.PrettyTitle();
|
||||
activity_.artist = song.artist();
|
||||
activity_.album = song.album();
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
@@ -419,8 +419,7 @@ std::optional<EBUR128Measures> EBUR128AnalysisImpl::Compute(const Song &song) {
|
||||
// Connect the elements
|
||||
gst_element_link_many(src, decode, nullptr);
|
||||
|
||||
GstStaticCaps static_caps = GST_STATIC_CAPS(
|
||||
"audio/x-raw,"
|
||||
GstStaticCaps static_caps = GST_STATIC_CAPS("audio/x-raw,"
|
||||
"format = (string) { S16LE, S32LE, F32LE, F64LE },"
|
||||
"layout = (string) interleaved");
|
||||
|
||||
|
||||
@@ -632,7 +632,10 @@ void GstEngine::HandlePipelineError(const int pipeline_id, const int domain, con
|
||||
qLog(Error) << "GStreamer error:" << domain << error_code << message;
|
||||
|
||||
Q_EMIT Error(message);
|
||||
|
||||
if (!debugstr.isEmpty()) {
|
||||
Q_EMIT Error(debugstr);
|
||||
}
|
||||
|
||||
if (fadeout_pause_pipeline_ && pipeline_id == fadeout_pause_pipeline_->id()) {
|
||||
StopFadeoutPause();
|
||||
@@ -1061,8 +1064,7 @@ void GstEngine::UpdateScope(const int chunk_length) {
|
||||
buffer_format_.startsWith("S24LE"_L1) ||
|
||||
buffer_format_.startsWith("S24_32LE"_L1) ||
|
||||
buffer_format_.startsWith("S32LE"_L1) ||
|
||||
buffer_format_.startsWith("F32LE"_L1)
|
||||
) {
|
||||
buffer_format_.startsWith("F32LE"_L1)) {
|
||||
memcpy(dest, source, bytes);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -1525,7 +1525,15 @@ void GstEnginePipeline::ElementMessageReceived(GstMessage *msg) {
|
||||
|
||||
const GstStructure *structure = gst_message_get_structure(msg);
|
||||
|
||||
if (gst_structure_has_name(structure, "redirect")) {
|
||||
if (gst_structure_has_name(structure, "missing-plugin")) {
|
||||
gchar *description = gst_missing_plugin_message_get_description(msg);
|
||||
gchar *detail = gst_missing_plugin_message_get_installer_detail(msg);
|
||||
const QString message = QLatin1String("Missing GStreamer plugin for %1 (%2)").arg(QString::fromLocal8Bit(description)).arg(QString::fromLocal8Bit(detail));
|
||||
g_free(description);
|
||||
g_free(detail);
|
||||
Q_EMIT Error(id(), static_cast<int>(GST_LIBRARY_ERROR), GST_CORE_ERROR_MISSING_PLUGIN, message, QString());
|
||||
}
|
||||
else if (gst_structure_has_name(structure, "redirect")) {
|
||||
const char *uri = gst_structure_get_string(structure, "new-location");
|
||||
|
||||
// Set the redirect URL. In mmssrc redirect messages come during the initial state change to PLAYING, so callers can pick up this URL after the state change has failed.
|
||||
|
||||
@@ -23,6 +23,6 @@
|
||||
namespace GstStartup {
|
||||
void Initialize();
|
||||
void SetEnvironment();
|
||||
} // namespace
|
||||
} // namespace GstStartup
|
||||
|
||||
#endif // GSTSTARTUP_H
|
||||
|
||||
@@ -147,4 +147,3 @@ PulseDeviceFinder::~PulseDeviceFinder() {
|
||||
pa_mainloop_free(mainloop_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -68,4 +68,3 @@ int EqualizerSlider::value() const {
|
||||
void EqualizerSlider::set_value(const int value) {
|
||||
ui_->slider->setValue(value);
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ class FileView : public QWidget {
|
||||
void SetTaskManager(SharedPtr<TaskManager> task_manager);
|
||||
|
||||
protected:
|
||||
void showEvent(QShowEvent*) override;
|
||||
void showEvent(QShowEvent *e) override;
|
||||
void keyPressEvent(QKeyEvent *e) override;
|
||||
|
||||
Q_SIGNALS:
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
|
||||
#include <QString>
|
||||
|
||||
#include "constants/timeconstants.h"
|
||||
#include "filterparser.h"
|
||||
#include "filtertreenop.h"
|
||||
#include "filtertreeand.h"
|
||||
@@ -322,7 +323,7 @@ FilterTree *FilterParser::createSearchTermTreeNode(const QString &column, const
|
||||
else if (Song::kInt64SearchColumns.contains(column, Qt::CaseInsensitive)) {
|
||||
qint64 number = 0;
|
||||
if (column == "length"_L1) {
|
||||
number = ParseTime(value);
|
||||
number = ParseTime(value) * kNsecPerSec;
|
||||
}
|
||||
else {
|
||||
number = value.toLongLong();
|
||||
|
||||
@@ -28,6 +28,7 @@ class FilterParserFloatEqComparator : public FilterParserSearchTermComparator {
|
||||
public:
|
||||
explicit FilterParserFloatEqComparator(const float search_term);
|
||||
bool Matches(const QVariant &value) const override;
|
||||
|
||||
private:
|
||||
float search_term_;
|
||||
Q_DISABLE_COPY(FilterParserFloatEqComparator)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user