Merge branch 'master' of github.com:poldi171254/strawberry

This commit is contained in:
Poldi 2024-03-14 11:17:07 +11:00
commit 992a16769a
123 changed files with 3707 additions and 1852 deletions

View File

@ -1,5 +1,10 @@
name: Build name: Build
on: [push, pull_request] on:
push:
pull_request:
types: [opened, synchronize, reopened]
release:
types: [published]
jobs: jobs:
@ -137,32 +142,24 @@ jobs:
CC: gcc-10 CC: gcc-10
CXX: g++-10 CXX: g++-10
run: rpmbuild -ba ../dist/unix/strawberry.spec run: rpmbuild -ba ../dist/unix/strawberry.spec
- name: Set opensuse subdir - name: Set subdir
run: echo "opensuse_subdir=$(echo ${{matrix.opensuse_version}} | sed 's/leap:/lp/g' | sed 's/\.//g')" > $GITHUB_ENV id: set-subdir
- name: Upload artifacts run: echo "subdir=$(echo ${{matrix.opensuse_version}} | sed 's/leap:/lp/g' | sed 's/\.//g')" > $GITHUB_OUTPUT
if: matrix.opensuse_version != 'tumbleweed' - name: Upload source
if: matrix.opensuse_version == 'tumbleweed' && matrix.qt_version == '6'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: opensuse-${{env.opensuse_subdir}}-qt${{matrix.qt_version}} name: source
path: | path: |
/usr/src/packages/SOURCES/*.xz /usr/src/packages/SOURCES/*.xz
- name: Upload rpm
if: matrix.opensuse_version != 'tumbleweed' && matrix.qt_version == '6'
uses: actions/upload-artifact@v4
with:
name: opensuse-${{steps.set-subdir.outputs.subdir}}
path: |
/usr/src/packages/SRPMS/*.rpm /usr/src/packages/SRPMS/*.rpm
/usr/src/packages/RPMS/x86_64/*.rpm /usr/src/packages/RPMS/x86_64/*.rpm
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/source ${{secrets.BUILDS_PATH}}/opensuse/${{env.opensuse_subdir}}
- name: rsync source
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci') && matrix.opensuse_version == 'tumbleweed' && matrix.qt_version == '6'
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var /usr/src/packages/SOURCES/*.xz ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/source/
- name: rsync rpms
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci') && matrix.opensuse_version != 'tumbleweed'
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var /usr/src/packages/SRPMS/*.rpm /usr/src/packages/RPMS/x86_64/*.rpm ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/opensuse/${{env.opensuse_subdir}}/
build-fedora: build-fedora:
@ -182,7 +179,7 @@ jobs:
run: dnf -y upgrade run: dnf -y upgrade
- name: Install dependencies - name: Install dependencies
run: > run: >
dnf -y install dnf -y --skip-broken install
@development-tools @development-tools
redhat-lsb-core redhat-lsb-core
which which
@ -256,18 +253,6 @@ jobs:
path: | path: |
/github/home/rpmbuild/SRPMS/*.rpm /github/home/rpmbuild/SRPMS/*.rpm
/github/home/rpmbuild/RPMS/x86_64/*.rpm /github/home/rpmbuild/RPMS/x86_64/*.rpm
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/fedora/${{matrix.fedora_version}}
- name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var /github/home/rpmbuild/SRPMS/*.rpm /github/home/rpmbuild/RPMS/x86_64/*.rpm ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/fedora/${{matrix.fedora_version}}/
build-openmandriva: build-openmandriva:
@ -360,24 +345,13 @@ jobs:
working-directory: build working-directory: build
run: rpmbuild -ba ../dist/unix/strawberry.spec run: rpmbuild -ba ../dist/unix/strawberry.spec
- name: Upload artifacts - name: Upload artifacts
if: matrix.openmandriva_version != 'cooker'
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: openmandriva-${{matrix.openmandriva_version}} name: openmandriva-${{matrix.openmandriva_version}}
path: | path: |
/github/home/rpmbuild/SRPMS/*.rpm /github/home/rpmbuild/SRPMS/*.rpm
/github/home/rpmbuild/RPMS/x86_64/*.rpm /github/home/rpmbuild/RPMS/x86_64/*.rpm
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && matrix.openmandriva_version != 'cooker' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && matrix.openmandriva_version != 'cooker' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/openmandriva/${{matrix.openmandriva_version}}
- name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && matrix.openmandriva_version != 'cooker' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var /github/home/rpmbuild/SRPMS/*.rpm /github/home/rpmbuild/RPMS/x86_64/*.rpm ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/openmandriva/${{matrix.openmandriva_version}}/
build-mageia: build-mageia:
@ -468,18 +442,6 @@ jobs:
path: | path: |
/github/home/rpmbuild/SRPMS/*.rpm /github/home/rpmbuild/SRPMS/*.rpm
/github/home/rpmbuild/RPMS/x86_64/*.rpm /github/home/rpmbuild/RPMS/x86_64/*.rpm
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/mageia/${{matrix.mageia_version}}
- name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var /github/home/rpmbuild/SRPMS/*.rpm /github/home/rpmbuild/RPMS/x86_64/*.rpm ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/mageia/${{matrix.mageia_version}}/
build-debian: build-debian:
@ -564,18 +526,6 @@ jobs:
with: with:
name: debian-${{matrix.debian_version}} name: debian-${{matrix.debian_version}}
path: "*.deb" path: "*.deb"
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/debian/${{matrix.debian_version}}
- name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var *.deb ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/debian/${{matrix.debian_version}}/
build-ubuntu: build-ubuntu:
@ -585,7 +535,7 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
ubuntu_version: [ 'focal', 'jammy', 'lunar', 'mantic' ] ubuntu_version: [ 'focal', 'jammy', 'mantic', 'noble' ]
container: container:
image: ubuntu:${{matrix.ubuntu_version}} image: ubuntu:${{matrix.ubuntu_version}}
steps: steps:
@ -665,28 +615,16 @@ jobs:
path: | path: |
*.deb *.deb
*.ddeb *.ddeb
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/ubuntu/${{matrix.ubuntu_version}}
- name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var *.deb *.ddeb ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/ubuntu/${{matrix.ubuntu_version}}/
upload-ubuntu-ppa: upload-ubuntu-ppa:
name: Upload Ubuntu PPA name: Upload Ubuntu PPA
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci') if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.event_name == 'release' || (github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')))
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
ubuntu_version: [ 'focal', 'jammy', 'lunar', 'mantic' ] ubuntu_version: [ 'focal', 'jammy', 'mantic', 'noble' ]
container: container:
image: ubuntu:${{matrix.ubuntu_version}} image: ubuntu:${{matrix.ubuntu_version}}
steps: steps:
@ -762,15 +700,11 @@ jobs:
gpg_private_key: ${{secrets.UBUNTU_PPA_GPG_PRIVATE_KEY}} gpg_private_key: ${{secrets.UBUNTU_PPA_GPG_PRIVATE_KEY}}
- name: dpkg-buildpackage - name: dpkg-buildpackage
run: dpkg-buildpackage -S -d -k573D197B5EA20EDF run: dpkg-buildpackage -S -d -k573D197B5EA20EDF
- name: Set is release
run: echo "is_release=$(grep '^\s*set\s*(\s*INCLUDE_GIT_REVISION\s\+OFF\s*)\s*$' cmake/Version.cmake >/dev/null 2>&1 && echo 1 || echo 0)" >> $GITHUB_ENV
- name: Get release version
run: echo "release_version=$(git describe --tags --exact-match ${GITHUB_SHA} 2>/dev/null | head -1)" >> $GITHUB_ENV
- name: Upload Unstable PPA - name: Upload Unstable PPA
if: env.is_release != '1' && env.release_version == '' if: github.event_name == 'push'
run: dput ppa:jonaski/strawberry-unstable ../*_source.changes run: dput ppa:jonaski/strawberry-unstable ../*_source.changes
- name: Upload Stable PPA - name: Upload Stable PPA
if: env.is_release == '1' && env.release_version != '' if: github.event_name == 'release'
run: dput ppa:jonaski/strawberry ../*_source.changes run: dput ppa:jonaski/strawberry ../*_source.changes
@ -869,10 +803,10 @@ jobs:
working-directory: build working-directory: build
run: make deploy run: make deploy
- name: Codesign libsoup - name: Manually Codesign
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false
working-directory: build working-directory: build
run: codesign -s 383J84DVB6 -f strawberry.app/Contents/Frameworks/{libsoup-3.0.0.dylib,libnghttp2.14.dylib,libpsl.5.dylib,libpcre2-16.0.dylib,libpng16.16.dylib,libzstd.1.dylib} strawberry.app run: codesign -s 383J84DVB6 -f strawberry.app/Contents/Frameworks/{libsoup-3.0.0.dylib,libnghttp2.14.dylib,libpsl.5.dylib,libpcre2-16.0.dylib,libpng16.16.dylib,libzstd.1.dylib} strawberry.app/Contents/Frameworks/png.framework/png strawberry.app
- name: Deploy check - name: Deploy check
working-directory: build working-directory: build
@ -888,34 +822,29 @@ jobs:
run: make dmg run: make dmg
- name: SSH key setup - name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/macos') if: github.repository == 'strawberrymusicplayer/strawberry' && (github.event_name == 'release' || (github.event_name == 'push' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/macos')))
uses: shimataro/ssh-key-action@v2 uses: shimataro/ssh-key-action@v2
with: with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}} known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }} key: ${{ secrets.SSH_KEY }}
- name: Set is release
run: echo "is_release=$(grep '^\s*set\s*(\s*INCLUDE_GIT_REVISION\s\+OFF\s*)\s*$' cmake/Version.cmake >/dev/null 2>&1 && echo 1 || echo 0)" >> $GITHUB_ENV
- name: Get release version
run: echo "release_version=$(git describe --tags --exact-match ${GITHUB_SHA} 2>/dev/null | head -1)" >> $GITHUB_ENV
- name: Set Upload path - name: Set Upload path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/macos') id: set-upload-path
if: github.repository == 'strawberrymusicplayer/strawberry' && (github.event_name == 'release' || (github.event_name == 'push' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/macos')))
run: | run: |
if [ "${{env.is_release}}" = "1" ] && ! [ "${{env.release_version}}" = "" ]; then if [ "${{github.event_name}}" = "release" ]; then
echo "upload_path=${{secrets.DOWNLOADS_PATH}}/stable_releases/macos" >> $GITHUB_ENV echo "upload_path=${{secrets.DOWNLOADS_PATH}}/stable_releases/macos" >> $GITHUB_OUTPUT
else else
echo "upload_path=${{secrets.DOWNLOADS_PATH}}/development_releases/macos" >> $GITHUB_ENV echo "upload_path=${{secrets.DOWNLOADS_PATH}}/development_releases/macos" >> $GITHUB_OUTPUT
fi fi
- name: Create server path - name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/macos') if: steps.set-upload-path.outputs.upload_path != ''
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{env.upload_path}} run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{steps.set-upload-path.outputs.upload_path}}
- name: rsync - name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci' || github.ref == 'refs/heads/macos') if: steps.set-upload-path.outputs.upload_path != ''
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/*.dmg ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{env.upload_path}}/ run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/*.dmg ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{steps.set-upload-path.outputs.upload_path}}/
build-macos-private: build-macos-private:
@ -996,6 +925,10 @@ jobs:
working-directory: build working-directory: build
run: make deploy run: make deploy
- name: Manually Codesign
working-directory: build
run: codesign -s 383J84DVB6 -f strawberry.app/Contents/Frameworks/png.framework/png strawberry.app
- name: Deploy check - name: Deploy check
working-directory: build working-directory: build
run: make deploycheck run: make deploycheck
@ -1008,22 +941,20 @@ jobs:
working-directory: build working-directory: build
run: make dmg run: make dmg
- name: Set is release
run: echo "is_release=$(grep '^\s*set\s*(\s*INCLUDE_GIT_REVISION\s\+OFF\s*)\s*$' cmake/Version.cmake >/dev/null 2>&1 && echo 1 || echo 0)" >> $GITHUB_ENV
- name: Set Upload path - name: Set Upload path
id: set-upload-path
run: | run: |
if [ "${{env.is_release}}" = "1" ]; then if [ "${{github.event_name}}" = "release" ]; then
echo "upload_path=${{secrets.DOWNLOADS_PATH}}/stable_releases/macos" >> $GITHUB_ENV echo "upload_path=${{secrets.DOWNLOADS_PATH}}/stable_releases/macos" >> $GITHUB_OUTPUT
else else
echo "upload_path=${{secrets.DOWNLOADS_PATH}}/development_releases/macos" >> $GITHUB_ENV echo "upload_path=${{secrets.DOWNLOADS_PATH}}/development_releases/macos" >> $GITHUB_OUTPUT
fi fi
- name: Create server path - name: Create server path
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{env.upload_path}} run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{steps.set-upload-path.outputs.upload_path}}
- name: rsync - name: rsync
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/*.dmg ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{env.upload_path}}/ run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/*.dmg ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{steps.set-upload-path.outputs.upload_path}}/
build-windows-mingw: build-windows-mingw:
@ -1111,7 +1042,7 @@ jobs:
- name: Copy gstreamer plugins - name: Copy gstreamer plugins
working-directory: build working-directory: build
run: cp /strawberry-mxe/usr/${{matrix.arch}}-w64-mingw32.shared/bin/gstreamer-1.0/{libgstaes.dll,libgstaiff.dll,libgstapetag.dll,libgstapp.dll,libgstasf.dll,libgstasfmux.dll,libgstaudioconvert.dll,libgstaudiofx.dll,libgstaudiomixer.dll,libgstaudioparsers.dll,libgstaudiorate.dll,libgstaudioresample.dll,libgstaudiotestsrc.dll,libgstautodetect.dll,libgstbs2b.dll,libgstcoreelements.dll,libgstdash.dll,libgstdirectsound.dll,libgstequalizer.dll,libgstfaac.dll,libgstfaad.dll,libgstfdkaac.dll,libgstflac.dll,libgstgio.dll,libgstgme.dll,libgsthls.dll,libgsticydemux.dll,libgstid3demux.dll,libgstid3tag.dll,libgstisomp4.dll,libgstlame.dll,libgstlibav.dll,libgstmpg123.dll,libgstmusepack.dll,libgstogg.dll,libgstopenmpt.dll,libgstopus.dll,libgstopusparse.dll,libgstpbtypes.dll,libgstplayback.dll,libgstreplaygain.dll,libgstrtp.dll,libgstrtsp.dll,libgstsoup.dll,libgstspectrum.dll,libgstspeex.dll,libgsttaglib.dll,libgsttcp.dll,libgsttwolame.dll,libgsttypefindfunctions.dll,libgstudp.dll,libgstvolume.dll,libgstvorbis.dll,libgstwasapi.dll,libgstwavenc.dll,libgstwavpack.dll,libgstwavparse.dll,libgstxingmux.dll} ${GITHUB_WORKSPACE}/build/gstreamer-plugins/ run: cp /strawberry-mxe/usr/${{matrix.arch}}-w64-mingw32.shared/bin/gstreamer-1.0/*.dll ${GITHUB_WORKSPACE}/build/gstreamer-plugins/
- name: Copy extra binaries - name: Copy extra binaries
working-directory: build working-directory: build
@ -1196,21 +1127,6 @@ jobs:
name: windows-mingw-${{matrix.arch}}-${{matrix.buildtype}} name: windows-mingw-${{matrix.arch}}-${{matrix.buildtype}}
path: build/StrawberrySetup*.exe path: build/StrawberrySetup*.exe
- name: SSH key setup
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{ secrets.SSH_KEY }}
- name: Create server path
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/windows/mingw
- name: rsync
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var build/StrawberrySetup*.exe ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/windows/mingw/
build-windows-msvc: build-windows-msvc:
name: Build Windows MSVC name: Build Windows MSVC
@ -1310,7 +1226,7 @@ jobs:
with: with:
arch: ${{matrix.arch}} arch: ${{matrix.arch}}
sdk: 10.0.20348.0 sdk: 10.0.20348.0
vsversion: 17 vsversion: 2022
toolset: 14.3 toolset: 14.3
- name: Checkout - name: Checkout
@ -1352,6 +1268,7 @@ jobs:
-DUSE_TAGLIB=ON -DUSE_TAGLIB=ON
-DPKG_CONFIG_EXECUTABLE="${{env.prefix_path_forwardslash}}/bin/pkg-config.exe" -DPKG_CONFIG_EXECUTABLE="${{env.prefix_path_forwardslash}}/bin/pkg-config.exe"
-DICU_ROOT="${{env.prefix_path_forwardslash}}" -DICU_ROOT="${{env.prefix_path_forwardslash}}"
-DFFTW3_DIR="${{env.prefix_path_forwardslash}}"
- name: Run Make - name: Run Make
shell: cmd shell: cmd
@ -1417,66 +1334,7 @@ jobs:
- name: Copy gstreamer plugins - name: Copy gstreamer plugins
shell: cmd shell: cmd
working-directory: build working-directory: build
run: | run: copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\*.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaes.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaiff.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstapetag.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstapp.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstasf.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstasfmux.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudioconvert.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudiofx.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudiomixer.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudioparsers.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudiorate.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudioresample.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstaudiotestsrc.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstautodetect.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstbs2b.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstcoreelements.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstdash.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstdirectsound.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstequalizer.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstfaac.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstfaad.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstfdkaac.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstflac.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstgio.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstgme.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gsthls.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gsticydemux.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstid3demux.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstid3tag.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstisomp4.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstlame.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstlibav.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstmpg123.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstmusepack.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstogg.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstopenmpt.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstopus.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstopusparse.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstpbtypes.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstplayback.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstreplaygain.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstrtp.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstrtsp.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstsoup.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstspectrum.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstspeex.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gsttaglib.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gsttcp.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gsttwolame.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gsttypefindfunctions.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstudp.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstvolume.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstvorbis.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstwasapi.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstwasapi2.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstwavenc.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstwavpack.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstwavparse.dll .\gstreamer-plugins\
copy ${{env.prefix_path_backslash}}\lib\gstreamer-1.0\gstxingmux.dll .\gstreamer-plugins\
- name: Download copydlldeps.sh - name: Download copydlldeps.sh
shell: bash shell: bash
@ -1557,38 +1415,9 @@ jobs:
path: build/StrawberrySetup*.exe path: build/StrawberrySetup*.exe
rsync-windows-msvc-builds: upload:
name: Rsync Windows MSVC builds name: Upload
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci') if: github.repository == 'strawberrymusicplayer/strawberry' && (github.event_name == 'release' || (github.event_name == 'push' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')))
runs-on: ubuntu-latest
needs:
- build-windows-msvc
steps:
- name: Download artifacts
uses: actions/download-artifact@v4
with:
path: builds
pattern: windows-msvc-*
- name: View files
run: find builds
- name: SSH key setup
uses: shimataro/ssh-key-action@v2
with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{secrets.SSH_KEY}}
- name: Create server path
shell: bash
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci'
run: ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${{secrets.BUILDS_PATH}}/windows/msvc
- name: rsync
shell: bash
if: github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci'
run: rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var builds/*/StrawberrySetup-*-msvc-*.exe ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.BUILDS_PATH}}/windows/msvc/
upload-release:
name: Upload release
if: github.repository == 'strawberrymusicplayer/strawberry' && github.event.pull_request.head.repo.fork == false && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/ci')
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- build-opensuse - build-opensuse
@ -1598,55 +1427,78 @@ jobs:
- build-windows-mingw - build-windows-mingw
- build-windows-msvc - build-windows-msvc
steps: steps:
- name: Install packages - name: Install packages
env: env:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
run: sudo apt install -y git rsync hub run: sudo apt install -y git rsync
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Set is release
run: echo "is_release=$(grep '^\s*set\s*(\s*INCLUDE_GIT_REVISION\s\+OFF\s*)\s*$' cmake/Version.cmake >/dev/null 2>&1 && echo 1 || echo 0)" >> $GITHUB_ENV
- name: Get release version
run: echo "release_version=$(git describe --tags --exact-match ${GITHUB_SHA} 2>/dev/null | head -1)" >> $GITHUB_ENV
- name: Show release version
if: env.release_version != ''
run: echo "Release version:" ${{env.release_version}}
- name: Show release assets
if: env.release_version != ''
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: hub release show -f "%as" ${{env.release_version}}
- name: Download artifacts - name: Download artifacts
if: env.release_version != ''
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
path: artifacts path: artifacts
- name: SSH key setup - name: SSH key setup
if: env.release_version != ''
uses: shimataro/ssh-key-action@v2 uses: shimataro/ssh-key-action@v2
with: with:
known_hosts: ${{secrets.SSH_KNOWN_HOSTS}} known_hosts: ${{secrets.SSH_KNOWN_HOSTS}}
key: ${{secrets.SSH_KEY}} key: ${{secrets.SSH_KEY}}
- name: Upload
run: |
for i in $(find artifacts -type f); do
if [ "${{github.event_name}}" = "release" ]; then
upload_path="${{secrets.RELEASES_PATH}}/"
else
distro=$(echo "$i" | cut -d '/' -f 2)
if [ "$(echo "$i" | grep '-' || true)" = "" ]; then
upload_path="${{secrets.BUILDS_PATH}}/${distro}/"
else
distro_name=$(echo "${distro}" | cut -d '-' -f 1)
distro_version=$(echo "${distro}" | cut -d '-' -f 2)
upload_path="${{secrets.BUILDS_PATH}}/${distro_name}/${distro_version}/"
fi
fi
ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}} mkdir -p ${upload_path}
rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var $i ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${upload_path}/
done
attach:
name: Attach to release
if: github.event_name == 'release'
runs-on: ubuntu-latest
needs:
- build-opensuse
- build-fedora
- build-debian
- build-ubuntu
- build-windows-mingw
- build-windows-msvc
steps:
- name: Install packages
env:
DEBIAN_FRONTEND: noninteractive
run: sudo apt install -y git jq gh
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Show release assets
env:
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@v4
with:
path: artifacts
- name: Add artifacts to release - name: Add artifacts to release
if: env.is_release == '1' && env.release_version != ''
env: env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
run: | run: |
echo "Release version: ${{env.release_version}}" echo "Release version: ${{github.event.release.tag_name}}"
filenames=() filenames=()
files=() files=()
a_files=()
for i in $(find artifacts -type f); do for i in $(find artifacts -type f); do
filename=$(basename $i) filename=$(basename $i)
if [[ ${filenames[@]} =~ ${filename} ]]; then if [[ ${filenames[@]} =~ ${filename} ]]; then
@ -1654,22 +1506,16 @@ jobs:
continue continue
fi fi
filenames+=("${filename}") filenames+=("${filename}")
existing_asset=$(hub release show -f "%as" ${{env.release_version}} | tr -d '[:blank:]' | grep ".*/${filename}\$" 2>/dev/null || true) existing_asset=$(gh release view "${{github.event.release.tag_name}}" --json assets | jq -r '.assets[].name' | tr -d '[:blank:]' | grep ".*/${filename}\$" 2>/dev/null || true)
if [ "${existing_asset}" = "" ]; then if [ "${existing_asset}" = "" ]; then
echo "Adding file: ${filename}" echo "Adding file: ${filename}"
files+=("$i") files+=("${i}")
a_files+=("-a" "${i}")
else else
echo "Release already has file: ${filename}" echo "Release already has file: ${filename}"
fi fi
done done
files_list="${files[@]}" files_list="${files[@]}"
a_files_list="${a_files[@]}"
if ! [ "${files_list}" = "" ]; then if ! [ "${files_list}" = "" ]; then
echo "Uploading files: ${files_list}" echo "Adding files to GitHub release"
rsync -e "ssh -p ${{secrets.SSH_PORT}} -o StrictHostKeyChecking=no" -var ${files_list} ${{secrets.SSH_USER}}@${{secrets.SSH_HOST}}:${{secrets.RELEASES_PATH}}/ gh release upload "${{github.event.release.tag_name}}" ${files_list}
fi
if ! [ "${a_files_list}" = "" ]; then
echo "Adding files to GitHub release: ${files_list}"
hub release edit -m "Strawberry ${{env.release_version}}" ${a_files_list} "${{env.release_version}}"
fi fi

View File

@ -266,25 +266,19 @@ if(X11_FOUND)
endif(X11_FOUND) endif(X11_FOUND)
option(USE_TAGLIB "Build with TagLib" OFF) option(USE_TAGLIB "Build with TagLib" ON)
option(USE_TAGPARSER "Build with TagParser" OFF) option(USE_TAGPARSER "Build with TagParser" OFF)
if(NOT USE_TAGLIB AND NOT USE_TAGPARSER)
set(USE_TAGLIB ON)
endif()
# TAGLIB # TAGLIB
if(USE_TAGLIB) if(USE_TAGLIB)
pkg_check_modules(TAGLIB REQUIRED taglib>=1.11.1) find_package(TagLib 2.0)
if(TAGLIB_FOUND) if(TARGET TagLib::TagLib)
find_path(HAVE_TAGLIB_DSFFILE_H taglib/dsffile.h) set(TAGLIB_FOUND ON)
find_path(HAVE_TAGLIB_DSDIFFFILE_H taglib/dsdifffile.h) set(TAGLIB_LIBRARIES TagLib::TagLib)
if(HAVE_TAGLIB_DSFFILE_H)
set(HAVE_TAGLIB_DSFFILE ON) set(HAVE_TAGLIB_DSFFILE ON)
endif(HAVE_TAGLIB_DSFFILE_H)
if(HAVE_TAGLIB_DSDIFFFILE_H)
set(HAVE_TAGLIB_DSDIFFFILE ON) set(HAVE_TAGLIB_DSDIFFFILE ON)
endif(HAVE_TAGLIB_DSDIFFFILE_H) else()
pkg_check_modules(TAGLIB REQUIRED taglib>=1.11.1)
endif() endif()
endif() endif()

View File

@ -48,24 +48,27 @@ small as possible.
### Commit messages ### Commit messages
The first line should start with "Class:", which referer to the class The first line should start with the name of the class that is changed
that is changed. Don't use a trailing period after the first line. followed by a colon then a short explanation of the commit.
If this change affects more than one class, omit the class and write a Don't use a trailing period after the first line.
If this change affects more than one class, omit the class name and write a
more general message. more general message.
You only need to include a main description (body) for larger changes You only need to include a main description (body) for larger changes
where the one line is not enough to describe everything. where the one line is not enough to describe everything.
The main description starts after two newlines, it is normal prose and The main description starts after two newlines, it is normal prose and
should use normal punctuation and capital letters where appropriate. should use normal punctuation and capital letters where appropriate.
It should explain exactly what's changed, why it's changed,
and what bugs were fixed.
An example of the expected format for git commit messages is as follows: An example of the expected format for git commit messages is as follows:
``` ```
class: Short explanation of the commit StretchHeaderView: Set default section size
Longer explanation explaining exactly what's changed, why it's changed, As of Qt 6.6.1, style changes are resetting the column sizes. To prevent this, we set a default section size.
and what bugs were fixed.
Fixes #1234 Fixes #1328
``` ```

View File

@ -2,6 +2,36 @@ Strawberry Music Player
======================= =======================
ChangeLog ChangeLog
Unreleased:
Bugfixes:
* Fixed crash when pressing CTRL + C (#1359).
* Pass on scroll events to page in settings to avoid changing settings when scrolling with mouse (#1380).
* (macOS/Windows) Fixed dash and hls streaming, plugins were missing.
Enhancements:
* Improve error messages when connecting and copying to devices.
* Allow enter to be used with multiselection to add songs to playlist (#1360)
* Add song progress to taskbar using D-Bus.
* Use API to receive Radio Paradise channels.
* (Unix) Add experimental GStreamer pipewire support.
* (Windows) Add experimental exclusive mode for WASAPI.
* (Windows MSVC) Add ASIO support.
* (Windows MSVC) Add back WASAPI2.
Version 1.0.23 (2024.01.11):
Bugfixes:
* Fixed possible duplication of song entries after organizing (#1341).
* Fixed possible crash when connecting devices (#1313).
* Fixed playlist sorting of original year (#1349).
* (macOS) Fixed crash when adding collection directory (QTBUG-120469) (#1350).
Enhancements:
* Treat all stream errors as non-fatal (#1347).
* Require KDSingleApplication 1.1.0.
* Fix logging of restored unavailable songs.
Version 1.0.22 (2023.12.09): Version 1.0.22 (2023.12.09):
Bugfixes: Bugfixes:

View File

@ -32,9 +32,9 @@ Resources:
### :moneybag: Sponsoring ### :moneybag: Sponsoring
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. 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 3 options for sponsoring: There are currently 4 options for sponsoring:
1. [GitHub Sponsors](https://github.com/sponsors/jonaski) 1. [GitHub](https://github.com/sponsors/jonaski)
2. [Patreon](https://www.patreon.com/jonaskvinge) 2. [Patreon](https://www.patreon.com/jonaskvinge)
3. [Ko-fi](https://ko-fi.com/jonaskvinge) 3. [Ko-fi](https://ko-fi.com/jonaskvinge)
4. [PayPal](https://paypal.me/jonaskvinge) 4. [PayPal](https://paypal.me/jonaskvinge)
@ -54,7 +54,7 @@ Funding developers is a way to contribute to open source projects you appreciate
* Edit tags on audio files * Edit tags on audio files
* Fetch tags from MusicBrainz * 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/) * 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/) and [lyricsmode.com](https://www.lyricsmode.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/) and [elyrics.net](https://www.elyrics.net/)
* Support for multiple backends * Support for multiple backends
* Audio analyzer * Audio analyzer
* Audio equalizer * Audio equalizer
@ -65,7 +65,7 @@ Funding developers is a way to contribute to open source projects you appreciate
It has so far been tested to work on Linux, OpenBSD, FreeBSD, macOS and Windows. It has so far been tested to work on Linux, OpenBSD, FreeBSD, macOS and Windows.
**macOS releases are currently limited to sponsors. This is because macOS releases require a developer account, Apple hardware and maintaining all libraries strawberry depends on. If you are sponsoring strawberry, e-mail support@strawberrymusicplayer.org for access to downloads.** **macOS releases are currently limited to sponsors. This is because Strawberry mainly has one contributor/developer and supporting macOS requires Apple hardware, building libraries Strawberry depends and a Apple developer account for signing releases. If you are sponsoring strawberry through Patreon, releases are available directly on Patreon, if you are sponsoring through GitHub, Ko-fi or Paypal, please e-mail support@strawberrymusicplayer.org for access to downloads.**
### :heavy_exclamation_mark: Requirements ### :heavy_exclamation_mark: Requirements

View File

@ -1,21 +1,33 @@
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext) find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext REQUIRED)
if(NOT GETTEXT_XGETTEXT_EXECUTABLE) find_program(CAT_EXECUTABLE cat REQUIRED)
message(FATAL_ERROR "Could not find xgettext executable")
endif(NOT GETTEXT_XGETTEXT_EXECUTABLE)
set (XGETTEXT_OPTIONS list(APPEND XGETTEXT_OPTIONS
--qt --qt
--keyword=tr:1,2c --keyword=tr:1,2c
--keyword=tr --flag=tr:1:pass-c-format --flag=tr:1:pass-qt-format --keyword=tr
--keyword=trUtf8 --flag=tr:1:pass-c-format --flag=tr:1:pass-qt-format --flag=tr:1:pass-c-format
--flag=tr:1:pass-qt-format
--keyword=trUtf8
--flag=tr:1:pass-c-format
--flag=tr:1:pass-qt-format
--keyword=translate:2,3c --keyword=translate:2,3c
--keyword=translate:2 --flag=translate:2:pass-c-format --flag=translate:2:pass-qt-format --keyword=translate:2
--keyword=QT_TR_NOOP --flag=QT_TR_NOOP:1:pass-c-format --flag=QT_TR_NOOP:1:pass-qt-format --flag=translate:2:pass-c-format
--keyword=QT_TRANSLATE_NOOP:2 --flag=QT_TRANSLATE_NOOP:2:pass-c-format --flag=QT_TRANSLATE_NOOP:2:pass-qt-format --flag=translate:2:pass-qt-format
--keyword=_ --flag=_:1:pass-c-format --flag=_:1:pass-qt-format --keyword=QT_TR_NOOP
--keyword=N_ --flag=N_:1:pass-c-format --flag=N_:1:pass-qt-format --flag=QT_TR_NOOP:1:pass-c-format
--flag=QT_TR_NOOP:1:pass-qt-format
--keyword=QT_TRANSLATE_NOOP:2
--flag=QT_TRANSLATE_NOOP:2:pass-c-format
--flag=QT_TRANSLATE_NOOP:2:pass-qt-format
--keyword=_
--flag=_:1:pass-c-format
--flag=_:1:pass-qt-format
--keyword=N_
--flag=N_:1:pass-c-format
--flag=N_:1:pass-qt-format
--from-code=utf-8 --from-code=utf-8
) )
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/translations) execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/translations)
@ -32,7 +44,7 @@ macro(add_pot outfiles header pot)
add_custom_command( add_custom_command(
OUTPUT ${pot} OUTPUT ${pot}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND ${GETTEXT_XGETTEXT_EXECUTABLE} ${XGETTEXT_OPTIONS} -s -C --omit-header --output=${CMAKE_CURRENT_BINARY_DIR}/pot.temp ${add_pot_sources} COMMAND xgettext ${XGETTEXT_OPTIONS} -s -C --omit-header --output="${CMAKE_CURRENT_BINARY_DIR}/pot.temp" ${add_pot_sources}
COMMAND cat ${header} ${CMAKE_CURRENT_BINARY_DIR}/pot.temp > ${pot} COMMAND cat ${header} ${CMAKE_CURRENT_BINARY_DIR}/pot.temp > ${pot}
DEPENDS ${add_pot_sources} ${header} DEPENDS ${add_pot_sources} ${header}
) )

View File

@ -1,6 +1,6 @@
set(STRAWBERRY_VERSION_MAJOR 1) set(STRAWBERRY_VERSION_MAJOR 1)
set(STRAWBERRY_VERSION_MINOR 0) set(STRAWBERRY_VERSION_MINOR 0)
set(STRAWBERRY_VERSION_PATCH 22) set(STRAWBERRY_VERSION_PATCH 23)
#set(STRAWBERRY_VERSION_PRERELEASE rc1) #set(STRAWBERRY_VERSION_PRERELEASE rc1)
set(INCLUDE_GIT_REVISION ON) set(INCLUDE_GIT_REVISION ON)

View File

@ -35,32 +35,32 @@
background-color: %palette-base; background-color: %palette-base;
} }
QToolButton { QToolButton[accessibleName="MenuPopupToolButton"] {
border: 2px solid transparent; border: 2px solid transparent;
border-radius: 3px; border-radius: 3px;
padding: 1px; padding: 1px;
} }
QToolButton:hover { QToolButton:hover[accessibleName="MenuPopupToolButton"] {
border: 2px solid %palette-highlight; border: 2px solid %palette-highlight;
background-color: %palette-highlight-lighter; background-color: %palette-highlight-lighter;
} }
QToolButton:pressed { QToolButton:pressed[accessibleName="MenuPopupToolButton"] {
border: 2px solid %palette-highlight-darker; border: 2px solid %palette-highlight-darker;
background-color: %palette-highlight-lighter; background-color: %palette-highlight-lighter;
} }
QToolButton[popupMode="MenuButtonPopup"], QToolButton:hover[popupMode="MenuButtonPopup"], QToolButton:pressed[popupMode="MenuButtonPopup"] { QToolButton[popupMode="MenuButtonPopup"][accessibleName="MenuPopupToolButton"], QToolButton:hover[popupMode="MenuButtonPopup"][accessibleName="MenuPopupToolButton"], QToolButton:pressed[popupMode="MenuButtonPopup"][accessibleName="MenuPopupToolButton"] {
padding-right: 16px; padding-right: 16px;
} }
/* For backwards compatibility with Qt 5 as it does not support property name */ /* For backwards compatibility with Qt 5 as it does not support property name */
QToolButton[popupMode="1"], QToolButton:hover[popupMode="1"], QToolButton:pressed[popupMode="1"] { QToolButton[popupMode="1"][accessibleName="MenuPopupToolButton"], QToolButton:hover[popupMode="1"][accessibleName="MenuPopupToolButton"], QToolButton:pressed[popupMode="1"][accessibleName="MenuPopupToolButton"] {
padding-right: 16px; padding-right: 16px;
} }
QToolButton::menu-button { QToolButton::menu-button[accessibleName="MenuPopupToolButton"] {
width: 16px; width: 16px;
border: none; border: none;
} }

2
debian/control.in vendored
View File

@ -53,7 +53,7 @@ Description: music player and music collection organizer
- Edit tags on audio files - Edit tags on audio files
- Automatically retrieve tags from MusicBrainz - Automatically retrieve tags from MusicBrainz
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify - 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 and lyricsmode.com - Song lyrics from Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com and elyrics.net
- Audio analyzer - Audio analyzer
- Audio equalizer - Audio equalizer
- Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic - Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic

View File

@ -62,6 +62,7 @@ cp -v -f "${GST_PLUGIN_SCANNER}" "${bundledir}/Contents/PlugIns/" || exit 1
install_name_tool -add_rpath "@loader_path/../Frameworks" "${bundledir}/Contents/PlugIns/$(basename ${GST_PLUGIN_SCANNER})" || exit 1 install_name_tool -add_rpath "@loader_path/../Frameworks" "${bundledir}/Contents/PlugIns/$(basename ${GST_PLUGIN_SCANNER})" || exit 1
gst_plugins=" gst_plugins="
libgstadaptivedemux2
libgstaes libgstaes
libgstaiff libgstaiff
libgstapetag libgstapetag
@ -70,16 +71,14 @@ libgstasf
libgstasfmux libgstasfmux
libgstaudioconvert libgstaudioconvert
libgstaudiofx libgstaudiofx
libgstaudiomixer
libgstaudioparsers libgstaudioparsers
libgstaudiorate
libgstaudioresample libgstaudioresample
libgstaudiotestsrc
libgstautodetect libgstautodetect
libgstbs2b libgstbs2b
libgstcdio libgstcdio
libgstcoreelements libgstcoreelements
libgstdash libgstdash
libgstdsd
libgstequalizer libgstequalizer
libgstfaac libgstfaac
libgstfaad libgstfaad
@ -92,6 +91,10 @@ libgstid3demux
libgstid3tag libgstid3tag
libgstisomp4 libgstisomp4
libgstlame libgstlame
libgstmpegpsdemux
libgstmpegpsmux
libgstmpegtsdemux
libgstmpegtsmux
libgstlibav libgstlibav
libgstmpg123 libgstmpg123
libgstmusepack libgstmusepack

View File

@ -29,7 +29,7 @@
<li>Edit tags on audio files</li> <li>Edit tags on audio files</li>
<li>Automatically retrieve tags from MusicBrainz</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>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 and lyricsmode.com</li> <li>Song lyrics from Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com and elyrics.net</li>
<li>Support for multiple backends</li> <li>Support for multiple backends</li>
<li>Audio analyzer and equalizer</li> <li>Audio analyzer and equalizer</li>
<li>Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic</li> <li>Transfer music to mass-storage USB players, MTP compatible devices and iPod Nano/Classic</li>
@ -50,6 +50,7 @@
</screenshots> </screenshots>
<update_contact>eclipseo@fedoraproject.org</update_contact> <update_contact>eclipseo@fedoraproject.org</update_contact>
<releases> <releases>
<release version="1.0.23" date="2024-01-11"/>
<release version="1.0.22" date="2023-12-09"/> <release version="1.0.22" date="2023-12-09"/>
<release version="1.0.21" date="2023-10-21"/> <release version="1.0.21" date="2023-10-21"/>
<release version="1.0.20" date="2023-09-24"/> <release version="1.0.20" date="2023-09-24"/>

View File

@ -99,7 +99,7 @@ Features:
- Edit tags on audio files - Edit tags on audio files
- Automatically retrieve tags from MusicBrainz - Automatically retrieve tags from MusicBrainz
- Album cover art from Last.fm, Musicbrainz, Discogs, Musixmatch, Deezer, Tidal, Qobuz and Spotify - 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 and lyricsmode.com - Song lyrics from Genius, Musixmatch, ChartLyrics, lyrics.ovh, lololyrics.com, songlyrics.com, azlyrics.com and elyrics.net
- Support for multiple backends - Support for multiple backends
- Audio analyzer - Audio analyzer
- Audio equalizer - Audio equalizer

View File

@ -282,8 +282,10 @@ Section "Strawberry" Strawberry
File "libgstaudio-1.0-0.dll" File "libgstaudio-1.0-0.dll"
File "libgstbadaudio-1.0-0.dll" File "libgstbadaudio-1.0-0.dll"
File "libgstbase-1.0-0.dll" File "libgstbase-1.0-0.dll"
File "libgstcodecparsers-1.0-0.dll"
File "libgstfft-1.0-0.dll" File "libgstfft-1.0-0.dll"
File "libgstisoff-1.0-0.dll" File "libgstisoff-1.0-0.dll"
File "libgstmpegts-1.0-0.dll"
File "libgstnet-1.0-0.dll" File "libgstnet-1.0-0.dll"
File "libgstpbutils-1.0-0.dll" File "libgstpbutils-1.0-0.dll"
File "libgstreamer-1.0-0.dll" File "libgstreamer-1.0-0.dll"
@ -422,8 +424,10 @@ Section "Strawberry" Strawberry
File "gstaudio-1.0-0.dll" File "gstaudio-1.0-0.dll"
File "gstbadaudio-1.0-0.dll" File "gstbadaudio-1.0-0.dll"
File "gstbase-1.0-0.dll" File "gstbase-1.0-0.dll"
File "gstcodecparsers-1.0-0.dll"
File "gstfft-1.0-0.dll" File "gstfft-1.0-0.dll"
File "gstisoff-1.0-0.dll" File "gstisoff-1.0-0.dll"
File "gstmpegts-1.0-0.dll"
File "gstnet-1.0-0.dll" File "gstnet-1.0-0.dll"
File "gstpbutils-1.0-0.dll" File "gstpbutils-1.0-0.dll"
File "gstreamer-1.0-0.dll" File "gstreamer-1.0-0.dll"
@ -627,6 +631,7 @@ Section "Gstreamer plugins" gstreamer-plugins
SetOutPath "$INSTDIR\gstreamer-plugins" SetOutPath "$INSTDIR\gstreamer-plugins"
!ifdef mingw !ifdef mingw
File "/oname=libgstadaptivedemux2.dll" "gstreamer-plugins\libgstadaptivedemux2.dll"
File "/oname=libgstaes.dll" "gstreamer-plugins\libgstaes.dll" File "/oname=libgstaes.dll" "gstreamer-plugins\libgstaes.dll"
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll" File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll" File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
@ -635,16 +640,14 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=libgstasfmux.dll" "gstreamer-plugins\libgstasfmux.dll" File "/oname=libgstasfmux.dll" "gstreamer-plugins\libgstasfmux.dll"
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll" File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll" File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
File "/oname=libgstaudiomixer.dll" "gstreamer-plugins\libgstaudiomixer.dll"
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll" File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
File "/oname=libgstaudiorate.dll" "gstreamer-plugins\libgstaudiorate.dll"
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll" File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll" File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
File "/oname=libgstbs2b.dll" "gstreamer-plugins\libgstbs2b.dll" File "/oname=libgstbs2b.dll" "gstreamer-plugins\libgstbs2b.dll"
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll" File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
File "/oname=libgstdash.dll" "gstreamer-plugins\libgstdash.dll" File "/oname=libgstdash.dll" "gstreamer-plugins\libgstdash.dll"
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll" File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
File "/oname=libgstdsd.dll" "gstreamer-plugins\libgstdsd.dll"
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll" File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
File "/oname=libgstfaac.dll" "gstreamer-plugins\libgstfaac.dll" File "/oname=libgstfaac.dll" "gstreamer-plugins\libgstfaac.dll"
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll" File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
@ -659,6 +662,10 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll" File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll" File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll" File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
File "/oname=libgstmpegpsdemux.dll" "gstreamer-plugins\libgstmpegpsdemux.dll"
File "/oname=libgstmpegpsmux.dll" "gstreamer-plugins\libgstmpegpsmux.dll"
File "/oname=libgstmpegtsdemux.dll" "gstreamer-plugins\libgstmpegtsdemux.dll"
File "/oname=libgstmpegtsmux.dll" "gstreamer-plugins\libgstmpegtsmux.dll"
File "/oname=libgstmpg123.dll" "gstreamer-plugins\libgstmpg123.dll" File "/oname=libgstmpg123.dll" "gstreamer-plugins\libgstmpg123.dll"
File "/oname=libgstmusepack.dll" "gstreamer-plugins\libgstmusepack.dll" File "/oname=libgstmusepack.dll" "gstreamer-plugins\libgstmusepack.dll"
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll" File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
@ -681,6 +688,7 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll" File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll" File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
File "/oname=libgstwasapi.dll" "gstreamer-plugins\libgstwasapi.dll" File "/oname=libgstwasapi.dll" "gstreamer-plugins\libgstwasapi.dll"
File "/oname=libgstwaveform.dll" "gstreamer-plugins\libgstwaveform.dll"
File "/oname=libgstwavenc.dll" "gstreamer-plugins\libgstwavenc.dll" File "/oname=libgstwavenc.dll" "gstreamer-plugins\libgstwavenc.dll"
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll" File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll" File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
@ -688,24 +696,24 @@ Section "Gstreamer plugins" gstreamer-plugins
!endif ; MinGW !endif ; MinGW
!ifdef msvc !ifdef msvc
File "/oname=gstadaptivedemux2.dll" "gstreamer-plugins\gstadaptivedemux2.dll"
File "/oname=gstaes.dll" "gstreamer-plugins\gstaes.dll" File "/oname=gstaes.dll" "gstreamer-plugins\gstaes.dll"
File "/oname=gstaiff.dll" "gstreamer-plugins\gstaiff.dll" File "/oname=gstaiff.dll" "gstreamer-plugins\gstaiff.dll"
File "/oname=gstapetag.dll" "gstreamer-plugins\gstapetag.dll" File "/oname=gstapetag.dll" "gstreamer-plugins\gstapetag.dll"
File "/oname=gstapp.dll" "gstreamer-plugins\gstapp.dll" File "/oname=gstapp.dll" "gstreamer-plugins\gstapp.dll"
File "/oname=gstasf.dll" "gstreamer-plugins\gstasf.dll" File "/oname=gstasf.dll" "gstreamer-plugins\gstasf.dll"
File "/oname=gstasfmux.dll" "gstreamer-plugins\gstasfmux.dll" File "/oname=gstasfmux.dll" "gstreamer-plugins\gstasfmux.dll"
File "/oname=gstasio.dll" "gstreamer-plugins\gstasio.dll"
File "/oname=gstaudioconvert.dll" "gstreamer-plugins\gstaudioconvert.dll" File "/oname=gstaudioconvert.dll" "gstreamer-plugins\gstaudioconvert.dll"
File "/oname=gstaudiofx.dll" "gstreamer-plugins\gstaudiofx.dll" File "/oname=gstaudiofx.dll" "gstreamer-plugins\gstaudiofx.dll"
File "/oname=gstaudiomixer.dll" "gstreamer-plugins\gstaudiomixer.dll"
File "/oname=gstaudioparsers.dll" "gstreamer-plugins\gstaudioparsers.dll" File "/oname=gstaudioparsers.dll" "gstreamer-plugins\gstaudioparsers.dll"
File "/oname=gstaudiorate.dll" "gstreamer-plugins\gstaudiorate.dll"
File "/oname=gstaudioresample.dll" "gstreamer-plugins\gstaudioresample.dll" File "/oname=gstaudioresample.dll" "gstreamer-plugins\gstaudioresample.dll"
File "/oname=gstaudiotestsrc.dll" "gstreamer-plugins\gstaudiotestsrc.dll"
File "/oname=gstautodetect.dll" "gstreamer-plugins\gstautodetect.dll" File "/oname=gstautodetect.dll" "gstreamer-plugins\gstautodetect.dll"
File "/oname=gstbs2b.dll" "gstreamer-plugins\gstbs2b.dll" File "/oname=gstbs2b.dll" "gstreamer-plugins\gstbs2b.dll"
File "/oname=gstcoreelements.dll" "gstreamer-plugins\gstcoreelements.dll" File "/oname=gstcoreelements.dll" "gstreamer-plugins\gstcoreelements.dll"
File "/oname=gstdash.dll" "gstreamer-plugins\gstdash.dll" File "/oname=gstdash.dll" "gstreamer-plugins\gstdash.dll"
File "/oname=gstdirectsound.dll" "gstreamer-plugins\gstdirectsound.dll" File "/oname=gstdirectsound.dll" "gstreamer-plugins\gstdirectsound.dll"
File "/oname=gstdsd.dll" "gstreamer-plugins\gstdsd.dll"
File "/oname=gstequalizer.dll" "gstreamer-plugins\gstequalizer.dll" File "/oname=gstequalizer.dll" "gstreamer-plugins\gstequalizer.dll"
File "/oname=gstfaac.dll" "gstreamer-plugins\gstfaac.dll" File "/oname=gstfaac.dll" "gstreamer-plugins\gstfaac.dll"
File "/oname=gstfaad.dll" "gstreamer-plugins\gstfaad.dll" File "/oname=gstfaad.dll" "gstreamer-plugins\gstfaad.dll"
@ -720,6 +728,10 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=gstisomp4.dll" "gstreamer-plugins\gstisomp4.dll" File "/oname=gstisomp4.dll" "gstreamer-plugins\gstisomp4.dll"
File "/oname=gstlame.dll" "gstreamer-plugins\gstlame.dll" File "/oname=gstlame.dll" "gstreamer-plugins\gstlame.dll"
File "/oname=gstlibav.dll" "gstreamer-plugins\gstlibav.dll" File "/oname=gstlibav.dll" "gstreamer-plugins\gstlibav.dll"
File "/oname=gstmpegpsdemux.dll" "gstreamer-plugins\gstmpegpsdemux.dll"
File "/oname=gstmpegpsmux.dll" "gstreamer-plugins\gstmpegpsmux.dll"
File "/oname=gstmpegtsdemux.dll" "gstreamer-plugins\gstmpegtsdemux.dll"
File "/oname=gstmpegtsmux.dll" "gstreamer-plugins\gstmpegtsmux.dll"
File "/oname=gstmpg123.dll" "gstreamer-plugins\gstmpg123.dll" File "/oname=gstmpg123.dll" "gstreamer-plugins\gstmpg123.dll"
File "/oname=gstmusepack.dll" "gstreamer-plugins\gstmusepack.dll" File "/oname=gstmusepack.dll" "gstreamer-plugins\gstmusepack.dll"
File "/oname=gstogg.dll" "gstreamer-plugins\gstogg.dll" File "/oname=gstogg.dll" "gstreamer-plugins\gstogg.dll"
@ -742,8 +754,8 @@ Section "Gstreamer plugins" gstreamer-plugins
File "/oname=gstvolume.dll" "gstreamer-plugins\gstvolume.dll" File "/oname=gstvolume.dll" "gstreamer-plugins\gstvolume.dll"
File "/oname=gstvorbis.dll" "gstreamer-plugins\gstvorbis.dll" File "/oname=gstvorbis.dll" "gstreamer-plugins\gstvorbis.dll"
File "/oname=gstwasapi.dll" "gstreamer-plugins\gstwasapi.dll" File "/oname=gstwasapi.dll" "gstreamer-plugins\gstwasapi.dll"
; Disable wasapi2 until issue (https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2870) is fixed. File "/oname=gstwasapi2.dll" "gstreamer-plugins\gstwasapi2.dll"
;File "/oname=gstwasapi2.dll" "gstreamer-plugins\gstwasapi2.dll" File "/oname=gstwaveform.dll" "gstreamer-plugins\gstwaveform.dll"
File "/oname=gstwavenc.dll" "gstreamer-plugins\gstwavenc.dll" File "/oname=gstwavenc.dll" "gstreamer-plugins\gstwavenc.dll"
File "/oname=gstwavpack.dll" "gstreamer-plugins\gstwavpack.dll" File "/oname=gstwavpack.dll" "gstreamer-plugins\gstwavpack.dll"
File "/oname=gstwavparse.dll" "gstreamer-plugins\gstwavparse.dll" File "/oname=gstwavparse.dll" "gstreamer-plugins\gstwavparse.dll"
@ -839,8 +851,10 @@ Section "Uninstall"
Delete "$INSTDIR\libgstaudio-1.0-0.dll" Delete "$INSTDIR\libgstaudio-1.0-0.dll"
Delete "$INSTDIR\libgstbadaudio-1.0-0.dll" Delete "$INSTDIR\libgstbadaudio-1.0-0.dll"
Delete "$INSTDIR\libgstbase-1.0-0.dll" Delete "$INSTDIR\libgstbase-1.0-0.dll"
Delete "$INSTDIR\libgstcodecparsers-1.0-0.dll"
Delete "$INSTDIR\libgstfft-1.0-0.dll" Delete "$INSTDIR\libgstfft-1.0-0.dll"
Delete "$INSTDIR\libgstisoff-1.0-0.dll" Delete "$INSTDIR\libgstisoff-1.0-0.dll"
Delete "$INSTDIR\libgstmpegts-1.0-0.dll"
Delete "$INSTDIR\libgstnet-1.0-0.dll" Delete "$INSTDIR\libgstnet-1.0-0.dll"
Delete "$INSTDIR\libgstpbutils-1.0-0.dll" Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
Delete "$INSTDIR\libgstreamer-1.0-0.dll" Delete "$INSTDIR\libgstreamer-1.0-0.dll"
@ -979,8 +993,10 @@ Section "Uninstall"
Delete "$INSTDIR\gstaudio-1.0-0.dll" Delete "$INSTDIR\gstaudio-1.0-0.dll"
Delete "$INSTDIR\gstbadaudio-1.0-0.dll" Delete "$INSTDIR\gstbadaudio-1.0-0.dll"
Delete "$INSTDIR\gstbase-1.0-0.dll" Delete "$INSTDIR\gstbase-1.0-0.dll"
Delete "$INSTDIR\gstcodecparsers-1.0-0.dll"
Delete "$INSTDIR\gstfft-1.0-0.dll" Delete "$INSTDIR\gstfft-1.0-0.dll"
Delete "$INSTDIR\gstisoff-1.0-0.dll" Delete "$INSTDIR\gstisoff-1.0-0.dll"
Delete "$INSTDIR\gstmpegts-1.0-0.dll"
Delete "$INSTDIR\gstnet-1.0-0.dll" Delete "$INSTDIR\gstnet-1.0-0.dll"
Delete "$INSTDIR\gstpbutils-1.0-0.dll" Delete "$INSTDIR\gstpbutils-1.0-0.dll"
Delete "$INSTDIR\gstreamer-1.0-0.dll" Delete "$INSTDIR\gstreamer-1.0-0.dll"
@ -1116,6 +1132,7 @@ Section "Uninstall"
; MinGW GStreamer plugins ; MinGW GStreamer plugins
!ifdef mingw !ifdef mingw
Delete "$INSTDIR\gstreamer-plugins\libgstadaptivedemux2.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaes.dll" Delete "$INSTDIR\gstreamer-plugins\libgstaes.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll" Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll" Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
@ -1124,16 +1141,14 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\libgstasfmux.dll" Delete "$INSTDIR\gstreamer-plugins\libgstasfmux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll" Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll" Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiomixer.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll" Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiorate.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll" Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll" Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstbs2b.dll" Delete "$INSTDIR\gstreamer-plugins\libgstbs2b.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll" Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdash.dll" Delete "$INSTDIR\gstreamer-plugins\libgstdash.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll" Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstdsd.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll" Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfaac.dll" Delete "$INSTDIR\gstreamer-plugins\libgstfaac.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll" Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
@ -1148,6 +1163,10 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll" Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll" Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll" Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmpegpsdemux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmpegpsmux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmpegtsdemux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmpegtsmux.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmpg123.dll" Delete "$INSTDIR\gstreamer-plugins\libgstmpg123.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstmusepack.dll" Delete "$INSTDIR\gstreamer-plugins\libgstmusepack.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll" Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
@ -1170,6 +1189,7 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll" Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll" Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwasapi.dll" Delete "$INSTDIR\gstreamer-plugins\libgstwasapi.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwaveform.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavenc.dll" Delete "$INSTDIR\gstreamer-plugins\libgstwavenc.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll" Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll" Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
@ -1179,24 +1199,24 @@ Section "Uninstall"
; MSVC GStreamer plugins ; MSVC GStreamer plugins
!ifdef msvc !ifdef msvc
Delete "$INSTDIR\gstreamer-plugins\gstadaptivedemux2.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaes.dll" Delete "$INSTDIR\gstreamer-plugins\gstaes.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaiff.dll" Delete "$INSTDIR\gstreamer-plugins\gstaiff.dll"
Delete "$INSTDIR\gstreamer-plugins\gstapetag.dll" Delete "$INSTDIR\gstreamer-plugins\gstapetag.dll"
Delete "$INSTDIR\gstreamer-plugins\gstapp.dll" Delete "$INSTDIR\gstreamer-plugins\gstapp.dll"
Delete "$INSTDIR\gstreamer-plugins\gstasf.dll" Delete "$INSTDIR\gstreamer-plugins\gstasf.dll"
Delete "$INSTDIR\gstreamer-plugins\gstasfmux.dll" Delete "$INSTDIR\gstreamer-plugins\gstasfmux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstasio.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudioconvert.dll" Delete "$INSTDIR\gstreamer-plugins\gstaudioconvert.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudiofx.dll" Delete "$INSTDIR\gstreamer-plugins\gstaudiofx.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudiomixer.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudioparsers.dll" Delete "$INSTDIR\gstreamer-plugins\gstaudioparsers.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudiorate.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudioresample.dll" Delete "$INSTDIR\gstreamer-plugins\gstaudioresample.dll"
Delete "$INSTDIR\gstreamer-plugins\gstaudiotestsrc.dll"
Delete "$INSTDIR\gstreamer-plugins\gstautodetect.dll" Delete "$INSTDIR\gstreamer-plugins\gstautodetect.dll"
Delete "$INSTDIR\gstreamer-plugins\gstbs2b.dll" Delete "$INSTDIR\gstreamer-plugins\gstbs2b.dll"
Delete "$INSTDIR\gstreamer-plugins\gstcoreelements.dll" Delete "$INSTDIR\gstreamer-plugins\gstcoreelements.dll"
Delete "$INSTDIR\gstreamer-plugins\gstdash.dll" Delete "$INSTDIR\gstreamer-plugins\gstdash.dll"
Delete "$INSTDIR\gstreamer-plugins\gstdirectsound.dll" Delete "$INSTDIR\gstreamer-plugins\gstdirectsound.dll"
Delete "$INSTDIR\gstreamer-plugins\gstdsd.dll"
Delete "$INSTDIR\gstreamer-plugins\gstequalizer.dll" Delete "$INSTDIR\gstreamer-plugins\gstequalizer.dll"
Delete "$INSTDIR\gstreamer-plugins\gstfaac.dll" Delete "$INSTDIR\gstreamer-plugins\gstfaac.dll"
Delete "$INSTDIR\gstreamer-plugins\gstfaad.dll" Delete "$INSTDIR\gstreamer-plugins\gstfaad.dll"
@ -1211,6 +1231,10 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\gstisomp4.dll" Delete "$INSTDIR\gstreamer-plugins\gstisomp4.dll"
Delete "$INSTDIR\gstreamer-plugins\gstlame.dll" Delete "$INSTDIR\gstreamer-plugins\gstlame.dll"
Delete "$INSTDIR\gstreamer-plugins\gstlibav.dll" Delete "$INSTDIR\gstreamer-plugins\gstlibav.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmpegpsdemux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmpegpsmux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmpegtsdemux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmpegtsmux.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmpg123.dll" Delete "$INSTDIR\gstreamer-plugins\gstmpg123.dll"
Delete "$INSTDIR\gstreamer-plugins\gstmusepack.dll" Delete "$INSTDIR\gstreamer-plugins\gstmusepack.dll"
Delete "$INSTDIR\gstreamer-plugins\gstogg.dll" Delete "$INSTDIR\gstreamer-plugins\gstogg.dll"
@ -1234,6 +1258,7 @@ Section "Uninstall"
Delete "$INSTDIR\gstreamer-plugins\gstvorbis.dll" Delete "$INSTDIR\gstreamer-plugins\gstvorbis.dll"
Delete "$INSTDIR\gstreamer-plugins\gstwasapi.dll" Delete "$INSTDIR\gstreamer-plugins\gstwasapi.dll"
Delete "$INSTDIR\gstreamer-plugins\gstwasapi2.dll" Delete "$INSTDIR\gstreamer-plugins\gstwasapi2.dll"
Delete "$INSTDIR\gstreamer-plugins\gstwaveform.dll"
Delete "$INSTDIR\gstreamer-plugins\gstwavenc.dll" Delete "$INSTDIR\gstreamer-plugins\gstwavenc.dll"
Delete "$INSTDIR\gstreamer-plugins\gstwavpack.dll" Delete "$INSTDIR\gstreamer-plugins\gstwavpack.dll"
Delete "$INSTDIR\gstreamer-plugins\gstwavparse.dll" Delete "$INSTDIR\gstreamer-plugins\gstwavparse.dll"

View File

@ -188,7 +188,7 @@ set(SOURCES
lyrics/songlyricscomlyricsprovider.cpp lyrics/songlyricscomlyricsprovider.cpp
lyrics/azlyricscomlyricsprovider.cpp lyrics/azlyricscomlyricsprovider.cpp
lyrics/elyricsnetlyricsprovider.cpp lyrics/elyricsnetlyricsprovider.cpp
lyrics/lyricsmodecomlyricsprovider.cpp lyrics/letraslyricsprovider.cpp
providers/musixmatchprovider.cpp providers/musixmatchprovider.cpp
@ -439,7 +439,7 @@ set(HEADERS
lyrics/songlyricscomlyricsprovider.h lyrics/songlyricscomlyricsprovider.h
lyrics/azlyricscomlyricsprovider.h lyrics/azlyricscomlyricsprovider.h
lyrics/elyricsnetlyricsprovider.h lyrics/elyricsnetlyricsprovider.h
lyrics/lyricsmodecomlyricsprovider.h lyrics/letraslyricsprovider.h
settings/settingsdialog.h settings/settingsdialog.h
settings/settingspage.h settings/settingspage.h
@ -867,7 +867,7 @@ optional_source(WIN32
HEADERS HEADERS
core/windows7thumbbar.h core/windows7thumbbar.h
) )
optional_source(MSVC SOURCES engine/uwpdevicefinder.cpp) optional_source(MSVC SOURCES engine/uwpdevicefinder.cpp engine/asiodevicefinder.cpp)
optional_source(HAVE_SUBSONIC optional_source(HAVE_SUBSONIC
SOURCES SOURCES

View File

@ -38,6 +38,9 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="options"> <widget class="QToolButton" name="options">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>16</width> <width>16</width>

View File

@ -86,6 +86,7 @@ CollectionModel::CollectionModel(SharedPtr<CollectionBackend> backend, Applicati
app_(app), app_(app),
dir_model_(new CollectionDirectoryModel(backend, this)), dir_model_(new CollectionDirectoryModel(backend, this)),
show_various_artists_(true), show_various_artists_(true),
sort_skips_articles_(true),
total_song_count_(0), total_song_count_(0),
total_artist_count_(0), total_artist_count_(0),
total_album_count_(0), total_album_count_(0),
@ -163,6 +164,15 @@ void CollectionModel::set_show_dividers(const bool show_dividers) {
} }
void CollectionModel::set_sort_skips_articles(const bool sort_skips_articles) {
if (sort_skips_articles != sort_skips_articles_) {
sort_skips_articles_ = sort_skips_articles;
Reset();
}
}
void CollectionModel::ReloadSettings() { void CollectionModel::ReloadSettings() {
QSettings s; QSettings s;
@ -1242,14 +1252,14 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
item->metadata.set_albumartist(row.value(0).toString()); item->metadata.set_albumartist(row.value(0).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.albumartist()); item->display_text = TextOrUnknown(item->metadata.albumartist());
item->sort_text = SortTextForArtist(item->metadata.albumartist()); item->sort_text = SortTextForArtist(item->metadata.albumartist(), sort_skips_articles_);
break; break;
} }
case GroupBy::Artist:{ case GroupBy::Artist:{
item->metadata.set_artist(row.value(0).toString()); item->metadata.set_artist(row.value(0).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.artist()); item->display_text = TextOrUnknown(item->metadata.artist());
item->sort_text = SortTextForArtist(item->metadata.artist()); item->sort_text = SortTextForArtist(item->metadata.artist(), sort_skips_articles_);
break; break;
} }
case GroupBy::Album:{ case GroupBy::Album:{
@ -1258,7 +1268,7 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
item->metadata.set_grouping(row.value(2).toString()); item->metadata.set_grouping(row.value(2).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.album()); item->display_text = TextOrUnknown(item->metadata.album());
item->sort_text = SortTextForArtist(item->metadata.album()); item->sort_text = SortTextForArtist(item->metadata.album(), sort_skips_articles_);
break; break;
} }
case GroupBy::AlbumDisc:{ case GroupBy::AlbumDisc:{
@ -1343,28 +1353,28 @@ CollectionItem *CollectionModel::ItemFromQuery(const GroupBy group_by, const boo
item->metadata.set_genre(row.value(0).toString()); item->metadata.set_genre(row.value(0).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.genre()); item->display_text = TextOrUnknown(item->metadata.genre());
item->sort_text = SortTextForArtist(item->metadata.genre()); item->sort_text = SortTextForArtist(item->metadata.genre(), sort_skips_articles_);
break; break;
} }
case GroupBy::Composer:{ case GroupBy::Composer:{
item->metadata.set_composer(row.value(0).toString()); item->metadata.set_composer(row.value(0).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.composer()); item->display_text = TextOrUnknown(item->metadata.composer());
item->sort_text = SortTextForArtist(item->metadata.composer()); item->sort_text = SortTextForArtist(item->metadata.composer(), sort_skips_articles_);
break; break;
} }
case GroupBy::Performer:{ case GroupBy::Performer:{
item->metadata.set_performer(row.value(0).toString()); item->metadata.set_performer(row.value(0).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.performer()); item->display_text = TextOrUnknown(item->metadata.performer());
item->sort_text = SortTextForArtist(item->metadata.performer()); item->sort_text = SortTextForArtist(item->metadata.performer(), sort_skips_articles_);
break; break;
} }
case GroupBy::Grouping:{ case GroupBy::Grouping:{
item->metadata.set_grouping(row.value(0).toString()); item->metadata.set_grouping(row.value(0).toString());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, item->metadata));
item->display_text = TextOrUnknown(item->metadata.grouping()); item->display_text = TextOrUnknown(item->metadata.grouping());
item->sort_text = SortTextForArtist(item->metadata.grouping()); item->sort_text = SortTextForArtist(item->metadata.grouping(), sort_skips_articles_);
break; break;
} }
case GroupBy::FileType:{ case GroupBy::FileType:{
@ -1441,14 +1451,14 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
item->metadata.set_albumartist(s.effective_albumartist()); item->metadata.set_albumartist(s.effective_albumartist());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.effective_albumartist()); item->display_text = TextOrUnknown(s.effective_albumartist());
item->sort_text = SortTextForArtist(s.effective_albumartist()); item->sort_text = SortTextForArtist(s.effective_albumartist(), sort_skips_articles_);
break; break;
} }
case GroupBy::Artist:{ case GroupBy::Artist:{
item->metadata.set_artist(s.artist()); item->metadata.set_artist(s.artist());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.artist()); item->display_text = TextOrUnknown(s.artist());
item->sort_text = SortTextForArtist(s.artist()); item->sort_text = SortTextForArtist(s.artist(), sort_skips_articles_);
break; break;
} }
case GroupBy::Album:{ case GroupBy::Album:{
@ -1457,7 +1467,7 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
item->metadata.set_grouping(s.grouping()); item->metadata.set_grouping(s.grouping());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.album()); item->display_text = TextOrUnknown(s.album());
item->sort_text = SortTextForArtist(s.album()); item->sort_text = SortTextForArtist(s.album(), sort_skips_articles_);
break; break;
} }
case GroupBy::AlbumDisc:{ case GroupBy::AlbumDisc:{
@ -1542,28 +1552,28 @@ CollectionItem *CollectionModel::ItemFromSong(const GroupBy group_by, const bool
item->metadata.set_genre(s.genre()); item->metadata.set_genre(s.genre());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.genre()); item->display_text = TextOrUnknown(s.genre());
item->sort_text = SortTextForArtist(s.genre()); item->sort_text = SortTextForArtist(s.genre(), sort_skips_articles_);
break; break;
} }
case GroupBy::Composer:{ case GroupBy::Composer:{
item->metadata.set_composer(s.composer()); item->metadata.set_composer(s.composer());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.composer()); item->display_text = TextOrUnknown(s.composer());
item->sort_text = SortTextForArtist(s.composer()); item->sort_text = SortTextForArtist(s.composer(), sort_skips_articles_);
break; break;
} }
case GroupBy::Performer:{ case GroupBy::Performer:{
item->metadata.set_performer(s.performer()); item->metadata.set_performer(s.performer());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.performer()); item->display_text = TextOrUnknown(s.performer());
item->sort_text = SortTextForArtist(s.performer()); item->sort_text = SortTextForArtist(s.performer(), sort_skips_articles_);
break; break;
} }
case GroupBy::Grouping:{ case GroupBy::Grouping:{
item->metadata.set_grouping(s.grouping()); item->metadata.set_grouping(s.grouping());
item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s)); item->key.append(ContainerKey(group_by, separate_albums_by_grouping, s));
item->display_text = TextOrUnknown(s.grouping()); item->display_text = TextOrUnknown(s.grouping());
item->sort_text = SortTextForArtist(s.grouping()); item->sort_text = SortTextForArtist(s.grouping(), sort_skips_articles_);
break; break;
} }
case GroupBy::FileType:{ case GroupBy::FileType:{
@ -1681,7 +1691,7 @@ QString CollectionModel::PrettyYearAlbum(const int year, const QString &album) {
QString CollectionModel::PrettyAlbumDisc(const QString &album, const int disc) { QString CollectionModel::PrettyAlbumDisc(const QString &album, const int disc) {
if (disc <= 0 || album.contains(Song::kAlbumRemoveDisc)) return TextOrUnknown(album); if (disc <= 0 || Song::AlbumContainsDisc(album)) return TextOrUnknown(album);
else return TextOrUnknown(album) + " - (Disc " + QString::number(disc) + ")"; else return TextOrUnknown(album) + " - (Disc " + QString::number(disc) + ")";
} }
@ -1693,7 +1703,7 @@ QString CollectionModel::PrettyYearAlbumDisc(const int year, const QString &albu
if (year <= 0) str = TextOrUnknown(album); if (year <= 0) str = TextOrUnknown(album);
else str = QString::number(year) + " - " + TextOrUnknown(album); else str = QString::number(year) + " - " + TextOrUnknown(album);
if (!album.contains(Song::kAlbumRemoveDisc) && disc > 0) str += " - (Disc " + QString::number(disc) + ")"; if (!Song::AlbumContainsDisc(album) && disc > 0) str += " - (Disc " + QString::number(disc) + ")";
return str; return str;
@ -1719,10 +1729,11 @@ QString CollectionModel::SortText(QString text) {
} }
QString CollectionModel::SortTextForArtist(QString artist) { QString CollectionModel::SortTextForArtist(QString artist, const bool skip_articles) {
artist = SortText(artist); artist = SortText(artist);
if (skip_articles) {
for (const auto &i : Song::kArticles) { for (const auto &i : Song::kArticles) {
if (artist.startsWith(i)) { if (artist.startsWith(i)) {
qint64 ilen = i.length(); qint64 ilen = i.length();
@ -1730,6 +1741,7 @@ QString CollectionModel::SortTextForArtist(QString artist) {
break; break;
} }
} }
}
return artist; return artist;

View File

@ -162,6 +162,9 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
// Whether or not to show letters heading in the collection view // Whether or not to show letters heading in the collection view
void set_show_dividers(const bool show_dividers); void set_show_dividers(const bool show_dividers);
// Whether to skip articles such as “The” when sorting artist names
void set_sort_skips_articles(const bool sort_skips_articles);
// Reload settings. // Reload settings.
void ReloadSettings(); void ReloadSettings();
@ -173,7 +176,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
static QString PrettyDisc(const int disc); static QString PrettyDisc(const int disc);
static QString SortText(QString text); static QString SortText(QString text);
static QString SortTextForNumber(const int number); static QString SortTextForNumber(const int number);
static QString SortTextForArtist(QString artist); static QString SortTextForArtist(QString artist, const bool skip_articles);
static QString SortTextForSong(const Song &song); static QString SortTextForSong(const Song &song);
static QString SortTextForYear(const int year); static QString SortTextForYear(const int year);
static QString SortTextForBitrate(const int bitrate); static QString SortTextForBitrate(const int bitrate);
@ -278,6 +281,7 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
Application *app_; Application *app_;
CollectionDirectoryModel *dir_model_; CollectionDirectoryModel *dir_model_;
bool show_various_artists_; bool show_various_artists_;
bool sort_skips_articles_;
int total_song_count_; int total_song_count_;
int total_artist_count_; int total_artist_count_;

View File

@ -232,6 +232,7 @@ void CollectionView::ReloadSettings() {
if (app_) { if (app_) {
app_->collection_model()->set_pretty_covers(settings.value("pretty_covers", true).toBool()); app_->collection_model()->set_pretty_covers(settings.value("pretty_covers", true).toBool());
app_->collection_model()->set_show_dividers(settings.value("show_dividers", true).toBool()); app_->collection_model()->set_show_dividers(settings.value("show_dividers", true).toBool());
app_->collection_model()->set_sort_skips_articles(settings.value("sort_skips_articles", true).toBool());
} }
delete_files_ = settings.value("delete_files", false).toBool(); delete_files_ = settings.value("delete_files", false).toBool();
@ -343,6 +344,22 @@ void CollectionView::mouseReleaseEvent(QMouseEvent *e) {
} }
void CollectionView::keyPressEvent(QKeyEvent *e) {
switch (e->key()) {
case Qt::Key_Enter:
case Qt::Key_Return:
if (currentIndex().isValid()) {
AddToPlaylist();
}
e->accept();
break;
}
AutoExpandingTreeView::keyPressEvent(e);
}
void CollectionView::contextMenuEvent(QContextMenuEvent *e) { void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
if (!context_menu_) { if (!context_menu_) {
@ -355,6 +372,10 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
action_add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, &CollectionView::AddToPlaylistEnqueue); action_add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, &CollectionView::AddToPlaylistEnqueue);
action_add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue to play next"), this, &CollectionView::AddToPlaylistEnqueueNext); action_add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue to play next"), this, &CollectionView::AddToPlaylistEnqueueNext);
context_menu_->addSeparator();
action_search_for_this_ = context_menu_->addAction(IconLoader::Load("edit-find"), tr("Search for this"), this, &CollectionView::SearchForThis);
context_menu_->addSeparator(); context_menu_->addSeparator();
action_organize_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, &CollectionView::Organize); action_organize_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, &CollectionView::Organize);
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
@ -545,6 +566,100 @@ void CollectionView::OpenInNewPlaylist() {
} }
void CollectionView::SearchForThis() {
QModelIndex current = currentIndex();
QVariant type = model()->data(current, CollectionModel::Role_Type);
if (!type.isValid() || (type.toInt() != CollectionItem::Type_Song && type.toInt() != CollectionItem::Type_Container && type.toInt() != CollectionItem::Type_Divider)) {
return;
}
QString search;
QModelIndex index = qobject_cast<QSortFilterProxyModel*>(model())->mapToSource(current);
switch (type.toInt()) {
case CollectionItem::Type_Song:{
SongList songs = app_->collection_model()->GetChildSongs(index);
if (!songs.isEmpty()) {
last_selected_song_ = songs.last();
}
search = QString("title:%1").arg(last_selected_song_.title());
break;
}
case CollectionItem::Type_Divider:{
break;
}
case CollectionItem::Type_Container:{
CollectionItem *item = app_->collection_model()->IndexToItem(index);
int container_level = item->container_level;
CollectionModel::GroupBy container_group_by = app_->collection_model()->GetGroupBy()[container_level];
switch (container_group_by) {
case CollectionModel::GroupBy::AlbumArtist:
search = QString("albumartist:%1").arg(item->metadata.effective_albumartist());
break;
case CollectionModel::GroupBy::Artist:
search = QString("artist:%1").arg(item->metadata.artist());
break;
case CollectionModel::GroupBy::Album:
search = QString("album:%1").arg(item->metadata.album());
break;
case CollectionModel::GroupBy::AlbumDisc:
search = QString("album:%1").arg(item->metadata.album());
break;
case CollectionModel::GroupBy::YearAlbum:
case CollectionModel::GroupBy::YearAlbumDisc:{
search = QString("year:%1 album:%2").arg(item->metadata.year()).arg(item->metadata.album());
break;
}
case CollectionModel::GroupBy::OriginalYearAlbum:
case CollectionModel::GroupBy::OriginalYearAlbumDisc:{
search = QString("year:%1 album:%2").arg(item->metadata.effective_originalyear()).arg(item->metadata.album());
break;
}
case CollectionModel::GroupBy::Year:
search = QString("year:%1").arg(item->metadata.year());
break;
case CollectionModel::GroupBy::OriginalYear:
search = QString("year:%1").arg(item->metadata.effective_originalyear());
break;
case CollectionModel::GroupBy::Genre:
search = QString("genre:%1").arg(item->metadata.genre());
break;
case CollectionModel::GroupBy::Composer:
search = QString("composer:%1").arg(item->metadata.composer());
break;
case CollectionModel::GroupBy::Performer:
search = QString("performer:%1").arg(item->metadata.performer());
break;
case CollectionModel::GroupBy::Grouping:
search = QString("grouping:%1").arg(item->metadata.grouping());
break;
case CollectionModel::GroupBy::Samplerate:
search = QString("samplerate:%1").arg(item->metadata.samplerate());
break;
case CollectionModel::GroupBy::Bitdepth:
search = QString("bitdepth:%1").arg(item->metadata.bitdepth());
break;
case CollectionModel::GroupBy::Bitrate:
search = QString("bitrate:%1").arg(item->metadata.bitrate());
break;
default:
search = model()->data(current, Qt::DisplayRole).toString();
}
break;
}
default:
return;
}
filter_->ShowInCollection(search);
}
void CollectionView::keyboardSearch(const QString &search) { void CollectionView::keyboardSearch(const QString &search) {
is_in_keyboard_search_ = true; is_in_keyboard_search_ = true;

View File

@ -93,6 +93,7 @@ class CollectionView : public AutoExpandingTreeView {
protected: protected:
// QWidget // QWidget
void paintEvent(QPaintEvent *event) override; void paintEvent(QPaintEvent *event) override;
void keyPressEvent(QKeyEvent *e) override;
void mouseReleaseEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override;
void contextMenuEvent(QContextMenuEvent *e) override; void contextMenuEvent(QContextMenuEvent *e) override;
@ -102,6 +103,7 @@ class CollectionView : public AutoExpandingTreeView {
void AddToPlaylistEnqueue(); void AddToPlaylistEnqueue();
void AddToPlaylistEnqueueNext(); void AddToPlaylistEnqueueNext();
void OpenInNewPlaylist(); void OpenInNewPlaylist();
void SearchForThis();
void Organize(); void Organize();
void CopyToDevice(); void CopyToDevice();
void EditTracks(); void EditTracks();
@ -136,6 +138,8 @@ class CollectionView : public AutoExpandingTreeView {
QAction *action_add_to_playlist_enqueue_next_; QAction *action_add_to_playlist_enqueue_next_;
QAction *action_open_in_new_playlist_; QAction *action_open_in_new_playlist_;
QAction *action_organize_; QAction *action_organize_;
QAction *action_search_for_this_;
#ifndef Q_OS_WIN #ifndef Q_OS_WIN
QAction *action_copy_to_device_; QAction *action_copy_to_device_;
#endif #endif

View File

@ -67,7 +67,7 @@
#include "lyrics/songlyricscomlyricsprovider.h" #include "lyrics/songlyricscomlyricsprovider.h"
#include "lyrics/azlyricscomlyricsprovider.h" #include "lyrics/azlyricscomlyricsprovider.h"
#include "lyrics/elyricsnetlyricsprovider.h" #include "lyrics/elyricsnetlyricsprovider.h"
#include "lyrics/lyricsmodecomlyricsprovider.h" #include "lyrics/letraslyricsprovider.h"
#include "scrobbler/audioscrobbler.h" #include "scrobbler/audioscrobbler.h"
#include "scrobbler/lastfmscrobbler.h" #include "scrobbler/lastfmscrobbler.h"
@ -171,7 +171,7 @@ class ApplicationImpl {
lyrics_providers->AddProvider(new SongLyricsComLyricsProvider(app->network())); lyrics_providers->AddProvider(new SongLyricsComLyricsProvider(app->network()));
lyrics_providers->AddProvider(new AzLyricsComLyricsProvider(app->network())); lyrics_providers->AddProvider(new AzLyricsComLyricsProvider(app->network()));
lyrics_providers->AddProvider(new ElyricsNetLyricsProvider(app->network())); lyrics_providers->AddProvider(new ElyricsNetLyricsProvider(app->network()));
lyrics_providers->AddProvider(new LyricsModeComLyricsProvider(app->network())); lyrics_providers->AddProvider(new LetrasLyricsProvider(app->network()));
lyrics_providers->ReloadSettings(); lyrics_providers->ReloadSettings();
return lyrics_providers; return lyrics_providers;
}), }),

View File

@ -92,7 +92,8 @@ void DeleteFiles::ProcessSomeFiles() {
if (progress_ >= songs_.count()) { if (progress_ >= songs_.count()) {
task_manager_->SetTaskProgress(task_id_, progress_, songs_.count()); task_manager_->SetTaskProgress(task_id_, progress_, songs_.count());
storage_->FinishCopy(songs_with_errors_.isEmpty()); QString error_text;
storage_->FinishCopy(songs_with_errors_.isEmpty(), error_text);
task_manager_->SetTaskFinished(task_id_); task_manager_->SetTaskFinished(task_id_);

View File

@ -36,7 +36,7 @@
FilesystemMusicStorage::FilesystemMusicStorage(const Song::Source source, const QString &root, const std::optional<int> collection_directory_id) : source_(source), root_(root), collection_directory_id_(collection_directory_id) {} FilesystemMusicStorage::FilesystemMusicStorage(const Song::Source source, const QString &root, const std::optional<int> collection_directory_id) : source_(source), root_(root), collection_directory_id_(collection_directory_id) {}
bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job) { bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job, QString &error_text) {
const QFileInfo src = QFileInfo(job.source_); const QFileInfo src = QFileInfo(job.source_);
const QFileInfo dest = QFileInfo(root_ + "/" + job.destination_); const QFileInfo dest = QFileInfo(root_ + "/" + job.destination_);
@ -54,7 +54,8 @@ bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job) {
// Create directories as required // Create directories as required
QDir dir; QDir dir;
if (!dir.mkpath(dest.absolutePath())) { if (!dir.mkpath(dest.absolutePath())) {
qLog(Warning) << "Failed to create directory" << dest.dir().absolutePath(); error_text = QObject::tr("Failed to create directory %1.").arg(dest.dir().absolutePath());
qLog(Error) << error_text;
return false; return false;
} }
@ -65,10 +66,12 @@ bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job) {
} }
// Copy or move // Copy or move
bool result(true); bool result = true;
if (job.remove_original_) { if (job.remove_original_) {
if (dest.exists() && !job.overwrite_) { if (dest.exists() && !job.overwrite_) {
result = false; result = false;
error_text = QObject::tr("Destination file %1 exists, but not allowed to overwrite.").arg(dest.absoluteFilePath());
qLog(Error) << error_text;
} }
else { else {
result = QFile::rename(src.absoluteFilePath(), dest.absoluteFilePath()); result = QFile::rename(src.absoluteFilePath(), dest.absoluteFilePath());
@ -86,9 +89,15 @@ bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job) {
else { else {
if (dest.exists() && !job.overwrite_) { if (dest.exists() && !job.overwrite_) {
result = false; result = false;
error_text = QObject::tr("Destination file %1 exists, but not allowed to overwrite").arg(dest.absoluteFilePath());
qLog(Error) << error_text;
} }
else { else {
result = QFile::copy(src.absoluteFilePath(), dest.absoluteFilePath()); result = QFile::copy(src.absoluteFilePath(), dest.absoluteFilePath());
if (!result) {
error_text = QObject::tr("Could not copy file %1 to %2.").arg(src.absoluteFilePath(), dest.absoluteFilePath());
qLog(Error) << error_text;
}
} }
if ((!cover_dest.exists() || job.overwrite_) && !cover_src.filePath().isEmpty() && !cover_dest.filePath().isEmpty()) { if ((!cover_dest.exists() || job.overwrite_) && !cover_src.filePath().isEmpty() && !cover_dest.filePath().isEmpty()) {
QFile::copy(cover_src.absoluteFilePath(), cover_dest.absoluteFilePath()); QFile::copy(cover_src.absoluteFilePath(), cover_dest.absoluteFilePath());

View File

@ -39,7 +39,7 @@ class FilesystemMusicStorage : public virtual MusicStorage {
QString LocalPath() const override { return root_; } QString LocalPath() const override { return root_; }
std::optional<int> collection_directory_id() const override { return collection_directory_id_; } std::optional<int> collection_directory_id() const override { return collection_directory_id_; }
bool CopyToStorage(const CopyJob &job) override; bool CopyToStorage(const CopyJob &job, QString &error_text) override;
bool DeleteFromStorage(const DeleteJob &job) override; bool DeleteFromStorage(const DeleteJob &job) override;
private: private:

View File

@ -73,6 +73,10 @@
#include <QToolButton> #include <QToolButton>
#include <QCheckBox> #include <QCheckBox>
#include <QClipboard> #include <QClipboard>
#ifdef HAVE_DBUS
# include <QDBusConnection>
# include <QDBusMessage>
#endif
#include "core/logging.h" #include "core/logging.h"
@ -1269,6 +1273,11 @@ void MainWindow::Exit() {
return; // Don't quit the application now: wait for the fadeout finished signal return; // Don't quit the application now: wait for the fadeout finished signal
} }
} }
#ifdef HAVE_DBUS
UpdateTaskbarProgress(false, 0, 0);
#endif
DoExit(); DoExit();
} }
@ -1321,6 +1330,10 @@ void MainWindow::MediaStopped() {
tray_icon_->SetProgress(0); tray_icon_->SetProgress(0);
tray_icon_->SetStopped(); tray_icon_->SetStopped();
#ifdef HAVE_DBUS
UpdateTaskbarProgress(false, 0, 0);
#endif
song_playing_ = Song(); song_playing_ = Song();
song_ = Song(); song_ = Song();
album_cover_ = AlbumCoverImageResult(); album_cover_ = AlbumCoverImageResult();
@ -1397,6 +1410,10 @@ void MainWindow::SongChanged(const Song &song) {
setWindowTitle(song.PrettyTitleWithArtist()); setWindowTitle(song.PrettyTitleWithArtist());
tray_icon_->SetProgress(0); tray_icon_->SetProgress(0);
#ifdef HAVE_DBUS
UpdateTaskbarProgress(false, 0, 0);
#endif
SendNowPlaying(); SendNowPlaying();
const bool enable_change_art = song.is_collection_song() && !song.effective_albumartist().isEmpty() && !song.album().isEmpty(); const bool enable_change_art = song.is_collection_song() && !song.effective_albumartist().isEmpty() && !song.album().isEmpty();
@ -1686,6 +1703,10 @@ void MainWindow::Seeked(const qint64 microseconds) {
const qint64 length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec; const qint64 length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec;
tray_icon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0)); tray_icon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0));
#ifdef HAVE_DBUS
UpdateTaskbarProgress(true, position, length);
#endif
} }
void MainWindow::UpdateTrackPosition() { void MainWindow::UpdateTrackPosition() {
@ -1700,6 +1721,10 @@ void MainWindow::UpdateTrackPosition() {
// Update the tray icon every 10 seconds // 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) tray_icon_->SetProgress(static_cast<int>(static_cast<double>(position) / static_cast<double>(length) * 100.0));
#ifdef HAVE_DBUS
UpdateTaskbarProgress(true, position, length);
#endif
// Send Scrobble // Send Scrobble
if (app_->scrobbler()->enabled() && item->Metadata().is_metadata_good()) { if (app_->scrobbler()->enabled() && item->Metadata().is_metadata_good()) {
Playlist *playlist = app_->playlist_manager()->active(); Playlist *playlist = app_->playlist_manager()->active();
@ -1726,6 +1751,21 @@ void MainWindow::UpdateTrackSliderPosition() {
} }
#ifdef HAVE_DBUS
void MainWindow::UpdateTaskbarProgress(const bool visible, const double position, const double length) {
QVariantMap map;
QDBusMessage msg = QDBusMessage::createSignal(QStringLiteral("/org/strawberrymusicplayer/strawberry"), QStringLiteral("com.canonical.Unity.LauncherEntry"), QStringLiteral("Update"));
map.insert(QStringLiteral("progress-visible"), visible);
map.insert(QStringLiteral("progress"), position / length);
msg << QString("application://org.strawberrymusicplayer.strawberry.desktop") << map;
QDBusConnection::sessionBus().send(msg);
}
#endif
void MainWindow::ApplyAddBehaviour(const BehaviourSettingsPage::AddBehaviour b, MimeData *mimedata) { void MainWindow::ApplyAddBehaviour(const BehaviourSettingsPage::AddBehaviour b, MimeData *mimedata) {
switch (b) { switch (b) {

View File

@ -290,6 +290,10 @@ class MainWindow : public QMainWindow, public PlatformInterface {
void SetToggleScrobblingIcon(const bool value); void SetToggleScrobblingIcon(const bool value);
#ifdef HAVE_DBUS
void UpdateTaskbarProgress(const bool visible, const double position, const double length);
#endif
private: private:
Ui_MainWindow *ui_; Ui_MainWindow *ui_;
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@ -122,6 +122,9 @@
</property> </property>
<item> <item>
<widget class="QToolButton" name="back_button"> <widget class="QToolButton" name="back_button">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>32</width> <width>32</width>
@ -135,6 +138,9 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="pause_play_button"> <widget class="QToolButton" name="pause_play_button">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>32</width> <width>32</width>
@ -151,6 +157,9 @@
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>32</width> <width>32</width>
@ -167,6 +176,9 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="forward_button"> <widget class="QToolButton" name="forward_button">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>32</width> <width>32</width>
@ -205,6 +217,9 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="button_love"> <widget class="QToolButton" name="button_love">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>32</width> <width>32</width>

View File

@ -89,12 +89,12 @@ class MusicStorage {
virtual bool GetSupportedFiletypes(QList<Song::FileType> *ret) { Q_UNUSED(ret); return true; } virtual bool GetSupportedFiletypes(QList<Song::FileType> *ret) { Q_UNUSED(ret); return true; }
virtual bool StartCopy(QList<Song::FileType> *supported_types) { Q_UNUSED(supported_types); return true; } virtual bool StartCopy(QList<Song::FileType> *supported_types) { Q_UNUSED(supported_types); return true; }
virtual bool CopyToStorage(const CopyJob &job) = 0; virtual bool CopyToStorage(const CopyJob &job, QString &error_text) = 0;
virtual void FinishCopy(bool success) { Q_UNUSED(success); } virtual bool FinishCopy(bool success, QString &error_text) { Q_UNUSED(error_text); return success; }
virtual void StartDelete() {} virtual void StartDelete() {}
virtual bool DeleteFromStorage(const DeleteJob &job) = 0; virtual bool DeleteFromStorage(const DeleteJob &job) = 0;
virtual void FinishDelete(bool success) { Q_UNUSED(success); } virtual bool FinishDelete(bool success, QString &error_text) { Q_UNUSED(error_text); return success; }
virtual void Eject() {} virtual void Eject() {}

View File

@ -167,9 +167,28 @@ const QString Song::kFtsColumnSpec = Song::kFtsColumns.join(", ");
const QString Song::kFtsBindSpec = Utilities::Prepend(":", Song::kFtsColumns).join(", "); const QString Song::kFtsBindSpec = Utilities::Prepend(":", Song::kFtsColumns).join(", ");
const QString Song::kFtsUpdateSpec = Utilities::Updateify(Song::kFtsColumns).join(", "); const QString Song::kFtsUpdateSpec = Utilities::Updateify(Song::kFtsColumns).join(", ");
const QRegularExpression Song::kAlbumRemoveDisc(" ?-? ((\\(|\\[)?)(Disc|CD) ?([0-9]{1,2})((\\)|\\])?)$", QRegularExpression::CaseInsensitiveOption); const Song::RegularExpressionList Song::kAlbumDisc = Song::RegularExpressionList()
const QRegularExpression Song::kAlbumRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|([0-9]{1,4}) *Remaster|Explicit) ?((\\)|\\])?)$", QRegularExpression::CaseInsensitiveOption); << QRegularExpression("\\s+-*\\s*(Disc|CD)\\s*([0-9]{1,2})$", QRegularExpression::CaseInsensitiveOption)
const QRegularExpression Song::kTitleRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|Remastered Version|([0-9]{1,4}) *Remaster) ?((\\)|\\])?)$", QRegularExpression::CaseInsensitiveOption); << QRegularExpression("\\s+-*\\s*\\(\\s*(Disc|CD)\\s*([0-9]{1,2})\\)$", QRegularExpression::CaseInsensitiveOption)
<< QRegularExpression("\\s+-*\\s*\\[\\s*(Disc|CD)\\s*([0-9]{1,2})\\]$", QRegularExpression::CaseInsensitiveOption);
const Song::RegularExpressionList Song::kRemastered = Song::RegularExpressionList()
<< QRegularExpression("\\s+-*\\s*(([0-9]{4})*\\s*Remastered|([0-9]{4})*\\s*Remaster)\\s*(Version)*\\s*$", QRegularExpression::CaseInsensitiveOption)
<< QRegularExpression("\\s+-*\\s*\\(\\s*(([0-9]{4})*\\s*Remastered|([0-9]{4})*\\s*Remaster)\\s*(Version)*\\s*\\)\\s*$", QRegularExpression::CaseInsensitiveOption)
<< QRegularExpression("\\s+-*\\s*\\[\\s*(([0-9]{4})*\\s*Remastered|([0-9]{4})*\\s*Remaster)\\s*(Version)*\\s*\\]\\s*$", QRegularExpression::CaseInsensitiveOption);
const Song::RegularExpressionList Song::kExplicit = Song::RegularExpressionList()
<< QRegularExpression("\\s+-*\\s*Explicit\\s*$", QRegularExpression::CaseInsensitiveOption)
<< QRegularExpression("\\s+-*\\s*\\(\\s*Explicit\\s*\\)\\s*$", QRegularExpression::CaseInsensitiveOption)
<< QRegularExpression("\\s+-*\\s*\\[\\s*Explicit\\s*\\]\\s*$", QRegularExpression::CaseInsensitiveOption);
const Song::RegularExpressionList Song::kAlbumMisc = Song::RegularExpressionList()
<< kRemastered
<< kExplicit;
const Song::RegularExpressionList Song::kTitleMisc = Song::RegularExpressionList()
<< kRemastered
<< kExplicit;
const QStringList Song::kArticles = QStringList() << "the " << "a " << "an "; const QStringList Song::kArticles = QStringList() << "the " << "a " << "an ";
@ -1843,3 +1862,53 @@ size_t HashSimilar(const Song &song) {
// Should compare the same fields as function IsSimilar // Should compare the same fields as function IsSimilar
return qHash(song.title().toLower()) ^ qHash(song.artist().toLower()) ^ qHash(song.album().toLower()); return qHash(song.title().toLower()) ^ qHash(song.artist().toLower()) ^ qHash(song.album().toLower());
} }
bool Song::ContainsRegexList(const QString &str, const RegularExpressionList &regex_list) {
for (const QRegularExpression &regex : regex_list) {
if (str.contains(regex)) return true;
}
return false;
}
QString Song::StripRegexList(QString str, const RegularExpressionList &regex_list) {
for (const QRegularExpression &regex : regex_list) {
str = str.remove(regex);
}
return str;
}
bool Song::AlbumContainsDisc(const QString &album) {
return ContainsRegexList(album, kAlbumDisc);
}
QString Song::AlbumRemoveDisc(const QString &album) {
return StripRegexList(album, kAlbumDisc);
}
QString Song::AlbumRemoveMisc(const QString &album) {
return StripRegexList(album, kAlbumMisc);
}
QString Song::AlbumRemoveDiscMisc(const QString &album) {
return StripRegexList(album, RegularExpressionList() << kAlbumDisc << kAlbumMisc);
}
QString Song::TitleRemoveMisc(const QString &title) {
return StripRegexList(title, kTitleMisc);
}

View File

@ -123,9 +123,12 @@ class Song {
static const QString kFtsBindSpec; static const QString kFtsBindSpec;
static const QString kFtsUpdateSpec; static const QString kFtsUpdateSpec;
static const QRegularExpression kAlbumRemoveDisc; using RegularExpressionList = QList<QRegularExpression>;
static const QRegularExpression kAlbumRemoveMisc; static const RegularExpressionList kAlbumDisc;
static const QRegularExpression kTitleRemoveMisc; static const RegularExpressionList kRemastered;
static const RegularExpressionList kExplicit;
static const RegularExpressionList kAlbumMisc;
static const RegularExpressionList kTitleMisc;
static const QStringList kArticles; static const QStringList kArticles;
@ -443,6 +446,14 @@ class Song {
// It is more efficient to use IsOnSameAlbum, but this function can be used when you need to hash the key to do fast lookups. // It is more efficient to use IsOnSameAlbum, but this function can be used when you need to hash the key to do fast lookups.
QString AlbumKey() const; QString AlbumKey() const;
static bool ContainsRegexList(const QString &str, const RegularExpressionList &regex_list);
static QString StripRegexList(QString str, const RegularExpressionList &regex_list);
static bool AlbumContainsDisc(const QString &album);
static QString AlbumRemoveDisc(const QString &album);
static QString AlbumRemoveMisc(const QString &album);
static QString AlbumRemoveDiscMisc(const QString &album);
static QString TitleRemoveMisc(const QString &title);
private: private:
struct Private; struct Private;

View File

@ -333,7 +333,7 @@ AlbumCoverImageResult AlbumCoverChoiceController::SearchForImage(Song *song) {
if (!song->url().isValid() || !song->url().isLocalFile() || song->effective_albumartist().isEmpty() || song->album().isEmpty()) return AlbumCoverImageResult(); if (!song->url().isValid() || !song->url().isLocalFile() || song->effective_albumartist().isEmpty() || song->album().isEmpty()) return AlbumCoverImageResult();
QString album = song->effective_album(); QString album = song->effective_album();
album = album.remove(Song::kAlbumRemoveDisc).remove(Song::kAlbumRemoveMisc); album = Song::AlbumRemoveDiscMisc(album);
// Get something sensible to stick in the search box // Get something sensible to stick in the search box
return cover_searcher_->Exec(song->effective_albumartist(), album); return cover_searcher_->Exec(song->effective_albumartist(), album);

View File

@ -66,9 +66,7 @@ quint64 AlbumCoverFetcher::FetchAlbumCover(const QString &artist, const QString
CoverSearchRequest request; CoverSearchRequest request;
request.id = ++next_id_; request.id = ++next_id_;
request.artist = artist; request.artist = artist;
request.album = album; request.album = Song::AlbumRemoveDiscMisc(album);
request.album = request.album.remove(Song::kAlbumRemoveDisc);
request.album = request.album.remove(Song::kAlbumRemoveMisc);
request.title = title; request.title = title;
request.search = false; request.search = false;
request.batch = batch; request.batch = batch;
@ -83,9 +81,7 @@ quint64 AlbumCoverFetcher::SearchForCovers(const QString &artist, const QString
CoverSearchRequest request; CoverSearchRequest request;
request.id = ++next_id_; request.id = ++next_id_;
request.artist = artist; request.artist = artist;
request.album = album; request.album = Song::AlbumRemoveDiscMisc(album);
request.album = request.album.remove(Song::kAlbumRemoveDisc);
request.album = request.album.remove(Song::kAlbumRemoveMisc);
request.title = title; request.title = title;
request.search = true; request.search = true;
request.batch = false; request.batch = false;

View File

@ -87,6 +87,9 @@
</item> </item>
<item> <item>
<widget class="QToolButton" name="view"> <widget class="QToolButton" name="view">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="text"> <property name="text">
<string>View</string> <string>View</string>
</property> </property>

View File

@ -265,12 +265,9 @@ void DeezerCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id)
} }
QString album = obj_album["title"].toString(); QString album = obj_album["title"].toString();
album = album.remove(Song::kAlbumRemoveDisc);
album = album.remove(Song::kAlbumRemoveMisc);
CoverProviderSearchResult cover_result; CoverProviderSearchResult cover_result;
cover_result.artist = artist; cover_result.artist = artist;
cover_result.album = album; cover_result.album = Song::AlbumRemoveDiscMisc(album);
bool have_cover = false; bool have_cover = false;
QList<QPair<QString, QSize>> cover_sizes = QList<QPair<QString, QSize>>() << qMakePair(QString("cover_xl"), QSize(1000, 1000)) QList<QPair<QString, QSize>> cover_sizes = QList<QPair<QString, QSize>>() << qMakePair(QString("cover_xl"), QSize(1000, 1000))

View File

@ -262,12 +262,9 @@ void QobuzCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) {
} }
QUrl cover_url(obj_image["large"].toString()); QUrl cover_url(obj_image["large"].toString());
album = album.remove(Song::kAlbumRemoveDisc);
album = album.remove(Song::kAlbumRemoveMisc);
CoverProviderSearchResult cover_result; CoverProviderSearchResult cover_result;
cover_result.artist = artist; cover_result.artist = artist;
cover_result.album = album; cover_result.album = Song::AlbumRemoveDiscMisc(album);
cover_result.image_url = cover_url; cover_result.image_url = cover_url;
cover_result.image_size = QSize(600, 600); cover_result.image_size = QSize(600, 600);
results << cover_result; results << cover_result;

View File

@ -241,15 +241,11 @@ void TidalCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) {
continue; continue;
} }
QString album = obj_album["title"].toString(); QString album = obj_album["title"].toString();
QString cover = obj_album["cover"].toString(); QString cover = obj_album["cover"].toString().replace("-", "/");
album = album.remove(Song::kAlbumRemoveDisc);
album = album.remove(Song::kAlbumRemoveMisc);
cover = cover.replace("-", "/");
CoverProviderSearchResult cover_result; CoverProviderSearchResult cover_result;
cover_result.artist = artist; cover_result.artist = artist;
cover_result.album = album; cover_result.album = Song::AlbumRemoveDiscMisc(album);
cover_result.number = ++i; cover_result.number = ++i;
QList<QPair<QString, QSize>> cover_sizes = QList<QPair<QString, QSize>>() << qMakePair(QString("1280x1280"), QSize(1280, 1280)) QList<QPair<QString, QSize>> cover_sizes = QList<QPair<QString, QSize>>() << qMakePair(QString("1280x1280"), QSize(1280, 1280))

View File

@ -51,7 +51,7 @@ class CddaDevice : public ConnectedDevice {
bool Init() override; bool Init() override;
void Refresh() override; void Refresh() override;
bool CopyToStorage(const MusicStorage::CopyJob&) override { return false; } bool CopyToStorage(const CopyJob&, QString&) override { return false; }
bool DeleteFromStorage(const MusicStorage::DeleteJob&) override { return false; } bool DeleteFromStorage(const MusicStorage::DeleteJob&) override { return false; }
static QStringList url_schemes() { return QStringList() << "cdda"; } static QStringList url_schemes() { return QStringList() << "cdda"; }

View File

@ -132,12 +132,14 @@ void ConnectedDevice::Eject() {
} }
void ConnectedDevice::FinishCopy(bool) { bool ConnectedDevice::FinishCopy(bool success, QString&) {
lister_->UpdateDeviceFreeSpace(unique_id_); lister_->UpdateDeviceFreeSpace(unique_id_);
return success;
} }
void ConnectedDevice::FinishDelete(bool) { bool ConnectedDevice::FinishDelete(bool success, QString&) {
lister_->UpdateDeviceFreeSpace(unique_id_); lister_->UpdateDeviceFreeSpace(unique_id_);
return success;
} }
MusicStorage::TranscodeMode ConnectedDevice::GetTranscodeMode() const { MusicStorage::TranscodeMode ConnectedDevice::GetTranscodeMode() const {

View File

@ -67,8 +67,8 @@ class ConnectedDevice : public QObject, public virtual MusicStorage, public enab
QUrl url() const { return url_; } QUrl url() const { return url_; }
qint64 song_count() const { return song_count_; } qint64 song_count() const { return song_count_; }
void FinishCopy(bool success) override; bool FinishCopy(bool success, QString &error_text) override;
void FinishDelete(bool success) override; bool FinishDelete(bool success, QString &error_text) override;
void Eject() override; void Eject() override;
virtual void Close(); virtual void Close();

View File

@ -830,7 +830,7 @@ void DeviceManager::DeviceTaskStarted(const int id) {
for (int i = 0; i < devices_.count(); ++i) { for (int i = 0; i < devices_.count(); ++i) {
DeviceInfo *info = devices_[i]; DeviceInfo *info = devices_[i];
if (&*info->device_ == device) { if (info->device_ && &*info->device_ == device) {
QModelIndex index = ItemToIndex(info); QModelIndex index = ItemToIndex(info);
if (!index.isValid()) continue; if (!index.isValid()) continue;
active_tasks_[id] = index; active_tasks_[id] = index;

View File

@ -185,7 +185,7 @@ void GPodDevice::AddTrackToModel(Itdb_Track *track, const QString &prefix) {
} }
bool GPodDevice::CopyToStorage(const CopyJob &job) { bool GPodDevice::CopyToStorage(const CopyJob &job, QString &error_text) {
Q_ASSERT(db_); Q_ASSERT(db_);
@ -238,9 +238,10 @@ bool GPodDevice::CopyToStorage(const CopyJob &job) {
GError *error = nullptr; GError *error = nullptr;
itdb_cp_track_to_ipod(track, QDir::toNativeSeparators(job.source_).toLocal8Bit().constData(), &error); itdb_cp_track_to_ipod(track, QDir::toNativeSeparators(job.source_).toLocal8Bit().constData(), &error);
if (error) { if (error) {
qLog(Error) << "Copying failed:" << error->message; error_text = tr("Could not copy %1 to %2: %3").arg(job.metadata_.url().toLocalFile(), url_.path(), QString::fromUtf8(error->message));
app_->AddError(QString::fromUtf8(error->message));
g_error_free(error); g_error_free(error);
qLog(Error) << error_text;
app_->AddError(error_text);
// Need to remove the track from the db again // Need to remove the track from the db again
itdb_track_remove(track); itdb_track_remove(track);
@ -272,19 +273,24 @@ bool GPodDevice::CopyToStorage(const CopyJob &job) {
} }
bool GPodDevice::WriteDatabase() { bool GPodDevice::WriteDatabase(QString &error_text) {
// Write the itunes database // Write the itunes database
GError *error = nullptr; GError *error = nullptr;
itdb_write(db_, &error); const bool success = itdb_write(db_, &error);
cover_files_.clear(); cover_files_.clear();
if (!success) {
if (error) { if (error) {
qLog(Error) << "Writing database failed:" << error->message; error_text = tr("Writing database failed: %1").arg(error->message);
app_->AddError(QString::fromUtf8(error->message));
g_error_free(error); g_error_free(error);
return false;
} }
else return true; else {
error_text = tr("Writing database failed.");
}
app_->AddError(error_text);
}
return success;
} }
@ -307,11 +313,11 @@ void GPodDevice::Finish(const bool success) {
} }
void GPodDevice::FinishCopy(bool success) { bool GPodDevice::FinishCopy(bool success, QString &error_text) {
if (success) success = WriteDatabase(); if (success) success = WriteDatabase(error_text);
Finish(success); Finish(success);
ConnectedDevice::FinishCopy(success); return ConnectedDevice::FinishCopy(success, error_text);
} }
@ -378,11 +384,11 @@ bool GPodDevice::DeleteFromStorage(const DeleteJob &job) {
} }
void GPodDevice::FinishDelete(bool success) { bool GPodDevice::FinishDelete(bool success, QString &error_text) {
if (success) success = WriteDatabase(); if (success) success = WriteDatabase(error_text);
Finish(success); Finish(success);
ConnectedDevice::FinishDelete(success); return ConnectedDevice::FinishDelete(success, error_text);
} }

View File

@ -64,12 +64,12 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
bool GetSupportedFiletypes(QList<Song::FileType> *ret) override; bool GetSupportedFiletypes(QList<Song::FileType> *ret) override;
bool StartCopy(QList<Song::FileType> *supported_filetypes) override; bool StartCopy(QList<Song::FileType> *supported_filetypes) override;
bool CopyToStorage(const CopyJob &job) override; bool CopyToStorage(const CopyJob &job, QString &error_text) override;
void FinishCopy(bool success) override; bool FinishCopy(bool success, QString &error_text) override;
void StartDelete() override; void StartDelete() override;
bool DeleteFromStorage(const DeleteJob &job) override; bool DeleteFromStorage(const DeleteJob &job) override;
void FinishDelete(bool success) override; bool FinishDelete(bool success, QString &error_text) override;
protected slots: protected slots:
void LoadFinished(Itdb_iTunesDB *db, const bool success); void LoadFinished(Itdb_iTunesDB *db, const bool success);
@ -83,7 +83,7 @@ class GPodDevice : public ConnectedDevice, public virtual MusicStorage {
private: private:
void Start(); void Start();
void Finish(const bool success); void Finish(const bool success);
bool WriteDatabase(); bool WriteDatabase(QString &error_text);
protected: protected:
GPodLoader *loader_; GPodLoader *loader_;

View File

@ -54,7 +54,8 @@ MtpConnection::MtpConnection(const QUrl &url, QObject *parent) : QObject(parent)
device_num = url_query.queryItemValue("devnum").toUInt(); device_num = url_query.queryItemValue("devnum").toUInt();
} }
else { else {
qLog(Warning) << "Invalid MTP device:" << hostname; error_text_ = tr("Invalid MTP device: %1").arg(hostname);
qLog(Error) << error_text_;
return; return;
} }
@ -70,15 +71,20 @@ MtpConnection::MtpConnection(const QUrl &url, QObject *parent) : QObject(parent)
raw_device->devnum = device_num; raw_device->devnum = device_num;
device_ = LIBMTP_Open_Raw_Device(raw_device); // NOLINT(clang-analyzer-unix.Malloc) device_ = LIBMTP_Open_Raw_Device(raw_device); // NOLINT(clang-analyzer-unix.Malloc)
if (!device_) {
error_text_ = tr("Could not open MTP device.");
qLog(Error) << error_text_;
}
return; return;
} }
// Get a list of devices from libmtp and figure out which one is ours // Get a list of devices from libmtp and figure out which one is ours
int count = 0; int count = 0;
LIBMTP_raw_device_t *raw_devices = nullptr; LIBMTP_raw_device_t *raw_devices = nullptr;
LIBMTP_error_number_t err = LIBMTP_Detect_Raw_Devices(&raw_devices, &count); LIBMTP_error_number_t error_number = LIBMTP_Detect_Raw_Devices(&raw_devices, &count);
if (err != LIBMTP_ERROR_NONE) { if (error_number != LIBMTP_ERROR_NONE) {
qLog(Warning) << "MTP error:" << err; error_text_ = tr("MTP error: %1").arg(ErrorString(error_number));
qLog(Error) << error_text_;
return; return;
} }
@ -91,13 +97,18 @@ MtpConnection::MtpConnection(const QUrl &url, QObject *parent) : QObject(parent)
} }
if (!raw_device) { if (!raw_device) {
qLog(Warning) << "MTP device not found"; error_text_ = tr("MTP device not found.");
qLog(Error) << error_text_;
free(raw_devices); free(raw_devices);
return; return;
} }
// Connect to the device // Connect to the device
device_ = LIBMTP_Open_Raw_Device(raw_device); device_ = LIBMTP_Open_Raw_Device(raw_device);
if (!device_) {
error_text_ = tr("Could not open MTP device.");
qLog(Error) << error_text_;
}
free(raw_devices); free(raw_devices);
@ -107,6 +118,24 @@ MtpConnection::~MtpConnection() {
if (device_) LIBMTP_Release_Device(device_); if (device_) LIBMTP_Release_Device(device_);
} }
QString MtpConnection::ErrorString(const LIBMTP_error_number_t error_number) {
switch(error_number) {
case LIBMTP_ERROR_NO_DEVICE_ATTACHED:
return "No Devices have been found.";
case LIBMTP_ERROR_CONNECTING:
return "There has been an error connecting.";
case LIBMTP_ERROR_MEMORY_ALLOCATION:
return "Memory Allocation Error.";
case LIBMTP_ERROR_GENERAL:
default:
return "Unknown error, please report this to the libmtp developers.";
case LIBMTP_ERROR_NONE:
return "Successfully connected.";
}
}
bool MtpConnection::GetSupportedFiletypes(QList<Song::FileType> *ret) { bool MtpConnection::GetSupportedFiletypes(QList<Song::FileType> *ret) {
if (!device_) return false; if (!device_) return false;

View File

@ -45,13 +45,17 @@ class MtpConnection : public QObject, public enable_shared_from_this<MtpConnecti
~MtpConnection() override; ~MtpConnection() override;
bool is_valid() const { return device_; } bool is_valid() const { return device_; }
QString error_text() const { return error_text_; }
LIBMTP_mtpdevice_t *device() const { return device_; } LIBMTP_mtpdevice_t *device() const { return device_; }
bool GetSupportedFiletypes(QList<Song::FileType> *ret); bool GetSupportedFiletypes(QList<Song::FileType> *ret);
static QString ErrorString(const LIBMTP_error_number_t error_number);
private: private:
Q_DISABLE_COPY(MtpConnection) Q_DISABLE_COPY(MtpConnection)
LIBMTP_mtpdevice_t *device_; LIBMTP_mtpdevice_t *device_;
QString error_text_;
}; };
#endif // MTPCONNECTION_H #endif // MTPCONNECTION_H

View File

@ -143,7 +143,8 @@ bool MtpDevice::StartCopy(QList<Song::FileType> *supported_types) {
// Did the caller want a list of supported types? // Did the caller want a list of supported types?
if (supported_types) { if (supported_types) {
if (!GetSupportedFiletypes(supported_types, connection_->device())) { if (!GetSupportedFiletypes(supported_types, connection_->device())) {
FinishCopy(false); QString error_text;
FinishCopy(false, error_text);
return false; return false;
} }
} }
@ -161,7 +162,7 @@ static int ProgressCallback(uint64_t const sent, uint64_t const total, void cons
} }
bool MtpDevice::CopyToStorage(const CopyJob &job) { bool MtpDevice::CopyToStorage(const CopyJob &job, QString &error_text) {
if (!connection_ || !connection_->is_valid()) return false; if (!connection_ || !connection_->is_valid()) return false;
@ -171,7 +172,15 @@ bool MtpDevice::CopyToStorage(const CopyJob &job) {
// Send the file // Send the file
int ret = LIBMTP_Send_Track_From_File(connection_->device(), job.source_.toUtf8().constData(), &track, ProgressCallback, &job); int ret = LIBMTP_Send_Track_From_File(connection_->device(), job.source_.toUtf8().constData(), &track, ProgressCallback, &job);
if (ret != 0) return false; if (ret != 0) {
LIBMTP_error_struct *error = LIBMTP_Get_Errorstack(connection_->device());
if (error) {
error_text = QString::fromUtf8(error->error_text);
qLog(Error) << error_text;
LIBMTP_Clear_Errorstack(connection_->device());
}
return false;
}
// Add it to our CollectionModel // Add it to our CollectionModel
Song metadata_on_device(Song::Source::Device); Song metadata_on_device(Song::Source::Device);
@ -190,7 +199,7 @@ bool MtpDevice::CopyToStorage(const CopyJob &job) {
} }
void MtpDevice::FinishCopy(const bool success) { bool MtpDevice::FinishCopy(const bool success, QString &error_text) {
if (success) { if (success) {
if (!songs_to_add_.isEmpty()) backend_->AddOrUpdateSongs(songs_to_add_); if (!songs_to_add_.isEmpty()) backend_->AddOrUpdateSongs(songs_to_add_);
@ -205,7 +214,7 @@ void MtpDevice::FinishCopy(const bool success) {
db_busy_.unlock(); db_busy_.unlock();
ConnectedDevice::FinishCopy(success); return ConnectedDevice::FinishCopy(success, error_text);
} }
@ -234,7 +243,7 @@ bool MtpDevice::DeleteFromStorage(const DeleteJob &job) {
} }
void MtpDevice::FinishDelete(const bool success) { FinishCopy(success); } bool MtpDevice::FinishDelete(const bool success, QString &error_text) { return FinishCopy(success, error_text); }
bool MtpDevice::GetSupportedFiletypes(QList<Song::FileType> *ret) { bool MtpDevice::GetSupportedFiletypes(QList<Song::FileType> *ret) {

View File

@ -63,12 +63,12 @@ class MtpDevice : public ConnectedDevice {
int GetCapacity(); int GetCapacity();
bool StartCopy(QList<Song::FileType> *supported_types) override; bool StartCopy(QList<Song::FileType> *supported_types) override;
bool CopyToStorage(const CopyJob &job) override; bool CopyToStorage(const CopyJob &job, QString &error_text) override;
void FinishCopy(const bool success) override; bool FinishCopy(const bool success, QString &error_text) override;
void StartDelete() override; void StartDelete() override;
bool DeleteFromStorage(const DeleteJob &job) override; bool DeleteFromStorage(const DeleteJob &job) override;
void FinishDelete(const bool success) override; bool FinishDelete(const bool success, QString &error_text) override;
private slots: private slots:
void LoadFinished(bool success, MtpConnection *connection); void LoadFinished(bool success, MtpConnection *connection);

View File

@ -68,11 +68,16 @@ bool MtpLoader::TryLoad() {
connection_ = make_unique<MtpConnection>(url_); connection_ = make_unique<MtpConnection>(url_);
if (!connection_ || !connection_->is_valid()) { if (!connection_) {
emit Error(tr("Error connecting MTP device %1").arg(url_.toString())); emit Error(tr("Error connecting MTP device %1").arg(url_.toString()));
return false; return false;
} }
if (!connection_->is_valid()) {
emit Error(tr("Error connecting MTP device %1: %2").arg(url_.toString(), connection_->error_text()));
return false;
}
// Load the list of songs on the device // Load the list of songs on the device
SongList songs; SongList songs;
LIBMTP_track_t *tracks = LIBMTP_Get_Tracklisting_With_Callback(connection_->device(), nullptr, nullptr); LIBMTP_track_t *tracks = LIBMTP_Get_Tracklisting_With_Callback(connection_->device(), nullptr, nullptr);
@ -84,7 +89,7 @@ bool MtpLoader::TryLoad() {
Song song(Song::Source::Device); Song song(Song::Source::Device);
song.InitFromMTP(track, url_.host()); song.InitFromMTP(track, url_.host());
if (song.is_valid() && !song.artist().isEmpty() && !song.title().isEmpty()) { if (song.is_valid() && !song.title().isEmpty()) {
song.set_directory_id(1); song.set_directory_id(1);
songs << song; songs << song;
} }

View File

@ -635,6 +635,9 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="tags_art_button"> <widget class="QPushButton" name="tags_art_button">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="text"> <property name="text">
<string>Change art</string> <string>Change art</string>
</property> </property>

View File

@ -0,0 +1,92 @@
/*
* 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/>.
*
*/
#include <windows.h>
#include <string.h>
#include <atlconv.h>
#include <winreg.h>
#include <QString>
#include "asiodevicefinder.h"
#include "enginedevice.h"
#include "core/logging.h"
AsioDeviceFinder::AsioDeviceFinder() : DeviceFinder("asio", { "asiosink" }) {}
EngineDeviceList AsioDeviceFinder::ListDevices() {
EngineDeviceList devices;
HKEY reg_key = nullptr;
LSTATUS status = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"software\\asio", 0, KEY_READ, &reg_key);
for (DWORD i = 0; status == ERROR_SUCCESS; i++) {
WCHAR key_name[256];
status = RegEnumKeyW(reg_key, i, key_name, sizeof(key_name));
EngineDevice device = GetDevice(reg_key, key_name);
if (device.value.isValid()) {
devices.append(device);
}
}
if (reg_key) {
RegCloseKey(reg_key);
}
return devices;
}
EngineDevice AsioDeviceFinder::GetDevice(HKEY reg_key, LPWSTR key_name) {
HKEY sub_key = nullptr;
const QScopeGuard scopeguard_sub_key = qScopeGuard([sub_key]() {
if (sub_key) {
RegCloseKey(sub_key);
}
});
LSTATUS status = RegOpenKeyExW(reg_key, key_name, 0, KEY_READ, &sub_key);
if (status != ERROR_SUCCESS) {
return EngineDevice();
}
DWORD type = REG_SZ;
WCHAR clsid_data[256]{};
DWORD clsid_data_size = sizeof(clsid_data);
status = RegQueryValueExW(sub_key, L"clsid", 0, &type, (LPBYTE)clsid_data, &clsid_data_size);
if (status != ERROR_SUCCESS) {
return EngineDevice();
}
EngineDevice device;
device.value = QString::fromStdWString(clsid_data);
device.description = QString::fromStdWString(key_name);
WCHAR desc_data[256]{};
DWORD desc_data_size = sizeof(desc_data);
status = RegQueryValueExW(sub_key, L"description", 0, &type, (LPBYTE)desc_data, &desc_data_size);
if (status == ERROR_SUCCESS) {
device.description = QString::fromStdWString(desc_data);
}
return device;
}

View File

@ -0,0 +1,41 @@
/*
* 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 ASIODEVICEFINDER_H
#define ASIODEVICEFINDER_H
#include "config.h"
#include <windows.h>
#include "devicefinder.h"
#include "enginedevice.h"
class AsioDeviceFinder : public DeviceFinder {
public:
explicit AsioDeviceFinder();
virtual bool Initialize() { return true; }
virtual EngineDeviceList ListDevices();
private:
EngineDevice GetDevice(HKEY reg_key, LPWSTR key_name);
};
#endif // ASIODEVICEFINDER_H

View File

@ -45,6 +45,7 @@
# include "mmdevicefinder.h" # include "mmdevicefinder.h"
# ifdef _MSC_VER # ifdef _MSC_VER
# include "uwpdevicefinder.h" # include "uwpdevicefinder.h"
# include "asiodevicefinder.h"
# endif // _MSC_VER # endif // _MSC_VER
#endif // Q_OS_WIN32 #endif // Q_OS_WIN32
@ -73,6 +74,7 @@ void DeviceFinders::Init() {
device_finders.append(new MMDeviceFinder); device_finders.append(new MMDeviceFinder);
# ifdef _MSC_VER # ifdef _MSC_VER
device_finders.append(new UWPDeviceFinder); device_finders.append(new UWPDeviceFinder);
device_finders.append(new AsioDeviceFinder);
# endif // _MSC_VER # endif // _MSC_VER
#endif // Q_OS_WIN32 #endif // Q_OS_WIN32

View File

@ -35,7 +35,7 @@
#include "enginedevice.h" #include "enginedevice.h"
#include "core/logging.h" #include "core/logging.h"
DirectSoundDeviceFinder::DirectSoundDeviceFinder() : DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink", "directx", "directx2" }) {} DirectSoundDeviceFinder::DirectSoundDeviceFinder() : DeviceFinder("directsound", { "directsound", "dsound", "directsoundsink", "directx", "directx2", "waveformsink" }) {}
EngineDeviceList DirectSoundDeviceFinder::ListDevices() { EngineDeviceList DirectSoundDeviceFinder::ListDevices() {
State state; State state;

View File

@ -39,6 +39,7 @@
EngineBase::EngineBase(QObject *parent) EngineBase::EngineBase(QObject *parent)
: QObject(parent), : QObject(parent),
exclusive_mode_(false),
volume_control_(true), volume_control_(true),
volume_(100), volume_(100),
beginning_nanosec_(0), beginning_nanosec_(0),
@ -167,6 +168,8 @@ void EngineBase::ReloadSettings() {
output_ = s.value("output").toString(); output_ = s.value("output").toString();
device_ = s.value("device"); device_ = s.value("device");
exclusive_mode_ = s.value("exclusive_mode", false).toBool();
volume_control_ = s.value("volume_control", true).toBool(); volume_control_ = s.value("volume_control", true).toBool();
channels_enabled_ = s.value("channels_enabled", false).toBool(); channels_enabled_ = s.value("channels_enabled", false).toBool();

View File

@ -129,6 +129,7 @@ class EngineBase : public QObject {
virtual QString DefaultOutput() = 0; virtual QString DefaultOutput() = 0;
virtual bool CustomDeviceSupport(const QString &output) = 0; virtual bool CustomDeviceSupport(const QString &output) = 0;
virtual bool ALSADeviceSupport(const QString &output) = 0; virtual bool ALSADeviceSupport(const QString &output) = 0;
virtual bool ExclusiveModeSupport(const QString &output) = 0;
// Plays a media stream represented with the URL 'u' from the given 'beginning' to the given 'end' (usually from 0 to a song's length). // Plays a media stream represented with the URL 'u' from the given 'beginning' to the given 'end' (usually from 0 to a song's length).
// Both markers should be passed in nanoseconds. 'end' can be negative, indicating that the real length of 'u' stream is unknown. // Both markers should be passed in nanoseconds. 'end' can be negative, indicating that the real length of 'u' stream is unknown.
@ -188,6 +189,7 @@ class EngineBase : public QObject {
void VolumeChanged(const uint volume); void VolumeChanged(const uint volume);
protected: protected:
bool exclusive_mode_;
bool volume_control_; bool volume_control_;
uint volume_; uint volume_;
quint64 beginning_nanosec_; quint64 beginning_nanosec_;

View File

@ -73,6 +73,7 @@ const char *GstEngine::kAVDTPSink = "avdtpsink";
const char *GstEngine::InterAudiosink = "interaudiosink"; const char *GstEngine::InterAudiosink = "interaudiosink";
const char *GstEngine::kDirectSoundSink = "directsoundsink"; const char *GstEngine::kDirectSoundSink = "directsoundsink";
const char *GstEngine::kOSXAudioSink = "osxaudiosink"; const char *GstEngine::kOSXAudioSink = "osxaudiosink";
const char *GstEngine::kWASAPISink = "wasapisink";
const int GstEngine::kDiscoveryTimeoutS = 10; const int GstEngine::kDiscoveryTimeoutS = 10;
const qint64 GstEngine::kTimerIntervalNanosec = 1000 * kNsecPerMsec; // 1s const qint64 GstEngine::kTimerIntervalNanosec = 1000 * kNsecPerMsec; // 1s
const qint64 GstEngine::kPreloadGapNanosec = 8000 * kNsecPerMsec; // 8s const qint64 GstEngine::kPreloadGapNanosec = 8000 * kNsecPerMsec; // 8s
@ -413,14 +414,19 @@ EngineBase::OutputDetailsList GstEngine::GetOutputsList() const {
GList *const features = gst_registry_get_feature_list(registry, GST_TYPE_ELEMENT_FACTORY); GList *const features = gst_registry_get_feature_list(registry, GST_TYPE_ELEMENT_FACTORY);
for (GList *future = features; future; future = g_list_next(future)) { for (GList *future = features; future; future = g_list_next(future)) {
GstElementFactory *factory = GST_ELEMENT_FACTORY(future->data); GstElementFactory *factory = GST_ELEMENT_FACTORY(future->data);
const gchar *metadata = gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS); const QString metadata = QString::fromUtf8(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS));
if (QString(metadata).startsWith("Sink/Audio", Qt::CaseInsensitive)) { const QString name = QString::fromUtf8(gst_plugin_feature_get_name(future->data));
OutputDetails output; if (metadata.startsWith("Sink/Audio", Qt::CaseInsensitive) || name == "pipewiresink" || (metadata.startsWith("Source/Audio", Qt::CaseInsensitive) && name.contains("sink"))) {
output.name = QString::fromUtf8(gst_plugin_feature_get_name(future->data)); QString description = QString::fromUtf8(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_DESCRIPTION));
output.description = QString::fromUtf8(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_DESCRIPTION)); if (name == "wasapi2sink" && description == "Stream audio to an audio capture device through WASAPI") {
if (output.name == "wasapi2sink" && output.description == "Stream audio to an audio capture device through WASAPI") { description.append("2");
output.description.append("2");
} }
else if (name == "pipewiresink" && description == "Send video to PipeWire") {
description = "Send audio to PipeWire";
}
OutputDetails output;
output.name = name;
output.description = description;
if (output.name == kAutoSink) output.iconname = "soundcard"; if (output.name == kAutoSink) output.iconname = "soundcard";
else if (output.name == kALSASink || output.name == kOSS4Sink) output.iconname = "alsa"; else if (output.name == kALSASink || output.name == kOSS4Sink) output.iconname = "alsa";
else if (output.name == kJackAudioSink) output.iconname = "jack"; else if (output.name == kJackAudioSink) output.iconname = "jack";
@ -454,6 +460,10 @@ bool GstEngine::ALSADeviceSupport(const QString &output) {
return (output == kALSASink); return (output == kALSASink);
} }
bool GstEngine::ExclusiveModeSupport(const QString &output) {
return output == kWASAPISink;
}
void GstEngine::ReloadSettings() { void GstEngine::ReloadSettings() {
EngineBase::ReloadSettings(); EngineBase::ReloadSettings();
@ -789,6 +799,7 @@ SharedPtr<GstEnginePipeline> GstEngine::CreatePipeline() {
SharedPtr<GstEnginePipeline> ret = make_shared<GstEnginePipeline>(); SharedPtr<GstEnginePipeline> ret = make_shared<GstEnginePipeline>();
ret->set_output_device(output_, device_); ret->set_output_device(output_, device_);
ret->set_exclusive_mode(exclusive_mode_);
ret->set_volume_enabled(volume_control_); ret->set_volume_enabled(volume_control_);
ret->set_stereo_balancer_enabled(stereo_balancer_enabled_); ret->set_stereo_balancer_enabled(stereo_balancer_enabled_);
ret->set_equalizer_enabled(equalizer_enabled_); ret->set_equalizer_enabled(equalizer_enabled_);

View File

@ -81,6 +81,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer {
QString DefaultOutput() override { return kAutoSink; } QString DefaultOutput() override { return kAutoSink; }
bool CustomDeviceSupport(const QString &output) override; bool CustomDeviceSupport(const QString &output) override;
bool ALSADeviceSupport(const QString &output) override; bool ALSADeviceSupport(const QString &output) override;
bool ExclusiveModeSupport(const QString &output) override;
void SetStartup(GstStartup *gst_startup) { gst_startup_ = gst_startup; } void SetStartup(GstStartup *gst_startup) { gst_startup_ = gst_startup; }
void EnsureInitialized() { gst_startup_->EnsureInitialized(); } void EnsureInitialized() { gst_startup_->EnsureInitialized(); }
@ -152,6 +153,7 @@ class GstEngine : public EngineBase, public GstBufferConsumer {
static const char *InterAudiosink; static const char *InterAudiosink;
static const char *kDirectSoundSink; static const char *kDirectSoundSink;
static const char *kOSXAudioSink; static const char *kOSXAudioSink;
static const char *kWASAPISink;
static const int kDiscoveryTimeoutS; static const int kDiscoveryTimeoutS;
static const qint64 kTimerIntervalNanosec; static const qint64 kTimerIntervalNanosec;
static const qint64 kPreloadGapNanosec; static const qint64 kPreloadGapNanosec;

View File

@ -74,6 +74,7 @@ GstEnginePipeline::GstEnginePipeline(QObject *parent)
: QObject(parent), : QObject(parent),
id_(sId++), id_(sId++),
valid_(false), valid_(false),
exclusive_mode_(false),
volume_enabled_(true), volume_enabled_(true),
stereo_balancer_enabled_(false), stereo_balancer_enabled_(false),
eq_enabled_(false), eq_enabled_(false),
@ -221,6 +222,10 @@ void GstEnginePipeline::set_output_device(const QString &output, const QVariant
} }
void GstEnginePipeline::set_exclusive_mode(const bool exclusive_mode) {
exclusive_mode_ = exclusive_mode;
}
void GstEnginePipeline::set_volume_enabled(const bool enabled) { void GstEnginePipeline::set_volume_enabled(const bool enabled) {
volume_enabled_ = enabled; volume_enabled_ = enabled;
} }
@ -335,7 +340,7 @@ bool GstEnginePipeline::InitFromUrl(const QUrl &media_url, const QUrl &stream_ur
guint version_major = 0, version_minor = 0, version_micro = 0, version_nano = 0; guint version_major = 0, version_minor = 0, version_micro = 0, version_nano = 0;
gst_plugins_base_version(&version_major, &version_minor, &version_micro, &version_nano); gst_plugins_base_version(&version_major, &version_minor, &version_micro, &version_nano);
if (QVersionNumber::compare(QVersionNumber(static_cast<int>(version_major), static_cast<int>(version_minor), static_cast<int>(version_micro)), QVersionNumber(1, 22, 0)) >= 0) { if (QVersionNumber::compare(QVersionNumber(static_cast<int>(version_major), static_cast<int>(version_minor)), QVersionNumber(1, 22)) >= 0) {
pipeline_ = CreateElement("playbin3", "pipeline", nullptr, error); pipeline_ = CreateElement("playbin3", "pipeline", nullptr, error);
} }
else { else {
@ -448,7 +453,41 @@ bool GstEnginePipeline::InitAudioBin(QString &error) {
break; break;
} }
} }
else if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "device-clsid")) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
switch (device_.metaType().id()) {
#else
switch (device_.type()) {
#endif
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
case QMetaType::QString:{
#else
case QVariant::String:{
#endif
QString device = device_.toString();
if (!device.isEmpty()) {
qLog(Debug) << "Setting device-clsid" << device << "for" << output_;
g_object_set(G_OBJECT(audiosink_), "device-clsid", device.toUtf8().constData(), nullptr);
}
break;
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
case QMetaType::QByteArray:{
#else
case QVariant::ByteArray:{
#endif
QByteArray device = device_.toByteArray();
if (!device.isEmpty()) {
qLog(Debug) << "Setting device-clsid" << device_ << "for" << output_;
g_object_set(G_OBJECT(audiosink_), "device-clsid", device.constData(), nullptr);
}
break;
}
default:
qLog(Warning) << "Unknown device clsid" << device_;
break;
}
}
else if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "port-pattern")) { else if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "port-pattern")) {
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
switch (device_.metaType().id()) { switch (device_.metaType().id()) {
@ -489,6 +528,13 @@ bool GstEnginePipeline::InitAudioBin(QString &error) {
} }
if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "exclusive")) {
if (exclusive_mode_) {
qLog(Debug) << "Setting exclusive mode for" << output_;
}
g_object_set(G_OBJECT(audiosink_), "exclusive", exclusive_mode_, nullptr);
}
#ifndef Q_OS_WIN32 #ifndef Q_OS_WIN32
if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "volume")) { if (g_object_class_find_property(G_OBJECT_GET_CLASS(audiosink_), "volume")) {
qLog(Debug) << output_ << "has volume, enabling volume synchronization."; qLog(Debug) << output_ << "has volume, enabling volume synchronization.";

View File

@ -62,6 +62,7 @@ class GstEnginePipeline : public QObject {
// Call these setters before Init // Call these setters before Init
void set_output_device(const QString &output, const QVariant &device); void set_output_device(const QString &output, const QVariant &device);
void set_exclusive_mode(const bool exclusive_mode);
void set_volume_enabled(const bool enabled); void set_volume_enabled(const bool enabled);
void set_stereo_balancer_enabled(const bool enabled); void set_stereo_balancer_enabled(const bool enabled);
void set_equalizer_enabled(const bool enabled); void set_equalizer_enabled(const bool enabled);
@ -202,6 +203,7 @@ class GstEnginePipeline : public QObject {
bool valid_; bool valid_;
QString output_; QString output_;
QVariant device_; QVariant device_;
bool exclusive_mode_;
bool volume_enabled_; bool volume_enabled_;
bool stereo_balancer_enabled_; bool stereo_balancer_enabled_;
bool eq_enabled_; bool eq_enabled_;

View File

@ -264,6 +264,11 @@ bool VLCEngine::ALSADeviceSupport(const QString &output) {
return (output == "alsa"); return (output == "alsa");
} }
bool VLCEngine::ExclusiveModeSupport(const QString &output) {
Q_UNUSED(output);
return false;
}
uint VLCEngine::position() const { uint VLCEngine::position() const {
if (!Initialized() || !libvlc_media_player_is_playing(player_)) return 0; if (!Initialized() || !libvlc_media_player_is_playing(player_)) return 0;

View File

@ -70,6 +70,7 @@ class VLCEngine : public EngineBase {
QString DefaultOutput() override { return ""; } QString DefaultOutput() override { return ""; }
bool CustomDeviceSupport(const QString &output) override; bool CustomDeviceSupport(const QString &output) override;
bool ALSADeviceSupport(const QString &output) override; bool ALSADeviceSupport(const QString &output) override;
bool ExclusiveModeSupport(const QString &output) override;
private: private:
libvlc_instance_t *instance_; libvlc_instance_t *instance_;

View File

@ -89,6 +89,7 @@ void InternetCollectionView::Init(Application *app, SharedPtr<CollectionBackend>
collection_model_->set_pretty_covers(true); collection_model_->set_pretty_covers(true);
collection_model_->set_show_dividers(true); collection_model_->set_show_dividers(true);
collection_model_->set_sort_skips_articles(true);
ReloadSettings(); ReloadSettings();

View File

@ -95,7 +95,7 @@ QStandardItem *InternetSearchModel::BuildContainers(const Song &s, QStandardItem
} }
else { else {
display_text = CollectionModel::TextOrUnknown(s.effective_albumartist()); display_text = CollectionModel::TextOrUnknown(s.effective_albumartist());
sort_text = CollectionModel::SortTextForArtist(s.effective_albumartist()); sort_text = CollectionModel::SortTextForArtist(s.effective_albumartist(), true);
} }
has_artist_icon = true; has_artist_icon = true;
break; break;
@ -107,14 +107,14 @@ QStandardItem *InternetSearchModel::BuildContainers(const Song &s, QStandardItem
} }
else { else {
display_text = CollectionModel::TextOrUnknown(s.artist()); display_text = CollectionModel::TextOrUnknown(s.artist());
sort_text = CollectionModel::SortTextForArtist(s.artist()); sort_text = CollectionModel::SortTextForArtist(s.artist(), true);
} }
has_artist_icon = true; has_artist_icon = true;
break; break;
case CollectionModel::GroupBy::Album: case CollectionModel::GroupBy::Album:
display_text = CollectionModel::TextOrUnknown(s.album()); display_text = CollectionModel::TextOrUnknown(s.album());
sort_text = CollectionModel::SortTextForArtist(s.album()); sort_text = CollectionModel::SortTextForArtist(s.album(), true);
unique_tag = s.album_id(); unique_tag = s.album_id();
has_album_icon = true; has_album_icon = true;
break; break;
@ -168,7 +168,7 @@ QStandardItem *InternetSearchModel::BuildContainers(const Song &s, QStandardItem
case CollectionModel::GroupBy::Disc: case CollectionModel::GroupBy::Disc:
display_text = CollectionModel::PrettyDisc(s.disc()); display_text = CollectionModel::PrettyDisc(s.disc());
sort_text = CollectionModel::SortTextForArtist(display_text); sort_text = CollectionModel::SortTextForArtist(display_text, true);
has_album_icon = true; has_album_icon = true;
break; break;
@ -188,25 +188,25 @@ QStandardItem *InternetSearchModel::BuildContainers(const Song &s, QStandardItem
case CollectionModel::GroupBy::Genre: case CollectionModel::GroupBy::Genre:
display_text = CollectionModel::TextOrUnknown(s.genre()); display_text = CollectionModel::TextOrUnknown(s.genre());
sort_text = CollectionModel::SortTextForArtist(s.genre()); sort_text = CollectionModel::SortTextForArtist(s.genre(), true);
has_album_icon = true; has_album_icon = true;
break; break;
case CollectionModel::GroupBy::Composer: case CollectionModel::GroupBy::Composer:
display_text = CollectionModel::TextOrUnknown(s.composer()); display_text = CollectionModel::TextOrUnknown(s.composer());
sort_text = CollectionModel::SortTextForArtist(s.composer()); sort_text = CollectionModel::SortTextForArtist(s.composer(), true);
has_album_icon = true; has_album_icon = true;
break; break;
case CollectionModel::GroupBy::Performer: case CollectionModel::GroupBy::Performer:
display_text = CollectionModel::TextOrUnknown(s.performer()); display_text = CollectionModel::TextOrUnknown(s.performer());
sort_text = CollectionModel::SortTextForArtist(s.performer()); sort_text = CollectionModel::SortTextForArtist(s.performer(), true);
has_album_icon = true; has_album_icon = true;
break; break;
case CollectionModel::GroupBy::Grouping: case CollectionModel::GroupBy::Grouping:
display_text = CollectionModel::TextOrUnknown(s.grouping()); display_text = CollectionModel::TextOrUnknown(s.grouping());
sort_text = CollectionModel::SortTextForArtist(s.grouping()); sort_text = CollectionModel::SortTextForArtist(s.grouping(), true);
has_album_icon = true; has_album_icon = true;
break; break;

View File

@ -176,7 +176,7 @@ void InternetSearchView::Init(Application *app, InternetServicePtr service) {
QMenu *settings_menu = new QMenu(this); QMenu *settings_menu = new QMenu(this);
settings_menu->addActions(group_by_actions_->actions()); settings_menu->addActions(group_by_actions_->actions());
settings_menu->addSeparator(); settings_menu->addSeparator();
settings_menu->addAction(IconLoader::Load("configure"), tr("Configure %1...").arg(Song::TextForSource(service_->source())), this, &InternetSearchView::OpenSettingsDialog); settings_menu->addAction(IconLoader::Load("configure"), tr("Configure %1...").arg(Song::DescriptionForSource(service_->source())), this, &InternetSearchView::OpenSettingsDialog);
ui_->settings->setMenu(settings_menu); ui_->settings->setMenu(settings_menu);
swap_models_timer_->setSingleShot(true); swap_models_timer_->setSingleShot(true);

View File

@ -54,6 +54,9 @@
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="iconSize"> <property name="iconSize">
<size> <size>
<width>16</width> <width>16</width>

View File

@ -56,7 +56,7 @@ InternetSongsView::InternetSongsView(Application *app, InternetServicePtr servic
ui_->filter_widget->SetSettingsGroup(settings_group); ui_->filter_widget->SetSettingsGroup(settings_group);
ui_->filter_widget->Init(service_->songs_collection_model()); ui_->filter_widget->Init(service_->songs_collection_model());
QAction *action_configure = new QAction(IconLoader::Load("configure"), tr("Configure %1...").arg(Song::TextForSource(service_->source())), this); QAction *action_configure = new QAction(IconLoader::Load("configure"), tr("Configure %1...").arg(Song::DescriptionForSource(service_->source())), this);
QObject::connect(action_configure, &QAction::triggered, this, &InternetSongsView::OpenSettingsDialog); QObject::connect(action_configure, &QAction::triggered, this, &InternetSongsView::OpenSettingsDialog);
ui_->filter_widget->AddMenuAction(action_configure); ui_->filter_widget->AddMenuAction(action_configure);

View File

@ -18,8 +18,6 @@
*/ */
#include <QObject> #include <QObject>
#include <QByteArray>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
#include <QRegularExpression> #include <QRegularExpression>

View File

@ -22,8 +22,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <QObject> #include <QObject>
#include <QList>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>

View File

@ -18,8 +18,6 @@
*/ */
#include <QObject> #include <QObject>
#include <QByteArray>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
#include <QRegularExpression> #include <QRegularExpression>

View File

@ -22,8 +22,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <QObject> #include <QObject>
#include <QList>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>

View File

@ -56,6 +56,7 @@ bool HtmlLyricsProvider::StartSearch(const int id, const LyricsSearchRequest &re
QUrl url(Url(request)); QUrl url(Url(request));
QNetworkRequest req(url); QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy); req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setRawHeader("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:122.0) Gecko/20100101 Firefox/122.0");
QNetworkReply *reply = network_->get(req); QNetworkReply *reply = network_->get(req);
replies_ << reply; replies_ << reply;
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id, request]() { HandleLyricsReply(reply, id, request); }); QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id, request]() { HandleLyricsReply(reply, id, request); });
@ -162,6 +163,7 @@ QString HtmlLyricsProvider::ParseLyricsFromHTML(const QString &content, const QR
.remove(QRegularExpression("<script>[^>]*</script>")) .remove(QRegularExpression("<script>[^>]*</script>"))
.remove(QRegularExpression("<div [^>]*>×</div>")) .remove(QRegularExpression("<div [^>]*>×</div>"))
.replace(QRegularExpression("<br[^>]*>"), "\n") .replace(QRegularExpression("<br[^>]*>"), "\n")
.replace(QRegularExpression("</p>"), "\n\n")
.remove(QRegularExpression("<[^>]*>")) .remove(QRegularExpression("<[^>]*>"))
.trimmed()); .trimmed());
} }

View File

@ -0,0 +1,56 @@
/*
* 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/>.
*
*/
#include <QObject>
#include <QString>
#include <QUrl>
#include <QRegularExpression>
#include "core/shared_ptr.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "utilities/transliterate.h"
#include "lyricssearchrequest.h"
#include "letraslyricsprovider.h"
const char LetrasLyricsProvider::kUrl[] = "https://www.letras.mus.br/winamp.php";
const char LetrasLyricsProvider::kStartTag[] = "<div[^>]*>";
const char LetrasLyricsProvider::kEndTag[] = "<\\/div>";
const char LetrasLyricsProvider::kLyricsStart[] = "<div id=\"letra-cnt\">";
LetrasLyricsProvider::LetrasLyricsProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: HtmlLyricsProvider("letras.mus.br", true, kStartTag, kEndTag, kLyricsStart, false, network, parent) {}
QUrl LetrasLyricsProvider::Url(const LyricsSearchRequest &request) {
return QUrl(QString(kUrl) + QStringLiteral("?musica=") + StringFixup(request.artist) + "&artista=" + StringFixup(request.title));
}
QString LetrasLyricsProvider::StringFixup(const QString &text) {
return QUrl::toPercentEncoding(Utilities::Transliterate(text)
.replace(QRegularExpression("[^\\w0-9_,&\\-\\(\\) ]"), "_")
.replace(QRegularExpression(" {2,}"), " ")
.simplified()
.replace(' ', '-')
.toLower()
);
}

View File

@ -1,6 +1,6 @@
/* /*
* Strawberry Music Player * Strawberry Music Player
* Copyright 2023, Jonas Kvinge <jonas@jkvinge.net> * Copyright 2024, Jonas Kvinge <jonas@jkvinge.net>
* *
* Strawberry is free software: you can redistribute it and/or modify * Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -17,13 +17,11 @@
* *
*/ */
#ifndef LYRICSMODECOMLYRICSPROVIDER_H #ifndef LETRASLYRICSPROVIDER_H
#define LYRICSMODECOMLYRICSPROVIDER_H #define LETRASLYRICSPROVIDER_H
#include <QtGlobal> #include <QtGlobal>
#include <QObject> #include <QObject>
#include <QList>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
@ -32,17 +30,17 @@
#include "htmllyricsprovider.h" #include "htmllyricsprovider.h"
#include "lyricssearchrequest.h" #include "lyricssearchrequest.h"
class LyricsModeComLyricsProvider : public HtmlLyricsProvider { class LetrasLyricsProvider : public HtmlLyricsProvider {
Q_OBJECT Q_OBJECT
public: public:
explicit LyricsModeComLyricsProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr); explicit LetrasLyricsProvider(SharedPtr<NetworkAccessManager> network, QObject *parent = nullptr);
protected: protected:
QUrl Url(const LyricsSearchRequest &request) override; QUrl Url(const LyricsSearchRequest &request) override;
private: private:
QString StringFixup(QString text); QString StringFixup(const QString &text);
private: private:
static const char kUrl[]; static const char kUrl[];
@ -51,4 +49,4 @@ class LyricsModeComLyricsProvider : public HtmlLyricsProvider {
static const char kLyricsStart[]; static const char kLyricsStart[];
}; };
#endif // LYRICSMODECOMLYRICSPROVIDER_H #endif // LETRASLYRICSPROVIDER_H

View File

@ -53,10 +53,8 @@ quint64 LyricsFetcher::Search(const QString &effective_albumartist, const QStrin
LyricsSearchRequest search_request; LyricsSearchRequest search_request;
search_request.albumartist = effective_albumartist; search_request.albumartist = effective_albumartist;
search_request.artist = artist; search_request.artist = artist;
search_request.album = album; search_request.album = Song::AlbumRemoveDiscMisc(album);
search_request.album.remove(Song::kAlbumRemoveMisc); search_request.title = Song::TitleRemoveMisc(title);
search_request.title = title;
search_request.title.remove(Song::kTitleRemoveMisc);
Request request; Request request;
request.id = ++next_id_; request.id = ++next_id_;

View File

@ -1,56 +0,0 @@
/*
* 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/>.
*
*/
#include <QObject>
#include <QByteArray>
#include <QVariant>
#include <QString>
#include <QUrl>
#include <QRegularExpression>
#include "core/shared_ptr.h"
#include "core/networkaccessmanager.h"
#include "lyricssearchrequest.h"
#include "lyricsmodecomlyricsprovider.h"
const char LyricsModeComLyricsProvider::kUrl[] = "https://www.lyricsmode.com/lyrics/";
const char LyricsModeComLyricsProvider::kStartTag[] = "<div[^>]*>";
const char LyricsModeComLyricsProvider::kEndTag[] = "<\\/div>";
const char LyricsModeComLyricsProvider::kLyricsStart[] = "<div id=\"lyrics_text\" [^>]*>";
LyricsModeComLyricsProvider::LyricsModeComLyricsProvider(SharedPtr<NetworkAccessManager> network, QObject *parent)
: HtmlLyricsProvider("lyricsmode.com", true, kStartTag, kEndTag, kLyricsStart, false, network, parent) {}
QUrl LyricsModeComLyricsProvider::Url(const LyricsSearchRequest &request) {
return QUrl(kUrl + request.artist[0].toLower() + "/" + StringFixup(request.artist) + "/" + StringFixup(request.title) + ".html");
}
QString LyricsModeComLyricsProvider::StringFixup(QString text) {
return text
.remove(QRegularExpression("[^\\w0-9_\\- ]"))
.replace(QRegularExpression(" {2,}"), " ")
.simplified()
.replace(' ', '_')
.replace('-', '_')
.toLower();
}

View File

@ -18,8 +18,6 @@
*/ */
#include <QObject> #include <QObject>
#include <QByteArray>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>
#include <QRegularExpression> #include <QRegularExpression>

View File

@ -22,8 +22,6 @@
#include <QtGlobal> #include <QtGlobal>
#include <QObject> #include <QObject>
#include <QList>
#include <QVariant>
#include <QString> #include <QString>
#include <QUrl> #include <QUrl>

View File

@ -146,7 +146,10 @@ void Organize::ProcessSomeFiles() {
UpdateProgress(); UpdateProgress();
destination_->FinishCopy(files_with_errors_.isEmpty()); QString error_text;
if (!destination_->FinishCopy(files_with_errors_.isEmpty(), error_text) && !error_text.isEmpty()) {
log_ << error_text;
}
if (eject_after_) destination_->Eject(); if (eject_after_) destination_->Eject();
task_manager_->SetTaskFinished(task_id_); task_manager_->SetTaskFinished(task_id_);
@ -250,7 +253,8 @@ void Organize::ProcessSomeFiles() {
job.progress_ = std::bind(&Organize::SetSongProgress, this, std::placeholders::_1, !task.transcoded_filename_.isEmpty()); job.progress_ = std::bind(&Organize::SetSongProgress, this, std::placeholders::_1, !task.transcoded_filename_.isEmpty());
if (destination_->CopyToStorage(job)) { QString error_text;
if (destination_->CopyToStorage(job, error_text)) {
if (job.remove_original_ && song.is_collection_song() && destination_->source() == Song::Source::Collection) { if (job.remove_original_ && song.is_collection_song() && destination_->source() == Song::Source::Collection) {
// Notify other aspects of system that song has been invalidated // Notify other aspects of system that song has been invalidated
QString root = destination_->LocalPath(); QString root = destination_->LocalPath();
@ -260,6 +264,9 @@ void Organize::ProcessSomeFiles() {
} }
else { else {
files_with_errors_ << task.song_info_.song_.basefilename(); files_with_errors_ << task.song_info_.song_.basefilename();
if (!error_text.isEmpty()) {
log_ << error_text;
}
} }
// Clean up the temporary transcoded file // Clean up the temporary transcoded file

View File

@ -269,6 +269,10 @@ bool Playlist::set_column_value(Song &song, Playlist::Column column, const QVari
QVariant Playlist::data(const QModelIndex &idx, int role) const { QVariant Playlist::data(const QModelIndex &idx, int role) const {
if (!idx.isValid()) {
return QVariant();
}
switch (role) { switch (role) {
case Role_IsCurrent: case Role_IsCurrent:
return current_item_index_.isValid() && idx.row() == current_item_index_.row(); return current_item_index_.isValid() && idx.row() == current_item_index_.row();
@ -1022,44 +1026,6 @@ void Playlist::InsertItems(const PlaylistItemPtrList &itemsIn, const int pos, co
PlaylistItemPtrList items = itemsIn; PlaylistItemPtrList items = itemsIn;
// Exercise vetoes
SongList songs;
songs.reserve(items.count());
for (PlaylistItemPtr item : items) { // clazy:exclude=range-loop-reference
songs << item->Metadata();
}
const qint64 song_count = songs.length();
QSet<Song> vetoed;
for (SongInsertVetoListener *listener : veto_listeners_) {
for (const Song &song : listener->AboutToInsertSongs(GetAllSongs(), songs)) {
// Avoid veto-ing a song multiple times
vetoed.insert(song);
}
if (vetoed.count() == song_count) {
// All songs were vetoed and there's nothing more to do (there's no need for an undo step)
return;
}
}
if (!vetoed.isEmpty()) {
QMutableListIterator<PlaylistItemPtr> it(items);
while (it.hasNext()) {
PlaylistItemPtr item = it.next();
const Song &current = item->Metadata();
if (vetoed.contains(current)) {
vetoed.remove(current);
it.remove();
}
}
// Check for empty items once again after veto
if (items.isEmpty()) {
return;
}
}
const int start = pos == -1 ? static_cast<int>(items_.count()) : pos; const int start = pos == -1 ? static_cast<int>(items_.count()) : pos;
if (items.count() > kUndoItemLimit) { if (items.count() > kUndoItemLimit) {
@ -1303,7 +1269,7 @@ bool Playlist::CompareItems(const int column, const Qt::SortOrder order, Playlis
case Column_Track: cmp(track); case Column_Track: cmp(track);
case Column_Disc: cmp(disc); case Column_Disc: cmp(disc);
case Column_Year: cmp(year); case Column_Year: cmp(year);
case Column_OriginalYear: cmp(originalyear); case Column_OriginalYear: cmp(effective_originalyear);
case Column_Genre: strcmp(genre); case Column_Genre: strcmp(genre);
case Column_AlbumArtist: strcmp(playlist_albumartist_sortable); case Column_AlbumArtist: strcmp(playlist_albumartist_sortable);
case Column_Composer: strcmp(composer); case Column_Composer: strcmp(composer);
@ -1901,20 +1867,6 @@ void Playlist::ReloadItemsBlocking(const QList<int> &rows) {
} }
void Playlist::AddSongInsertVetoListener(SongInsertVetoListener *listener) {
veto_listeners_.append(listener);
QObject::connect(listener, &SongInsertVetoListener::destroyed, this, &Playlist::SongInsertVetoListenerDestroyed);
}
void Playlist::RemoveSongInsertVetoListener(SongInsertVetoListener *listener) {
QObject::disconnect(listener, &SongInsertVetoListener::destroyed, this, &Playlist::SongInsertVetoListenerDestroyed);
veto_listeners_.removeAll(listener);
}
void Playlist::SongInsertVetoListenerDestroyed() {
veto_listeners_.removeAll(qobject_cast<SongInsertVetoListener*>(sender()));
}
void Playlist::Shuffle() { void Playlist::Shuffle() {
PlaylistItemPtrList new_items(items_); PlaylistItemPtrList new_items(items_);

View File

@ -74,18 +74,6 @@ using ColumnAlignmentMap = QMap<int, Qt::Alignment>;
Q_DECLARE_METATYPE(Qt::Alignment) Q_DECLARE_METATYPE(Qt::Alignment)
Q_DECLARE_METATYPE(ColumnAlignmentMap) Q_DECLARE_METATYPE(ColumnAlignmentMap)
// Objects that may prevent a song being added to the playlist.
// When there is something about to be inserted into it,
// Playlist notifies all of its listeners about the fact and every one of them picks 'invalid' songs.
class SongInsertVetoListener : public QObject {
Q_OBJECT
public:
// Listener returns a list of 'invalid' songs.
// 'old_songs' are songs that are currently in the playlist and 'new_songs' are the songs about to be added if nobody exercises a veto.
virtual SongList AboutToInsertSongs(const SongList &old_songs, const SongList &new_songs) = 0;
};
class Playlist : public QAbstractListModel { class Playlist : public QAbstractListModel {
Q_OBJECT Q_OBJECT
@ -258,11 +246,6 @@ class Playlist : public QAbstractListModel {
void ReloadItemsBlocking(const QList<int> &rows); void ReloadItemsBlocking(const QList<int> &rows);
void InformOfCurrentSongChange(const AutoScroll autoscroll, const bool minor); void InformOfCurrentSongChange(const AutoScroll autoscroll, const bool minor);
// Registers an object which will get notifications when new songs are about to be inserted into this playlist.
void AddSongInsertVetoListener(SongInsertVetoListener *listener);
// Unregisters a SongInsertVetoListener object.
void RemoveSongInsertVetoListener(SongInsertVetoListener *listener);
// Just emits the dataChanged() signal so the mood column is repainted. // Just emits the dataChanged() signal so the mood column is repainted.
#ifdef HAVE_MOODBAR #ifdef HAVE_MOODBAR
void MoodbarUpdated(const QModelIndex &idx); void MoodbarUpdated(const QModelIndex &idx);
@ -376,7 +359,6 @@ class Playlist : public QAbstractListModel {
void SongSaveComplete(TagReaderReply *reply, const QPersistentModelIndex &idx, const Song &old_metadata); void SongSaveComplete(TagReaderReply *reply, const QPersistentModelIndex &idx, const Song &old_metadata);
void ItemReloadComplete(const QPersistentModelIndex &idx, const Song &old_metadata, const bool metadata_edit); void ItemReloadComplete(const QPersistentModelIndex &idx, const Song &old_metadata, const bool metadata_edit);
void ItemsLoaded(); void ItemsLoaded();
void SongInsertVetoListenerDestroyed();
void ScheduleSave(); void ScheduleSave();
void Save(); void Save();
@ -420,8 +402,6 @@ class Playlist : public QAbstractListModel {
ColumnAlignmentMap column_alignments_; ColumnAlignmentMap column_alignments_;
QList<SongInsertVetoListener*> veto_listeners_;
QString special_type_; QString special_type_;
// Cancel async restore if songs are already replaced // Cancel async restore if songs are already replaced

View File

@ -1189,7 +1189,7 @@ void QobuzRequest::ParseSong(Song &song, const QJsonObject &json_obj, const Arti
url.setScheme(url_handler_->scheme()); url.setScheme(url_handler_->scheme());
url.setPath(song_id); url.setPath(song_id);
title.remove(Song::kTitleRemoveMisc); title = Song::TitleRemoveMisc(title);
//qLog(Debug) << "id" << song_id << "track" << track << "title" << title << "album" << album << "album artist" << album_artist << cover_url << streamable << url; //qLog(Debug) << "id" << song_id << "track" << track << "title" << title << "album" << album << "album artist" << album_artist << cover_url << streamable << url;

View File

@ -1,6 +1,6 @@
/* /*
* Strawberry Music Player * Strawberry Music Player
* Copyright 2021, Jonas Kvinge <jonas@jkvinge.net> * Copyright 2021-2024, Jonas Kvinge <jonas@jkvinge.net>
* *
* Strawberry is free software: you can redistribute it and/or modify * Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,28 +19,107 @@
#include <QObject> #include <QObject>
#include <QUrl> #include <QUrl>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonValue>
#include <QJsonObject>
#include <QJsonArray>
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/taskmanager.h"
#include "core/iconloader.h" #include "core/iconloader.h"
#include "radioparadiseservice.h" #include "radioparadiseservice.h"
#include "radiochannel.h" #include "radiochannel.h"
const char *RadioParadiseService::kApiChannelsUrl = "https://api.radioparadise.com/api/list_streams";
RadioParadiseService::RadioParadiseService(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent) RadioParadiseService::RadioParadiseService(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: RadioService(Song::Source::RadioParadise, "Radio Paradise", IconLoader::Load("radioparadise"), app, network, parent) {} : RadioService(Song::Source::RadioParadise, "Radio Paradise", IconLoader::Load("radioparadise"), app, network, parent) {}
QUrl RadioParadiseService::Homepage() { return QUrl("https://radioparadise.com/"); } QUrl RadioParadiseService::Homepage() { return QUrl("https://radioparadise.com/"); }
QUrl RadioParadiseService::Donate() { return QUrl("https://payments.radioparadise.com/rp2s-content.php?name=Support&file=support"); } QUrl RadioParadiseService::Donate() { return QUrl("https://payments.radioparadise.com/rp2s-content.php?name=Support&file=support"); }
void RadioParadiseService::GetChannels() { void RadioParadiseService::Abort() {
emit NewChannels(RadioChannelList() while (!replies_.isEmpty()) {
<< RadioChannel(source_, "Main Mix 320k AAC", QUrl("https://stream.radioparadise.com/aac-320")) QNetworkReply *reply = replies_.takeFirst();
<< RadioChannel(source_, "Mellow Mix 320k AAC", QUrl("https://stream.radioparadise.com/mellow-320")) QObject::disconnect(reply, nullptr, this, nullptr);
<< RadioChannel(source_, "Rock Mix 320k AAC", QUrl("https://stream.radioparadise.com/rock-320")) if (reply->isRunning()) reply->abort();
<< RadioChannel(source_, "World/Etc Mix 320k AAC", QUrl("https://stream.radioparadise.com/world-etc-320")) reply->deleteLater();
<< RadioChannel(source_, "Main Mix FLAC", QUrl("https://stream.radioparadise.com/flacm")) }
<< RadioChannel(source_, "Mellow Mix FLAC", QUrl("https://stream.radioparadise.com/mellow-flacm"))
<< RadioChannel(source_, "Rock Mix FLAC", QUrl("https://stream.radioparadise.com/rock-flacm")) channels_.clear();
<< RadioChannel(source_, "World/Etc Mix FLAC", QUrl("https://stream.radioparadise.com/world-etc-flacm"))
); }
void RadioParadiseService::GetChannels() {
Abort();
QUrl url(kApiChannelsUrl);
QNetworkRequest req(url);
QNetworkReply *reply = network_->get(req);
replies_ << reply;
const int task_id = app_->task_manager()->StartTask(tr("Getting %1 channels").arg(name_));
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, task_id]() { GetChannelsReply(reply, task_id); });
}
void RadioParadiseService::GetChannelsReply(QNetworkReply *reply, const int task_id) {
if (replies_.contains(reply)) replies_.removeAll(reply);
reply->deleteLater();
QJsonObject object = ExtractJsonObj(reply);
if (object.isEmpty()) {
app_->task_manager()->SetTaskFinished(task_id);
emit NewChannels();
return;
}
if (!object.contains("channels") || !object["channels"].isArray()) {
Error("Missing JSON channels array.", object);
app_->task_manager()->SetTaskFinished(task_id);
emit NewChannels();
return;
}
QJsonArray array_channels = object["channels"].toArray();
RadioChannelList channels;
for (const QJsonValueRef value_channel : array_channels) {
if (!value_channel.isObject()) continue;
QJsonObject obj_channel = value_channel.toObject();
if (!obj_channel.contains("chan_name") || !obj_channel.contains("streams")) {
continue;
}
QString name = obj_channel["chan_name"].toString();
QJsonValue value_streams = obj_channel["streams"];
if (!value_streams.isArray()) {
continue;
}
QJsonArray array_streams = obj_channel["streams"].toArray();
for (const QJsonValueRef value_stream : array_streams) {
if (!value_stream.isObject()) continue;
QJsonObject obj_stream = value_stream.toObject();
if (!obj_stream.contains("label") || !obj_stream.contains("url")) {
continue;
}
QString label = obj_stream["label"].toString();
QString url = obj_stream["url"].toString();
if (!url.contains(QRegularExpression("^[0-9a-zA-Z]*:\\/\\/", QRegularExpression::CaseInsensitiveOption))) {
url.prepend("https://");
}
RadioChannel channel;
channel.source = source_;
channel.name = name + " - " + label;
channel.url.setUrl(url);
channels << channel;
}
}
app_->task_manager()->SetTaskFinished(task_id);
emit NewChannels(channels);
} }

View File

@ -1,6 +1,6 @@
/* /*
* Strawberry Music Player * Strawberry Music Player
* Copyright 2021, Jonas Kvinge <jonas@jkvinge.net> * Copyright 2021-2024, Jonas Kvinge <jonas@jkvinge.net>
* *
* Strawberry is free software: you can redistribute it and/or modify * Strawberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -24,9 +24,11 @@
#include <QUrl> #include <QUrl>
#include "radioservice.h" #include "radioservice.h"
#include "radiochannel.h"
class Application; class Application;
class NetworkAccessManager; class NetworkAccessManager;
class QNetworkReply;
class RadioParadiseService : public RadioService { class RadioParadiseService : public RadioService {
Q_OBJECT Q_OBJECT
@ -37,8 +39,18 @@ class RadioParadiseService : public RadioService {
QUrl Homepage() override; QUrl Homepage() override;
QUrl Donate() override; QUrl Donate() override;
void Abort();
public slots: public slots:
void GetChannels() override; void GetChannels() override;
private slots:
void GetChannelsReply(QNetworkReply *reply, const int task_id);
private:
static const char *kApiChannelsUrl;
QList<QNetworkReply*> replies_;
RadioChannelList channels_;
}; };
#endif // RADIOPARADISESERVICE_H #endif // RADIOPARADISESERVICE_H

View File

@ -50,14 +50,14 @@ bool ScrobblerService::ExtractJsonObj(const QByteArray &data, QJsonObject &json_
} }
QString ScrobblerService::StripAlbum(QString album) const { QString ScrobblerService::StripAlbum(const QString &album) const {
return album.remove(Song::kAlbumRemoveDisc).remove(Song::kAlbumRemoveMisc); return Song::AlbumRemoveDisc(album);
} }
QString ScrobblerService::StripTitle(QString title) const { QString ScrobblerService::StripTitle(const QString &title) const {
return title.remove(Song::kTitleRemoveMisc); return Song::TitleRemoveMisc(title);
} }

View File

@ -61,8 +61,8 @@ class ScrobblerService : public QObject {
bool ExtractJsonObj(const QByteArray &data, QJsonObject &json_obj, QString &error_description); bool ExtractJsonObj(const QByteArray &data, QJsonObject &json_obj, QString &error_description);
QString StripAlbum(QString album) const; QString StripAlbum(const QString &album) const;
QString StripTitle(QString title) const; QString StripTitle(const QString &title) const;
public slots: public slots:
virtual void Submit() = 0; virtual void Submit() = 0;

View File

@ -174,13 +174,10 @@ ScrobblingAPI20::ReplyResult ScrobblingAPI20::GetJsonObject(QNetworkReply *reply
reply_error_type = ReplyResult::APIError; reply_error_type = ReplyResult::APIError;
} }
const ScrobbleErrorCode lastfm_error_code = static_cast<ScrobbleErrorCode>(error_code); const ScrobbleErrorCode lastfm_error_code = static_cast<ScrobbleErrorCode>(error_code);
if (reply->error() == QNetworkReply::ContentAccessDenied || if (reply->error() == QNetworkReply::AuthenticationRequiredError ||
reply->error() == QNetworkReply::ContentOperationNotPermittedError ||
reply->error() == QNetworkReply::AuthenticationRequiredError ||
lastfm_error_code == ScrobbleErrorCode::InvalidSessionKey || lastfm_error_code == ScrobbleErrorCode::InvalidSessionKey ||
lastfm_error_code == ScrobbleErrorCode::UnauthorizedToken || lastfm_error_code == ScrobbleErrorCode::UnauthorizedToken ||
lastfm_error_code == ScrobbleErrorCode::LoginRequired || lastfm_error_code == ScrobbleErrorCode::LoginRequired ||
lastfm_error_code == ScrobbleErrorCode::AuthenticationFailed ||
lastfm_error_code == ScrobbleErrorCode::APIKeySuspended lastfm_error_code == ScrobbleErrorCode::APIKeySuspended
) { ) {
// Session is probably expired // Session is probably expired

View File

@ -96,6 +96,12 @@ BackendSettingsPage::BackendSettingsPage(SettingsDialog *dialog, QWidget *parent
QObject::connect(ui_->checkbox_channels, &QCheckBox::toggled, ui_->widget_channels, &QSpinBox::setEnabled); QObject::connect(ui_->checkbox_channels, &QCheckBox::toggled, ui_->widget_channels, &QSpinBox::setEnabled);
QObject::connect(ui_->button_buffer_defaults, &QPushButton::clicked, this, &BackendSettingsPage::BufferDefaults); QObject::connect(ui_->button_buffer_defaults, &QPushButton::clicked, this, &BackendSettingsPage::BufferDefaults);
#ifdef Q_OS_WIN32
ui_->widget_exclusive_mode->show();
#else
ui_->widget_exclusive_mode->hide();
#endif
} }
BackendSettingsPage::~BackendSettingsPage() { BackendSettingsPage::~BackendSettingsPage() {
@ -149,6 +155,10 @@ void BackendSettingsPage::Load() {
ui_->widget_alsa_plugin->hide(); ui_->widget_alsa_plugin->hide();
#endif #endif
#ifdef Q_OS_WIN32
ui_->checkbox_exclusive_mode->setChecked(s.value("exclusive_mode", false).toBool());
#endif
if (EngineInitialized()) Load_Engine(enginetype); if (EngineInitialized()) Load_Engine(enginetype);
ui_->checkbox_volume_control->setChecked(s.value("volume_control", true).toBool()); ui_->checkbox_volume_control->setChecked(s.value("volume_control", true).toBool());
@ -331,6 +341,10 @@ void BackendSettingsPage::Load_Output(QString output, QVariant device) {
ui_->groupbox_ebur128->setEnabled(false); ui_->groupbox_ebur128->setEnabled(false);
} }
#ifdef Q_OS_WIN32
ui_->widget_exclusive_mode->setEnabled(engine()->ExclusiveModeSupport(output));
#endif
if (ui_->combobox_output->count() >= 1) Load_Device(output, device); if (ui_->combobox_output->count() >= 1) Load_Device(output, device);
FadingOptionsChanged(); FadingOptionsChanged();
@ -481,6 +495,10 @@ void BackendSettingsPage::Save() {
else s.remove("alsaplugin"); else s.remove("alsaplugin");
#endif #endif
#ifdef Q_OS_WIN32
s.setValue("exclusive_mode", ui_->checkbox_exclusive_mode->isChecked());
#endif
s.setValue("volume_control", ui_->checkbox_volume_control->isChecked()); s.setValue("volume_control", ui_->checkbox_volume_control->isChecked());
s.setValue("channels_enabled", ui_->checkbox_channels->isChecked()); s.setValue("channels_enabled", ui_->checkbox_channels->isChecked());
@ -550,6 +568,11 @@ void BackendSettingsPage::OutputChanged(const int index) {
if (!configloaded_ || !EngineInitialized()) return; if (!configloaded_ || !EngineInitialized()) return;
EngineBase::OutputDetails output = ui_->combobox_output->itemData(index).value<EngineBase::OutputDetails>(); EngineBase::OutputDetails output = ui_->combobox_output->itemData(index).value<EngineBase::OutputDetails>();
#ifdef Q_OS_WIN32
ui_->widget_exclusive_mode->setEnabled(engine()->ExclusiveModeSupport(output.name));
#endif
Load_Device(output.name, QVariant()); Load_Device(output.name, QVariant());
} }

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>717</width> <width>717</width>
<height>1245</height> <height>1259</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -153,6 +153,47 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QWidget" name="widget_exclusive_mode" native="true">
<layout class="QHBoxLayout" name="layout_exclusive_mode">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QCheckBox" name="checkbox_exclusive_mode">
<property name="text">
<string>Exclusive mode (Experimental)</string>
</property>
</widget>
</item>
<item>
<spacer name="spacer_exclusive_mode">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -179,6 +179,7 @@ void CollectionSettingsPage::Load() {
ui_->auto_open->setChecked(s.value("auto_open", true).toBool()); ui_->auto_open->setChecked(s.value("auto_open", true).toBool());
ui_->pretty_covers->setChecked(s.value("pretty_covers", true).toBool()); ui_->pretty_covers->setChecked(s.value("pretty_covers", true).toBool());
ui_->show_dividers->setChecked(s.value("show_dividers", true).toBool()); ui_->show_dividers->setChecked(s.value("show_dividers", true).toBool());
ui_->sort_skips_articles->setChecked(s.value("sort_skips_articles", true).toBool());
ui_->startup_scan->setChecked(s.value("startup_scan", true).toBool()); ui_->startup_scan->setChecked(s.value("startup_scan", true).toBool());
ui_->monitor->setChecked(s.value("monitor", true).toBool()); ui_->monitor->setChecked(s.value("monitor", true).toBool());
ui_->song_tracking->setChecked(s.value("song_tracking", false).toBool()); ui_->song_tracking->setChecked(s.value("song_tracking", false).toBool());
@ -226,6 +227,7 @@ void CollectionSettingsPage::Save() {
s.setValue("auto_open", ui_->auto_open->isChecked()); s.setValue("auto_open", ui_->auto_open->isChecked());
s.setValue("pretty_covers", ui_->pretty_covers->isChecked()); s.setValue("pretty_covers", ui_->pretty_covers->isChecked());
s.setValue("show_dividers", ui_->show_dividers->isChecked()); s.setValue("show_dividers", ui_->show_dividers->isChecked());
s.setValue("sort_skips_articles", ui_->sort_skips_articles->isChecked());
s.setValue("startup_scan", ui_->startup_scan->isChecked()); s.setValue("startup_scan", ui_->startup_scan->isChecked());
s.setValue("monitor", ui_->monitor->isChecked()); s.setValue("monitor", ui_->monitor->isChecked());
s.setValue("song_tracking", ui_->song_tracking->isChecked()); s.setValue("song_tracking", ui_->song_tracking->isChecked());

View File

@ -225,6 +225,13 @@ If there are no matches then it will use the largest image in the directory.</st
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="sort_skips_articles">
<property name="text">
<string>Skip leading articles (&quot;the&quot;, &quot;a&quot;, &quot;an&quot;) when sorting artist names</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -506,6 +513,7 @@ If there are no matches then it will use the largest image in the directory.</st
<tabstop>auto_open</tabstop> <tabstop>auto_open</tabstop>
<tabstop>pretty_covers</tabstop> <tabstop>pretty_covers</tabstop>
<tabstop>show_dividers</tabstop> <tabstop>show_dividers</tabstop>
<tabstop>sort_skips_articles</tabstop>
<tabstop>spinbox_cache_size</tabstop> <tabstop>spinbox_cache_size</tabstop>
<tabstop>combobox_cache_size</tabstop> <tabstop>combobox_cache_size</tabstop>
<tabstop>checkbox_disk_cache</tabstop> <tabstop>checkbox_disk_cache</tabstop>

View File

@ -74,6 +74,9 @@
</item> </item>
<item row="0" column="2"> <item row="0" column="2">
<widget class="QToolButton" name="context_exp_chooser1"> <widget class="QToolButton" name="context_exp_chooser1">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -102,6 +105,9 @@
</item> </item>
<item row="1" column="2"> <item row="1" column="2">
<widget class="QToolButton" name="context_exp_chooser2"> <widget class="QToolButton" name="context_exp_chooser2">
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>

View File

@ -236,6 +236,9 @@
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
@ -267,6 +270,9 @@
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="accessibleName">
<string>MenuPopupToolButton</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>

View File

@ -23,6 +23,7 @@
#include <QCheckBox> #include <QCheckBox>
#include <QComboBox> #include <QComboBox>
#include <QSpinBox> #include <QSpinBox>
#include <QDoubleSpinBox>
#include <QRadioButton> #include <QRadioButton>
#include <QSlider> #include <QSlider>
#include <QLineEdit> #include <QLineEdit>
@ -63,15 +64,26 @@ void SettingsPage::Init(QWidget *ui_widget) {
radiobuttons_ << qMakePair(radiobutton, radiobutton->isChecked()); radiobuttons_ << qMakePair(radiobutton, radiobutton->isChecked());
} }
else if (QComboBox *combobox = qobject_cast<QComboBox*>(w)) { else if (QComboBox *combobox = qobject_cast<QComboBox*>(w)) {
combobox->setFocusPolicy(Qt::StrongFocus);
combobox->installEventFilter(this);
comboboxes_ << qMakePair(combobox, combobox->currentText()); comboboxes_ << qMakePair(combobox, combobox->currentText());
} }
else if (QSpinBox *spinbox = qobject_cast<QSpinBox*>(w)) { else if (QSpinBox *spinbox = qobject_cast<QSpinBox*>(w)) {
spinbox->setFocusPolicy(Qt::StrongFocus);
spinbox->installEventFilter(this);
spinboxes_ << qMakePair(spinbox, spinbox->value()); spinboxes_ << qMakePair(spinbox, spinbox->value());
} }
else if (QDoubleSpinBox *double_spinbox = qobject_cast<QDoubleSpinBox*>(w)) {
double_spinbox->setFocusPolicy(Qt::StrongFocus);
double_spinbox->installEventFilter(this);
double_spinboxes_ << qMakePair(double_spinbox, double_spinbox->value());
}
else if (QLineEdit *lineedit = qobject_cast<QLineEdit*>(w)) { else if (QLineEdit *lineedit = qobject_cast<QLineEdit*>(w)) {
lineedits_ << qMakePair(lineedit, lineedit->text()); lineedits_ << qMakePair(lineedit, lineedit->text());
} }
else if (QSlider *slider = qobject_cast<QSlider*>(w)) { else if (QSlider *slider = qobject_cast<QSlider*>(w)) {
slider->setFocusPolicy(Qt::StrongFocus);
slider->installEventFilter(this);
sliders_ << qMakePair(slider, slider->value()); sliders_ << qMakePair(slider, slider->value());
} }
} }
@ -114,6 +126,11 @@ void SettingsPage::Apply() {
changed_ = true; changed_ = true;
qLog(Info) << spinbox.first->objectName() << "is changed for" << windowTitle() << "settings."; qLog(Info) << spinbox.first->objectName() << "is changed for" << windowTitle() << "settings.";
} }
for (QPair<QDoubleSpinBox*, int> &double_spinbox : double_spinboxes_) {
if (double_spinbox.first->value() == double_spinbox.second) continue;
changed_ = true;
qLog(Info) << double_spinbox.first->objectName() << "is changed for" << windowTitle() << "settings.";
}
for (QPair<QLineEdit*, QString> &lineedit : lineedits_) { for (QPair<QLineEdit*, QString> &lineedit : lineedits_) {
if (lineedit.first->text() == lineedit.second) continue; if (lineedit.first->text() == lineedit.second) continue;
changed_ = true; changed_ = true;
@ -161,3 +178,32 @@ void SettingsPage::ComboBoxLoadFromSettingsByIndex(const QSettings &s, QComboBox
} }
bool SettingsPage::eventFilter(QObject *obj, QEvent *e) {
if (e->type() == QEvent::Wheel) {
if (QComboBox *combobox = qobject_cast<QComboBox*>(obj)) {
if (!combobox->hasFocus()) {
return event(e);
}
}
else if (QSpinBox *spinbox = qobject_cast<QSpinBox*>(obj)) {
if (!spinbox->hasFocus()) {
return event(e);
}
}
else if (QDoubleSpinBox *double_spinbox = qobject_cast<QDoubleSpinBox*>(obj)) {
if (!double_spinbox->hasFocus()) {
return event(e);
}
}
else if (QSlider *slider = qobject_cast<QSlider*>(obj)) {
if (!slider->hasFocus()) {
return event(e);
}
}
}
return false;
}

View File

@ -39,6 +39,7 @@ class QCheckBox;
class QComboBox; class QComboBox;
class QRadioButton; class QRadioButton;
class QSpinBox; class QSpinBox;
class QDoubleSpinBox;
class QSlider; class QSlider;
class QLineEdit; class QLineEdit;
class QShowEvent; class QShowEvent;
@ -75,6 +76,9 @@ class SettingsPage : public QWidget {
virtual void Save() = 0; virtual void Save() = 0;
virtual void Cancel() {} virtual void Cancel() {}
protected:
bool eventFilter(QObject *obj, QEvent *e) override;
signals: signals:
void NotificationPreview(const OSDBase::Behaviour, const QString&, const QString&); void NotificationPreview(const OSDBase::Behaviour, const QString&, const QString&);
@ -86,6 +90,7 @@ class SettingsPage : public QWidget {
QList<QPair<QRadioButton*, bool>> radiobuttons_; QList<QPair<QRadioButton*, bool>> radiobuttons_;
QList<QPair<QComboBox*, QString>> comboboxes_; QList<QPair<QComboBox*, QString>> comboboxes_;
QList<QPair<QSpinBox*, int>> spinboxes_; QList<QPair<QSpinBox*, int>> spinboxes_;
QList<QPair<QDoubleSpinBox*, int>> double_spinboxes_;
QList<QPair<QSlider*, int>> sliders_; QList<QPair<QSlider*, int>> sliders_;
QList<QPair<QLineEdit*, QString>> lineedits_; QList<QPair<QLineEdit*, QString>> lineedits_;
}; };

View File

@ -124,7 +124,7 @@
<item> <item>
<widget class="QRadioButton" name="auth_method_md5"> <widget class="QRadioButton" name="auth_method_md5">
<property name="text"> <property name="text">
<string>MD5 token</string> <string>MD5 token (Recommended)</string>
</property> </property>
</widget> </widget>
</item> </item>

View File

@ -1129,7 +1129,7 @@ void TidalRequest::ParseSong(Song &song, const QJsonObject &json_obj, const Arti
} }
} }
title.remove(Song::kTitleRemoveMisc); title = Song::TitleRemoveMisc(title);
//qLog(Debug) << "id" << song_id << "track" << track << "disc" << disc << "title" << title << "album" << album << "album artist" << album_artist << "artist" << artist << cover << allow_streaming << url; //qLog(Debug) << "id" << song_id << "track" << track << "disc" << disc << "title" << title << "album" << album << "album artist" << album_artist << "artist" << artist << cover << allow_streaming << url;

View File

@ -742,7 +742,7 @@ msgstr "Després de copiar…"
msgid "Albu&m cover" msgid "Albu&m cover"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1365 #: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1369
#: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194 #: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194
#: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238 #: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238
#: ../build/src/ui_albumcoversearcher.h:108 #: ../build/src/ui_albumcoversearcher.h:108
@ -762,7 +762,7 @@ msgstr "Àlbum (volum ideal per a totes les peces)"
msgid "Album - Disc" msgid "Album - Disc"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1372 #: playlist/playlist.cpp:1376
msgid "Album Artist" msgid "Album Artist"
msgstr "" msgstr ""
@ -851,7 +851,7 @@ msgstr "Comença sempre la reproducció"
msgid "An error occurred loading the iTunes database" msgid "An error occurred loading the iTunes database"
msgstr "Sha produït un error en carregar la base de dades de liTunes" msgstr "Sha produït un error en carregar la base de dades de liTunes"
#: playlist/playlist.cpp:426 dialogs/edittagdialog.cpp:1450 #: playlist/playlist.cpp:430 dialogs/edittagdialog.cpp:1450
#, qt-format #, qt-format
msgid "An error occurred writing metadata to '%1'" msgid "An error occurred writing metadata to '%1'"
msgstr "Sha produït un error en escriure les metadades a «%1»" msgstr "Sha produït un error en escriure les metadades a «%1»"
@ -880,7 +880,7 @@ msgstr ""
msgid "Append files/URLs to the playlist" msgid "Append files/URLs to the playlist"
msgstr "Afegeix fitxers/URL a la llista de reproducció" msgstr "Afegeix fitxers/URL a la llista de reproducció"
#: collection/collectionview.cpp:350 #: collection/collectionview.cpp:366
#: smartplaylists/smartplaylistsviewcontainer.cpp:65 #: smartplaylists/smartplaylistsviewcontainer.cpp:65
#: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316 #: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316
#: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69 #: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69
@ -931,7 +931,7 @@ msgstr ""
msgid "Art Unset" msgid "Art Unset"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1364 #: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1368
#: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192 #: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192
#: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236 #: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236
#: ../build/src/ui_albumcoversearcher.h:104 #: ../build/src/ui_albumcoversearcher.h:104
@ -1093,7 +1093,7 @@ msgstr "Comportament"
msgid "Best" msgid "Best"
msgstr "Millor" msgstr "Millor"
#: playlist/playlist.cpp:1382 #: playlist/playlist.cpp:1386
msgid "Bit Depth" msgid "Bit Depth"
msgstr "" msgstr ""
@ -1109,7 +1109,7 @@ msgid "Bit rate"
msgstr "Taxa de bits" msgstr "Taxa de bits"
#: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149 #: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149
#: playlist/playlist.cpp:1383 ../build/src/ui_groupbydialog.h:210 #: playlist/playlist.cpp:1387 ../build/src/ui_groupbydialog.h:210
#: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254 #: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254
#: ../build/src/ui_transcoderoptionsaac.h:132 #: ../build/src/ui_transcoderoptionsaac.h:132
#: ../build/src/ui_transcoderoptionsopus.h:76 #: ../build/src/ui_transcoderoptionsopus.h:76
@ -1180,7 +1180,7 @@ msgstr ""
msgid "CDDA" msgid "CDDA"
msgstr "CDDA" msgstr "CDDA"
#: playlist/playlist.cpp:1396 #: playlist/playlist.cpp:1400
msgid "CUE" msgid "CUE"
msgstr "" msgstr ""
@ -1338,7 +1338,7 @@ msgstr "Cerca a la col·lecció"
msgid "Comma separated list of class:level, level is 0-3" msgid "Comma separated list of class:level, level is 0-3"
msgstr "Llista separada per comes de classe:nivell, el nivell és 0-3" msgstr "Llista separada per comes de classe:nivell, el nivell és 0-3"
#: playlist/playlist.cpp:1392 smartplaylists/smartplaylistsearchterm.cpp:391 #: playlist/playlist.cpp:1396 smartplaylists/smartplaylistsearchterm.cpp:391
#: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918 #: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918
msgid "Comment" msgid "Comment"
msgstr "Comentari" msgstr "Comentari"
@ -1355,7 +1355,7 @@ msgstr "Completa les etiquetes automàticament"
msgid "Complete tags automatically..." msgid "Complete tags automatically..."
msgstr "Completa les etiquetes automàticament…" msgstr "Completa les etiquetes automàticament…"
#: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1373 #: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1377
#: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204 #: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204
#: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248 #: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248
#: ../build/src/ui_edittagdialog.h:915 #: ../build/src/ui_edittagdialog.h:915
@ -1436,7 +1436,7 @@ msgstr "Copia a la col·lecció…"
msgid "Copy to device" msgid "Copy to device"
msgstr "" msgstr ""
#: core/mainwindow.cpp:758 collection/collectionview.cpp:361 #: core/mainwindow.cpp:758 collection/collectionview.cpp:381
#: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48 #: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48
msgid "Copy to device..." msgid "Copy to device..."
msgstr "Copia al dispositiu…" msgstr "Copia al dispositiu…"
@ -1447,6 +1447,16 @@ msgid ""
"avoid losing configuration before you uninstall the snap:" "avoid losing configuration before you uninstall the snap:"
msgstr "" msgstr ""
#: device/gpoddevice.cpp:241
#, qt-format
msgid "Could not copy %1 to %2: %3"
msgstr ""
#: core/filesystemmusicstorage.cpp:98
#, qt-format
msgid "Could not copy file %1 to %2."
msgstr ""
#: transcoder/transcoder.cpp:72 #: transcoder/transcoder.cpp:72
#, qt-format #, qt-format
msgid "" msgid ""
@ -1461,6 +1471,10 @@ msgstr ""
msgid "Could not open CUE file %1 for reading: %2" msgid "Could not open CUE file %1 for reading: %2"
msgstr "" msgstr ""
#: device/mtpconnection.cpp:75 device/mtpconnection.cpp:109
msgid "Could not open MTP device."
msgstr ""
#: scrobbler/scrobblingapi20.cpp:223 #: scrobbler/scrobblingapi20.cpp:223
msgid "Could not open URL. Please open this URL in your browser" msgid "Could not open URL. Please open this URL in your browser"
msgstr "" msgstr ""
@ -1692,11 +1706,11 @@ msgstr "Dance"
msgid "Database corruption detected." msgid "Database corruption detected."
msgstr "" msgstr ""
#: playlist/playlist.cpp:1390 #: playlist/playlist.cpp:1394
msgid "Date Created" msgid "Date Created"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1389 #: playlist/playlist.cpp:1393
msgid "Date Modified" msgid "Date Modified"
msgstr "" msgstr ""
@ -1749,7 +1763,7 @@ msgstr "Suprimeix els fitxers"
msgid "Delete from device..." msgid "Delete from device..."
msgstr "Suprimeix del dispositiu…" msgstr "Suprimeix del dispositiu…"
#: core/mainwindow.cpp:760 collection/collectionview.cpp:363 #: core/mainwindow.cpp:760 collection/collectionview.cpp:383
#: widgets/fileviewlist.cpp:49 #: widgets/fileviewlist.cpp:49
msgid "Delete from disk..." msgid "Delete from disk..."
msgstr "Suprimeix del disc…" msgstr "Suprimeix del disc…"
@ -1787,6 +1801,16 @@ msgstr "Treu de la cua la peça"
msgid "Destination" msgid "Destination"
msgstr "Destí" msgstr "Destí"
#: core/filesystemmusicstorage.cpp:92
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite"
msgstr ""
#: core/filesystemmusicstorage.cpp:73
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite."
msgstr ""
#: ../build/src/ui_transcodedialog.h:235 #: ../build/src/ui_transcodedialog.h:235
msgid "Details..." msgid "Details..."
msgstr "Detalls…" msgstr "Detalls…"
@ -1833,7 +1857,7 @@ msgctxt "Refers to a disabled notification type in Notification settings."
msgid "Disabled" msgid "Disabled"
msgstr "Inhabilitat" msgstr "Inhabilitat"
#: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1367 #: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1371
#: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196 #: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196
#: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240 #: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240
#: ../build/src/ui_edittagdialog.h:908 #: ../build/src/ui_edittagdialog.h:908
@ -1877,7 +1901,7 @@ msgstr ""
msgid "Don't repeat" msgid "Don't repeat"
msgstr "Sense repetició" msgstr "Sense repetició"
#: collection/collectionview.cpp:376 #: collection/collectionview.cpp:396
msgid "Don't show in various artists" msgid "Don't show in various artists"
msgstr "No ho mostris a Artistes diversos" msgstr "No ho mostris a Artistes diversos"
@ -1974,12 +1998,12 @@ msgstr "Edita letiqueta…"
msgid "Edit track information" msgid "Edit track information"
msgstr "Edita la informació de la peça" msgstr "Edita la informació de la peça"
#: collection/collectionview.cpp:366 widgets/fileviewlist.cpp:52 #: collection/collectionview.cpp:386 widgets/fileviewlist.cpp:52
#: ../build/src/ui_mainwindow.h:642 #: ../build/src/ui_mainwindow.h:642
msgid "Edit track information..." msgid "Edit track information..."
msgstr "Edita la informació de la peça…" msgstr "Edita la informació de la peça…"
#: collection/collectionview.cpp:367 #: collection/collectionview.cpp:387
msgid "Edit tracks information..." msgid "Edit tracks information..."
msgstr "Edita la informació de les peces..." msgstr "Edita la informació de les peces..."
@ -2130,7 +2154,7 @@ msgid "Equivalent to --log-levels *:3"
msgstr "Equivalent a --log-levels *:3" msgstr "Equivalent a --log-levels *:3"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
@ -2139,6 +2163,11 @@ msgstr "Error"
msgid "Error connecting MTP device %1" msgid "Error connecting MTP device %1"
msgstr "" msgstr ""
#: device/mtploader.cpp:77
#, qt-format
msgid "Error connecting MTP device %1: %2"
msgstr ""
#: organize/organizeerrordialog.cpp:71 #: organize/organizeerrordialog.cpp:71
msgid "Error copying songs" msgid "Error copying songs"
msgstr "Sha produït un error en copiar les cançons" msgstr "Sha produït un error en copiar les cançons"
@ -2265,6 +2294,11 @@ msgstr "Durada de lesvaïment"
msgid "Failed SQL query: %1" msgid "Failed SQL query: %1"
msgstr "" msgstr ""
#: core/filesystemmusicstorage.cpp:57
#, qt-format
msgid "Failed to create directory %1."
msgstr ""
#: covermanager/albumcoverchoicecontroller.cpp:379 #: covermanager/albumcoverchoicecontroller.cpp:379
#: covermanager/albumcoverchoicecontroller.cpp:396 #: covermanager/albumcoverchoicecontroller.cpp:396
#, qt-format #, qt-format
@ -2341,19 +2375,19 @@ msgstr ""
msgid "File %1 is not recognized as a valid audio file." msgid "File %1 is not recognized as a valid audio file."
msgstr "" msgstr ""
#: playlist/playlist.cpp:1385 #: playlist/playlist.cpp:1389
msgid "File Name" msgid "File Name"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1386 #: playlist/playlist.cpp:1390
msgid "File Name (without path)" msgid "File Name (without path)"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1387 #: playlist/playlist.cpp:1391
msgid "File Size" msgid "File Size"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1388 #: playlist/playlist.cpp:1392
msgid "File Type" msgid "File Type"
msgstr "" msgstr ""
@ -2532,7 +2566,7 @@ msgstr "Configuració general"
msgid "Genius Authentication" msgid "Genius Authentication"
msgstr "Autenticació amb el Genius" msgstr "Autenticació amb el Genius"
#: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1371 #: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1375
#: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198 #: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198
#: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242 #: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242
#: ../build/src/ui_edittagdialog.h:917 #: ../build/src/ui_edittagdialog.h:917
@ -2640,7 +2674,7 @@ msgstr ""
msgid "Group by Genre/Artist/Album" msgid "Group by Genre/Artist/Album"
msgstr "Agrupa per gènere/artista/àlbum" msgstr "Agrupa per gènere/artista/àlbum"
#: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1375 #: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1379
#: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206 #: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206
#: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250 #: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250
#: ../build/src/ui_edittagdialog.h:909 #: ../build/src/ui_edittagdialog.h:909
@ -2813,7 +2847,7 @@ msgstr "Insereix…"
msgid "Install strawberry through PPA:" msgid "Install strawberry through PPA:"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1398 #: playlist/playlist.cpp:1402
msgid "Integrated Loudness" msgid "Integrated Loudness"
msgstr "" msgstr ""
@ -2833,6 +2867,11 @@ msgstr ""
msgid "Intro tracks" msgid "Intro tracks"
msgstr "Peces dintroducció" msgstr "Peces dintroducció"
#: device/mtpconnection.cpp:57
#, qt-format
msgid "Invalid MTP device: %1"
msgstr ""
#: scrobbler/scrobblingapi20.cpp:257 #: scrobbler/scrobblingapi20.cpp:257
msgid "Invalid reply from web browser. Missing token." msgid "Invalid reply from web browser. Missing token."
msgstr "" msgstr ""
@ -2892,7 +2931,7 @@ msgstr "Coberta dàlbum gran"
msgid "Large sidebar" msgid "Large sidebar"
msgstr "Barra lateral gran" msgstr "Barra lateral gran"
#: playlist/playlist.cpp:1379 #: playlist/playlist.cpp:1383
msgid "Last Played" msgid "Last Played"
msgstr "" msgstr ""
@ -2923,7 +2962,7 @@ msgstr ""
msgid "Left" msgid "Left"
msgstr "Esquerra" msgstr "Esquerra"
#: context/contextview.cpp:163 playlist/playlist.cpp:1368 #: context/contextview.cpp:163 playlist/playlist.cpp:1372
#: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888 #: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888
msgid "Length" msgid "Length"
msgstr "Durada" msgstr "Durada"
@ -3030,7 +3069,7 @@ msgstr "Entra"
msgid "Long term prediction profile (LTP)" msgid "Long term prediction profile (LTP)"
msgstr "Perfil de predicció a llarg termini (LTP)" msgstr "Perfil de predicció a llarg termini (LTP)"
#: playlist/playlist.cpp:1399 #: playlist/playlist.cpp:1403
msgid "Loudness Range" msgid "Loudness Range"
msgstr "" msgstr ""
@ -3065,13 +3104,22 @@ msgid "Lyrics providers"
msgstr "" msgstr ""
#: ../build/src/ui_subsonicsettingspage.h:251 #: ../build/src/ui_subsonicsettingspage.h:251
msgid "MD5 token" msgid "MD5 token (Recommended)"
msgstr "" msgstr ""
#: ../build/src/ui_transcodersettingspage.h:194 #: ../build/src/ui_transcodersettingspage.h:194
msgid "MP3" msgid "MP3"
msgstr "MP3" msgstr "MP3"
#: device/mtpconnection.cpp:100
msgid "MTP device not found."
msgstr ""
#: device/mtpconnection.cpp:86
#, qt-format
msgid "MTP error: %1"
msgstr ""
#: ../build/src/ui_transcoderoptionsaac.h:135 #: ../build/src/ui_transcoderoptionsaac.h:135
msgid "Main profile (MAIN)" msgid "Main profile (MAIN)"
msgstr "Perfil principal (MAIN)" msgstr "Perfil principal (MAIN)"
@ -3223,7 +3271,7 @@ msgstr "Monitoritza els canvis a la col·lecció"
msgid "Months" msgid "Months"
msgstr "Mesos" msgstr "Mesos"
#: playlist/playlist.cpp:1394 #: playlist/playlist.cpp:1398
msgid "Mood" msgid "Mood"
msgstr "" msgstr ""
@ -3401,7 +3449,7 @@ msgid "None"
msgstr "Cap" msgstr "Cap"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "None of the selected songs were suitable for copying to a device" msgid "None of the selected songs were suitable for copying to a device"
msgstr "" msgstr ""
"Cap de les cançons seleccionades són adequades per copiar-les a un " "Cap de les cançons seleccionades són adequades per copiar-les a un "
@ -3502,7 +3550,7 @@ msgstr "Obrir dispositiu"
msgid "Open homepage" msgid "Open homepage"
msgstr "" msgstr ""
#: collection/collectionview.cpp:352 #: collection/collectionview.cpp:368
#: smartplaylists/smartplaylistsviewcontainer.cpp:67 #: smartplaylists/smartplaylistsviewcontainer.cpp:67
#: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318 #: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318
#: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77 #: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77
@ -3540,7 +3588,7 @@ msgstr "Opus"
msgid "Organize Files" msgid "Organize Files"
msgstr "" msgstr ""
#: core/mainwindow.cpp:754 collection/collectionview.cpp:359 #: core/mainwindow.cpp:754 collection/collectionview.cpp:379
msgid "Organize files..." msgid "Organize files..."
msgstr "" msgstr ""
@ -3548,7 +3596,7 @@ msgstr ""
msgid "Organizing files" msgid "Organizing files"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1370 #: playlist/playlist.cpp:1374
msgid "Original Year" msgid "Original Year"
msgstr "" msgstr ""
@ -3655,7 +3703,7 @@ msgstr ""
msgid "Perform track loudness normalization" msgid "Perform track loudness normalization"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1374 #: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1378
#: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205 #: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205
#: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249 #: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249
#: ../build/src/ui_edittagdialog.h:919 #: ../build/src/ui_edittagdialog.h:919
@ -3676,7 +3724,7 @@ msgstr "Barra lateral senzilla"
msgid "Play" msgid "Play"
msgstr "Reprodueix" msgstr "Reprodueix"
#: playlist/playlist.cpp:1377 #: playlist/playlist.cpp:1381
msgid "Play Count" msgid "Play Count"
msgstr "" msgstr ""
@ -3936,12 +3984,12 @@ msgstr "Afegeix les peces seleccionades a la cua"
msgid "Queue selected tracks to play next" msgid "Queue selected tracks to play next"
msgstr "" msgstr ""
#: core/mainwindow.cpp:1961 collection/collectionview.cpp:356 #: core/mainwindow.cpp:1961 collection/collectionview.cpp:372
#: internet/internetcollectionview.cpp:321 #: internet/internetcollectionview.cpp:321
msgid "Queue to play next" msgid "Queue to play next"
msgstr "" msgstr ""
#: core/mainwindow.cpp:1953 collection/collectionview.cpp:355 #: core/mainwindow.cpp:1953 collection/collectionview.cpp:371
#: smartplaylists/smartplaylistsviewcontainer.cpp:70 #: smartplaylists/smartplaylistsviewcontainer.cpp:70
#: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320 #: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320
msgid "Queue track" msgid "Queue track"
@ -3967,7 +4015,7 @@ msgstr ""
msgid "Random" msgid "Random"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1395 ../build/src/ui_edittagdialog.h:922 #: playlist/playlist.cpp:1399 ../build/src/ui_edittagdialog.h:922
msgid "Rating" msgid "Rating"
msgstr "" msgstr ""
@ -4167,7 +4215,7 @@ msgstr "Repeteix la llista de reproducció"
msgid "Repeat track" msgid "Repeat track"
msgstr "Repeteix la peça" msgstr "Repeteix la peça"
#: collection/collectionview.cpp:351 #: collection/collectionview.cpp:367
#: smartplaylists/smartplaylistsviewcontainer.cpp:66 #: smartplaylists/smartplaylistsviewcontainer.cpp:66
#: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317 #: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317
#: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73 #: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73
@ -4203,7 +4251,7 @@ msgstr ""
msgid "Repopulate" msgid "Repopulate"
msgstr "" msgstr ""
#: collection/collectionview.cpp:372 #: collection/collectionview.cpp:392
msgid "Rescan song(s)" msgid "Rescan song(s)"
msgstr "" msgstr ""
@ -4306,7 +4354,7 @@ msgstr "Treure el dispositiu amb seguretat"
msgid "Safely remove the device after copying" msgid "Safely remove the device after copying"
msgstr "Treure el dispositiu amb seguretat després de copiar" msgstr "Treure el dispositiu amb seguretat després de copiar"
#: playlist/playlist.cpp:1381 #: playlist/playlist.cpp:1385
msgid "Sample Rate" msgid "Sample Rate"
msgstr "" msgstr ""
@ -4440,7 +4488,7 @@ msgstr ""
msgid "Search for album covers..." msgid "Search for album covers..."
msgstr "Cerca cobertes dels àlbums…" msgstr "Cerca cobertes dels àlbums…"
#: internet/internetsearchview.cpp:339 #: collection/collectionview.cpp:376 internet/internetsearchview.cpp:339
msgid "Search for this" msgid "Search for this"
msgstr "Cerca-ho" msgstr "Cerca-ho"
@ -4672,12 +4720,12 @@ msgstr "Mostra a la col·lecció…"
msgid "Show in file browser" msgid "Show in file browser"
msgstr "" msgstr ""
#: core/mainwindow.cpp:753 collection/collectionview.cpp:368 #: core/mainwindow.cpp:753 collection/collectionview.cpp:388
#: widgets/fileviewlist.cpp:53 #: widgets/fileviewlist.cpp:53
msgid "Show in file browser..." msgid "Show in file browser..."
msgstr "Mostra al gestor de fitxers" msgstr "Mostra al gestor de fitxers"
#: collection/collectionview.cpp:375 #: collection/collectionview.cpp:395
msgid "Show in various artists" msgid "Show in various artists"
msgstr "Mostra en Artistes diversos" msgstr "Mostra en Artistes diversos"
@ -4778,7 +4826,7 @@ msgstr "Mida:"
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"
#: playlist/playlist.cpp:1378 #: playlist/playlist.cpp:1382
msgid "Skip Count" msgid "Skip Count"
msgstr "" msgstr ""
@ -4874,7 +4922,7 @@ msgstr ""
msgid "Sorting" msgid "Sorting"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1393 #: playlist/playlist.cpp:1397
msgid "Source" msgid "Source"
msgstr "Font" msgstr "Font"
@ -5184,7 +5232,7 @@ msgstr ""
"La versió de Strawberry a la que us acabeu dactualitzar necessita tornar a " "La versió de Strawberry a la que us acabeu dactualitzar necessita tornar a "
"analitzar tota la col·lecció perquè incorpora les següents funcions noves:" "analitzar tota la col·lecció perquè incorpora les següents funcions noves:"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "There are other songs in this album" msgid "There are other songs in this album"
msgstr "Hi ha altres cançons en aquest àlbum" msgstr "Hi ha altres cançons en aquest àlbum"
@ -5300,7 +5348,7 @@ msgstr ""
msgid "Time step" msgid "Time step"
msgstr "Salt en el temps" msgstr "Salt en el temps"
#: playlist/playlist.cpp:1363 organize/organizedialog.cpp:104 #: playlist/playlist.cpp:1367 organize/organizedialog.cpp:104
#: ../build/src/ui_contextsettingspage.h:422 #: ../build/src/ui_contextsettingspage.h:422
#: ../build/src/ui_edittagdialog.h:913 #: ../build/src/ui_edittagdialog.h:913
#: ../build/src/ui_trackselectiondialog.h:210 #: ../build/src/ui_trackselectiondialog.h:210
@ -5351,7 +5399,7 @@ msgstr "Bytes totals transferits"
msgid "Total network requests made" msgid "Total network requests made"
msgstr "Total de sol·licituds de xarxa fetes" msgstr "Total de sol·licituds de xarxa fetes"
#: playlist/playlist.cpp:1366 organize/organizedialog.cpp:112 #: playlist/playlist.cpp:1370 organize/organizedialog.cpp:112
#: ../build/src/ui_edittagdialog.h:921 #: ../build/src/ui_edittagdialog.h:921
#: ../build/src/ui_trackselectiondialog.h:212 #: ../build/src/ui_trackselectiondialog.h:212
msgid "Track" msgid "Track"
@ -5697,7 +5745,7 @@ msgstr "Sense coberta:"
msgid "Work in offline mode (Only cache scrobbles)" msgid "Work in offline mode (Only cache scrobbles)"
msgstr "" msgstr ""
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "" msgid ""
"Would you like to move the other songs on this album to Various Artists as " "Would you like to move the other songs on this album to Various Artists as "
"well?" "well?"
@ -5715,7 +5763,16 @@ msgstr ""
msgid "Write metadata when saving playlists" msgid "Write metadata when saving playlists"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1369 #: device/gpoddevice.cpp:288
msgid "Writing database failed."
msgstr ""
#: device/gpoddevice.cpp:284
#, qt-format
msgid "Writing database failed: %1"
msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1373
#: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199 #: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199
#: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243 #: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243
#: ../build/src/ui_edittagdialog.h:912 #: ../build/src/ui_edittagdialog.h:912

View File

@ -748,7 +748,7 @@ msgstr "Po zkopírování..."
msgid "Albu&m cover" msgid "Albu&m cover"
msgstr "Obal alb&a" msgstr "Obal alb&a"
#: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1365 #: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1369
#: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194 #: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194
#: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238 #: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238
#: ../build/src/ui_albumcoversearcher.h:108 #: ../build/src/ui_albumcoversearcher.h:108
@ -768,7 +768,7 @@ msgstr "Album (ideální hlasitost pro všechny skladby)"
msgid "Album - Disc" msgid "Album - Disc"
msgstr "Album - Disk" msgstr "Album - Disk"
#: playlist/playlist.cpp:1372 #: playlist/playlist.cpp:1376
msgid "Album Artist" msgid "Album Artist"
msgstr "" msgstr ""
@ -857,7 +857,7 @@ msgstr "Vždy začít přehrávat"
msgid "An error occurred loading the iTunes database" msgid "An error occurred loading the iTunes database"
msgstr "Při nahrávání databáze iTunes nastala chyba" msgstr "Při nahrávání databáze iTunes nastala chyba"
#: playlist/playlist.cpp:426 dialogs/edittagdialog.cpp:1450 #: playlist/playlist.cpp:430 dialogs/edittagdialog.cpp:1450
#, qt-format #, qt-format
msgid "An error occurred writing metadata to '%1'" msgid "An error occurred writing metadata to '%1'"
msgstr "Při zápisu údajů do '%1' se vyskytla chyba" msgstr "Při zápisu údajů do '%1' se vyskytla chyba"
@ -886,7 +886,7 @@ msgstr ""
msgid "Append files/URLs to the playlist" msgid "Append files/URLs to the playlist"
msgstr "Přidat soubory/adresy do seznamu skladeb" msgstr "Přidat soubory/adresy do seznamu skladeb"
#: collection/collectionview.cpp:350 #: collection/collectionview.cpp:366
#: smartplaylists/smartplaylistsviewcontainer.cpp:65 #: smartplaylists/smartplaylistsviewcontainer.cpp:65
#: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316 #: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316
#: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69 #: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69
@ -937,7 +937,7 @@ msgstr ""
msgid "Art Unset" msgid "Art Unset"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1364 #: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1368
#: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192 #: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192
#: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236 #: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236
#: ../build/src/ui_albumcoversearcher.h:104 #: ../build/src/ui_albumcoversearcher.h:104
@ -1098,7 +1098,7 @@ msgstr "Chování"
msgid "Best" msgid "Best"
msgstr "Nejlepší" msgstr "Nejlepší"
#: playlist/playlist.cpp:1382 #: playlist/playlist.cpp:1386
msgid "Bit Depth" msgid "Bit Depth"
msgstr "" msgstr ""
@ -1114,7 +1114,7 @@ msgid "Bit rate"
msgstr "Datový tok" msgstr "Datový tok"
#: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149 #: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149
#: playlist/playlist.cpp:1383 ../build/src/ui_groupbydialog.h:210 #: playlist/playlist.cpp:1387 ../build/src/ui_groupbydialog.h:210
#: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254 #: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254
#: ../build/src/ui_transcoderoptionsaac.h:132 #: ../build/src/ui_transcoderoptionsaac.h:132
#: ../build/src/ui_transcoderoptionsopus.h:76 #: ../build/src/ui_transcoderoptionsopus.h:76
@ -1186,7 +1186,7 @@ msgstr "Přehrávání disků CD je možné pouze za použití GStreamer enginu.
msgid "CDDA" msgid "CDDA"
msgstr "CDDA" msgstr "CDDA"
#: playlist/playlist.cpp:1396 #: playlist/playlist.cpp:1400
msgid "CUE" msgid "CUE"
msgstr "" msgstr ""
@ -1342,7 +1342,7 @@ msgstr "Hledání v kolekci"
msgid "Comma separated list of class:level, level is 0-3" msgid "Comma separated list of class:level, level is 0-3"
msgstr "Čárkou oddělený seznam class:level, level je 0-3" msgstr "Čárkou oddělený seznam class:level, level je 0-3"
#: playlist/playlist.cpp:1392 smartplaylists/smartplaylistsearchterm.cpp:391 #: playlist/playlist.cpp:1396 smartplaylists/smartplaylistsearchterm.cpp:391
#: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918 #: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918
msgid "Comment" msgid "Comment"
msgstr "Poznámka" msgstr "Poznámka"
@ -1359,7 +1359,7 @@ msgstr "Doplnit značky automaticky"
msgid "Complete tags automatically..." msgid "Complete tags automatically..."
msgstr "Doplnit značky automaticky..." msgstr "Doplnit značky automaticky..."
#: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1373 #: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1377
#: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204 #: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204
#: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248 #: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248
#: ../build/src/ui_edittagdialog.h:915 #: ../build/src/ui_edittagdialog.h:915
@ -1440,7 +1440,7 @@ msgstr "Zkopírovat do sbírky..."
msgid "Copy to device" msgid "Copy to device"
msgstr "Zkopírovat na zařízení" msgstr "Zkopírovat na zařízení"
#: core/mainwindow.cpp:758 collection/collectionview.cpp:361 #: core/mainwindow.cpp:758 collection/collectionview.cpp:381
#: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48 #: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48
msgid "Copy to device..." msgid "Copy to device..."
msgstr "Zkopírovat do zařízení..." msgstr "Zkopírovat do zařízení..."
@ -1451,6 +1451,16 @@ msgid ""
"avoid losing configuration before you uninstall the snap:" "avoid losing configuration before you uninstall the snap:"
msgstr "" msgstr ""
#: device/gpoddevice.cpp:241
#, qt-format
msgid "Could not copy %1 to %2: %3"
msgstr ""
#: core/filesystemmusicstorage.cpp:98
#, qt-format
msgid "Could not copy file %1 to %2."
msgstr ""
#: transcoder/transcoder.cpp:72 #: transcoder/transcoder.cpp:72
#, qt-format #, qt-format
msgid "" msgid ""
@ -1465,6 +1475,10 @@ msgstr ""
msgid "Could not open CUE file %1 for reading: %2" msgid "Could not open CUE file %1 for reading: %2"
msgstr "" msgstr ""
#: device/mtpconnection.cpp:75 device/mtpconnection.cpp:109
msgid "Could not open MTP device."
msgstr ""
#: scrobbler/scrobblingapi20.cpp:223 #: scrobbler/scrobblingapi20.cpp:223
msgid "Could not open URL. Please open this URL in your browser" msgid "Could not open URL. Please open this URL in your browser"
msgstr "" msgstr ""
@ -1697,11 +1711,11 @@ msgstr "Taneční hudba"
msgid "Database corruption detected." msgid "Database corruption detected."
msgstr "Databáze je poškozená." msgstr "Databáze je poškozená."
#: playlist/playlist.cpp:1390 #: playlist/playlist.cpp:1394
msgid "Date Created" msgid "Date Created"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1389 #: playlist/playlist.cpp:1393
msgid "Date Modified" msgid "Date Modified"
msgstr "" msgstr ""
@ -1754,7 +1768,7 @@ msgstr "Smazat soubory"
msgid "Delete from device..." msgid "Delete from device..."
msgstr "Smazat ze zařízení..." msgstr "Smazat ze zařízení..."
#: core/mainwindow.cpp:760 collection/collectionview.cpp:363 #: core/mainwindow.cpp:760 collection/collectionview.cpp:383
#: widgets/fileviewlist.cpp:49 #: widgets/fileviewlist.cpp:49
msgid "Delete from disk..." msgid "Delete from disk..."
msgstr "Smazat z disku..." msgstr "Smazat z disku..."
@ -1792,6 +1806,16 @@ msgstr "Odstranit skladbu z řady"
msgid "Destination" msgid "Destination"
msgstr "Cíl" msgstr "Cíl"
#: core/filesystemmusicstorage.cpp:92
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite"
msgstr ""
#: core/filesystemmusicstorage.cpp:73
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite."
msgstr ""
#: ../build/src/ui_transcodedialog.h:235 #: ../build/src/ui_transcodedialog.h:235
msgid "Details..." msgid "Details..."
msgstr "Podrobnosti..." msgstr "Podrobnosti..."
@ -1838,7 +1862,7 @@ msgctxt "Refers to a disabled notification type in Notification settings."
msgid "Disabled" msgid "Disabled"
msgstr "Zakázáno" msgstr "Zakázáno"
#: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1367 #: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1371
#: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196 #: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196
#: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240 #: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240
#: ../build/src/ui_edittagdialog.h:908 #: ../build/src/ui_edittagdialog.h:908
@ -1882,7 +1906,7 @@ msgstr "Tuto zprávu již nezobrazovat."
msgid "Don't repeat" msgid "Don't repeat"
msgstr "Neopakovat" msgstr "Neopakovat"
#: collection/collectionview.cpp:376 #: collection/collectionview.cpp:396
msgid "Don't show in various artists" msgid "Don't show in various artists"
msgstr "Nezobrazovat pod různými umělci" msgstr "Nezobrazovat pod různými umělci"
@ -1979,12 +2003,12 @@ msgstr "Upravit značku..."
msgid "Edit track information" msgid "Edit track information"
msgstr "Upravit informace o skladbě" msgstr "Upravit informace o skladbě"
#: collection/collectionview.cpp:366 widgets/fileviewlist.cpp:52 #: collection/collectionview.cpp:386 widgets/fileviewlist.cpp:52
#: ../build/src/ui_mainwindow.h:642 #: ../build/src/ui_mainwindow.h:642
msgid "Edit track information..." msgid "Edit track information..."
msgstr "Upravit informace o skladbě..." msgstr "Upravit informace o skladbě..."
#: collection/collectionview.cpp:367 #: collection/collectionview.cpp:387
msgid "Edit tracks information..." msgid "Edit tracks information..."
msgstr "Upravit informace o skladbách..." msgstr "Upravit informace o skladbách..."
@ -2134,7 +2158,7 @@ msgid "Equivalent to --log-levels *:3"
msgstr "Rovnocenné s --log-levels *:3" msgstr "Rovnocenné s --log-levels *:3"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "Error" msgid "Error"
msgstr "Chyba" msgstr "Chyba"
@ -2143,6 +2167,11 @@ msgstr "Chyba"
msgid "Error connecting MTP device %1" msgid "Error connecting MTP device %1"
msgstr "Chyba při připojování k MTP zařízení %1" msgstr "Chyba při připojování k MTP zařízení %1"
#: device/mtploader.cpp:77
#, qt-format
msgid "Error connecting MTP device %1: %2"
msgstr ""
#: organize/organizeerrordialog.cpp:71 #: organize/organizeerrordialog.cpp:71
msgid "Error copying songs" msgid "Error copying songs"
msgstr "Chyba při kopírování písní" msgstr "Chyba při kopírování písní"
@ -2269,6 +2298,11 @@ msgstr "Doba slábnutí"
msgid "Failed SQL query: %1" msgid "Failed SQL query: %1"
msgstr "" msgstr ""
#: core/filesystemmusicstorage.cpp:57
#, qt-format
msgid "Failed to create directory %1."
msgstr ""
#: covermanager/albumcoverchoicecontroller.cpp:379 #: covermanager/albumcoverchoicecontroller.cpp:379
#: covermanager/albumcoverchoicecontroller.cpp:396 #: covermanager/albumcoverchoicecontroller.cpp:396
#, qt-format #, qt-format
@ -2345,19 +2379,19 @@ msgstr ""
msgid "File %1 is not recognized as a valid audio file." msgid "File %1 is not recognized as a valid audio file."
msgstr "Soubor %1 nebyl rozpoznán jako platný zvukový soubor." msgstr "Soubor %1 nebyl rozpoznán jako platný zvukový soubor."
#: playlist/playlist.cpp:1385 #: playlist/playlist.cpp:1389
msgid "File Name" msgid "File Name"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1386 #: playlist/playlist.cpp:1390
msgid "File Name (without path)" msgid "File Name (without path)"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1387 #: playlist/playlist.cpp:1391
msgid "File Size" msgid "File Size"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1388 #: playlist/playlist.cpp:1392
msgid "File Type" msgid "File Type"
msgstr "" msgstr ""
@ -2538,7 +2572,7 @@ msgstr "Obecná nastavení"
msgid "Genius Authentication" msgid "Genius Authentication"
msgstr "Ověření Genius" msgstr "Ověření Genius"
#: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1371 #: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1375
#: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198 #: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198
#: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242 #: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242
#: ../build/src/ui_edittagdialog.h:917 #: ../build/src/ui_edittagdialog.h:917
@ -2646,7 +2680,7 @@ msgstr "Seskupit jako Žánr/Autor alba/Album"
msgid "Group by Genre/Artist/Album" msgid "Group by Genre/Artist/Album"
msgstr "Seskupovat podle žánru/umělce/alba" msgstr "Seskupovat podle žánru/umělce/alba"
#: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1375 #: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1379
#: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206 #: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206
#: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250 #: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250
#: ../build/src/ui_edittagdialog.h:909 #: ../build/src/ui_edittagdialog.h:909
@ -2822,7 +2856,7 @@ msgstr "Vložit..."
msgid "Install strawberry through PPA:" msgid "Install strawberry through PPA:"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1398 #: playlist/playlist.cpp:1402
msgid "Integrated Loudness" msgid "Integrated Loudness"
msgstr "" msgstr ""
@ -2842,6 +2876,11 @@ msgstr "Zobrazení karet Internetu"
msgid "Intro tracks" msgid "Intro tracks"
msgstr "Skladby úvodu" msgstr "Skladby úvodu"
#: device/mtpconnection.cpp:57
#, qt-format
msgid "Invalid MTP device: %1"
msgstr ""
#: scrobbler/scrobblingapi20.cpp:257 #: scrobbler/scrobblingapi20.cpp:257
msgid "Invalid reply from web browser. Missing token." msgid "Invalid reply from web browser. Missing token."
msgstr "Špatná odpověď od prohlížeče. Token chybí." msgstr "Špatná odpověď od prohlížeče. Token chybí."
@ -2902,7 +2941,7 @@ msgstr "Velký obal alba"
msgid "Large sidebar" msgid "Large sidebar"
msgstr "Velký postranní panel" msgstr "Velký postranní panel"
#: playlist/playlist.cpp:1379 #: playlist/playlist.cpp:1383
msgid "Last Played" msgid "Last Played"
msgstr "" msgstr ""
@ -2933,7 +2972,7 @@ msgstr "Nejméně oblíbené skladby"
msgid "Left" msgid "Left"
msgstr "Vlevo" msgstr "Vlevo"
#: context/contextview.cpp:163 playlist/playlist.cpp:1368 #: context/contextview.cpp:163 playlist/playlist.cpp:1372
#: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888 #: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888
msgid "Length" msgid "Length"
msgstr "Délka" msgstr "Délka"
@ -3040,7 +3079,7 @@ msgstr "Přihlášení"
msgid "Long term prediction profile (LTP)" msgid "Long term prediction profile (LTP)"
msgstr "Dlouhodobý předpověďní profil" msgstr "Dlouhodobý předpověďní profil"
#: playlist/playlist.cpp:1399 #: playlist/playlist.cpp:1403
msgid "Loudness Range" msgid "Loudness Range"
msgstr "" msgstr ""
@ -3076,13 +3115,22 @@ msgid "Lyrics providers"
msgstr "Poskytovatelé textů" msgstr "Poskytovatelé textů"
#: ../build/src/ui_subsonicsettingspage.h:251 #: ../build/src/ui_subsonicsettingspage.h:251
msgid "MD5 token" msgid "MD5 token (Recommended)"
msgstr "" msgstr ""
#: ../build/src/ui_transcodersettingspage.h:194 #: ../build/src/ui_transcodersettingspage.h:194
msgid "MP3" msgid "MP3"
msgstr "MP3" msgstr "MP3"
#: device/mtpconnection.cpp:100
msgid "MTP device not found."
msgstr ""
#: device/mtpconnection.cpp:86
#, qt-format
msgid "MTP error: %1"
msgstr ""
#: ../build/src/ui_transcoderoptionsaac.h:135 #: ../build/src/ui_transcoderoptionsaac.h:135
msgid "Main profile (MAIN)" msgid "Main profile (MAIN)"
msgstr "Hlavní profil" msgstr "Hlavní profil"
@ -3234,7 +3282,7 @@ msgstr "Sledovat změny ve sbírce"
msgid "Months" msgid "Months"
msgstr "Měsíce" msgstr "Měsíce"
#: playlist/playlist.cpp:1394 #: playlist/playlist.cpp:1398
msgid "Mood" msgid "Mood"
msgstr "Nálada" msgstr "Nálada"
@ -3412,7 +3460,7 @@ msgid "None"
msgstr "Žádná" msgstr "Žádná"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "None of the selected songs were suitable for copying to a device" msgid "None of the selected songs were suitable for copying to a device"
msgstr "Žádná z vybraných písní nebyla vhodná ke zkopírování do zařízení" msgstr "Žádná z vybraných písní nebyla vhodná ke zkopírování do zařízení"
@ -3514,7 +3562,7 @@ msgstr "Otevřít zařízení"
msgid "Open homepage" msgid "Open homepage"
msgstr "" msgstr ""
#: collection/collectionview.cpp:352 #: collection/collectionview.cpp:368
#: smartplaylists/smartplaylistsviewcontainer.cpp:67 #: smartplaylists/smartplaylistsviewcontainer.cpp:67
#: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318 #: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318
#: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77 #: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77
@ -3552,7 +3600,7 @@ msgstr "Opus"
msgid "Organize Files" msgid "Organize Files"
msgstr "Uspořádat Soubory" msgstr "Uspořádat Soubory"
#: core/mainwindow.cpp:754 collection/collectionview.cpp:359 #: core/mainwindow.cpp:754 collection/collectionview.cpp:379
msgid "Organize files..." msgid "Organize files..."
msgstr "Uspořádat soubory..." msgstr "Uspořádat soubory..."
@ -3560,7 +3608,7 @@ msgstr "Uspořádat soubory..."
msgid "Organizing files" msgid "Organizing files"
msgstr "Organizace souborů" msgstr "Organizace souborů"
#: playlist/playlist.cpp:1370 #: playlist/playlist.cpp:1374
msgid "Original Year" msgid "Original Year"
msgstr "" msgstr ""
@ -3667,7 +3715,7 @@ msgstr ""
msgid "Perform track loudness normalization" msgid "Perform track loudness normalization"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1374 #: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1378
#: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205 #: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205
#: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249 #: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249
#: ../build/src/ui_edittagdialog.h:919 #: ../build/src/ui_edittagdialog.h:919
@ -3688,7 +3736,7 @@ msgstr "Prostý postranní panel"
msgid "Play" msgid "Play"
msgstr "Přehrát" msgstr "Přehrát"
#: playlist/playlist.cpp:1377 #: playlist/playlist.cpp:1381
msgid "Play Count" msgid "Play Count"
msgstr "" msgstr ""
@ -3950,12 +3998,12 @@ msgstr "Přidat vybrané skladby do řady"
msgid "Queue selected tracks to play next" msgid "Queue selected tracks to play next"
msgstr "Přidat vybrané skladby do fronty" msgstr "Přidat vybrané skladby do fronty"
#: core/mainwindow.cpp:1961 collection/collectionview.cpp:356 #: core/mainwindow.cpp:1961 collection/collectionview.cpp:372
#: internet/internetcollectionview.cpp:321 #: internet/internetcollectionview.cpp:321
msgid "Queue to play next" msgid "Queue to play next"
msgstr "Do fronty jako další" msgstr "Do fronty jako další"
#: core/mainwindow.cpp:1953 collection/collectionview.cpp:355 #: core/mainwindow.cpp:1953 collection/collectionview.cpp:371
#: smartplaylists/smartplaylistsviewcontainer.cpp:70 #: smartplaylists/smartplaylistsviewcontainer.cpp:70
#: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320 #: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320
msgid "Queue track" msgid "Queue track"
@ -3981,7 +4029,7 @@ msgstr ""
msgid "Random" msgid "Random"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1395 ../build/src/ui_edittagdialog.h:922 #: playlist/playlist.cpp:1399 ../build/src/ui_edittagdialog.h:922
msgid "Rating" msgid "Rating"
msgstr "Hodnocení" msgstr "Hodnocení"
@ -4181,7 +4229,7 @@ msgstr "Opakovat seznam skladeb"
msgid "Repeat track" msgid "Repeat track"
msgstr "Opakovat skladbu" msgstr "Opakovat skladbu"
#: collection/collectionview.cpp:351 #: collection/collectionview.cpp:367
#: smartplaylists/smartplaylistsviewcontainer.cpp:66 #: smartplaylists/smartplaylistsviewcontainer.cpp:66
#: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317 #: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317
#: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73 #: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73
@ -4217,7 +4265,7 @@ msgstr "Odpověď od Tidal neobsahuje dotazové položky."
msgid "Repopulate" msgid "Repopulate"
msgstr "" msgstr ""
#: collection/collectionview.cpp:372 #: collection/collectionview.cpp:392
msgid "Rescan song(s)" msgid "Rescan song(s)"
msgstr "Prohledat skladbu" msgstr "Prohledat skladbu"
@ -4322,7 +4370,7 @@ msgstr "Bezpečně odebrat zařízení"
msgid "Safely remove the device after copying" msgid "Safely remove the device after copying"
msgstr "Po dokončení kopírování bezpečně odebrat zařízení" msgstr "Po dokončení kopírování bezpečně odebrat zařízení"
#: playlist/playlist.cpp:1381 #: playlist/playlist.cpp:1385
msgid "Sample Rate" msgid "Sample Rate"
msgstr "" msgstr ""
@ -4456,7 +4504,7 @@ msgstr "Zpožděné vyhledávání"
msgid "Search for album covers..." msgid "Search for album covers..."
msgstr "Hledat obaly alb..." msgstr "Hledat obaly alb..."
#: internet/internetsearchview.cpp:339 #: collection/collectionview.cpp:376 internet/internetsearchview.cpp:339
msgid "Search for this" msgid "Search for this"
msgstr "Hledat toto" msgstr "Hledat toto"
@ -4689,12 +4737,12 @@ msgstr "Ukazovat ve sbírce..."
msgid "Show in file browser" msgid "Show in file browser"
msgstr "Zobrazit v průzkumníku souborů" msgstr "Zobrazit v průzkumníku souborů"
#: core/mainwindow.cpp:753 collection/collectionview.cpp:368 #: core/mainwindow.cpp:753 collection/collectionview.cpp:388
#: widgets/fileviewlist.cpp:53 #: widgets/fileviewlist.cpp:53
msgid "Show in file browser..." msgid "Show in file browser..."
msgstr "Ukázat v prohlížeči souborů..." msgstr "Ukázat v prohlížeči souborů..."
#: collection/collectionview.cpp:375 #: collection/collectionview.cpp:395
msgid "Show in various artists" msgid "Show in various artists"
msgstr "Ukázat pod různými umělci" msgstr "Ukázat pod různými umělci"
@ -4795,7 +4843,7 @@ msgstr "Velikost:"
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"
#: playlist/playlist.cpp:1378 #: playlist/playlist.cpp:1382
msgid "Skip Count" msgid "Skip Count"
msgstr "" msgstr ""
@ -4895,7 +4943,7 @@ msgstr ""
msgid "Sorting" msgid "Sorting"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1393 #: playlist/playlist.cpp:1397
msgid "Source" msgid "Source"
msgstr "Zdroj" msgstr "Zdroj"
@ -5206,7 +5254,7 @@ msgstr ""
"Verze Strawberry, na kterou jste právě povýšili, vyžaduje z důvodu nových " "Verze Strawberry, na kterou jste právě povýšili, vyžaduje z důvodu nových "
"vlastností vypsaných níže úplné nové prohledání sbírky:" "vlastností vypsaných níže úplné nové prohledání sbírky:"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "There are other songs in this album" msgid "There are other songs in this album"
msgstr "Na tomto albu jsou další písně" msgstr "Na tomto albu jsou další písně"
@ -5317,7 +5365,7 @@ msgstr ""
msgid "Time step" msgid "Time step"
msgstr "Časový krok" msgstr "Časový krok"
#: playlist/playlist.cpp:1363 organize/organizedialog.cpp:104 #: playlist/playlist.cpp:1367 organize/organizedialog.cpp:104
#: ../build/src/ui_contextsettingspage.h:422 #: ../build/src/ui_contextsettingspage.h:422
#: ../build/src/ui_edittagdialog.h:913 #: ../build/src/ui_edittagdialog.h:913
#: ../build/src/ui_trackselectiondialog.h:210 #: ../build/src/ui_trackselectiondialog.h:210
@ -5368,7 +5416,7 @@ msgstr "Celkem přeneseno bajtů"
msgid "Total network requests made" msgid "Total network requests made"
msgstr "Celkem uskutečněno síťových požadavků" msgstr "Celkem uskutečněno síťových požadavků"
#: playlist/playlist.cpp:1366 organize/organizedialog.cpp:112 #: playlist/playlist.cpp:1370 organize/organizedialog.cpp:112
#: ../build/src/ui_edittagdialog.h:921 #: ../build/src/ui_edittagdialog.h:921
#: ../build/src/ui_trackselectiondialog.h:212 #: ../build/src/ui_trackselectiondialog.h:212
msgid "Track" msgid "Track"
@ -5716,7 +5764,7 @@ msgstr "Bez obalu:"
msgid "Work in offline mode (Only cache scrobbles)" msgid "Work in offline mode (Only cache scrobbles)"
msgstr "Pracovat v režimu offline (pouze ukládat přehrané skladby)" msgstr "Pracovat v režimu offline (pouze ukládat přehrané skladby)"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "" msgid ""
"Would you like to move the other songs on this album to Various Artists as " "Would you like to move the other songs on this album to Various Artists as "
"well?" "well?"
@ -5734,7 +5782,16 @@ msgstr ""
msgid "Write metadata when saving playlists" msgid "Write metadata when saving playlists"
msgstr "Zapisovat metadata při ukládání seznamů skladeb" msgstr "Zapisovat metadata při ukládání seznamů skladeb"
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1369 #: device/gpoddevice.cpp:288
msgid "Writing database failed."
msgstr ""
#: device/gpoddevice.cpp:284
#, qt-format
msgid "Writing database failed: %1"
msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1373
#: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199 #: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199
#: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243 #: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243
#: ../build/src/ui_edittagdialog.h:912 #: ../build/src/ui_edittagdialog.h:912

View File

@ -800,7 +800,7 @@ msgstr "Nach dem Kopieren …"
msgid "Albu&m cover" msgid "Albu&m cover"
msgstr "Albu&m cover" msgstr "Albu&m cover"
#: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1365 #: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1369
#: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194 #: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194
#: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238 #: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238
#: ../build/src/ui_albumcoversearcher.h:108 #: ../build/src/ui_albumcoversearcher.h:108
@ -820,7 +820,7 @@ msgstr "Album (idealer Pegel für alle Titel)"
msgid "Album - Disc" msgid "Album - Disc"
msgstr "Album - Disc" msgstr "Album - Disc"
#: playlist/playlist.cpp:1372 #: playlist/playlist.cpp:1376
msgid "Album Artist" msgid "Album Artist"
msgstr "Album-Interpret" msgstr "Album-Interpret"
@ -909,7 +909,7 @@ msgstr "Immer mit der Wiedergabe beginnen"
msgid "An error occurred loading the iTunes database" msgid "An error occurred loading the iTunes database"
msgstr "Beim Laden der iTunes-Datenbank ist ein Fehler aufgetreten" msgstr "Beim Laden der iTunes-Datenbank ist ein Fehler aufgetreten"
#: playlist/playlist.cpp:426 dialogs/edittagdialog.cpp:1450 #: playlist/playlist.cpp:430 dialogs/edittagdialog.cpp:1450
#, qt-format #, qt-format
msgid "An error occurred writing metadata to '%1'" msgid "An error occurred writing metadata to '%1'"
msgstr "Beim Schreiben der Metadaten für '%1' trat ein Fehler auf" msgstr "Beim Schreiben der Metadaten für '%1' trat ein Fehler auf"
@ -938,7 +938,7 @@ msgstr "\"Nicht jugendfrei\" zu Titeln nicht jugendfreier Alben hinzufügen"
msgid "Append files/URLs to the playlist" msgid "Append files/URLs to the playlist"
msgstr "Dateien/Adressen an die Wiedergabeliste anhängen" msgstr "Dateien/Adressen an die Wiedergabeliste anhängen"
#: collection/collectionview.cpp:350 #: collection/collectionview.cpp:366
#: smartplaylists/smartplaylistsviewcontainer.cpp:65 #: smartplaylists/smartplaylistsviewcontainer.cpp:65
#: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316 #: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316
#: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69 #: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69
@ -994,7 +994,7 @@ msgstr "Bild manuell"
msgid "Art Unset" msgid "Art Unset"
msgstr "Bild nicht gesetzt" msgstr "Bild nicht gesetzt"
#: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1364 #: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1368
#: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192 #: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192
#: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236 #: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236
#: ../build/src/ui_albumcoversearcher.h:104 #: ../build/src/ui_albumcoversearcher.h:104
@ -1155,7 +1155,7 @@ msgstr "Verhalten"
msgid "Best" msgid "Best"
msgstr "Optimal" msgstr "Optimal"
#: playlist/playlist.cpp:1382 #: playlist/playlist.cpp:1386
msgid "Bit Depth" msgid "Bit Depth"
msgstr "Bit-Tiefe" msgstr "Bit-Tiefe"
@ -1171,7 +1171,7 @@ msgid "Bit rate"
msgstr "Bitrate" msgstr "Bitrate"
#: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149 #: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149
#: playlist/playlist.cpp:1383 ../build/src/ui_groupbydialog.h:210 #: playlist/playlist.cpp:1387 ../build/src/ui_groupbydialog.h:210
#: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254 #: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254
#: ../build/src/ui_transcoderoptionsaac.h:132 #: ../build/src/ui_transcoderoptionsaac.h:132
#: ../build/src/ui_transcoderoptionsopus.h:76 #: ../build/src/ui_transcoderoptionsopus.h:76
@ -1242,7 +1242,7 @@ msgstr "CD Wiedergabe ist nur mit der GStreamer Implementierung verfügbar"
msgid "CDDA" msgid "CDDA"
msgstr "CDDA" msgstr "CDDA"
#: playlist/playlist.cpp:1396 #: playlist/playlist.cpp:1400
msgid "CUE" msgid "CUE"
msgstr "Stichwort" msgstr "Stichwort"
@ -1402,7 +1402,7 @@ msgstr "Bibliothek durchsuchen"
msgid "Comma separated list of class:level, level is 0-3" msgid "Comma separated list of class:level, level is 0-3"
msgstr "Komma getrennte Liste mit »class:level« (Level ist 0-3)" msgstr "Komma getrennte Liste mit »class:level« (Level ist 0-3)"
#: playlist/playlist.cpp:1392 smartplaylists/smartplaylistsearchterm.cpp:391 #: playlist/playlist.cpp:1396 smartplaylists/smartplaylistsearchterm.cpp:391
#: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918 #: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918
msgid "Comment" msgid "Comment"
msgstr "Kommentar" msgstr "Kommentar"
@ -1419,7 +1419,7 @@ msgstr "Schlagworte automatisch vervollständigen"
msgid "Complete tags automatically..." msgid "Complete tags automatically..."
msgstr "Schlagworte automatisch vervollständigen …" msgstr "Schlagworte automatisch vervollständigen …"
#: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1373 #: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1377
#: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204 #: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204
#: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248 #: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248
#: ../build/src/ui_edittagdialog.h:915 #: ../build/src/ui_edittagdialog.h:915
@ -1502,7 +1502,7 @@ msgstr "Zur Bibliothek kopieren …"
msgid "Copy to device" msgid "Copy to device"
msgstr "Kopieren auf ein Gerät" msgstr "Kopieren auf ein Gerät"
#: core/mainwindow.cpp:758 collection/collectionview.cpp:361 #: core/mainwindow.cpp:758 collection/collectionview.cpp:381
#: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48 #: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48
msgid "Copy to device..." msgid "Copy to device..."
msgstr "Auf das Gerät kopieren …" msgstr "Auf das Gerät kopieren …"
@ -1516,6 +1516,16 @@ msgstr ""
"strawberry.db aus dem Ordner ~/snap kopieren, um Ihre Einstellungen nicht zu " "strawberry.db aus dem Ordner ~/snap kopieren, um Ihre Einstellungen nicht zu "
"verlieren:" "verlieren:"
#: device/gpoddevice.cpp:241
#, qt-format
msgid "Could not copy %1 to %2: %3"
msgstr ""
#: core/filesystemmusicstorage.cpp:98
#, qt-format
msgid "Could not copy file %1 to %2."
msgstr ""
#: transcoder/transcoder.cpp:72 #: transcoder/transcoder.cpp:72
#, qt-format #, qt-format
msgid "" msgid ""
@ -1530,6 +1540,10 @@ msgstr ""
msgid "Could not open CUE file %1 for reading: %2" msgid "Could not open CUE file %1 for reading: %2"
msgstr "Konnte nicht CUE-Datei %1 zum Lesen öffnen: %2" msgstr "Konnte nicht CUE-Datei %1 zum Lesen öffnen: %2"
#: device/mtpconnection.cpp:75 device/mtpconnection.cpp:109
msgid "Could not open MTP device."
msgstr ""
#: scrobbler/scrobblingapi20.cpp:223 #: scrobbler/scrobblingapi20.cpp:223
msgid "Could not open URL. Please open this URL in your browser" msgid "Could not open URL. Please open this URL in your browser"
msgstr "Konnte die URL nicht öffnen. Bitte diese URL im Browser öffnen" msgstr "Konnte die URL nicht öffnen. Bitte diese URL im Browser öffnen"
@ -1763,11 +1777,11 @@ msgstr "Dance"
msgid "Database corruption detected." msgid "Database corruption detected."
msgstr "Datenbankfehler festgestellt" msgstr "Datenbankfehler festgestellt"
#: playlist/playlist.cpp:1390 #: playlist/playlist.cpp:1394
msgid "Date Created" msgid "Date Created"
msgstr "Erstellungsdatum" msgstr "Erstellungsdatum"
#: playlist/playlist.cpp:1389 #: playlist/playlist.cpp:1393
msgid "Date Modified" msgid "Date Modified"
msgstr "Änderungsdatum" msgstr "Änderungsdatum"
@ -1820,7 +1834,7 @@ msgstr "Dateien löschen"
msgid "Delete from device..." msgid "Delete from device..."
msgstr "Vom Gerät löschen …" msgstr "Vom Gerät löschen …"
#: core/mainwindow.cpp:760 collection/collectionview.cpp:363 #: core/mainwindow.cpp:760 collection/collectionview.cpp:383
#: widgets/fileviewlist.cpp:49 #: widgets/fileviewlist.cpp:49
msgid "Delete from disk..." msgid "Delete from disk..."
msgstr "Von der Festplatte löschen …" msgstr "Von der Festplatte löschen …"
@ -1858,6 +1872,16 @@ msgstr "Titel aus der Warteschlange nehmen"
msgid "Destination" msgid "Destination"
msgstr "Ziel:" msgstr "Ziel:"
#: core/filesystemmusicstorage.cpp:92
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite"
msgstr ""
#: core/filesystemmusicstorage.cpp:73
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite."
msgstr ""
#: ../build/src/ui_transcodedialog.h:235 #: ../build/src/ui_transcodedialog.h:235
msgid "Details..." msgid "Details..."
msgstr "Details …" msgstr "Details …"
@ -1904,7 +1928,7 @@ msgctxt "Refers to a disabled notification type in Notification settings."
msgid "Disabled" msgid "Disabled"
msgstr "Deaktiviert" msgstr "Deaktiviert"
#: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1367 #: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1371
#: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196 #: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196
#: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240 #: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240
#: ../build/src/ui_edittagdialog.h:908 #: ../build/src/ui_edittagdialog.h:908
@ -1948,7 +1972,7 @@ msgstr "Zeige diese Nachricht nicht wieder."
msgid "Don't repeat" msgid "Don't repeat"
msgstr "Wiederholung aus" msgstr "Wiederholung aus"
#: collection/collectionview.cpp:376 #: collection/collectionview.cpp:396
msgid "Don't show in various artists" msgid "Don't show in various artists"
msgstr "Nicht unter »Verschiedene Interpreten« anzeigen" msgstr "Nicht unter »Verschiedene Interpreten« anzeigen"
@ -2048,12 +2072,12 @@ msgstr "Schlagwort bearbeiten …"
msgid "Edit track information" msgid "Edit track information"
msgstr "Metadaten bearbeiten" msgstr "Metadaten bearbeiten"
#: collection/collectionview.cpp:366 widgets/fileviewlist.cpp:52 #: collection/collectionview.cpp:386 widgets/fileviewlist.cpp:52
#: ../build/src/ui_mainwindow.h:642 #: ../build/src/ui_mainwindow.h:642
msgid "Edit track information..." msgid "Edit track information..."
msgstr "Metadaten bearbeiten …" msgstr "Metadaten bearbeiten …"
#: collection/collectionview.cpp:367 #: collection/collectionview.cpp:387
msgid "Edit tracks information..." msgid "Edit tracks information..."
msgstr "Metadaten bearbeiten …" msgstr "Metadaten bearbeiten …"
@ -2207,7 +2231,7 @@ msgid "Equivalent to --log-levels *:3"
msgstr "Äquivalent zu --log-levels *:3" msgstr "Äquivalent zu --log-levels *:3"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "Error" msgid "Error"
msgstr "Fehler" msgstr "Fehler"
@ -2216,6 +2240,11 @@ msgstr "Fehler"
msgid "Error connecting MTP device %1" msgid "Error connecting MTP device %1"
msgstr "Fehler beim Verbinden zu MTP Gerät %1" msgstr "Fehler beim Verbinden zu MTP Gerät %1"
#: device/mtploader.cpp:77
#, qt-format
msgid "Error connecting MTP device %1: %2"
msgstr ""
#: organize/organizeerrordialog.cpp:71 #: organize/organizeerrordialog.cpp:71
msgid "Error copying songs" msgid "Error copying songs"
msgstr "Fehler beim Kopieren der Titel" msgstr "Fehler beim Kopieren der Titel"
@ -2342,6 +2371,11 @@ msgstr "Dauer:"
msgid "Failed SQL query: %1" msgid "Failed SQL query: %1"
msgstr "Fehlgeschlagene SQL-Abfrage: %1" msgstr "Fehlgeschlagene SQL-Abfrage: %1"
#: core/filesystemmusicstorage.cpp:57
#, qt-format
msgid "Failed to create directory %1."
msgstr ""
#: covermanager/albumcoverchoicecontroller.cpp:379 #: covermanager/albumcoverchoicecontroller.cpp:379
#: covermanager/albumcoverchoicecontroller.cpp:396 #: covermanager/albumcoverchoicecontroller.cpp:396
#, qt-format #, qt-format
@ -2418,19 +2452,19 @@ msgstr "Datei %1 existiert nicht. "
msgid "File %1 is not recognized as a valid audio file." msgid "File %1 is not recognized as a valid audio file."
msgstr "Datei %1 kann nicht als korrekte Audiodatei erkannt werden." msgstr "Datei %1 kann nicht als korrekte Audiodatei erkannt werden."
#: playlist/playlist.cpp:1385 #: playlist/playlist.cpp:1389
msgid "File Name" msgid "File Name"
msgstr "Dateiname" msgstr "Dateiname"
#: playlist/playlist.cpp:1386 #: playlist/playlist.cpp:1390
msgid "File Name (without path)" msgid "File Name (without path)"
msgstr "Dateiname (ohne Dateipfad)" msgstr "Dateiname (ohne Dateipfad)"
#: playlist/playlist.cpp:1387 #: playlist/playlist.cpp:1391
msgid "File Size" msgid "File Size"
msgstr "Dateigröße" msgstr "Dateigröße"
#: playlist/playlist.cpp:1388 #: playlist/playlist.cpp:1392
msgid "File Type" msgid "File Type"
msgstr "Dateityp" msgstr "Dateityp"
@ -2613,7 +2647,7 @@ msgstr "Allgemeine Einstellungen"
msgid "Genius Authentication" msgid "Genius Authentication"
msgstr "Genius Authentifizierung" msgstr "Genius Authentifizierung"
#: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1371 #: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1375
#: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198 #: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198
#: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242 #: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242
#: ../build/src/ui_edittagdialog.h:917 #: ../build/src/ui_edittagdialog.h:917
@ -2722,7 +2756,7 @@ msgstr "Gruppe nach Genre/Album Künstler/Album"
msgid "Group by Genre/Artist/Album" msgid "Group by Genre/Artist/Album"
msgstr "Genre/Interpret/Album" msgstr "Genre/Interpret/Album"
#: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1375 #: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1379
#: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206 #: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206
#: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250 #: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250
#: ../build/src/ui_edittagdialog.h:909 #: ../build/src/ui_edittagdialog.h:909
@ -2898,7 +2932,7 @@ msgstr "Einfügen …"
msgid "Install strawberry through PPA:" msgid "Install strawberry through PPA:"
msgstr "Strawberry aus PPA installieren:" msgstr "Strawberry aus PPA installieren:"
#: playlist/playlist.cpp:1398 #: playlist/playlist.cpp:1402
msgid "Integrated Loudness" msgid "Integrated Loudness"
msgstr "Integrierte Lautheit" msgstr "Integrierte Lautheit"
@ -2918,6 +2952,11 @@ msgstr "Internet Registerkartenansicht"
msgid "Intro tracks" msgid "Intro tracks"
msgstr "Einleitungstitel" msgstr "Einleitungstitel"
#: device/mtpconnection.cpp:57
#, qt-format
msgid "Invalid MTP device: %1"
msgstr ""
#: scrobbler/scrobblingapi20.cpp:257 #: scrobbler/scrobblingapi20.cpp:257
msgid "Invalid reply from web browser. Missing token." msgid "Invalid reply from web browser. Missing token."
msgstr "Ungültige Antwort vom Webbrowser. Token fehlt." msgstr "Ungültige Antwort vom Webbrowser. Token fehlt."
@ -2979,7 +3018,7 @@ msgstr "Großes Titelbild"
msgid "Large sidebar" msgid "Large sidebar"
msgstr "Große Seitenleiste" msgstr "Große Seitenleiste"
#: playlist/playlist.cpp:1379 #: playlist/playlist.cpp:1383
msgid "Last Played" msgid "Last Played"
msgstr "Zuletzt gespielt" msgstr "Zuletzt gespielt"
@ -3010,7 +3049,7 @@ msgstr "Am wenigsten gemochte Titel"
msgid "Left" msgid "Left"
msgstr "Links" msgstr "Links"
#: context/contextview.cpp:163 playlist/playlist.cpp:1368 #: context/contextview.cpp:163 playlist/playlist.cpp:1372
#: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888 #: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888
msgid "Length" msgid "Length"
msgstr "Länge" msgstr "Länge"
@ -3117,7 +3156,7 @@ msgstr "Anmelden"
msgid "Long term prediction profile (LTP)" msgid "Long term prediction profile (LTP)"
msgstr "Langzeitvorhersageprofil (LTP)" msgstr "Langzeitvorhersageprofil (LTP)"
#: playlist/playlist.cpp:1399 #: playlist/playlist.cpp:1403
msgid "Loudness Range" msgid "Loudness Range"
msgstr "Lautstärkeumfang" msgstr "Lautstärkeumfang"
@ -3152,13 +3191,22 @@ msgid "Lyrics providers"
msgstr "Anbieter für Songtexte" msgstr "Anbieter für Songtexte"
#: ../build/src/ui_subsonicsettingspage.h:251 #: ../build/src/ui_subsonicsettingspage.h:251
msgid "MD5 token" msgid "MD5 token (Recommended)"
msgstr "MD5-Token" msgstr ""
#: ../build/src/ui_transcodersettingspage.h:194 #: ../build/src/ui_transcodersettingspage.h:194
msgid "MP3" msgid "MP3"
msgstr "MP3" msgstr "MP3"
#: device/mtpconnection.cpp:100
msgid "MTP device not found."
msgstr ""
#: device/mtpconnection.cpp:86
#, qt-format
msgid "MTP error: %1"
msgstr ""
#: ../build/src/ui_transcoderoptionsaac.h:135 #: ../build/src/ui_transcoderoptionsaac.h:135
msgid "Main profile (MAIN)" msgid "Main profile (MAIN)"
msgstr "Hauptprofil (MAIN)" msgstr "Hauptprofil (MAIN)"
@ -3310,7 +3358,7 @@ msgstr "Bibliothek auf Änderungen überwachen"
msgid "Months" msgid "Months"
msgstr "Monate" msgstr "Monate"
#: playlist/playlist.cpp:1394 #: playlist/playlist.cpp:1398
msgid "Mood" msgid "Mood"
msgstr "Stimmung" msgstr "Stimmung"
@ -3490,7 +3538,7 @@ msgid "None"
msgstr "Nichts" msgstr "Nichts"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "None of the selected songs were suitable for copying to a device" msgid "None of the selected songs were suitable for copying to a device"
msgstr "Keiner der gewählten Titel war zum Kopieren auf ein Gerät geeignet." msgstr "Keiner der gewählten Titel war zum Kopieren auf ein Gerät geeignet."
@ -3594,7 +3642,7 @@ msgstr "Gerät öffnen"
msgid "Open homepage" msgid "Open homepage"
msgstr "Homepage öffnen" msgstr "Homepage öffnen"
#: collection/collectionview.cpp:352 #: collection/collectionview.cpp:368
#: smartplaylists/smartplaylistsviewcontainer.cpp:67 #: smartplaylists/smartplaylistsviewcontainer.cpp:67
#: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318 #: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318
#: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77 #: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77
@ -3632,7 +3680,7 @@ msgstr "Opus"
msgid "Organize Files" msgid "Organize Files"
msgstr "Dateien organisieren" msgstr "Dateien organisieren"
#: core/mainwindow.cpp:754 collection/collectionview.cpp:359 #: core/mainwindow.cpp:754 collection/collectionview.cpp:379
msgid "Organize files..." msgid "Organize files..."
msgstr "Dateien organisieren..." msgstr "Dateien organisieren..."
@ -3640,7 +3688,7 @@ msgstr "Dateien organisieren..."
msgid "Organizing files" msgid "Organizing files"
msgstr "Dateien organisieren" msgstr "Dateien organisieren"
#: playlist/playlist.cpp:1370 #: playlist/playlist.cpp:1374
msgid "Original Year" msgid "Original Year"
msgstr "Ursprüngliches Jahr" msgstr "Ursprüngliches Jahr"
@ -3753,7 +3801,7 @@ msgstr ""
msgid "Perform track loudness normalization" msgid "Perform track loudness normalization"
msgstr "Lautstärke-Normalisierung anwenden" msgstr "Lautstärke-Normalisierung anwenden"
#: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1374 #: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1378
#: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205 #: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205
#: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249 #: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249
#: ../build/src/ui_edittagdialog.h:919 #: ../build/src/ui_edittagdialog.h:919
@ -3774,7 +3822,7 @@ msgstr "Einfache Seitenleiste"
msgid "Play" msgid "Play"
msgstr "Wiedergabe" msgstr "Wiedergabe"
#: playlist/playlist.cpp:1377 #: playlist/playlist.cpp:1381
msgid "Play Count" msgid "Play Count"
msgstr "Wiedergabezähler" msgstr "Wiedergabezähler"
@ -4046,12 +4094,12 @@ msgstr ""
"Ausgewählte Titel in die Warteschlange stellen, um sie als nächstes " "Ausgewählte Titel in die Warteschlange stellen, um sie als nächstes "
"abzuspielen" "abzuspielen"
#: core/mainwindow.cpp:1961 collection/collectionview.cpp:356 #: core/mainwindow.cpp:1961 collection/collectionview.cpp:372
#: internet/internetcollectionview.cpp:321 #: internet/internetcollectionview.cpp:321
msgid "Queue to play next" msgid "Queue to play next"
msgstr "In die Warteschlange, um sie als nächstes abzuspielen" msgstr "In die Warteschlange, um sie als nächstes abzuspielen"
#: core/mainwindow.cpp:1953 collection/collectionview.cpp:355 #: core/mainwindow.cpp:1953 collection/collectionview.cpp:371
#: smartplaylists/smartplaylistsviewcontainer.cpp:70 #: smartplaylists/smartplaylistsviewcontainer.cpp:70
#: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320 #: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320
msgid "Queue track" msgid "Queue track"
@ -4077,7 +4125,7 @@ msgstr "Radios"
msgid "Random" msgid "Random"
msgstr "Zufällig" msgstr "Zufällig"
#: playlist/playlist.cpp:1395 ../build/src/ui_edittagdialog.h:922 #: playlist/playlist.cpp:1399 ../build/src/ui_edittagdialog.h:922
msgid "Rating" msgid "Rating"
msgstr "Bewertung" msgstr "Bewertung"
@ -4287,7 +4335,7 @@ msgstr "Wiedergabeliste wiederholen"
msgid "Repeat track" msgid "Repeat track"
msgstr "Titel wiederholen" msgstr "Titel wiederholen"
#: collection/collectionview.cpp:351 #: collection/collectionview.cpp:367
#: smartplaylists/smartplaylistsviewcontainer.cpp:66 #: smartplaylists/smartplaylistsviewcontainer.cpp:66
#: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317 #: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317
#: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73 #: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73
@ -4323,7 +4371,7 @@ msgstr "Bei der Antwort von Tidal fehlen Abfrageelemente."
msgid "Repopulate" msgid "Repopulate"
msgstr "Neu füllen" msgstr "Neu füllen"
#: collection/collectionview.cpp:372 #: collection/collectionview.cpp:392
msgid "Rescan song(s)" msgid "Rescan song(s)"
msgstr "Lied erneut scannen" msgstr "Lied erneut scannen"
@ -4427,7 +4475,7 @@ msgstr "Gerät sicher entfernen"
msgid "Safely remove the device after copying" msgid "Safely remove the device after copying"
msgstr "Das Gerät nach dem Kopiervorgang sicher entfernen" msgstr "Das Gerät nach dem Kopiervorgang sicher entfernen"
#: playlist/playlist.cpp:1381 #: playlist/playlist.cpp:1385
msgid "Sample Rate" msgid "Sample Rate"
msgstr "Abtastrate" msgstr "Abtastrate"
@ -4561,7 +4609,7 @@ msgstr "Suche verzögert"
msgid "Search for album covers..." msgid "Search for album covers..."
msgstr "Nach Titelbild suchen …" msgstr "Nach Titelbild suchen …"
#: internet/internetsearchview.cpp:339 #: collection/collectionview.cpp:376 internet/internetsearchview.cpp:339
msgid "Search for this" msgid "Search for this"
msgstr "Nach diesem suchen" msgstr "Nach diesem suchen"
@ -4797,12 +4845,12 @@ msgstr "In Bibliothek anzeigen …"
msgid "Show in file browser" msgid "Show in file browser"
msgstr "Zeige im Dateimanager" msgstr "Zeige im Dateimanager"
#: core/mainwindow.cpp:753 collection/collectionview.cpp:368 #: core/mainwindow.cpp:753 collection/collectionview.cpp:388
#: widgets/fileviewlist.cpp:53 #: widgets/fileviewlist.cpp:53
msgid "Show in file browser..." msgid "Show in file browser..."
msgstr "In Dateiverwaltung anzeigen …" msgstr "In Dateiverwaltung anzeigen …"
#: collection/collectionview.cpp:375 #: collection/collectionview.cpp:395
msgid "Show in various artists" msgid "Show in various artists"
msgstr "Unter »Verschiedene Interpreten« anzeigen" msgstr "Unter »Verschiedene Interpreten« anzeigen"
@ -4903,7 +4951,7 @@ msgstr "Größe:"
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"
#: playlist/playlist.cpp:1378 #: playlist/playlist.cpp:1382
msgid "Skip Count" msgid "Skip Count"
msgstr "Übersprungzähler" msgstr "Übersprungzähler"
@ -5002,7 +5050,7 @@ msgstr "Sortiere Titel nach"
msgid "Sorting" msgid "Sorting"
msgstr "Sortieren" msgstr "Sortieren"
#: playlist/playlist.cpp:1393 #: playlist/playlist.cpp:1397
msgid "Source" msgid "Source"
msgstr "Quelle" msgstr "Quelle"
@ -5321,7 +5369,7 @@ msgstr ""
"eine komplette Aktualisierung Ihrer Bibliothek, damit die folgenden neuen " "eine komplette Aktualisierung Ihrer Bibliothek, damit die folgenden neuen "
"Funktionen genutzt werden können:" "Funktionen genutzt werden können:"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "There are other songs in this album" msgid "There are other songs in this album"
msgstr "Dieses Album enthält auch andere Titel" msgstr "Dieses Album enthält auch andere Titel"
@ -5437,7 +5485,7 @@ msgstr ""
msgid "Time step" msgid "Time step"
msgstr "Zeitschritt" msgstr "Zeitschritt"
#: playlist/playlist.cpp:1363 organize/organizedialog.cpp:104 #: playlist/playlist.cpp:1367 organize/organizedialog.cpp:104
#: ../build/src/ui_contextsettingspage.h:422 #: ../build/src/ui_contextsettingspage.h:422
#: ../build/src/ui_edittagdialog.h:913 #: ../build/src/ui_edittagdialog.h:913
#: ../build/src/ui_trackselectiondialog.h:210 #: ../build/src/ui_trackselectiondialog.h:210
@ -5488,7 +5536,7 @@ msgstr "Insgesamt übertragene Bytes"
msgid "Total network requests made" msgid "Total network requests made"
msgstr "Insgesamt gestellte Netzwerkanfragen" msgstr "Insgesamt gestellte Netzwerkanfragen"
#: playlist/playlist.cpp:1366 organize/organizedialog.cpp:112 #: playlist/playlist.cpp:1370 organize/organizedialog.cpp:112
#: ../build/src/ui_edittagdialog.h:921 #: ../build/src/ui_edittagdialog.h:921
#: ../build/src/ui_trackselectiondialog.h:212 #: ../build/src/ui_trackselectiondialog.h:212
msgid "Track" msgid "Track"
@ -5842,7 +5890,7 @@ msgstr "Ohne Titelbild:"
msgid "Work in offline mode (Only cache scrobbles)" msgid "Work in offline mode (Only cache scrobbles)"
msgstr "Offline arbeiten (Nur im Speicher scrobbeln)" msgstr "Offline arbeiten (Nur im Speicher scrobbeln)"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "" msgid ""
"Would you like to move the other songs on this album to Various Artists as " "Would you like to move the other songs on this album to Various Artists as "
"well?" "well?"
@ -5862,7 +5910,16 @@ msgstr "Alle Wiedergabezahlen und Bewertungen in Dateien schreiben"
msgid "Write metadata when saving playlists" msgid "Write metadata when saving playlists"
msgstr "Metadaten schreiben, wenn Wiedergabelisten gespeichert werden" msgstr "Metadaten schreiben, wenn Wiedergabelisten gespeichert werden"
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1369 #: device/gpoddevice.cpp:288
msgid "Writing database failed."
msgstr ""
#: device/gpoddevice.cpp:284
#, qt-format
msgid "Writing database failed: %1"
msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1373
#: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199 #: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199
#: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243 #: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243
#: ../build/src/ui_edittagdialog.h:912 #: ../build/src/ui_edittagdialog.h:912

View File

@ -775,7 +775,7 @@ msgstr "Después de copiar…"
msgid "Albu&m cover" msgid "Albu&m cover"
msgstr "C&ubierta del álbum" msgstr "C&ubierta del álbum"
#: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1365 #: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1369
#: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194 #: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194
#: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238 #: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238
#: ../build/src/ui_albumcoversearcher.h:108 #: ../build/src/ui_albumcoversearcher.h:108
@ -795,7 +795,7 @@ msgstr "Álbum (volumen idóneo para todas las pistas)"
msgid "Album - Disc" msgid "Album - Disc"
msgstr "Álbum - Disco" msgstr "Álbum - Disco"
#: playlist/playlist.cpp:1372 #: playlist/playlist.cpp:1376
msgid "Album Artist" msgid "Album Artist"
msgstr "" msgstr ""
@ -886,7 +886,7 @@ msgstr "Comenzar siempre la reproducción"
msgid "An error occurred loading the iTunes database" msgid "An error occurred loading the iTunes database"
msgstr "Se produjo un error al cargar la base de datos de iTunes" msgstr "Se produjo un error al cargar la base de datos de iTunes"
#: playlist/playlist.cpp:426 dialogs/edittagdialog.cpp:1450 #: playlist/playlist.cpp:430 dialogs/edittagdialog.cpp:1450
#, qt-format #, qt-format
msgid "An error occurred writing metadata to '%1'" msgid "An error occurred writing metadata to '%1'"
msgstr "Se produjo un error al escribir los metadatos en «%1»" msgstr "Se produjo un error al escribir los metadatos en «%1»"
@ -915,7 +915,7 @@ msgstr "Añadir «explícito» al nombre de los álbumes explícitos"
msgid "Append files/URLs to the playlist" msgid "Append files/URLs to the playlist"
msgstr "Añadir archivos/URL a la lista de reproducción" msgstr "Añadir archivos/URL a la lista de reproducción"
#: collection/collectionview.cpp:350 #: collection/collectionview.cpp:366
#: smartplaylists/smartplaylistsviewcontainer.cpp:65 #: smartplaylists/smartplaylistsviewcontainer.cpp:65
#: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316 #: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316
#: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69 #: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69
@ -966,7 +966,7 @@ msgstr "Cubierta manual"
msgid "Art Unset" msgid "Art Unset"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1364 #: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1368
#: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192 #: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192
#: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236 #: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236
#: ../build/src/ui_albumcoversearcher.h:104 #: ../build/src/ui_albumcoversearcher.h:104
@ -1127,7 +1127,7 @@ msgstr "Comportamiento"
msgid "Best" msgid "Best"
msgstr "Mejor" msgstr "Mejor"
#: playlist/playlist.cpp:1382 #: playlist/playlist.cpp:1386
msgid "Bit Depth" msgid "Bit Depth"
msgstr "" msgstr ""
@ -1143,7 +1143,7 @@ msgid "Bit rate"
msgstr "Tasa de bits" msgstr "Tasa de bits"
#: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149 #: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149
#: playlist/playlist.cpp:1383 ../build/src/ui_groupbydialog.h:210 #: playlist/playlist.cpp:1387 ../build/src/ui_groupbydialog.h:210
#: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254 #: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254
#: ../build/src/ui_transcoderoptionsaac.h:132 #: ../build/src/ui_transcoderoptionsaac.h:132
#: ../build/src/ui_transcoderoptionsopus.h:76 #: ../build/src/ui_transcoderoptionsopus.h:76
@ -1214,7 +1214,7 @@ msgstr "La reproducción de CD solo es posible con el motor GStreamer."
msgid "CDDA" msgid "CDDA"
msgstr "CDDA" msgstr "CDDA"
#: playlist/playlist.cpp:1396 #: playlist/playlist.cpp:1400
msgid "CUE" msgid "CUE"
msgstr "CUE" msgstr "CUE"
@ -1371,7 +1371,7 @@ msgstr "Búsqueda en la colección"
msgid "Comma separated list of class:level, level is 0-3" msgid "Comma separated list of class:level, level is 0-3"
msgstr "Lista separada por comas de la clase:nivel, el nivel es 0-3" msgstr "Lista separada por comas de la clase:nivel, el nivel es 0-3"
#: playlist/playlist.cpp:1392 smartplaylists/smartplaylistsearchterm.cpp:391 #: playlist/playlist.cpp:1396 smartplaylists/smartplaylistsearchterm.cpp:391
#: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918 #: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918
msgid "Comment" msgid "Comment"
msgstr "Comentario" msgstr "Comentario"
@ -1388,7 +1388,7 @@ msgstr "Completar etiquetas automáticamente"
msgid "Complete tags automatically..." msgid "Complete tags automatically..."
msgstr "Completar etiquetas automáticamente…" msgstr "Completar etiquetas automáticamente…"
#: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1373 #: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1377
#: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204 #: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204
#: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248 #: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248
#: ../build/src/ui_edittagdialog.h:915 #: ../build/src/ui_edittagdialog.h:915
@ -1471,7 +1471,7 @@ msgstr "Copiar en la colección…"
msgid "Copy to device" msgid "Copy to device"
msgstr "Copiar en un dispositivo" msgstr "Copiar en un dispositivo"
#: core/mainwindow.cpp:758 collection/collectionview.cpp:361 #: core/mainwindow.cpp:758 collection/collectionview.cpp:381
#: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48 #: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48
msgid "Copy to device..." msgid "Copy to device..."
msgstr "Copiar en un dispositivo…" msgstr "Copiar en un dispositivo…"
@ -1482,6 +1482,16 @@ msgid ""
"avoid losing configuration before you uninstall the snap:" "avoid losing configuration before you uninstall the snap:"
msgstr "" msgstr ""
#: device/gpoddevice.cpp:241
#, qt-format
msgid "Could not copy %1 to %2: %3"
msgstr ""
#: core/filesystemmusicstorage.cpp:98
#, qt-format
msgid "Could not copy file %1 to %2."
msgstr ""
#: transcoder/transcoder.cpp:72 #: transcoder/transcoder.cpp:72
#, qt-format #, qt-format
msgid "" msgid ""
@ -1496,6 +1506,10 @@ msgstr ""
msgid "Could not open CUE file %1 for reading: %2" msgid "Could not open CUE file %1 for reading: %2"
msgstr "" msgstr ""
#: device/mtpconnection.cpp:75 device/mtpconnection.cpp:109
msgid "Could not open MTP device."
msgstr ""
#: scrobbler/scrobblingapi20.cpp:223 #: scrobbler/scrobblingapi20.cpp:223
msgid "Could not open URL. Please open this URL in your browser" msgid "Could not open URL. Please open this URL in your browser"
msgstr "No se ha podido abrir URL. Por favor, ábrela en tu navegador" msgstr "No se ha podido abrir URL. Por favor, ábrela en tu navegador"
@ -1727,11 +1741,11 @@ msgstr "Dance"
msgid "Database corruption detected." msgid "Database corruption detected."
msgstr "Se han detectado errores en la base de datos" msgstr "Se han detectado errores en la base de datos"
#: playlist/playlist.cpp:1390 #: playlist/playlist.cpp:1394
msgid "Date Created" msgid "Date Created"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1389 #: playlist/playlist.cpp:1393
msgid "Date Modified" msgid "Date Modified"
msgstr "" msgstr ""
@ -1784,7 +1798,7 @@ msgstr "Eliminar archivos"
msgid "Delete from device..." msgid "Delete from device..."
msgstr "Eliminar del dispositivo…" msgstr "Eliminar del dispositivo…"
#: core/mainwindow.cpp:760 collection/collectionview.cpp:363 #: core/mainwindow.cpp:760 collection/collectionview.cpp:383
#: widgets/fileviewlist.cpp:49 #: widgets/fileviewlist.cpp:49
msgid "Delete from disk..." msgid "Delete from disk..."
msgstr "Eliminar del disco…" msgstr "Eliminar del disco…"
@ -1822,6 +1836,16 @@ msgstr "Quitar la pista de la cola"
msgid "Destination" msgid "Destination"
msgstr "Destino" msgstr "Destino"
#: core/filesystemmusicstorage.cpp:92
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite"
msgstr ""
#: core/filesystemmusicstorage.cpp:73
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite."
msgstr ""
#: ../build/src/ui_transcodedialog.h:235 #: ../build/src/ui_transcodedialog.h:235
msgid "Details..." msgid "Details..."
msgstr "Detalles…" msgstr "Detalles…"
@ -1868,7 +1892,7 @@ msgctxt "Refers to a disabled notification type in Notification settings."
msgid "Disabled" msgid "Disabled"
msgstr "Desactivado" msgstr "Desactivado"
#: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1367 #: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1371
#: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196 #: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196
#: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240 #: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240
#: ../build/src/ui_edittagdialog.h:908 #: ../build/src/ui_edittagdialog.h:908
@ -1912,7 +1936,7 @@ msgstr "No volver a mostrar este mensaje."
msgid "Don't repeat" msgid "Don't repeat"
msgstr "No repetir" msgstr "No repetir"
#: collection/collectionview.cpp:376 #: collection/collectionview.cpp:396
msgid "Don't show in various artists" msgid "Don't show in various artists"
msgstr "No mostrar en Varios artistas" msgstr "No mostrar en Varios artistas"
@ -2011,12 +2035,12 @@ msgstr "Editar etiqueta…"
msgid "Edit track information" msgid "Edit track information"
msgstr "Editar información de la pista" msgstr "Editar información de la pista"
#: collection/collectionview.cpp:366 widgets/fileviewlist.cpp:52 #: collection/collectionview.cpp:386 widgets/fileviewlist.cpp:52
#: ../build/src/ui_mainwindow.h:642 #: ../build/src/ui_mainwindow.h:642
msgid "Edit track information..." msgid "Edit track information..."
msgstr "Editar información de la pista…" msgstr "Editar información de la pista…"
#: collection/collectionview.cpp:367 #: collection/collectionview.cpp:387
msgid "Edit tracks information..." msgid "Edit tracks information..."
msgstr "Editar información de las pistas…" msgstr "Editar información de las pistas…"
@ -2170,7 +2194,7 @@ msgid "Equivalent to --log-levels *:3"
msgstr "Equivalente a --log-levels*:3" msgstr "Equivalente a --log-levels*:3"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
@ -2179,6 +2203,11 @@ msgstr "Error"
msgid "Error connecting MTP device %1" msgid "Error connecting MTP device %1"
msgstr "Error al conectar al dispositivo MTP %1" msgstr "Error al conectar al dispositivo MTP %1"
#: device/mtploader.cpp:77
#, qt-format
msgid "Error connecting MTP device %1: %2"
msgstr ""
#: organize/organizeerrordialog.cpp:71 #: organize/organizeerrordialog.cpp:71
msgid "Error copying songs" msgid "Error copying songs"
msgstr "Error al copiar pistas" msgstr "Error al copiar pistas"
@ -2305,6 +2334,11 @@ msgstr "Duración del fundido"
msgid "Failed SQL query: %1" msgid "Failed SQL query: %1"
msgstr "" msgstr ""
#: core/filesystemmusicstorage.cpp:57
#, qt-format
msgid "Failed to create directory %1."
msgstr ""
#: covermanager/albumcoverchoicecontroller.cpp:379 #: covermanager/albumcoverchoicecontroller.cpp:379
#: covermanager/albumcoverchoicecontroller.cpp:396 #: covermanager/albumcoverchoicecontroller.cpp:396
#, qt-format #, qt-format
@ -2381,19 +2415,19 @@ msgstr ""
msgid "File %1 is not recognized as a valid audio file." msgid "File %1 is not recognized as a valid audio file."
msgstr "El archivo de audio %1 no parece válido." msgstr "El archivo de audio %1 no parece válido."
#: playlist/playlist.cpp:1385 #: playlist/playlist.cpp:1389
msgid "File Name" msgid "File Name"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1386 #: playlist/playlist.cpp:1390
msgid "File Name (without path)" msgid "File Name (without path)"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1387 #: playlist/playlist.cpp:1391
msgid "File Size" msgid "File Size"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1388 #: playlist/playlist.cpp:1392
msgid "File Type" msgid "File Type"
msgstr "" msgstr ""
@ -2575,7 +2609,7 @@ msgstr "Configuración general"
msgid "Genius Authentication" msgid "Genius Authentication"
msgstr "Autenticación con Genius" msgstr "Autenticación con Genius"
#: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1371 #: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1375
#: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198 #: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198
#: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242 #: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242
#: ../build/src/ui_edittagdialog.h:917 #: ../build/src/ui_edittagdialog.h:917
@ -2687,7 +2721,7 @@ msgstr "Agrupar por género/artista del álbum/álbum"
msgid "Group by Genre/Artist/Album" msgid "Group by Genre/Artist/Album"
msgstr "Agrupar por género/artista/álbum" msgstr "Agrupar por género/artista/álbum"
#: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1375 #: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1379
#: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206 #: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206
#: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250 #: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250
#: ../build/src/ui_edittagdialog.h:909 #: ../build/src/ui_edittagdialog.h:909
@ -2864,7 +2898,7 @@ msgstr "Insertar…"
msgid "Install strawberry through PPA:" msgid "Install strawberry through PPA:"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1398 #: playlist/playlist.cpp:1402
msgid "Integrated Loudness" msgid "Integrated Loudness"
msgstr "" msgstr ""
@ -2884,6 +2918,11 @@ msgstr "Vista de pestañas de Internet"
msgid "Intro tracks" msgid "Intro tracks"
msgstr "Pistas de introducción" msgstr "Pistas de introducción"
#: device/mtpconnection.cpp:57
#, qt-format
msgid "Invalid MTP device: %1"
msgstr ""
#: scrobbler/scrobblingapi20.cpp:257 #: scrobbler/scrobblingapi20.cpp:257
msgid "Invalid reply from web browser. Missing token." msgid "Invalid reply from web browser. Missing token."
msgstr "El servidor web devolvió una respuesta no válida. Falta la ficha." msgstr "El servidor web devolvió una respuesta no válida. Falta la ficha."
@ -2944,7 +2983,7 @@ msgstr "Cubierta de álbum grande"
msgid "Large sidebar" msgid "Large sidebar"
msgstr "Barra lateral grande" msgstr "Barra lateral grande"
#: playlist/playlist.cpp:1379 #: playlist/playlist.cpp:1383
msgid "Last Played" msgid "Last Played"
msgstr "" msgstr ""
@ -2975,7 +3014,7 @@ msgstr "Pistas menos valoradas"
msgid "Left" msgid "Left"
msgstr "Izquierda" msgstr "Izquierda"
#: context/contextview.cpp:163 playlist/playlist.cpp:1368 #: context/contextview.cpp:163 playlist/playlist.cpp:1372
#: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888 #: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888
msgid "Length" msgid "Length"
msgstr "Duración" msgstr "Duración"
@ -3082,7 +3121,7 @@ msgstr "Acceder"
msgid "Long term prediction profile (LTP)" msgid "Long term prediction profile (LTP)"
msgstr "Perfil de predicción a largo plazo (LTP)" msgstr "Perfil de predicción a largo plazo (LTP)"
#: playlist/playlist.cpp:1399 #: playlist/playlist.cpp:1403
msgid "Loudness Range" msgid "Loudness Range"
msgstr "" msgstr ""
@ -3117,13 +3156,22 @@ msgid "Lyrics providers"
msgstr "Proveedores de letras" msgstr "Proveedores de letras"
#: ../build/src/ui_subsonicsettingspage.h:251 #: ../build/src/ui_subsonicsettingspage.h:251
msgid "MD5 token" msgid "MD5 token (Recommended)"
msgstr "MD5 token" msgstr ""
#: ../build/src/ui_transcodersettingspage.h:194 #: ../build/src/ui_transcodersettingspage.h:194
msgid "MP3" msgid "MP3"
msgstr "MP3" msgstr "MP3"
#: device/mtpconnection.cpp:100
msgid "MTP device not found."
msgstr ""
#: device/mtpconnection.cpp:86
#, qt-format
msgid "MTP error: %1"
msgstr ""
#: ../build/src/ui_transcoderoptionsaac.h:135 #: ../build/src/ui_transcoderoptionsaac.h:135
msgid "Main profile (MAIN)" msgid "Main profile (MAIN)"
msgstr "Perfil principal (MAIN)" msgstr "Perfil principal (MAIN)"
@ -3275,7 +3323,7 @@ msgstr "Vigilar cambios en la colección"
msgid "Months" msgid "Months"
msgstr "Meses" msgstr "Meses"
#: playlist/playlist.cpp:1394 #: playlist/playlist.cpp:1398
msgid "Mood" msgid "Mood"
msgstr "Ánimo" msgstr "Ánimo"
@ -3453,7 +3501,7 @@ msgid "None"
msgstr "Ninguno" msgstr "Ninguno"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "None of the selected songs were suitable for copying to a device" msgid "None of the selected songs were suitable for copying to a device"
msgstr "" msgstr ""
"Ninguna de las pistas seleccionadas era apta para copiarse en un dispositivo" "Ninguna de las pistas seleccionadas era apta para copiarse en un dispositivo"
@ -3556,7 +3604,7 @@ msgstr "Abrir dispositivo"
msgid "Open homepage" msgid "Open homepage"
msgstr "" msgstr ""
#: collection/collectionview.cpp:352 #: collection/collectionview.cpp:368
#: smartplaylists/smartplaylistsviewcontainer.cpp:67 #: smartplaylists/smartplaylistsviewcontainer.cpp:67
#: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318 #: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318
#: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77 #: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77
@ -3594,7 +3642,7 @@ msgstr "Opus"
msgid "Organize Files" msgid "Organize Files"
msgstr "Organizar archivos" msgstr "Organizar archivos"
#: core/mainwindow.cpp:754 collection/collectionview.cpp:359 #: core/mainwindow.cpp:754 collection/collectionview.cpp:379
msgid "Organize files..." msgid "Organize files..."
msgstr "Organizar archivos…" msgstr "Organizar archivos…"
@ -3602,7 +3650,7 @@ msgstr "Organizar archivos…"
msgid "Organizing files" msgid "Organizing files"
msgstr "Organizando archivos" msgstr "Organizando archivos"
#: playlist/playlist.cpp:1370 #: playlist/playlist.cpp:1374
msgid "Original Year" msgid "Original Year"
msgstr "" msgstr ""
@ -3709,7 +3757,7 @@ msgstr ""
msgid "Perform track loudness normalization" msgid "Perform track loudness normalization"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1374 #: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1378
#: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205 #: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205
#: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249 #: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249
#: ../build/src/ui_edittagdialog.h:919 #: ../build/src/ui_edittagdialog.h:919
@ -3730,7 +3778,7 @@ msgstr "Barra lateral simple"
msgid "Play" msgid "Play"
msgstr "Reproducir" msgstr "Reproducir"
#: playlist/playlist.cpp:1377 #: playlist/playlist.cpp:1381
msgid "Play Count" msgid "Play Count"
msgstr "" msgstr ""
@ -3996,12 +4044,12 @@ msgstr "Poner en cola las pistas seleccionadas"
msgid "Queue selected tracks to play next" msgid "Queue selected tracks to play next"
msgstr "Poner en cola las pistas seleccionadas para reproducir a continuación" msgstr "Poner en cola las pistas seleccionadas para reproducir a continuación"
#: core/mainwindow.cpp:1961 collection/collectionview.cpp:356 #: core/mainwindow.cpp:1961 collection/collectionview.cpp:372
#: internet/internetcollectionview.cpp:321 #: internet/internetcollectionview.cpp:321
msgid "Queue to play next" msgid "Queue to play next"
msgstr "Poner en cola para reproducir a continuación" msgstr "Poner en cola para reproducir a continuación"
#: core/mainwindow.cpp:1953 collection/collectionview.cpp:355 #: core/mainwindow.cpp:1953 collection/collectionview.cpp:371
#: smartplaylists/smartplaylistsviewcontainer.cpp:70 #: smartplaylists/smartplaylistsviewcontainer.cpp:70
#: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320 #: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320
msgid "Queue track" msgid "Queue track"
@ -4027,7 +4075,7 @@ msgstr ""
msgid "Random" msgid "Random"
msgstr "Al azar" msgstr "Al azar"
#: playlist/playlist.cpp:1395 ../build/src/ui_edittagdialog.h:922 #: playlist/playlist.cpp:1399 ../build/src/ui_edittagdialog.h:922
msgid "Rating" msgid "Rating"
msgstr "Valoración" msgstr "Valoración"
@ -4230,7 +4278,7 @@ msgstr "Repetir lista de reproducción"
msgid "Repeat track" msgid "Repeat track"
msgstr "Repetir pista" msgstr "Repetir pista"
#: collection/collectionview.cpp:351 #: collection/collectionview.cpp:367
#: smartplaylists/smartplaylistsviewcontainer.cpp:66 #: smartplaylists/smartplaylistsviewcontainer.cpp:66
#: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317 #: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317
#: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73 #: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73
@ -4266,7 +4314,7 @@ msgstr "Faltan elementos en la respuesta de Tidal."
msgid "Repopulate" msgid "Repopulate"
msgstr "Volver a poblar" msgstr "Volver a poblar"
#: collection/collectionview.cpp:372 #: collection/collectionview.cpp:392
msgid "Rescan song(s)" msgid "Rescan song(s)"
msgstr "Volver a escanear pistas" msgstr "Volver a escanear pistas"
@ -4369,7 +4417,7 @@ msgstr "Quitar dispositivo con seguridad"
msgid "Safely remove the device after copying" msgid "Safely remove the device after copying"
msgstr "Quitar dispositivo con seguridad después de copiar" msgstr "Quitar dispositivo con seguridad después de copiar"
#: playlist/playlist.cpp:1381 #: playlist/playlist.cpp:1385
msgid "Sample Rate" msgid "Sample Rate"
msgstr "" msgstr ""
@ -4503,7 +4551,7 @@ msgstr "Demora de búsqueda"
msgid "Search for album covers..." msgid "Search for album covers..."
msgstr "Buscar cubiertas de álbumes…" msgstr "Buscar cubiertas de álbumes…"
#: internet/internetsearchview.cpp:339 #: collection/collectionview.cpp:376 internet/internetsearchview.cpp:339
msgid "Search for this" msgid "Search for this"
msgstr "Buscar esto" msgstr "Buscar esto"
@ -4733,12 +4781,12 @@ msgstr "Mostrar en la colección…"
msgid "Show in file browser" msgid "Show in file browser"
msgstr "Mostrar en el navegador de archivos" msgstr "Mostrar en el navegador de archivos"
#: core/mainwindow.cpp:753 collection/collectionview.cpp:368 #: core/mainwindow.cpp:753 collection/collectionview.cpp:388
#: widgets/fileviewlist.cpp:53 #: widgets/fileviewlist.cpp:53
msgid "Show in file browser..." msgid "Show in file browser..."
msgstr "Mostrar en el gestor de archivos…" msgstr "Mostrar en el gestor de archivos…"
#: collection/collectionview.cpp:375 #: collection/collectionview.cpp:395
msgid "Show in various artists" msgid "Show in various artists"
msgstr "Mostrar en Varios artistas" msgstr "Mostrar en Varios artistas"
@ -4839,7 +4887,7 @@ msgstr "Tamaño:"
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"
#: playlist/playlist.cpp:1378 #: playlist/playlist.cpp:1382
msgid "Skip Count" msgid "Skip Count"
msgstr "" msgstr ""
@ -4938,7 +4986,7 @@ msgstr "Ordenar temas por"
msgid "Sorting" msgid "Sorting"
msgstr "Ordenación" msgstr "Ordenación"
#: playlist/playlist.cpp:1393 #: playlist/playlist.cpp:1397
msgid "Source" msgid "Source"
msgstr "Origen" msgstr "Origen"
@ -5248,7 +5296,7 @@ msgstr ""
"La versión de Strawberry a la que se acaba de actualizar necesita volver a " "La versión de Strawberry a la que se acaba de actualizar necesita volver a "
"analizar la colección debido a estas nuevas funciones:" "analizar la colección debido a estas nuevas funciones:"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "There are other songs in this album" msgid "There are other songs in this album"
msgstr "Hay otras pistas en este álbum" msgstr "Hay otras pistas en este álbum"
@ -5365,7 +5413,7 @@ msgstr ""
msgid "Time step" msgid "Time step"
msgstr "Salto en el tiempo" msgstr "Salto en el tiempo"
#: playlist/playlist.cpp:1363 organize/organizedialog.cpp:104 #: playlist/playlist.cpp:1367 organize/organizedialog.cpp:104
#: ../build/src/ui_contextsettingspage.h:422 #: ../build/src/ui_contextsettingspage.h:422
#: ../build/src/ui_edittagdialog.h:913 #: ../build/src/ui_edittagdialog.h:913
#: ../build/src/ui_trackselectiondialog.h:210 #: ../build/src/ui_trackselectiondialog.h:210
@ -5416,7 +5464,7 @@ msgstr "Total de bytes transferidos"
msgid "Total network requests made" msgid "Total network requests made"
msgstr "Total de solicitudes hechas a la red" msgstr "Total de solicitudes hechas a la red"
#: playlist/playlist.cpp:1366 organize/organizedialog.cpp:112 #: playlist/playlist.cpp:1370 organize/organizedialog.cpp:112
#: ../build/src/ui_edittagdialog.h:921 #: ../build/src/ui_edittagdialog.h:921
#: ../build/src/ui_trackselectiondialog.h:212 #: ../build/src/ui_trackselectiondialog.h:212
msgid "Track" msgid "Track"
@ -5769,7 +5817,7 @@ msgstr "Sin cubierta:"
msgid "Work in offline mode (Only cache scrobbles)" msgid "Work in offline mode (Only cache scrobbles)"
msgstr "Trabajar sin conexión (solo registros de reproducción prealmacenados)" msgstr "Trabajar sin conexión (solo registros de reproducción prealmacenados)"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "" msgid ""
"Would you like to move the other songs on this album to Various Artists as " "Would you like to move the other songs on this album to Various Artists as "
"well?" "well?"
@ -5788,7 +5836,16 @@ msgstr ""
msgid "Write metadata when saving playlists" msgid "Write metadata when saving playlists"
msgstr "Escribir los metadatos al guardar las listas de reproducción" msgstr "Escribir los metadatos al guardar las listas de reproducción"
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1369 #: device/gpoddevice.cpp:288
msgid "Writing database failed."
msgstr ""
#: device/gpoddevice.cpp:284
#, qt-format
msgid "Writing database failed: %1"
msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1373
#: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199 #: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199
#: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243 #: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243
#: ../build/src/ui_edittagdialog.h:912 #: ../build/src/ui_edittagdialog.h:912

View File

@ -739,7 +739,7 @@ msgstr "Después de copiar…"
msgid "Albu&m cover" msgid "Albu&m cover"
msgstr "C&ubierta del álbum" msgstr "C&ubierta del álbum"
#: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1365 #: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1369
#: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194 #: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194
#: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238 #: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238
#: ../build/src/ui_albumcoversearcher.h:108 #: ../build/src/ui_albumcoversearcher.h:108
@ -759,7 +759,7 @@ msgstr "Álbum (volumen idóneo para todas las pistas)"
msgid "Album - Disc" msgid "Album - Disc"
msgstr "Álbum - Disco" msgstr "Álbum - Disco"
#: playlist/playlist.cpp:1372 #: playlist/playlist.cpp:1376
msgid "Album Artist" msgid "Album Artist"
msgstr "" msgstr ""
@ -850,7 +850,7 @@ msgstr "Comenzar siempre la reproducción"
msgid "An error occurred loading the iTunes database" msgid "An error occurred loading the iTunes database"
msgstr "Se produjo un error al cargar la base de datos de iTunes" msgstr "Se produjo un error al cargar la base de datos de iTunes"
#: playlist/playlist.cpp:426 dialogs/edittagdialog.cpp:1450 #: playlist/playlist.cpp:430 dialogs/edittagdialog.cpp:1450
#, qt-format #, qt-format
msgid "An error occurred writing metadata to '%1'" msgid "An error occurred writing metadata to '%1'"
msgstr "Se produjo un error al escribir los metadatos en «%1»" msgstr "Se produjo un error al escribir los metadatos en «%1»"
@ -879,7 +879,7 @@ msgstr "Añadir «explícito» al nombre de los álbumes explícitos"
msgid "Append files/URLs to the playlist" msgid "Append files/URLs to the playlist"
msgstr "Añadir archivos/URL a la lista de reproducción" msgstr "Añadir archivos/URL a la lista de reproducción"
#: collection/collectionview.cpp:350 #: collection/collectionview.cpp:366
#: smartplaylists/smartplaylistsviewcontainer.cpp:65 #: smartplaylists/smartplaylistsviewcontainer.cpp:65
#: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316 #: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316
#: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69 #: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69
@ -930,7 +930,7 @@ msgstr "Cubierta manual"
msgid "Art Unset" msgid "Art Unset"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1364 #: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1368
#: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192 #: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192
#: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236 #: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236
#: ../build/src/ui_albumcoversearcher.h:104 #: ../build/src/ui_albumcoversearcher.h:104
@ -1091,7 +1091,7 @@ msgstr "Comportamiento"
msgid "Best" msgid "Best"
msgstr "Mejor" msgstr "Mejor"
#: playlist/playlist.cpp:1382 #: playlist/playlist.cpp:1386
msgid "Bit Depth" msgid "Bit Depth"
msgstr "" msgstr ""
@ -1107,7 +1107,7 @@ msgid "Bit rate"
msgstr "Tasa de bits" msgstr "Tasa de bits"
#: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149 #: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149
#: playlist/playlist.cpp:1383 ../build/src/ui_groupbydialog.h:210 #: playlist/playlist.cpp:1387 ../build/src/ui_groupbydialog.h:210
#: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254 #: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254
#: ../build/src/ui_transcoderoptionsaac.h:132 #: ../build/src/ui_transcoderoptionsaac.h:132
#: ../build/src/ui_transcoderoptionsopus.h:76 #: ../build/src/ui_transcoderoptionsopus.h:76
@ -1178,7 +1178,7 @@ msgstr "La reproducción de CD solo es posible con el motor GStreamer."
msgid "CDDA" msgid "CDDA"
msgstr "CDDA" msgstr "CDDA"
#: playlist/playlist.cpp:1396 #: playlist/playlist.cpp:1400
msgid "CUE" msgid "CUE"
msgstr "CUE" msgstr "CUE"
@ -1335,7 +1335,7 @@ msgstr "Búsqueda en la colección"
msgid "Comma separated list of class:level, level is 0-3" msgid "Comma separated list of class:level, level is 0-3"
msgstr "Lista separada por comas de la clase:nivel, el nivel es 0-3" msgstr "Lista separada por comas de la clase:nivel, el nivel es 0-3"
#: playlist/playlist.cpp:1392 smartplaylists/smartplaylistsearchterm.cpp:391 #: playlist/playlist.cpp:1396 smartplaylists/smartplaylistsearchterm.cpp:391
#: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918 #: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918
msgid "Comment" msgid "Comment"
msgstr "Comentario" msgstr "Comentario"
@ -1352,7 +1352,7 @@ msgstr "Completar etiquetas automáticamente"
msgid "Complete tags automatically..." msgid "Complete tags automatically..."
msgstr "Completar etiquetas automáticamente…" msgstr "Completar etiquetas automáticamente…"
#: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1373 #: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1377
#: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204 #: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204
#: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248 #: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248
#: ../build/src/ui_edittagdialog.h:915 #: ../build/src/ui_edittagdialog.h:915
@ -1435,7 +1435,7 @@ msgstr "Copiar en la colección…"
msgid "Copy to device" msgid "Copy to device"
msgstr "Copiar en un dispositivo" msgstr "Copiar en un dispositivo"
#: core/mainwindow.cpp:758 collection/collectionview.cpp:361 #: core/mainwindow.cpp:758 collection/collectionview.cpp:381
#: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48 #: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48
msgid "Copy to device..." msgid "Copy to device..."
msgstr "Copiar en un dispositivo…" msgstr "Copiar en un dispositivo…"
@ -1446,6 +1446,16 @@ msgid ""
"avoid losing configuration before you uninstall the snap:" "avoid losing configuration before you uninstall the snap:"
msgstr "" msgstr ""
#: device/gpoddevice.cpp:241
#, qt-format
msgid "Could not copy %1 to %2: %3"
msgstr ""
#: core/filesystemmusicstorage.cpp:98
#, qt-format
msgid "Could not copy file %1 to %2."
msgstr ""
#: transcoder/transcoder.cpp:72 #: transcoder/transcoder.cpp:72
#, qt-format #, qt-format
msgid "" msgid ""
@ -1460,6 +1470,10 @@ msgstr ""
msgid "Could not open CUE file %1 for reading: %2" msgid "Could not open CUE file %1 for reading: %2"
msgstr "" msgstr ""
#: device/mtpconnection.cpp:75 device/mtpconnection.cpp:109
msgid "Could not open MTP device."
msgstr ""
#: scrobbler/scrobblingapi20.cpp:223 #: scrobbler/scrobblingapi20.cpp:223
msgid "Could not open URL. Please open this URL in your browser" msgid "Could not open URL. Please open this URL in your browser"
msgstr "No se ha podido abrir URL. Por favor, ábrela en tu navegador" msgstr "No se ha podido abrir URL. Por favor, ábrela en tu navegador"
@ -1691,11 +1705,11 @@ msgstr "Dance"
msgid "Database corruption detected." msgid "Database corruption detected."
msgstr "Se han detectado errores en la base de datos" msgstr "Se han detectado errores en la base de datos"
#: playlist/playlist.cpp:1390 #: playlist/playlist.cpp:1394
msgid "Date Created" msgid "Date Created"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1389 #: playlist/playlist.cpp:1393
msgid "Date Modified" msgid "Date Modified"
msgstr "" msgstr ""
@ -1748,7 +1762,7 @@ msgstr "Eliminar archivos"
msgid "Delete from device..." msgid "Delete from device..."
msgstr "Eliminar del dispositivo…" msgstr "Eliminar del dispositivo…"
#: core/mainwindow.cpp:760 collection/collectionview.cpp:363 #: core/mainwindow.cpp:760 collection/collectionview.cpp:383
#: widgets/fileviewlist.cpp:49 #: widgets/fileviewlist.cpp:49
msgid "Delete from disk..." msgid "Delete from disk..."
msgstr "Eliminar del disco…" msgstr "Eliminar del disco…"
@ -1786,6 +1800,16 @@ msgstr "Quitar la pista de la cola"
msgid "Destination" msgid "Destination"
msgstr "Destino" msgstr "Destino"
#: core/filesystemmusicstorage.cpp:92
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite"
msgstr ""
#: core/filesystemmusicstorage.cpp:73
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite."
msgstr ""
#: ../build/src/ui_transcodedialog.h:235 #: ../build/src/ui_transcodedialog.h:235
msgid "Details..." msgid "Details..."
msgstr "Detalles…" msgstr "Detalles…"
@ -1832,7 +1856,7 @@ msgctxt "Refers to a disabled notification type in Notification settings."
msgid "Disabled" msgid "Disabled"
msgstr "Desactivado" msgstr "Desactivado"
#: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1367 #: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1371
#: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196 #: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196
#: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240 #: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240
#: ../build/src/ui_edittagdialog.h:908 #: ../build/src/ui_edittagdialog.h:908
@ -1876,7 +1900,7 @@ msgstr "No volver a mostrar este mensaje."
msgid "Don't repeat" msgid "Don't repeat"
msgstr "No repetir" msgstr "No repetir"
#: collection/collectionview.cpp:376 #: collection/collectionview.cpp:396
msgid "Don't show in various artists" msgid "Don't show in various artists"
msgstr "No mostrar en Varios artistas" msgstr "No mostrar en Varios artistas"
@ -1975,12 +1999,12 @@ msgstr "Editar etiqueta…"
msgid "Edit track information" msgid "Edit track information"
msgstr "Editar información de la pista" msgstr "Editar información de la pista"
#: collection/collectionview.cpp:366 widgets/fileviewlist.cpp:52 #: collection/collectionview.cpp:386 widgets/fileviewlist.cpp:52
#: ../build/src/ui_mainwindow.h:642 #: ../build/src/ui_mainwindow.h:642
msgid "Edit track information..." msgid "Edit track information..."
msgstr "Editar información de la pista…" msgstr "Editar información de la pista…"
#: collection/collectionview.cpp:367 #: collection/collectionview.cpp:387
msgid "Edit tracks information..." msgid "Edit tracks information..."
msgstr "Editar información de las pistas…" msgstr "Editar información de las pistas…"
@ -2134,7 +2158,7 @@ msgid "Equivalent to --log-levels *:3"
msgstr "Equivalente a --log-levels*:3" msgstr "Equivalente a --log-levels*:3"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
@ -2143,6 +2167,11 @@ msgstr "Error"
msgid "Error connecting MTP device %1" msgid "Error connecting MTP device %1"
msgstr "Error al conectar al dispositivo MTP %1" msgstr "Error al conectar al dispositivo MTP %1"
#: device/mtploader.cpp:77
#, qt-format
msgid "Error connecting MTP device %1: %2"
msgstr ""
#: organize/organizeerrordialog.cpp:71 #: organize/organizeerrordialog.cpp:71
msgid "Error copying songs" msgid "Error copying songs"
msgstr "Error al copiar pistas" msgstr "Error al copiar pistas"
@ -2269,6 +2298,11 @@ msgstr "Duración del fundido"
msgid "Failed SQL query: %1" msgid "Failed SQL query: %1"
msgstr "" msgstr ""
#: core/filesystemmusicstorage.cpp:57
#, qt-format
msgid "Failed to create directory %1."
msgstr ""
#: covermanager/albumcoverchoicecontroller.cpp:379 #: covermanager/albumcoverchoicecontroller.cpp:379
#: covermanager/albumcoverchoicecontroller.cpp:396 #: covermanager/albumcoverchoicecontroller.cpp:396
#, qt-format #, qt-format
@ -2345,19 +2379,19 @@ msgstr ""
msgid "File %1 is not recognized as a valid audio file." msgid "File %1 is not recognized as a valid audio file."
msgstr "El archivo de audio %1 no parece válido." msgstr "El archivo de audio %1 no parece válido."
#: playlist/playlist.cpp:1385 #: playlist/playlist.cpp:1389
msgid "File Name" msgid "File Name"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1386 #: playlist/playlist.cpp:1390
msgid "File Name (without path)" msgid "File Name (without path)"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1387 #: playlist/playlist.cpp:1391
msgid "File Size" msgid "File Size"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1388 #: playlist/playlist.cpp:1392
msgid "File Type" msgid "File Type"
msgstr "" msgstr ""
@ -2539,7 +2573,7 @@ msgstr "Configuración general"
msgid "Genius Authentication" msgid "Genius Authentication"
msgstr "Autenticación con Genius" msgstr "Autenticación con Genius"
#: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1371 #: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1375
#: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198 #: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198
#: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242 #: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242
#: ../build/src/ui_edittagdialog.h:917 #: ../build/src/ui_edittagdialog.h:917
@ -2651,7 +2685,7 @@ msgstr "Agrupar por género/artista del álbum/álbum"
msgid "Group by Genre/Artist/Album" msgid "Group by Genre/Artist/Album"
msgstr "Agrupar por género/artista/álbum" msgstr "Agrupar por género/artista/álbum"
#: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1375 #: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1379
#: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206 #: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206
#: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250 #: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250
#: ../build/src/ui_edittagdialog.h:909 #: ../build/src/ui_edittagdialog.h:909
@ -2828,7 +2862,7 @@ msgstr "Insertar…"
msgid "Install strawberry through PPA:" msgid "Install strawberry through PPA:"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1398 #: playlist/playlist.cpp:1402
msgid "Integrated Loudness" msgid "Integrated Loudness"
msgstr "" msgstr ""
@ -2848,6 +2882,11 @@ msgstr "Vista de pestañas de Internet"
msgid "Intro tracks" msgid "Intro tracks"
msgstr "Pistas de introducción" msgstr "Pistas de introducción"
#: device/mtpconnection.cpp:57
#, qt-format
msgid "Invalid MTP device: %1"
msgstr ""
#: scrobbler/scrobblingapi20.cpp:257 #: scrobbler/scrobblingapi20.cpp:257
msgid "Invalid reply from web browser. Missing token." msgid "Invalid reply from web browser. Missing token."
msgstr "El servidor web devolvió una respuesta no válida. Falta la ficha." msgstr "El servidor web devolvió una respuesta no válida. Falta la ficha."
@ -2908,7 +2947,7 @@ msgstr "Cubierta de álbum grande"
msgid "Large sidebar" msgid "Large sidebar"
msgstr "Barra lateral grande" msgstr "Barra lateral grande"
#: playlist/playlist.cpp:1379 #: playlist/playlist.cpp:1383
msgid "Last Played" msgid "Last Played"
msgstr "" msgstr ""
@ -2939,7 +2978,7 @@ msgstr "Pistas menos valoradas"
msgid "Left" msgid "Left"
msgstr "Izquierda" msgstr "Izquierda"
#: context/contextview.cpp:163 playlist/playlist.cpp:1368 #: context/contextview.cpp:163 playlist/playlist.cpp:1372
#: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888 #: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888
msgid "Length" msgid "Length"
msgstr "Duración" msgstr "Duración"
@ -3046,7 +3085,7 @@ msgstr "Acceder"
msgid "Long term prediction profile (LTP)" msgid "Long term prediction profile (LTP)"
msgstr "Perfil de predicción a largo plazo (LTP)" msgstr "Perfil de predicción a largo plazo (LTP)"
#: playlist/playlist.cpp:1399 #: playlist/playlist.cpp:1403
msgid "Loudness Range" msgid "Loudness Range"
msgstr "" msgstr ""
@ -3081,13 +3120,22 @@ msgid "Lyrics providers"
msgstr "Proveedores de letras" msgstr "Proveedores de letras"
#: ../build/src/ui_subsonicsettingspage.h:251 #: ../build/src/ui_subsonicsettingspage.h:251
msgid "MD5 token" msgid "MD5 token (Recommended)"
msgstr "MD5 token" msgstr ""
#: ../build/src/ui_transcodersettingspage.h:194 #: ../build/src/ui_transcodersettingspage.h:194
msgid "MP3" msgid "MP3"
msgstr "MP3" msgstr "MP3"
#: device/mtpconnection.cpp:100
msgid "MTP device not found."
msgstr ""
#: device/mtpconnection.cpp:86
#, qt-format
msgid "MTP error: %1"
msgstr ""
#: ../build/src/ui_transcoderoptionsaac.h:135 #: ../build/src/ui_transcoderoptionsaac.h:135
msgid "Main profile (MAIN)" msgid "Main profile (MAIN)"
msgstr "Perfil principal (MAIN)" msgstr "Perfil principal (MAIN)"
@ -3239,7 +3287,7 @@ msgstr "Vigilar cambios en la colección"
msgid "Months" msgid "Months"
msgstr "Meses" msgstr "Meses"
#: playlist/playlist.cpp:1394 #: playlist/playlist.cpp:1398
msgid "Mood" msgid "Mood"
msgstr "Ánimo" msgstr "Ánimo"
@ -3417,7 +3465,7 @@ msgid "None"
msgstr "Ninguno" msgstr "Ninguno"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "None of the selected songs were suitable for copying to a device" msgid "None of the selected songs were suitable for copying to a device"
msgstr "" msgstr ""
"Ninguna de las pistas seleccionadas era apta para copiarse en un dispositivo" "Ninguna de las pistas seleccionadas era apta para copiarse en un dispositivo"
@ -3520,7 +3568,7 @@ msgstr "Abrir dispositivo"
msgid "Open homepage" msgid "Open homepage"
msgstr "" msgstr ""
#: collection/collectionview.cpp:352 #: collection/collectionview.cpp:368
#: smartplaylists/smartplaylistsviewcontainer.cpp:67 #: smartplaylists/smartplaylistsviewcontainer.cpp:67
#: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318 #: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318
#: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77 #: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77
@ -3558,7 +3606,7 @@ msgstr "Opus"
msgid "Organize Files" msgid "Organize Files"
msgstr "Organizar archivos" msgstr "Organizar archivos"
#: core/mainwindow.cpp:754 collection/collectionview.cpp:359 #: core/mainwindow.cpp:754 collection/collectionview.cpp:379
msgid "Organize files..." msgid "Organize files..."
msgstr "Organizar archivos…" msgstr "Organizar archivos…"
@ -3566,7 +3614,7 @@ msgstr "Organizar archivos…"
msgid "Organizing files" msgid "Organizing files"
msgstr "Organizando archivos" msgstr "Organizando archivos"
#: playlist/playlist.cpp:1370 #: playlist/playlist.cpp:1374
msgid "Original Year" msgid "Original Year"
msgstr "" msgstr ""
@ -3673,7 +3721,7 @@ msgstr ""
msgid "Perform track loudness normalization" msgid "Perform track loudness normalization"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1374 #: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1378
#: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205 #: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205
#: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249 #: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249
#: ../build/src/ui_edittagdialog.h:919 #: ../build/src/ui_edittagdialog.h:919
@ -3694,7 +3742,7 @@ msgstr "Barra lateral simple"
msgid "Play" msgid "Play"
msgstr "Reproducir" msgstr "Reproducir"
#: playlist/playlist.cpp:1377 #: playlist/playlist.cpp:1381
msgid "Play Count" msgid "Play Count"
msgstr "" msgstr ""
@ -3960,12 +4008,12 @@ msgstr "Poner en cola las pistas seleccionadas"
msgid "Queue selected tracks to play next" msgid "Queue selected tracks to play next"
msgstr "Poner en cola las pistas seleccionadas para reproducir a continuación" msgstr "Poner en cola las pistas seleccionadas para reproducir a continuación"
#: core/mainwindow.cpp:1961 collection/collectionview.cpp:356 #: core/mainwindow.cpp:1961 collection/collectionview.cpp:372
#: internet/internetcollectionview.cpp:321 #: internet/internetcollectionview.cpp:321
msgid "Queue to play next" msgid "Queue to play next"
msgstr "Poner en cola para reproducir a continuación" msgstr "Poner en cola para reproducir a continuación"
#: core/mainwindow.cpp:1953 collection/collectionview.cpp:355 #: core/mainwindow.cpp:1953 collection/collectionview.cpp:371
#: smartplaylists/smartplaylistsviewcontainer.cpp:70 #: smartplaylists/smartplaylistsviewcontainer.cpp:70
#: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320 #: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320
msgid "Queue track" msgid "Queue track"
@ -3991,7 +4039,7 @@ msgstr ""
msgid "Random" msgid "Random"
msgstr "Al azar" msgstr "Al azar"
#: playlist/playlist.cpp:1395 ../build/src/ui_edittagdialog.h:922 #: playlist/playlist.cpp:1399 ../build/src/ui_edittagdialog.h:922
msgid "Rating" msgid "Rating"
msgstr "Valoración" msgstr "Valoración"
@ -4194,7 +4242,7 @@ msgstr "Repetir lista de reproducción"
msgid "Repeat track" msgid "Repeat track"
msgstr "Repetir pista" msgstr "Repetir pista"
#: collection/collectionview.cpp:351 #: collection/collectionview.cpp:367
#: smartplaylists/smartplaylistsviewcontainer.cpp:66 #: smartplaylists/smartplaylistsviewcontainer.cpp:66
#: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317 #: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317
#: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73 #: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73
@ -4230,7 +4278,7 @@ msgstr "Faltan elementos en la respuesta de Tidal."
msgid "Repopulate" msgid "Repopulate"
msgstr "Volver a poblar" msgstr "Volver a poblar"
#: collection/collectionview.cpp:372 #: collection/collectionview.cpp:392
msgid "Rescan song(s)" msgid "Rescan song(s)"
msgstr "Volver a escanear pistas" msgstr "Volver a escanear pistas"
@ -4333,7 +4381,7 @@ msgstr "Quitar dispositivo con seguridad"
msgid "Safely remove the device after copying" msgid "Safely remove the device after copying"
msgstr "Quitar dispositivo con seguridad después de copiar" msgstr "Quitar dispositivo con seguridad después de copiar"
#: playlist/playlist.cpp:1381 #: playlist/playlist.cpp:1385
msgid "Sample Rate" msgid "Sample Rate"
msgstr "" msgstr ""
@ -4467,7 +4515,7 @@ msgstr "Demora de búsqueda"
msgid "Search for album covers..." msgid "Search for album covers..."
msgstr "Buscar cubiertas de álbumes…" msgstr "Buscar cubiertas de álbumes…"
#: internet/internetsearchview.cpp:339 #: collection/collectionview.cpp:376 internet/internetsearchview.cpp:339
msgid "Search for this" msgid "Search for this"
msgstr "Buscar esto" msgstr "Buscar esto"
@ -4697,12 +4745,12 @@ msgstr "Mostrar en la colección…"
msgid "Show in file browser" msgid "Show in file browser"
msgstr "Mostrar en el navegador de archivos" msgstr "Mostrar en el navegador de archivos"
#: core/mainwindow.cpp:753 collection/collectionview.cpp:368 #: core/mainwindow.cpp:753 collection/collectionview.cpp:388
#: widgets/fileviewlist.cpp:53 #: widgets/fileviewlist.cpp:53
msgid "Show in file browser..." msgid "Show in file browser..."
msgstr "Mostrar en el gestor de archivos…" msgstr "Mostrar en el gestor de archivos…"
#: collection/collectionview.cpp:375 #: collection/collectionview.cpp:395
msgid "Show in various artists" msgid "Show in various artists"
msgstr "Mostrar en Varios artistas" msgstr "Mostrar en Varios artistas"
@ -4803,7 +4851,7 @@ msgstr "Tamaño:"
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"
#: playlist/playlist.cpp:1378 #: playlist/playlist.cpp:1382
msgid "Skip Count" msgid "Skip Count"
msgstr "" msgstr ""
@ -4902,7 +4950,7 @@ msgstr "Ordenar temas por"
msgid "Sorting" msgid "Sorting"
msgstr "Ordenación" msgstr "Ordenación"
#: playlist/playlist.cpp:1393 #: playlist/playlist.cpp:1397
msgid "Source" msgid "Source"
msgstr "Origen" msgstr "Origen"
@ -5212,7 +5260,7 @@ msgstr ""
"La versión de Strawberry a la que se acaba de actualizar necesita volver a " "La versión de Strawberry a la que se acaba de actualizar necesita volver a "
"analizar la colección debido a estas nuevas funciones:" "analizar la colección debido a estas nuevas funciones:"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "There are other songs in this album" msgid "There are other songs in this album"
msgstr "Hay otras pistas en este álbum" msgstr "Hay otras pistas en este álbum"
@ -5329,7 +5377,7 @@ msgstr ""
msgid "Time step" msgid "Time step"
msgstr "Salto en el tiempo" msgstr "Salto en el tiempo"
#: playlist/playlist.cpp:1363 organize/organizedialog.cpp:104 #: playlist/playlist.cpp:1367 organize/organizedialog.cpp:104
#: ../build/src/ui_contextsettingspage.h:422 #: ../build/src/ui_contextsettingspage.h:422
#: ../build/src/ui_edittagdialog.h:913 #: ../build/src/ui_edittagdialog.h:913
#: ../build/src/ui_trackselectiondialog.h:210 #: ../build/src/ui_trackselectiondialog.h:210
@ -5380,7 +5428,7 @@ msgstr "Total de bytes transferidos"
msgid "Total network requests made" msgid "Total network requests made"
msgstr "Total de solicitudes hechas a la red" msgstr "Total de solicitudes hechas a la red"
#: playlist/playlist.cpp:1366 organize/organizedialog.cpp:112 #: playlist/playlist.cpp:1370 organize/organizedialog.cpp:112
#: ../build/src/ui_edittagdialog.h:921 #: ../build/src/ui_edittagdialog.h:921
#: ../build/src/ui_trackselectiondialog.h:212 #: ../build/src/ui_trackselectiondialog.h:212
msgid "Track" msgid "Track"
@ -5733,7 +5781,7 @@ msgstr "Sin cubierta:"
msgid "Work in offline mode (Only cache scrobbles)" msgid "Work in offline mode (Only cache scrobbles)"
msgstr "Trabajar sin conexión (solo registros de reproducción prealmacenados)" msgstr "Trabajar sin conexión (solo registros de reproducción prealmacenados)"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "" msgid ""
"Would you like to move the other songs on this album to Various Artists as " "Would you like to move the other songs on this album to Various Artists as "
"well?" "well?"
@ -5752,7 +5800,16 @@ msgstr ""
msgid "Write metadata when saving playlists" msgid "Write metadata when saving playlists"
msgstr "Escribir los metadatos al guardar las listas de reproducción" msgstr "Escribir los metadatos al guardar las listas de reproducción"
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1369 #: device/gpoddevice.cpp:288
msgid "Writing database failed."
msgstr ""
#: device/gpoddevice.cpp:284
#, qt-format
msgid "Writing database failed: %1"
msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1373
#: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199 #: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199
#: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243 #: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243
#: ../build/src/ui_edittagdialog.h:912 #: ../build/src/ui_edittagdialog.h:912

View File

@ -753,7 +753,7 @@ msgstr "Después de copiar…"
msgid "Albu&m cover" msgid "Albu&m cover"
msgstr "&Portada del álbum" msgstr "&Portada del álbum"
#: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1365 #: collection/savedgroupingmanager.cpp:98 playlist/playlist.cpp:1369
#: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194 #: organize/organizedialog.cpp:105 ../build/src/ui_groupbydialog.h:194
#: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238 #: ../build/src/ui_groupbydialog.h:216 ../build/src/ui_groupbydialog.h:238
#: ../build/src/ui_albumcoversearcher.h:108 #: ../build/src/ui_albumcoversearcher.h:108
@ -773,7 +773,7 @@ msgstr "Álbum (volumen idóneo para todas las pistas)"
msgid "Album - Disc" msgid "Album - Disc"
msgstr "Álbum - Disco" msgstr "Álbum - Disco"
#: playlist/playlist.cpp:1372 #: playlist/playlist.cpp:1376
msgid "Album Artist" msgid "Album Artist"
msgstr "" msgstr ""
@ -864,7 +864,7 @@ msgstr "Comenzar siempre la reproducción"
msgid "An error occurred loading the iTunes database" msgid "An error occurred loading the iTunes database"
msgstr "Se produjo un error al cargar la base de datos de iTunes" msgstr "Se produjo un error al cargar la base de datos de iTunes"
#: playlist/playlist.cpp:426 dialogs/edittagdialog.cpp:1450 #: playlist/playlist.cpp:430 dialogs/edittagdialog.cpp:1450
#, qt-format #, qt-format
msgid "An error occurred writing metadata to '%1'" msgid "An error occurred writing metadata to '%1'"
msgstr "Se produjo un error al escribir los metadatos en «%1»" msgstr "Se produjo un error al escribir los metadatos en «%1»"
@ -893,7 +893,7 @@ msgstr "Añadir «explícito» al nombre de los álbumes explícitos"
msgid "Append files/URLs to the playlist" msgid "Append files/URLs to the playlist"
msgstr "Añadir archivos/URL a la lista de reproducción" msgstr "Añadir archivos/URL a la lista de reproducción"
#: collection/collectionview.cpp:350 #: collection/collectionview.cpp:366
#: smartplaylists/smartplaylistsviewcontainer.cpp:65 #: smartplaylists/smartplaylistsviewcontainer.cpp:65
#: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316 #: widgets/fileviewlist.cpp:42 internet/internetsearchview.cpp:316
#: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69 #: internet/internetcollectionview.cpp:315 radios/radioview.cpp:69
@ -946,7 +946,7 @@ msgstr "Portada manual"
msgid "Art Unset" msgid "Art Unset"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1364 #: collection/savedgroupingmanager.cpp:95 playlist/playlist.cpp:1368
#: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192 #: organize/organizedialog.cpp:106 ../build/src/ui_groupbydialog.h:192
#: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236 #: ../build/src/ui_groupbydialog.h:214 ../build/src/ui_groupbydialog.h:236
#: ../build/src/ui_albumcoversearcher.h:104 #: ../build/src/ui_albumcoversearcher.h:104
@ -1107,7 +1107,7 @@ msgstr "Comportamiento"
msgid "Best" msgid "Best"
msgstr "Mejor" msgstr "Mejor"
#: playlist/playlist.cpp:1382 #: playlist/playlist.cpp:1386
msgid "Bit Depth" msgid "Bit Depth"
msgstr "" msgstr ""
@ -1123,7 +1123,7 @@ msgid "Bit rate"
msgstr "Tasa de bits" msgstr "Tasa de bits"
#: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149 #: context/contextview.cpp:166 collection/savedgroupingmanager.cpp:149
#: playlist/playlist.cpp:1383 ../build/src/ui_groupbydialog.h:210 #: playlist/playlist.cpp:1387 ../build/src/ui_groupbydialog.h:210
#: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254 #: ../build/src/ui_groupbydialog.h:232 ../build/src/ui_groupbydialog.h:254
#: ../build/src/ui_transcoderoptionsaac.h:132 #: ../build/src/ui_transcoderoptionsaac.h:132
#: ../build/src/ui_transcoderoptionsopus.h:76 #: ../build/src/ui_transcoderoptionsopus.h:76
@ -1194,7 +1194,7 @@ msgstr "La reproducción de CD solo es posible con el motor GStreamer."
msgid "CDDA" msgid "CDDA"
msgstr "CDDA" msgstr "CDDA"
#: playlist/playlist.cpp:1396 #: playlist/playlist.cpp:1400
msgid "CUE" msgid "CUE"
msgstr "CUE" msgstr "CUE"
@ -1350,7 +1350,7 @@ msgstr "Búsqueda en la colección"
msgid "Comma separated list of class:level, level is 0-3" msgid "Comma separated list of class:level, level is 0-3"
msgstr "Lista separada por comas de la clase:nivel, el nivel es 0-3" msgstr "Lista separada por comas de la clase:nivel, el nivel es 0-3"
#: playlist/playlist.cpp:1392 smartplaylists/smartplaylistsearchterm.cpp:391 #: playlist/playlist.cpp:1396 smartplaylists/smartplaylistsearchterm.cpp:391
#: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918 #: organize/organizedialog.cpp:117 ../build/src/ui_edittagdialog.h:918
msgid "Comment" msgid "Comment"
msgstr "Comentario" msgstr "Comentario"
@ -1367,7 +1367,7 @@ msgstr "Completar etiquetas automáticamente"
msgid "Complete tags automatically..." msgid "Complete tags automatically..."
msgstr "Completar etiquetas automáticamente…" msgstr "Completar etiquetas automáticamente…"
#: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1373 #: collection/savedgroupingmanager.cpp:128 playlist/playlist.cpp:1377
#: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204 #: organize/organizedialog.cpp:109 ../build/src/ui_groupbydialog.h:204
#: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248 #: ../build/src/ui_groupbydialog.h:226 ../build/src/ui_groupbydialog.h:248
#: ../build/src/ui_edittagdialog.h:915 #: ../build/src/ui_edittagdialog.h:915
@ -1450,7 +1450,7 @@ msgstr "Copiar en la colección…"
msgid "Copy to device" msgid "Copy to device"
msgstr "Copiar en un dispositivo" msgstr "Copiar en un dispositivo"
#: core/mainwindow.cpp:758 collection/collectionview.cpp:361 #: core/mainwindow.cpp:758 collection/collectionview.cpp:381
#: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48 #: playlist/playlistlistcontainer.cpp:92 widgets/fileviewlist.cpp:48
msgid "Copy to device..." msgid "Copy to device..."
msgstr "Copiar en un dispositivo…" msgstr "Copiar en un dispositivo…"
@ -1463,6 +1463,16 @@ msgstr ""
"Copia los archivos strawberry.conf y strawberry.db de tu directorio ~/snap " "Copia los archivos strawberry.conf y strawberry.db de tu directorio ~/snap "
"antes de desinstalar el paquete snap para no perder tu configuración:" "antes de desinstalar el paquete snap para no perder tu configuración:"
#: device/gpoddevice.cpp:241
#, qt-format
msgid "Could not copy %1 to %2: %3"
msgstr ""
#: core/filesystemmusicstorage.cpp:98
#, qt-format
msgid "Could not copy file %1 to %2."
msgstr ""
#: transcoder/transcoder.cpp:72 #: transcoder/transcoder.cpp:72
#, qt-format #, qt-format
msgid "" msgid ""
@ -1477,6 +1487,10 @@ msgstr ""
msgid "Could not open CUE file %1 for reading: %2" msgid "Could not open CUE file %1 for reading: %2"
msgstr "No se ha podido leer el archivo CUE %1: %2" msgstr "No se ha podido leer el archivo CUE %1: %2"
#: device/mtpconnection.cpp:75 device/mtpconnection.cpp:109
msgid "Could not open MTP device."
msgstr ""
#: scrobbler/scrobblingapi20.cpp:223 #: scrobbler/scrobblingapi20.cpp:223
msgid "Could not open URL. Please open this URL in your browser" msgid "Could not open URL. Please open this URL in your browser"
msgstr "No se ha podido abrir URL. Por favor, ábrala en su navegador" msgstr "No se ha podido abrir URL. Por favor, ábrala en su navegador"
@ -1708,11 +1722,11 @@ msgstr "Dance"
msgid "Database corruption detected." msgid "Database corruption detected."
msgstr "Se han detectado errores en la base de datos." msgstr "Se han detectado errores en la base de datos."
#: playlist/playlist.cpp:1390 #: playlist/playlist.cpp:1394
msgid "Date Created" msgid "Date Created"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1389 #: playlist/playlist.cpp:1393
msgid "Date Modified" msgid "Date Modified"
msgstr "" msgstr ""
@ -1765,7 +1779,7 @@ msgstr "Eliminar archivos"
msgid "Delete from device..." msgid "Delete from device..."
msgstr "Eliminar del dispositivo…" msgstr "Eliminar del dispositivo…"
#: core/mainwindow.cpp:760 collection/collectionview.cpp:363 #: core/mainwindow.cpp:760 collection/collectionview.cpp:383
#: widgets/fileviewlist.cpp:49 #: widgets/fileviewlist.cpp:49
msgid "Delete from disk..." msgid "Delete from disk..."
msgstr "Eliminar del disco…" msgstr "Eliminar del disco…"
@ -1803,6 +1817,16 @@ msgstr "Quitar la pista de la cola"
msgid "Destination" msgid "Destination"
msgstr "Destino" msgstr "Destino"
#: core/filesystemmusicstorage.cpp:92
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite"
msgstr ""
#: core/filesystemmusicstorage.cpp:73
#, qt-format
msgid "Destination file %1 exists, but not allowed to overwrite."
msgstr ""
#: ../build/src/ui_transcodedialog.h:235 #: ../build/src/ui_transcodedialog.h:235
msgid "Details..." msgid "Details..."
msgstr "Detalles…" msgstr "Detalles…"
@ -1849,7 +1873,7 @@ msgctxt "Refers to a disabled notification type in Notification settings."
msgid "Disabled" msgid "Disabled"
msgstr "Desactivado" msgstr "Desactivado"
#: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1367 #: collection/savedgroupingmanager.cpp:116 playlist/playlist.cpp:1371
#: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196 #: organize/organizedialog.cpp:113 ../build/src/ui_groupbydialog.h:196
#: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240 #: ../build/src/ui_groupbydialog.h:218 ../build/src/ui_groupbydialog.h:240
#: ../build/src/ui_edittagdialog.h:908 #: ../build/src/ui_edittagdialog.h:908
@ -1893,7 +1917,7 @@ msgstr "No volver a mostrar este mensaje."
msgid "Don't repeat" msgid "Don't repeat"
msgstr "No repetir" msgstr "No repetir"
#: collection/collectionview.cpp:376 #: collection/collectionview.cpp:396
msgid "Don't show in various artists" msgid "Don't show in various artists"
msgstr "No mostrar en Varios artistas" msgstr "No mostrar en Varios artistas"
@ -1992,12 +2016,12 @@ msgstr "Editar etiqueta…"
msgid "Edit track information" msgid "Edit track information"
msgstr "Editar información de la pista" msgstr "Editar información de la pista"
#: collection/collectionview.cpp:366 widgets/fileviewlist.cpp:52 #: collection/collectionview.cpp:386 widgets/fileviewlist.cpp:52
#: ../build/src/ui_mainwindow.h:642 #: ../build/src/ui_mainwindow.h:642
msgid "Edit track information..." msgid "Edit track information..."
msgstr "Editar información de la pista…" msgstr "Editar información de la pista…"
#: collection/collectionview.cpp:367 #: collection/collectionview.cpp:387
msgid "Edit tracks information..." msgid "Edit tracks information..."
msgstr "Editar información de las pistas…" msgstr "Editar información de las pistas…"
@ -2151,7 +2175,7 @@ msgid "Equivalent to --log-levels *:3"
msgstr "Equivalente a --log-levels*:3" msgstr "Equivalente a --log-levels*:3"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
@ -2160,6 +2184,11 @@ msgstr "Error"
msgid "Error connecting MTP device %1" msgid "Error connecting MTP device %1"
msgstr "Error al conectar al dispositivo MTP %1" msgstr "Error al conectar al dispositivo MTP %1"
#: device/mtploader.cpp:77
#, qt-format
msgid "Error connecting MTP device %1: %2"
msgstr ""
#: organize/organizeerrordialog.cpp:71 #: organize/organizeerrordialog.cpp:71
msgid "Error copying songs" msgid "Error copying songs"
msgstr "Error al copiar temas" msgstr "Error al copiar temas"
@ -2286,6 +2315,11 @@ msgstr "Duración del fundido"
msgid "Failed SQL query: %1" msgid "Failed SQL query: %1"
msgstr "" msgstr ""
#: core/filesystemmusicstorage.cpp:57
#, qt-format
msgid "Failed to create directory %1."
msgstr ""
#: covermanager/albumcoverchoicecontroller.cpp:379 #: covermanager/albumcoverchoicecontroller.cpp:379
#: covermanager/albumcoverchoicecontroller.cpp:396 #: covermanager/albumcoverchoicecontroller.cpp:396
#, qt-format #, qt-format
@ -2362,19 +2396,19 @@ msgstr "El archivo %1 no existe."
msgid "File %1 is not recognized as a valid audio file." msgid "File %1 is not recognized as a valid audio file."
msgstr "El archivo de audio %1 no parece válido." msgstr "El archivo de audio %1 no parece válido."
#: playlist/playlist.cpp:1385 #: playlist/playlist.cpp:1389
msgid "File Name" msgid "File Name"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1386 #: playlist/playlist.cpp:1390
msgid "File Name (without path)" msgid "File Name (without path)"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1387 #: playlist/playlist.cpp:1391
msgid "File Size" msgid "File Size"
msgstr "" msgstr ""
#: playlist/playlist.cpp:1388 #: playlist/playlist.cpp:1392
msgid "File Type" msgid "File Type"
msgstr "" msgstr ""
@ -2554,7 +2588,7 @@ msgstr "Configuración general"
msgid "Genius Authentication" msgid "Genius Authentication"
msgstr "Autenticación con Genius" msgstr "Autenticación con Genius"
#: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1371 #: collection/savedgroupingmanager.cpp:125 playlist/playlist.cpp:1375
#: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198 #: organize/organizedialog.cpp:116 ../build/src/ui_groupbydialog.h:198
#: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242 #: ../build/src/ui_groupbydialog.h:220 ../build/src/ui_groupbydialog.h:242
#: ../build/src/ui_edittagdialog.h:917 #: ../build/src/ui_edittagdialog.h:917
@ -2666,7 +2700,7 @@ msgstr "Agrupar por género/artista del álbum/álbum"
msgid "Group by Genre/Artist/Album" msgid "Group by Genre/Artist/Album"
msgstr "Agrupar por género/artista/álbum" msgstr "Agrupar por género/artista/álbum"
#: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1375 #: collection/savedgroupingmanager.cpp:134 playlist/playlist.cpp:1379
#: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206 #: organize/organizedialog.cpp:111 ../build/src/ui_groupbydialog.h:206
#: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250 #: ../build/src/ui_groupbydialog.h:228 ../build/src/ui_groupbydialog.h:250
#: ../build/src/ui_edittagdialog.h:909 #: ../build/src/ui_edittagdialog.h:909
@ -2843,7 +2877,7 @@ msgstr "Insertar…"
msgid "Install strawberry through PPA:" msgid "Install strawberry through PPA:"
msgstr "Instalar Strawberry mediante un PPA:" msgstr "Instalar Strawberry mediante un PPA:"
#: playlist/playlist.cpp:1398 #: playlist/playlist.cpp:1402
msgid "Integrated Loudness" msgid "Integrated Loudness"
msgstr "" msgstr ""
@ -2863,6 +2897,11 @@ msgstr "Vista de pestañas de Internet"
msgid "Intro tracks" msgid "Intro tracks"
msgstr "Pistas de introducción" msgstr "Pistas de introducción"
#: device/mtpconnection.cpp:57
#, qt-format
msgid "Invalid MTP device: %1"
msgstr ""
#: scrobbler/scrobblingapi20.cpp:257 #: scrobbler/scrobblingapi20.cpp:257
msgid "Invalid reply from web browser. Missing token." msgid "Invalid reply from web browser. Missing token."
msgstr "El servidor web devolvió una respuesta no válida. Falta el token." msgstr "El servidor web devolvió una respuesta no válida. Falta el token."
@ -2923,7 +2962,7 @@ msgstr "Portadas de álbum grande"
msgid "Large sidebar" msgid "Large sidebar"
msgstr "Barra lateral grande" msgstr "Barra lateral grande"
#: playlist/playlist.cpp:1379 #: playlist/playlist.cpp:1383
msgid "Last Played" msgid "Last Played"
msgstr "" msgstr ""
@ -2954,7 +2993,7 @@ msgstr "Pistas menos valoradas"
msgid "Left" msgid "Left"
msgstr "Izquierda" msgstr "Izquierda"
#: context/contextview.cpp:163 playlist/playlist.cpp:1368 #: context/contextview.cpp:163 playlist/playlist.cpp:1372
#: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888 #: organize/organizedialog.cpp:118 ../build/src/ui_edittagdialog.h:888
msgid "Length" msgid "Length"
msgstr "Duración" msgstr "Duración"
@ -3061,7 +3100,7 @@ msgstr "Acceder"
msgid "Long term prediction profile (LTP)" msgid "Long term prediction profile (LTP)"
msgstr "Perfil de predicción a largo plazo (LTP)" msgstr "Perfil de predicción a largo plazo (LTP)"
#: playlist/playlist.cpp:1399 #: playlist/playlist.cpp:1403
msgid "Loudness Range" msgid "Loudness Range"
msgstr "" msgstr ""
@ -3096,13 +3135,22 @@ msgid "Lyrics providers"
msgstr "Proveedores de letras" msgstr "Proveedores de letras"
#: ../build/src/ui_subsonicsettingspage.h:251 #: ../build/src/ui_subsonicsettingspage.h:251
msgid "MD5 token" msgid "MD5 token (Recommended)"
msgstr "Token MD5" msgstr ""
#: ../build/src/ui_transcodersettingspage.h:194 #: ../build/src/ui_transcodersettingspage.h:194
msgid "MP3" msgid "MP3"
msgstr "MP3" msgstr "MP3"
#: device/mtpconnection.cpp:100
msgid "MTP device not found."
msgstr ""
#: device/mtpconnection.cpp:86
#, qt-format
msgid "MTP error: %1"
msgstr ""
#: ../build/src/ui_transcoderoptionsaac.h:135 #: ../build/src/ui_transcoderoptionsaac.h:135
msgid "Main profile (MAIN)" msgid "Main profile (MAIN)"
msgstr "Perfil principal (MAIN)" msgstr "Perfil principal (MAIN)"
@ -3254,7 +3302,7 @@ msgstr "Vigilar cambios en la colección"
msgid "Months" msgid "Months"
msgstr "Meses" msgstr "Meses"
#: playlist/playlist.cpp:1394 #: playlist/playlist.cpp:1398
msgid "Mood" msgid "Mood"
msgstr "Ánimo" msgstr "Ánimo"
@ -3432,7 +3480,7 @@ msgid "None"
msgstr "Ninguno" msgstr "Ninguno"
#: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776 #: core/mainwindow.cpp:2625 core/mainwindow.cpp:2776
#: collection/collectionview.cpp:587 #: collection/collectionview.cpp:701
msgid "None of the selected songs were suitable for copying to a device" msgid "None of the selected songs were suitable for copying to a device"
msgstr "Ninguna de los temas seleccionados podía copiarse en un dispositivo" msgstr "Ninguna de los temas seleccionados podía copiarse en un dispositivo"
@ -3534,7 +3582,7 @@ msgstr "Abrir dispositivo"
msgid "Open homepage" msgid "Open homepage"
msgstr "Abrir página principal" msgstr "Abrir página principal"
#: collection/collectionview.cpp:352 #: collection/collectionview.cpp:368
#: smartplaylists/smartplaylistsviewcontainer.cpp:67 #: smartplaylists/smartplaylistsviewcontainer.cpp:67
#: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318 #: widgets/fileviewlist.cpp:44 internet/internetsearchview.cpp:318
#: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77 #: internet/internetcollectionview.cpp:317 radios/radioview.cpp:77
@ -3572,7 +3620,7 @@ msgstr "Opus"
msgid "Organize Files" msgid "Organize Files"
msgstr "Organizar archivos" msgstr "Organizar archivos"
#: core/mainwindow.cpp:754 collection/collectionview.cpp:359 #: core/mainwindow.cpp:754 collection/collectionview.cpp:379
msgid "Organize files..." msgid "Organize files..."
msgstr "Organizar archivos…" msgstr "Organizar archivos…"
@ -3580,7 +3628,7 @@ msgstr "Organizar archivos…"
msgid "Organizing files" msgid "Organizing files"
msgstr "Organizando archivos" msgstr "Organizando archivos"
#: playlist/playlist.cpp:1370 #: playlist/playlist.cpp:1374
msgid "Original Year" msgid "Original Year"
msgstr "" msgstr ""
@ -3689,7 +3737,7 @@ msgstr ""
msgid "Perform track loudness normalization" msgid "Perform track loudness normalization"
msgstr "" msgstr ""
#: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1374 #: collection/savedgroupingmanager.cpp:131 playlist/playlist.cpp:1378
#: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205 #: organize/organizedialog.cpp:110 ../build/src/ui_groupbydialog.h:205
#: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249 #: ../build/src/ui_groupbydialog.h:227 ../build/src/ui_groupbydialog.h:249
#: ../build/src/ui_edittagdialog.h:919 #: ../build/src/ui_edittagdialog.h:919
@ -3710,7 +3758,7 @@ msgstr "Barra lateral simple"
msgid "Play" msgid "Play"
msgstr "Reproducir" msgstr "Reproducir"
#: playlist/playlist.cpp:1377 #: playlist/playlist.cpp:1381
msgid "Play Count" msgid "Play Count"
msgstr "" msgstr ""
@ -3976,12 +4024,12 @@ msgstr "Poner en cola las pistas seleccionadas"
msgid "Queue selected tracks to play next" msgid "Queue selected tracks to play next"
msgstr "Poner en cola las pistas seleccionadas para reproducir a continuación" msgstr "Poner en cola las pistas seleccionadas para reproducir a continuación"
#: core/mainwindow.cpp:1961 collection/collectionview.cpp:356 #: core/mainwindow.cpp:1961 collection/collectionview.cpp:372
#: internet/internetcollectionview.cpp:321 #: internet/internetcollectionview.cpp:321
msgid "Queue to play next" msgid "Queue to play next"
msgstr "Poner en cola para reproducir a continuación" msgstr "Poner en cola para reproducir a continuación"
#: core/mainwindow.cpp:1953 collection/collectionview.cpp:355 #: core/mainwindow.cpp:1953 collection/collectionview.cpp:371
#: smartplaylists/smartplaylistsviewcontainer.cpp:70 #: smartplaylists/smartplaylistsviewcontainer.cpp:70
#: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320 #: internet/internetsearchview.cpp:321 internet/internetcollectionview.cpp:320
msgid "Queue track" msgid "Queue track"
@ -4007,7 +4055,7 @@ msgstr "Radios"
msgid "Random" msgid "Random"
msgstr "Al azar" msgstr "Al azar"
#: playlist/playlist.cpp:1395 ../build/src/ui_edittagdialog.h:922 #: playlist/playlist.cpp:1399 ../build/src/ui_edittagdialog.h:922
msgid "Rating" msgid "Rating"
msgstr "Valoración" msgstr "Valoración"
@ -4214,7 +4262,7 @@ msgstr "Repetir lista de reproducción"
msgid "Repeat track" msgid "Repeat track"
msgstr "Repetir pista" msgstr "Repetir pista"
#: collection/collectionview.cpp:351 #: collection/collectionview.cpp:367
#: smartplaylists/smartplaylistsviewcontainer.cpp:66 #: smartplaylists/smartplaylistsviewcontainer.cpp:66
#: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317 #: widgets/fileviewlist.cpp:43 internet/internetsearchview.cpp:317
#: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73 #: internet/internetcollectionview.cpp:316 radios/radioview.cpp:73
@ -4250,7 +4298,7 @@ msgstr "Faltan elementos en la respuesta de Tidal."
msgid "Repopulate" msgid "Repopulate"
msgstr "Volver a poblar" msgstr "Volver a poblar"
#: collection/collectionview.cpp:372 #: collection/collectionview.cpp:392
msgid "Rescan song(s)" msgid "Rescan song(s)"
msgstr "Volver a escanear tema(s)" msgstr "Volver a escanear tema(s)"
@ -4353,7 +4401,7 @@ msgstr "Quitar dispositivo con seguridad"
msgid "Safely remove the device after copying" msgid "Safely remove the device after copying"
msgstr "Quitar dispositivo con seguridad después de copiar" msgstr "Quitar dispositivo con seguridad después de copiar"
#: playlist/playlist.cpp:1381 #: playlist/playlist.cpp:1385
msgid "Sample Rate" msgid "Sample Rate"
msgstr "" msgstr ""
@ -4489,7 +4537,7 @@ msgstr "Demora de búsqueda"
msgid "Search for album covers..." msgid "Search for album covers..."
msgstr "Buscar portadas de álbumes…" msgstr "Buscar portadas de álbumes…"
#: internet/internetsearchview.cpp:339 #: collection/collectionview.cpp:376 internet/internetsearchview.cpp:339
msgid "Search for this" msgid "Search for this"
msgstr "Buscar esto" msgstr "Buscar esto"
@ -4719,12 +4767,12 @@ msgstr "Mostrar en la colección…"
msgid "Show in file browser" msgid "Show in file browser"
msgstr "Mostrar en el navegador de archivos" msgstr "Mostrar en el navegador de archivos"
#: core/mainwindow.cpp:753 collection/collectionview.cpp:368 #: core/mainwindow.cpp:753 collection/collectionview.cpp:388
#: widgets/fileviewlist.cpp:53 #: widgets/fileviewlist.cpp:53
msgid "Show in file browser..." msgid "Show in file browser..."
msgstr "Mostrar en el gestor de archivos…" msgstr "Mostrar en el gestor de archivos…"
#: collection/collectionview.cpp:375 #: collection/collectionview.cpp:395
msgid "Show in various artists" msgid "Show in various artists"
msgstr "Mostrar en Varios artistas" msgstr "Mostrar en Varios artistas"
@ -4825,7 +4873,7 @@ msgstr "Tamaño:"
msgid "Ska" msgid "Ska"
msgstr "Ska" msgstr "Ska"
#: playlist/playlist.cpp:1378 #: playlist/playlist.cpp:1382
msgid "Skip Count" msgid "Skip Count"
msgstr "" msgstr ""
@ -4924,7 +4972,7 @@ msgstr "Ordenar temas por"
msgid "Sorting" msgid "Sorting"
msgstr "Ordenación" msgstr "Ordenación"
#: playlist/playlist.cpp:1393 #: playlist/playlist.cpp:1397
msgid "Source" msgid "Source"
msgstr "Origen" msgstr "Origen"
@ -5238,7 +5286,7 @@ msgstr ""
"La versión de Strawberry a la que se acaba de actualizar necesita volver a " "La versión de Strawberry a la que se acaba de actualizar necesita volver a "
"analizar la colección debido a estas nuevas funciones:" "analizar la colección debido a estas nuevas funciones:"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "There are other songs in this album" msgid "There are other songs in this album"
msgstr "Hay otros temas en este álbum" msgstr "Hay otros temas en este álbum"
@ -5355,7 +5403,7 @@ msgstr ""
msgid "Time step" msgid "Time step"
msgstr "Salto en el tiempo" msgstr "Salto en el tiempo"
#: playlist/playlist.cpp:1363 organize/organizedialog.cpp:104 #: playlist/playlist.cpp:1367 organize/organizedialog.cpp:104
#: ../build/src/ui_contextsettingspage.h:422 #: ../build/src/ui_contextsettingspage.h:422
#: ../build/src/ui_edittagdialog.h:913 #: ../build/src/ui_edittagdialog.h:913
#: ../build/src/ui_trackselectiondialog.h:210 #: ../build/src/ui_trackselectiondialog.h:210
@ -5406,7 +5454,7 @@ msgstr "Total de bytes transferidos"
msgid "Total network requests made" msgid "Total network requests made"
msgstr "Total de solicitudes hechas a la red" msgstr "Total de solicitudes hechas a la red"
#: playlist/playlist.cpp:1366 organize/organizedialog.cpp:112 #: playlist/playlist.cpp:1370 organize/organizedialog.cpp:112
#: ../build/src/ui_edittagdialog.h:921 #: ../build/src/ui_edittagdialog.h:921
#: ../build/src/ui_trackselectiondialog.h:212 #: ../build/src/ui_trackselectiondialog.h:212
msgid "Track" msgid "Track"
@ -5759,7 +5807,7 @@ msgstr "Sin portada:"
msgid "Work in offline mode (Only cache scrobbles)" msgid "Work in offline mode (Only cache scrobbles)"
msgstr "Trabajar sin conexión (solo registros de reproducción prealmacenados)" msgstr "Trabajar sin conexión (solo registros de reproducción prealmacenados)"
#: collection/collectionview.cpp:483 #: collection/collectionview.cpp:503
msgid "" msgid ""
"Would you like to move the other songs on this album to Various Artists as " "Would you like to move the other songs on this album to Various Artists as "
"well?" "well?"
@ -5780,7 +5828,16 @@ msgstr ""
msgid "Write metadata when saving playlists" msgid "Write metadata when saving playlists"
msgstr "Escribir los metadatos al guardar las listas de reproducción" msgstr "Escribir los metadatos al guardar las listas de reproducción"
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1369 #: device/gpoddevice.cpp:288
msgid "Writing database failed."
msgstr ""
#: device/gpoddevice.cpp:284
#, qt-format
msgid "Writing database failed: %1"
msgstr ""
#: collection/savedgroupingmanager.cpp:119 playlist/playlist.cpp:1373
#: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199 #: organize/organizedialog.cpp:114 ../build/src/ui_groupbydialog.h:199
#: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243 #: ../build/src/ui_groupbydialog.h:221 ../build/src/ui_groupbydialog.h:243
#: ../build/src/ui_edittagdialog.h:912 #: ../build/src/ui_edittagdialog.h:912

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