Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae5da12afb | ||
|
|
a3042b8f79 | ||
|
|
29cbfe7c1a | ||
|
|
1ddc3292cc | ||
|
|
658e1d122e | ||
|
|
d936a080db | ||
|
|
2a92af1e09 | ||
|
|
9cde537066 | ||
|
|
ffc5446914 | ||
|
|
5f70b32795 | ||
|
|
6b6117653a | ||
|
|
59bffed47f | ||
|
|
f91a679cdf | ||
|
|
66b8d27d66 | ||
|
|
1219f504ea | ||
|
|
ee5a191e39 | ||
|
|
f577aa8d4f | ||
|
|
2436c87372 | ||
|
|
e90b5e63e5 | ||
|
|
78588d8cdf | ||
|
|
20c1c1d4be | ||
|
|
329dfb21b9 | ||
|
|
02c30211a7 | ||
|
|
645da2713d | ||
|
|
20c5a79efa | ||
|
|
b224aeb0d8 | ||
|
|
73eebd6162 | ||
|
|
99a1851f4d | ||
|
|
d9d89d0927 | ||
|
|
54f2aa5f77 | ||
|
|
d022e9dd00 | ||
|
|
17cf8ec1c6 | ||
|
|
c4a6d81cda | ||
|
|
66ed485803 | ||
|
|
6de585d1c8 | ||
|
|
9498638988 | ||
|
|
87dad82210 | ||
|
|
e37aec16ac | ||
|
|
6fb48af598 | ||
|
|
8193be36e5 | ||
|
|
a7df2bc4fb | ||
|
|
5eda028af3 | ||
|
|
f77475dbfe | ||
|
|
96c1a35c8e | ||
|
|
0ef26be03f | ||
|
|
f5bb15f72e | ||
|
|
d84aebd8f4 | ||
|
|
7d8d9f4c4d | ||
|
|
61b201810d | ||
|
|
c75db8dc60 | ||
|
|
e0bf4091dd |
639
.github/workflows/ccpp.yml
vendored
639
.github/workflows/ccpp.yml
vendored
@@ -72,83 +72,6 @@ jobs:
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
|
||||
|
||||
build_opensuse_lp151:
|
||||
name: Build openSUSE Leap 15.1
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: opensuse/leap:15.1
|
||||
steps:
|
||||
- uses: actions/checkout@v1.2.0
|
||||
- name: Update packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
- name: Install openSUSE dependencies
|
||||
run: >
|
||||
zypper --non-interactive --gpg-auto-import-keys install
|
||||
lsb-release
|
||||
rpm-build
|
||||
git
|
||||
tar
|
||||
make
|
||||
cmake
|
||||
gcc
|
||||
gcc-c++
|
||||
gettext-tools
|
||||
glibc-devel
|
||||
libboost_headers-devel
|
||||
boost-devel
|
||||
glib2-devel
|
||||
glib2-tools
|
||||
dbus-1-devel
|
||||
alsa-devel
|
||||
libnotify-devel
|
||||
libgnutls-devel
|
||||
protobuf-devel
|
||||
sqlite3-devel
|
||||
libpulse-devel
|
||||
gstreamer-devel
|
||||
gstreamer-plugins-base-devel
|
||||
vlc-devel
|
||||
taglib-devel
|
||||
libQt5Core-devel
|
||||
libQt5Gui-devel
|
||||
libQt5Widgets-devel
|
||||
libQt5Concurrent-devel
|
||||
libQt5Network-devel
|
||||
libQt5Sql-devel
|
||||
libQt5DBus-devel
|
||||
libQt5Test-devel
|
||||
libqt5-qtx11extras-devel
|
||||
libqt5-qtbase-common-devel
|
||||
libQt5Sql5-sqlite
|
||||
libqt5-linguist-devel
|
||||
libcdio-devel
|
||||
libgpod-devel
|
||||
libmtp-devel
|
||||
libchromaprint-devel
|
||||
desktop-file-utils
|
||||
update-desktop-files
|
||||
appstream-glib
|
||||
hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON
|
||||
- name: Create source tarball
|
||||
working-directory: build
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
- name: Create RPM build sources directories
|
||||
run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
- name: Copy source tarball
|
||||
working-directory: build
|
||||
run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
- name: Build RPM
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_opensuse_lp152_qt5:
|
||||
name: Build openSUSE Leap 15.2 Qt 5
|
||||
runs-on: ubuntu-latest
|
||||
@@ -225,6 +148,7 @@ jobs:
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_opensuse_lp152_qt6:
|
||||
name: Build openSUSE Leap 15.2 Qt 6
|
||||
runs-on: ubuntu-latest
|
||||
@@ -302,165 +226,317 @@ jobs:
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
#build_opensuse_tumbleweed_qt5:
|
||||
#name: Build openSUSE Tumbleweed Qt 5
|
||||
#runs-on: ubuntu-latest
|
||||
#container:
|
||||
#image: opensuse/tumbleweed
|
||||
#steps:
|
||||
#- uses: actions/checkout@v1.2.0
|
||||
#- name: Lock packages
|
||||
#run: zypper --non-interactive --gpg-auto-import-keys addlock openssh-server
|
||||
#- name: Update packages
|
||||
#run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
#- name: Upgrade packages
|
||||
#run: zypper --non-interactive --gpg-auto-import-keys dup
|
||||
#- name: Install openSUSE dependencies
|
||||
#run: >
|
||||
#zypper --non-interactive --gpg-auto-import-keys install
|
||||
#lsb-release
|
||||
#rpm-build
|
||||
#git
|
||||
#tar
|
||||
#make
|
||||
#cmake
|
||||
#gcc
|
||||
#gcc-c++
|
||||
#gettext-tools
|
||||
#glibc-devel
|
||||
#libboost_headers-devel
|
||||
#boost-devel
|
||||
#glib2-devel
|
||||
#glib2-tools
|
||||
#dbus-1-devel
|
||||
#alsa-devel
|
||||
#libnotify-devel
|
||||
#libgnutls-devel
|
||||
#protobuf-devel
|
||||
#sqlite3-devel
|
||||
#libpulse-devel
|
||||
#gstreamer-devel
|
||||
#gstreamer-plugins-base-devel
|
||||
#vlc-devel
|
||||
#taglib-devel
|
||||
#libQt5Core-devel
|
||||
#libQt5Gui-devel
|
||||
#libQt5Widgets-devel
|
||||
#libQt5Concurrent-devel
|
||||
#libQt5Network-devel
|
||||
#libQt5Sql-devel
|
||||
#libQt5DBus-devel
|
||||
#libQt5Test-devel
|
||||
#libqt5-qtx11extras-devel
|
||||
#libqt5-qtbase-common-devel
|
||||
#libQt5Sql5-sqlite
|
||||
#libqt5-linguist-devel
|
||||
#libcdio-devel
|
||||
#libgpod-devel
|
||||
#libmtp-devel
|
||||
#libchromaprint-devel
|
||||
#desktop-file-utils
|
||||
#update-desktop-files
|
||||
#appstream-glib
|
||||
#hicolor-icon-theme
|
||||
#- name: Create Build Environment
|
||||
#shell: bash
|
||||
#run: cmake -E make_directory build
|
||||
#- name: Configure CMake
|
||||
#shell: bash
|
||||
#working-directory: build
|
||||
#run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON -DBUILD_WITH_QT5=ON
|
||||
#- name: Create source tarball
|
||||
#working-directory: build
|
||||
#run: ../dist/scripts/maketarball.sh
|
||||
#- name: Create RPM build sources directories
|
||||
#run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
#- name: Copy source tarball
|
||||
#working-directory: build
|
||||
#run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
#- name: Build RPM
|
||||
#working-directory: build
|
||||
#run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
build_opensuse_lp153_qt5:
|
||||
name: Build openSUSE Leap 15.3 Qt 5
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: opensuse/leap:15.3
|
||||
steps:
|
||||
- uses: actions/checkout@v1.2.0
|
||||
- name: Update packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
- name: Install openSUSE dependencies
|
||||
run: >
|
||||
zypper --non-interactive --gpg-auto-import-keys install
|
||||
lsb-release
|
||||
rpm-build
|
||||
git
|
||||
tar
|
||||
make
|
||||
cmake
|
||||
gcc
|
||||
gcc-c++
|
||||
gettext-tools
|
||||
glibc-devel
|
||||
libboost_headers-devel
|
||||
boost-devel
|
||||
glib2-devel
|
||||
glib2-tools
|
||||
dbus-1-devel
|
||||
alsa-devel
|
||||
libnotify-devel
|
||||
libgnutls-devel
|
||||
protobuf-devel
|
||||
sqlite3-devel
|
||||
libpulse-devel
|
||||
gstreamer-devel
|
||||
gstreamer-plugins-base-devel
|
||||
vlc-devel
|
||||
taglib-devel
|
||||
libQt5Core-devel
|
||||
libQt5Gui-devel
|
||||
libQt5Widgets-devel
|
||||
libQt5Concurrent-devel
|
||||
libQt5Network-devel
|
||||
libQt5Sql-devel
|
||||
libQt5DBus-devel
|
||||
libQt5Test-devel
|
||||
libqt5-qtx11extras-devel
|
||||
libqt5-qtbase-common-devel
|
||||
libQt5Sql5-sqlite
|
||||
libqt5-linguist-devel
|
||||
libcdio-devel
|
||||
libgpod-devel
|
||||
libmtp-devel
|
||||
libchromaprint-devel
|
||||
desktop-file-utils
|
||||
update-desktop-files
|
||||
appstream-glib
|
||||
hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON -DBUILD_WITH_QT5=ON
|
||||
- name: Create source tarball
|
||||
working-directory: build
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
- name: Create RPM build sources directories
|
||||
run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
- name: Copy source tarball
|
||||
working-directory: build
|
||||
run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
- name: Build RPM
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
#build_opensuse_tumbleweed_qt6:
|
||||
#name: Build openSUSE Tumbleweed Qt 6
|
||||
#runs-on: ubuntu-latest
|
||||
#container:
|
||||
#image: opensuse/tumbleweed
|
||||
#steps:
|
||||
#- uses: actions/checkout@v1.2.0
|
||||
#- name: Lock packages
|
||||
#run: zypper --non-interactive --gpg-auto-import-keys addlock openssh-server
|
||||
#- name: Update packages
|
||||
#run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
#- name: Upgrade packages
|
||||
#run: zypper --non-interactive --gpg-auto-import-keys dup
|
||||
#- name: Install openSUSE dependencies
|
||||
#run: >
|
||||
#zypper --non-interactive --gpg-auto-import-keys install
|
||||
#lsb-release
|
||||
#rpm-build
|
||||
#git
|
||||
#tar
|
||||
#make
|
||||
#cmake
|
||||
#gcc
|
||||
#gcc-c++
|
||||
#gettext-tools
|
||||
#glibc-devel
|
||||
#libboost_headers-devel
|
||||
#boost-devel
|
||||
#glib2-devel
|
||||
#glib2-tools
|
||||
#dbus-1-devel
|
||||
#alsa-devel
|
||||
#libnotify-devel
|
||||
#libgnutls-devel
|
||||
#protobuf-devel
|
||||
#sqlite3-devel
|
||||
#libpulse-devel
|
||||
#gstreamer-devel
|
||||
#gstreamer-plugins-base-devel
|
||||
#vlc-devel
|
||||
#taglib-devel
|
||||
#qt6-core-devel
|
||||
#qt6-gui-devel
|
||||
#qt6-widgets-devel
|
||||
#qt6-concurrent-devel
|
||||
#qt6-network-devel
|
||||
#qt6-sql-devel
|
||||
#qt6-dbus-devel
|
||||
#qt6-test-devel
|
||||
#qt6-base-common-devel
|
||||
#qt6-sql-sqlite
|
||||
#qt6-linguist-devel
|
||||
#libcdio-devel
|
||||
#libgpod-devel
|
||||
#libmtp-devel
|
||||
#libchromaprint-devel
|
||||
#desktop-file-utils
|
||||
#update-desktop-files
|
||||
#appstream-glib
|
||||
#hicolor-icon-theme
|
||||
#- name: Create Build Environment
|
||||
#shell: bash
|
||||
#run: cmake -E make_directory build
|
||||
#- name: Configure CMake
|
||||
#shell: bash
|
||||
#working-directory: build
|
||||
#run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON -DBUILD_WITH_QT6=ON
|
||||
#- name: Create source tarball
|
||||
#working-directory: build
|
||||
#run: ../dist/scripts/maketarball.sh
|
||||
#- name: Create RPM build sources directories
|
||||
#run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
#- name: Copy source tarball
|
||||
#working-directory: build
|
||||
#run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
#- name: Build RPM
|
||||
#working-directory: build
|
||||
#run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
build_opensuse_lp153_qt6:
|
||||
name: Build openSUSE Leap 15.3 Qt 6
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: opensuse/leap:15.3
|
||||
steps:
|
||||
- uses: actions/checkout@v1.2.0
|
||||
- name: Add Qt 6 repo
|
||||
run: zypper -n ar -c -f -n 'repo-qt6' https://download.opensuse.org/repositories/home:/jonaski:/qt6/openSUSE_Leap_15.3/ repo-qt6
|
||||
- name: Update packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
- name: Install openSUSE dependencies
|
||||
run: >
|
||||
zypper --non-interactive --gpg-auto-import-keys install
|
||||
lsb-release
|
||||
rpm-build
|
||||
git
|
||||
tar
|
||||
make
|
||||
cmake
|
||||
gcc
|
||||
gcc-c++
|
||||
gettext-tools
|
||||
glibc-devel
|
||||
libboost_headers-devel
|
||||
boost-devel
|
||||
glib2-devel
|
||||
glib2-tools
|
||||
dbus-1-devel
|
||||
alsa-devel
|
||||
libnotify-devel
|
||||
libgnutls-devel
|
||||
protobuf-devel
|
||||
sqlite3-devel
|
||||
libpulse-devel
|
||||
gstreamer-devel
|
||||
gstreamer-plugins-base-devel
|
||||
vlc-devel
|
||||
taglib-devel
|
||||
qt6-core-devel
|
||||
qt6-gui-devel
|
||||
qt6-widgets-devel
|
||||
qt6-concurrent-devel
|
||||
qt6-network-devel
|
||||
qt6-sql-devel
|
||||
qt6-dbus-devel
|
||||
qt6-test-devel
|
||||
qt6-base-common-devel
|
||||
qt6-sql-sqlite
|
||||
qt6-linguist-devel
|
||||
libcdio-devel
|
||||
libgpod-devel
|
||||
libmtp-devel
|
||||
libchromaprint-devel
|
||||
desktop-file-utils
|
||||
update-desktop-files
|
||||
appstream-glib
|
||||
hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON -DBUILD_WITH_QT6=ON
|
||||
- name: Create source tarball
|
||||
working-directory: build
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
- name: Create RPM build sources directories
|
||||
run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
- name: Copy source tarball
|
||||
working-directory: build
|
||||
run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
- name: Build RPM
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_opensuse_tumbleweed_qt5:
|
||||
name: Build openSUSE Tumbleweed Qt 5
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: opensuse/tumbleweed
|
||||
steps:
|
||||
- uses: actions/checkout@v1.2.0
|
||||
- name: Update packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
- name: Upgrade packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys dup
|
||||
- name: Install openSUSE dependencies
|
||||
run: >
|
||||
zypper --non-interactive --gpg-auto-import-keys install
|
||||
lsb-release
|
||||
rpm-build
|
||||
git
|
||||
tar
|
||||
make
|
||||
cmake
|
||||
gcc
|
||||
gcc-c++
|
||||
gettext-tools
|
||||
glibc-devel
|
||||
libboost_headers-devel
|
||||
boost-devel
|
||||
glib2-devel
|
||||
glib2-tools
|
||||
dbus-1-devel
|
||||
alsa-devel
|
||||
libnotify-devel
|
||||
libgnutls-devel
|
||||
protobuf-devel
|
||||
sqlite3-devel
|
||||
libpulse-devel
|
||||
gstreamer-devel
|
||||
gstreamer-plugins-base-devel
|
||||
vlc-devel
|
||||
taglib-devel
|
||||
libQt5Core-devel
|
||||
libQt5Gui-devel
|
||||
libQt5Widgets-devel
|
||||
libQt5Concurrent-devel
|
||||
libQt5Network-devel
|
||||
libQt5Sql-devel
|
||||
libQt5DBus-devel
|
||||
libQt5Test-devel
|
||||
libqt5-qtx11extras-devel
|
||||
libqt5-qtbase-common-devel
|
||||
libQt5Sql5-sqlite
|
||||
libqt5-linguist-devel
|
||||
libcdio-devel
|
||||
libgpod-devel
|
||||
libmtp-devel
|
||||
libchromaprint-devel
|
||||
desktop-file-utils
|
||||
update-desktop-files
|
||||
appstream-glib
|
||||
hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON -DBUILD_WITH_QT5=ON
|
||||
- name: Create source tarball
|
||||
working-directory: build
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
- name: Create RPM build sources directories
|
||||
run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
- name: Copy source tarball
|
||||
working-directory: build
|
||||
run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
- name: Build RPM
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_opensuse_tumbleweed_qt6:
|
||||
name: Build openSUSE Tumbleweed Qt 6
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: opensuse/tumbleweed
|
||||
steps:
|
||||
- uses: actions/checkout@v1.2.0
|
||||
- name: Update packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
- name: Upgrade packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys dup
|
||||
- name: Install openSUSE dependencies
|
||||
run: >
|
||||
zypper --non-interactive --gpg-auto-import-keys install
|
||||
lsb-release
|
||||
rpm-build
|
||||
git
|
||||
tar
|
||||
make
|
||||
cmake
|
||||
gcc
|
||||
gcc-c++
|
||||
gettext-tools
|
||||
glibc-devel
|
||||
libboost_headers-devel
|
||||
boost-devel
|
||||
glib2-devel
|
||||
glib2-tools
|
||||
dbus-1-devel
|
||||
alsa-devel
|
||||
libnotify-devel
|
||||
libgnutls-devel
|
||||
protobuf-devel
|
||||
sqlite3-devel
|
||||
libpulse-devel
|
||||
gstreamer-devel
|
||||
gstreamer-plugins-base-devel
|
||||
vlc-devel
|
||||
taglib-devel
|
||||
qt6-core-devel
|
||||
qt6-gui-devel
|
||||
qt6-widgets-devel
|
||||
qt6-concurrent-devel
|
||||
qt6-network-devel
|
||||
qt6-sql-devel
|
||||
qt6-dbus-devel
|
||||
qt6-test-devel
|
||||
qt6-base-common-devel
|
||||
qt6-sql-sqlite
|
||||
qt6-linguist-devel
|
||||
libcdio-devel
|
||||
libgpod-devel
|
||||
libmtp-devel
|
||||
libchromaprint-devel
|
||||
desktop-file-utils
|
||||
update-desktop-files
|
||||
appstream-glib
|
||||
hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON -DBUILD_WITH_QT6=ON
|
||||
- name: Create source tarball
|
||||
working-directory: build
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
- name: Create RPM build sources directories
|
||||
run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
- name: Copy source tarball
|
||||
working-directory: build
|
||||
run: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||
- name: Build RPM
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_fedora_32:
|
||||
@@ -618,6 +694,83 @@ jobs:
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_fedora_34:
|
||||
name: Build Fedora 34
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: fedora:34
|
||||
env:
|
||||
RPM_BUILD_NCPUS: "2"
|
||||
steps:
|
||||
- uses: actions/checkout@v1.2.0
|
||||
|
||||
- name: Update packages
|
||||
run: yum update --assumeyes
|
||||
|
||||
- name: Upgrade packages
|
||||
run: yum upgrade --assumeyes
|
||||
|
||||
- name: Install Fedora dependencies
|
||||
run: >
|
||||
dnf install --assumeyes
|
||||
@development-tools
|
||||
redhat-lsb-core
|
||||
git
|
||||
glibc
|
||||
gcc-c++
|
||||
rpmdevtools
|
||||
make
|
||||
cmake
|
||||
pkgconfig
|
||||
glib
|
||||
man
|
||||
tar
|
||||
gettext
|
||||
openssh
|
||||
boost-devel
|
||||
dbus-devel
|
||||
protobuf-devel
|
||||
protobuf-compiler
|
||||
sqlite-devel
|
||||
alsa-lib-devel
|
||||
pulseaudio-libs-devel
|
||||
libnotify-devel
|
||||
gnutls-devel
|
||||
qt5-qtbase-devel
|
||||
qt5-qtx11extras-devel
|
||||
qt5-qttools-devel
|
||||
gstreamer1-devel
|
||||
gstreamer1-plugins-base-devel
|
||||
taglib-devel
|
||||
libcdio-devel
|
||||
libgpod-devel
|
||||
libmtp-devel
|
||||
libchromaprint-devel
|
||||
fftw-devel
|
||||
desktop-file-utils
|
||||
libappstream-glib
|
||||
hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
run: cmake -E make_directory build
|
||||
- name: Configure CMake
|
||||
shell: bash
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WERROR=ON
|
||||
- name: Create source tarball
|
||||
working-directory: build
|
||||
run: ../dist/scripts/maketarball.sh
|
||||
- name: Create RPM build sources directories
|
||||
working-directory: build
|
||||
run: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||
- name: Copy source tarball
|
||||
working-directory: build
|
||||
run: cp strawberry-*.tar.xz ~/rpmbuild/SOURCES/
|
||||
- name: Build RPM
|
||||
working-directory: build
|
||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
|
||||
|
||||
build_centos_8:
|
||||
name: Build CentOS 8
|
||||
runs-on: ubuntu-latest
|
||||
@@ -1055,8 +1208,7 @@ jobs:
|
||||
- name: Link Sparkle
|
||||
shell: bash
|
||||
run: |
|
||||
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework
|
||||
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework.dSYM /Library/Frameworks/Sparkle.framework.dSYM
|
||||
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1) /usr/local/opt/sparkle
|
||||
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
@@ -1068,7 +1220,8 @@ jobs:
|
||||
PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
|
||||
Qt6_DIR: /usr/local/opt/qt6/lib/cmake
|
||||
Qt5LinguistTools_DIR: /usr/local/opt/qt6/lib/cmake/Qt6LinguistTools
|
||||
GST_SCANNER_PATH: /usr/local/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner
|
||||
GIO_EXTRA_MODULES: /usr/local/lib/gio/modules
|
||||
GST_PLUGIN_SCANNER: /usr/local/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner
|
||||
GST_PLUGIN_PATH: /usr/local/lib/gstreamer-1.0
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WITH_QT6=ON -DBUILD_WERROR=ON -DUSE_BUNDLE=ON -DCMAKE_PREFIX_PATH=/usr/local/opt/qt6/lib/cmake
|
||||
@@ -1082,9 +1235,6 @@ jobs:
|
||||
working-directory: build
|
||||
shell: bash
|
||||
run: make install
|
||||
- name: Hack to make macdeployqt find plugins
|
||||
shell: bash
|
||||
run: sudo ln -s /usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt/ | tail -n1)/share/qt/plugins /usr/local/plugins
|
||||
- name: Create DMG
|
||||
working-directory: build
|
||||
shell: bash
|
||||
@@ -1131,8 +1281,7 @@ jobs:
|
||||
- name: Link Sparkle
|
||||
shell: bash
|
||||
run: |
|
||||
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework
|
||||
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework.dSYM /Library/Frameworks/Sparkle.framework.dSYM
|
||||
sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1) /usr/local/opt/sparkle
|
||||
|
||||
- name: Create Build Environment
|
||||
shell: bash
|
||||
@@ -1144,7 +1293,8 @@ jobs:
|
||||
PKG_CONFIG_PATH: /usr/local/lib/pkgconfig
|
||||
Qt5_DIR: /usr/local/opt/qt6/lib/cmake
|
||||
Qt5LinguistTools_DIR: /usr/local/opt/qt6/lib/cmake/Qt6LinguistTools
|
||||
GST_SCANNER_PATH: /usr/local/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner
|
||||
GIO_EXTRA_MODULES: /usr/local/lib/gio/modules
|
||||
GST_PLUGIN_SCANNER: /usr/local/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner
|
||||
GST_PLUGIN_PATH: /usr/local/lib/gstreamer-1.0
|
||||
working-directory: build
|
||||
run: cmake .. -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_WITH_QT6=ON -DBUILD_WERROR=ON -DUSE_BUNDLE=ON -DCMAKE_PREFIX_PATH=/usr/local/opt/qt6/lib/cmake
|
||||
@@ -1158,9 +1308,6 @@ jobs:
|
||||
working-directory: build
|
||||
shell: bash
|
||||
run: make install
|
||||
- name: Hack to make macdeployqt find plugins
|
||||
shell: bash
|
||||
run: sudo ln -s /usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt/ | tail -n1)/share/qt/plugins /usr/local/plugins
|
||||
- name: Create DMG
|
||||
working-directory: build
|
||||
shell: bash
|
||||
|
||||
@@ -19,8 +19,7 @@ before_install:
|
||||
- brew install libcdio libmtp
|
||||
- brew install create-dmg
|
||||
- brew install --cask sparkle
|
||||
- sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework /Library/Frameworks/Sparkle.framework
|
||||
- sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1)/Sparkle.framework.dSYM /Library/Frameworks/Sparkle.framework.dSYM
|
||||
- sudo ln -s /usr/local/Caskroom/sparkle/$(ls /usr/local/Caskroom/sparkle | head -n1) /usr/local/opt/sparkle
|
||||
- export Qt6_DIR=/usr/local/opt/qt6/lib/cmake
|
||||
- export Qt6LinguistTools_DIR=/usr/local/opt/qt6/lib/cmake/Qt6LinguistTools
|
||||
- ls /usr/local/lib/gstreamer-1.0
|
||||
@@ -31,7 +30,6 @@ before_script:
|
||||
script:
|
||||
- make -j8
|
||||
- make install
|
||||
- sudo ln -s /usr/local/Cellar/qt/$(ls /usr/local/Cellar/qt/ | tail -n1)/share/qt/plugins /usr/local/plugins
|
||||
- make dmg2
|
||||
after_success:
|
||||
- ls -lh strawberry*.dmg
|
||||
|
||||
10
3rdparty/README.md
vendored
10
3rdparty/README.md
vendored
@@ -14,6 +14,12 @@ URL: https://github.com/itay-grudev/SingleApplication
|
||||
|
||||
SPMediaKeyTap
|
||||
-------------
|
||||
Used on macOS to exclusively enable strawberry to grab global media shortcuts.
|
||||
Can safely be deleted on other platforms.
|
||||
|
||||
This is used for macOS only to enable strawberry to grab global shortcuts and can safely be deleted on other
|
||||
platforms.
|
||||
|
||||
macdeployqt
|
||||
-----------
|
||||
A modified version of Qt's official macdeployqt utility that fixes some issues,
|
||||
this version also deploys gstreamer plugins.
|
||||
Can safely be deleted on other platforms.
|
||||
|
||||
7
3rdparty/macdeployqt/CMakeLists.txt
vendored
Normal file
7
3rdparty/macdeployqt/CMakeLists.txt
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
add_executable(macdeployqt main.cpp shared.cpp)
|
||||
target_link_libraries(macdeployqt PRIVATE
|
||||
"-framework AppKit"
|
||||
${QtCore_LIBRARIES}
|
||||
)
|
||||
|
||||
#execute_process(COMMAND cp ${CMAKE_CURRENT_BINARY_DIR}/macdeployqt ${CMAKE_BINARY_DIR})
|
||||
294
3rdparty/macdeployqt/main.cpp
vendored
Normal file
294
3rdparty/macdeployqt/main.cpp
vendored
Normal file
@@ -0,0 +1,294 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#undef QT_NO_DEBUG_OUTPUT
|
||||
#undef QT_NO_WARNING_OUTPUT
|
||||
#undef QT_NO_INFO_OUTPUT
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QDir>
|
||||
#include <QLibraryInfo>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
QString appBundlePath;
|
||||
if (argc > 1)
|
||||
appBundlePath = QString::fromLocal8Bit(argv[1]);
|
||||
|
||||
if (argc < 2 || appBundlePath.startsWith("-")) {
|
||||
qDebug() << "Usage: macdeployqt app-bundle [options]";
|
||||
qDebug() << "";
|
||||
qDebug() << "Options:";
|
||||
qDebug() << " -verbose=<0-3> : 0 = no output, 1 = error/warning (default), 2 = normal, 3 = debug";
|
||||
qDebug() << " -no-plugins : Skip plugin deployment";
|
||||
qDebug() << " -dmg : Create a .dmg disk image";
|
||||
qDebug() << " -no-strip : Don't run 'strip' on the binaries";
|
||||
qDebug() << " -use-debug-libs : Deploy with debug versions of frameworks and plugins (implies -no-strip)";
|
||||
qDebug() << " -executable=<path> : Let the given executable use the deployed frameworks too";
|
||||
qDebug() << " -qmldir=<path> : Scan for QML imports in the given path";
|
||||
qDebug() << " -qmlimport=<path> : Add the given path to the QML module search locations";
|
||||
qDebug() << " -always-overwrite : Copy files even if the target file exists";
|
||||
qDebug() << " -codesign=<ident> : Run codesign with the given identity on all executables";
|
||||
qDebug() << " -hardened-runtime : Enable Hardened Runtime when code signing";
|
||||
qDebug() << " -timestamp : Include a secure timestamp when code signing (requires internet connection)";
|
||||
qDebug() << " -sign-for-notarization=<ident>: Activate the necessary options for notarization (requires internet connection)";
|
||||
qDebug() << " -appstore-compliant : Skip deployment of components that use private API";
|
||||
qDebug() << " -libpath=<path> : Add the given path to the library search path";
|
||||
qDebug() << " -fs=<filesystem> : Set the filesystem used for the .dmg disk image (defaults to HFS+)";
|
||||
qDebug() << " -plugins-dir=<path> : Set plugins directory";
|
||||
qDebug() << "";
|
||||
qDebug() << "macdeployqt takes an application bundle as input and makes it";
|
||||
qDebug() << "self-contained by copying in the Qt frameworks and plugins that";
|
||||
qDebug() << "the application uses.";
|
||||
qDebug() << "";
|
||||
qDebug() << "Plugins related to a framework are copied in with the";
|
||||
qDebug() << "framework. The accessibility, image formats, and text codec";
|
||||
qDebug() << "plugins are always copied, unless \"-no-plugins\" is specified.";
|
||||
qDebug() << "";
|
||||
qDebug() << "Qt plugins may use private API and will cause the app to be";
|
||||
qDebug() << "rejected from the Mac App store. MacDeployQt will print a warning";
|
||||
qDebug() << "when known incompatible plugins are deployed. Use -appstore-compliant ";
|
||||
qDebug() << "to skip these plugins. Currently two SQL plugins are known to";
|
||||
qDebug() << "be incompatible: qsqlodbc and qsqlpsql.";
|
||||
qDebug() << "";
|
||||
qDebug() << "See the \"Deploying Applications on OS X\" topic in the";
|
||||
qDebug() << "documentation for more information about deployment on OS X.";
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
appBundlePath = QDir::cleanPath(appBundlePath);
|
||||
|
||||
if (QDir().exists(appBundlePath) == false) {
|
||||
qDebug() << "Error: Could not find app bundle" << appBundlePath;
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool plugins = true;
|
||||
bool dmg = false;
|
||||
QByteArray filesystem("HFS+");
|
||||
bool useDebugLibs = false;
|
||||
extern bool runStripEnabled;
|
||||
extern bool alwaysOwerwriteEnabled;
|
||||
extern QStringList librarySearchPath;
|
||||
QStringList additionalExecutables;
|
||||
bool qmldirArgumentUsed = false;
|
||||
QStringList qmlDirs;
|
||||
QStringList qmlImportPaths;
|
||||
extern bool runCodesign;
|
||||
extern QString codesignIdentiy;
|
||||
extern bool hardenedRuntime;
|
||||
extern bool appstoreCompliant;
|
||||
extern bool deployFramework;
|
||||
extern bool secureTimestamp;
|
||||
QString plugin_dir;
|
||||
|
||||
for (int i = 2; i < argc; ++i) {
|
||||
QByteArray argument = QByteArray(argv[i]);
|
||||
if (argument == QByteArray("-no-plugins")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
plugins = false;
|
||||
} else if (argument == QByteArray("-dmg")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
dmg = true;
|
||||
} else if (argument == QByteArray("-no-strip")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
runStripEnabled = false;
|
||||
} else if (argument == QByteArray("-use-debug-libs")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
useDebugLibs = true;
|
||||
runStripEnabled = false;
|
||||
} else if (argument.startsWith(QByteArray("-verbose"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf("=");
|
||||
bool ok = false;
|
||||
int number = argument.mid(index+1).toInt(&ok);
|
||||
if (!ok)
|
||||
LogError() << "Could not parse verbose level";
|
||||
else
|
||||
logLevel = number;
|
||||
} else if (argument.startsWith(QByteArray("-executable"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf('=');
|
||||
if (index == -1)
|
||||
LogError() << "Missing executable path";
|
||||
else
|
||||
additionalExecutables << argument.mid(index+1);
|
||||
} else if (argument.startsWith(QByteArray("-qmldir"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
qmldirArgumentUsed = true;
|
||||
int index = argument.indexOf('=');
|
||||
if (index == -1)
|
||||
LogError() << "Missing qml directory path";
|
||||
else
|
||||
qmlDirs << argument.mid(index+1);
|
||||
} else if (argument.startsWith(QByteArray("-qmlimport"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf('=');
|
||||
if (index == -1)
|
||||
LogError() << "Missing qml import path";
|
||||
else
|
||||
qmlImportPaths << argument.mid(index+1);
|
||||
} else if (argument.startsWith(QByteArray("-libpath"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf('=');
|
||||
if (index == -1)
|
||||
LogError() << "Missing library search path";
|
||||
else
|
||||
librarySearchPath << argument.mid(index+1);
|
||||
} else if (argument == QByteArray("-always-overwrite")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
alwaysOwerwriteEnabled = true;
|
||||
} else if (argument.startsWith(QByteArray("-codesign"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf("=");
|
||||
if (index < 0 || index >= argument.size()) {
|
||||
LogError() << "Missing code signing identity";
|
||||
} else {
|
||||
runCodesign = true;
|
||||
codesignIdentiy = argument.mid(index+1);
|
||||
}
|
||||
} else if (argument.startsWith(QByteArray("-sign-for-notarization"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf("=");
|
||||
if (index < 0 || index >= argument.size()) {
|
||||
LogError() << "Missing code signing identity";
|
||||
} else {
|
||||
runCodesign = true;
|
||||
hardenedRuntime = true;
|
||||
secureTimestamp = true;
|
||||
codesignIdentiy = argument.mid(index+1);
|
||||
}
|
||||
} else if (argument.startsWith(QByteArray("-hardened-runtime"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
hardenedRuntime = true;
|
||||
} else if (argument.startsWith(QByteArray("-timestamp"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
secureTimestamp = true;
|
||||
} else if (argument == QByteArray("-appstore-compliant")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
appstoreCompliant = true;
|
||||
|
||||
// Undocumented option, may not work as intented
|
||||
} else if (argument == QByteArray("-deploy-framework")) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
deployFramework = true;
|
||||
|
||||
} else if (argument.startsWith(QByteArray("-fs"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf('=');
|
||||
if (index == -1)
|
||||
LogError() << "Missing filesystem type";
|
||||
else
|
||||
filesystem = argument.mid(index+1);
|
||||
} else if (argument.startsWith(QByteArray("-plugins-dir"))) {
|
||||
LogDebug() << "Argument found:" << argument;
|
||||
int index = argument.indexOf('=');
|
||||
if (index == -1)
|
||||
LogError() << "Missing filesystem type";
|
||||
else
|
||||
plugin_dir = argument.mid(index+1);
|
||||
} else if (argument.startsWith("-")) {
|
||||
LogError() << "Unknown argument" << argument << "\n";
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
DeploymentInfo deploymentInfo = deployQtFrameworks(appBundlePath, additionalExecutables, useDebugLibs);
|
||||
|
||||
if (deploymentInfo.isDebug)
|
||||
useDebugLibs = true;
|
||||
|
||||
if (deployFramework && deploymentInfo.isFramework)
|
||||
fixupFramework(appBundlePath);
|
||||
|
||||
// Convenience: Look for .qml files in the current directoty if no -qmldir specified.
|
||||
if (qmlDirs.isEmpty()) {
|
||||
QDir dir;
|
||||
if (!dir.entryList(QStringList() << QStringLiteral("*.qml")).isEmpty()) {
|
||||
qmlDirs += QStringLiteral(".");
|
||||
}
|
||||
}
|
||||
|
||||
if (!qmlDirs.isEmpty()) {
|
||||
bool ok = deployQmlImports(appBundlePath, deploymentInfo, qmlDirs, qmlImportPaths);
|
||||
if (!ok && qmldirArgumentUsed)
|
||||
return 1; // exit if the user explicitly asked for qml import deployment
|
||||
|
||||
// Update deploymentInfo.deployedFrameworks - the QML imports
|
||||
// may have brought in extra frameworks as dependencies.
|
||||
deploymentInfo.deployedFrameworks += findAppFrameworkNames(appBundlePath);
|
||||
deploymentInfo.deployedFrameworks =
|
||||
QSet<QString>(deploymentInfo.deployedFrameworks.begin(),
|
||||
deploymentInfo.deployedFrameworks.end()).values();
|
||||
}
|
||||
|
||||
if (plugins) {
|
||||
if (plugin_dir.isEmpty()) {
|
||||
deploymentInfo.pluginPath = QLibraryInfo::path(QLibraryInfo::PluginsPath);
|
||||
}
|
||||
else {
|
||||
deploymentInfo.pluginPath = plugin_dir;
|
||||
}
|
||||
if (deploymentInfo.pluginPath.isEmpty()) {
|
||||
LogError() << "Missing Qt plugins path\n";
|
||||
return 1;
|
||||
}
|
||||
if (!QDir(deploymentInfo.pluginPath).exists()) {
|
||||
LogError() << "Plugins path does not exist\n" << deploymentInfo.pluginPath;
|
||||
return 1;
|
||||
}
|
||||
Q_ASSERT(!deploymentInfo.pluginPath.isEmpty());
|
||||
if (!deploymentInfo.pluginPath.isEmpty()) {
|
||||
LogNormal();
|
||||
deployPlugins(appBundlePath, deploymentInfo, useDebugLibs);
|
||||
createQtConf(appBundlePath);
|
||||
}
|
||||
}
|
||||
|
||||
if (runStripEnabled)
|
||||
stripAppBinary(appBundlePath);
|
||||
|
||||
if (!FinalCheck(appBundlePath)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (runCodesign)
|
||||
codesign(codesignIdentiy, appBundlePath);
|
||||
|
||||
if (dmg) {
|
||||
LogNormal();
|
||||
createDiskImage(appBundlePath, filesystem);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
1806
3rdparty/macdeployqt/shared.cpp
vendored
Normal file
1806
3rdparty/macdeployqt/shared.cpp
vendored
Normal file
File diff suppressed because it is too large
Load Diff
141
3rdparty/macdeployqt/shared.h
vendored
Normal file
141
3rdparty/macdeployqt/shared.h
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of the tools applications of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef MAC_DEPLOMYMENT_SHARED_H
|
||||
#define MAC_DEPLOMYMENT_SHARED_H
|
||||
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QDebug>
|
||||
#include <QSet>
|
||||
#include <QVersionNumber>
|
||||
|
||||
extern int logLevel;
|
||||
#define LogError() if (logLevel < 0) {} else qDebug() << "ERROR:"
|
||||
#define LogWarning() if (logLevel < 1) {} else qDebug() << "WARNING:"
|
||||
#define LogNormal() if (logLevel < 2) {} else qDebug() << "Log:"
|
||||
#define LogDebug() if (logLevel < 3) {} else qDebug() << "Log:"
|
||||
|
||||
extern bool runStripEnabled;
|
||||
|
||||
class FrameworkInfo
|
||||
{
|
||||
public:
|
||||
bool isDylib;
|
||||
QString frameworkDirectory;
|
||||
QString frameworkName;
|
||||
QString frameworkPath;
|
||||
QString binaryDirectory;
|
||||
QString binaryName;
|
||||
QString binaryPath;
|
||||
QString rpathUsed;
|
||||
QString version;
|
||||
QString installName;
|
||||
QString deployedInstallName;
|
||||
QString sourceFilePath;
|
||||
QString frameworkDestinationDirectory;
|
||||
QString binaryDestinationDirectory;
|
||||
|
||||
bool isDebugLibrary() const
|
||||
{
|
||||
return binaryName.contains(QLatin1String("_debug"));
|
||||
}
|
||||
};
|
||||
|
||||
class DylibInfo
|
||||
{
|
||||
public:
|
||||
QString binaryPath;
|
||||
QVersionNumber currentVersion;
|
||||
QVersionNumber compatibilityVersion;
|
||||
};
|
||||
|
||||
class OtoolInfo
|
||||
{
|
||||
public:
|
||||
QString installName;
|
||||
QString binaryPath;
|
||||
QVersionNumber currentVersion;
|
||||
QVersionNumber compatibilityVersion;
|
||||
QList<DylibInfo> dependencies;
|
||||
};
|
||||
|
||||
bool operator==(const FrameworkInfo &a, const FrameworkInfo &b);
|
||||
QDebug operator<<(QDebug debug, const FrameworkInfo &info);
|
||||
|
||||
class ApplicationBundleInfo
|
||||
{
|
||||
public:
|
||||
QString path;
|
||||
QString binaryPath;
|
||||
QStringList libraryPaths;
|
||||
};
|
||||
|
||||
class DeploymentInfo
|
||||
{
|
||||
public:
|
||||
QString qtPath;
|
||||
QString pluginPath;
|
||||
QStringList deployedFrameworks;
|
||||
QSet<QString> rpathsUsed;
|
||||
bool useLoaderPath;
|
||||
bool isFramework;
|
||||
bool isDebug;
|
||||
|
||||
bool containsModule(const QString &module, const QString &libInFix) const;
|
||||
};
|
||||
|
||||
inline QDebug operator<<(QDebug debug, const ApplicationBundleInfo &info);
|
||||
|
||||
OtoolInfo findDependencyInfo(const QString &binaryPath);
|
||||
FrameworkInfo parseOtoolLibraryLine(const QString &line, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs);
|
||||
QString findAppBinary(const QString &appBundlePath);
|
||||
QList<FrameworkInfo> getQtFrameworks(const QString &path, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs);
|
||||
QList<FrameworkInfo> getQtFrameworks(const QStringList &otoolLines, const QString &appBundlePath, const QSet<QString> &rpaths, bool useDebugLibs);
|
||||
QString copyFramework(const FrameworkInfo &framework, const QString path);
|
||||
DeploymentInfo deployQtFrameworks(const QString &appBundlePath, const QStringList &additionalExecutables, bool useDebugLibs);
|
||||
DeploymentInfo deployQtFrameworks(QList<FrameworkInfo> frameworks,const QString &bundlePath, const QStringList &binaryPaths, bool useDebugLibs, bool useLoaderPath);
|
||||
void createQtConf(const QString &appBundlePath);
|
||||
void deployPlugins(const QString &appBundlePath, DeploymentInfo deploymentInfo, bool useDebugLibs);
|
||||
bool deployQmlImports(const QString &appBundlePath, DeploymentInfo deploymentInfo, QStringList &qmlDirs, QStringList &qmlImportPaths);
|
||||
void changeIdentification(const QString &id, const QString &binaryPath);
|
||||
void changeInstallName(const QString &oldName, const QString &newName, const QString &binaryPath);
|
||||
void runStrip(const QString &binaryPath);
|
||||
void stripAppBinary(const QString &bundlePath);
|
||||
QString findAppBinary(const QString &appBundlePath);
|
||||
QStringList findAppFrameworkNames(const QString &appBundlePath);
|
||||
QStringList findAppFrameworkPaths(const QString &appBundlePath);
|
||||
void codesignFile(const QString &identity, const QString &filePath);
|
||||
QSet<QString> codesignBundle(const QString &identity,
|
||||
const QString &appBundlePath,
|
||||
QList<QString> additionalBinariesContainingRpaths);
|
||||
void codesign(const QString &identity, const QString &appBundlePath);
|
||||
void createDiskImage(const QString &appBundlePath, const QString &filesystemType);
|
||||
void fixupFramework(const QString &appBundlePath);
|
||||
bool FinalCheck(const QString &appBundlePath);
|
||||
|
||||
#endif
|
||||
@@ -220,7 +220,7 @@ void SingleApplicationPrivate::startSecondary() {
|
||||
|
||||
}
|
||||
|
||||
bool SingleApplicationPrivate::connectToPrimary(int timeout, ConnectionType connectionType) {
|
||||
bool SingleApplicationPrivate::connectToPrimary(const int timeout, const ConnectionType connectionType) {
|
||||
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
@@ -241,7 +241,7 @@ bool SingleApplicationPrivate::connectToPrimary(int timeout, ConnectionType conn
|
||||
socket_->connectToServer(blockServerName_);
|
||||
|
||||
if (socket_->state() == QLocalSocket::ConnectingState) {
|
||||
socket_->waitForConnected(timeout - time.elapsed());
|
||||
socket_->waitForConnected(static_cast<int>(timeout - time.elapsed()));
|
||||
}
|
||||
|
||||
// If connected break out of the loop
|
||||
@@ -277,7 +277,7 @@ bool SingleApplicationPrivate::connectToPrimary(int timeout, ConnectionType conn
|
||||
|
||||
socket_->write(header);
|
||||
socket_->write(initMsg);
|
||||
bool result = socket_->waitForBytesWritten(timeout - time.elapsed());
|
||||
bool result = socket_->waitForBytesWritten(static_cast<int>(timeout - time.elapsed()));
|
||||
socket_->flush();
|
||||
|
||||
return result;
|
||||
@@ -326,17 +326,17 @@ void SingleApplicationPrivate::slotConnectionEstablished() {
|
||||
QLocalSocket *nextConnSocket = server_->nextPendingConnection();
|
||||
connectionMap_.insert(nextConnSocket, ConnectionInfo());
|
||||
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, [nextConnSocket, this]() {
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, this, [nextConnSocket, this]() {
|
||||
auto &info = connectionMap_[nextConnSocket];
|
||||
Q_EMIT this->slotClientConnectionClosed(nextConnSocket, info.instanceId);
|
||||
slotClientConnectionClosed(nextConnSocket, info.instanceId);
|
||||
});
|
||||
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected, [nextConnSocket, this]() {
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected, this, [nextConnSocket, this]() {
|
||||
connectionMap_.remove(nextConnSocket);
|
||||
nextConnSocket->deleteLater();
|
||||
});
|
||||
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead, [nextConnSocket, this]() {
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead, this, [nextConnSocket, this]() {
|
||||
auto &info = connectionMap_[nextConnSocket];
|
||||
switch (info.stage) {
|
||||
case StageHeader:
|
||||
@@ -346,7 +346,7 @@ void SingleApplicationPrivate::slotConnectionEstablished() {
|
||||
readInitMessageBody(nextConnSocket);
|
||||
break;
|
||||
case StageConnected:
|
||||
Q_EMIT this->slotDataAvailable(nextConnSocket, info.instanceId);
|
||||
slotDataAvailable(nextConnSocket, info.instanceId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -438,7 +438,7 @@ void SingleApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
|
||||
}
|
||||
|
||||
if (sock->bytesAvailable() > 0) {
|
||||
Q_EMIT this->slotDataAvailable(sock, instanceId);
|
||||
slotDataAvailable(sock, instanceId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -453,7 +453,7 @@ void SingleApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const
|
||||
void SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
|
||||
|
||||
if (closedSocket->bytesAvailable() > 0) {
|
||||
Q_EMIT slotDataAvailable(closedSocket, instanceId);
|
||||
slotDataAvailable(closedSocket, instanceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class SingleApplicationPrivate : public QObject {
|
||||
void initializeMemoryBlock();
|
||||
void startPrimary();
|
||||
void startSecondary();
|
||||
bool connectToPrimary(const int msecs, const ConnectionType connectionType);
|
||||
bool connectToPrimary(const int timeout, const ConnectionType connectionType);
|
||||
quint16 blockChecksum();
|
||||
qint64 primaryPid();
|
||||
QString primaryUser();
|
||||
|
||||
@@ -220,7 +220,7 @@ void SingleCoreApplicationPrivate::startSecondary() {
|
||||
|
||||
}
|
||||
|
||||
bool SingleCoreApplicationPrivate::connectToPrimary(int timeout, ConnectionType connectionType) {
|
||||
bool SingleCoreApplicationPrivate::connectToPrimary(const int timeout, const ConnectionType connectionType) {
|
||||
|
||||
QElapsedTimer time;
|
||||
time.start();
|
||||
@@ -241,7 +241,7 @@ bool SingleCoreApplicationPrivate::connectToPrimary(int timeout, ConnectionType
|
||||
socket_->connectToServer(blockServerName_);
|
||||
|
||||
if (socket_->state() == QLocalSocket::ConnectingState) {
|
||||
socket_->waitForConnected(timeout - time.elapsed());
|
||||
socket_->waitForConnected(static_cast<int>(timeout - time.elapsed()));
|
||||
}
|
||||
|
||||
// If connected break out of the loop
|
||||
@@ -277,7 +277,7 @@ bool SingleCoreApplicationPrivate::connectToPrimary(int timeout, ConnectionType
|
||||
|
||||
socket_->write(header);
|
||||
socket_->write(initMsg);
|
||||
bool result = socket_->waitForBytesWritten(timeout - time.elapsed());
|
||||
bool result = socket_->waitForBytesWritten(timeout - static_cast<int>(time.elapsed()));
|
||||
socket_->flush();
|
||||
|
||||
return result;
|
||||
@@ -326,17 +326,17 @@ void SingleCoreApplicationPrivate::slotConnectionEstablished() {
|
||||
QLocalSocket *nextConnSocket = server_->nextPendingConnection();
|
||||
connectionMap_.insert(nextConnSocket, ConnectionInfo());
|
||||
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, [nextConnSocket, this]() {
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose, this, [nextConnSocket, this]() {
|
||||
auto &info = connectionMap_[nextConnSocket];
|
||||
Q_EMIT this->slotClientConnectionClosed(nextConnSocket, info.instanceId);
|
||||
slotClientConnectionClosed(nextConnSocket, info.instanceId);
|
||||
});
|
||||
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected, [nextConnSocket, this]() {
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected, this, [nextConnSocket, this]() {
|
||||
connectionMap_.remove(nextConnSocket);
|
||||
nextConnSocket->deleteLater();
|
||||
});
|
||||
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead, [nextConnSocket, this]() {
|
||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead, this, [nextConnSocket, this]() {
|
||||
auto &info = connectionMap_[nextConnSocket];
|
||||
switch (info.stage) {
|
||||
case StageHeader:
|
||||
@@ -346,7 +346,7 @@ void SingleCoreApplicationPrivate::slotConnectionEstablished() {
|
||||
readInitMessageBody(nextConnSocket);
|
||||
break;
|
||||
case StageConnected:
|
||||
Q_EMIT this->slotDataAvailable(nextConnSocket, info.instanceId);
|
||||
slotDataAvailable(nextConnSocket, info.instanceId);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -438,7 +438,7 @@ void SingleCoreApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
|
||||
}
|
||||
|
||||
if (sock->bytesAvailable() > 0) {
|
||||
Q_EMIT this->slotDataAvailable(sock, instanceId);
|
||||
slotDataAvailable(sock, instanceId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -453,7 +453,7 @@ void SingleCoreApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, c
|
||||
void SingleCoreApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
|
||||
|
||||
if (closedSocket->bytesAvailable() > 0) {
|
||||
Q_EMIT slotDataAvailable(closedSocket, instanceId);
|
||||
slotDataAvailable(closedSocket, instanceId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ class SingleCoreApplicationPrivate : public QObject {
|
||||
void initializeMemoryBlock();
|
||||
void startPrimary();
|
||||
void startSecondary();
|
||||
bool connectToPrimary(const int msecs, const ConnectionType connectionType);
|
||||
bool connectToPrimary(const int timeout, const ConnectionType connectionType);
|
||||
quint16 blockChecksum();
|
||||
qint64 primaryPid();
|
||||
QString primaryUser();
|
||||
|
||||
@@ -69,11 +69,6 @@ add_compile_options(${COMPILE_OPTIONS})
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
add_definitions(-DNDEBUG)
|
||||
add_definitions(-DQT_NO_DEBUG_OUTPUT)
|
||||
#add_definitions(-DQT_NO_WARNING_OUTPUT)
|
||||
endif()
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||
set(DEBUG ON)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
@@ -256,7 +251,8 @@ set(SINGLEAPPLICATION_LIBRARIES singleapplication)
|
||||
set(SINGLECOREAPPLICATION_LIBRARIES singlecoreapplication)
|
||||
|
||||
if(APPLE)
|
||||
find_library(SPARKLE Sparkle)
|
||||
find_library(SPARKLE Sparkle PATHS "/usr/local/opt/sparkle")
|
||||
add_subdirectory(3rdparty/macdeployqt)
|
||||
add_subdirectory(3rdparty/SPMediaKeyTap)
|
||||
set(SPMEDIAKEYTAP_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/SPMediaKeyTap)
|
||||
set(SPMEDIAKEYTAP_LIBRARIES SPMediaKeyTap)
|
||||
|
||||
14
Changelog
14
Changelog
@@ -2,6 +2,17 @@ Strawberry Music Player
|
||||
=======================
|
||||
ChangeLog
|
||||
|
||||
0.9.2:
|
||||
|
||||
Bugfixes:
|
||||
* Fix marking songs available.
|
||||
* Fix crash when transcoding music, or copying music to devices with transcoding.
|
||||
* Fix copying album covers to iPod.
|
||||
* Fix playlist tabbar close and save right click actions.
|
||||
* Fix slow opening of cover manager.
|
||||
* (macOS) Fix crash when opening cover manager.
|
||||
* (macOS) Fix broken Qt plugins resulting in album covers not showing.
|
||||
|
||||
0.9.1:
|
||||
|
||||
Bugfixes:
|
||||
@@ -9,7 +20,7 @@ ChangeLog
|
||||
* Fix overwriting existing newer last played when importing last played from last.fm.
|
||||
* Fix memory leak on song change when moodbar is disabled.
|
||||
* Fix playlist filter search for text with spaces with Qt 6.
|
||||
* Fix 'Except between tracks on the same album' backend fade option always greyed out.
|
||||
* Fix 'Except between tracks on the same album' backend fade option always grayed out.
|
||||
* Fix read and save vorbis comment grouping tag.
|
||||
* Fix QAtomicInteger compile error on armv.
|
||||
* Fix compile error with protobuf 3.15.0 and newer.
|
||||
@@ -31,6 +42,7 @@ ChangeLog
|
||||
* Add right click actions to clear set cover, and option delete covers.
|
||||
* Show artist and album underneath the albums in the cover manager when all Artists is selected.
|
||||
* Disable unavailable right click cover actions.
|
||||
* Remove 3rdparty TagLib now that TagLib 1.12 is available.
|
||||
* (macOS) Update and improve build deployment/bundling for Qt 6.
|
||||
|
||||
New features:
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
find_program(MACDEPLOYQT_EXECUTABLE NAMES macdeployqt PATHS /usr/local/opt/qt6/bin /usr/local/opt/qt5/bin /usr/local/bin REQUIRED)
|
||||
if(MACDEPLOYQT_EXECUTABLE)
|
||||
message(STATUS "Found macdeployqt: ${MACDEPLOYQT_EXECUTABLE}")
|
||||
else()
|
||||
message(WARNING "Missing macdeployqt executable.")
|
||||
endif()
|
||||
#find_program(MACDEPLOYQT_EXECUTABLE NAMES macdeployqt PATHS /usr/local/opt/qt6/bin /usr/local/opt/qt5/bin /usr/local/bin REQUIRED)
|
||||
#if(MACDEPLOYQT_EXECUTABLE)
|
||||
# message(STATUS "Found macdeployqt: ${MACDEPLOYQT_EXECUTABLE}")
|
||||
#else()
|
||||
# message(WARNING "Missing macdeployqt executable.")
|
||||
#endif()
|
||||
|
||||
set(MACDEPLOYQT_EXECUTABLE "${CMAKE_BINARY_DIR}/3rdparty/macdeployqt/macdeployqt")
|
||||
|
||||
find_program(CREATEDMG_EXECUTABLE NAMES create-dmg REQUIRED)
|
||||
if(CREATEDMG_EXECUTABLE)
|
||||
@@ -19,14 +21,16 @@ endif()
|
||||
|
||||
if(MACDEPLOYQT_EXECUTABLE AND CREATEDMG_EXECUTABLE AND MACOS_VERSION_PACKAGE)
|
||||
add_custom_target(dmg
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/macos/macdeploy.py strawberry.app
|
||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
|
||||
COMMAND cp -r /usr/local/opt/sparkle/Sparkle.framework ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -verbose=3 -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
|
||||
COMMAND ${CREATEDMG_EXECUTABLE} --volname strawberry --background "${CMAKE_SOURCE_DIR}/dist/macos/dmg_background.png" --app-drop-link 450 218 --icon strawberry.app 150 218 --window-size 600 450 strawberry-${STRAWBERRY_VERSION_PACKAGE}-${MACOS_VERSION_PACKAGE}-${CMAKE_HOST_SYSTEM_PROCESSOR}.dmg strawberry.app
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
add_custom_target(dmg2
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/macos/macdeploy.py strawberry.app
|
||||
COMMAND mkdir -p ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
|
||||
COMMAND cp -r /usr/local/opt/sparkle/Sparkle.framework ${CMAKE_BINARY_DIR}/strawberry.app/Contents/Frameworks/
|
||||
COMMAND ${MACDEPLOYQT_EXECUTABLE} strawberry.app -verbose=3 -executable=${CMAKE_BINARY_DIR}/strawberry.app/Contents/PlugIns/strawberry-tagreader
|
||||
COMMAND ${CREATEDMG_EXECUTABLE} --skip-jenkins --volname strawberry --background "${CMAKE_SOURCE_DIR}/dist/macos/dmg_background.png" --app-drop-link 450 218 --icon strawberry.app 150 218 --window-size 600 450 strawberry-${STRAWBERRY_VERSION_PACKAGE}-${MACOS_VERSION_PACKAGE}-${CMAKE_HOST_SYSTEM_PROCESSOR}.dmg strawberry.app
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
set(STRAWBERRY_VERSION_MAJOR 0)
|
||||
set(STRAWBERRY_VERSION_MINOR 9)
|
||||
set(STRAWBERRY_VERSION_PATCH 1)
|
||||
set(STRAWBERRY_VERSION_PATCH 2)
|
||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||
|
||||
set(INCLUDE_GIT_REVISION OFF)
|
||||
|
||||
514
dist/macos/macdeploy.py
vendored
514
dist/macos/macdeploy.py
vendored
@@ -1,514 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Strawberry Music Player
|
||||
# This file was part of Clementine.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
from distutils import spawn
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
LOGGER = logging.getLogger('macdeploy')
|
||||
|
||||
LIBRARY_SEARCH_PATH = ['/usr/local/lib', '/usr/local/opt/icu4c/lib']
|
||||
|
||||
FRAMEWORK_SEARCH_PATH = [
|
||||
'/Library/Frameworks',
|
||||
os.path.join(os.environ['HOME'], 'Library/Frameworks'),
|
||||
'/Library/Frameworks/Sparkle.framework/Versions'
|
||||
]
|
||||
|
||||
QT_PLUGINS = [
|
||||
'platforms/libqcocoa.dylib',
|
||||
'platforminputcontexts/libqtvirtualkeyboardplugin.dylib',
|
||||
'styles/libqmacstyle.dylib',
|
||||
'sqldrivers/libqsqlite.dylib',
|
||||
'bearer/libqgenericbearer.dylib',
|
||||
'iconengines/libqsvgicon.dylib',
|
||||
'imageformats/libqgif.dylib',
|
||||
'imageformats/libqicns.dylib',
|
||||
'imageformats/libqico.dylib',
|
||||
'imageformats/libqjpeg.dylib',
|
||||
'imageformats/libqsvg.dylib',
|
||||
'imageformats/libqtiff.dylib',
|
||||
'printsupport/libcocoaprintersupport.dylib',
|
||||
'virtualkeyboard/libqtvirtualkeyboard_hangul.dylib',
|
||||
'virtualkeyboard/libqtvirtualkeyboard_openwnn.dylib',
|
||||
'virtualkeyboard/libqtvirtualkeyboard_pinyin.dylib',
|
||||
'virtualkeyboard/libqtvirtualkeyboard_tcime.dylib',
|
||||
'virtualkeyboard/libqtvirtualkeyboard_thai.dylib',
|
||||
]
|
||||
|
||||
QT_PLUGINS_SEARCH_PATH = [
|
||||
'/usr/local/opt/qt/plugins',
|
||||
]
|
||||
|
||||
GSTREAMER_SEARCH_PATH = [
|
||||
'/usr/local/lib/gstreamer-1.0',
|
||||
'/usr/local/Cellar/gstreamer',
|
||||
]
|
||||
|
||||
GSTREAMER_PLUGINS = [
|
||||
|
||||
'libgstapetag.dylib',
|
||||
'libgstapp.dylib',
|
||||
'libgstaudioconvert.dylib',
|
||||
'libgstaudiofx.dylib',
|
||||
'libgstaudiomixer.dylib',
|
||||
'libgstaudioparsers.dylib',
|
||||
'libgstaudiorate.dylib',
|
||||
'libgstaudioresample.dylib',
|
||||
'libgstaudiotestsrc.dylib',
|
||||
'libgstaudiovisualizers.dylib',
|
||||
'libgstauparse.dylib',
|
||||
'libgstautoconvert.dylib',
|
||||
'libgstautodetect.dylib',
|
||||
'libgstcoreelements.dylib',
|
||||
'libgstequalizer.dylib',
|
||||
'libgstgio.dylib',
|
||||
'libgsticydemux.dylib',
|
||||
'libgstid3demux.dylib',
|
||||
'libgstlevel.dylib',
|
||||
'libgstosxaudio.dylib',
|
||||
'libgstplayback.dylib',
|
||||
'libgstrawparse.dylib',
|
||||
'libgstreplaygain.dylib',
|
||||
'libgstsoup.dylib',
|
||||
'libgstspectrum.dylib',
|
||||
'libgsttypefindfunctions.dylib',
|
||||
'libgstvolume.dylib',
|
||||
'libgstxingmux.dylib',
|
||||
'libgsttcp.dylib',
|
||||
'libgstudp.dylib',
|
||||
'libgstpbtypes.dylib',
|
||||
'libgstrtp.dylib',
|
||||
'libgstrtsp.dylib',
|
||||
|
||||
'libgstflac.dylib',
|
||||
'libgstwavparse.dylib',
|
||||
'libgstfaac.dylib',
|
||||
'libgstfaad.dylib',
|
||||
'libgstogg.dylib',
|
||||
'libgstopus.dylib',
|
||||
'libgstopusparse.dylib',
|
||||
'libgstasf.dylib',
|
||||
'libgstspeex.dylib',
|
||||
'libgsttaglib.dylib',
|
||||
'libgstvorbis.dylib',
|
||||
'libgstisomp4.dylib',
|
||||
'libgstlibav.dylib',
|
||||
'libgstaiff.dylib',
|
||||
'libgstlame.dylib',
|
||||
'libgstmusepack.dylib',
|
||||
|
||||
]
|
||||
|
||||
GIO_MODULES_SEARCH_PATH = ['/usr/local/lib/gio/modules',]
|
||||
|
||||
INSTALL_NAME_TOOL_APPLE = 'install_name_tool'
|
||||
INSTALL_NAME_TOOL_CROSS = 'x86_64-apple-darwin-%s' % INSTALL_NAME_TOOL_APPLE
|
||||
INSTALL_NAME_TOOL = INSTALL_NAME_TOOL_CROSS if spawn.find_executable(INSTALL_NAME_TOOL_CROSS) else INSTALL_NAME_TOOL_APPLE
|
||||
|
||||
OTOOL_APPLE = 'otool'
|
||||
OTOOL_CROSS = 'x86_64-apple-darwin-%s' % OTOOL_APPLE
|
||||
OTOOL = OTOOL_CROSS if spawn.find_executable(OTOOL_CROSS) else OTOOL_APPLE
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class CouldNotFindFrameworkError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindGioModuleError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotFindQtPluginError(Error):
|
||||
pass
|
||||
|
||||
class CouldNotParseFrameworkNameError(Error):
|
||||
pass
|
||||
|
||||
class InstallNameToolError(Error):
|
||||
pass
|
||||
|
||||
|
||||
class CouldNotFindGstreamerPluginError(Error):
|
||||
pass
|
||||
|
||||
if len(sys.argv) < 2:
|
||||
print('Usage: %s <bundle.app>' % sys.argv[0])
|
||||
|
||||
bundle_dir = sys.argv[1]
|
||||
|
||||
bundle_name = os.path.basename(bundle_dir).split('.')[0]
|
||||
|
||||
commands = []
|
||||
|
||||
frameworks_dir = os.path.join(bundle_dir, 'Contents', 'Frameworks')
|
||||
commands.append(['mkdir', '-p', frameworks_dir])
|
||||
resources_dir = os.path.join(bundle_dir, 'Contents', 'Resources')
|
||||
commands.append(['mkdir', '-p', resources_dir])
|
||||
plugins_dir = os.path.join(bundle_dir, 'Contents', 'PlugIns')
|
||||
binary = os.path.join(bundle_dir, 'Contents', 'MacOS', bundle_name)
|
||||
tagreader_binary = os.path.join(plugins_dir, bundle_name + "-tagreader")
|
||||
|
||||
fixed_libraries = set()
|
||||
fixed_frameworks = set()
|
||||
|
||||
|
||||
def GetBrokenLibraries(binary):
|
||||
#print("Checking libs for binary: %s" % binary)
|
||||
output = subprocess.Popen([OTOOL, '-L', binary], stdout=subprocess.PIPE).communicate()[0].decode('utf-8')
|
||||
broken_libs = {'frameworks': [], 'libs': []}
|
||||
for line in [x.split(' ')[0].lstrip() for x in output.split('\n')[1:]]:
|
||||
#print("Checking line: %s" % line)
|
||||
if not line: # skip empty lines
|
||||
continue
|
||||
if os.path.basename(binary) == os.path.basename(line):
|
||||
#print("mnope %s-%s" % (os.path.basename(binary), os.path.basename(line)))
|
||||
continue
|
||||
if re.match(r'^\s*/System/', line):
|
||||
#print("system framework: %s" % line)
|
||||
continue # System framework
|
||||
elif re.match(r'^\s*/usr/lib/', line):
|
||||
#print("unix style system lib: %s" % line)
|
||||
continue # unix style system library
|
||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@rpath', line) or re.match(r'^\s*@loader_path', line):
|
||||
# Potentially already fixed library
|
||||
if line.count('/') == 1:
|
||||
relative_path = os.path.join(*line.split('/')[1:])
|
||||
if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
|
||||
broken_libs['libs'].append(relative_path)
|
||||
elif line.count('/') == 2:
|
||||
relative_path = os.path.join(*line.split('/')[2:])
|
||||
if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
|
||||
broken_libs['libs'].append(relative_path)
|
||||
elif line.count('/') >= 3:
|
||||
relative_path = os.path.join(*line.split('/')[3:])
|
||||
if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
|
||||
broken_libs['frameworks'].append(relative_path)
|
||||
else:
|
||||
print("GetBrokenLibraries Error: %s" % line)
|
||||
elif re.search(r'\w+\.framework', line):
|
||||
#print("framework: %s" % line)
|
||||
broken_libs['frameworks'].append(line)
|
||||
else:
|
||||
broken_libs['libs'].append(line)
|
||||
|
||||
return broken_libs
|
||||
|
||||
|
||||
def FindFramework(path):
|
||||
for search_path in FRAMEWORK_SEARCH_PATH:
|
||||
abs_path = os.path.join(search_path, path)
|
||||
if os.path.exists(abs_path):
|
||||
LOGGER.debug("Found framework '%s' in '%s'", path, search_path)
|
||||
return abs_path
|
||||
|
||||
raise CouldNotFindFrameworkError(path)
|
||||
|
||||
|
||||
def FindLibrary(path):
|
||||
if os.path.exists(path):
|
||||
return path
|
||||
for search_path in LIBRARY_SEARCH_PATH:
|
||||
abs_path = os.path.join(search_path, path)
|
||||
if os.path.exists(abs_path):
|
||||
LOGGER.debug("Found library '%s' in '%s'", path, search_path)
|
||||
return abs_path
|
||||
else: # try harder---look for lib name in library folders
|
||||
newpath = os.path.join(search_path,os.path.basename(path))
|
||||
if os.path.exists(newpath):
|
||||
return newpath
|
||||
|
||||
raise CouldNotFindFrameworkError(path)
|
||||
|
||||
|
||||
def FixAllLibraries(broken_libs):
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFramework(framework)
|
||||
for lib in broken_libs['libs']:
|
||||
FixLibrary(lib)
|
||||
|
||||
|
||||
def FixFramework(path):
|
||||
if path in fixed_frameworks:
|
||||
return
|
||||
else:
|
||||
fixed_frameworks.add(path)
|
||||
abs_path = FindFramework(path)
|
||||
broken_libs = GetBrokenLibraries(abs_path)
|
||||
FixAllLibraries(broken_libs)
|
||||
|
||||
new_path = CopyFramework(abs_path)
|
||||
id = os.sep.join(new_path.split(os.sep)[3:])
|
||||
FixFrameworkId(new_path, id)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, new_path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, new_path)
|
||||
|
||||
|
||||
def FixLibrary(path):
|
||||
|
||||
if path in fixed_libraries:
|
||||
return
|
||||
|
||||
# Always bundle libraries provided by homebrew (/usr/local).
|
||||
if not re.match(r'^\s*/usr/local', path) and FindSystemLibrary(os.path.basename(path)) is not None:
|
||||
return
|
||||
|
||||
fixed_libraries.add(path)
|
||||
|
||||
abs_path = FindLibrary(path)
|
||||
if abs_path == "":
|
||||
print("Could not resolve %s, not fixing!" % path)
|
||||
return
|
||||
|
||||
broken_libs = GetBrokenLibraries(abs_path)
|
||||
FixAllLibraries(broken_libs)
|
||||
|
||||
new_path = CopyLibrary(abs_path)
|
||||
FixLibraryId(new_path)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, new_path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, new_path)
|
||||
|
||||
|
||||
def FixPlugin(abs_path, subdir):
|
||||
broken_libs = GetBrokenLibraries(abs_path)
|
||||
FixAllLibraries(broken_libs)
|
||||
|
||||
new_path = CopyPlugin(abs_path, subdir)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, new_path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, new_path)
|
||||
|
||||
|
||||
def FixBinary(path):
|
||||
broken_libs = GetBrokenLibraries(path)
|
||||
FixAllLibraries(broken_libs)
|
||||
for framework in broken_libs['frameworks']:
|
||||
FixFrameworkInstallPath(framework, path)
|
||||
for library in broken_libs['libs']:
|
||||
FixLibraryInstallPath(library, path)
|
||||
|
||||
|
||||
def CopyLibrary(path):
|
||||
new_path = os.path.join(frameworks_dir, os.path.basename(path))
|
||||
#args = ['cp', path, new_path]
|
||||
args = ['ditto', '--arch=i386', '--arch=x86_64', path, new_path]
|
||||
commands.append(args)
|
||||
commands.append(['chmod', '+w', new_path])
|
||||
LOGGER.info("Copying library '%s'", path)
|
||||
return new_path
|
||||
|
||||
|
||||
def CopyPlugin(path, subdir):
|
||||
new_path = os.path.join(plugins_dir, subdir, os.path.basename(path))
|
||||
args = ['mkdir', '-p', os.path.dirname(new_path)]
|
||||
commands.append(args)
|
||||
#args = ['cp', path, new_path]
|
||||
args = ['ditto', '--arch=i386', '--arch=x86_64', path, new_path]
|
||||
commands.append(args)
|
||||
commands.append(['chmod', '+w', new_path])
|
||||
LOGGER.info("Copying plugin '%s'", path)
|
||||
return new_path
|
||||
|
||||
def CopyFramework(path):
|
||||
parts = path.split(os.sep)
|
||||
for i, part in enumerate(parts):
|
||||
if re.match(r'\w+\.framework', part):
|
||||
full_path = os.path.join(frameworks_dir, *parts[i:-1])
|
||||
framework_name = part.split(".framework")[0]
|
||||
break
|
||||
|
||||
def CopyFramework(src_binary):
|
||||
while os.path.islink(src_binary):
|
||||
src_binary = os.path.realpath(src_binary)
|
||||
|
||||
m = re.match(r'(.*/([^/]+)\.framework)/Versions/([^/]+)/.*', src_binary)
|
||||
if not m:
|
||||
raise CouldNotParseFrameworkNameError(src_binary)
|
||||
|
||||
src_base = m.group(1)
|
||||
name = m.group(2)
|
||||
version = m.group(3)
|
||||
|
||||
LOGGER.info('Copying framework %s version %s', name, version)
|
||||
|
||||
dest_base = os.path.join(frameworks_dir, '%s.framework' % name)
|
||||
dest_dir = os.path.join(dest_base, 'Versions', version)
|
||||
dest_binary = os.path.join(dest_dir, name)
|
||||
|
||||
commands.append(['mkdir', '-p', dest_dir])
|
||||
commands.append(['cp', src_binary, dest_binary])
|
||||
commands.append(['chmod', '+w', dest_binary])
|
||||
|
||||
# Copy special files from various places:
|
||||
# QtCore has Resources/qt_menu.nib (copy to app's Resources)
|
||||
# Sparkle has Resources/*
|
||||
# Qt* have Resources/Info.plist
|
||||
resources_src = os.path.join(src_base, 'Resources')
|
||||
menu_nib = os.path.join(resources_src, 'qt_menu.nib')
|
||||
if os.path.exists(menu_nib):
|
||||
LOGGER.info("Copying qt_menu.nib '%s'", menu_nib)
|
||||
commands.append(['cp', '-r', menu_nib, resources_dir])
|
||||
elif os.path.exists(resources_src):
|
||||
LOGGER.info("Copying resources dir '%s'", resources_src)
|
||||
commands.append(['cp', '-r', resources_src, dest_dir])
|
||||
|
||||
info_plist = os.path.join(src_base, 'Contents', 'Info.plist')
|
||||
if os.path.exists(info_plist):
|
||||
LOGGER.info("Copying special file '%s'", info_plist)
|
||||
resources_dest = os.path.join(dest_dir, 'Resources')
|
||||
commands.append(['mkdir', resources_dest])
|
||||
commands.append(['cp', '-r', info_plist, resources_dest])
|
||||
|
||||
# Create symlinks in the Framework to make it look like
|
||||
# https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/FrameworkAnatomy.html
|
||||
commands.append([
|
||||
'ln', '-sf', 'Versions/Current/%s' % name, os.path.join(dest_base, name)
|
||||
])
|
||||
commands.append([
|
||||
'ln', '-sf', 'Versions/Current/Resources',
|
||||
os.path.join(dest_base, 'Resources')
|
||||
])
|
||||
commands.append(
|
||||
['ln', '-sf', version, os.path.join(dest_base, 'Versions/Current')])
|
||||
|
||||
return dest_binary
|
||||
|
||||
|
||||
def FixId(path, library_name):
|
||||
id = '@executable_path/../Frameworks/%s' % library_name
|
||||
args = [INSTALL_NAME_TOOL, '-id', id, path]
|
||||
commands.append(args)
|
||||
|
||||
|
||||
def FixLibraryId(path):
|
||||
library_name = os.path.basename(path)
|
||||
FixId(path, library_name)
|
||||
|
||||
|
||||
def FixFrameworkId(path, id):
|
||||
FixId(path, id)
|
||||
|
||||
|
||||
def FixInstallPath(library_path, library, new_path):
|
||||
args = [INSTALL_NAME_TOOL, '-change', library_path, new_path, library]
|
||||
commands.append(args)
|
||||
|
||||
|
||||
def FindSystemLibrary(library_name):
|
||||
for path in ['/lib', '/usr/lib']:
|
||||
full_path = os.path.join(path, library_name)
|
||||
if os.path.exists(full_path):
|
||||
return full_path
|
||||
return None
|
||||
|
||||
|
||||
def FixLibraryInstallPath(library_path, library):
|
||||
system_library = FindSystemLibrary(os.path.basename(library_path))
|
||||
if system_library is None or re.match(r'^\s*/usr/local', library_path):
|
||||
new_path = '@executable_path/../Frameworks/%s' % os.path.basename(library_path)
|
||||
FixInstallPath(library_path, library, new_path)
|
||||
else:
|
||||
FixInstallPath(library_path, library, system_library)
|
||||
|
||||
|
||||
def FixFrameworkInstallPath(library_path, library):
|
||||
parts = library_path.split(os.sep)
|
||||
full_path = ""
|
||||
for i, part in enumerate(parts):
|
||||
if re.match(r'\w+\.framework', part):
|
||||
full_path = os.path.join(*parts[i:])
|
||||
break
|
||||
if full_path:
|
||||
new_path = '@executable_path/../Frameworks/%s' % full_path
|
||||
FixInstallPath(library_path, library, new_path)
|
||||
|
||||
|
||||
def FindQtPlugin(name):
|
||||
for path in QT_PLUGINS_SEARCH_PATH:
|
||||
if os.path.exists(path):
|
||||
if os.path.exists(os.path.join(path, name)):
|
||||
return os.path.join(path, name)
|
||||
raise CouldNotFindQtPluginError(name)
|
||||
|
||||
|
||||
def FindGstreamerPlugin(name):
|
||||
for path in GSTREAMER_SEARCH_PATH:
|
||||
if os.path.exists(path):
|
||||
for dir, dirs, files in os.walk(path):
|
||||
if name in files:
|
||||
return os.path.join(dir, name)
|
||||
raise CouldNotFindGstreamerPluginError(name)
|
||||
|
||||
|
||||
def FindGioModule(name):
|
||||
for path in GIO_MODULES_SEARCH_PATH:
|
||||
if os.path.exists(path):
|
||||
for dir, dirs, files in os.walk(path):
|
||||
if name in files:
|
||||
return os.path.join(dir, name)
|
||||
raise CouldNotFindGioModuleError(name)
|
||||
|
||||
|
||||
def main():
|
||||
logging.basicConfig(filename='macdeploy.log', level=logging.DEBUG, format='%(asctime)s %(levelname)-8s %(message)s')
|
||||
|
||||
FixBinary(binary)
|
||||
FixBinary(tagreader_binary)
|
||||
|
||||
# macdeployqt needs to handle strawberry-tagreader for Qt deployment, so we can't use FixPlugin() here.
|
||||
#try:
|
||||
# FixPlugin('strawberry-tagreader', '.')
|
||||
#except:
|
||||
# print('Failed to find blob: %s' % traceback.format_exc())
|
||||
|
||||
for plugin in GSTREAMER_PLUGINS:
|
||||
FixPlugin(FindGstreamerPlugin(plugin), 'gstreamer')
|
||||
|
||||
FixPlugin(FindGstreamerPlugin('gst-plugin-scanner'), '.')
|
||||
FixPlugin(FindGioModule('libgiognutls.so'), 'gio-modules')
|
||||
#FixPlugin(FindGioModule('libgiognomeproxy.so'), 'gio-modules')
|
||||
|
||||
#for plugin in QT_PLUGINS:
|
||||
#FixPlugin(FindQtPlugin(plugin), os.path.dirname(plugin))
|
||||
|
||||
if len(sys.argv) <= 2:
|
||||
print('Would run %d commands:' % len(commands))
|
||||
for command in commands:
|
||||
print(' '.join(command))
|
||||
|
||||
#print('OK?')
|
||||
#raw_input()
|
||||
|
||||
for command in commands:
|
||||
p = subprocess.Popen(command)
|
||||
os.waitpid(p.pid, 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -82,7 +82,7 @@ template <typename MT>
|
||||
class AbstractMessageHandler : public _MessageHandlerBase {
|
||||
public:
|
||||
AbstractMessageHandler(QIODevice *device, QObject *parent);
|
||||
~AbstractMessageHandler() override { AbortAll(); }
|
||||
~AbstractMessageHandler() override { AbstractMessageHandler::AbortAll(); }
|
||||
|
||||
typedef MT MessageType;
|
||||
typedef MessageReply<MT> ReplyType;
|
||||
|
||||
@@ -191,10 +191,11 @@ void AnalyzerContainer::Load() {
|
||||
}
|
||||
|
||||
// Framerate
|
||||
QList<QAction*> actions = group_framerate_->actions();
|
||||
for (int i = 0; i < framerate_list_.count(); ++i) {
|
||||
if (current_framerate_ == framerate_list_[i]) {
|
||||
ChangeFramerate(current_framerate_);
|
||||
group_framerate_->actions()[i]->setChecked(true);
|
||||
actions[i]->setChecked(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
#include "analyzerbase.h"
|
||||
#include "fht.h"
|
||||
|
||||
const uint BlockAnalyzer::kHeight = 2;
|
||||
const uint BlockAnalyzer::kWidth = 4;
|
||||
const uint BlockAnalyzer::kMinRows = 3; // arbituary
|
||||
const uint BlockAnalyzer::kMinColumns = 32; // arbituary
|
||||
const uint BlockAnalyzer::kMaxColumns = 256; // must be 2**n
|
||||
const uint BlockAnalyzer::kFadeSize = 90;
|
||||
const int BlockAnalyzer::kHeight = 2;
|
||||
const int BlockAnalyzer::kWidth = 4;
|
||||
const int BlockAnalyzer::kMinRows = 3; // arbituary
|
||||
const int BlockAnalyzer::kMinColumns = 32; // arbituary
|
||||
const int BlockAnalyzer::kMaxColumns = 256; // must be 2**n
|
||||
const int BlockAnalyzer::kFadeSize = 90;
|
||||
|
||||
const char *BlockAnalyzer::kName = QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
|
||||
|
||||
@@ -74,11 +74,11 @@ void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
|
||||
background_ = QPixmap(size());
|
||||
canvas_ = QPixmap(size());
|
||||
|
||||
const uint oldRows = rows_;
|
||||
const int oldRows = rows_;
|
||||
|
||||
// all is explained in analyze()..
|
||||
// +1 to counter -1 in maxSizes, trust me we need this!
|
||||
columns_ = qMin(static_cast<uint>(static_cast<double>(width() + 1) / (kWidth + 1)) + 1, kMaxColumns);
|
||||
columns_ = qMin(static_cast<int>(static_cast<double>(width() + 1) / (kWidth + 1)) + 1, kMaxColumns);
|
||||
rows_ = static_cast<uint>(static_cast<double>(height() + 1) / (kHeight + 1));
|
||||
|
||||
// this is the y-offset for drawing from the top of the widget
|
||||
@@ -94,9 +94,9 @@ void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
|
||||
|
||||
yscale_.resize(rows_ + 1);
|
||||
|
||||
const uint PRE = 1, PRO = 1; // PRE and PRO allow us to restrict the range somewhat
|
||||
const int PRE = 1, PRO = 1; // PRE and PRO allow us to restrict the range somewhat
|
||||
|
||||
for (uint z = 0; z < rows_; ++z)
|
||||
for (int z = 0; z < rows_; ++z)
|
||||
yscale_[z] = 1 - (log10(PRE + z) / log10(PRE + rows_ + PRO));
|
||||
|
||||
yscale_[rows_] = 0;
|
||||
@@ -115,7 +115,7 @@ void BlockAnalyzer::determineStep() {
|
||||
// I calculated the value 30 based on some trial and error
|
||||
|
||||
// the fall time of 30 is too slow on framerates above 50fps
|
||||
const double fallTime = timeout() < 20 ? 20 * rows_ : 30 * rows_;
|
||||
const double fallTime = static_cast<double>(timeout() < 20 ? 20 * rows_ : 30 * rows_);
|
||||
|
||||
step_ = double(rows_ * timeout()) / fallTime;
|
||||
|
||||
@@ -164,12 +164,12 @@ void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_fram
|
||||
// Paint the background
|
||||
canvas_painter.drawPixmap(0, 0, background_);
|
||||
|
||||
for (uint y, x = 0; x < scope_.size(); ++x) {
|
||||
for (int y, x = 0; x < static_cast<int>(scope_.size()); ++x) {
|
||||
// determine y
|
||||
for (y = 0; scope_[x] < yscale_[y]; ++y) continue;
|
||||
|
||||
// This is opposite to what you'd think, higher than y means the bar is lower than y (physically)
|
||||
if (static_cast<float>(y) > store_[x])
|
||||
if (static_cast<double>(y) > store_[x])
|
||||
y = static_cast<int>(store_[x] += step_);
|
||||
else
|
||||
store_[x] = y;
|
||||
@@ -182,8 +182,8 @@ void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_fram
|
||||
}
|
||||
|
||||
if (fade_intensity_[x] > 0) {
|
||||
const uint offset = --fade_intensity_[x];
|
||||
const uint y2 = y_ + (fade_pos_[x] * (kHeight + 1));
|
||||
const int offset = --fade_intensity_[x];
|
||||
const int y2 = y_ + (fade_pos_[x] * (kHeight + 1));
|
||||
canvas_painter.drawPixmap(x * (kWidth + 1), y2, fade_bars_[offset], 0, 0, kWidth, height() - y2);
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_fram
|
||||
|
||||
}
|
||||
|
||||
static inline void adjustToLimits(int &b, int &f, uint &amount) {
|
||||
static inline void adjustToLimits(int &b, int &f, int &amount) {
|
||||
|
||||
// with a range of 0-255 and maximum adjustment of amount, maximise the difference between f and b
|
||||
|
||||
@@ -235,8 +235,8 @@ static inline void adjustToLimits(int &b, int &f, uint &amount) {
|
||||
* It won't modify the hue of fg unless absolutely necessary
|
||||
* @return the adjusted form of fg
|
||||
*/
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount = 150);
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, int amount = 150);
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, int amount) {
|
||||
|
||||
class OutputOnExit {
|
||||
public:
|
||||
@@ -278,9 +278,9 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
|
||||
|
||||
// check the saturation for the two colours is sufficient that hue alone can
|
||||
// provide sufficient contrast
|
||||
if (ds > static_cast<int>(amount) / 2 && (bs > 125 && fs > 125))
|
||||
if (ds > amount / 2 && (bs > 125 && fs > 125))
|
||||
return fg;
|
||||
else if (dv > static_cast<int>(amount) / 2 && (bv > 125 && fv > 125))
|
||||
else if (dv > amount / 2 && (bv > 125 && fv > 125))
|
||||
return fg;
|
||||
}
|
||||
|
||||
@@ -295,11 +295,11 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
|
||||
}
|
||||
|
||||
// test that there is available value to honor our contrast requirement
|
||||
if (255 - dv < static_cast<int>(amount)) {
|
||||
if (255 - dv < amount) {
|
||||
// we have to modify the value and saturation of fg
|
||||
// adjustToLimits( bv, fv, amount );
|
||||
// see if we need to adjust the saturation
|
||||
if (static_cast<int>(amount) > 0) adjustToLimits(bs, fs, amount);
|
||||
if (amount > 0) adjustToLimits(bs, fs, amount);
|
||||
|
||||
// see if we need to adjust the hue
|
||||
if (static_cast<int>(amount) > 0)
|
||||
@@ -312,13 +312,13 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
|
||||
return QColor::fromHsv(fh, fs, bv - static_cast<int>(amount));
|
||||
|
||||
if (fv < bv && fv > static_cast<int>(amount))
|
||||
return QColor::fromHsv(fh, fs, fv - static_cast<int>(amount));
|
||||
return QColor::fromHsv(fh, fs, fv - amount);
|
||||
|
||||
if (fv > bv && (255 - fv > static_cast<int>(amount)))
|
||||
return QColor::fromHsv(fh, fs, fv + static_cast<int>(amount));
|
||||
return QColor::fromHsv(fh, fs, fv + amount);
|
||||
|
||||
if (fv < bv && (255 - bv > static_cast<int>(amount)))
|
||||
return QColor::fromHsv(fh, fs, bv + static_cast<int>(amount));
|
||||
return QColor::fromHsv(fh, fs, bv + amount);
|
||||
|
||||
return Qt::blue;
|
||||
}
|
||||
@@ -338,7 +338,7 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
|
||||
bar()->fill(bg);
|
||||
|
||||
QPainter p(bar());
|
||||
for (int y = 0; static_cast<uint>(y) < rows_; ++y)
|
||||
for (int y = 0; y < rows_; ++y)
|
||||
// graduate the fg color
|
||||
p.fillRect(0, y * (kHeight + 1), kWidth, kHeight, QColor(r + static_cast<int>(dr * y), g + static_cast<int>(dg * y), b + static_cast<int>(db * y)));
|
||||
|
||||
@@ -360,7 +360,7 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
|
||||
for (uint y = 0; y < kFadeSize; ++y) {
|
||||
fade_bars_[y].fill(palette().color(QPalette::Window));
|
||||
QPainter f(&fade_bars_[y]);
|
||||
for (int z = 0; static_cast<uint>(z) < rows_; ++z) {
|
||||
for (int z = 0; z < rows_; ++z) {
|
||||
const double Y = 1.0 - (log10(kFadeSize - y) / log10(kFadeSize));
|
||||
f.fillRect(0, z * (kHeight + 1), kWidth, kHeight, QColor(r2 + static_cast<int>(dr2 * Y), g2 + static_cast<int>(dg2 * Y), b2 + static_cast<int>(db2 * Y)));
|
||||
}
|
||||
@@ -386,8 +386,8 @@ void BlockAnalyzer::drawBackground() {
|
||||
|
||||
if (!p.paintEngine()) return;
|
||||
|
||||
for (int x = 0; static_cast<uint>(x) < columns_; ++x)
|
||||
for (int y = 0; static_cast<uint>(y) < rows_; ++y)
|
||||
for (int x = 0; x < columns_; ++x)
|
||||
for (int y = 0; y < rows_; ++y)
|
||||
p.fillRect(x * (kWidth + 1), y * (kHeight + 1) + y_, kWidth, kHeight, bgdark);
|
||||
|
||||
}
|
||||
|
||||
@@ -43,12 +43,12 @@ class BlockAnalyzer : public Analyzer::Base {
|
||||
public:
|
||||
Q_INVOKABLE explicit BlockAnalyzer(QWidget*);
|
||||
|
||||
static const uint kHeight;
|
||||
static const uint kWidth;
|
||||
static const uint kMinRows;
|
||||
static const uint kMinColumns;
|
||||
static const uint kMaxColumns;
|
||||
static const uint kFadeSize;
|
||||
static const int kHeight;
|
||||
static const int kWidth;
|
||||
static const int kMinRows;
|
||||
static const int kMinColumns;
|
||||
static const int kMaxColumns;
|
||||
static const int kFadeSize;
|
||||
|
||||
static const char *kName;
|
||||
|
||||
@@ -65,21 +65,21 @@ class BlockAnalyzer : public Analyzer::Base {
|
||||
private:
|
||||
QPixmap *bar() { return &barpixmap_; }
|
||||
|
||||
uint columns_, rows_; // number of rows and columns of blocks
|
||||
uint y_; // y-offset from top of widget
|
||||
int columns_, rows_; // number of rows and columns of blocks
|
||||
int y_; // y-offset from top of widget
|
||||
QPixmap barpixmap_;
|
||||
QPixmap topbarpixmap_;
|
||||
QPixmap background_;
|
||||
QPixmap canvas_;
|
||||
Analyzer::Scope scope_; // so we don't create a vector every frame
|
||||
QVector<float> store_; // current bar heights
|
||||
QVector<float> yscale_;
|
||||
QVector<double> store_; // current bar heights
|
||||
QVector<double> yscale_;
|
||||
|
||||
QVector<QPixmap> fade_bars_;
|
||||
QVector<uint> fade_pos_;
|
||||
QVector<int> fade_pos_;
|
||||
QVector<int> fade_intensity_;
|
||||
|
||||
float step_; // rows to fall per frame
|
||||
double step_; // rows to fall per frame
|
||||
};
|
||||
|
||||
#endif // BLOCKANALYZER_H
|
||||
|
||||
@@ -39,9 +39,9 @@
|
||||
|
||||
using Analyzer::Scope;
|
||||
|
||||
const uint BoomAnalyzer::kColumnWidth = 4;
|
||||
const uint BoomAnalyzer::kMaxBandCount = 256;
|
||||
const uint BoomAnalyzer::kMinBandCount = 32;
|
||||
const int BoomAnalyzer::kColumnWidth = 4;
|
||||
const int BoomAnalyzer::kMaxBandCount = 256;
|
||||
const int BoomAnalyzer::kMinBandCount = 32;
|
||||
|
||||
const char* BoomAnalyzer::kName = QT_TRANSLATE_NOOP("AnalyzerContainer", "Boom analyzer");
|
||||
|
||||
@@ -80,10 +80,10 @@ void BoomAnalyzer::resizeEvent(QResizeEvent* e) {
|
||||
const uint HEIGHT = height() - 2;
|
||||
const double h = 1.2 / HEIGHT;
|
||||
|
||||
bands_ = qMin(static_cast<uint>(static_cast<double>(width() + 1) / (kColumnWidth + 1)) + 1, kMaxBandCount);
|
||||
bands_ = qMin(static_cast<int>(static_cast<double>(width() + 1) / (kColumnWidth + 1)) + 1, kMaxBandCount);
|
||||
scope_.resize(bands_);
|
||||
|
||||
F_ = static_cast<double>(HEIGHT) / (log10(256) * 1.1 /*<- max. amplitude*/);
|
||||
F_ = double(HEIGHT) / (log10(256) * double(1.1) /*<- max. amplitude*/);
|
||||
|
||||
barPixmap_ = QPixmap(kColumnWidth - 2, HEIGHT);
|
||||
canvas_ = QPixmap(size());
|
||||
@@ -106,7 +106,7 @@ void BoomAnalyzer::transform(Scope& s) {
|
||||
fht_->spectrum(s.data());
|
||||
fht_->scale(s.data(), 1.0 / 50);
|
||||
|
||||
s.resize(scope_.size() <= kMaxBandCount / 2 ? kMaxBandCount / 2 : scope_.size());
|
||||
s.resize(scope_.size() <= static_cast<quint64>(kMaxBandCount) / 2 ? kMaxBandCount / 2 : scope_.size());
|
||||
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void BoomAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
||||
p.drawPixmap(0, 0, canvas_);
|
||||
return;
|
||||
}
|
||||
float h;
|
||||
double h;
|
||||
const uint MAX_HEIGHT = height() - 1;
|
||||
|
||||
QPainter canvas_painter(&canvas_);
|
||||
@@ -124,7 +124,7 @@ void BoomAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
||||
|
||||
Analyzer::interpolate(scope, scope_);
|
||||
|
||||
for (uint i = 0, x = 0, y; i < bands_; ++i, x += kColumnWidth + 1) {
|
||||
for (int i = 0, x = 0, y; i < bands_; ++i, x += kColumnWidth + 1) {
|
||||
h = log10(scope_[i] * 256.0) * F_;
|
||||
|
||||
if (h > MAX_HEIGHT) h = MAX_HEIGHT;
|
||||
@@ -157,13 +157,13 @@ void BoomAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
||||
}
|
||||
}
|
||||
|
||||
y = height() - uint(bar_height_[i]);
|
||||
y = height() - static_cast<int>(bar_height_[i]);
|
||||
canvas_painter.drawPixmap(x + 1, y, barPixmap_, 0, y, -1, -1);
|
||||
canvas_painter.setPen(fg_);
|
||||
if (bar_height_[i] > 0)
|
||||
canvas_painter.drawRect(x, y, kColumnWidth - 1, height() - y - 1);
|
||||
|
||||
y = height() - uint(peak_height_[i]);
|
||||
y = height() - static_cast<int>(peak_height_[i]);
|
||||
canvas_painter.setPen(palette().color(QPalette::Midlight));
|
||||
canvas_painter.drawLine(x, y, x + kColumnWidth - 1, y);
|
||||
}
|
||||
|
||||
@@ -54,19 +54,19 @@ class BoomAnalyzer : public Analyzer::Base {
|
||||
protected:
|
||||
void resizeEvent(QResizeEvent *e) override;
|
||||
|
||||
static const uint kColumnWidth;
|
||||
static const uint kMaxBandCount;
|
||||
static const uint kMinBandCount;
|
||||
static const int kColumnWidth;
|
||||
static const int kMaxBandCount;
|
||||
static const int kMinBandCount;
|
||||
|
||||
uint bands_;
|
||||
int bands_;
|
||||
Analyzer::Scope scope_;
|
||||
QColor fg_;
|
||||
|
||||
double K_barHeight_, F_peakSpeed_, F_;
|
||||
|
||||
std::vector<float> bar_height_;
|
||||
std::vector<float> peak_height_;
|
||||
std::vector<float> peak_speed_;
|
||||
std::vector<double> bar_height_;
|
||||
std::vector<double> peak_height_;
|
||||
std::vector<double> peak_speed_;
|
||||
|
||||
QPixmap barPixmap_;
|
||||
QPixmap canvas_;
|
||||
|
||||
@@ -112,7 +112,7 @@ void Rainbow::RainbowAnalyzer::resizeEvent(QResizeEvent* e) {
|
||||
void Rainbow::RainbowAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s, bool new_frame) {
|
||||
|
||||
// Discard the second half of the transform
|
||||
const int scope_size = s.size() / 2;
|
||||
const int scope_size = static_cast<int>(s.size() / 2);
|
||||
|
||||
if ((new_frame && is_playing_) || (buffer_[0].isNull() && buffer_[1].isNull())) {
|
||||
// Transform the music into rainbows!
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -597,7 +597,13 @@ void CollectionBackend::MarkSongsUnavailable(const SongList &songs, const bool u
|
||||
}
|
||||
transaction.Commit();
|
||||
|
||||
emit SongsDeleted(songs);
|
||||
if (unavailable) {
|
||||
emit SongsDeleted(songs);
|
||||
}
|
||||
else {
|
||||
emit SongsDiscovered(songs);
|
||||
}
|
||||
|
||||
UpdateTotalSongCountAsync();
|
||||
UpdateTotalArtistCountAsync();
|
||||
UpdateTotalAlbumCountAsync();
|
||||
@@ -752,7 +758,7 @@ SongList CollectionBackend::GetSongsByForeignId(const QStringList &ids, const QS
|
||||
|
||||
QVector<Song> ret(ids.count());
|
||||
while (q.next()) {
|
||||
const QString foreign_id = q.value(Song::kColumns.count() + 1).toString();
|
||||
const QString foreign_id = q.value(static_cast<int>(Song::kColumns.count()) + 1).toString();
|
||||
const int index = ids.indexOf(foreign_id);
|
||||
if (index == -1) continue;
|
||||
|
||||
@@ -1478,7 +1484,7 @@ void CollectionBackend::UpdatePlayCount(const QString &artist, const QString &ti
|
||||
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateSongRating(const int id, const float rating) {
|
||||
void CollectionBackend::UpdateSongRating(const int id, const double rating) {
|
||||
|
||||
if (id == -1) return;
|
||||
|
||||
@@ -1488,7 +1494,7 @@ void CollectionBackend::UpdateSongRating(const int id, const float rating) {
|
||||
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateSongsRating(const QList<int> &id_list, const float rating) {
|
||||
void CollectionBackend::UpdateSongsRating(const QList<int> &id_list, const double rating) {
|
||||
|
||||
if (id_list.isEmpty()) return;
|
||||
|
||||
@@ -1510,10 +1516,10 @@ void CollectionBackend::UpdateSongsRating(const QList<int> &id_list, const float
|
||||
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateSongRatingAsync(const int id, const float rating) {
|
||||
metaObject()->invokeMethod(this, "UpdateSongRating", Qt::QueuedConnection, Q_ARG(int, id), Q_ARG(float, rating));
|
||||
void CollectionBackend::UpdateSongRatingAsync(const int id, const double rating) {
|
||||
metaObject()->invokeMethod(this, "UpdateSongRating", Qt::QueuedConnection, Q_ARG(int, id), Q_ARG(double, rating));
|
||||
}
|
||||
|
||||
void CollectionBackend::UpdateSongsRatingAsync(const QList<int>& ids, const float rating) {
|
||||
metaObject()->invokeMethod(this, "UpdateSongsRating", Qt::QueuedConnection, Q_ARG(QList<int>, ids), Q_ARG(float, rating));
|
||||
void CollectionBackend::UpdateSongsRatingAsync(const QList<int>& ids, const double rating) {
|
||||
metaObject()->invokeMethod(this, "UpdateSongsRating", Qt::QueuedConnection, Q_ARG(QList<int>, ids), Q_ARG(double, rating));
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -193,8 +193,8 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
|
||||
void AddOrUpdateSongsAsync(const SongList &songs);
|
||||
|
||||
void UpdateSongRatingAsync(const int id, const float rating);
|
||||
void UpdateSongsRatingAsync(const QList<int> &ids, const float rating);
|
||||
void UpdateSongRatingAsync(const int id, const double rating);
|
||||
void UpdateSongsRatingAsync(const QList<int> &ids, const double rating);
|
||||
|
||||
public slots:
|
||||
void Exit();
|
||||
@@ -220,8 +220,8 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
void UpdateLastPlayed(const QString &artist, const QString &album, const QString &title, const qint64 lastplayed);
|
||||
void UpdatePlayCount(const QString &artist, const QString &title, const int playcount);
|
||||
|
||||
void UpdateSongRating(const int id, const float rating);
|
||||
void UpdateSongsRating(const QList<int> &id_list, const float rating);
|
||||
void UpdateSongRating(const int id, const double rating);
|
||||
void UpdateSongsRating(const QList<int> &id_list, const double rating);
|
||||
|
||||
signals:
|
||||
void DirectoryDiscovered(Directory, SubdirectoryList);
|
||||
|
||||
@@ -303,7 +303,8 @@ void CollectionFilterWidget::SetCollectionModel(CollectionModel *model) {
|
||||
QObject::disconnect(model_, nullptr, this, nullptr);
|
||||
QObject::disconnect(model_, nullptr, group_by_dialog_.get(), nullptr);
|
||||
QObject::disconnect(group_by_dialog_.get(), nullptr, model_, nullptr);
|
||||
for (QAction *action : filter_ages_.keys()) {
|
||||
QList<QAction*> filter_ages = filter_ages_.keys();
|
||||
for (QAction *action : filter_ages) {
|
||||
QObject::disconnect(action, &QAction::triggered, model_, nullptr);
|
||||
}
|
||||
}
|
||||
@@ -315,7 +316,8 @@ void CollectionFilterWidget::SetCollectionModel(CollectionModel *model) {
|
||||
QObject::connect(model_, &CollectionModel::GroupingChanged, this, &CollectionFilterWidget::GroupingChanged);
|
||||
QObject::connect(group_by_dialog_.get(), &GroupByDialog::Accepted, model_, &CollectionModel::SetGroupBy);
|
||||
|
||||
for (QAction *action : filter_ages_.keys()) {
|
||||
QList<QAction*> filter_ages = filter_ages_.keys();
|
||||
for (QAction *action : filter_ages) {
|
||||
int age = filter_ages_[action];
|
||||
QObject::connect(action, &QAction::triggered, [this, age]() { model_->SetFilterAge(age); } );
|
||||
}
|
||||
@@ -382,7 +384,9 @@ void CollectionFilterWidget::CheckCurrentGrouping(const CollectionModel::Groupin
|
||||
}
|
||||
|
||||
// Check the advanced action
|
||||
group_by_group_->actions().last()->setChecked(true);
|
||||
QList<QAction*> actions = group_by_group_->actions();
|
||||
QAction *action = actions.last();
|
||||
action->setChecked(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -103,6 +103,7 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
||||
group_by_[2] = GroupBy_None;
|
||||
|
||||
cover_loader_options_.get_image_data_ = false;
|
||||
cover_loader_options_.get_image_ = true;
|
||||
cover_loader_options_.scale_output_image_ = true;
|
||||
cover_loader_options_.pad_output_image_ = true;
|
||||
cover_loader_options_.desired_height_ = kPrettyCoverSize;
|
||||
@@ -113,7 +114,8 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
||||
|
||||
QIcon nocover = IconLoader::Load("cdcase");
|
||||
if (!nocover.isNull()) {
|
||||
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QList<QSize> nocover_sizes = nocover.availableSizes();
|
||||
no_cover_icon_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
if (app_ && !sIconCache) {
|
||||
@@ -184,7 +186,7 @@ void CollectionModel::ReloadSettings() {
|
||||
|
||||
use_disk_cache_ = s.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool();
|
||||
|
||||
QPixmapCache::setCacheLimit(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024);
|
||||
QPixmapCache::setCacheLimit(static_cast<int>(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024));
|
||||
|
||||
if (sIconCache) {
|
||||
sIconCache->setMaximumCacheSize(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit, CollectionSettingsPage::kSettingsDiskCacheSizeDefault));
|
||||
@@ -381,10 +383,10 @@ QString CollectionModel::ContainerKey(const GroupBy type, const Song &song) cons
|
||||
}
|
||||
else {
|
||||
if (song.bitdepth() <= 0) {
|
||||
key = QString("%1 (%2)").arg(song.TextForFiletype()).arg(QString::number(song.samplerate() / 1000.0, 'G', 5));
|
||||
key = QString("%1 (%2)").arg(song.TextForFiletype(), QString::number(song.samplerate() / 1000.0, 'G', 5));
|
||||
}
|
||||
else {
|
||||
key = QString("%1 (%2/%3)").arg(song.TextForFiletype()).arg(QString::number(song.samplerate() / 1000.0, 'G', 5)).arg(song.bitdepth());
|
||||
key = QString("%1 (%2/%3)").arg(song.TextForFiletype(), QString::number(song.samplerate() / 1000.0, 'G', 5)).arg(song.bitdepth());
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -420,7 +422,8 @@ QString CollectionModel::DividerKey(const GroupBy type, CollectionItem *item) co
|
||||
if (c.isDigit()) return "0";
|
||||
if (c == ' ') return QString();
|
||||
if (c.decompositionTag() != QChar::NoDecomposition) {
|
||||
return QChar(c.decomposition()[0]);
|
||||
QString decomposition = c.decomposition();
|
||||
return QChar(decomposition[0]);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
@@ -586,12 +589,13 @@ void CollectionModel::SongsDeleted(const SongList &songs) {
|
||||
}
|
||||
|
||||
// Delete empty dividers
|
||||
for (const QString ÷r_key : divider_keys) {
|
||||
for (const QString ÷r_key : qAsConst(divider_keys)) {
|
||||
if (!divider_nodes_.contains(divider_key)) continue;
|
||||
|
||||
// Look to see if there are any other items still under this divider
|
||||
bool found = false;
|
||||
for (CollectionItem *node : container_nodes_[0].values()) {
|
||||
QList<CollectionItem*> container_nodes = container_nodes_[0].values();
|
||||
for (CollectionItem *node : container_nodes) {
|
||||
if (DividerKey(group_by_[0], node) == divider_key) {
|
||||
found = true;
|
||||
break;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -195,6 +195,9 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||
|
||||
void ExpandAll(CollectionItem *item = nullptr) const;
|
||||
|
||||
const CollectionModel::Grouping &GetGroupBy() const { return group_by_; }
|
||||
void SetGroupBy(const CollectionModel::Grouping &g);
|
||||
|
||||
signals:
|
||||
void TotalSongCountUpdated(int count);
|
||||
void TotalArtistCountUpdated(int count);
|
||||
@@ -206,8 +209,6 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||
void SetFilterText(const QString &text);
|
||||
void SetFilterQueryMode(QueryOptions::QueryMode query_mode);
|
||||
|
||||
void SetGroupBy(const CollectionModel::Grouping &g);
|
||||
const CollectionModel::Grouping &GetGroupBy() const { return group_by_; }
|
||||
void Init(const bool async = true);
|
||||
void Reset();
|
||||
void ResetAsync();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -91,7 +92,7 @@ CollectionQuery::CollectionQuery(const QueryOptions &options)
|
||||
}
|
||||
|
||||
if (options.max_age() != -1) {
|
||||
int cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - options.max_age();
|
||||
qint64 cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - options.max_age();
|
||||
|
||||
where_clauses_ << "ctime > ?";
|
||||
bound_values_ << cutoff;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -197,15 +198,15 @@ bool CollectionView::RestoreLevelFocus(const QModelIndex &parent) {
|
||||
case CollectionItem::Type_Divider: {
|
||||
QString text = model()->data(current, CollectionModel::Role_SortText).toString();
|
||||
if (!last_selected_container_.isEmpty() && last_selected_container_ == text) {
|
||||
emit expand(current);
|
||||
expand(current);
|
||||
setCurrentIndex(current);
|
||||
return true;
|
||||
}
|
||||
else if (last_selected_path_.contains(text)) {
|
||||
emit expand(current);
|
||||
expand(current);
|
||||
// If a selected container or song were not found, we've got into a wrong subtree (happens with "unknown" all the time)
|
||||
if (!RestoreLevelFocus(current)) {
|
||||
emit collapse(current);
|
||||
collapse(current);
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
@@ -462,7 +463,8 @@ void CollectionView::SetShowInVarious(const bool on) {
|
||||
// If we have only one album and we are putting it into Various Artists, check to see
|
||||
// if there are other Artists in this album and prompt the user if they'd like them moved, too
|
||||
if (on && albums.keys().count() == 1) {
|
||||
const QString album = albums.keys().first();
|
||||
const QStringList albums_list = albums.keys();
|
||||
const QString album = albums_list.first();
|
||||
QList<Song> all_of_album = app_->collection_backend()->GetSongsByAlbum(album);
|
||||
QSet<QString> other_artists;
|
||||
for (const Song &s : all_of_album) {
|
||||
@@ -480,10 +482,11 @@ void CollectionView::SetShowInVarious(const bool on) {
|
||||
}
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
||||
for (const QString &album : QSet<QString>(albums.keyBegin(), albums.keyEnd())) {
|
||||
QSet<QString> albums_set = QSet<QString>(albums.keyBegin(), albums.keyEnd());
|
||||
#else
|
||||
for (const QString &album : QSet<QString>::fromList(albums.keys())) {
|
||||
QSet<QString> albums_set = QSet<QString>::fromList(albums.keys());
|
||||
#endif
|
||||
for (const QString &album : albums_set) {
|
||||
app_->collection_backend()->ForceCompilation(album, albums.values(album), on);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -110,6 +110,45 @@ void CollectionWatcher::Exit() {
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::ReloadSettingsAsync() {
|
||||
|
||||
QMetaObject::invokeMethod(this, "ReloadSettings", Qt::QueuedConnection);
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::ReloadSettings() {
|
||||
|
||||
const bool was_monitoring_before = monitor_;
|
||||
QSettings s;
|
||||
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
scan_on_startup_ = s.value("startup_scan", true).toBool();
|
||||
monitor_ = s.value("monitor", true).toBool();
|
||||
mark_songs_unavailable_ = s.value("mark_songs_unavailable", false).toBool();
|
||||
QStringList filters = s.value("cover_art_patterns", QStringList() << "front" << "cover").toStringList();
|
||||
s.endGroup();
|
||||
|
||||
best_image_filters_.clear();
|
||||
for (const QString &filter : filters) {
|
||||
QString str = filter.trimmed();
|
||||
if (!str.isEmpty()) best_image_filters_ << str;
|
||||
}
|
||||
|
||||
if (!monitor_ && was_monitoring_before) {
|
||||
fs_watcher_->Clear();
|
||||
}
|
||||
else if (monitor_ && !was_monitoring_before) {
|
||||
// Add all directories to all QFileSystemWatchers again
|
||||
QList<Directory> dirs = watched_dirs_.values();
|
||||
for (const Directory &dir : dirs) {
|
||||
SubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id);
|
||||
for (const Subdirectory &subdir : subdirs) {
|
||||
AddWatch(dir, subdir.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CollectionWatcher::ScanTransaction::ScanTransaction(CollectionWatcher *watcher, const int dir, const bool incremental, const bool ignores_mtime, const bool mark_songs_unavailable)
|
||||
: progress_(0),
|
||||
progress_max_(0),
|
||||
@@ -119,15 +158,16 @@ CollectionWatcher::ScanTransaction::ScanTransaction(CollectionWatcher *watcher,
|
||||
mark_songs_unavailable_(mark_songs_unavailable),
|
||||
watcher_(watcher),
|
||||
cached_songs_dirty_(true),
|
||||
known_subdirs_dirty_(true)
|
||||
{
|
||||
known_subdirs_dirty_(true) {
|
||||
|
||||
QString description;
|
||||
|
||||
if (watcher_->device_name_.isEmpty())
|
||||
if (watcher_->device_name_.isEmpty()) {
|
||||
description = tr("Updating collection");
|
||||
else
|
||||
}
|
||||
else {
|
||||
description = tr("Updating %1").arg(watcher_->device_name_);
|
||||
}
|
||||
|
||||
task_id_ = watcher_->task_manager_->StartTask(description);
|
||||
emit watcher_->ScanStarted(task_id_);
|
||||
@@ -310,7 +350,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
// Do not scan symlinked dirs that are already in collection
|
||||
if (path_info.isSymLink()) {
|
||||
QString real_path = path_info.symLinkTarget();
|
||||
for (const Directory &dir : watched_dirs_) {
|
||||
for (const Directory &dir : qAsConst(watched_dirs_)) {
|
||||
if (real_path.startsWith(dir.path)) {
|
||||
t->AddToProgress(1);
|
||||
return;
|
||||
@@ -347,6 +387,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
// First we "quickly" get a list of the files in the directory that we think might be music. While we're here, we also look for new subdirectories and possible album artwork.
|
||||
QDirIterator it(path, QDir::Dirs | QDir::Files | QDir::Hidden | QDir::NoDotAndDotDot);
|
||||
while (it.hasNext()) {
|
||||
|
||||
if (stop_requested_) return;
|
||||
|
||||
QString child(it.next());
|
||||
@@ -384,7 +425,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
for (const QString &file : files_on_disk) {
|
||||
if (stop_requested_) return;
|
||||
|
||||
// associated cue
|
||||
// Associated cue
|
||||
QString matching_cue = NoExtensionPart(file) + ".cue";
|
||||
|
||||
Song matching_song(source_);
|
||||
@@ -401,14 +442,14 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
continue;
|
||||
}
|
||||
|
||||
// cue sheet's path from collection (if any)
|
||||
// CUE sheet's path from collection (if any)
|
||||
QString song_cue = matching_song.cue_path();
|
||||
qint64 song_cue_mtime = GetMtimeForCue(song_cue);
|
||||
|
||||
bool cue_deleted = song_cue_mtime == 0 && matching_song.has_cue();
|
||||
bool cue_added = matching_cue_mtime != 0 && !matching_song.has_cue();
|
||||
|
||||
// watch out for cue songs which have their mtime equal to qMax(media_file_mtime, cue_sheet_mtime)
|
||||
// Watch out for CUE songs which have their mtime equal to qMax(media_file_mtime, cue_sheet_mtime)
|
||||
bool changed = (matching_song.mtime() != qMax(file_info.lastModified().toSecsSinceEpoch(), song_cue_mtime)) || cue_deleted || cue_added;
|
||||
|
||||
// Also want to look to see whether the album art has changed
|
||||
@@ -417,16 +458,14 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
changed = true;
|
||||
}
|
||||
|
||||
// the song's changed - reread the metadata from file
|
||||
// The song's changed - reread the metadata from file
|
||||
if (t->ignores_mtime() || changed) {
|
||||
qLog(Debug) << file << "changed";
|
||||
|
||||
// if cue associated...
|
||||
if (!cue_deleted && (matching_song.has_cue() || cue_added)) {
|
||||
if (!cue_deleted && (matching_song.has_cue() || cue_added)) { // If CUE associated.
|
||||
UpdateCueAssociatedSongs(file, path, matching_cue, image, t);
|
||||
// if no cue or it's about to lose it...
|
||||
}
|
||||
else {
|
||||
else { // If no CUE or it's about to lose it.
|
||||
UpdateNonCueAssociatedSong(file, matching_song, image, cue_deleted, t);
|
||||
}
|
||||
}
|
||||
@@ -444,7 +483,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
||||
}
|
||||
|
||||
qLog(Debug) << file << "created";
|
||||
// choose an image for the song(s)
|
||||
// Choose an image for the song(s)
|
||||
QUrl image = ImageForSong(file, album_art);
|
||||
|
||||
for (Song song : song_list) {
|
||||
@@ -509,7 +548,7 @@ void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QStr
|
||||
cue_song.set_directory_id(t->dir());
|
||||
|
||||
Song matching = sections_map[cue_song.beginning_nanosec()];
|
||||
// a new section
|
||||
// A new section
|
||||
if (!matching.is_valid()) {
|
||||
t->new_songs << cue_song;
|
||||
// changed section
|
||||
@@ -520,7 +559,7 @@ void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QStr
|
||||
}
|
||||
}
|
||||
|
||||
// sections that are now missing
|
||||
// Sections that are now missing
|
||||
for (const Song &matching : old_sections) {
|
||||
if (!used_ids.contains(matching.id())) {
|
||||
t->deleted_songs << matching;
|
||||
@@ -531,7 +570,7 @@ void CollectionWatcher::UpdateCueAssociatedSongs(const QString &file, const QStr
|
||||
|
||||
void CollectionWatcher::UpdateNonCueAssociatedSong(const QString &file, const Song &matching_song, const QUrl &image, bool cue_deleted, ScanTransaction *t) {
|
||||
|
||||
// If a cue got deleted, we turn it's first section into the new 'raw' (cueless) song and we just remove the rest of the sections from the collection
|
||||
// If a CUE got deleted, we turn it's first section into the new 'raw' (cueless) song and we just remove the rest of the sections from the collection
|
||||
if (cue_deleted) {
|
||||
for (const Song &song : backend_->GetSongsByUrl(QUrl::fromLocalFile(file))) {
|
||||
if (!song.IsMetadataAndArtEqual(matching_song)) {
|
||||
@@ -555,9 +594,8 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
||||
SongList song_list;
|
||||
|
||||
quint64 matching_cue_mtime = GetMtimeForCue(matching_cue);
|
||||
// If it's a cue - create virtual tracks
|
||||
if (matching_cue_mtime) {
|
||||
// don't process the same cue many times
|
||||
if (matching_cue_mtime) { // If it's a CUE - create virtual tracks
|
||||
// Don't process the same cue many times
|
||||
if (cues_processed->contains(matching_cue)) return song_list;
|
||||
|
||||
QFile cue(matching_cue);
|
||||
@@ -580,9 +618,8 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
||||
*cues_processed << matching_cue;
|
||||
}
|
||||
|
||||
// it's a normal media file
|
||||
}
|
||||
else {
|
||||
else { // It's a normal media file
|
||||
Song song(source_);
|
||||
TagReaderClient::Instance()->ReadFileBlocking(file, &song);
|
||||
if (song.is_valid()) {
|
||||
@@ -653,7 +690,8 @@ void CollectionWatcher::AddWatch(const Directory &dir, const QString &path) {
|
||||
|
||||
void CollectionWatcher::RemoveWatch(const Directory &dir, const Subdirectory &subdir) {
|
||||
|
||||
for (const QString &subdir_path : subdir_mapping_.keys(dir)) {
|
||||
QStringList subdir_paths = subdir_mapping_.keys(dir);
|
||||
for (const QString &subdir_path : subdir_paths) {
|
||||
if (subdir_path != subdir.path) continue;
|
||||
fs_watcher_->RemovePath(subdir_path);
|
||||
subdir_mapping_.remove(subdir_path);
|
||||
@@ -668,7 +706,8 @@ void CollectionWatcher::RemoveDirectory(const Directory &dir) {
|
||||
watched_dirs_.remove(dir.id);
|
||||
|
||||
// Stop watching the directory's subdirectories
|
||||
for (const QString &subdir_path : subdir_mapping_.keys(dir)) {
|
||||
QStringList subdir_paths = subdir_mapping_.keys(dir);
|
||||
for (const QString &subdir_path : subdir_paths) {
|
||||
fs_watcher_->RemovePath(subdir_path);
|
||||
subdir_mapping_.remove(subdir_path);
|
||||
}
|
||||
@@ -708,7 +747,8 @@ void CollectionWatcher::DirectoryChanged(const QString &subdir) {
|
||||
|
||||
void CollectionWatcher::RescanPathsNow() {
|
||||
|
||||
for (int dir : rescan_queue_.keys()) {
|
||||
QList<int> dirs = rescan_queue_.keys();
|
||||
for (const int dir : dirs) {
|
||||
if (stop_requested_) break;
|
||||
ScanTransaction transaction(this, dir, false, false, mark_songs_unavailable_);
|
||||
transaction.AddToProgressMax(rescan_queue_[dir].count());
|
||||
@@ -793,44 +833,6 @@ QUrl CollectionWatcher::ImageForSong(const QString &path, QMap<QString, QStringL
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::ReloadSettingsAsync() {
|
||||
|
||||
QMetaObject::invokeMethod(this, "ReloadSettings", Qt::QueuedConnection);
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::ReloadSettings() {
|
||||
|
||||
const bool was_monitoring_before = monitor_;
|
||||
QSettings s;
|
||||
s.beginGroup(CollectionSettingsPage::kSettingsGroup);
|
||||
scan_on_startup_ = s.value("startup_scan", true).toBool();
|
||||
monitor_ = s.value("monitor", true).toBool();
|
||||
mark_songs_unavailable_ = s.value("mark_songs_unavailable", false).toBool();
|
||||
QStringList filters = s.value("cover_art_patterns", QStringList() << "front" << "cover").toStringList();
|
||||
s.endGroup();
|
||||
|
||||
best_image_filters_.clear();
|
||||
for (const QString &filter : filters) {
|
||||
QString str = filter.trimmed();
|
||||
if (!str.isEmpty()) best_image_filters_ << str;
|
||||
}
|
||||
|
||||
if (!monitor_ && was_monitoring_before) {
|
||||
fs_watcher_->Clear();
|
||||
}
|
||||
else if (monitor_ && !was_monitoring_before) {
|
||||
// Add all directories to all QFileSystemWatchers again
|
||||
for (const Directory &dir : watched_dirs_.values()) {
|
||||
SubdirectoryList subdirs = backend_->SubdirsInDirectory(dir.id);
|
||||
for (const Subdirectory &subdir : subdirs) {
|
||||
AddWatch(dir, subdir.path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CollectionWatcher::SetRescanPausedAsync(bool pause) {
|
||||
|
||||
QMetaObject::invokeMethod(this, "SetRescanPaused", Qt::QueuedConnection, Q_ARG(bool, pause));
|
||||
@@ -902,7 +904,8 @@ void CollectionWatcher::PerformScan(bool incremental, bool ignore_mtimes) {
|
||||
|
||||
stop_requested_ = false;
|
||||
|
||||
for (const Directory &dir : watched_dirs_.values()) {
|
||||
QList<Directory> dirs = watched_dirs_.values();
|
||||
for (const Directory &dir : dirs) {
|
||||
|
||||
if (stop_requested_) break;
|
||||
ScanTransaction transaction(this, dir.id, incremental, ignore_mtimes, mark_songs_unavailable_);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -155,7 +155,7 @@ class CollectionWatcher : public QObject {
|
||||
void FullScanNow();
|
||||
void RescanTracksNow();
|
||||
void RescanPathsNow();
|
||||
void ScanSubdirectory(const QString &path, const Subdirectory &subdir, ScanTransaction *t, bool force_noincremental = false);
|
||||
void ScanSubdirectory(const QString &path, const Subdirectory &subdir, CollectionWatcher::ScanTransaction *t, bool force_noincremental = false);
|
||||
|
||||
private:
|
||||
static bool FindSongByPath(const SongList &list, const QString &path, Song *out);
|
||||
@@ -228,4 +228,3 @@ inline QString CollectionWatcher::DirectoryPart(const QString& fileName) {
|
||||
}
|
||||
|
||||
#endif // COLLECTIONWATCHER_H
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2015, Nick Lanham <nick@afternight.org>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2015, Nick Lanham <nick@afternight.org>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.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 CONFIG_H_IN
|
||||
#define CONFIG_H_IN
|
||||
|
||||
@@ -24,7 +5,6 @@
|
||||
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||
#define CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}"
|
||||
|
||||
#cmakedefine DEBUG
|
||||
#cmakedefine HAVE_BACKTRACE
|
||||
#cmakedefine HAVE_GIO
|
||||
#cmakedefine HAVE_DBUS
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2020-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2020-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This code was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -75,7 +75,8 @@ ContextAlbumsModel::ContextAlbumsModel(CollectionBackend *backend, Application *
|
||||
QObject::connect(app_->album_cover_loader(), &AlbumCoverLoader::AlbumCoverLoaded, this, &ContextAlbumsModel::AlbumCoverLoaded);
|
||||
|
||||
QIcon nocover = IconLoader::Load("cdcase");
|
||||
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QList<QSize> nocover_sizes = nocover.availableSizes();
|
||||
no_cover_icon_ = nocover.pixmap(nocover_sizes.last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This code was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This code was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This code was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2012, 2014, John Maguire <john.maguire@gmail.com>
|
||||
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2012, 2014, John Maguire <john.maguire@gmail.com>
|
||||
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -184,7 +184,8 @@ QSqlDatabase Database::Connect() {
|
||||
}
|
||||
|
||||
// Attach external databases
|
||||
for (const QString &key : attached_databases_.keys()) {
|
||||
QStringList keys = attached_databases_.keys();
|
||||
for (const QString &key : keys) {
|
||||
QString filename = attached_databases_[key].filename_;
|
||||
|
||||
if (!injected_database_name_.isNull()) filename = injected_database_name_;
|
||||
@@ -204,7 +205,8 @@ QSqlDatabase Database::Connect() {
|
||||
}
|
||||
|
||||
// We might have to initialize the schema in some attached databases now, if they were deleted and don't match up with the main schema version.
|
||||
for (const QString &key : attached_databases_.keys()) {
|
||||
keys = attached_databases_.keys();
|
||||
for (const QString &key : keys) {
|
||||
if (attached_databases_[key].is_temporary_ && attached_databases_[key].schema_.isEmpty())
|
||||
continue;
|
||||
// Find out if there are any tables in this database
|
||||
@@ -453,7 +455,8 @@ QStringList Database::SongsTables(QSqlDatabase &db, int schema_version) const {
|
||||
}
|
||||
|
||||
// look for the tables in attached dbs
|
||||
for (const QString &key : attached_databases_.keys()) {
|
||||
QStringList keys = attached_databases_.keys();
|
||||
for (const QString &key : keys) {
|
||||
QSqlQuery q(db);
|
||||
q.prepare(QString("SELECT NAME FROM %1.sqlite_master WHERE type='table' AND name='songs' OR name LIKE '%songs'").arg(key));
|
||||
if (q.exec()) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2013, 2017-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013, 2017-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -75,7 +75,7 @@ QIcon IconLoader::Load(const QString &name, const int fixed_size, const int min_
|
||||
if (icon_prop.allow_system_icon) {
|
||||
ret = QIcon::fromTheme(name);
|
||||
if (ret.isNull()) {
|
||||
for (QString alt_name : icon_prop.names) {
|
||||
for (const QString &alt_name : icon_prop.names) {
|
||||
ret = QIcon::fromTheme(alt_name);
|
||||
if (!ret.isNull()) break;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2013, 2017-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013, 2017-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2011, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Strawberry Music Player
|
||||
* Copyright 2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2012, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
*Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -1599,11 +1599,11 @@ void MainWindow::FilePathChanged(const QString &path) {
|
||||
settings_.setValue("file_path", path);
|
||||
}
|
||||
|
||||
void MainWindow::Seeked(const qlonglong microseconds) {
|
||||
void MainWindow::Seeked(const qint64 microseconds) {
|
||||
|
||||
const int position = microseconds / kUsecPerSec;
|
||||
const int length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec;
|
||||
if (tray_icon_) tray_icon_->SetProgress(double(position) / length * 100);
|
||||
const qint64 position = microseconds / kUsecPerSec;
|
||||
const qint64 length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec;
|
||||
if (tray_icon_) tray_icon_->SetProgress(static_cast<int>(double(position) / length * 100));
|
||||
|
||||
}
|
||||
|
||||
@@ -1612,18 +1612,18 @@ void MainWindow::UpdateTrackPosition() {
|
||||
PlaylistItemPtr item(app_->player()->GetCurrentItem());
|
||||
if (!item) return;
|
||||
|
||||
const int length = (item->Metadata().length_nanosec() / kNsecPerSec);
|
||||
const qint64 length = (item->Metadata().length_nanosec() / kNsecPerSec);
|
||||
if (length <= 0) return;
|
||||
const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5);
|
||||
|
||||
// Update the tray icon every 10 seconds
|
||||
if (tray_icon_ && position % 10 == 0) tray_icon_->SetProgress(double(position) / length * 100);
|
||||
if (tray_icon_ && position % 10 == 0) tray_icon_->SetProgress(static_cast<int>(double(position) / length * 100));
|
||||
|
||||
// Send Scrobble
|
||||
if (app_->scrobbler()->IsEnabled() && item->Metadata().is_metadata_good()) {
|
||||
Playlist *playlist = app_->playlist_manager()->active();
|
||||
if (playlist && !playlist->scrobbled()) {
|
||||
const int scrobble_point = (playlist->scrobble_point_nanosec() / kNsecPerSec);
|
||||
const qint64 scrobble_point = (playlist->scrobble_point_nanosec() / kNsecPerSec);
|
||||
if (position >= scrobble_point) {
|
||||
app_->scrobbler()->Scrobble(item->Metadata(), scrobble_point);
|
||||
playlist->set_scrobbled(true);
|
||||
@@ -1637,8 +1637,8 @@ void MainWindow::UpdateTrackSliderPosition() {
|
||||
|
||||
PlaylistItemPtr item(app_->player()->GetCurrentItem());
|
||||
|
||||
const int slider_position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerMsec);
|
||||
const int slider_length = app_->player()->engine()->length_nanosec() / kNsecPerMsec;
|
||||
const qint64 slider_position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerMsec);
|
||||
const qint64 slider_length = app_->player()->engine()->length_nanosec() / kNsecPerMsec;
|
||||
|
||||
// Update the slider
|
||||
ui_->track_slider->SetValue(slider_position, slider_length);
|
||||
@@ -1913,7 +1913,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
||||
QString column_value = app_->playlist_manager()->current()->data(source_index).toString();
|
||||
if (column_value.length() > 25) column_value = column_value.left(25) + "...";
|
||||
|
||||
ui_->action_selection_set_value->setText(tr("Set %1 to \"%2\"...").arg(column_name.toLower()).arg(column_value));
|
||||
ui_->action_selection_set_value->setText(tr("Set %1 to \"%2\"...").arg(column_name.toLower(), column_value));
|
||||
ui_->action_edit_value->setText(tr("Edit tag \"%1\"...").arg(column_name));
|
||||
|
||||
// Is it a collection item?
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2013-2020, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2013-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -200,7 +200,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
||||
void ToggleShowHide();
|
||||
void ToggleHide();
|
||||
|
||||
void Seeked(const qlonglong microseconds);
|
||||
void Seeked(const qint64 microseconds);
|
||||
void UpdateTrackPosition();
|
||||
void UpdateTrackSliderPosition();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -417,7 +418,8 @@ QStringList MergedProxyModel::mimeTypes() const {
|
||||
QStringList ret;
|
||||
ret << sourceModel()->mimeTypes();
|
||||
|
||||
for (const QAbstractItemModel *model : merge_points_.keys()) {
|
||||
QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
for (const QAbstractItemModel *model : models) {
|
||||
ret << model->mimeTypes();
|
||||
}
|
||||
|
||||
@@ -494,7 +496,8 @@ QAbstractItemModel *MergedProxyModel::GetModel(const QModelIndex &source_index)
|
||||
// This is essentially const_cast<QAbstractItemModel*>(source_index.model()), but without the const_cast
|
||||
const QAbstractItemModel *const_model = source_index.model();
|
||||
if (const_model == sourceModel()) return sourceModel();
|
||||
for (QAbstractItemModel *submodel : merge_points_.keys()) {
|
||||
QList<QAbstractItemModel*> submodels = merge_points_.keys();
|
||||
for (QAbstractItemModel *submodel : submodels) {
|
||||
if (submodel == const_model) return submodel;
|
||||
}
|
||||
return nullptr;
|
||||
@@ -508,19 +511,21 @@ void MergedProxyModel::DataChanged(const QModelIndex &top_left, const QModelInde
|
||||
void MergedProxyModel::LayoutAboutToBeChanged() {
|
||||
|
||||
old_merge_points_.clear();
|
||||
for (QAbstractItemModel *key : merge_points_.keys()) {
|
||||
old_merge_points_[key] = merge_points_.value(key);
|
||||
QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
for (QAbstractItemModel *model : models) {
|
||||
old_merge_points_[model] = merge_points_.value(model);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MergedProxyModel::LayoutChanged() {
|
||||
|
||||
for (QAbstractItemModel *key : merge_points_.keys()) {
|
||||
if (!old_merge_points_.contains(key)) continue;
|
||||
QList<QAbstractItemModel*> models = merge_points_.keys();
|
||||
for (QAbstractItemModel *model : models) {
|
||||
if (!old_merge_points_.contains(model)) continue;
|
||||
|
||||
const int old_row = old_merge_points_[key].row();
|
||||
const int new_row = merge_points_[key].row();
|
||||
const int old_row = old_merge_points_[model].row();
|
||||
const int new_row = merge_points_[model].row();
|
||||
|
||||
if (old_row != new_row) {
|
||||
beginResetModel();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2019-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -411,9 +412,9 @@ void Mpris2::AlbumCoverLoaded(const Song &song, const AlbumCoverLoaderResult &re
|
||||
|
||||
double Mpris2::Volume() const { return app_->player()->GetVolume() / 100.0; }
|
||||
|
||||
void Mpris2::SetVolume(double value) { app_->player()->SetVolume(value * 100); }
|
||||
void Mpris2::SetVolume(double value) { app_->player()->SetVolume(static_cast<int>(value * 100)); }
|
||||
|
||||
qlonglong Mpris2::Position() const {
|
||||
qint64 Mpris2::Position() const {
|
||||
return app_->player()->engine()->position_nanosec() / kNsecPerUsec;
|
||||
}
|
||||
|
||||
@@ -478,13 +479,16 @@ void Mpris2::Play() {
|
||||
}
|
||||
}
|
||||
|
||||
void Mpris2::Seek(qlonglong offset) {
|
||||
void Mpris2::Seek(qint64 offset) {
|
||||
|
||||
if (CanSeek()) {
|
||||
app_->player()->SeekTo(app_->player()->engine()->position_nanosec() / kNsecPerSec + offset / kUsecPerSec);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Mpris2::SetPosition(const QDBusObjectPath &trackId, qlonglong offset) {
|
||||
void Mpris2::SetPosition(const QDBusObjectPath &trackId, qint64 offset) {
|
||||
|
||||
if (CanSeek() && trackId.path() == current_track_id() && offset >= 0) {
|
||||
offset *= kNsecPerUsec;
|
||||
|
||||
@@ -492,6 +496,7 @@ void Mpris2::SetPosition(const QDBusObjectPath &trackId, qlonglong offset) {
|
||||
app_->player()->SeekTo(offset / kNsecPerSec);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Mpris2::OpenUri(const QString &uri) {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -97,7 +98,7 @@ class Mpris2 : public QObject {
|
||||
Q_PROPERTY(bool Shuffle READ Shuffle WRITE SetShuffle)
|
||||
Q_PROPERTY(QVariantMap Metadata READ Metadata)
|
||||
Q_PROPERTY(double Volume READ Volume WRITE SetVolume)
|
||||
Q_PROPERTY(qlonglong Position READ Position)
|
||||
Q_PROPERTY(qint64 Position READ Position)
|
||||
Q_PROPERTY(double MinimumRate READ MinimumRate)
|
||||
Q_PROPERTY(double MaximumRate READ MaximumRate)
|
||||
Q_PROPERTY(bool CanGoNext READ CanGoNext)
|
||||
@@ -145,7 +146,7 @@ class Mpris2 : public QObject {
|
||||
QVariantMap Metadata() const;
|
||||
double Volume() const;
|
||||
void SetVolume(double value);
|
||||
qlonglong Position() const;
|
||||
qint64 Position() const;
|
||||
double MaximumRate() const;
|
||||
double MinimumRate() const;
|
||||
bool CanGoNext() const;
|
||||
@@ -162,8 +163,8 @@ class Mpris2 : public QObject {
|
||||
void PlayPause();
|
||||
void Stop();
|
||||
void Play();
|
||||
void Seek(qlonglong offset);
|
||||
void SetPosition(const QDBusObjectPath &trackId, qlonglong offset);
|
||||
void Seek(qint64 offset);
|
||||
void SetPosition(const QDBusObjectPath &trackId, qint64 offset);
|
||||
void OpenUri(const QString &uri);
|
||||
|
||||
// TrackList Properties
|
||||
@@ -187,7 +188,7 @@ class Mpris2 : public QObject {
|
||||
|
||||
signals:
|
||||
// Player
|
||||
void Seeked(qlonglong position);
|
||||
void Seeked(qint64 position);
|
||||
|
||||
// TrackList
|
||||
void TrackListReplaced(Track_Ids Tracks, QDBusObjectPath CurrentTrack);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -633,7 +633,7 @@ void Player::CurrentMetadataChanged(const Song &metadata) {
|
||||
|
||||
}
|
||||
|
||||
void Player::SeekTo(const int seconds) {
|
||||
void Player::SeekTo(const qint64 seconds) {
|
||||
|
||||
const qint64 length_nanosec = engine_->length_nanosec();
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -87,7 +87,7 @@ class PlayerInterface : public QObject {
|
||||
virtual void SetVolume(const int value) = 0;
|
||||
virtual void VolumeUp() = 0;
|
||||
virtual void VolumeDown() = 0;
|
||||
virtual void SeekTo(const int seconds) = 0;
|
||||
virtual void SeekTo(const qint64 seconds) = 0;
|
||||
// Moves the position of the currently playing song five seconds forward.
|
||||
virtual void SeekForward() = 0;
|
||||
// Moves the position of the currently playing song five seconds backwards.
|
||||
@@ -113,7 +113,7 @@ class PlayerInterface : public QObject {
|
||||
void VolumeChanged(int volume);
|
||||
void TrackSkipped(PlaylistItemPtr old_track);
|
||||
// Emitted when there's a manual change to the current's track position.
|
||||
void Seeked(qlonglong microseconds);
|
||||
void Seeked(qint64 microseconds);
|
||||
|
||||
// Emitted when Player has processed a request to play another song.
|
||||
// This contains the URL of the song and a flag saying whether it was able to play the song.
|
||||
@@ -168,7 +168,7 @@ class Player : public PlayerInterface {
|
||||
void SetVolume(const int value) override;
|
||||
void VolumeUp() override { SetVolume(GetVolume() + 5); }
|
||||
void VolumeDown() override { SetVolume(GetVolume() - 5); }
|
||||
void SeekTo(const int seconds) override;
|
||||
void SeekTo(const qint64 seconds) override;
|
||||
void SeekForward() override;
|
||||
void SeekBackward() override;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -60,7 +61,7 @@ QtSystemTrayIcon::QtSystemTrayIcon(QObject *parent)
|
||||
}
|
||||
tray_->setIcon(normal_icon_);
|
||||
tray_->installEventFilter(this);
|
||||
ClearNowPlaying();
|
||||
QtSystemTrayIcon::ClearNowPlaying();
|
||||
|
||||
QObject::connect(tray_, &QSystemTrayIcon::activated, this, &QtSystemTrayIcon::Clicked);
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -41,7 +41,7 @@ gulong CheckedGConnect(gpointer source, const char *signal, GCallback callback,
|
||||
GSignalQuery query;
|
||||
g_signal_query(signal_id, &query);
|
||||
// The signature for a signal callback is always: return_type callback(gpointer data1, params..., gpointer data2);
|
||||
int signal_params = query.n_params + 2;
|
||||
int signal_params = static_cast<int>(query.n_params) + 2;
|
||||
if (signal_params != callback_param_count) {
|
||||
qFatal("Connecting callback to signal with different parameters counts");
|
||||
return 0;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -152,6 +152,8 @@ const QString Song::kVariousArtists("various artists");
|
||||
|
||||
const QStringList Song::kArticles = QStringList() << "the " << "a " << "an ";
|
||||
|
||||
const QStringList Song::kAcceptedExtensions = QStringList() << "aac" << "ac3" << "dts";
|
||||
|
||||
struct Song::Private : public QSharedData {
|
||||
|
||||
explicit Private(Source source = Source_Unknown);
|
||||
@@ -202,7 +204,7 @@ struct Song::Private : public QSharedData {
|
||||
|
||||
int playcount_;
|
||||
int skipcount_;
|
||||
int lastplayed_;
|
||||
qint64 lastplayed_;
|
||||
|
||||
bool compilation_detected_; // From the collection scanner
|
||||
bool compilation_on_; // Set by the user
|
||||
@@ -214,7 +216,7 @@ struct Song::Private : public QSharedData {
|
||||
|
||||
QString cue_path_; // If the song has a CUE, this contains it's path.
|
||||
|
||||
float rating_; // Database rating, not read from tags.
|
||||
double rating_; // Database rating, not read from tags.
|
||||
|
||||
QUrl stream_url_; // Temporary stream url set by url handler.
|
||||
QImage image_; // Album Cover image set by album cover loader.
|
||||
@@ -360,7 +362,7 @@ const QImage &Song::image() const { return d->image_; }
|
||||
const QString &Song::cue_path() const { return d->cue_path_; }
|
||||
bool Song::has_cue() const { return !d->cue_path_.isEmpty(); }
|
||||
|
||||
float Song::rating() const { return d->rating_; }
|
||||
double Song::rating() const { return d->rating_; }
|
||||
|
||||
bool Song::is_collection_song() const { return d->source_ == Source_Collection; }
|
||||
bool Song::is_metadata_good() const { return !d->url_.isEmpty() && !d->artist_.isEmpty() && !d->title_.isEmpty(); }
|
||||
@@ -461,7 +463,7 @@ void Song::set_art_automatic(const QUrl &v) { d->art_automatic_ = v; }
|
||||
void Song::set_art_manual(const QUrl &v) { d->art_manual_ = v; }
|
||||
void Song::set_cue_path(const QString &v) { d->cue_path_ = v; }
|
||||
|
||||
void Song::set_rating(float v) { d->rating_ = v; }
|
||||
void Song::set_rating(double v) { d->rating_ = v; }
|
||||
|
||||
void Song::set_stream_url(const QUrl &v) { d->stream_url_ = v; }
|
||||
void Song::set_image(const QImage &i) { d->image_ = i; }
|
||||
@@ -844,7 +846,7 @@ void Song::ToProtobuf(spb::tagreader::SongMetadata *pb) const {
|
||||
#define tostr(n) (q.value(n).isNull() ? QString() : q.value(n).toString())
|
||||
#define toint(n) (q.value(n).isNull() ? -1 : q.value(n).toInt())
|
||||
#define tolonglong(n) (q.value(n).isNull() ? -1 : q.value(n).toLongLong())
|
||||
#define tofloat(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
|
||||
#define todouble(n) (q.value(n).isNull() ? -1 : q.value(n).toDouble())
|
||||
|
||||
void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
|
||||
|
||||
@@ -1013,7 +1015,7 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
|
||||
}
|
||||
|
||||
else if (Song::kColumns.value(i) == "rating") {
|
||||
d->rating_ = tofloat(x);
|
||||
d->rating_ = todouble(x);
|
||||
}
|
||||
|
||||
else {
|
||||
@@ -1029,7 +1031,7 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
|
||||
#undef tostr
|
||||
#undef toint
|
||||
#undef tolonglong
|
||||
#undef tofloat
|
||||
#undef todouble
|
||||
|
||||
}
|
||||
|
||||
@@ -1038,7 +1040,6 @@ void Song::InitFromFilePartial(const QString &filename) {
|
||||
set_url(QUrl::fromLocalFile(filename));
|
||||
QFileInfo info(filename);
|
||||
d->basefilename_ = info.fileName();
|
||||
QString suffix = info.suffix().toLower();
|
||||
|
||||
TagLib::FileRef fileref(filename.toUtf8().constData());
|
||||
if (fileref.file()) {
|
||||
@@ -1046,6 +1047,13 @@ void Song::InitFromFilePartial(const QString &filename) {
|
||||
d->source_ = Source_LocalFile;
|
||||
if (d->art_manual_.isEmpty()) InitArtManual();
|
||||
}
|
||||
else if (kAcceptedExtensions.contains(info.suffix(), Qt::CaseInsensitive)) {
|
||||
d->valid_ = true;
|
||||
d->source_ = Source_LocalFile;
|
||||
d->filetype_ = FiletypeByExtension(info.suffix());
|
||||
d->title_ = info.fileName();
|
||||
if (d->art_manual_.isEmpty()) InitArtManual();
|
||||
}
|
||||
else {
|
||||
d->valid_ = false;
|
||||
d->error_ = QObject::tr("File %1 is not recognized as a valid audio file.").arg(filename);
|
||||
@@ -1458,7 +1466,7 @@ QString Song::TitleWithCompilationArtist() const {
|
||||
|
||||
if (title.isEmpty()) title = d->basefilename_;
|
||||
|
||||
if (is_compilation() && !d->artist_.isEmpty() && !d->artist_.toLower().contains("various")) title = d->artist_ + " - " + title;
|
||||
if (is_compilation() && !d->artist_.isEmpty() && !d->artist_.contains("various", Qt::CaseInsensitive)) title = d->artist_ + " - " + title;
|
||||
|
||||
return title;
|
||||
|
||||
@@ -1475,7 +1483,7 @@ QString Song::SampleRateBitDepthToText() const {
|
||||
|
||||
QString Song::PrettyRating() const {
|
||||
|
||||
float rating = d->rating_;
|
||||
double rating = d->rating_;
|
||||
|
||||
if (rating == -1.0f) return "0";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -127,6 +127,8 @@ class Song {
|
||||
|
||||
static const QStringList kArticles;
|
||||
|
||||
static const QStringList kAcceptedExtensions;
|
||||
|
||||
static QString JoinSpec(const QString &table);
|
||||
|
||||
static Source SourceFromURL(const QUrl &url);
|
||||
@@ -243,7 +245,7 @@ class Song {
|
||||
const QString &cue_path() const;
|
||||
bool has_cue() const;
|
||||
|
||||
float rating() const;
|
||||
double rating() const;
|
||||
|
||||
const QString &effective_album() const;
|
||||
int effective_originalyear() const;
|
||||
@@ -356,7 +358,7 @@ class Song {
|
||||
|
||||
void set_cue_path(const QString &v);
|
||||
|
||||
void set_rating(const float v);
|
||||
void set_rating(const double v);
|
||||
|
||||
void set_stream_url(const QUrl &v);
|
||||
void set_image(const QImage &i);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* Strawberry Music Player
|
||||
* This file was part of Clementine.
|
||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||
* Copyright 2018-2019, Jonas Kvinge <jonas@jkvinge.net>
|
||||
* Copyright 2018-2021, Jonas Kvinge <jonas@jkvinge.net>
|
||||
*
|
||||
* Strawberry is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user