Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
47b5dea95c | ||
|
|
b0df63f1e8 | ||
|
|
3c4209b676 | ||
|
|
d51b9a8e0e | ||
|
|
3b56125bd2 | ||
|
|
6e69e39007 | ||
|
|
97208cb329 | ||
|
|
414a4a97fb | ||
|
|
2a809f96c4 | ||
|
|
17799b03f3 | ||
|
|
efc55fc648 | ||
|
|
22bd41211a | ||
|
|
4cb0171bd0 | ||
|
|
ce6c5af72c | ||
|
|
171575256c | ||
|
|
d3664dcf78 | ||
|
|
0788981783 | ||
|
|
aeee7c02d5 | ||
|
|
6e49a50461 | ||
|
|
fbc99827ab | ||
|
|
3b134320c4 | ||
|
|
c315e5016d | ||
|
|
7aebd6ed57 | ||
|
|
1a8ca06495 | ||
|
|
a27ae7e4a6 | ||
|
|
dd0ab897aa | ||
|
|
00ad92fb6d | ||
|
|
f84128ecbd | ||
|
|
ba89e0f4e3 | ||
|
|
832d36a4d4 | ||
|
|
0b437b3bfb | ||
|
|
7b50ec4630 | ||
|
|
4ddb13abac | ||
|
|
d2ac081177 | ||
|
|
9692fbf15b | ||
|
|
be966488e8 | ||
|
|
0ce613264f | ||
|
|
34634d776e | ||
|
|
673ded3819 | ||
|
|
b9a94ad3ae | ||
|
|
3f80b330cc | ||
|
|
01632d538c | ||
|
|
b0a9b1cd09 | ||
|
|
1f772081fd | ||
|
|
4ae54dbaad | ||
|
|
e47f4ff731 | ||
|
|
465369d79e | ||
|
|
15ddf6ff20 | ||
|
|
16a753bd95 | ||
|
|
c15103636c | ||
|
|
8a5f82ee7d | ||
|
|
5ec33ec821 | ||
|
|
ab7d383cf1 | ||
|
|
184e9a5c93 | ||
|
|
c4f5363cde | ||
|
|
002882cebf | ||
|
|
1cb3ec0c7b | ||
|
|
6bf325c6f6 | ||
|
|
09c7ff9e8b | ||
|
|
c2a94b61bf | ||
|
|
1db16232de | ||
|
|
3da681a6b1 | ||
|
|
a79b3e7852 | ||
|
|
b1099e6974 | ||
|
|
4f6e06131c | ||
|
|
19f69e9e6c | ||
|
|
01481da773 | ||
|
|
3e8f7e1cf1 | ||
|
|
5da69646f2 | ||
|
|
3cac01583b | ||
|
|
d16a26605e | ||
|
|
a4f692c788 | ||
|
|
9f01206c57 | ||
|
|
d34fc551ed | ||
|
|
7aa5f0d258 | ||
|
|
276a34bb66 | ||
|
|
0d820eda12 | ||
|
|
1991c1b677 | ||
|
|
459404e3f0 | ||
|
|
badc623a3c | ||
|
|
8e39f92cb7 | ||
|
|
3ff4885973 | ||
|
|
f9d45f7657 | ||
|
|
789ff9df5c | ||
|
|
a2064ed16b | ||
|
|
b3d06c0868 | ||
|
|
db1a6b3e38 | ||
|
|
8390237cc4 | ||
|
|
9967eae7bb | ||
|
|
b3be7d1c6f | ||
|
|
33ccb5dbb2 | ||
|
|
5b90c0d695 | ||
|
|
472a660239 | ||
|
|
ab67536d9a | ||
|
|
ee85fb3aec | ||
|
|
214b6f4358 | ||
|
|
af0d092054 | ||
|
|
b07903c3e9 | ||
|
|
ffa4c6bf09 | ||
|
|
b4125fa56c | ||
|
|
2c72302087 | ||
|
|
0fa52bc64f | ||
|
|
f55a80b15a | ||
|
|
0735483321 | ||
|
|
53fc2c7c21 | ||
|
|
f22133c3c5 | ||
|
|
2d5a6d6583 | ||
|
|
dc4adf2836 | ||
|
|
dd6e254e4f | ||
|
|
4c028c1659 | ||
|
|
d332a6777a | ||
|
|
378251f229 | ||
|
|
b6b9b903ed | ||
|
|
143d68cfd5 | ||
|
|
a31eac1426 | ||
|
|
797196f7fc | ||
|
|
c9d0bc81dd | ||
|
|
b5448ff607 | ||
|
|
5ebd363d5d | ||
|
|
1d439e673e | ||
|
|
0b7b7656b2 | ||
|
|
eb270df835 | ||
|
|
ff73dd2183 | ||
|
|
e043a03eb6 | ||
|
|
3cb4e8e373 | ||
|
|
7e6de528b4 | ||
|
|
df901c30ef | ||
|
|
13856b33ec | ||
|
|
a3a1c6f4c8 | ||
|
|
638998a861 | ||
|
|
6e2ec89a05 | ||
|
|
af67de8aa6 | ||
|
|
425dac478e | ||
|
|
b15c4ecd10 | ||
|
|
d7f88cf3a4 | ||
|
|
5b7fbcd9b8 | ||
|
|
7af64b0782 | ||
|
|
b84c70e811 | ||
|
|
f5b245c72d | ||
|
|
4307183817 | ||
|
|
aeb32783d6 | ||
|
|
3927b3bf27 | ||
|
|
da9d2f9417 | ||
|
|
1cec48e8f8 | ||
|
|
f1105393da | ||
|
|
dc7047e3c2 | ||
|
|
08b2945623 | ||
|
|
cbcc223150 | ||
|
|
9830f21e4a | ||
|
|
5f49567bf7 | ||
|
|
6154ae7342 | ||
|
|
978f3a3682 | ||
|
|
1f0961d574 | ||
|
|
a101252701 | ||
|
|
c96c29b1e3 | ||
|
|
3b0fc180ff | ||
|
|
9b8bfdf33c | ||
|
|
4328831fcd | ||
|
|
e5b3df41e9 | ||
|
|
cf5259e218 | ||
|
|
f24b6a520c | ||
|
|
4140163ab2 | ||
|
|
7afde0e93f | ||
|
|
d27a571882 | ||
|
|
1c70e3be25 | ||
|
|
1819f64467 | ||
|
|
9852e588c1 | ||
|
|
71a1ea481b | ||
|
|
9e32f0d778 | ||
|
|
4478174dc2 | ||
|
|
07553476d4 | ||
|
|
1773283456 | ||
|
|
221ab51d90 | ||
|
|
43e0dd922b | ||
|
|
b3262652c3 | ||
|
|
0cfa2b8c20 |
@@ -80,7 +80,6 @@ commands:
|
|||||||
libpulse-devel
|
libpulse-devel
|
||||||
gstreamer-devel
|
gstreamer-devel
|
||||||
gstreamer-plugins-base-devel
|
gstreamer-plugins-base-devel
|
||||||
libxine-devel
|
|
||||||
vlc-devel
|
vlc-devel
|
||||||
libQt5Core-devel
|
libQt5Core-devel
|
||||||
libQt5Gui-devel
|
libQt5Gui-devel
|
||||||
@@ -96,9 +95,7 @@ commands:
|
|||||||
libqt5-linguist-devel
|
libqt5-linguist-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libusbmuxd-devel
|
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
desktop-file-utils
|
desktop-file-utils
|
||||||
update-desktop-files
|
update-desktop-files
|
||||||
@@ -150,8 +147,6 @@ commands:
|
|||||||
taglib-devel
|
taglib-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libusbmuxd-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
fftw-devel
|
fftw-devel
|
||||||
@@ -214,8 +209,6 @@ commands:
|
|||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libusbmuxd-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libjpeg-devel
|
libjpeg-devel
|
||||||
cairo-devel
|
cairo-devel
|
||||||
@@ -238,14 +231,14 @@ commands:
|
|||||||
steps:
|
steps:
|
||||||
- run:
|
- run:
|
||||||
name: Update packages
|
name: Update packages
|
||||||
command: urpmi.update -a
|
command: urpmi.update --auto -a
|
||||||
- run:
|
- run:
|
||||||
name: Configure auto update
|
name: Configure auto update
|
||||||
command: urpmi --auto-update
|
command: urpmi --auto --auto-update
|
||||||
- run:
|
- run:
|
||||||
name: Install dependencies
|
name: Install dependencies
|
||||||
command: >
|
command: >
|
||||||
urpmi --force
|
urpmi --auto --force
|
||||||
urpmi-debuginfo-install
|
urpmi-debuginfo-install
|
||||||
git
|
git
|
||||||
tar
|
tar
|
||||||
@@ -281,8 +274,6 @@ commands:
|
|||||||
lib64gstreamer-plugins-base1.0-devel
|
lib64gstreamer-plugins-base1.0-devel
|
||||||
lib64cdio-devel
|
lib64cdio-devel
|
||||||
lib64gpod-devel
|
lib64gpod-devel
|
||||||
lib64plist-devel
|
|
||||||
lib64usbmuxd-devel
|
|
||||||
lib64mtp-devel
|
lib64mtp-devel
|
||||||
lib64raw1394-devel
|
lib64raw1394-devel
|
||||||
lib64chromaprint-devel
|
lib64chromaprint-devel
|
||||||
@@ -336,9 +327,6 @@ commands:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
|
|
||||||
|
|
||||||
install_ubuntu_dependencies:
|
install_ubuntu_dependencies:
|
||||||
@@ -390,9 +378,6 @@ commands:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -501,15 +486,6 @@ jobs:
|
|||||||
- build_rpm
|
- build_rpm
|
||||||
|
|
||||||
|
|
||||||
build_debian_stretch:
|
|
||||||
docker:
|
|
||||||
- image: debian:stretch
|
|
||||||
steps:
|
|
||||||
- install_debian_dependencies
|
|
||||||
- checkout
|
|
||||||
- cmake
|
|
||||||
- build_deb
|
|
||||||
|
|
||||||
build_debian_buster:
|
build_debian_buster:
|
||||||
docker:
|
docker:
|
||||||
- image: debian:buster
|
- image: debian:buster
|
||||||
@@ -603,10 +579,6 @@ workflows:
|
|||||||
only: /.*/
|
only: /.*/
|
||||||
|
|
||||||
|
|
||||||
- build_debian_stretch:
|
|
||||||
filters:
|
|
||||||
tags:
|
|
||||||
only: /.*/
|
|
||||||
- build_debian_buster:
|
- build_debian_buster:
|
||||||
filters:
|
filters:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
176
.github/workflows/ccpp.yml
vendored
176
.github/workflows/ccpp.yml
vendored
@@ -38,7 +38,6 @@ jobs:
|
|||||||
libpulse-devel
|
libpulse-devel
|
||||||
gstreamer-devel
|
gstreamer-devel
|
||||||
gstreamer-plugins-base-devel
|
gstreamer-plugins-base-devel
|
||||||
libxine-devel
|
|
||||||
vlc-devel
|
vlc-devel
|
||||||
libQt5Core-devel
|
libQt5Core-devel
|
||||||
libQt5Gui-devel
|
libQt5Gui-devel
|
||||||
@@ -54,9 +53,7 @@ jobs:
|
|||||||
libqt5-linguist-devel
|
libqt5-linguist-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libusbmuxd-devel
|
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
desktop-file-utils
|
desktop-file-utils
|
||||||
update-desktop-files
|
update-desktop-files
|
||||||
@@ -109,7 +106,6 @@ jobs:
|
|||||||
libpulse-devel
|
libpulse-devel
|
||||||
gstreamer-devel
|
gstreamer-devel
|
||||||
gstreamer-plugins-base-devel
|
gstreamer-plugins-base-devel
|
||||||
libxine-devel
|
|
||||||
vlc-devel
|
vlc-devel
|
||||||
libQt5Core-devel
|
libQt5Core-devel
|
||||||
libQt5Gui-devel
|
libQt5Gui-devel
|
||||||
@@ -125,9 +121,7 @@ jobs:
|
|||||||
libqt5-linguist-devel
|
libqt5-linguist-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libusbmuxd-devel
|
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
desktop-file-utils
|
desktop-file-utils
|
||||||
update-desktop-files
|
update-desktop-files
|
||||||
@@ -188,7 +182,6 @@ jobs:
|
|||||||
libpulse-devel
|
libpulse-devel
|
||||||
gstreamer-devel
|
gstreamer-devel
|
||||||
gstreamer-plugins-base-devel
|
gstreamer-plugins-base-devel
|
||||||
libxine-devel
|
|
||||||
vlc-devel
|
vlc-devel
|
||||||
libQt5Core-devel
|
libQt5Core-devel
|
||||||
libQt5Gui-devel
|
libQt5Gui-devel
|
||||||
@@ -204,9 +197,7 @@ jobs:
|
|||||||
libqt5-linguist-devel
|
libqt5-linguist-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libusbmuxd-devel
|
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
desktop-file-utils
|
desktop-file-utils
|
||||||
update-desktop-files
|
update-desktop-files
|
||||||
@@ -269,7 +260,6 @@ jobs:
|
|||||||
libpulse-devel
|
libpulse-devel
|
||||||
gstreamer-devel
|
gstreamer-devel
|
||||||
gstreamer-plugins-base-devel
|
gstreamer-plugins-base-devel
|
||||||
libxine-devel
|
|
||||||
vlc-devel
|
vlc-devel
|
||||||
libQt5Core-devel
|
libQt5Core-devel
|
||||||
libQt5Gui-devel
|
libQt5Gui-devel
|
||||||
@@ -285,9 +275,7 @@ jobs:
|
|||||||
libqt5-linguist-devel
|
libqt5-linguist-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libusbmuxd-devel
|
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
desktop-file-utils
|
desktop-file-utils
|
||||||
update-desktop-files
|
update-desktop-files
|
||||||
@@ -313,6 +301,78 @@ jobs:
|
|||||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||||
|
|
||||||
|
|
||||||
|
build_opensuse_qt6:
|
||||||
|
name: Build openSUSE Qt 6
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: opensuse/tumbleweed
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1.2.0
|
||||||
|
- name: Add Qt 6 repository
|
||||||
|
run: zypper -n ar -c -f -n 'repo-qt6' https://download.opensuse.org/repositories/home:/jonaski:/qt6/openSUSE_Tumbleweed/ repo-qt6
|
||||||
|
- 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
|
||||||
|
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-x11extras-devel
|
||||||
|
qt6-base-common-devel
|
||||||
|
qt6-sql-sqlite
|
||||||
|
qt6-qt5compat-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 -DWITH_QT6=ON
|
||||||
|
- name: Build
|
||||||
|
working-directory: build
|
||||||
|
run: cmake --build . --config $BUILD_TYPE
|
||||||
|
|
||||||
|
|
||||||
build_fedora_32:
|
build_fedora_32:
|
||||||
name: Build Fedora 32
|
name: Build Fedora 32
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -364,8 +424,6 @@ jobs:
|
|||||||
taglib-devel
|
taglib-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libusbmuxd-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
fftw-devel
|
fftw-devel
|
||||||
@@ -448,8 +506,6 @@ jobs:
|
|||||||
libchromaprint-devel
|
libchromaprint-devel
|
||||||
libcdio-devel
|
libcdio-devel
|
||||||
libgpod-devel
|
libgpod-devel
|
||||||
libplist-devel
|
|
||||||
libusbmuxd-devel
|
|
||||||
libmtp-devel
|
libmtp-devel
|
||||||
libjpeg-devel
|
libjpeg-devel
|
||||||
cairo-devel
|
cairo-devel
|
||||||
@@ -494,14 +550,14 @@ jobs:
|
|||||||
- uses: actions/checkout@v1.2.0
|
- uses: actions/checkout@v1.2.0
|
||||||
|
|
||||||
- name: Update packages
|
- name: Update packages
|
||||||
run: urpmi.update -a
|
run: urpmi.update --auto -a
|
||||||
|
|
||||||
- name: Configure auto update
|
- name: Configure auto update
|
||||||
run: urpmi --auto-update
|
run: urpmi --auto --auto-update
|
||||||
|
|
||||||
- name: Install Mageia dependencies
|
- name: Install Mageia dependencies
|
||||||
run: >
|
run: >
|
||||||
urpmi --force
|
urpmi --auto --force
|
||||||
urpmi-debuginfo-install
|
urpmi-debuginfo-install
|
||||||
git
|
git
|
||||||
tar
|
tar
|
||||||
@@ -537,8 +593,6 @@ jobs:
|
|||||||
lib64gstreamer-plugins-base1.0-devel
|
lib64gstreamer-plugins-base1.0-devel
|
||||||
lib64cdio-devel
|
lib64cdio-devel
|
||||||
lib64gpod-devel
|
lib64gpod-devel
|
||||||
lib64plist-devel
|
|
||||||
lib64usbmuxd-devel
|
|
||||||
lib64mtp-devel
|
lib64mtp-devel
|
||||||
lib64raw1394-devel
|
lib64raw1394-devel
|
||||||
lib64chromaprint-devel
|
lib64chromaprint-devel
|
||||||
@@ -570,65 +624,6 @@ jobs:
|
|||||||
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
run: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||||
|
|
||||||
|
|
||||||
build_debian_stretch:
|
|
||||||
name: Build Debian Stretch
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
container:
|
|
||||||
image: debian:stretch
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v1.2.0
|
|
||||||
- name: Install Debian dependencies
|
|
||||||
run: >
|
|
||||||
apt-get update && apt-get install -y
|
|
||||||
build-essential
|
|
||||||
ssh
|
|
||||||
git
|
|
||||||
make
|
|
||||||
cmake
|
|
||||||
gcc
|
|
||||||
pkg-config
|
|
||||||
fakeroot
|
|
||||||
gettext
|
|
||||||
lsb-release
|
|
||||||
libglib2.0-dev
|
|
||||||
dpkg-dev
|
|
||||||
libdbus-1-dev
|
|
||||||
libboost-dev
|
|
||||||
libprotobuf-dev
|
|
||||||
protobuf-compiler
|
|
||||||
libsqlite3-dev
|
|
||||||
libgnutls28-dev
|
|
||||||
libasound2-dev
|
|
||||||
libpulse-dev
|
|
||||||
qtbase5-dev
|
|
||||||
qtbase5-dev-tools
|
|
||||||
qtbase5-private-dev
|
|
||||||
libqt5x11extras5-dev
|
|
||||||
qttools5-dev
|
|
||||||
libgstreamer1.0-dev
|
|
||||||
libgstreamer-plugins-base1.0-dev
|
|
||||||
gstreamer1.0-alsa
|
|
||||||
gstreamer1.0-pulseaudio
|
|
||||||
libchromaprint-dev
|
|
||||||
libfftw3-dev
|
|
||||||
libcdio-dev
|
|
||||||
libmtp-dev
|
|
||||||
libgpod-dev
|
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
- 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
|
|
||||||
- name: make deb
|
|
||||||
shell: bash
|
|
||||||
run: dpkg-buildpackage -b -d -uc -us -nc -j2
|
|
||||||
|
|
||||||
|
|
||||||
build_debian_buster:
|
build_debian_buster:
|
||||||
name: Build Debian Buster
|
name: Build Debian Buster
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -673,9 +668,6 @@ jobs:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -E make_directory build
|
run: cmake -E make_directory build
|
||||||
@@ -732,9 +724,6 @@ jobs:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -E make_directory build
|
run: cmake -E make_directory build
|
||||||
@@ -796,9 +785,6 @@ jobs:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -E make_directory build
|
run: cmake -E make_directory build
|
||||||
@@ -860,9 +846,6 @@ jobs:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -E make_directory build
|
run: cmake -E make_directory build
|
||||||
@@ -924,9 +907,6 @@ jobs:
|
|||||||
libcdio-dev
|
libcdio-dev
|
||||||
libmtp-dev
|
libmtp-dev
|
||||||
libgpod-dev
|
libgpod-dev
|
||||||
libimobiledevice-dev
|
|
||||||
libplist-dev
|
|
||||||
libusbmuxd-dev
|
|
||||||
- name: Create Build Environment
|
- name: Create Build Environment
|
||||||
shell: bash
|
shell: bash
|
||||||
run: cmake -E make_directory build
|
run: cmake -E make_directory build
|
||||||
@@ -969,8 +949,6 @@ jobs:
|
|||||||
gst-libav
|
gst-libav
|
||||||
libcdio
|
libcdio
|
||||||
libmtp
|
libmtp
|
||||||
libimobiledevice
|
|
||||||
libplist
|
|
||||||
create-dmg
|
create-dmg
|
||||||
taglib
|
taglib
|
||||||
|
|
||||||
@@ -1034,9 +1012,7 @@ jobs:
|
|||||||
-DENABLE_WIN32_CONSOLE=OFF
|
-DENABLE_WIN32_CONSOLE=OFF
|
||||||
-DENABLE_DBUS=OFF
|
-DENABLE_DBUS=OFF
|
||||||
-DENABLE_LIBGPOD=OFF
|
-DENABLE_LIBGPOD=OFF
|
||||||
-DENABLE_IMOBILEDEVICE=OFF
|
|
||||||
-DENABLE_LIBMTP=OFF
|
-DENABLE_LIBMTP=OFF
|
||||||
-DENABLE_XINE=OFF
|
|
||||||
-DProtobuf_PROTOC_EXECUTABLE=/usr/src/strawberry-mxe/usr/x86_64-pc-linux-gnu/bin/protoc
|
-DProtobuf_PROTOC_EXECUTABLE=/usr/src/strawberry-mxe/usr/x86_64-pc-linux-gnu/bin/protoc
|
||||||
|
|
||||||
- name: Run Make
|
- name: Run Make
|
||||||
@@ -1049,7 +1025,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Create directories
|
- name: Create directories
|
||||||
working-directory: build
|
working-directory: build
|
||||||
run: mkdir -p gio-modules platforms sqldrivers imageformats styles gstreamer-plugins xine-plugins nsisplugins
|
run: mkdir -p gio-modules platforms sqldrivers imageformats styles gstreamer-plugins nsisplugins
|
||||||
|
|
||||||
- name: Copy GIO modules
|
- name: Copy GIO modules
|
||||||
working-directory: build
|
working-directory: build
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -104,7 +104,6 @@ Thumbs.db
|
|||||||
|
|
||||||
# Stuff in dist
|
# Stuff in dist
|
||||||
maketarball.sh
|
maketarball.sh
|
||||||
create-dmg.sh
|
|
||||||
changelog
|
changelog
|
||||||
PKGBUILD
|
PKGBUILD
|
||||||
|
|
||||||
|
|||||||
@@ -23,8 +23,11 @@ before_install:
|
|||||||
brew unlink python@2 || travis_terminate 1;
|
brew unlink python@2 || travis_terminate 1;
|
||||||
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint zlib taglib;
|
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint zlib taglib;
|
||||||
brew install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav;
|
brew install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav;
|
||||||
brew install libcdio libmtp libimobiledevice libplist;
|
brew install libcdio libmtp;
|
||||||
brew install create-dmg;
|
brew install create-dmg;
|
||||||
|
brew cask install 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;
|
||||||
export Qt5_DIR=/usr/local/opt/qt5/lib/cmake;
|
export Qt5_DIR=/usr/local/opt/qt5/lib/cmake;
|
||||||
export Qt5LinguistTools_DIR=/usr/local/opt/qt5/lib/cmake/Qt5LinguistTools;
|
export Qt5LinguistTools_DIR=/usr/local/opt/qt5/lib/cmake/Qt5LinguistTools;
|
||||||
export PATH="/usr/local/opt/gettext/bin:$PATH";
|
export PATH="/usr/local/opt/gettext/bin:$PATH";
|
||||||
|
|||||||
32
3rdparty/singleapplication/CMakeLists.txt
vendored
32
3rdparty/singleapplication/CMakeLists.txt
vendored
@@ -10,38 +10,46 @@ endif()
|
|||||||
|
|
||||||
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
|
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
|
||||||
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)
|
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)
|
||||||
QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
|
if(WITH_QT6)
|
||||||
|
qt6_wrap_cpp(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
|
||||||
|
else()
|
||||||
|
qt5_wrap_cpp(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
|
||||||
|
endif()
|
||||||
add_library(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
|
add_library(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
|
||||||
target_include_directories(singleapplication SYSTEM PRIVATE
|
target_include_directories(singleapplication SYSTEM PRIVATE
|
||||||
${Qt5Core_INCLUDE_DIRS}
|
${QtCore_INCLUDE_DIRS}
|
||||||
${Qt5Widgets_INCLUDE_DIRS}
|
${QtWidgets_INCLUDE_DIRS}
|
||||||
${Qt5Network_INCLUDE_DIRS}
|
${QtNetwork_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
target_include_directories(singleapplication PRIVATE
|
target_include_directories(singleapplication PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(singleapplication PRIVATE
|
target_link_libraries(singleapplication PRIVATE
|
||||||
${Qt5Core_LIBRARIES}
|
${QtCore_LIBRARIES}
|
||||||
${Qt5Widgets_LIBRARIES}
|
${QtWidgets_LIBRARIES}
|
||||||
${Qt5Network_LIBRARIES}
|
${QtNetwork_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
set(SINGLECOREAPP-SOURCES singlecoreapplication.cpp singlecoreapplication_p.cpp)
|
set(SINGLECOREAPP-SOURCES singlecoreapplication.cpp singlecoreapplication_p.cpp)
|
||||||
set(SINGLECOREAPP-MOC-HEADERS singlecoreapplication.h singlecoreapplication_p.h)
|
set(SINGLECOREAPP-MOC-HEADERS singlecoreapplication.h singlecoreapplication_p.h)
|
||||||
QT5_WRAP_CPP(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
|
if(WITH_QT6)
|
||||||
|
qt6_wrap_cpp(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
|
||||||
|
else()
|
||||||
|
qt5_wrap_cpp(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
|
||||||
|
endif()
|
||||||
add_library(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
|
add_library(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
|
||||||
target_include_directories(singlecoreapplication SYSTEM PRIVATE
|
target_include_directories(singlecoreapplication SYSTEM PRIVATE
|
||||||
${Qt5Core_INCLUDE_DIRS}
|
${QtCore_INCLUDE_DIRS}
|
||||||
${Qt5Network_INCLUDE_DIRS}
|
${QtNetwork_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
target_include_directories(singlecoreapplication PRIVATE
|
target_include_directories(singlecoreapplication PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
target_link_libraries(singlecoreapplication PRIVATE
|
target_link_libraries(singlecoreapplication PRIVATE
|
||||||
${Qt5Core_LIBRARIES}
|
${QtCore_LIBRARIES}
|
||||||
${Qt5Network_LIBRARIES}
|
${QtNetwork_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
configure_file(config.h.in "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
configure_file(config.h.in "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
||||||
|
|||||||
14
3rdparty/taglib/ConfigureChecks.cmake
vendored
14
3rdparty/taglib/ConfigureChecks.cmake
vendored
@@ -6,32 +6,32 @@ include(CheckCXXSourceCompiles)
|
|||||||
# Check if the size of numeric types are suitable.
|
# Check if the size of numeric types are suitable.
|
||||||
|
|
||||||
check_type_size("short" SIZEOF_SHORT)
|
check_type_size("short" SIZEOF_SHORT)
|
||||||
if(NOT ${SIZEOF_SHORT} EQUAL 2)
|
if(NOT SIZEOF_SHORT EQUAL 2)
|
||||||
message(FATAL_ERROR "TagLib requires that short is 16-bit wide.")
|
message(FATAL_ERROR "TagLib requires that short is 16-bit wide.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_type_size("int" SIZEOF_INT)
|
check_type_size("int" SIZEOF_INT)
|
||||||
if(NOT ${SIZEOF_INT} EQUAL 4)
|
if(NOT SIZEOF_INT EQUAL 4)
|
||||||
message(FATAL_ERROR "TagLib requires that int is 32-bit wide.")
|
message(FATAL_ERROR "TagLib requires that int is 32-bit wide.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_type_size("long long" SIZEOF_LONGLONG)
|
check_type_size("long long" SIZEOF_LONGLONG)
|
||||||
if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
|
if(NOT SIZEOF_LONGLONG EQUAL 8)
|
||||||
message(FATAL_ERROR "TagLib requires that long long is 64-bit wide.")
|
message(FATAL_ERROR "TagLib requires that long long is 64-bit wide.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
||||||
if(${SIZEOF_WCHAR_T} LESS 2)
|
if(SIZEOF_WCHAR_T LESS 2)
|
||||||
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
|
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_type_size("float" SIZEOF_FLOAT)
|
check_type_size("float" SIZEOF_FLOAT)
|
||||||
if(NOT ${SIZEOF_FLOAT} EQUAL 4)
|
if(NOT SIZEOF_FLOAT EQUAL 4)
|
||||||
message(FATAL_ERROR "TagLib requires that float is 32-bit wide.")
|
message(FATAL_ERROR "TagLib requires that float is 32-bit wide.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
check_type_size("double" SIZEOF_DOUBLE)
|
check_type_size("double" SIZEOF_DOUBLE)
|
||||||
if(NOT ${SIZEOF_DOUBLE} EQUAL 8)
|
if(NOT SIZEOF_DOUBLE EQUAL 8)
|
||||||
message(FATAL_ERROR "TagLib requires that double is 64-bit wide.")
|
message(FATAL_ERROR "TagLib requires that double is 64-bit wide.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
@@ -212,5 +212,5 @@ endif()
|
|||||||
|
|
||||||
# Detect WinRT mode
|
# Detect WinRT mode
|
||||||
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
|
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
|
||||||
set(PLATFORM WINRT 1)
|
set(PLATFORM WINRT 1)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
5
3rdparty/taglib/toolkit/tutils.h
vendored
5
3rdparty/taglib/toolkit/tutils.h
vendored
@@ -160,6 +160,9 @@ inline String formatString(const char *format, ...) {
|
|||||||
char buf[BufferSize];
|
char buf[BufferSize];
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
|
||||||
|
|
||||||
# if defined(HAVE_VSNPRINTF)
|
# if defined(HAVE_VSNPRINTF)
|
||||||
|
|
||||||
length = vsnprintf(buf, BufferSize, format, args);
|
length = vsnprintf(buf, BufferSize, format, args);
|
||||||
@@ -180,6 +183,8 @@ inline String formatString(const char *format, ...) {
|
|||||||
|
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
|
|||||||
178
CMakeLists.txt
178
CMakeLists.txt
@@ -50,16 +50,11 @@ list(APPEND COMPILE_OPTIONS
|
|||||||
-Wunused-parameter
|
-Wunused-parameter
|
||||||
-Wformat=2
|
-Wformat=2
|
||||||
-Wdisabled-optimization
|
-Wdisabled-optimization
|
||||||
-Wno-sign-conversion
|
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>
|
$<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-old-style-cast>
|
$<$<COMPILE_LANGUAGE:CXX>:-Wno-old-style-cast>
|
||||||
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
||||||
)
|
)
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
list(APPEND COMPILE_OPTIONS -Wno-unused-parameter)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
option(BUILD_WERROR "Build with -Werror" OFF)
|
option(BUILD_WERROR "Build with -Werror" OFF)
|
||||||
if(BUILD_WERROR)
|
if(BUILD_WERROR)
|
||||||
list(APPEND COMPILE_OPTIONS -Werror)
|
list(APPEND COMPILE_OPTIONS -Werror)
|
||||||
@@ -77,6 +72,11 @@ if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
|||||||
set(DEBUG ON)
|
set(DEBUG ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(APPLE)
|
||||||
|
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
|
||||||
|
set(CMAKE_INSTALL_RPATH "@loader_path/../Frameworks")
|
||||||
|
endif()
|
||||||
|
|
||||||
find_program(CCACHE_EXECUTABLE NAMES ccache)
|
find_program(CCACHE_EXECUTABLE NAMES ccache)
|
||||||
if (CCACHE_EXECUTABLE)
|
if (CCACHE_EXECUTABLE)
|
||||||
message(STATUS "ccache found: will be used for compilation and linkage")
|
message(STATUS "ccache found: will be used for compilation and linkage")
|
||||||
@@ -93,7 +93,9 @@ if(Backtrace_FOUND)
|
|||||||
endif()
|
endif()
|
||||||
find_package(GnuTLS REQUIRED)
|
find_package(GnuTLS REQUIRED)
|
||||||
find_package(Protobuf REQUIRED)
|
find_package(Protobuf REQUIRED)
|
||||||
find_library(PROTOBUF_STATIC_LIBRARY libprotobuf.a libprotobuf)
|
if (NOT Protobuf_PROTOC_EXECUTABLE)
|
||||||
|
message(FATAL_ERROR "Missing protobuf compiler.")
|
||||||
|
endif()
|
||||||
if(LINUX)
|
if(LINUX)
|
||||||
find_package(ALSA REQUIRED)
|
find_package(ALSA REQUIRED)
|
||||||
pkg_check_modules(DBUS REQUIRED dbus-1)
|
pkg_check_modules(DBUS REQUIRED dbus-1)
|
||||||
@@ -118,23 +120,17 @@ pkg_check_modules(GSTREAMER_AUDIO gstreamer-audio-1.0)
|
|||||||
pkg_check_modules(GSTREAMER_APP gstreamer-app-1.0)
|
pkg_check_modules(GSTREAMER_APP gstreamer-app-1.0)
|
||||||
pkg_check_modules(GSTREAMER_TAG gstreamer-tag-1.0)
|
pkg_check_modules(GSTREAMER_TAG gstreamer-tag-1.0)
|
||||||
pkg_check_modules(GSTREAMER_PBUTILS gstreamer-pbutils-1.0)
|
pkg_check_modules(GSTREAMER_PBUTILS gstreamer-pbutils-1.0)
|
||||||
pkg_check_modules(LIBXINE libxine)
|
|
||||||
pkg_check_modules(LIBVLC libvlc)
|
pkg_check_modules(LIBVLC libvlc)
|
||||||
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.9)
|
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.9)
|
||||||
pkg_check_modules(LIBPULSE libpulse)
|
pkg_check_modules(LIBPULSE libpulse)
|
||||||
pkg_check_modules(CHROMAPRINT libchromaprint)
|
pkg_check_modules(CHROMAPRINT libchromaprint)
|
||||||
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
|
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
|
||||||
pkg_check_modules(LIBMTP libmtp>=1.0)
|
pkg_check_modules(LIBMTP libmtp>=1.0)
|
||||||
pkg_check_modules(LIBIMOBILEDEVICE libimobiledevice-1.0)
|
|
||||||
pkg_search_module(LIBUSBMUXD libusbmuxd-2.0 libusbmuxd)
|
|
||||||
pkg_search_module(LIBPLIST libplist-2.0 libplist)
|
|
||||||
find_package(Gettext)
|
find_package(Gettext)
|
||||||
find_package(FFTW3)
|
find_package(FFTW3)
|
||||||
|
|
||||||
# QT
|
option(WITH_QT6 "Use Qt 6" OFF)
|
||||||
set(QT_MIN_VERSION 5.6)
|
|
||||||
set(QT_COMPONENTS Core Concurrent Widgets Network Sql)
|
set(QT_COMPONENTS Core Concurrent Widgets Network Sql)
|
||||||
|
|
||||||
if(X11_FOUND)
|
if(X11_FOUND)
|
||||||
list(APPEND QT_COMPONENTS X11Extras)
|
list(APPEND QT_COMPONENTS X11Extras)
|
||||||
endif()
|
endif()
|
||||||
@@ -148,32 +144,71 @@ if(WIN32)
|
|||||||
list(APPEND QT_COMPONENTS WinExtras)
|
list(APPEND QT_COMPONENTS WinExtras)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS ${QT_COMPONENTS})
|
if(WITH_QT6)
|
||||||
|
list(APPEND QT_COMPONENTS Core5Compat)
|
||||||
set(QT_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Concurrent_LIBRARIES} ${Qt5Widgets_LIBRARIES} ${Qt5Network_LIBRARIES} ${Qt5Sql_LIBRARIES})
|
find_package(Qt6 REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||||
set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Concurrent_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5Sql_INCLUDE_DIRS})
|
set(QtCore_LIBRARIES Qt6::Core)
|
||||||
|
set(QtConcurrent_LIBRARIES Qt6::Concurrent)
|
||||||
if(Qt5DBus_FOUND)
|
set(QtWidgets_LIBRARIES Qt6::Widgets)
|
||||||
list(APPEND QT_LIBRARIES ${Qt5DBus_LIBRARIES})
|
set(QtNetwork_LIBRARIES Qt6::Network)
|
||||||
list(APPEND QT_INCLUDE_DIRS ${Qt5DBus_INCLUDE_DIRS})
|
set(QtSql_LIBRARIES Qt6::Sql)
|
||||||
get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION)
|
set(QT_LIBRARIES Qt6::Core Qt6::Concurrent Qt6::Widgets Qt6::Network Qt6::Sql Qt6::Core5Compat)
|
||||||
endif()
|
if(Qt6DBus_FOUND)
|
||||||
if(Qt5X11Extras_FOUND)
|
set(QtDBus_LIBRARIES Qt6::DBus)
|
||||||
list(APPEND QT_LIBRARIES ${Qt5X11Extras_LIBRARIES})
|
list(APPEND QT_LIBRARIES Qt6::DBus)
|
||||||
list(APPEND QT_INCLUDE_DIRS ${Qt5X11Extras_INCLUDE_DIRS})
|
get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt6::qdbusxml2cpp LOCATION)
|
||||||
endif()
|
endif()
|
||||||
if(Qt5MacExtras_FOUND)
|
if(Qt6X11Extras_FOUND)
|
||||||
list(APPEND QT_LIBRARIES ${Qt5MacExtras_LIBRARIES})
|
set(QtX11Extras_LIBRARIES Qt6::X11Extras)
|
||||||
list(APPEND QT_INCLUDE_DIRS ${Qt5MacExtras_INCLUDE_DIRS})
|
list(APPEND QT_LIBRARIES Qt6::X11Extras)
|
||||||
endif()
|
endif()
|
||||||
if(Qt5WinExtras_FOUND)
|
if(Qt6MacExtras_FOUND)
|
||||||
list(APPEND QT_LIBRARIES ${Qt5WinExtras_LIBRARIES})
|
set(QtMacExtras_LIBRARIES Qt6::MacExtras)
|
||||||
list(APPEND QT_INCLUDE_DIRS ${Qt5WinExtras_INCLUDE_DIRS})
|
list(APPEND QT_LIBRARIES Qt6::MacExtras)
|
||||||
endif()
|
endif()
|
||||||
|
if(Qt6WinExtras_FOUND)
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} QUIET COMPONENTS LinguistTools CONFIG)
|
set(QtWinExtras_LIBRARIES Qt6::WinExtras)
|
||||||
if (Qt5LinguistTools_FOUND)
|
list(APPEND QT_LIBRARIES Qt6::WinExtras)
|
||||||
set(QT_LCONVERT_EXECUTABLE Qt5::lconvert)
|
endif()
|
||||||
|
find_package(Qt6 QUIET COMPONENTS LinguistTools CONFIG)
|
||||||
|
if (Qt6LinguistTools_FOUND)
|
||||||
|
set(QT_LCONVERT_EXECUTABLE Qt6::lconvert)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(QT_MIN_VERSION 5.8)
|
||||||
|
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS ${QT_COMPONENTS})
|
||||||
|
set(QtCore_LIBRARIES ${Qt5Core_LIBRARIES})
|
||||||
|
set(QtConcurrent_LIBRARIES ${Qt5Concurrent_LIBRARIES})
|
||||||
|
set(QtWidgets_LIBRARIES ${Qt5Widgets_LIBRARIES})
|
||||||
|
set(QtNetwork_LIBRARIES ${Qt5Network_LIBRARIES})
|
||||||
|
set(QtSql_LIBRARIES ${Qt5Sql_LIBRARIES})
|
||||||
|
set(QT_LIBRARIES ${QtCore_LIBRARIES} ${QtConcurrent_LIBRARIES} ${QtWidgets_LIBRARIES} ${QtNetwork_LIBRARIES} ${QtSql_LIBRARIES})
|
||||||
|
set(QT_INCLUDE_DIRS ${Qt5Core_INCLUDE_DIRS} ${Qt5Concurrent_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS} ${Qt5Network_INCLUDE_DIRS} ${Qt5Sql_INCLUDE_DIRS})
|
||||||
|
if(Qt5DBus_FOUND)
|
||||||
|
set(QtDBus_LIBRARIES ${Qt5DBus_LIBRARIES})
|
||||||
|
list(APPEND QT_LIBRARIES ${Qt5DBus_LIBRARIES})
|
||||||
|
list(APPEND QT_INCLUDE_DIRS ${Qt5DBus_INCLUDE_DIRS})
|
||||||
|
get_target_property(QT_DBUSXML2CPP_EXECUTABLE Qt5::qdbusxml2cpp LOCATION)
|
||||||
|
endif()
|
||||||
|
if(Qt5X11Extras_FOUND)
|
||||||
|
set(QtX11Extras_LIBRARIES ${Qt5X11Extras_LIBRARIES})
|
||||||
|
list(APPEND QT_LIBRARIES ${Qt5X11Extras_LIBRARIES})
|
||||||
|
list(APPEND QT_INCLUDE_DIRS ${Qt5X11Extras_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
if(Qt5MacExtras_FOUND)
|
||||||
|
set(QtMacExtras_LIBRARIES ${Qt5MacExtras_LIBRARIES})
|
||||||
|
list(APPEND QT_LIBRARIES ${Qt5MacExtras_LIBRARIES})
|
||||||
|
list(APPEND QT_INCLUDE_DIRS ${Qt5MacExtras_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
if(Qt5WinExtras_FOUND)
|
||||||
|
set(QtWinExtras_LIBRARIES ${Qt5WinExtras_LIBRARIES})
|
||||||
|
list(APPEND QT_LIBRARIES ${Qt5WinExtras_LIBRARIES})
|
||||||
|
list(APPEND QT_INCLUDE_DIRS ${Qt5WinExtras_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
find_package(Qt5 ${QT_MIN_VERSION} QUIET COMPONENTS LinguistTools CONFIG)
|
||||||
|
if (Qt5LinguistTools_FOUND)
|
||||||
|
set(QT_LCONVERT_EXECUTABLE Qt5::lconvert)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(X11_FOUND)
|
if(X11_FOUND)
|
||||||
@@ -221,9 +256,20 @@ set(SINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/singleap
|
|||||||
set(SINGLEAPPLICATION_LIBRARIES singleapplication)
|
set(SINGLEAPPLICATION_LIBRARIES singleapplication)
|
||||||
set(SINGLECOREAPPLICATION_LIBRARIES singlecoreapplication)
|
set(SINGLECOREAPPLICATION_LIBRARIES singlecoreapplication)
|
||||||
|
|
||||||
if (APPLE)
|
if(APPLE)
|
||||||
find_library(SPARKLE Sparkle)
|
find_library(SPARKLE Sparkle)
|
||||||
endif (APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
|
if(NOT SPARKLE AND (APPLE OR WIN32))
|
||||||
|
if(WITH_QT6)
|
||||||
|
pkg_check_modules(QTSPARKLE qtsparkle-qt6)
|
||||||
|
else()
|
||||||
|
pkg_check_modules(QTSPARKLE qtsparkle-qt5)
|
||||||
|
endif()
|
||||||
|
if(QTSPARKLE_FOUND)
|
||||||
|
set(HAVE_QTSPARKLE ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
# RC compiler
|
# RC compiler
|
||||||
@@ -258,10 +304,6 @@ optional_component(GSTREAMER ON "Engine: GStreamer backend"
|
|||||||
DEPENDS "gstreamer-pbutils-1.0" GSTREAMER_PBUTILS_FOUND
|
DEPENDS "gstreamer-pbutils-1.0" GSTREAMER_PBUTILS_FOUND
|
||||||
)
|
)
|
||||||
|
|
||||||
optional_component(XINE ON "Engine: Xine backend"
|
|
||||||
DEPENDS "libxine" LIBXINE_FOUND
|
|
||||||
)
|
|
||||||
|
|
||||||
optional_component(VLC ON "Engine: VLC backend"
|
optional_component(VLC ON "Engine: VLC backend"
|
||||||
DEPENDS "libvlc" LIBVLC_FOUND
|
DEPENDS "libvlc" LIBVLC_FOUND
|
||||||
)
|
)
|
||||||
@@ -299,22 +341,24 @@ optional_component(LIBMTP ON "Devices: MTP support"
|
|||||||
DEPENDS "libmtp" LIBMTP_FOUND
|
DEPENDS "libmtp" LIBMTP_FOUND
|
||||||
)
|
)
|
||||||
|
|
||||||
optional_component(IMOBILEDEVICE ON "Devices: iPhone, iPod Touch, iPad and Apple TV support"
|
|
||||||
DEPENDS "libimobiledevice" LIBIMOBILEDEVICE_FOUND
|
|
||||||
DEPENDS "libplist" LIBPLIST_FOUND
|
|
||||||
DEPENDS "libusbmuxd" LIBUSBMUXD_FOUND
|
|
||||||
DEPENDS "libgpod" HAVE_LIBGPOD
|
|
||||||
)
|
|
||||||
|
|
||||||
optional_component(SPARKLE ON "Sparkle integration"
|
optional_component(SPARKLE ON "Sparkle integration"
|
||||||
DEPENDS "macOS" APPLE
|
DEPENDS "macOS" APPLE
|
||||||
DEPENDS "Sparkle" SPARKLE
|
DEPENDS "Sparkle" SPARKLE
|
||||||
)
|
)
|
||||||
|
|
||||||
optional_component(TRANSLATIONS ON "Translations"
|
if(WITH_QT6)
|
||||||
DEPENDS "gettext" GETTEXT_FOUND
|
optional_component(TRANSLATIONS ON "Translations"
|
||||||
DEPENDS "Qt5LinguistTools" Qt5LinguistTools_FOUND
|
DEPENDS "gettext" GETTEXT_FOUND
|
||||||
)
|
DEPENDS "Qt6LinguistTools" Qt6LinguistTools_FOUND
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
optional_component(TRANSLATIONS ON "Translations"
|
||||||
|
DEPENDS "gettext" GETTEXT_FOUND
|
||||||
|
DEPENDS "Qt5LinguistTools" Qt5LinguistTools_FOUND
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
option(INSTALL_TRANSLATIONS "Install translations" OFF)
|
||||||
|
|
||||||
optional_component(SUBSONIC ON "Subsonic support")
|
optional_component(SUBSONIC ON "Subsonic support")
|
||||||
optional_component(TIDAL ON "Tidal support")
|
optional_component(TIDAL ON "Tidal support")
|
||||||
@@ -343,8 +387,8 @@ endif(USE_BUNDLE AND NOT USE_BUNDLE_DIR)
|
|||||||
|
|
||||||
if(NOT CMAKE_CROSSCOMPILING)
|
if(NOT CMAKE_CROSSCOMPILING)
|
||||||
set(CMAKE_REQUIRED_FLAGS "--std=c++11")
|
set(CMAKE_REQUIRED_FLAGS "--std=c++11")
|
||||||
set(CMAKE_REQUIRED_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Sql_LIBRARIES})
|
set(CMAKE_REQUIRED_LIBRARIES ${QtCore_LIBRARIES} ${QtSql_LIBRARIES})
|
||||||
set(CMAKE_REQUIRED_INCLUDES ${Qt5Core_INCLUDE_DIRS} ${Qt5Sql_INCLUDE_DIRS})
|
set(CMAKE_REQUIRED_INCLUDES ${QtCore_INCLUDE_DIRS} ${QtSql_INCLUDE_DIRS})
|
||||||
check_cxx_source_runs("
|
check_cxx_source_runs("
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
@@ -361,20 +405,6 @@ if(NOT CMAKE_CROSSCOMPILING)
|
|||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HAVE_XINE)
|
|
||||||
check_cxx_source_compiles("
|
|
||||||
#define METRONOM_INTERNAL
|
|
||||||
#include <iostream>
|
|
||||||
#include <xine/metronom.h>
|
|
||||||
int main() {
|
|
||||||
metronom_t metronom;
|
|
||||||
std::cout << metronom.pts_per_smpls;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
XINE_ANALYZER)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Set up definitions
|
# Set up definitions
|
||||||
|
|
||||||
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
|
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
|
||||||
@@ -415,8 +445,8 @@ add_custom_target(uninstall
|
|||||||
|
|
||||||
# Show a summary of what we have enabled
|
# Show a summary of what we have enabled
|
||||||
summary_show()
|
summary_show()
|
||||||
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC)
|
if(NOT HAVE_GSTREAMER AND NOT HAVE_VLC)
|
||||||
message(FATAL_ERROR "You need to have either GStreamer, Xine or VLC to compile!")
|
message(FATAL_ERROR "You need to have either GStreamer or VLC to compile!")
|
||||||
elseif(NOT HAVE_GSTREAMER)
|
elseif(NOT HAVE_GSTREAMER)
|
||||||
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
|
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
46
Changelog
46
Changelog
@@ -2,6 +2,52 @@ Strawberry Music Player
|
|||||||
=======================
|
=======================
|
||||||
ChangeLog
|
ChangeLog
|
||||||
|
|
||||||
|
0.7.2:
|
||||||
|
|
||||||
|
BugFixes:
|
||||||
|
* Fixed installation directory for translations.
|
||||||
|
* Fixed collection sorting for non-ASCII characters.
|
||||||
|
* Fixed closing connected devices on exit.
|
||||||
|
|
||||||
|
0.7.1:
|
||||||
|
|
||||||
|
Bugfixes:
|
||||||
|
* Fixed incorrectly mapped global shortcuts keys "2" and "3".
|
||||||
|
* Fixed Last.fm scrobbling to correctly start array notation for parameters at 0 and not 1.
|
||||||
|
* Fixed sending trackNumber correctly for Last.fm and Libre.fm scrobbling.
|
||||||
|
* Fixed collection search when using special characters in the search query.
|
||||||
|
* Fixed reading and saving MP4 lyrics tag.
|
||||||
|
* Fixed reading ASF comment tag.
|
||||||
|
* Fixed adding playlist songs outside the collection when there are multiple files with the same URL.
|
||||||
|
* Fixed the rescan songs option to work with local songs outside of the collection.
|
||||||
|
* Fixed problems with editing song metadata in the playlists.
|
||||||
|
* Fixed saving and restoring playlist scrollbar position when switching between playlists.
|
||||||
|
* Fixed minor issue in cue parser with date and genre.
|
||||||
|
* (macOS) Fixed gst-libav plugin issue resulting in MP3 not working.
|
||||||
|
|
||||||
|
Enhancements:
|
||||||
|
* Simplified and improved startup behaviour code.
|
||||||
|
* Adapted all source code to be compatible with Qt 6, and increased required Qt version to 5.8.
|
||||||
|
* Added option to compile with Qt 6 (-DWITH_QT6=ON).
|
||||||
|
* Base warning for show in file browser on unique directories to avoid unneeded warning about opening many files.
|
||||||
|
* Use album artist instead of artist for album repeat mode when available.
|
||||||
|
* Added extra safety for overwriting files for filesystem storages when organizing files.
|
||||||
|
* Remove diacritics in FTS search.
|
||||||
|
* Improved playlist context menu.
|
||||||
|
* Added fatal CMake error for missing protobuf compiler.
|
||||||
|
* Added support for parsing radio streams metadata with tilde in title.
|
||||||
|
* Added CMake option to install translation files.
|
||||||
|
* Increased maximum time step for seeking to 60.
|
||||||
|
* (Unix) Added playback actions to desktop file.
|
||||||
|
* (macOS) Hide behaviour settings that are unavailable on macOS.
|
||||||
|
* (macOS) Fixed compile warnings.
|
||||||
|
* (macOS) Added Sparkle integration to notify on new versions.
|
||||||
|
* (Windows) Added QtSparkle support to notify on new versions.
|
||||||
|
|
||||||
|
Removed features:
|
||||||
|
* Removed Xine engine support.
|
||||||
|
* Removed broken imobiledevice (iPhone) support.
|
||||||
|
|
||||||
0.6.13:
|
0.6.13:
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
|||||||
17
README.md
17
README.md
@@ -2,7 +2,7 @@
|
|||||||
[](https://paypal.me/jonaskvinge)
|
[](https://paypal.me/jonaskvinge)
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
Strawberry is a music player and music collection organizer. It is a fork of Clementine released in 2018 aimed at music collectors and audiophiles. It's written in C++ using the Qt 5 framework.
|
Strawberry is a music player and music collection organizer. It is a fork of Clementine released in 2018 aimed at music collectors and audiophiles. It's written in C++ using the Qt 5 or 6 toolkit.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ You can also make a one-time payment through [paypal.me/jonaskvinge](https://pay
|
|||||||
* Support for multiple backends
|
* Support for multiple backends
|
||||||
* Audio analyzer
|
* Audio analyzer
|
||||||
* Audio equalizer
|
* Audio equalizer
|
||||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
* Transfer music to iPod, MTP or mass-storage USB player
|
||||||
* Scrobbler with support for [Last.fm](https://www.last.fm/), [Libre.fm](https://libre.fm/) and [ListenBrainz](https://listenbrainz.org/)
|
* Scrobbler with support for [Last.fm](https://www.last.fm/), [Libre.fm](https://libre.fm/) and [ListenBrainz](https://listenbrainz.org/)
|
||||||
* Subsonic and Tidal streaming support
|
* Subsonic and Tidal streaming support
|
||||||
|
|
||||||
@@ -63,14 +63,14 @@ To build Strawberry from source you need the following installed on your system
|
|||||||
* [POSIX thread (pthread)](http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html)
|
* [POSIX thread (pthread)](http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html)
|
||||||
* [GLib](https://developer.gnome.org/glib/)
|
* [GLib](https://developer.gnome.org/glib/)
|
||||||
* [Protobuf library and compiler](https://developers.google.com/protocol-buffers/)
|
* [Protobuf library and compiler](https://developers.google.com/protocol-buffers/)
|
||||||
* [Qt 5.6 or higher with components Core, Gui, Widgets, Concurrent, Network and Sql](https://www.qt.io/)
|
* [Qt 5.8 or higher (or Qt 6) with components Core, Gui, Widgets, Concurrent, Network and Sql](https://www.qt.io/)
|
||||||
* [Qt 5 components X11Extras and DBus for Linux/BSD, MacExtras for macOS and WinExtras for Windows](https://www.qt.io/)
|
* [Qt components X11Extras and DBus for Linux/BSD, MacExtras for macOS and WinExtras for Windows](https://www.qt.io/)
|
||||||
* [SQLite 3.9 or newer with FTS5](https://www.sqlite.org)
|
* [SQLite 3.9 or newer with FTS5](https://www.sqlite.org)
|
||||||
* [Chromaprint library](https://acoustid.org/chromaprint)
|
* [Chromaprint library](https://acoustid.org/chromaprint)
|
||||||
* [ALSA library (linux)](https://www.alsa-project.org/)
|
* [ALSA library (linux)](https://www.alsa-project.org/)
|
||||||
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
|
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
|
||||||
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
|
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
|
||||||
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org) or [VLC](https://www.videolan.org)
|
* [GStreamer](https://gstreamer.freedesktop.org/) or [VLC](https://www.videolan.org)
|
||||||
* [GnuTLS](https://www.gnutls.org/)
|
* [GnuTLS](https://www.gnutls.org/)
|
||||||
|
|
||||||
Optional dependencies:
|
Optional dependencies:
|
||||||
@@ -78,12 +78,13 @@ Optional dependencies:
|
|||||||
* Audio CD: [libcdio](https://www.gnu.org/software/libcdio/)
|
* Audio CD: [libcdio](https://www.gnu.org/software/libcdio/)
|
||||||
* MTP devices: [libmtp](http://libmtp.sourceforge.net/)
|
* MTP devices: [libmtp](http://libmtp.sourceforge.net/)
|
||||||
* iPod Classic devices: [libgpod](http://www.gtkpod.org/libgpod/)
|
* iPod Classic devices: [libgpod](http://www.gtkpod.org/libgpod/)
|
||||||
* iPhone, iPod Touch, iPad and Apple TV devices: [libimobiledevice, libplist and libusbmuxd](https://www.libimobiledevice.org/)
|
|
||||||
* Moodbar: [fftw3](http://www.fftw.org/)
|
* Moodbar: [fftw3](http://www.fftw.org/)
|
||||||
|
|
||||||
Either GStreamer, Xine or VLC engine is required, but only GStreamer is fully implemented so far.
|
Either GStreamer or VLC engine is required, but only GStreamer is fully implemented so far.
|
||||||
You should also install the gstreamer plugins base and good, and optionally bad and ugly.
|
You should also install the gstreamer plugins base and good, and optionally bad and ugly.
|
||||||
|
|
||||||
|
With Qt 6 we also depend on the Core5Compat module for QTextCodec.
|
||||||
|
|
||||||
### :wrench: Compiling from source
|
### :wrench: Compiling from source
|
||||||
|
|
||||||
### Get the code:
|
### Get the code:
|
||||||
@@ -97,6 +98,8 @@ You should also install the gstreamer plugins base and good, and optionally bad
|
|||||||
cmake ..
|
cmake ..
|
||||||
make -j4
|
make -j4
|
||||||
sudo make install
|
sudo make install
|
||||||
|
|
||||||
|
To compile with Qt 6 use: cmake .. -DWITH_QT6=ON
|
||||||
|
|
||||||
### :penguin: Packaging status
|
### :penguin: Packaging status
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
add_custom_target(dmg
|
add_custom_target(dmg
|
||||||
COMMAND /usr/local/opt/qt5/bin/macdeployqt strawberry.app
|
COMMAND /usr/local/opt/qt5/bin/macdeployqt strawberry.app
|
||||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/macos/macdeploy.py strawberry.app
|
COMMAND ${CMAKE_SOURCE_DIR}/dist/macos/macdeploy.py strawberry.app
|
||||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/macos/create-dmg.sh strawberry.app
|
COMMAND create-dmg --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}.dmg strawberry.app
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,7 +15,11 @@ macro(optional_source TOGGLE)
|
|||||||
list(APPEND OTHER_SOURCES ${OPTIONAL_SOURCE_HEADERS})
|
list(APPEND OTHER_SOURCES ${OPTIONAL_SOURCE_HEADERS})
|
||||||
|
|
||||||
set(_uic_sources)
|
set(_uic_sources)
|
||||||
qt5_wrap_ui(_uic_sources ${OPTIONAL_SOURCE_UI})
|
if(WITH_QT6)
|
||||||
|
qt6_wrap_ui(_uic_sources ${OPTIONAL_SOURCE_UI})
|
||||||
|
else()
|
||||||
|
qt5_wrap_ui(_uic_sources ${OPTIONAL_SOURCE_UI})
|
||||||
|
endif()
|
||||||
list(APPEND OTHER_SOURCES ${_uic_sources})
|
list(APPEND OTHER_SOURCES ${_uic_sources})
|
||||||
list(APPEND OTHER_UIC_SOURCES ${_uic_sources})
|
list(APPEND OTHER_UIC_SOURCES ${_uic_sources})
|
||||||
endif(${TOGGLE})
|
endif(${TOGGLE})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.11)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
|
||||||
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
|
find_program(GETTEXT_XGETTEXT_EXECUTABLE xgettext)
|
||||||
if(NOT GETTEXT_XGETTEXT_EXECUTABLE)
|
if(NOT GETTEXT_XGETTEXT_EXECUTABLE)
|
||||||
@@ -19,6 +19,8 @@ set (XGETTEXT_OPTIONS
|
|||||||
--from-code=utf-8
|
--from-code=utf-8
|
||||||
)
|
)
|
||||||
|
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}/translations)
|
||||||
|
|
||||||
macro(add_pot outfiles header pot)
|
macro(add_pot outfiles header pot)
|
||||||
# Make relative filenames for all source files
|
# Make relative filenames for all source files
|
||||||
set(add_pot_sources)
|
set(add_pot_sources)
|
||||||
@@ -64,14 +66,21 @@ macro(add_po outfiles po_prefix)
|
|||||||
)
|
)
|
||||||
|
|
||||||
list(APPEND ${outfiles} ${_qm_filepath})
|
list(APPEND ${outfiles} ${_qm_filepath})
|
||||||
|
list(APPEND INSTALL_TRANSLATIONS_FILES ${_qm_filepath})
|
||||||
endforeach (_lang)
|
endforeach (_lang)
|
||||||
|
|
||||||
# Generate a qrc file for the translations
|
# Generate a qrc file for the translations
|
||||||
set(_qrc ${CMAKE_CURRENT_BINARY_DIR}/${ADD_PO_DIRECTORY}/translations.qrc)
|
if(NOT INSTALL_TRANSLATIONS)
|
||||||
file(WRITE ${_qrc} "<RCC><qresource prefix=\"/${ADD_PO_DIRECTORY}\">")
|
set(_qrc ${CMAKE_CURRENT_BINARY_DIR}/${ADD_PO_DIRECTORY}/translations.qrc)
|
||||||
foreach(_lang ${ADD_PO_LANGUAGES})
|
file(WRITE ${_qrc} "<RCC><qresource prefix=\"/${ADD_PO_DIRECTORY}\">")
|
||||||
file(APPEND ${_qrc} "<file>${po_prefix}${_lang}.qm</file>")
|
foreach(_lang ${ADD_PO_LANGUAGES})
|
||||||
endforeach(_lang)
|
file(APPEND ${_qrc} "<file>${po_prefix}${_lang}.qm</file>")
|
||||||
file(APPEND ${_qrc} "</qresource></RCC>")
|
endforeach(_lang)
|
||||||
qt5_add_resources(${outfiles} ${_qrc})
|
file(APPEND ${_qrc} "</qresource></RCC>")
|
||||||
|
if(WITH_QT6)
|
||||||
|
qt6_add_resources(${outfiles} ${_qrc})
|
||||||
|
else()
|
||||||
|
qt5_add_resources(${outfiles} ${_qrc})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
endmacro(add_po)
|
endmacro(add_po)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
set(STRAWBERRY_VERSION_MAJOR 0)
|
set(STRAWBERRY_VERSION_MAJOR 0)
|
||||||
set(STRAWBERRY_VERSION_MINOR 6)
|
set(STRAWBERRY_VERSION_MINOR 7)
|
||||||
set(STRAWBERRY_VERSION_PATCH 13)
|
set(STRAWBERRY_VERSION_PATCH 2)
|
||||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||||
|
|
||||||
set(INCLUDE_GIT_REVISION OFF)
|
set(INCLUDE_GIT_REVISION OFF)
|
||||||
|
|||||||
@@ -81,7 +81,6 @@
|
|||||||
<file>icons/128x128/view-refresh.png</file>
|
<file>icons/128x128/view-refresh.png</file>
|
||||||
<file>icons/128x128/library-music.png</file>
|
<file>icons/128x128/library-music.png</file>
|
||||||
<file>icons/128x128/vlc.png</file>
|
<file>icons/128x128/vlc.png</file>
|
||||||
<file>icons/128x128/xine.png</file>
|
|
||||||
<file>icons/128x128/zoom-in.png</file>
|
<file>icons/128x128/zoom-in.png</file>
|
||||||
<file>icons/128x128/zoom-out.png</file>
|
<file>icons/128x128/zoom-out.png</file>
|
||||||
<file>icons/128x128/scrobble.png</file>
|
<file>icons/128x128/scrobble.png</file>
|
||||||
@@ -172,7 +171,6 @@
|
|||||||
<file>icons/64x64/view-refresh.png</file>
|
<file>icons/64x64/view-refresh.png</file>
|
||||||
<file>icons/64x64/library-music.png</file>
|
<file>icons/64x64/library-music.png</file>
|
||||||
<file>icons/64x64/vlc.png</file>
|
<file>icons/64x64/vlc.png</file>
|
||||||
<file>icons/64x64/xine.png</file>
|
|
||||||
<file>icons/64x64/zoom-in.png</file>
|
<file>icons/64x64/zoom-in.png</file>
|
||||||
<file>icons/64x64/zoom-out.png</file>
|
<file>icons/64x64/zoom-out.png</file>
|
||||||
<file>icons/64x64/scrobble.png</file>
|
<file>icons/64x64/scrobble.png</file>
|
||||||
@@ -267,7 +265,6 @@
|
|||||||
<file>icons/48x48/view-refresh.png</file>
|
<file>icons/48x48/view-refresh.png</file>
|
||||||
<file>icons/48x48/library-music.png</file>
|
<file>icons/48x48/library-music.png</file>
|
||||||
<file>icons/48x48/vlc.png</file>
|
<file>icons/48x48/vlc.png</file>
|
||||||
<file>icons/48x48/xine.png</file>
|
|
||||||
<file>icons/48x48/zoom-in.png</file>
|
<file>icons/48x48/zoom-in.png</file>
|
||||||
<file>icons/48x48/zoom-out.png</file>
|
<file>icons/48x48/zoom-out.png</file>
|
||||||
<file>icons/48x48/scrobble.png</file>
|
<file>icons/48x48/scrobble.png</file>
|
||||||
@@ -362,7 +359,6 @@
|
|||||||
<file>icons/32x32/view-refresh.png</file>
|
<file>icons/32x32/view-refresh.png</file>
|
||||||
<file>icons/32x32/library-music.png</file>
|
<file>icons/32x32/library-music.png</file>
|
||||||
<file>icons/32x32/vlc.png</file>
|
<file>icons/32x32/vlc.png</file>
|
||||||
<file>icons/32x32/xine.png</file>
|
|
||||||
<file>icons/32x32/zoom-in.png</file>
|
<file>icons/32x32/zoom-in.png</file>
|
||||||
<file>icons/32x32/zoom-out.png</file>
|
<file>icons/32x32/zoom-out.png</file>
|
||||||
<file>icons/32x32/scrobble.png</file>
|
<file>icons/32x32/scrobble.png</file>
|
||||||
@@ -457,7 +453,6 @@
|
|||||||
<file>icons/22x22/view-refresh.png</file>
|
<file>icons/22x22/view-refresh.png</file>
|
||||||
<file>icons/22x22/library-music.png</file>
|
<file>icons/22x22/library-music.png</file>
|
||||||
<file>icons/22x22/vlc.png</file>
|
<file>icons/22x22/vlc.png</file>
|
||||||
<file>icons/22x22/xine.png</file>
|
|
||||||
<file>icons/22x22/zoom-in.png</file>
|
<file>icons/22x22/zoom-in.png</file>
|
||||||
<file>icons/22x22/zoom-out.png</file>
|
<file>icons/22x22/zoom-out.png</file>
|
||||||
<file>icons/22x22/scrobble.png</file>
|
<file>icons/22x22/scrobble.png</file>
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 2.2 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 3.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 5.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 8.3 KiB |
@@ -72,7 +72,7 @@ CREATE INDEX idx_device_%deviceid_songs_comp_artist ON device_%deviceid_songs (c
|
|||||||
|
|
||||||
CREATE VIRTUAL TABLE device_%deviceid_fts USING fts5(
|
CREATE VIRTUAL TABLE device_%deviceid_fts USING fts5(
|
||||||
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
|
ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
);
|
);
|
||||||
|
|
||||||
UPDATE devices SET schema_version=1 WHERE ROWID=%deviceid;
|
UPDATE devices SET schema_version=1 WHERE ROWID=%deviceid;
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ CREATE VIRTUAL TABLE %allsongstables_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -28,7 +28,7 @@ CREATE VIRTUAL TABLE playlist_items_fts_ USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ CREATE TABLE IF NOT EXISTS songs (
|
|||||||
track INTEGER NOT NULL DEFAULT -1,
|
track INTEGER NOT NULL DEFAULT -1,
|
||||||
disc INTEGER NOT NULL DEFAULT -1,
|
disc INTEGER NOT NULL DEFAULT -1,
|
||||||
year INTEGER NOT NULL DEFAULT -1,
|
year INTEGER NOT NULL DEFAULT -1,
|
||||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||||
genre TEXT,
|
genre TEXT,
|
||||||
compilation INTEGER NOT NULL DEFAULT 0,
|
compilation INTEGER NOT NULL DEFAULT 0,
|
||||||
composer TEXT,
|
composer TEXT,
|
||||||
@@ -83,7 +83,7 @@ CREATE TABLE IF NOT EXISTS tidal_artists_songs (
|
|||||||
track INTEGER NOT NULL DEFAULT -1,
|
track INTEGER NOT NULL DEFAULT -1,
|
||||||
disc INTEGER NOT NULL DEFAULT -1,
|
disc INTEGER NOT NULL DEFAULT -1,
|
||||||
year INTEGER NOT NULL DEFAULT -1,
|
year INTEGER NOT NULL DEFAULT -1,
|
||||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||||
genre TEXT,
|
genre TEXT,
|
||||||
compilation INTEGER NOT NULL DEFAULT 0,
|
compilation INTEGER NOT NULL DEFAULT 0,
|
||||||
composer TEXT,
|
composer TEXT,
|
||||||
@@ -140,7 +140,7 @@ CREATE TABLE IF NOT EXISTS tidal_albums_songs (
|
|||||||
track INTEGER NOT NULL DEFAULT -1,
|
track INTEGER NOT NULL DEFAULT -1,
|
||||||
disc INTEGER NOT NULL DEFAULT -1,
|
disc INTEGER NOT NULL DEFAULT -1,
|
||||||
year INTEGER NOT NULL DEFAULT -1,
|
year INTEGER NOT NULL DEFAULT -1,
|
||||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||||
genre TEXT,
|
genre TEXT,
|
||||||
compilation INTEGER NOT NULL DEFAULT 0,
|
compilation INTEGER NOT NULL DEFAULT 0,
|
||||||
composer TEXT,
|
composer TEXT,
|
||||||
@@ -197,7 +197,7 @@ CREATE TABLE IF NOT EXISTS tidal_songs (
|
|||||||
track INTEGER NOT NULL DEFAULT -1,
|
track INTEGER NOT NULL DEFAULT -1,
|
||||||
disc INTEGER NOT NULL DEFAULT -1,
|
disc INTEGER NOT NULL DEFAULT -1,
|
||||||
year INTEGER NOT NULL DEFAULT -1,
|
year INTEGER NOT NULL DEFAULT -1,
|
||||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||||
genre TEXT,
|
genre TEXT,
|
||||||
compilation INTEGER NOT NULL DEFAULT 0,
|
compilation INTEGER NOT NULL DEFAULT 0,
|
||||||
composer TEXT,
|
composer TEXT,
|
||||||
@@ -254,7 +254,7 @@ CREATE TABLE IF NOT EXISTS subsonic_songs (
|
|||||||
track INTEGER NOT NULL DEFAULT -1,
|
track INTEGER NOT NULL DEFAULT -1,
|
||||||
disc INTEGER NOT NULL DEFAULT -1,
|
disc INTEGER NOT NULL DEFAULT -1,
|
||||||
year INTEGER NOT NULL DEFAULT -1,
|
year INTEGER NOT NULL DEFAULT -1,
|
||||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
originalyear INTEGER NOT NULL DEFAULT -1,
|
||||||
genre TEXT,
|
genre TEXT,
|
||||||
compilation INTEGER NOT NULL DEFAULT 0,
|
compilation INTEGER NOT NULL DEFAULT 0,
|
||||||
composer TEXT,
|
composer TEXT,
|
||||||
@@ -410,7 +410,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -425,7 +425,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -440,7 +440,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -455,7 +455,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -470,7 +470,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS subsonic_songs_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -485,7 +485,7 @@ CREATE VIRTUAL TABLE IF NOT EXISTS playlist_items_fts_ USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -500,6 +500,6 @@ CREATE VIRTUAL TABLE IF NOT EXISTS %allsongstables_fts USING fts5(
|
|||||||
ftsgrouping,
|
ftsgrouping,
|
||||||
ftsgenre,
|
ftsgenre,
|
||||||
ftscomment,
|
ftscomment,
|
||||||
tokenize = "unicode61 remove_diacritics 0"
|
tokenize = "unicode61 remove_diacritics 1"
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
3
debian/control
vendored
3
debian/control
vendored
@@ -24,10 +24,7 @@ Build-Depends: debhelper (>= 11),
|
|||||||
libgstreamer-plugins-base1.0-dev,
|
libgstreamer-plugins-base1.0-dev,
|
||||||
libcdio-dev,
|
libcdio-dev,
|
||||||
libgpod-dev,
|
libgpod-dev,
|
||||||
libimobiledevice-dev,
|
|
||||||
libmtp-dev,
|
libmtp-dev,
|
||||||
libplist-dev,
|
|
||||||
libusbmuxd-dev,
|
|
||||||
libchromaprint-dev,
|
libchromaprint-dev,
|
||||||
libfftw3-dev
|
libfftw3-dev
|
||||||
Standards-Version: 4.2.1
|
Standards-Version: 4.2.1
|
||||||
|
|||||||
37
debian/copyright
vendored
37
debian/copyright
vendored
@@ -122,8 +122,14 @@ Files: src/core/main.cpp
|
|||||||
src/context/contextalbumsview.h
|
src/context/contextalbumsview.h
|
||||||
src/widgets/playingwidget.cpp
|
src/widgets/playingwidget.cpp
|
||||||
src/widgets/playingwidget.h
|
src/widgets/playingwidget.h
|
||||||
src/widgets/osdpretty.cpp
|
src/osd/osdbase.cpp
|
||||||
src/widgets/osdpretty.h
|
src/osd/osdbase.h
|
||||||
|
src/osd/osdpretty.cpp
|
||||||
|
src/osd/osdpretty.h
|
||||||
|
src/osd/osddbus.cpp
|
||||||
|
src/osd/osddbus.h
|
||||||
|
src/osd/osdmac.cpp
|
||||||
|
src/osd/osdmac.h
|
||||||
src/dialogs/about.cpp
|
src/dialogs/about.cpp
|
||||||
src/dialogs/about.h
|
src/dialogs/about.h
|
||||||
src/playlist/playlist.cpp
|
src/playlist/playlist.cpp
|
||||||
@@ -171,12 +177,12 @@ Files: src/core/main.cpp
|
|||||||
src/settings/shortcutssettingspage.h
|
src/settings/shortcutssettingspage.h
|
||||||
src/settings/appearancesettingspage.cpp
|
src/settings/appearancesettingspage.cpp
|
||||||
src/settings/appearancesettingspage.h
|
src/settings/appearancesettingspage.h
|
||||||
src/organise/organise.cpp
|
src/organize/organize.cpp
|
||||||
src/organise/organise.h
|
src/organize/organize.h
|
||||||
src/organise/organisedialog.cpp
|
src/organize/organizedialog.cpp
|
||||||
src/organise/organisedialog.h
|
src/organize/organizedialog.h
|
||||||
src/organise/organiseerrordialog.cpp
|
src/organize/organizeerrordialog.cpp
|
||||||
src/organise/organiseerrordialog.h
|
src/organize/organizeerrordialog.h
|
||||||
src/transcoder/transcoder.cpp
|
src/transcoder/transcoder.cpp
|
||||||
src/transcoder/transcoder.h
|
src/transcoder/transcoder.h
|
||||||
src/musicbrainz/musicbrainzclient.cpp
|
src/musicbrainz/musicbrainzclient.cpp
|
||||||
@@ -213,21 +219,6 @@ Copyright: 2017, 2018, Jonas Kvinge <jonas@jkvinge.net>
|
|||||||
2003-2005, Mark Kretschmann <markey@web.de>
|
2003-2005, Mark Kretschmann <markey@web.de>
|
||||||
License: GPL-2+
|
License: GPL-2+
|
||||||
|
|
||||||
Files: src/engine/xineengine.cpp
|
|
||||||
src/engine/xineengine.h
|
|
||||||
Copyright: 2017, 2018, Jonas Kvinge <jonas@jkvinge.net>
|
|
||||||
2005, Ian Monroe <ian@monroe.nu>
|
|
||||||
2005, Christophe Thommeret <hftom@free.fr>
|
|
||||||
2005, 2006, Mark Kretschmann <markey@web.de>
|
|
||||||
2004, 2005, Max Howell <max.howell@methylblue.com>
|
|
||||||
2003, 2004, J. Kofler <kaffeine@gmx.net>
|
|
||||||
License: GPL-2+
|
|
||||||
|
|
||||||
Files: src/engine/xinescope.c
|
|
||||||
src/engine/xinescope.h
|
|
||||||
Copyright: 2004, Max Howell <max.howell@methylblue.com>
|
|
||||||
License: GPL-2+
|
|
||||||
|
|
||||||
Files: src/widgets/fancytabwidget.cpp
|
Files: src/widgets/fancytabwidget.cpp
|
||||||
src/widgets/fancytabwidget.h
|
src/widgets/fancytabwidget.h
|
||||||
Copyright: 2018, Vikram Ambrose <ambroseworks@gmail.com>
|
Copyright: 2018, Vikram Ambrose <ambroseworks@gmail.com>
|
||||||
|
|||||||
1
debian/rules
vendored
1
debian/rules
vendored
@@ -5,7 +5,6 @@
|
|||||||
|
|
||||||
override_dh_auto_clean:
|
override_dh_auto_clean:
|
||||||
rm -f dist/macos/Info.plist
|
rm -f dist/macos/Info.plist
|
||||||
rm -f dist/macos/create-dmg.sh
|
|
||||||
rm -f dist/unix/PKGBUILD
|
rm -f dist/unix/PKGBUILD
|
||||||
rm -f dist/unix/strawberry.spec
|
rm -f dist/unix/strawberry.spec
|
||||||
rm -f dist/scripts/maketarball.sh
|
rm -f dist/scripts/maketarball.sh
|
||||||
|
|||||||
1
dist/CMakeLists.txt
vendored
1
dist/CMakeLists.txt
vendored
@@ -3,7 +3,6 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD.in ${CMAKE_CURRENT_SOUR
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/create-dmg.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/create-dmg.sh)
|
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|||||||
4
dist/macos/Info.plist.in
vendored
4
dist/macos/Info.plist.in
vendored
@@ -34,6 +34,10 @@
|
|||||||
<string>public.app-category.music</string>
|
<string>public.app-category.music</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
<string>10.13.4</string>
|
<string>10.13.4</string>
|
||||||
|
<key>SUFeedURL</key>
|
||||||
|
<string>https://www.strawberrymusicplayer.org/sparkle-macos</string>
|
||||||
|
<key>SUPublicEDKey</key>
|
||||||
|
<string>3IRScV8YtNVnx7zoeJAXvg28Kh1gN/Pyl2iPM467pG8=</string>
|
||||||
<key>CFBundleDocumentTypes</key>
|
<key>CFBundleDocumentTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
|||||||
24
dist/macos/create-dmg.sh.in
vendored
24
dist/macos/create-dmg.sh.in
vendored
@@ -1,24 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
version="@STRAWBERRY_VERSION_PACKAGE@"
|
|
||||||
|
|
||||||
if [ -z "$1" ]; then
|
|
||||||
echo "Usage: $0 <bundle.app> (append)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
name=$(basename "$1" | perl -pe 's/(.*).app/\1/')
|
|
||||||
bundle_dir="$1"
|
|
||||||
temp_dir="dmg/$name"
|
|
||||||
if [ -z "$2" ]; then
|
|
||||||
output_file="$name-$version.dmg"
|
|
||||||
else
|
|
||||||
output_file="$name-$2-$version.dmg"
|
|
||||||
fi
|
|
||||||
|
|
||||||
rm -rf "$temp_dir"
|
|
||||||
rm -f "$output_file"
|
|
||||||
|
|
||||||
mkdir -p "$temp_dir"
|
|
||||||
|
|
||||||
/usr/local/bin/create-dmg --volname "$name" --background "@CMAKE_SOURCE_DIR@/dist/macos/dmg_background.png" --app-drop-link 450 218 --icon $bundle_dir 150 218 --window-size 600 450 $output_file $bundle_dir
|
|
||||||
60
dist/macos/macdeploy.py
vendored
60
dist/macos/macdeploy.py
vendored
@@ -27,11 +27,12 @@ import traceback
|
|||||||
|
|
||||||
LOGGER = logging.getLogger('macdeploy')
|
LOGGER = logging.getLogger('macdeploy')
|
||||||
|
|
||||||
LIBRARY_SEARCH_PATH = ['/usr/local/lib']
|
LIBRARY_SEARCH_PATH = ['/usr/local/lib', '/usr/local/opt/icu4c/lib']
|
||||||
|
|
||||||
FRAMEWORK_SEARCH_PATH = [
|
FRAMEWORK_SEARCH_PATH = [
|
||||||
'/Library/Frameworks',
|
'/Library/Frameworks',
|
||||||
os.path.join(os.environ['HOME'], 'Library/Frameworks')
|
os.path.join(os.environ['HOME'], 'Library/Frameworks'),
|
||||||
|
'/Library/Frameworks/Sparkle.framework/Versions'
|
||||||
]
|
]
|
||||||
|
|
||||||
QT_PLUGINS = [
|
QT_PLUGINS = [
|
||||||
@@ -154,12 +155,6 @@ class InstallNameToolError(Error):
|
|||||||
class CouldNotFindGstreamerPluginError(Error):
|
class CouldNotFindGstreamerPluginError(Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class CouldNotFindXinePluginError(Error):
|
|
||||||
pass
|
|
||||||
|
|
||||||
class CouldNotFindVLCPluginError(Error):
|
|
||||||
pass
|
|
||||||
|
|
||||||
if len(sys.argv) < 2:
|
if len(sys.argv) < 2:
|
||||||
print 'Usage: %s <bundle.app>' % sys.argv[0]
|
print 'Usage: %s <bundle.app>' % sys.argv[0]
|
||||||
|
|
||||||
@@ -196,11 +191,22 @@ def GetBrokenLibraries(binary):
|
|||||||
elif re.match(r'^\s*/usr/lib/', line):
|
elif re.match(r'^\s*/usr/lib/', line):
|
||||||
#print "unix style system lib"
|
#print "unix style system lib"
|
||||||
continue # unix style system library
|
continue # unix style system library
|
||||||
elif re.match(r'^\s*@executable_path', line) or re.match(r'^\s*@loader_path', line):
|
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
|
# Potentially already fixed library
|
||||||
relative_path = os.path.join(*line.split('/')[3:])
|
if line.count('/') == 1:
|
||||||
if not os.path.exists(os.path.join(frameworks_dir, relative_path)):
|
relative_path = os.path.join(*line.split('/')[1:])
|
||||||
broken_libs['frameworks'].append(relative_path)
|
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):
|
elif re.search(r'\w+\.framework', line):
|
||||||
broken_libs['frameworks'].append(line)
|
broken_libs['frameworks'].append(line)
|
||||||
else:
|
else:
|
||||||
@@ -261,14 +267,21 @@ def FixFramework(path):
|
|||||||
|
|
||||||
|
|
||||||
def FixLibrary(path):
|
def FixLibrary(path):
|
||||||
if path in fixed_libraries or FindSystemLibrary(os.path.basename(path)) is not None:
|
|
||||||
|
if path in fixed_libraries:
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
fixed_libraries.add(path)
|
# 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)
|
abs_path = FindLibrary(path)
|
||||||
if abs_path == "":
|
if abs_path == "":
|
||||||
print "Could not resolve %s, not fixing!" % path
|
print "Could not resolve %s, not fixing!" % path
|
||||||
return
|
return
|
||||||
|
|
||||||
broken_libs = GetBrokenLibraries(abs_path)
|
broken_libs = GetBrokenLibraries(abs_path)
|
||||||
FixAllLibraries(broken_libs)
|
FixAllLibraries(broken_libs)
|
||||||
|
|
||||||
@@ -416,7 +429,7 @@ def FindSystemLibrary(library_name):
|
|||||||
|
|
||||||
def FixLibraryInstallPath(library_path, library):
|
def FixLibraryInstallPath(library_path, library):
|
||||||
system_library = FindSystemLibrary(os.path.basename(library_path))
|
system_library = FindSystemLibrary(os.path.basename(library_path))
|
||||||
if system_library is None:
|
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)
|
new_path = '@executable_path/../Frameworks/%s' % os.path.basename(library_path)
|
||||||
FixInstallPath(library_path, library, new_path)
|
FixInstallPath(library_path, library, new_path)
|
||||||
else:
|
else:
|
||||||
@@ -425,21 +438,14 @@ def FixLibraryInstallPath(library_path, library):
|
|||||||
|
|
||||||
def FixFrameworkInstallPath(library_path, library):
|
def FixFrameworkInstallPath(library_path, library):
|
||||||
parts = library_path.split(os.sep)
|
parts = library_path.split(os.sep)
|
||||||
|
full_path = ""
|
||||||
for i, part in enumerate(parts):
|
for i, part in enumerate(parts):
|
||||||
if re.match(r'\w+\.framework', part):
|
if re.match(r'\w+\.framework', part):
|
||||||
full_path = os.path.join(*parts[i:])
|
full_path = os.path.join(*parts[i:])
|
||||||
break
|
break
|
||||||
new_path = '@executable_path/../Frameworks/%s' % full_path
|
if full_path:
|
||||||
FixInstallPath(library_path, library, new_path)
|
new_path = '@executable_path/../Frameworks/%s' % full_path
|
||||||
|
FixInstallPath(library_path, library, new_path)
|
||||||
|
|
||||||
def FindXinePlugin(name):
|
|
||||||
for path in XINEPLUGIN_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 CouldNotFindXinePluginError(name)
|
|
||||||
|
|
||||||
|
|
||||||
def FindQtPlugin(name):
|
def FindQtPlugin(name):
|
||||||
|
|||||||
1
dist/scripts/maketarball.sh.in
vendored
1
dist/scripts/maketarball.sh.in
vendored
@@ -38,7 +38,6 @@ tar -cJf $name-$version.tar.xz \
|
|||||||
--exclude="$root/debian/changelog" \
|
--exclude="$root/debian/changelog" \
|
||||||
--exclude="$root/dist/scripts/maketarball.sh" \
|
--exclude="$root/dist/scripts/maketarball.sh" \
|
||||||
--exclude="$root/dist/unix/PKGBUILD" \
|
--exclude="$root/dist/unix/PKGBUILD" \
|
||||||
--exclude="$root/dist/macos/create-dmg.sh" \
|
|
||||||
--exclude="$root/dist/macos/Info.plist" \
|
--exclude="$root/dist/macos/Info.plist" \
|
||||||
--exclude="$root/dist/windows/windres.rc" \
|
--exclude="$root/dist/windows/windres.rc" \
|
||||||
--exclude="$root/src/translations/translations.pot" \
|
--exclude="$root/src/translations/translations.pot" \
|
||||||
|
|||||||
4
dist/unix/PKGBUILD.in
vendored
4
dist/unix/PKGBUILD.in
vendored
@@ -23,15 +23,11 @@ depends=(
|
|||||||
gstreamer
|
gstreamer
|
||||||
gst-plugins-base
|
gst-plugins-base
|
||||||
gst-plugins-good
|
gst-plugins-good
|
||||||
xine-lib
|
|
||||||
vlc
|
vlc
|
||||||
chromaprint
|
chromaprint
|
||||||
libgpod
|
libgpod
|
||||||
libcdio
|
libcdio
|
||||||
libmtp
|
libmtp
|
||||||
libusbmuxd
|
|
||||||
libplist
|
|
||||||
libimobiledevice
|
|
||||||
fftw
|
fftw
|
||||||
)
|
)
|
||||||
optdepends=(
|
optdepends=(
|
||||||
|
|||||||
@@ -12,3 +12,28 @@ Categories=AudioVideo;Player;Qt;Audio;
|
|||||||
StartupNotify=false
|
StartupNotify=false
|
||||||
MimeType=x-content/audio-player;application/ogg;application/x-ogg;application/x-ogm-audio;audio/flac;audio/ogg;audio/vorbis;audio/aac;audio/mp4;audio/mpeg;audio/mpegurl;audio/vnd.rn-realaudio;audio/x-flac;audio/x-oggflac;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-speex;audio/x-wav;audio/x-wavpack;audio/x-ape;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-wma;audio/x-musepack;audio/x-pn-realaudio;audio/x-scpls;video/x-ms-asf;x-scheme-handler/tidal;
|
MimeType=x-content/audio-player;application/ogg;application/x-ogg;application/x-ogm-audio;audio/flac;audio/ogg;audio/vorbis;audio/aac;audio/mp4;audio/mpeg;audio/mpegurl;audio/vnd.rn-realaudio;audio/x-flac;audio/x-oggflac;audio/x-vorbis;audio/x-vorbis+ogg;audio/x-speex;audio/x-wav;audio/x-wavpack;audio/x-ape;audio/x-mp3;audio/x-mpeg;audio/x-mpegurl;audio/x-ms-wma;audio/x-musepack;audio/x-pn-realaudio;audio/x-scpls;video/x-ms-asf;x-scheme-handler/tidal;
|
||||||
StartupWMClass=strawberry
|
StartupWMClass=strawberry
|
||||||
|
Actions=Play;Pause;Stop;StopAfterCurrent;Previous;Next;
|
||||||
|
|
||||||
|
[Desktop Action Play]
|
||||||
|
Name=Play
|
||||||
|
Exec=strawberry --play
|
||||||
|
|
||||||
|
[Desktop Action Pause]
|
||||||
|
Name=Pause
|
||||||
|
Exec=strawberry --pause
|
||||||
|
|
||||||
|
[Desktop Action Stop]
|
||||||
|
Name=Stop
|
||||||
|
Exec=strawberry --stop
|
||||||
|
|
||||||
|
[Desktop Action StopAfterCurrent]
|
||||||
|
Name=Stop after this track
|
||||||
|
Exec=strawberry --stop-after-current
|
||||||
|
|
||||||
|
[Desktop Action Previous]
|
||||||
|
Name=Previous
|
||||||
|
Exec=strawberry --previous
|
||||||
|
|
||||||
|
[Desktop Action Next]
|
||||||
|
Name=Next
|
||||||
|
Exec=strawberry --next
|
||||||
|
|||||||
5
dist/unix/strawberry.spec.in
vendored
5
dist/unix/strawberry.spec.in
vendored
@@ -1,7 +1,7 @@
|
|||||||
Name: strawberry
|
Name: strawberry
|
||||||
Version: @STRAWBERRY_VERSION_RPM_V@
|
Version: @STRAWBERRY_VERSION_RPM_V@
|
||||||
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
||||||
Summary: A music player and music collection organiser
|
Summary: A music player and music collection organizer
|
||||||
Group: Applications/Multimedia
|
Group: Applications/Multimedia
|
||||||
License: GPL-3.0+
|
License: GPL-3.0+
|
||||||
URL: https://www.strawberrymusicplayer.org/
|
URL: https://www.strawberrymusicplayer.org/
|
||||||
@@ -73,7 +73,6 @@ BuildRequires: pkgconfig(libmtp)
|
|||||||
BuildRequires: pkgconfig(libnotify)
|
BuildRequires: pkgconfig(libnotify)
|
||||||
BuildRequires: pkgconfig(libudf)
|
BuildRequires: pkgconfig(libudf)
|
||||||
%if 0%{?suse_version} || 0%{?fedora_version}
|
%if 0%{?suse_version} || 0%{?fedora_version}
|
||||||
BuildRequires: pkgconfig(libxine)
|
|
||||||
BuildRequires: pkgconfig(libvlc)
|
BuildRequires: pkgconfig(libvlc)
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
@@ -107,7 +106,7 @@ Features:
|
|||||||
- Support for multiple backends
|
- Support for multiple backends
|
||||||
- Audio analyzer
|
- Audio analyzer
|
||||||
- Audio equalizer
|
- Audio equalizer
|
||||||
- Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
- Transfer music to iPod, MTP or mass-storage USB player
|
||||||
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
|
- Scrobbler with support for Last.fm, Libre.fm and ListenBrainz
|
||||||
- Streaming support for Subsonic
|
- Streaming support for Subsonic
|
||||||
|
|
||||||
|
|||||||
49
dist/windows/strawberry.nsi.in
vendored
49
dist/windows/strawberry.nsi.in
vendored
@@ -18,6 +18,10 @@
|
|||||||
!define debug
|
!define debug
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
|
!if "@WITH_QT6@" == "ON"
|
||||||
|
!define with_qt6
|
||||||
|
!endif
|
||||||
|
|
||||||
!ifdef debug
|
!ifdef debug
|
||||||
!define PRODUCT_NAME "Strawberry Music Player Debug"
|
!define PRODUCT_NAME "Strawberry Music Player Debug"
|
||||||
!define PRODUCT_NAME_SHORT "Strawberry"
|
!define PRODUCT_NAME_SHORT "Strawberry"
|
||||||
@@ -91,17 +95,33 @@ SetCompressor /SOLID lzma
|
|||||||
Name "${PRODUCT_NAME}"
|
Name "${PRODUCT_NAME}"
|
||||||
!ifdef arch_x86
|
!ifdef arch_x86
|
||||||
!ifdef debug
|
!ifdef debug
|
||||||
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x86.exe"
|
!ifdef with_qt6
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Qt6-Debug-x86.exe"
|
||||||
|
!else
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x86.exe"
|
||||||
|
!endif
|
||||||
!else
|
!else
|
||||||
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-x86.exe"
|
!ifdef with_qt6
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Qt6-x86.exe"
|
||||||
|
!else
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-x86.exe"
|
||||||
|
!endif
|
||||||
!endif
|
!endif
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
!ifdef arch_x64
|
!ifdef arch_x64
|
||||||
!ifdef debug
|
!ifdef debug
|
||||||
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
|
!ifdef with_qt6
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Qt6-Debug-x64.exe"
|
||||||
|
!else
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
|
||||||
|
!endif
|
||||||
!else
|
!else
|
||||||
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-x64.exe"
|
!ifdef with_qt6
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-Qt6-x64.exe"
|
||||||
|
!else
|
||||||
|
OutFile "${PRODUCT_NAME_SHORT}Setup-${PRODUCT_DISPLAY_VERSION}-x64.exe"
|
||||||
|
!endif
|
||||||
!endif
|
!endif
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
@@ -209,6 +229,16 @@ Section "Strawberry" Strawberry
|
|||||||
File "libwavpack-1.dll"
|
File "libwavpack-1.dll"
|
||||||
File "libwinpthread-1.dll"
|
File "libwinpthread-1.dll"
|
||||||
File "libxml2-2.dll"
|
File "libxml2-2.dll"
|
||||||
|
!ifdef with_qt6
|
||||||
|
File "Qt6Concurrent.dll"
|
||||||
|
File "Qt6Core.dll"
|
||||||
|
File "Qt6Gui.dll"
|
||||||
|
File "Qt6Network.dll"
|
||||||
|
File "Qt6Sql.dll"
|
||||||
|
File "Qt6Widgets.dll"
|
||||||
|
File "Qt6WinExtras.dll"
|
||||||
|
File "libqtsparkle-qt6.dll"
|
||||||
|
!else
|
||||||
File "Qt5Concurrent.dll"
|
File "Qt5Concurrent.dll"
|
||||||
File "Qt5Core.dll"
|
File "Qt5Core.dll"
|
||||||
File "Qt5Gui.dll"
|
File "Qt5Gui.dll"
|
||||||
@@ -216,6 +246,8 @@ Section "Strawberry" Strawberry
|
|||||||
File "Qt5Sql.dll"
|
File "Qt5Sql.dll"
|
||||||
File "Qt5Widgets.dll"
|
File "Qt5Widgets.dll"
|
||||||
File "Qt5WinExtras.dll"
|
File "Qt5WinExtras.dll"
|
||||||
|
File "libqtsparkle-qt5.dll"
|
||||||
|
!endif
|
||||||
File "zlib1.dll"
|
File "zlib1.dll"
|
||||||
File "libzstd.dll"
|
File "libzstd.dll"
|
||||||
File "libtasn1-6.dll"
|
File "libtasn1-6.dll"
|
||||||
@@ -445,6 +477,15 @@ Section "Uninstall"
|
|||||||
Delete "$INSTDIR\Qt5Sql.dll"
|
Delete "$INSTDIR\Qt5Sql.dll"
|
||||||
Delete "$INSTDIR\Qt5Widgets.dll"
|
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||||
Delete "$INSTDIR\Qt5WinExtras.dll"
|
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||||
|
Delete "$INSTDIR\libqtsparkle-qt5.dll"
|
||||||
|
Delete "$INSTDIR\Qt6Concurrent.dll"
|
||||||
|
Delete "$INSTDIR\Qt6Core.dll"
|
||||||
|
Delete "$INSTDIR\Qt6Gui.dll"
|
||||||
|
Delete "$INSTDIR\Qt6Network.dll"
|
||||||
|
Delete "$INSTDIR\Qt6Sql.dll"
|
||||||
|
Delete "$INSTDIR\Qt6Widgets.dll"
|
||||||
|
Delete "$INSTDIR\Qt6WinExtras.dll"
|
||||||
|
Delete "$INSTDIR\libqtsparkle-qt6.dll"
|
||||||
Delete "$INSTDIR\zlib1.dll"
|
Delete "$INSTDIR\zlib1.dll"
|
||||||
Delete "$INSTDIR\libzstd.dll"
|
Delete "$INSTDIR\libzstd.dll"
|
||||||
Delete "$INSTDIR\libtasn1-6.dll"
|
Delete "$INSTDIR\libtasn1-6.dll"
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ link_directories(
|
|||||||
${GSTREAMER_BASE_LIBRARY_DIRS}
|
${GSTREAMER_BASE_LIBRARY_DIRS}
|
||||||
${GSTREAMER_AUDIO_LIBRARY_DIRS}
|
${GSTREAMER_AUDIO_LIBRARY_DIRS}
|
||||||
${FFTW3_LIBRARY_DIRS}
|
${FFTW3_LIBRARY_DIRS}
|
||||||
${Qt5Core_LIBRARY_DIRS}
|
${QtCore_LIBRARY_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(gstmoodbar STATIC ${SOURCES})
|
add_library(gstmoodbar STATIC ${SOURCES})
|
||||||
@@ -21,7 +21,7 @@ target_include_directories(gstmoodbar SYSTEM PRIVATE
|
|||||||
${GSTREAMER_BASE_INCLUDE_DIRS}
|
${GSTREAMER_BASE_INCLUDE_DIRS}
|
||||||
${GSTREAMER_AUDIO_INCLUDE_DIRS}
|
${GSTREAMER_AUDIO_INCLUDE_DIRS}
|
||||||
${FFTW3_INCLUDE_DIR}
|
${FFTW3_INCLUDE_DIR}
|
||||||
${Qt5Core_INCLUDE_DIRS}
|
${QtCore_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(gstmoodbar PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
target_include_directories(gstmoodbar PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
@@ -33,5 +33,5 @@ target_link_libraries(gstmoodbar PRIVATE
|
|||||||
${GSTREAMER_BASE_LIBRARIES}
|
${GSTREAMER_BASE_LIBRARIES}
|
||||||
${GSTREAMER_AUDIO_LIBRARIES}
|
${GSTREAMER_AUDIO_LIBRARIES}
|
||||||
${FFTW3_FFTW_LIBRARY}
|
${FFTW3_FFTW_LIBRARY}
|
||||||
${Qt5Core_LIBRARIES}
|
${QtCore_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ static void gst_fastspectrum_reset_state (GstFastSpectrum * spectrum) {
|
|||||||
|
|
||||||
static void gst_fastspectrum_finalize (GObject * object) {
|
static void gst_fastspectrum_finalize (GObject * object) {
|
||||||
|
|
||||||
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (object);
|
GstFastSpectrum *spectrum = reinterpret_cast<GstFastSpectrum*>(object);
|
||||||
|
|
||||||
gst_fastspectrum_reset_state (spectrum);
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
g_mutex_clear (&spectrum->lock);
|
g_mutex_clear (&spectrum->lock);
|
||||||
@@ -190,7 +190,7 @@ static void gst_fastspectrum_finalize (GObject * object) {
|
|||||||
|
|
||||||
static void gst_fastspectrum_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) {
|
static void gst_fastspectrum_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) {
|
||||||
|
|
||||||
GstFastSpectrum *filter = GST_FASTSPECTRUM (object);
|
GstFastSpectrum *filter = reinterpret_cast<GstFastSpectrum*>(object);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_INTERVAL:{
|
case PROP_INTERVAL:{
|
||||||
@@ -222,7 +222,7 @@ static void gst_fastspectrum_set_property (GObject * object, guint prop_id, cons
|
|||||||
|
|
||||||
static void gst_fastspectrum_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) {
|
static void gst_fastspectrum_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) {
|
||||||
|
|
||||||
GstFastSpectrum *filter = GST_FASTSPECTRUM (object);
|
GstFastSpectrum *filter = reinterpret_cast<GstFastSpectrum*>(object);
|
||||||
|
|
||||||
switch (prop_id) {
|
switch (prop_id) {
|
||||||
case PROP_INTERVAL:
|
case PROP_INTERVAL:
|
||||||
@@ -240,7 +240,7 @@ static void gst_fastspectrum_get_property (GObject * object, guint prop_id, GVal
|
|||||||
|
|
||||||
static gboolean gst_fastspectrum_start (GstBaseTransform * trans) {
|
static gboolean gst_fastspectrum_start (GstBaseTransform * trans) {
|
||||||
|
|
||||||
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (trans);
|
GstFastSpectrum *spectrum = reinterpret_cast<GstFastSpectrum*>(trans);
|
||||||
|
|
||||||
gst_fastspectrum_reset_state (spectrum);
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
|
|
||||||
@@ -250,7 +250,7 @@ static gboolean gst_fastspectrum_start (GstBaseTransform * trans) {
|
|||||||
|
|
||||||
static gboolean gst_fastspectrum_stop (GstBaseTransform * trans) {
|
static gboolean gst_fastspectrum_stop (GstBaseTransform * trans) {
|
||||||
|
|
||||||
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (trans);
|
GstFastSpectrum *spectrum = reinterpret_cast<GstFastSpectrum*>(trans);
|
||||||
|
|
||||||
gst_fastspectrum_reset_state (spectrum);
|
gst_fastspectrum_reset_state (spectrum);
|
||||||
|
|
||||||
@@ -334,7 +334,7 @@ static void input_data_mixed_int16_max (const guint8 * _in, double * out, guint
|
|||||||
|
|
||||||
static gboolean gst_fastspectrum_setup (GstAudioFilter * base, const GstAudioInfo * info) {
|
static gboolean gst_fastspectrum_setup (GstAudioFilter * base, const GstAudioInfo * info) {
|
||||||
|
|
||||||
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (base);
|
GstFastSpectrum *spectrum = reinterpret_cast<GstFastSpectrum*>(base);
|
||||||
GstFastSpectrumInputData input_data = nullptr;
|
GstFastSpectrumInputData input_data = nullptr;
|
||||||
|
|
||||||
g_mutex_lock (&spectrum->lock);
|
g_mutex_lock (&spectrum->lock);
|
||||||
@@ -392,7 +392,7 @@ static void gst_fastspectrum_run_fft (GstFastSpectrum * spectrum, guint input_po
|
|||||||
|
|
||||||
static GstFlowReturn gst_fastspectrum_transform_ip (GstBaseTransform *trans, GstBuffer *buffer) {
|
static GstFlowReturn gst_fastspectrum_transform_ip (GstBaseTransform *trans, GstBuffer *buffer) {
|
||||||
|
|
||||||
GstFastSpectrum *spectrum = GST_FASTSPECTRUM (trans);
|
GstFastSpectrum *spectrum = reinterpret_cast<GstFastSpectrum*>(trans);
|
||||||
guint rate = GST_AUDIO_FILTER_RATE (spectrum);
|
guint rate = GST_AUDIO_FILTER_RATE (spectrum);
|
||||||
guint bps = GST_AUDIO_FILTER_BPS (spectrum);
|
guint bps = GST_AUDIO_FILTER_BPS (spectrum);
|
||||||
guint bpf = GST_AUDIO_FILTER_BPF (spectrum);
|
guint bpf = GST_AUDIO_FILTER_BPF (spectrum);
|
||||||
|
|||||||
@@ -20,20 +20,24 @@ if(APPLE)
|
|||||||
list(APPEND SOURCES core/scoped_nsautorelease_pool.mm)
|
list(APPEND SOURCES core/scoped_nsautorelease_pool.mm)
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
qt5_wrap_cpp(MOC ${HEADERS})
|
if(WITH_QT6)
|
||||||
|
qt6_wrap_cpp(MOC ${HEADERS})
|
||||||
|
else()
|
||||||
|
qt5_wrap_cpp(MOC ${HEADERS})
|
||||||
|
endif()
|
||||||
|
|
||||||
link_directories(
|
link_directories(
|
||||||
${GLIB_LIBRARY_DIRS}
|
${GLIB_LIBRARY_DIRS}
|
||||||
${Qt5Core_LIBRARY_DIRS}
|
${QtCore_LIBRARY_DIRS}
|
||||||
${Qt5Network_LIBRARY_DIRS}
|
${QtNetwork_LIBRARY_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(libstrawberry-common STATIC ${SOURCES} ${MOC})
|
add_library(libstrawberry-common STATIC ${SOURCES} ${MOC})
|
||||||
|
|
||||||
target_include_directories(libstrawberry-common SYSTEM PRIVATE
|
target_include_directories(libstrawberry-common SYSTEM PRIVATE
|
||||||
${GLIB_INCLUDE_DIRS}
|
${GLIB_INCLUDE_DIRS}
|
||||||
${Qt5Core_INCLUDE_DIRS}
|
${QtCore_INCLUDE_DIRS}
|
||||||
${Qt5Network_INCLUDE_DIRS}
|
${QtNetwork_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(libstrawberry-common PRIVATE
|
target_include_directories(libstrawberry-common PRIVATE
|
||||||
@@ -46,8 +50,8 @@ target_include_directories(libstrawberry-common PRIVATE
|
|||||||
target_link_libraries(libstrawberry-common PRIVATE
|
target_link_libraries(libstrawberry-common PRIVATE
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${GLIB_LIBRARIES}
|
${GLIB_LIBRARIES}
|
||||||
${Qt5Core_LIBRARIES}
|
${QtCore_LIBRARIES}
|
||||||
${Qt5Network_LIBRARIES}
|
${QtNetwork_LIBRARIES}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(Backtrace_FOUND)
|
if(Backtrace_FOUND)
|
||||||
|
|||||||
@@ -35,7 +35,8 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QIODevice>
|
#include <QIODevice>
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
@@ -306,11 +307,12 @@ QString LinuxDemangle(const QString &symbol);
|
|||||||
|
|
||||||
QString LinuxDemangle(const QString &symbol) {
|
QString LinuxDemangle(const QString &symbol) {
|
||||||
|
|
||||||
QRegExp regex("\\(([^+]+)");
|
QRegularExpression regex("\\(([^+]+)");
|
||||||
if (!symbol.contains(regex)) {
|
QRegularExpressionMatch match = regex.match(symbol);
|
||||||
|
if (!match.hasMatch()) {
|
||||||
return symbol;
|
return symbol;
|
||||||
}
|
}
|
||||||
QString mangled_function = regex.cap(1);
|
QString mangled_function = match.captured(1);
|
||||||
return CXXDemangle(mangled_function);
|
return CXXDemangle(mangled_function);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,10 +102,10 @@ void _MessageHandlerBase::WriteMessage(const QByteArray &data) {
|
|||||||
|
|
||||||
// Sorry.
|
// Sorry.
|
||||||
if (flush_abstract_socket_) {
|
if (flush_abstract_socket_) {
|
||||||
((static_cast<QAbstractSocket*>(device_))->*(flush_abstract_socket_))();
|
((qobject_cast<QAbstractSocket*>(device_))->*(flush_abstract_socket_))();
|
||||||
}
|
}
|
||||||
else if (flush_local_socket_) {
|
else if (flush_local_socket_) {
|
||||||
((static_cast<QLocalSocket*>(device_))->*(flush_local_socket_))();
|
((qobject_cast<QLocalSocket*>(device_))->*(flush_local_socket_))();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ template <typename HandlerType>
|
|||||||
WorkerPool<HandlerType>::~WorkerPool() {
|
WorkerPool<HandlerType>::~WorkerPool() {
|
||||||
for (const Worker &worker : workers_) {
|
for (const Worker &worker : workers_) {
|
||||||
if (worker.local_socket_ && worker.process_) {
|
if (worker.local_socket_ && worker.process_) {
|
||||||
disconnect(worker.process_, SIGNAL(error(QProcess::ProcessError)), this, SLOT(ProcessError(QProcess::ProcessError)));
|
disconnect(worker.process_, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(ProcessError(QProcess::ProcessError)));
|
||||||
|
|
||||||
// The worker is connected. Close his socket and wait for him to exit.
|
// The worker is connected. Close his socket and wait for him to exit.
|
||||||
qLog(Debug) << "Closing worker socket";
|
qLog(Debug) << "Closing worker socket";
|
||||||
@@ -263,7 +263,7 @@ void WorkerPool<HandlerType>::StartOneWorker(Worker *worker) {
|
|||||||
worker->process_ = new QProcess(this);
|
worker->process_ = new QProcess(this);
|
||||||
|
|
||||||
connect(worker->local_server_, SIGNAL(newConnection()), SLOT(NewConnection()));
|
connect(worker->local_server_, SIGNAL(newConnection()), SLOT(NewConnection()));
|
||||||
connect(worker->process_, SIGNAL(error(QProcess::ProcessError)), SLOT(ProcessError(QProcess::ProcessError)));
|
connect(worker->process_, SIGNAL(errorOccurred(QProcess::ProcessError)), SLOT(ProcessError(QProcess::ProcessError)));
|
||||||
|
|
||||||
// Create a server, find an unused name and start listening
|
// Create a server, find an unused name and start listening
|
||||||
forever {
|
forever {
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ add_library(libstrawberry-tagreader STATIC ${PROTO_SOURCES} ${SOURCES})
|
|||||||
target_include_directories(libstrawberry-tagreader SYSTEM PRIVATE
|
target_include_directories(libstrawberry-tagreader SYSTEM PRIVATE
|
||||||
${GLIB_INCLUDE_DIRS}
|
${GLIB_INCLUDE_DIRS}
|
||||||
${PROTOBUF_INCLUDE_DIRS}
|
${PROTOBUF_INCLUDE_DIRS}
|
||||||
${Qt5Core_INCLUDE_DIRS}
|
${QtCore_INCLUDE_DIRS}
|
||||||
${Qt5Network_INCLUDE_DIRS}
|
${QtNetwork_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(libstrawberry-tagreader PRIVATE
|
target_include_directories(libstrawberry-tagreader PRIVATE
|
||||||
@@ -34,6 +34,11 @@ target_link_libraries(libstrawberry-tagreader PRIVATE
|
|||||||
${GLIB_LIBRARIES}
|
${GLIB_LIBRARIES}
|
||||||
${PROTOBUF_LIBRARY}
|
${PROTOBUF_LIBRARY}
|
||||||
${TAGLIB_LIBRARIES}
|
${TAGLIB_LIBRARIES}
|
||||||
${Qt5Core_LIBRARIES}
|
${QtCore_LIBRARIES}
|
||||||
|
${QtNetwork_LIBRARIES}
|
||||||
libstrawberry-common
|
libstrawberry-common
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(WITH_QT6)
|
||||||
|
target_link_libraries(libstrawberry-tagreader PRIVATE Qt6::Core5Compat)
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QChar>
|
#include <QChar>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
|
|
||||||
#include "fmpsparser.h"
|
#include "fmpsparser.h"
|
||||||
|
|
||||||
@@ -89,20 +91,20 @@ bool FMPSParser::Parse(const QString &data) {
|
|||||||
|
|
||||||
int FMPSParser::ParseValueRef(const QStringRef& data, QVariant* ret) const {
|
int FMPSParser::ParseValueRef(const QStringRef& data, QVariant* ret) const {
|
||||||
// Try to match a float
|
// Try to match a float
|
||||||
int pos = float_re_.indexIn(*data.string(), data.position());
|
QRegularExpressionMatch re_match = float_re_.match(*data.string(), data.position());
|
||||||
if (pos == data.position()) {
|
if (re_match.capturedStart() == data.position()) {
|
||||||
*ret = float_re_.cap(1).toDouble();
|
*ret = re_match.captured(1).toDouble();
|
||||||
return float_re_.matchedLength();
|
return re_match.capturedLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise try to match a string
|
// Otherwise try to match a string
|
||||||
pos = string_re_.indexIn(*data.string(), data.position());
|
re_match = string_re_.match(*data.string(), data.position());
|
||||||
if (pos == data.position()) {
|
if (re_match.capturedStart() == data.position()) {
|
||||||
// Replace escape sequences with their actual characters
|
// Replace escape sequences with their actual characters
|
||||||
QString value = string_re_.cap(1);
|
QString value = re_match.captured(1);
|
||||||
value.replace(escape_re_, "\\1");
|
value.replace(escape_re_, "\\1");
|
||||||
*ret = value;
|
*ret = value;
|
||||||
return string_re_.matchedLength();
|
return re_match.capturedLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@@ -23,12 +23,12 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
|
|
||||||
class QVariant;
|
class QVariant;
|
||||||
|
|
||||||
class FMPSParser {
|
class FMPSParser {
|
||||||
public:
|
public:
|
||||||
FMPSParser();
|
FMPSParser();
|
||||||
|
|
||||||
// A FMPS result is a list of lists of values (where a value is a string or
|
// A FMPS result is a list of lists of values (where a value is a string or
|
||||||
@@ -54,10 +54,10 @@ public:
|
|||||||
int ParseListList(const QString &data, Result *ret) const;
|
int ParseListList(const QString &data, Result *ret) const;
|
||||||
int ParseListListRef(const QStringRef &data, Result *ret) const;
|
int ParseListListRef(const QStringRef &data, Result *ret) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QRegExp float_re_;
|
QRegularExpression float_re_;
|
||||||
QRegExp string_re_;
|
QRegularExpression string_re_;
|
||||||
QRegExp escape_re_;
|
QRegularExpression escape_re_;
|
||||||
Result result_;
|
Result result_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -177,11 +177,11 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
|||||||
song->set_basefilename(DataCommaSizeFromQString(info.fileName()));
|
song->set_basefilename(DataCommaSizeFromQString(info.fileName()));
|
||||||
song->set_url(url.constData(), url.size());
|
song->set_url(url.constData(), url.size());
|
||||||
song->set_filesize(info.size());
|
song->set_filesize(info.size());
|
||||||
song->set_mtime(info.lastModified().toTime_t());
|
song->set_mtime(info.lastModified().toSecsSinceEpoch());
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
|
||||||
song->set_ctime(info.birthTime().isValid() ? info.birthTime().toTime_t() : info.lastModified().toTime_t());
|
song->set_ctime(info.birthTime().isValid() ? info.birthTime().toSecsSinceEpoch() : info.lastModified().toSecsSinceEpoch());
|
||||||
#else
|
#else
|
||||||
song->set_ctime(info.created().toTime_t());
|
song->set_ctime(info.created().toSecsSinceEpoch());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
std::unique_ptr<TagLib::FileRef> fileref(factory_->GetFileRef(filename));
|
||||||
@@ -342,6 +342,9 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
|||||||
if (mp4_tag->item("\251grp").isValid()) {
|
if (mp4_tag->item("\251grp").isValid()) {
|
||||||
Decode(mp4_tag->item("\251grp").toStringList().toString(" "), nullptr, song->mutable_grouping());
|
Decode(mp4_tag->item("\251grp").toStringList().toString(" "), nullptr, song->mutable_grouping());
|
||||||
}
|
}
|
||||||
|
if (mp4_tag->item("\251lyr").isValid()) {
|
||||||
|
Decode(mp4_tag->item("\251lyr").toStringList().toString(" "), nullptr, song->mutable_lyrics());
|
||||||
|
}
|
||||||
|
|
||||||
if (mp4_tag->item(kMP4_OriginalYear_ID).isValid()) {
|
if (mp4_tag->item(kMP4_OriginalYear_ID).isValid()) {
|
||||||
song->set_originalyear(TStringToQString(mp4_tag->item(kMP4_OriginalYear_ID).toStringList().toString('\n')).left(4).toInt());
|
song->set_originalyear(TStringToQString(mp4_tag->item(kMP4_OriginalYear_ID).toStringList().toString('\n')).left(4).toInt());
|
||||||
@@ -355,6 +358,10 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
|||||||
|
|
||||||
song->set_bitdepth(file_asf->audioProperties()->bitsPerSample());
|
song->set_bitdepth(file_asf->audioProperties()->bitsPerSample());
|
||||||
|
|
||||||
|
if (file_asf->tag()) {
|
||||||
|
Decode(file_asf->tag()->comment(), nullptr, song->mutable_comment());
|
||||||
|
}
|
||||||
|
|
||||||
const TagLib::ASF::AttributeListMap &attributes_map = file_asf->tag()->attributeListMap();
|
const TagLib::ASF::AttributeListMap &attributes_map = file_asf->tag()->attributeListMap();
|
||||||
|
|
||||||
if (attributes_map.contains(kASF_OriginalDate_ID)) {
|
if (attributes_map.contains(kASF_OriginalDate_ID)) {
|
||||||
@@ -617,6 +624,7 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
|
|||||||
tag->setItem("disk", TagLib::MP4::Item(song.disc() <= 0 -1 ? 0 : song.disc(), 0));
|
tag->setItem("disk", TagLib::MP4::Item(song.disc() <= 0 -1 ? 0 : song.disc(), 0));
|
||||||
tag->setItem("\251wrt", TagLib::StringList(song.composer().c_str()));
|
tag->setItem("\251wrt", TagLib::StringList(song.composer().c_str()));
|
||||||
tag->setItem("\251grp", TagLib::StringList(song.grouping().c_str()));
|
tag->setItem("\251grp", TagLib::StringList(song.grouping().c_str()));
|
||||||
|
tag->setItem("\251lyr", TagLib::StringList(song.lyrics().c_str()));
|
||||||
tag->setItem("aART", TagLib::StringList(song.albumartist().c_str()));
|
tag->setItem("aART", TagLib::StringList(song.albumartist().c_str()));
|
||||||
tag->setItem("cpil", TagLib::StringList(song.compilation() ? "1" : "0"));
|
tag->setItem("cpil", TagLib::StringList(song.compilation() ? "1" : "0"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@
|
|||||||
|
|
||||||
class QTextCodec;
|
class QTextCodec;
|
||||||
|
|
||||||
|
|
||||||
#ifndef USE_SYSTEM_TAGLIB
|
#ifndef USE_SYSTEM_TAGLIB
|
||||||
using namespace Strawberry_TagLib;
|
using namespace Strawberry_TagLib;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ message SongMetadata {
|
|||||||
optional string basefilename = 22;
|
optional string basefilename = 22;
|
||||||
optional FileType filetype = 23;
|
optional FileType filetype = 23;
|
||||||
optional int32 filesize = 24;
|
optional int32 filesize = 24;
|
||||||
optional int32 mtime = 25;
|
optional int64 mtime = 25;
|
||||||
optional int32 ctime = 26;
|
optional int64 ctime = 26;
|
||||||
|
|
||||||
optional int32 playcount = 27;
|
optional int32 playcount = 27;
|
||||||
optional int32 skipcount = 28;
|
optional int32 skipcount = 28;
|
||||||
|
|||||||
@@ -4,14 +4,19 @@ set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
|
|||||||
|
|
||||||
set(SOURCES main.cpp tagreaderworker.cpp)
|
set(SOURCES main.cpp tagreaderworker.cpp)
|
||||||
|
|
||||||
qt5_wrap_cpp(MOC ${HEADERS})
|
if(WITH_QT6)
|
||||||
qt5_add_resources(QRC data/data.qrc)
|
qt6_wrap_cpp(MOC ${HEADERS})
|
||||||
|
qt6_add_resources(QRC data/data.qrc)
|
||||||
|
else()
|
||||||
|
qt5_wrap_cpp(MOC ${HEADERS})
|
||||||
|
qt5_add_resources(QRC data/data.qrc)
|
||||||
|
endif()
|
||||||
|
|
||||||
link_directories(
|
link_directories(
|
||||||
${GLIB_LIBRARY_DIRS}
|
${GLIB_LIBRARY_DIRS}
|
||||||
${TAGLIB_LIBRARY_DIRS}
|
${TAGLIB_LIBRARY_DIRS}
|
||||||
${Qt5Core_LIBRARY_DIRS}
|
${QtCore_LIBRARY_DIRS}
|
||||||
${Qt5Network_LIBRARY_DIRS}
|
${QtNetwork_LIBRARY_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(strawberry-tagreader ${SOURCES} ${MOC} ${QRC})
|
add_executable(strawberry-tagreader ${SOURCES} ${MOC} ${QRC})
|
||||||
@@ -19,8 +24,8 @@ add_executable(strawberry-tagreader ${SOURCES} ${MOC} ${QRC})
|
|||||||
target_include_directories(strawberry-tagreader SYSTEM PRIVATE
|
target_include_directories(strawberry-tagreader SYSTEM PRIVATE
|
||||||
${GLIB_INCLUDE_DIRS}
|
${GLIB_INCLUDE_DIRS}
|
||||||
${PROTOBUF_INCLUDE_DIRS}
|
${PROTOBUF_INCLUDE_DIRS}
|
||||||
${Qt5Core_INCLUDE_DIRS}
|
${QtCore_INCLUDE_DIRS}
|
||||||
${Qt5Network_INCLUDE_DIRS}
|
${QtNetwork_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(strawberry-tagreader PRIVATE
|
target_include_directories(strawberry-tagreader PRIVATE
|
||||||
@@ -34,8 +39,8 @@ target_include_directories(strawberry-tagreader PRIVATE
|
|||||||
target_link_libraries(strawberry-tagreader PRIVATE
|
target_link_libraries(strawberry-tagreader PRIVATE
|
||||||
${GLIB_LIBRARIES}
|
${GLIB_LIBRARIES}
|
||||||
${TAGLIB_LIBRARIES}
|
${TAGLIB_LIBRARIES}
|
||||||
${Qt5Core_LIBRARIES}
|
${QtCore_LIBRARIES}
|
||||||
${Qt5Network_LIBRARIES}
|
${QtNetwork_LIBRARIES}
|
||||||
libstrawberry-common
|
libstrawberry-common
|
||||||
libstrawberry-tagreader
|
libstrawberry-tagreader
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: strawberry
|
name: strawberry
|
||||||
version: '0.6.13+git'
|
version: '0.7.2+git'
|
||||||
summary: music player and collection organizer
|
summary: music player and collection organizer
|
||||||
description: |
|
description: |
|
||||||
Strawberry is a music player and collection organizer.
|
Strawberry is a music player and collection organizer.
|
||||||
@@ -99,14 +99,10 @@ parts:
|
|||||||
- libqt5x11extras5-dev
|
- libqt5x11extras5-dev
|
||||||
- libgstreamer1.0-dev
|
- libgstreamer1.0-dev
|
||||||
- libgstreamer-plugins-base1.0-dev
|
- libgstreamer-plugins-base1.0-dev
|
||||||
- libxine2-dev
|
|
||||||
- libvlc-dev
|
- libvlc-dev
|
||||||
- libcdio-dev
|
- libcdio-dev
|
||||||
- libgpod-dev
|
- libgpod-dev
|
||||||
- libimobiledevice-dev
|
|
||||||
- libmtp-dev
|
- libmtp-dev
|
||||||
- libplist-dev
|
|
||||||
- libusbmuxd-dev
|
|
||||||
- libchromaprint-dev
|
- libchromaprint-dev
|
||||||
- libfftw3-dev
|
- libfftw3-dev
|
||||||
|
|
||||||
@@ -132,10 +128,6 @@ parts:
|
|||||||
- libcdio17
|
- libcdio17
|
||||||
- libgpod4
|
- libgpod4
|
||||||
- libmtp9
|
- libmtp9
|
||||||
- libimobiledevice6
|
|
||||||
- libplist3
|
|
||||||
- libusbmuxd4
|
|
||||||
- libxine2
|
|
||||||
- libvlc5
|
- libvlc5
|
||||||
- libvlccore9
|
- libvlccore9
|
||||||
- libtag1v5
|
- libtag1v5
|
||||||
@@ -144,7 +136,6 @@ parts:
|
|||||||
- libx11-6
|
- libx11-6
|
||||||
- libxcomposite1
|
- libxcomposite1
|
||||||
- libxcursor1
|
- libxcursor1
|
||||||
- libxinerama1
|
|
||||||
- libxrandr2
|
- libxrandr2
|
||||||
- libdb5.3
|
- libdb5.3
|
||||||
- libglu1
|
- libglu1
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ set(SOURCES
|
|||||||
dialogs/edittagdialog.cpp
|
dialogs/edittagdialog.cpp
|
||||||
dialogs/trackselectiondialog.cpp
|
dialogs/trackselectiondialog.cpp
|
||||||
dialogs/addstreamdialog.cpp
|
dialogs/addstreamdialog.cpp
|
||||||
|
dialogs/userpassdialog.cpp
|
||||||
|
|
||||||
widgets/autoexpandingtreeview.cpp
|
widgets/autoexpandingtreeview.cpp
|
||||||
widgets/busyindicator.cpp
|
widgets/busyindicator.cpp
|
||||||
@@ -183,8 +184,6 @@ set(SOURCES
|
|||||||
widgets/linetextedit.cpp
|
widgets/linetextedit.cpp
|
||||||
widgets/multiloadingindicator.cpp
|
widgets/multiloadingindicator.cpp
|
||||||
widgets/playingwidget.cpp
|
widgets/playingwidget.cpp
|
||||||
widgets/osd.cpp
|
|
||||||
widgets/osdpretty.cpp
|
|
||||||
widgets/renametablineedit.cpp
|
widgets/renametablineedit.cpp
|
||||||
widgets/volumeslider.cpp
|
widgets/volumeslider.cpp
|
||||||
widgets/stickyslider.cpp
|
widgets/stickyslider.cpp
|
||||||
@@ -194,6 +193,9 @@ set(SOURCES
|
|||||||
widgets/tracksliderslider.cpp
|
widgets/tracksliderslider.cpp
|
||||||
widgets/loginstatewidget.cpp
|
widgets/loginstatewidget.cpp
|
||||||
|
|
||||||
|
osd/osdbase.cpp
|
||||||
|
osd/osdpretty.cpp
|
||||||
|
|
||||||
musicbrainz/acoustidclient.cpp
|
musicbrainz/acoustidclient.cpp
|
||||||
musicbrainz/musicbrainzclient.cpp
|
musicbrainz/musicbrainzclient.cpp
|
||||||
|
|
||||||
@@ -221,10 +223,10 @@ set(SOURCES
|
|||||||
scrobbler/librefmscrobbler.cpp
|
scrobbler/librefmscrobbler.cpp
|
||||||
scrobbler/listenbrainzscrobbler.cpp
|
scrobbler/listenbrainzscrobbler.cpp
|
||||||
|
|
||||||
organise/organise.cpp
|
organize/organize.cpp
|
||||||
organise/organiseformat.cpp
|
organize/organizeformat.cpp
|
||||||
organise/organisedialog.cpp
|
organize/organizedialog.cpp
|
||||||
organise/organiseerrordialog.cpp
|
organize/organizeerrordialog.cpp
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -364,6 +366,7 @@ set(HEADERS
|
|||||||
dialogs/edittagdialog.h
|
dialogs/edittagdialog.h
|
||||||
dialogs/trackselectiondialog.h
|
dialogs/trackselectiondialog.h
|
||||||
dialogs/addstreamdialog.h
|
dialogs/addstreamdialog.h
|
||||||
|
dialogs/userpassdialog.h
|
||||||
|
|
||||||
widgets/autoexpandingtreeview.h
|
widgets/autoexpandingtreeview.h
|
||||||
widgets/busyindicator.h
|
widgets/busyindicator.h
|
||||||
@@ -378,8 +381,6 @@ set(HEADERS
|
|||||||
widgets/linetextedit.h
|
widgets/linetextedit.h
|
||||||
widgets/multiloadingindicator.h
|
widgets/multiloadingindicator.h
|
||||||
widgets/playingwidget.h
|
widgets/playingwidget.h
|
||||||
widgets/osd.h
|
|
||||||
widgets/osdpretty.h
|
|
||||||
widgets/renametablineedit.h
|
widgets/renametablineedit.h
|
||||||
widgets/volumeslider.h
|
widgets/volumeslider.h
|
||||||
widgets/stickyslider.h
|
widgets/stickyslider.h
|
||||||
@@ -390,6 +391,9 @@ set(HEADERS
|
|||||||
widgets/loginstatewidget.h
|
widgets/loginstatewidget.h
|
||||||
widgets/qsearchfield.h
|
widgets/qsearchfield.h
|
||||||
|
|
||||||
|
osd/osdbase.h
|
||||||
|
osd/osdpretty.h
|
||||||
|
|
||||||
musicbrainz/acoustidclient.h
|
musicbrainz/acoustidclient.h
|
||||||
musicbrainz/musicbrainzclient.h
|
musicbrainz/musicbrainzclient.h
|
||||||
|
|
||||||
@@ -415,9 +419,9 @@ set(HEADERS
|
|||||||
scrobbler/librefmscrobbler.h
|
scrobbler/librefmscrobbler.h
|
||||||
scrobbler/listenbrainzscrobbler.h
|
scrobbler/listenbrainzscrobbler.h
|
||||||
|
|
||||||
organise/organise.h
|
organize/organize.h
|
||||||
organise/organisedialog.h
|
organize/organizedialog.h
|
||||||
organise/organiseerrordialog.h
|
organize/organizeerrordialog.h
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -465,18 +469,20 @@ set(UI
|
|||||||
dialogs/edittagdialog.ui
|
dialogs/edittagdialog.ui
|
||||||
dialogs/trackselectiondialog.ui
|
dialogs/trackselectiondialog.ui
|
||||||
dialogs/addstreamdialog.ui
|
dialogs/addstreamdialog.ui
|
||||||
|
dialogs/userpassdialog.ui
|
||||||
|
|
||||||
widgets/trackslider.ui
|
widgets/trackslider.ui
|
||||||
widgets/osdpretty.ui
|
|
||||||
widgets/fileview.ui
|
widgets/fileview.ui
|
||||||
widgets/loginstatewidget.ui
|
widgets/loginstatewidget.ui
|
||||||
|
|
||||||
|
osd/osdpretty.ui
|
||||||
|
|
||||||
internet/internettabsview.ui
|
internet/internettabsview.ui
|
||||||
internet/internetcollectionviewcontainer.ui
|
internet/internetcollectionviewcontainer.ui
|
||||||
internet/internetsearchview.ui
|
internet/internetsearchview.ui
|
||||||
|
|
||||||
organise/organisedialog.ui
|
organize/organizedialog.ui
|
||||||
organise/organiseerrordialog.ui
|
organize/organizeerrordialog.ui
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -521,10 +527,12 @@ optional_source(HAVE_ALSA
|
|||||||
engine/alsadevicefinder.cpp
|
engine/alsadevicefinder.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
# X11
|
# DBUS
|
||||||
optional_source(X11_FOUND
|
optional_source(HAVE_DBUS
|
||||||
SOURCES
|
SOURCES
|
||||||
widgets/osd_x11.cpp
|
osd/osddbus.cpp
|
||||||
|
HEADERS
|
||||||
|
osd/osddbus.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# GStreamer
|
# GStreamer
|
||||||
@@ -533,15 +541,6 @@ optional_source(HAVE_GSTREAMER
|
|||||||
HEADERS engine/gststartup.h engine/gstengine.h engine/gstenginepipeline.h engine/gstelementdeleter.h
|
HEADERS engine/gststartup.h engine/gstengine.h engine/gstenginepipeline.h engine/gstelementdeleter.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# Xine
|
|
||||||
optional_source(HAVE_XINE
|
|
||||||
SOURCES engine/xineengine.cpp
|
|
||||||
HEADERS engine/xineengine.h
|
|
||||||
)
|
|
||||||
optional_source(XINE_ANALYZER
|
|
||||||
SOURCES engine/xinescope.c
|
|
||||||
)
|
|
||||||
|
|
||||||
# VLC
|
# VLC
|
||||||
optional_source(HAVE_VLC
|
optional_source(HAVE_VLC
|
||||||
SOURCES engine/vlcengine.cpp
|
SOURCES engine/vlcengine.cpp
|
||||||
@@ -561,31 +560,63 @@ if(UNIX AND HAVE_DBUS)
|
|||||||
HEADERS device/udisks2lister.h
|
HEADERS device/udisks2lister.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# MPRIS 2.0 DBUS interfaces
|
if (WITH_QT6)
|
||||||
qt5_add_dbus_adaptor(SOURCES
|
|
||||||
dbus/org.mpris.MediaPlayer2.Player.xml
|
|
||||||
core/mpris2.h mpris::Mpris2 core/mpris2_player Mpris2Player)
|
|
||||||
qt5_add_dbus_adaptor(SOURCES
|
|
||||||
dbus/org.mpris.MediaPlayer2.xml
|
|
||||||
core/mpris2.h mpris::Mpris2 core/mpris2_root Mpris2Root)
|
|
||||||
qt5_add_dbus_adaptor(SOURCES
|
|
||||||
dbus/org.mpris.MediaPlayer2.TrackList.xml
|
|
||||||
core/mpris2.h mpris::Mpris2 core/mpris2_tracklist Mpris2TrackList)
|
|
||||||
|
|
||||||
# MPRIS 2.1 DBUS interfaces
|
# MPRIS 2.0 DBUS interfaces
|
||||||
qt5_add_dbus_adaptor(SOURCES
|
qt6_add_dbus_adaptor(SOURCES
|
||||||
dbus/org.mpris.MediaPlayer2.Playlists.xml
|
dbus/org.mpris.MediaPlayer2.Player.xml
|
||||||
core/mpris2.h mpris::Mpris2 core/mpris2_playlists Mpris2Playlists)
|
core/mpris2.h mpris::Mpris2 core/mpris2_player Mpris2Player)
|
||||||
|
qt6_add_dbus_adaptor(SOURCES
|
||||||
|
dbus/org.mpris.MediaPlayer2.xml
|
||||||
|
core/mpris2.h mpris::Mpris2 core/mpris2_root Mpris2Root)
|
||||||
|
qt6_add_dbus_adaptor(SOURCES
|
||||||
|
dbus/org.mpris.MediaPlayer2.TrackList.xml
|
||||||
|
core/mpris2.h mpris::Mpris2 core/mpris2_tracklist Mpris2TrackList)
|
||||||
|
|
||||||
# org.freedesktop.Notifications DBUS interface
|
# MPRIS 2.1 DBUS interfaces
|
||||||
qt5_add_dbus_interface(SOURCES
|
qt6_add_dbus_adaptor(SOURCES
|
||||||
dbus/org.freedesktop.Notifications.xml
|
dbus/org.mpris.MediaPlayer2.Playlists.xml
|
||||||
dbus/notification)
|
core/mpris2.h mpris::Mpris2 core/mpris2_playlists Mpris2Playlists)
|
||||||
|
|
||||||
# org.gnome.SettingsDaemon interface
|
# org.freedesktop.Notifications DBUS interface
|
||||||
qt5_add_dbus_interface(SOURCES
|
qt6_add_dbus_interface(SOURCES
|
||||||
dbus/org.gnome.SettingsDaemon.MediaKeys.xml
|
dbus/org.freedesktop.Notifications.xml
|
||||||
dbus/gnomesettingsdaemon)
|
dbus/notification)
|
||||||
|
|
||||||
|
# org.gnome.SettingsDaemon interface
|
||||||
|
qt6_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.gnome.SettingsDaemon.MediaKeys.xml
|
||||||
|
dbus/gnomesettingsdaemon)
|
||||||
|
|
||||||
|
else()
|
||||||
|
|
||||||
|
# MPRIS 2.0 DBUS interfaces
|
||||||
|
qt5_add_dbus_adaptor(SOURCES
|
||||||
|
dbus/org.mpris.MediaPlayer2.Player.xml
|
||||||
|
core/mpris2.h mpris::Mpris2 core/mpris2_player Mpris2Player)
|
||||||
|
qt5_add_dbus_adaptor(SOURCES
|
||||||
|
dbus/org.mpris.MediaPlayer2.xml
|
||||||
|
core/mpris2.h mpris::Mpris2 core/mpris2_root Mpris2Root)
|
||||||
|
qt5_add_dbus_adaptor(SOURCES
|
||||||
|
dbus/org.mpris.MediaPlayer2.TrackList.xml
|
||||||
|
core/mpris2.h mpris::Mpris2 core/mpris2_tracklist Mpris2TrackList)
|
||||||
|
|
||||||
|
# MPRIS 2.1 DBUS interfaces
|
||||||
|
qt5_add_dbus_adaptor(SOURCES
|
||||||
|
dbus/org.mpris.MediaPlayer2.Playlists.xml
|
||||||
|
core/mpris2.h mpris::Mpris2 core/mpris2_playlists Mpris2Playlists)
|
||||||
|
|
||||||
|
# org.freedesktop.Notifications DBUS interface
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.freedesktop.Notifications.xml
|
||||||
|
dbus/notification)
|
||||||
|
|
||||||
|
# org.gnome.SettingsDaemon interface
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.gnome.SettingsDaemon.MediaKeys.xml
|
||||||
|
dbus/gnomesettingsdaemon)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
|
||||||
# org.freedesktop.Avahi.Server interface
|
# org.freedesktop.Avahi.Server interface
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
@@ -626,21 +657,39 @@ if(UNIX AND HAVE_DBUS)
|
|||||||
PROPERTIES NO_NAMESPACE dbus/udisks2drive INCLUDE dbus/metatypes.h)
|
PROPERTIES NO_NAMESPACE dbus/udisks2drive INCLUDE dbus/metatypes.h)
|
||||||
set_source_files_properties(dbus/org.freedesktop.UDisks2.Job.xml
|
set_source_files_properties(dbus/org.freedesktop.UDisks2.Job.xml
|
||||||
PROPERTIES NO_NAMESPACE dbus/udisks2job INCLUDE dbus/metatypes.h)
|
PROPERTIES NO_NAMESPACE dbus/udisks2job INCLUDE dbus/metatypes.h)
|
||||||
qt5_add_dbus_interface(SOURCES
|
if(WITH_QT6)
|
||||||
dbus/org.freedesktop.DBus.ObjectManager.xml
|
qt6_add_dbus_interface(SOURCES
|
||||||
dbus/objectmanager)
|
dbus/org.freedesktop.DBus.ObjectManager.xml
|
||||||
qt5_add_dbus_interface(SOURCES
|
dbus/objectmanager)
|
||||||
dbus/org.freedesktop.UDisks2.Filesystem.xml
|
qt6_add_dbus_interface(SOURCES
|
||||||
dbus/udisks2filesystem)
|
dbus/org.freedesktop.UDisks2.Filesystem.xml
|
||||||
qt5_add_dbus_interface(SOURCES
|
dbus/udisks2filesystem)
|
||||||
dbus/org.freedesktop.UDisks2.Block.xml
|
qt6_add_dbus_interface(SOURCES
|
||||||
dbus/udisks2block)
|
dbus/org.freedesktop.UDisks2.Block.xml
|
||||||
qt5_add_dbus_interface(SOURCES
|
dbus/udisks2block)
|
||||||
dbus/org.freedesktop.UDisks2.Drive.xml
|
qt6_add_dbus_interface(SOURCES
|
||||||
dbus/udisks2drive)
|
dbus/org.freedesktop.UDisks2.Drive.xml
|
||||||
qt5_add_dbus_interface(SOURCES
|
dbus/udisks2drive)
|
||||||
dbus/org.freedesktop.UDisks2.Job.xml
|
qt6_add_dbus_interface(SOURCES
|
||||||
dbus/udisks2job)
|
dbus/org.freedesktop.UDisks2.Job.xml
|
||||||
|
dbus/udisks2job)
|
||||||
|
else()
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.freedesktop.DBus.ObjectManager.xml
|
||||||
|
dbus/objectmanager)
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.freedesktop.UDisks2.Filesystem.xml
|
||||||
|
dbus/udisks2filesystem)
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.freedesktop.UDisks2.Block.xml
|
||||||
|
dbus/udisks2block)
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.freedesktop.UDisks2.Drive.xml
|
||||||
|
dbus/udisks2drive)
|
||||||
|
qt5_add_dbus_interface(SOURCES
|
||||||
|
dbus/org.freedesktop.UDisks2.Job.xml
|
||||||
|
dbus/udisks2job)
|
||||||
|
endif()
|
||||||
endif(HAVE_UDISKS2)
|
endif(HAVE_UDISKS2)
|
||||||
|
|
||||||
endif(UNIX AND HAVE_DBUS)
|
endif(UNIX AND HAVE_DBUS)
|
||||||
@@ -688,21 +737,6 @@ optional_source(HAVE_GIO
|
|||||||
HEADERS device/giolister.h
|
HEADERS device/giolister.h
|
||||||
)
|
)
|
||||||
|
|
||||||
# imobiledevice backend and device
|
|
||||||
optional_source(HAVE_IMOBILEDEVICE
|
|
||||||
SOURCES
|
|
||||||
device/afcdevice.cpp
|
|
||||||
device/afcfile.cpp
|
|
||||||
device/afctransfer.cpp
|
|
||||||
device/ilister.cpp
|
|
||||||
device/imobiledeviceconnection.cpp
|
|
||||||
HEADERS
|
|
||||||
device/afcdevice.h
|
|
||||||
device/afcfile.h
|
|
||||||
device/afctransfer.h
|
|
||||||
device/ilister.h
|
|
||||||
)
|
|
||||||
|
|
||||||
# mtp device
|
# mtp device
|
||||||
optional_source(HAVE_LIBMTP
|
optional_source(HAVE_LIBMTP
|
||||||
SOURCES
|
SOURCES
|
||||||
@@ -785,7 +819,7 @@ optional_source(APPLE
|
|||||||
core/macsystemtrayicon.mm
|
core/macsystemtrayicon.mm
|
||||||
core/macscreensaver.cpp
|
core/macscreensaver.cpp
|
||||||
core/macfslistener.mm
|
core/macfslistener.mm
|
||||||
widgets/osd_mac.mm
|
osd/osdmac.mm
|
||||||
widgets/qsearchfield_mac.mm
|
widgets/qsearchfield_mac.mm
|
||||||
engine/macosdevicefinder.cpp
|
engine/macosdevicefinder.cpp
|
||||||
globalshortcuts/globalshortcutbackend-macos.mm
|
globalshortcuts/globalshortcutbackend-macos.mm
|
||||||
@@ -793,6 +827,7 @@ optional_source(APPLE
|
|||||||
HEADERS
|
HEADERS
|
||||||
core/macsystemtrayicon.h
|
core/macsystemtrayicon.h
|
||||||
core/macfslistener.h
|
core/macfslistener.h
|
||||||
|
osd/osdmac.h
|
||||||
globalshortcuts/globalshortcutbackend-macos.h
|
globalshortcuts/globalshortcutbackend-macos.h
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -810,7 +845,6 @@ optional_source(WIN32
|
|||||||
SOURCES
|
SOURCES
|
||||||
engine/directsounddevicefinder.cpp
|
engine/directsounddevicefinder.cpp
|
||||||
engine/mmdevicefinder.cpp
|
engine/mmdevicefinder.cpp
|
||||||
widgets/osd_win.cpp
|
|
||||||
core/windows7thumbbar.cpp
|
core/windows7thumbbar.cpp
|
||||||
HEADERS
|
HEADERS
|
||||||
core/windows7thumbbar.h
|
core/windows7thumbbar.h
|
||||||
@@ -881,9 +915,15 @@ optional_source(HAVE_MOODBAR
|
|||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
|
||||||
|
|
||||||
qt5_wrap_cpp(MOC ${HEADERS})
|
if(WITH_QT6)
|
||||||
qt5_wrap_ui(UIC ${UI})
|
qt6_wrap_cpp(MOC ${HEADERS})
|
||||||
qt5_add_resources(QRC ${RESOURCES})
|
qt6_wrap_ui(UIC ${UI})
|
||||||
|
qt6_add_resources(QRC ${RESOURCES})
|
||||||
|
else()
|
||||||
|
qt5_wrap_cpp(MOC ${HEADERS})
|
||||||
|
qt5_wrap_ui(UIC ${UI})
|
||||||
|
qt5_add_resources(QRC ${RESOURCES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(HAVE_TRANSLATIONS)
|
if(HAVE_TRANSLATIONS)
|
||||||
|
|
||||||
@@ -926,6 +966,7 @@ link_directories(
|
|||||||
${QT_LIBRARY_DIRS}
|
${QT_LIBRARY_DIRS}
|
||||||
${SINGLEAPPLICATION_LIBRARY_DIRS}
|
${SINGLEAPPLICATION_LIBRARY_DIRS}
|
||||||
${SINGLECOREAPPLICATION_LIBRARY_DIRS}
|
${SINGLECOREAPPLICATION_LIBRARY_DIRS}
|
||||||
|
${QTSPARKLE_LIBRARY_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
if(HAVE_ALSA)
|
if(HAVE_ALSA)
|
||||||
@@ -947,10 +988,6 @@ if(HAVE_GSTREAMER)
|
|||||||
)
|
)
|
||||||
endif(HAVE_GSTREAMER)
|
endif(HAVE_GSTREAMER)
|
||||||
|
|
||||||
if(HAVE_XINE)
|
|
||||||
link_directories(${LIBXINE_LIBRARY_DIRS})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(HAVE_VLC)
|
if(HAVE_VLC)
|
||||||
link_directories(${LIBVLC_LIBRARY_DIRS})
|
link_directories(${LIBVLC_LIBRARY_DIRS})
|
||||||
endif()
|
endif()
|
||||||
@@ -983,14 +1020,6 @@ if(HAVE_LIBMTP)
|
|||||||
link_directories(${LIBMTP_LIBRARY_DIRS})
|
link_directories(${LIBMTP_LIBRARY_DIRS})
|
||||||
endif(HAVE_LIBMTP)
|
endif(HAVE_LIBMTP)
|
||||||
|
|
||||||
if(HAVE_IMOBILEDEVICE)
|
|
||||||
link_directories(
|
|
||||||
${LIBUSBMUXD_LIBRARY_DIRS}
|
|
||||||
${LIBPLIST_LIBRARY_DIRS}
|
|
||||||
${LIBIMOBILEDEVICE_LIBRARY_DIRS}
|
|
||||||
)
|
|
||||||
endif(HAVE_IMOBILEDEVICE)
|
|
||||||
|
|
||||||
add_library(strawberry_lib STATIC
|
add_library(strawberry_lib STATIC
|
||||||
${SOURCES}
|
${SOURCES}
|
||||||
${MOC}
|
${MOC}
|
||||||
@@ -1033,6 +1062,7 @@ target_link_libraries(strawberry_lib PUBLIC
|
|||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
${SINGLEAPPLICATION_LIBRARIES}
|
${SINGLEAPPLICATION_LIBRARIES}
|
||||||
${SINGLECOREAPPLICATION_LIBRARIES}
|
${SINGLECOREAPPLICATION_LIBRARIES}
|
||||||
|
${QTSPARKLE_LIBRARIES}
|
||||||
libstrawberry-common
|
libstrawberry-common
|
||||||
libstrawberry-tagreader
|
libstrawberry-tagreader
|
||||||
)
|
)
|
||||||
@@ -1070,11 +1100,6 @@ if(HAVE_MOODBAR)
|
|||||||
target_link_libraries(strawberry_lib PRIVATE gstmoodbar)
|
target_link_libraries(strawberry_lib PRIVATE gstmoodbar)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(HAVE_XINE)
|
|
||||||
target_include_directories(strawberry_lib SYSTEM PRIVATE ${LIBXINE_INCLUDE_DIRS})
|
|
||||||
target_link_libraries(strawberry_lib PRIVATE ${LIBXINE_LIBRARIES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(HAVE_VLC)
|
if(HAVE_VLC)
|
||||||
target_include_directories(strawberry_lib SYSTEM PRIVATE ${LIBVLC_INCLUDE_DIRS})
|
target_include_directories(strawberry_lib SYSTEM PRIVATE ${LIBVLC_INCLUDE_DIRS})
|
||||||
target_link_libraries(strawberry_lib PRIVATE ${LIBVLC_LIBRARIES})
|
target_link_libraries(strawberry_lib PRIVATE ${LIBVLC_LIBRARIES})
|
||||||
@@ -1115,19 +1140,6 @@ if(HAVE_LIBMTP)
|
|||||||
target_link_libraries(strawberry_lib PRIVATE ${LIBMTP_LIBRARIES})
|
target_link_libraries(strawberry_lib PRIVATE ${LIBMTP_LIBRARIES})
|
||||||
endif(HAVE_LIBMTP)
|
endif(HAVE_LIBMTP)
|
||||||
|
|
||||||
if(HAVE_IMOBILEDEVICE)
|
|
||||||
target_include_directories(strawberry_lib SYSTEM PRIVATE
|
|
||||||
${LIBUSBMUXD_INCLUDE_DIRS}
|
|
||||||
${LIBPLIST_INCLUDE_DIRS}
|
|
||||||
${LIBIMOBILEDEVICE_INCLUDE_DIRS}
|
|
||||||
)
|
|
||||||
target_link_libraries(strawberry_lib PRIVATE
|
|
||||||
${LIBUSBMUXD_LIBRARIES}
|
|
||||||
${LIBPLIST_LIBRARIES}
|
|
||||||
${LIBIMOBILEDEVICE_LIBRARIES}
|
|
||||||
)
|
|
||||||
endif(HAVE_IMOBILEDEVICE)
|
|
||||||
|
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
target_link_libraries(strawberry_lib PRIVATE
|
target_link_libraries(strawberry_lib PRIVATE
|
||||||
@@ -1149,11 +1161,10 @@ if(WIN32)
|
|||||||
target_link_libraries(strawberry_lib PRIVATE dsound)
|
target_link_libraries(strawberry_lib PRIVATE dsound)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(X11_FOUND)
|
||||||
# Hack: the Gold linker pays attention to the order that libraries are specified on the link line.
|
# Hack: the Gold linker pays attention to the order that libraries are specified on the link line.
|
||||||
# -lX11 and -ldl are provided earlier in the link command but they're actually used by libraries that appear after them, so they end up getting ignored.
|
# -lX11 and -ldl are provided earlier in the link command but they're actually used by libraries that appear after them, so they end up getting ignored.
|
||||||
# This appends them to the very end of the link line, ensuring they're always used.
|
# This appends them to the very end of the link line, ensuring they're always used.
|
||||||
find_package(X11)
|
|
||||||
if(FREEBSD)
|
if(FREEBSD)
|
||||||
target_link_libraries(strawberry_lib PRIVATE ${X11_X11_LIB})
|
target_link_libraries(strawberry_lib PRIVATE ${X11_X11_LIB})
|
||||||
else()
|
else()
|
||||||
@@ -1196,6 +1207,10 @@ if(NOT APPLE)
|
|||||||
install(TARGETS strawberry RUNTIME DESTINATION bin)
|
install(TARGETS strawberry RUNTIME DESTINATION bin)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_TRANSLATIONS AND INSTALL_TRANSLATIONS AND INSTALL_TRANSLATIONS_FILES)
|
||||||
|
install(FILES ${INSTALL_TRANSLATIONS_FILES} DESTINATION share/strawberry/translations)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set_target_properties(strawberry PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/../dist/macos/Info.plist")
|
set_target_properties(strawberry PROPERTIES MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/../dist/macos/Info.plist")
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
|||||||
@@ -99,10 +99,14 @@ AnalyzerContainer::AnalyzerContainer(QWidget *parent)
|
|||||||
|
|
||||||
void AnalyzerContainer::mouseReleaseEvent(QMouseEvent *e) {
|
void AnalyzerContainer::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
|
||||||
if (engine_->type() != Engine::EngineType::GStreamer && engine_->type() != Engine::EngineType::Xine) return;
|
if (engine_->type() != Engine::EngineType::GStreamer) return;
|
||||||
|
|
||||||
if (e->button() == Qt::RightButton) {
|
if (e->button() == Qt::RightButton) {
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
context_menu_->popup(e->globalPosition().toPoint());
|
||||||
|
#else
|
||||||
context_menu_->popup(e->globalPos());
|
context_menu_->popup(e->globalPos());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,11 @@
|
|||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
|
#include <QActionGroup>
|
||||||
|
|
||||||
#include "engine/engine_fwd.h"
|
#include "engine/engine_fwd.h"
|
||||||
|
|
||||||
class QTimer;
|
class QTimer;
|
||||||
class QActionGroup;
|
|
||||||
class QMouseEvent;
|
class QMouseEvent;
|
||||||
class QWheelEvent;
|
class QWheelEvent;
|
||||||
|
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
|
|||||||
|
|
||||||
void BlockAnalyzer::paletteChange(const QPalette&) {
|
void BlockAnalyzer::paletteChange(const QPalette&) {
|
||||||
|
|
||||||
const QColor bg = palette().color(QPalette::Background);
|
const QColor bg = palette().color(QPalette::Window);
|
||||||
const QColor fg = ensureContrast(bg, palette().color(QPalette::Highlight));
|
const QColor fg = ensureContrast(bg, palette().color(QPalette::Highlight));
|
||||||
|
|
||||||
topbarpixmap_.fill(fg);
|
topbarpixmap_.fill(fg);
|
||||||
@@ -343,12 +343,12 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
|
|||||||
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)));
|
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)));
|
||||||
|
|
||||||
{
|
{
|
||||||
const QColor bg2 = palette().color(QPalette::Background).darker(112);
|
const QColor bg2 = palette().color(QPalette::Window).darker(112);
|
||||||
|
|
||||||
// make a complimentary fadebar colour
|
// make a complimentary fadebar colour
|
||||||
// TODO dark is not always correct, dumbo!
|
// TODO dark is not always correct, dumbo!
|
||||||
int h, s, v;
|
int h, s, v;
|
||||||
palette().color(QPalette::Background).darker(150).getHsv(&h, &s, &v);
|
palette().color(QPalette::Window).darker(150).getHsv(&h, &s, &v);
|
||||||
const QColor fg2(QColor::fromHsv(h + 120, s, v));
|
const QColor fg2(QColor::fromHsv(h + 120, s, v));
|
||||||
|
|
||||||
const double dr2 = fg2.red() - bg2.red();
|
const double dr2 = fg2.red() - bg2.red();
|
||||||
@@ -358,7 +358,7 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
|
|||||||
|
|
||||||
// Precalculate all fade-bar pixmaps
|
// Precalculate all fade-bar pixmaps
|
||||||
for (uint y = 0; y < kFadeSize; ++y) {
|
for (uint y = 0; y < kFadeSize; ++y) {
|
||||||
fade_bars_[y].fill(palette().color(QPalette::Background));
|
fade_bars_[y].fill(palette().color(QPalette::Window));
|
||||||
QPainter f(&fade_bars_[y]);
|
QPainter f(&fade_bars_[y]);
|
||||||
for (int z = 0; static_cast<uint>(z) < rows_; ++z) {
|
for (int z = 0; static_cast<uint>(z) < rows_; ++z) {
|
||||||
const double Y = 1.0 - (log10(kFadeSize - y) / log10(kFadeSize));
|
const double Y = 1.0 - (log10(kFadeSize - y) / log10(kFadeSize));
|
||||||
@@ -377,7 +377,7 @@ void BlockAnalyzer::drawBackground() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QColor bg = palette().color(QPalette::Background);
|
const QColor bg = palette().color(QPalette::Window);
|
||||||
const QColor bgdark = bg.darker(112);
|
const QColor bgdark = bg.darker(112);
|
||||||
|
|
||||||
background_.fill(bg);
|
background_.fill(bg);
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ void BoomAnalyzer::resizeEvent(QResizeEvent* e) {
|
|||||||
|
|
||||||
barPixmap_ = QPixmap(kColumnWidth - 2, HEIGHT);
|
barPixmap_ = QPixmap(kColumnWidth - 2, HEIGHT);
|
||||||
canvas_ = QPixmap(size());
|
canvas_ = QPixmap(size());
|
||||||
canvas_.fill(palette().color(QPalette::Background));
|
canvas_.fill(palette().color(QPalette::Window));
|
||||||
|
|
||||||
QPainter p(&barPixmap_);
|
QPainter p(&barPixmap_);
|
||||||
for (uint y = 0; y < HEIGHT; ++y) {
|
for (uint y = 0; y < HEIGHT; ++y) {
|
||||||
@@ -120,7 +120,7 @@ void BoomAnalyzer::analyze(QPainter& p, const Scope& scope, bool new_frame) {
|
|||||||
const uint MAX_HEIGHT = height() - 1;
|
const uint MAX_HEIGHT = height() - 1;
|
||||||
|
|
||||||
QPainter canvas_painter(&canvas_);
|
QPainter canvas_painter(&canvas_);
|
||||||
canvas_.fill(palette().color(QPalette::Background));
|
canvas_.fill(palette().color(QPalette::Window));
|
||||||
|
|
||||||
Analyzer::interpolate(scope, scope_);
|
Analyzer::interpolate(scope, scope_);
|
||||||
|
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ void SCollection::Exit() {
|
|||||||
|
|
||||||
void SCollection::ExitReceived() {
|
void SCollection::ExitReceived() {
|
||||||
|
|
||||||
QObject *obj = static_cast<QObject*>(sender());
|
QObject *obj = qobject_cast<QObject*>(sender());
|
||||||
disconnect(obj, nullptr, this, nullptr);
|
disconnect(obj, nullptr, this, nullptr);
|
||||||
qLog(Debug) << obj << "successfully exited.";
|
qLog(Debug) << obj << "successfully exited.";
|
||||||
wait_for_exit_.removeAll(obj);
|
wait_for_exit_.removeAll(obj);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
|
|
||||||
@@ -222,7 +222,7 @@ SubdirectoryList CollectionBackend::SubdirsInDirectory(int id, QSqlDatabase &db)
|
|||||||
Subdirectory subdir;
|
Subdirectory subdir;
|
||||||
subdir.directory_id = id;
|
subdir.directory_id = id;
|
||||||
subdir.path = q.value(0).toString();
|
subdir.path = q.value(0).toString();
|
||||||
subdir.mtime = q.value(1).toUInt();
|
subdir.mtime = q.value(1).toLongLong();
|
||||||
subdirs << subdir;
|
subdirs << subdir;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1031,7 +1031,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
|||||||
info.first_url = QUrl::fromEncoded(query.Value(7).toByteArray());
|
info.first_url = QUrl::fromEncoded(query.Value(7).toByteArray());
|
||||||
|
|
||||||
QString art_automatic = query.Value(5).toString();
|
QString art_automatic = query.Value(5).toString();
|
||||||
if (art_automatic.contains(QRegExp("..+:.*"))) {
|
if (art_automatic.contains(QRegularExpression("..+:.*"))) {
|
||||||
info.art_automatic = QUrl::fromEncoded(art_automatic.toUtf8());
|
info.art_automatic = QUrl::fromEncoded(art_automatic.toUtf8());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1039,7 +1039,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString art_manual = query.Value(6).toString();
|
QString art_manual = query.Value(6).toString();
|
||||||
if (art_manual.contains(QRegExp("..+:.*"))) {
|
if (art_manual.contains(QRegularExpression("..+:.*"))) {
|
||||||
info.art_manual = QUrl::fromEncoded(art_manual.toUtf8());
|
info.art_manual = QUrl::fromEncoded(art_manual.toUtf8());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1228,7 +1228,7 @@ void CollectionBackend::IncrementPlayCount(int id) {
|
|||||||
|
|
||||||
QSqlQuery q(db);
|
QSqlQuery q(db);
|
||||||
q.prepare(QString("UPDATE %1 SET playcount = playcount + 1, lastplayed = :now WHERE ROWID = :id").arg(songs_table_));
|
q.prepare(QString("UPDATE %1 SET playcount = playcount + 1, lastplayed = :now WHERE ROWID = :id").arg(songs_table_));
|
||||||
q.bindValue(":now", QDateTime::currentDateTime().toTime_t());
|
q.bindValue(":now", QDateTime::currentDateTime().toSecsSinceEpoch());
|
||||||
q.bindValue(":id", id);
|
q.bindValue(":id", id);
|
||||||
q.exec();
|
q.exec();
|
||||||
if (db_->CheckErrors(q)) return;
|
if (db_->CheckErrors(q)) return;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QInputDialog>
|
#include <QInputDialog>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -63,27 +63,26 @@ CollectionFilterWidget::CollectionFilterWidget(QWidget *parent)
|
|||||||
|
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
|
|
||||||
QString available_fields = Song::kFtsColumns.join(", ").replace(QRegExp("\\bfts"), "");
|
QString available_fields = Song::kFtsColumns.join(", ").replace(QRegularExpression("\\bfts"), "");
|
||||||
|
|
||||||
ui_->filter->setToolTip(
|
ui_->filter->setToolTip(
|
||||||
"<html><head/><body><p>" +
|
QString("<html><head/><body><p>") +
|
||||||
tr("Prefix a word with a field name to limit the search to that field, e.g.:") +
|
tr("Prefix a word with a field name to limit the search to that field, e.g.:") +
|
||||||
" " +
|
QString(" ") +
|
||||||
"<span style=\"font-weight:600;\">" +
|
QString("<span style=\"font-weight:600;\">") +
|
||||||
tr("artist") +
|
tr("artist") +
|
||||||
":" +
|
QString(":") +
|
||||||
"</span><span style=\"font-style:italic;\">Strawbs</span>" +
|
QString("</span><span style=\"font-style:italic;\">Strawbs</span>") +
|
||||||
" " +
|
QString(" ") +
|
||||||
tr("searches the collection for all artists that contain the word") +
|
tr("searches the collection for all artists that contain the word") +
|
||||||
"Strawbs" +
|
QString(" Strawbs.") +
|
||||||
"." +
|
QString("</p><p><span style=\"font-weight:600;\">") +
|
||||||
"</p><p><span style=\"font-weight:600;\">" +
|
|
||||||
tr("Available fields") +
|
tr("Available fields") +
|
||||||
": " +
|
QString(": ") +
|
||||||
"</span><span style=\"font-style:italic;\">" +
|
"</span><span style=\"font-style:italic;\">" +
|
||||||
available_fields +
|
available_fields +
|
||||||
"</span>." +
|
QString("</span>.") +
|
||||||
"</p></body></html>"
|
QString("</p></body></html>")
|
||||||
);
|
);
|
||||||
|
|
||||||
connect(ui_->filter, SIGNAL(returnPressed()), SIGNAL(ReturnPressed()));
|
connect(ui_->filter, SIGNAL(returnPressed()), SIGNAL(ReturnPressed()));
|
||||||
|
|||||||
@@ -33,7 +33,6 @@ class CollectionItem : public SimpleTreeItem<CollectionItem> {
|
|||||||
Type_Divider,
|
Type_Divider,
|
||||||
Type_Container,
|
Type_Container,
|
||||||
Type_Song,
|
Type_Song,
|
||||||
Type_PlaylistContainer,
|
|
||||||
Type_LoadingIndicator,
|
Type_LoadingIndicator,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrent>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QChar>
|
#include <QChar>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#include <QNetworkDiskCache>
|
#include <QNetworkDiskCache>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
@@ -97,8 +97,6 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
|||||||
total_album_count_(0),
|
total_album_count_(0),
|
||||||
artist_icon_(IconLoader::Load("folder-sound")),
|
artist_icon_(IconLoader::Load("folder-sound")),
|
||||||
album_icon_(IconLoader::Load("cdcase")),
|
album_icon_(IconLoader::Load("cdcase")),
|
||||||
playlists_dir_icon_(IconLoader::Load("folder-sound")),
|
|
||||||
playlist_icon_(IconLoader::Load("albums")),
|
|
||||||
init_task_id_(-1),
|
init_task_id_(-1),
|
||||||
use_pretty_covers_(false),
|
use_pretty_covers_(false),
|
||||||
show_dividers_(true),
|
show_dividers_(true),
|
||||||
@@ -695,8 +693,6 @@ QVariant CollectionModel::data(const CollectionItem *item, const int role) const
|
|||||||
|
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case CollectionItem::Type_PlaylistContainer:
|
|
||||||
return playlists_dir_icon_;
|
|
||||||
case CollectionItem::Type_Container:
|
case CollectionItem::Type_Container:
|
||||||
switch (container_type) {
|
switch (container_type) {
|
||||||
case GroupBy_Album:
|
case GroupBy_Album:
|
||||||
@@ -859,9 +855,8 @@ void CollectionModel::LazyPopulate(CollectionItem *parent, const bool signal) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::ResetAsync() {
|
void CollectionModel::ResetAsync() {
|
||||||
QFuture<CollectionModel::QueryResult> future = QtConcurrent::run(this, &CollectionModel::RunQuery, root_);
|
QFuture<CollectionModel::QueryResult> future = QtConcurrent::run(std::bind(&CollectionModel::RunQuery, this, root_));
|
||||||
NewClosure(future, this, SLOT(ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult>)), future);
|
NewClosure(future, this, SLOT(ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult>)), future);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionModel::ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult> future) {
|
void CollectionModel::ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult> future) {
|
||||||
@@ -1421,7 +1416,7 @@ QString CollectionModel::PrettyYearAlbum(const int year, const QString &album) {
|
|||||||
|
|
||||||
QString CollectionModel::PrettyAlbumDisc(const QString &album, const int disc) {
|
QString CollectionModel::PrettyAlbumDisc(const QString &album, const int disc) {
|
||||||
|
|
||||||
if (disc <= 0 || album.contains(QRegExp(Song::kAlbumRemoveDisc))) return TextOrUnknown(album);
|
if (disc <= 0 || album.contains(QRegularExpression(Song::kAlbumRemoveDisc))) return TextOrUnknown(album);
|
||||||
else return TextOrUnknown(album) + " - (Disc " + QString::number(disc) + ")";
|
else return TextOrUnknown(album) + " - (Disc " + QString::number(disc) + ")";
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1433,7 +1428,7 @@ QString CollectionModel::PrettyYearAlbumDisc(const int year, const QString &albu
|
|||||||
if (year <= 0) str = TextOrUnknown(album);
|
if (year <= 0) str = TextOrUnknown(album);
|
||||||
else str = QString::number(year) + " - " + TextOrUnknown(album);
|
else str = QString::number(year) + " - " + TextOrUnknown(album);
|
||||||
|
|
||||||
if (!album.contains(QRegExp(Song::kAlbumRemoveDisc)) && disc > 0) str += " - (Disc " + QString::number(disc) + ")";
|
if (!album.contains(QRegularExpression(Song::kAlbumRemoveDisc)) && disc > 0) str += " - (Disc " + QString::number(disc) + ")";
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
|
|
||||||
@@ -1447,7 +1442,7 @@ QString CollectionModel::SortText(QString text) {
|
|||||||
else {
|
else {
|
||||||
text = text.toLower();
|
text = text.toLower();
|
||||||
}
|
}
|
||||||
text = text.remove(QRegExp("[^\\w ]"));
|
text = text.remove(QRegularExpression("[^\\w ]", QRegularExpression::UseUnicodePropertiesOption));
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
|
|||||||
@@ -280,8 +280,6 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
|||||||
QIcon album_icon_;
|
QIcon album_icon_;
|
||||||
// Used as a generic icon to show when no cover art is found, fixed to the same size as the artwork (32x32)
|
// Used as a generic icon to show when no cover art is found, fixed to the same size as the artwork (32x32)
|
||||||
QPixmap no_cover_icon_;
|
QPixmap no_cover_icon_;
|
||||||
QIcon playlists_dir_icon_;
|
|
||||||
QIcon playlist_icon_;
|
|
||||||
|
|
||||||
static QNetworkDiskCache *sIconCache;
|
static QNetworkDiskCache *sIconCache;
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ class CollectionPlaylistItem : public PlaylistItem {
|
|||||||
void Reload() override;
|
void Reload() override;
|
||||||
|
|
||||||
Song Metadata() const override;
|
Song Metadata() const override;
|
||||||
|
Song OriginalMetadata() const override { return song_; }
|
||||||
void SetMetadata(const Song &song) { song_ = song; }
|
void SetMetadata(const Song &song) { song_ = song; }
|
||||||
|
|
||||||
QUrl Url() const override;
|
QUrl Url() const override;
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
#include <QSqlQuery>
|
#include <QSqlQuery>
|
||||||
|
|
||||||
@@ -46,9 +46,9 @@ CollectionQuery::CollectionQuery(const QueryOptions &options)
|
|||||||
|
|
||||||
// Split on whitespace
|
// Split on whitespace
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
|
||||||
QStringList tokens(options.filter().split(QRegExp("\\s+"), Qt::SkipEmptyParts));
|
QStringList tokens(options.filter().split(QRegularExpression("\\s+"), Qt::SkipEmptyParts));
|
||||||
#else
|
#else
|
||||||
QStringList tokens(options.filter().split(QRegExp("\\s+"), QString::SkipEmptyParts));
|
QStringList tokens(options.filter().split(QRegularExpression("\\s+"), QString::SkipEmptyParts));
|
||||||
#endif
|
#endif
|
||||||
QString query;
|
QString query;
|
||||||
for (QString token : tokens) {
|
for (QString token : tokens) {
|
||||||
@@ -65,17 +65,21 @@ CollectionQuery::CollectionQuery(const QueryOptions &options)
|
|||||||
QString subtoken = token.section(':', 1, -1);
|
QString subtoken = token.section(':', 1, -1);
|
||||||
subtoken.replace(":", " ");
|
subtoken.replace(":", " ");
|
||||||
subtoken = subtoken.trimmed();
|
subtoken = subtoken.trimmed();
|
||||||
if (!subtoken.isEmpty())
|
if (!subtoken.isEmpty()) {
|
||||||
query += "fts" + columntoken + subtoken + "* ";
|
if (!query.isEmpty()) query.append(" ");
|
||||||
|
query += "fts" + columntoken + "\"" + subtoken + "\"*";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
token.replace(":", " ");
|
token.replace(":", " ");
|
||||||
token = token.trimmed();
|
token = token.trimmed();
|
||||||
query += token + "* ";
|
if (!query.isEmpty()) query.append(" ");
|
||||||
|
query += "\"" + token + "\"*";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
query += token + "* ";
|
if (!query.isEmpty()) query.append(" ");
|
||||||
|
query += "\"" + token + "\"*";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!query.isEmpty()) {
|
if (!query.isEmpty()) {
|
||||||
@@ -86,7 +90,7 @@ CollectionQuery::CollectionQuery(const QueryOptions &options)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (options.max_age() != -1) {
|
if (options.max_age() != -1) {
|
||||||
int cutoff = QDateTime::currentDateTime().toTime_t() - options.max_age();
|
int cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - options.max_age();
|
||||||
|
|
||||||
where_clauses_ << "ctime > ?";
|
where_clauses_ << "ctime > ?";
|
||||||
bound_values_ << cutoff;
|
bound_values_ << cutoff;
|
||||||
@@ -202,7 +206,7 @@ QVariant CollectionQuery::Value(int column) const { return query_.value(column);
|
|||||||
bool QueryOptions::Matches(const Song &song) const {
|
bool QueryOptions::Matches(const Song &song) const {
|
||||||
|
|
||||||
if (max_age_ != -1) {
|
if (max_age_ != -1) {
|
||||||
const uint cutoff = QDateTime::currentDateTime().toTime_t() - max_age_;
|
const uint cutoff = QDateTime::currentDateTime().toSecsSinceEpoch() - max_age_;
|
||||||
if (song.ctime() <= cutoff) return false;
|
if (song.ctime() <= cutoff) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@
|
|||||||
# include "device/devicestatefiltermodel.h"
|
# include "device/devicestatefiltermodel.h"
|
||||||
#endif
|
#endif
|
||||||
#include "dialogs/edittagdialog.h"
|
#include "dialogs/edittagdialog.h"
|
||||||
#include "organise/organisedialog.h"
|
#include "organize/organizedialog.h"
|
||||||
#include "settings/collectionsettingspage.h"
|
#include "settings/collectionsettingspage.h"
|
||||||
|
|
||||||
CollectionView::CollectionView(QWidget *parent)
|
CollectionView::CollectionView(QWidget *parent)
|
||||||
@@ -325,7 +325,7 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue to play next"), this, SLOT(AddToPlaylistEnqueueNext()));
|
add_to_playlist_enqueue_next_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue to play next"), this, SLOT(AddToPlaylistEnqueueNext()));
|
||||||
|
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
|
organize_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, SLOT(Organize()));
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
||||||
#endif
|
#endif
|
||||||
@@ -366,39 +366,40 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
int regular_editable = 0;
|
int regular_editable = 0;
|
||||||
|
|
||||||
for (const QModelIndex &index : selected_indexes) {
|
for (const QModelIndex &index : selected_indexes) {
|
||||||
regular_elements++;
|
++regular_elements;
|
||||||
if(app_->collection_model()->data(index, CollectionModel::Role_Editable).toBool()) {
|
if(app_->collection_model()->data(index, CollectionModel::Role_Editable).toBool()) {
|
||||||
regular_editable++;
|
++regular_editable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check if custom plugin actions should be enabled / visible
|
|
||||||
const int songs_selected = regular_elements;
|
const int songs_selected = regular_elements;
|
||||||
const bool regular_elements_only = songs_selected == regular_elements && regular_elements > 0;
|
const bool regular_elements_only = songs_selected == regular_elements && regular_elements > 0;
|
||||||
|
|
||||||
// in all modes
|
// in all modes
|
||||||
load_->setEnabled(songs_selected);
|
load_->setEnabled(songs_selected > 0);
|
||||||
add_to_playlist_->setEnabled(songs_selected);
|
add_to_playlist_->setEnabled(songs_selected > 0);
|
||||||
open_in_new_playlist_->setEnabled(songs_selected);
|
open_in_new_playlist_->setEnabled(songs_selected > 0);
|
||||||
add_to_playlist_enqueue_->setEnabled(songs_selected);
|
add_to_playlist_enqueue_->setEnabled(songs_selected > 0);
|
||||||
|
|
||||||
// if neither edit_track not edit_tracks are available, we show disabled edit_track element
|
// if neither edit_track not edit_tracks are available, we show disabled edit_track element
|
||||||
edit_track_->setVisible(regular_editable <= 1);
|
edit_track_->setVisible(regular_editable == 1);
|
||||||
edit_track_->setEnabled(regular_editable == 1);
|
edit_track_->setEnabled(regular_editable == 1);
|
||||||
|
edit_tracks_->setVisible(regular_editable > 1);
|
||||||
|
edit_tracks_->setEnabled(regular_editable > 1);
|
||||||
|
|
||||||
rescan_songs_->setVisible(edit_track_->isVisible());
|
rescan_songs_->setVisible(regular_editable > 0);
|
||||||
rescan_songs_->setEnabled(true);
|
rescan_songs_->setEnabled(regular_editable > 0);
|
||||||
|
|
||||||
organise_->setVisible(regular_elements_only);
|
organize_->setVisible(regular_elements == regular_editable);
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setVisible(regular_elements_only);
|
copy_to_device_->setVisible(regular_elements == regular_editable);
|
||||||
#endif
|
#endif
|
||||||
//delete_->setVisible(regular_elements_only);
|
//delete_->setVisible(regular_elements_only);
|
||||||
show_in_various_->setVisible(regular_elements_only);
|
show_in_various_->setVisible(regular_elements_only);
|
||||||
no_show_in_various_->setVisible(regular_elements_only);
|
no_show_in_various_->setVisible(regular_elements_only);
|
||||||
|
|
||||||
// only when all selected items are editable
|
// only when all selected items are editable
|
||||||
organise_->setEnabled(regular_elements == regular_editable);
|
organize_->setEnabled(regular_elements == regular_editable);
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
||||||
#endif
|
#endif
|
||||||
@@ -529,15 +530,15 @@ SongList CollectionView::GetSelectedSongs() const {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionView::Organise() {
|
void CollectionView::Organize() {
|
||||||
|
|
||||||
if (!organise_dialog_)
|
if (!organize_dialog_)
|
||||||
organise_dialog_.reset(new OrganiseDialog(app_->task_manager(), app_->collection_backend(), this));
|
organize_dialog_.reset(new OrganizeDialog(app_->task_manager(), app_->collection_backend(), this));
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||||
organise_dialog_->SetCopy(false);
|
organize_dialog_->SetCopy(false);
|
||||||
if (organise_dialog_->SetSongs(GetSelectedSongs()))
|
if (organize_dialog_->SetSongs(GetSelectedSongs()))
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
else {
|
else {
|
||||||
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||||
}
|
}
|
||||||
@@ -568,13 +569,13 @@ void CollectionView::RescanSongs() {
|
|||||||
void CollectionView::CopyToDevice() {
|
void CollectionView::CopyToDevice() {
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
if (!organise_dialog_)
|
if (!organize_dialog_)
|
||||||
organise_dialog_.reset(new OrganiseDialog(app_->task_manager(), nullptr, this));
|
organize_dialog_.reset(new OrganizeDialog(app_->task_manager(), nullptr, this));
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||||
organise_dialog_->SetCopy(true);
|
organize_dialog_->SetCopy(true);
|
||||||
organise_dialog_->SetSongs(GetSelectedSongs());
|
organize_dialog_->SetSongs(GetSelectedSongs());
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ class QPaintEvent;
|
|||||||
class Application;
|
class Application;
|
||||||
class CollectionFilterWidget;
|
class CollectionFilterWidget;
|
||||||
class EditTagDialog;
|
class EditTagDialog;
|
||||||
class OrganiseDialog;
|
class OrganizeDialog;
|
||||||
|
|
||||||
class CollectionView : public AutoExpandingTreeView {
|
class CollectionView : public AutoExpandingTreeView {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -102,7 +102,7 @@ class CollectionView : public AutoExpandingTreeView {
|
|||||||
void AddToPlaylistEnqueue();
|
void AddToPlaylistEnqueue();
|
||||||
void AddToPlaylistEnqueueNext();
|
void AddToPlaylistEnqueueNext();
|
||||||
void OpenInNewPlaylist();
|
void OpenInNewPlaylist();
|
||||||
void Organise();
|
void Organize();
|
||||||
void CopyToDevice();
|
void CopyToDevice();
|
||||||
void EditTracks();
|
void EditTracks();
|
||||||
void RescanSongs();
|
void RescanSongs();
|
||||||
@@ -133,7 +133,7 @@ class CollectionView : public AutoExpandingTreeView {
|
|||||||
QAction *add_to_playlist_enqueue_;
|
QAction *add_to_playlist_enqueue_;
|
||||||
QAction *add_to_playlist_enqueue_next_;
|
QAction *add_to_playlist_enqueue_next_;
|
||||||
QAction *open_in_new_playlist_;
|
QAction *open_in_new_playlist_;
|
||||||
QAction *organise_;
|
QAction *organize_;
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
QAction *copy_to_device_;
|
QAction *copy_to_device_;
|
||||||
#endif
|
#endif
|
||||||
@@ -145,7 +145,7 @@ class CollectionView : public AutoExpandingTreeView {
|
|||||||
QAction *show_in_various_;
|
QAction *show_in_various_;
|
||||||
QAction *no_show_in_various_;
|
QAction *no_show_in_various_;
|
||||||
|
|
||||||
std::unique_ptr<OrganiseDialog> organise_dialog_;
|
std::unique_ptr<OrganizeDialog> organize_dialog_;
|
||||||
std::unique_ptr<EditTagDialog> edit_tag_dialog_;
|
std::unique_ptr<EditTagDialog> edit_tag_dialog_;
|
||||||
|
|
||||||
bool is_in_keyboard_search_;
|
bool is_in_keyboard_search_;
|
||||||
|
|||||||
@@ -328,7 +328,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!t->ignores_mtime() && !force_noincremental && t->is_incremental() && subdir.mtime == path_info.lastModified().toTime_t()) {
|
if (!t->ignores_mtime() && !force_noincremental && t->is_incremental() && subdir.mtime == path_info.lastModified().toSecsSinceEpoch()) {
|
||||||
// The directory hasn't changed since last time
|
// The directory hasn't changed since last time
|
||||||
t->AddToProgress(1);
|
t->AddToProgress(1);
|
||||||
return;
|
return;
|
||||||
@@ -362,7 +362,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
|||||||
Subdirectory new_subdir;
|
Subdirectory new_subdir;
|
||||||
new_subdir.directory_id = -1;
|
new_subdir.directory_id = -1;
|
||||||
new_subdir.path = child;
|
new_subdir.path = child;
|
||||||
new_subdir.mtime = child_info.lastModified().toTime_t();
|
new_subdir.mtime = child_info.lastModified().toSecsSinceEpoch();
|
||||||
my_new_subdirs << new_subdir;
|
my_new_subdirs << new_subdir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -393,7 +393,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
|||||||
|
|
||||||
Song matching_song(source_);
|
Song matching_song(source_);
|
||||||
if (FindSongByPath(songs_in_db, file, &matching_song)) {
|
if (FindSongByPath(songs_in_db, file, &matching_song)) {
|
||||||
uint matching_cue_mtime = GetMtimeForCue(matching_cue);
|
qint64 matching_cue_mtime = GetMtimeForCue(matching_cue);
|
||||||
|
|
||||||
// The song is in the database and still on disk.
|
// The song is in the database and still on disk.
|
||||||
// Check the mtime to see if it's been changed since it was added.
|
// Check the mtime to see if it's been changed since it was added.
|
||||||
@@ -407,13 +407,13 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
|||||||
|
|
||||||
// cue sheet's path from collection (if any)
|
// cue sheet's path from collection (if any)
|
||||||
QString song_cue = matching_song.cue_path();
|
QString song_cue = matching_song.cue_path();
|
||||||
uint song_cue_mtime = GetMtimeForCue(song_cue);
|
qint64 song_cue_mtime = GetMtimeForCue(song_cue);
|
||||||
|
|
||||||
bool cue_deleted = song_cue_mtime == 0 && matching_song.has_cue();
|
bool cue_deleted = song_cue_mtime == 0 && matching_song.has_cue();
|
||||||
bool cue_added = matching_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().toTime_t(), song_cue_mtime)) || cue_deleted || cue_added;
|
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
|
// Also want to look to see whether the album art has changed
|
||||||
QUrl image = ImageForSong(file, album_art);
|
QUrl image = ImageForSong(file, album_art);
|
||||||
@@ -470,7 +470,7 @@ void CollectionWatcher::ScanSubdirectory(const QString &path, const Subdirectory
|
|||||||
// Add this subdir to the new or touched list
|
// Add this subdir to the new or touched list
|
||||||
Subdirectory updated_subdir;
|
Subdirectory updated_subdir;
|
||||||
updated_subdir.directory_id = t->dir();
|
updated_subdir.directory_id = t->dir();
|
||||||
updated_subdir.mtime = path_info.exists() ? path_info.lastModified().toTime_t() : 0;
|
updated_subdir.mtime = path_info.exists() ? path_info.lastModified().toSecsSinceEpoch() : 0;
|
||||||
updated_subdir.path = path;
|
updated_subdir.path = path;
|
||||||
|
|
||||||
if (subdir.directory_id == -1)
|
if (subdir.directory_id == -1)
|
||||||
@@ -560,7 +560,7 @@ SongList CollectionWatcher::ScanNewFile(const QString &file, const QString &path
|
|||||||
|
|
||||||
SongList song_list;
|
SongList song_list;
|
||||||
|
|
||||||
uint matching_cue_mtime = GetMtimeForCue(matching_cue);
|
quint64 matching_cue_mtime = GetMtimeForCue(matching_cue);
|
||||||
// If it's a cue - create virtual tracks
|
// If it's a cue - create virtual tracks
|
||||||
if (matching_cue_mtime) {
|
if (matching_cue_mtime) {
|
||||||
// don't process the same cue many times
|
// don't process the same cue many times
|
||||||
@@ -629,7 +629,7 @@ void CollectionWatcher::PreserveUserSetData(const QString &file, const QUrl &ima
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint CollectionWatcher::GetMtimeForCue(const QString &cue_path) {
|
quint64 CollectionWatcher::GetMtimeForCue(const QString &cue_path) {
|
||||||
|
|
||||||
// Slight optimisation
|
// Slight optimisation
|
||||||
if (cue_path.isEmpty()) {
|
if (cue_path.isEmpty()) {
|
||||||
@@ -643,7 +643,7 @@ uint CollectionWatcher::GetMtimeForCue(const QString &cue_path) {
|
|||||||
|
|
||||||
const QDateTime cue_last_modified = file_info.lastModified();
|
const QDateTime cue_last_modified = file_info.lastModified();
|
||||||
|
|
||||||
return cue_last_modified.isValid() ? cue_last_modified.toTime_t() : 0;
|
return cue_last_modified.isValid() ? cue_last_modified.toSecsSinceEpoch() : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CollectionWatcher::AddWatch(const Directory &dir, const QString &path) {
|
void CollectionWatcher::AddWatch(const Directory &dir, const QString &path) {
|
||||||
|
|||||||
@@ -166,7 +166,7 @@ class CollectionWatcher : public QObject {
|
|||||||
QUrl ImageForSong(const QString &path, QMap<QString, QStringList> &album_art);
|
QUrl ImageForSong(const QString &path, QMap<QString, QStringList> &album_art);
|
||||||
void AddWatch(const Directory &dir, const QString &path);
|
void AddWatch(const Directory &dir, const QString &path);
|
||||||
void RemoveWatch(const Directory &dir, const Subdirectory &subdir);
|
void RemoveWatch(const Directory &dir, const Subdirectory &subdir);
|
||||||
uint GetMtimeForCue(const QString &cue_path);
|
quint64 GetMtimeForCue(const QString &cue_path);
|
||||||
void PerformScan(bool incremental, bool ignore_mtimes);
|
void PerformScan(bool incremental, bool ignore_mtimes);
|
||||||
|
|
||||||
// Updates the sections of a cue associated and altered (according to mtime) media file during a scan.
|
// Updates the sections of a cue associated and altered (according to mtime) media file during a scan.
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ struct Subdirectory {
|
|||||||
|
|
||||||
int directory_id;
|
int directory_id;
|
||||||
QString path;
|
QString path;
|
||||||
uint mtime;
|
qint64 mtime;
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(Subdirectory)
|
Q_DECLARE_METATYPE(Subdirectory)
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>You can change the way the songs in the collection are organised.</string>
|
<string>You can change the way the songs in the collection are organized.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
@@ -31,20 +31,18 @@
|
|||||||
#cmakedefine HAVE_X11
|
#cmakedefine HAVE_X11
|
||||||
#cmakedefine HAVE_UDISKS2
|
#cmakedefine HAVE_UDISKS2
|
||||||
#cmakedefine HAVE_ALSA
|
#cmakedefine HAVE_ALSA
|
||||||
#cmakedefine HAVE_IMOBILEDEVICE
|
|
||||||
#cmakedefine HAVE_AUDIOCD
|
#cmakedefine HAVE_AUDIOCD
|
||||||
#cmakedefine HAVE_LIBGPOD
|
#cmakedefine HAVE_LIBGPOD
|
||||||
#cmakedefine HAVE_LIBMTP
|
#cmakedefine HAVE_LIBMTP
|
||||||
#cmakedefine HAVE_LIBPULSE
|
#cmakedefine HAVE_LIBPULSE
|
||||||
#cmakedefine HAVE_SPARKLE
|
#cmakedefine HAVE_SPARKLE
|
||||||
|
#cmakedefine HAVE_QTSPARKLE
|
||||||
#cmakedefine HAVE_CHROMAPRINT
|
#cmakedefine HAVE_CHROMAPRINT
|
||||||
#cmakedefine HAVE_GLOBALSHORTCUTS
|
#cmakedefine HAVE_GLOBALSHORTCUTS
|
||||||
#cmakedefine USE_INSTALL_PREFIX
|
#cmakedefine USE_INSTALL_PREFIX
|
||||||
|
|
||||||
#cmakedefine HAVE_GSTREAMER
|
#cmakedefine HAVE_GSTREAMER
|
||||||
#cmakedefine HAVE_VLC
|
#cmakedefine HAVE_VLC
|
||||||
#cmakedefine HAVE_XINE
|
|
||||||
#cmakedefine XINE_ANALYZER
|
|
||||||
|
|
||||||
#cmakedefine HAVE_SUBSONIC
|
#cmakedefine HAVE_SUBSONIC
|
||||||
#cmakedefine HAVE_TIDAL
|
#cmakedefine HAVE_TIDAL
|
||||||
@@ -59,9 +57,10 @@
|
|||||||
#cmakedefine HAVE_TAGLIB_DSDIFFFILE
|
#cmakedefine HAVE_TAGLIB_DSDIFFFILE
|
||||||
|
|
||||||
#cmakedefine USE_BUNDLE
|
#cmakedefine USE_BUNDLE
|
||||||
|
|
||||||
#define USE_BUNDLE_DIR "${USE_BUNDLE_DIR}"
|
#define USE_BUNDLE_DIR "${USE_BUNDLE_DIR}"
|
||||||
|
|
||||||
#cmakedefine HAVE_TRANSLATIONS
|
#cmakedefine HAVE_TRANSLATIONS
|
||||||
|
#cmakedefine INSTALL_TRANSLATIONS
|
||||||
|
#define TRANSLATIONS_DIR "${CMAKE_INSTALL_PREFIX}/share/strawberry/translations"
|
||||||
|
|
||||||
#endif // CONFIG_H_IN
|
#endif // CONFIG_H_IN
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QSet>
|
#include <QSet>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
@@ -62,8 +62,7 @@ ContextAlbumsModel::ContextAlbumsModel(CollectionBackend *backend, Application *
|
|||||||
SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent),
|
SimpleTreeModel<CollectionItem>(new CollectionItem(this), parent),
|
||||||
backend_(backend),
|
backend_(backend),
|
||||||
app_(app),
|
app_(app),
|
||||||
album_icon_(IconLoader::Load("cdcase")),
|
album_icon_(IconLoader::Load("cdcase")) {
|
||||||
playlists_dir_icon_(IconLoader::Load("folder-sound")) {
|
|
||||||
|
|
||||||
root_->lazy_loaded = true;
|
root_->lazy_loaded = true;
|
||||||
|
|
||||||
@@ -195,8 +194,6 @@ QVariant ContextAlbumsModel::data(const CollectionItem *item, int role) const {
|
|||||||
|
|
||||||
case Qt::DecorationRole:
|
case Qt::DecorationRole:
|
||||||
switch (item->type) {
|
switch (item->type) {
|
||||||
case CollectionItem::Type_PlaylistContainer:
|
|
||||||
return playlists_dir_icon_;
|
|
||||||
case CollectionItem::Type_Container:
|
case CollectionItem::Type_Container:
|
||||||
if (item->type == CollectionItem::Type_Container && item->container_level == 0) { return album_icon_; }
|
if (item->type == CollectionItem::Type_Container && item->container_level == 0) { return album_icon_; }
|
||||||
break;
|
break;
|
||||||
@@ -370,7 +367,7 @@ QString ContextAlbumsModel::SortText(QString text) {
|
|||||||
else {
|
else {
|
||||||
text = text.toLower();
|
text = text.toLower();
|
||||||
}
|
}
|
||||||
text = text.remove(QRegExp("[^\\w ]"));
|
text = text.remove(QRegularExpression("[^\\w ]", QRegularExpression::UseUnicodePropertiesOption));
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
|
|
||||||
|
|||||||
@@ -120,7 +120,6 @@ class ContextAlbumsModel : public SimpleTreeModel<CollectionItem> {
|
|||||||
QMap<int, CollectionItem*> song_nodes_;
|
QMap<int, CollectionItem*> song_nodes_;
|
||||||
QIcon album_icon_;
|
QIcon album_icon_;
|
||||||
QPixmap no_cover_icon_;
|
QPixmap no_cover_icon_;
|
||||||
QIcon playlists_dir_icon_;
|
|
||||||
AlbumCoverLoaderOptions cover_loader_options_;
|
AlbumCoverLoaderOptions cover_loader_options_;
|
||||||
typedef QPair<CollectionItem*, QString> ItemAndCacheKey;
|
typedef QPair<CollectionItem*, QString> ItemAndCacheKey;
|
||||||
QMap<quint64, ItemAndCacheKey> pending_art_;
|
QMap<quint64, ItemAndCacheKey> pending_art_;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@
|
|||||||
# include "device/devicestatefiltermodel.h"
|
# include "device/devicestatefiltermodel.h"
|
||||||
#endif
|
#endif
|
||||||
#include "dialogs/edittagdialog.h"
|
#include "dialogs/edittagdialog.h"
|
||||||
#include "organise/organisedialog.h"
|
#include "organize/organizedialog.h"
|
||||||
|
|
||||||
#include "contextalbumsmodel.h"
|
#include "contextalbumsmodel.h"
|
||||||
#include "contextalbumsview.h"
|
#include "contextalbumsview.h"
|
||||||
@@ -257,7 +257,7 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, SLOT(AddToPlaylistEnqueue()));
|
add_to_playlist_enqueue_ = context_menu_->addAction(IconLoader::Load("go-next"), tr("Queue track"), this, SLOT(AddToPlaylistEnqueue()));
|
||||||
|
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
|
organize_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, SLOT(Organize()));
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
||||||
#endif
|
#endif
|
||||||
@@ -304,13 +304,13 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
edit_track_->setVisible(regular_editable <= 1);
|
edit_track_->setVisible(regular_editable <= 1);
|
||||||
edit_track_->setEnabled(regular_editable == 1);
|
edit_track_->setEnabled(regular_editable == 1);
|
||||||
|
|
||||||
organise_->setVisible(regular_elements_only);
|
organize_->setVisible(regular_elements_only);
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setVisible(regular_elements_only);
|
copy_to_device_->setVisible(regular_elements_only);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// only when all selected items are editable
|
// only when all selected items are editable
|
||||||
organise_->setEnabled(regular_elements == regular_editable);
|
organize_->setEnabled(regular_elements == regular_editable);
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
||||||
#endif
|
#endif
|
||||||
@@ -369,15 +369,15 @@ SongList ContextAlbumsView::GetSelectedSongs() const {
|
|||||||
return model_->GetChildSongs(selected_indexes);
|
return model_->GetChildSongs(selected_indexes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextAlbumsView::Organise() {
|
void ContextAlbumsView::Organize() {
|
||||||
|
|
||||||
if (!organise_dialog_)
|
if (!organize_dialog_)
|
||||||
organise_dialog_.reset(new OrganiseDialog(app_->task_manager(), app_->collection_backend(), this));
|
organize_dialog_.reset(new OrganizeDialog(app_->task_manager(), app_->collection_backend(), this));
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||||
organise_dialog_->SetCopy(false);
|
organize_dialog_->SetCopy(false);
|
||||||
if (organise_dialog_->SetSongs(GetSelectedSongs()))
|
if (organize_dialog_->SetSongs(GetSelectedSongs()))
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
else {
|
else {
|
||||||
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||||
}
|
}
|
||||||
@@ -396,13 +396,13 @@ void ContextAlbumsView::EditTracks() {
|
|||||||
|
|
||||||
void ContextAlbumsView::CopyToDevice() {
|
void ContextAlbumsView::CopyToDevice() {
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
if (!organise_dialog_)
|
if (!organize_dialog_)
|
||||||
organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
|
organize_dialog_.reset(new OrganizeDialog(app_->task_manager()));
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||||
organise_dialog_->SetCopy(true);
|
organize_dialog_->SetCopy(true);
|
||||||
organise_dialog_->SetSongs(GetSelectedSongs());
|
organize_dialog_->SetSongs(GetSelectedSongs());
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class QPaintEvent;
|
|||||||
class Application;
|
class Application;
|
||||||
class ContextAlbumsModel;
|
class ContextAlbumsModel;
|
||||||
class EditTagDialog;
|
class EditTagDialog;
|
||||||
class OrganiseDialog;
|
class OrganizeDialog;
|
||||||
|
|
||||||
class ContextItemDelegate : public QStyledItemDelegate {
|
class ContextItemDelegate : public QStyledItemDelegate {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -93,7 +93,7 @@ class ContextAlbumsView : public AutoExpandingTreeView {
|
|||||||
void AddToPlaylist();
|
void AddToPlaylist();
|
||||||
void AddToPlaylistEnqueue();
|
void AddToPlaylistEnqueue();
|
||||||
void OpenInNewPlaylist();
|
void OpenInNewPlaylist();
|
||||||
void Organise();
|
void Organize();
|
||||||
void CopyToDevice();
|
void CopyToDevice();
|
||||||
void EditTracks();
|
void EditTracks();
|
||||||
void ShowInBrowser();
|
void ShowInBrowser();
|
||||||
@@ -112,7 +112,7 @@ class ContextAlbumsView : public AutoExpandingTreeView {
|
|||||||
QAction *add_to_playlist_;
|
QAction *add_to_playlist_;
|
||||||
QAction *add_to_playlist_enqueue_;
|
QAction *add_to_playlist_enqueue_;
|
||||||
QAction *open_in_new_playlist_;
|
QAction *open_in_new_playlist_;
|
||||||
QAction *organise_;
|
QAction *organize_;
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
QAction *copy_to_device_;
|
QAction *copy_to_device_;
|
||||||
#endif
|
#endif
|
||||||
@@ -120,7 +120,7 @@ class ContextAlbumsView : public AutoExpandingTreeView {
|
|||||||
QAction *edit_tracks_;
|
QAction *edit_tracks_;
|
||||||
QAction *show_in_browser_;
|
QAction *show_in_browser_;
|
||||||
|
|
||||||
std::unique_ptr<OrganiseDialog> organise_dialog_;
|
std::unique_ptr<OrganizeDialog> organize_dialog_;
|
||||||
std::unique_ptr<EditTagDialog> edit_tag_dialog_;
|
std::unique_ptr<EditTagDialog> edit_tag_dialog_;
|
||||||
|
|
||||||
bool is_in_keyboard_search_;
|
bool is_in_keyboard_search_;
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
SBSystemPreferencesWindow, SBSystemPreferencesPane,
|
SBSystemPreferencesWindow, SBSystemPreferencesPane,
|
||||||
SBSystemPreferencesAnchor;
|
SBSystemPreferencesAnchor;
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wmultichar"
|
||||||
|
#pragma GCC diagnostic ignored "-Wfour-char-constants"
|
||||||
|
|
||||||
enum SBSystemPreferencesSaveOptions {
|
enum SBSystemPreferencesSaveOptions {
|
||||||
SBSystemPreferencesSaveOptionsYes = 'yes ' /* Save the file. */,
|
SBSystemPreferencesSaveOptionsYes = 'yes ' /* Save the file. */,
|
||||||
SBSystemPreferencesSaveOptionsNo = 'no ' /* Do not save the file. */,
|
SBSystemPreferencesSaveOptionsNo = 'no ' /* Do not save the file. */,
|
||||||
@@ -27,6 +31,9 @@ enum SBSystemPreferencesPrintingErrorHandling {
|
|||||||
SBSystemPreferencesPrintingErrorHandlingDetailed =
|
SBSystemPreferencesPrintingErrorHandlingDetailed =
|
||||||
'lwdt' /* print a detailed report of PostScript errors */
|
'lwdt' /* print a detailed report of PostScript errors */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
typedef enum SBSystemPreferencesPrintingErrorHandling
|
typedef enum SBSystemPreferencesPrintingErrorHandling
|
||||||
SBSystemPreferencesPrintingErrorHandling;
|
SBSystemPreferencesPrintingErrorHandling;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringBuilder>
|
#include <QStringBuilder>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QSqlDriver>
|
#include <QSqlDriver>
|
||||||
#include <QSqlDatabase>
|
#include <QSqlDatabase>
|
||||||
@@ -392,7 +392,7 @@ void Database::ExecSchemaCommandsFromFile(QSqlDatabase &db, const QString &filen
|
|||||||
void Database::ExecSchemaCommands(QSqlDatabase &db, const QString &schema, int schema_version, bool in_transaction) {
|
void Database::ExecSchemaCommands(QSqlDatabase &db, const QString &schema, int schema_version, bool in_transaction) {
|
||||||
|
|
||||||
// Run each command
|
// Run each command
|
||||||
const QStringList commands(schema.split(QRegExp("; *\n\n")));
|
const QStringList commands(schema.split(QRegularExpression("; *\n\n")));
|
||||||
|
|
||||||
// We don't want this list to reflect possible DB schema changes so we initialize it before executing any statements.
|
// We don't want this list to reflect possible DB schema changes so we initialize it before executing any statements.
|
||||||
// If no outer transaction is provided the song tables need to be queried before beginning an inner transaction! Otherwise
|
// If no outer transaction is provided the song tables need to be queried before beginning an inner transaction! Otherwise
|
||||||
|
|||||||
@@ -69,8 +69,13 @@ bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job) {
|
|||||||
// Copy or move
|
// Copy or move
|
||||||
bool result(true);
|
bool result(true);
|
||||||
if (job.remove_original_) {
|
if (job.remove_original_) {
|
||||||
result = QFile::rename(src.absoluteFilePath(), dest.absoluteFilePath());
|
if (dest.exists() && !job.overwrite_) {
|
||||||
if (!cover_src.filePath().isEmpty() && !cover_dest.filePath().isEmpty()) {
|
result = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = QFile::rename(src.absoluteFilePath(), dest.absoluteFilePath());
|
||||||
|
}
|
||||||
|
if ((!cover_dest.exists() || job.overwrite_) && !cover_src.filePath().isEmpty() && !cover_dest.filePath().isEmpty()) {
|
||||||
QFile::rename(cover_src.absoluteFilePath(), cover_dest.absoluteFilePath());
|
QFile::rename(cover_src.absoluteFilePath(), cover_dest.absoluteFilePath());
|
||||||
}
|
}
|
||||||
// Remove empty directories.
|
// Remove empty directories.
|
||||||
@@ -83,10 +88,13 @@ bool FilesystemMusicStorage::CopyToStorage(const CopyJob &job) {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!dest.exists()) {
|
if (dest.exists() && !job.overwrite_) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
result = QFile::copy(src.absoluteFilePath(), dest.absoluteFilePath());
|
result = QFile::copy(src.absoluteFilePath(), dest.absoluteFilePath());
|
||||||
}
|
}
|
||||||
if (!cover_src.filePath().isEmpty() && !cover_dest.filePath().isEmpty() && !cover_dest.exists()) {
|
if ((!cover_dest.exists() || job.overwrite_) && !cover_src.filePath().isEmpty() && !cover_dest.filePath().isEmpty()) {
|
||||||
QFile::copy(cover_src.absoluteFilePath(), cover_dest.absoluteFilePath());
|
QFile::copy(cover_src.absoluteFilePath(), cover_dest.absoluteFilePath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,7 +129,6 @@ static const QMap<QString, IconProperties> iconmapper_ = {
|
|||||||
{ "view-refresh", { {}} },
|
{ "view-refresh", { {}} },
|
||||||
{ "library-music", { {"vinyl"}} },
|
{ "library-music", { {"vinyl"}} },
|
||||||
{ "vlc", { {}} },
|
{ "vlc", { {}} },
|
||||||
{ "xine", { {}} },
|
|
||||||
{ "zoom-in", { {}} },
|
{ "zoom-in", { {}} },
|
||||||
{ "zoom-out", { {}, 0, 0 } }
|
{ "zoom-out", { {}, 0, 0 } }
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@
|
|||||||
#include "globalshortcuts/globalshortcutbackend-macos.h"
|
#include "globalshortcuts/globalshortcutbackend-macos.h"
|
||||||
|
|
||||||
#ifdef HAVE_SPARKLE
|
#ifdef HAVE_SPARKLE
|
||||||
# import <Sparkle/SUUpdater.h>
|
# import <SUUpdater.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@@ -117,6 +117,9 @@ QDebug operator<<(QDebug dbg, NSObject* object) {
|
|||||||
|
|
||||||
- (BOOL) applicationShouldHandleReopen: (NSApplication*)app hasVisibleWindows:(BOOL)flag {
|
- (BOOL) applicationShouldHandleReopen: (NSApplication*)app hasVisibleWindows:(BOOL)flag {
|
||||||
|
|
||||||
|
Q_UNUSED(app);
|
||||||
|
Q_UNUSED(flag);
|
||||||
|
|
||||||
if (application_handler_) {
|
if (application_handler_) {
|
||||||
application_handler_->Activate();
|
application_handler_->Activate();
|
||||||
}
|
}
|
||||||
@@ -129,6 +132,7 @@ QDebug operator<<(QDebug dbg, NSObject* object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSMenu*)applicationDockMenu:(NSApplication*)sender {
|
- (NSMenu*)applicationDockMenu:(NSApplication*)sender {
|
||||||
|
Q_UNUSED(sender);
|
||||||
return dock_menu_;
|
return dock_menu_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,11 +145,13 @@ QDebug operator<<(QDebug dbg, NSObject* object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
|
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification {
|
||||||
|
Q_UNUSED(aNotification);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)application:(NSApplication*)app openFile:(NSString*)filename {
|
- (BOOL)application:(NSApplication*)app openFile:(NSString*)filename {
|
||||||
|
|
||||||
|
Q_UNUSED(app);
|
||||||
|
|
||||||
qLog(Debug) << "Wants to open:" << [filename UTF8String];
|
qLog(Debug) << "Wants to open:" << [filename UTF8String];
|
||||||
|
|
||||||
if (application_handler_->LoadUrl(QString::fromUtf8([filename UTF8String]))) {
|
if (application_handler_->LoadUrl(QString::fromUtf8([filename UTF8String]))) {
|
||||||
@@ -159,17 +165,20 @@ QDebug operator<<(QDebug dbg, NSObject* object) {
|
|||||||
- (void)application:(NSApplication*)app openFiles:(NSArray*)filenames {
|
- (void)application:(NSApplication*)app openFiles:(NSArray*)filenames {
|
||||||
|
|
||||||
qLog(Debug) << "Wants to open:" << filenames;
|
qLog(Debug) << "Wants to open:" << filenames;
|
||||||
[filenames enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL* stop) {
|
[filenames enumerateObjectsUsingBlock:^(id object, NSUInteger, BOOL*) {
|
||||||
[self application:app openFile:(NSString*)object];
|
[self application:app openFile:(NSString*)object];
|
||||||
}];
|
}];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*) sender {
|
- (NSApplicationTerminateReply) applicationShouldTerminate:(NSApplication*) sender {
|
||||||
|
Q_UNUSED(sender);
|
||||||
return NSTerminateNow;
|
return NSTerminateNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) userNotificationCenter: (id)center shouldPresentNotification: (id)notification {
|
- (BOOL) userNotificationCenter: (id)center shouldPresentNotification: (id)notification {
|
||||||
|
Q_UNUSED(center);
|
||||||
|
Q_UNUSED(notification);
|
||||||
// Always show notifications, even if Strawberry is in the foreground.
|
// Always show notifications, even if Strawberry is in the foreground.
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ void MacFSListener::Init() { run_loop_ = CFRunLoopGetCurrent(); }
|
|||||||
|
|
||||||
void MacFSListener::EventStreamCallback(ConstFSEventStreamRef stream, void* user_data, size_t num_events, void* event_paths, const FSEventStreamEventFlags event_flags[], const FSEventStreamEventId event_ids[]) {
|
void MacFSListener::EventStreamCallback(ConstFSEventStreamRef stream, void* user_data, size_t num_events, void* event_paths, const FSEventStreamEventFlags event_flags[], const FSEventStreamEventId event_ids[]) {
|
||||||
|
|
||||||
|
Q_UNUSED(stream);
|
||||||
|
Q_UNUSED(event_flags);
|
||||||
|
Q_UNUSED(event_ids);
|
||||||
|
|
||||||
MacFSListener* me = reinterpret_cast<MacFSListener*>(user_data);
|
MacFSListener* me = reinterpret_cast<MacFSListener*>(user_data);
|
||||||
char** paths = reinterpret_cast<char**>(event_paths);
|
char** paths = reinterpret_cast<char**>(event_paths);
|
||||||
for (size_t i = 0; i < num_events; ++i) {
|
for (size_t i = 0; i < num_events; ++i) {
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) validateMenuItem: (NSMenuItem*)menuItem {
|
- (BOOL) validateMenuItem: (NSMenuItem*)menuItem {
|
||||||
|
Q_UNUSED(menuItem);
|
||||||
// This is called when the menu is shown.
|
// This is called when the menu is shown.
|
||||||
return action_->isEnabled();
|
return action_->isEnabled();
|
||||||
}
|
}
|
||||||
@@ -206,5 +207,6 @@ void MacSystemTrayIcon::ClearNowPlaying() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MacSystemTrayIcon::SetNowPlaying(const Song& song, const QUrl& cover_url) {
|
void MacSystemTrayIcon::SetNowPlaying(const Song& song, const QUrl& cover_url) {
|
||||||
|
Q_UNUSED(cover_url);
|
||||||
p_->ShowNowPlaying(song.artist(), song.PrettyTitle());
|
p_->ShowNowPlaying(song.artist(), song.PrettyTitle());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -67,9 +68,11 @@
|
|||||||
#include <QStackedWidget>
|
#include <QStackedWidget>
|
||||||
#include <QTabBar>
|
#include <QTabBar>
|
||||||
#include <QToolButton>
|
#include <QToolButton>
|
||||||
|
#include <QClipboard>
|
||||||
|
|
||||||
#include "core/logging.h"
|
#include "core/logging.h"
|
||||||
#include "core/closure.h"
|
#include "core/closure.h"
|
||||||
|
#include "core/network.h"
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
@@ -97,14 +100,14 @@
|
|||||||
#include "dialogs/trackselectiondialog.h"
|
#include "dialogs/trackselectiondialog.h"
|
||||||
#include "dialogs/edittagdialog.h"
|
#include "dialogs/edittagdialog.h"
|
||||||
#include "dialogs/addstreamdialog.h"
|
#include "dialogs/addstreamdialog.h"
|
||||||
#include "organise/organisedialog.h"
|
#include "organize/organizedialog.h"
|
||||||
#include "widgets/fancytabwidget.h"
|
#include "widgets/fancytabwidget.h"
|
||||||
#include "widgets/playingwidget.h"
|
#include "widgets/playingwidget.h"
|
||||||
#include "widgets/volumeslider.h"
|
#include "widgets/volumeslider.h"
|
||||||
#include "widgets/fileview.h"
|
#include "widgets/fileview.h"
|
||||||
#include "widgets/multiloadingindicator.h"
|
#include "widgets/multiloadingindicator.h"
|
||||||
#include "widgets/osd.h"
|
|
||||||
#include "widgets/trackslider.h"
|
#include "widgets/trackslider.h"
|
||||||
|
#include "osd/osdbase.h"
|
||||||
#include "context/contextview.h"
|
#include "context/contextview.h"
|
||||||
#include "context/contextalbumsview.h"
|
#include "context/contextalbumsview.h"
|
||||||
#include "collection/collection.h"
|
#include "collection/collection.h"
|
||||||
@@ -181,6 +184,14 @@
|
|||||||
# include "windows7thumbbar.h"
|
# include "windows7thumbbar.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_QTSPARKLE
|
||||||
|
# if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
|
# include <qtsparkle-qt6/Updater>
|
||||||
|
# else
|
||||||
|
# include <qtsparkle-qt5/Updater>
|
||||||
|
# endif
|
||||||
|
#endif // HAVE_QTSPARKLE
|
||||||
|
|
||||||
const char *MainWindow::kSettingsGroup = "MainWindow";
|
const char *MainWindow::kSettingsGroup = "MainWindow";
|
||||||
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
||||||
|
|
||||||
@@ -189,7 +200,7 @@ const int kTrackSliderUpdateTimeMs = 200;
|
|||||||
const int kTrackPositionUpdateTimeMs = 1000;
|
const int kTrackPositionUpdateTimeMs = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, const CommandlineOptions &options, QWidget *parent) :
|
MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd, const CommandlineOptions &options, QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
ui_(new Ui_MainWindow),
|
ui_(new Ui_MainWindow),
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
@@ -221,8 +232,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
return cover_manager;
|
return cover_manager;
|
||||||
}),
|
}),
|
||||||
equalizer_(new Equalizer),
|
equalizer_(new Equalizer),
|
||||||
organise_dialog_([=]() {
|
organize_dialog_([=]() {
|
||||||
OrganiseDialog *dialog = new OrganiseDialog(app->task_manager(), app->collection_backend(), this);
|
OrganizeDialog *dialog = new OrganizeDialog(app->task_manager(), app->collection_backend(), this);
|
||||||
dialog->SetDestinationModel(app->collection()->model()->directory_model());
|
dialog->SetDestinationModel(app->collection()->model()->directory_model());
|
||||||
return dialog;
|
return dialog;
|
||||||
}),
|
}),
|
||||||
@@ -243,9 +254,28 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
#ifdef HAVE_TIDAL
|
#ifdef HAVE_TIDAL
|
||||||
tidal_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source_Tidal), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)),
|
tidal_view_(new InternetTabsView(app_, app->internet_services()->ServiceBySource(Song::Source_Tidal), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)),
|
||||||
#endif
|
#endif
|
||||||
|
collection_show_all_(nullptr),
|
||||||
|
collection_show_duplicates_(nullptr),
|
||||||
|
collection_show_untagged_(nullptr),
|
||||||
playlist_menu_(new QMenu(this)),
|
playlist_menu_(new QMenu(this)),
|
||||||
|
playlist_play_pause_(nullptr),
|
||||||
|
playlist_stop_after_(nullptr),
|
||||||
|
playlist_undoredo_(nullptr),
|
||||||
|
playlist_organize_(nullptr),
|
||||||
|
playlist_show_in_collection_(nullptr),
|
||||||
|
playlist_copy_to_collection_(nullptr),
|
||||||
|
playlist_move_to_collection_(nullptr),
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
playlist_copy_to_device_(nullptr),
|
||||||
|
#endif
|
||||||
|
playlist_open_in_browser_(nullptr),
|
||||||
|
playlist_copy_url_(nullptr),
|
||||||
|
playlist_queue_(nullptr),
|
||||||
|
playlist_queue_play_next_(nullptr),
|
||||||
|
playlist_skip_(nullptr),
|
||||||
playlist_add_to_another_(nullptr),
|
playlist_add_to_another_(nullptr),
|
||||||
playlistitem_actions_separator_(nullptr),
|
playlistitem_actions_separator_(nullptr),
|
||||||
|
playlist_rescan_songs_(nullptr),
|
||||||
collection_sort_model_(new QSortFilterProxyModel(this)),
|
collection_sort_model_(new QSortFilterProxyModel(this)),
|
||||||
track_position_timer_(new QTimer(this)),
|
track_position_timer_(new QTimer(this)),
|
||||||
track_slider_timer_(new QTimer(this)),
|
track_slider_timer_(new QTimer(this)),
|
||||||
@@ -335,7 +365,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
#endif
|
#endif
|
||||||
playlist_list_->SetApplication(app_);
|
playlist_list_->SetApplication(app_);
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->collection()->model()->directory_model());
|
organize_dialog_->SetDestinationModel(app_->collection()->model()->directory_model());
|
||||||
|
|
||||||
// Icons
|
// Icons
|
||||||
qLog(Debug) << "Creating UI";
|
qLog(Debug) << "Creating UI";
|
||||||
@@ -371,8 +401,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
ui_->action_shuffle->setIcon(IconLoader::Load("media-playlist-shuffle"));
|
ui_->action_shuffle->setIcon(IconLoader::Load("media-playlist-shuffle"));
|
||||||
ui_->action_remove_duplicates->setIcon(IconLoader::Load("list-remove"));
|
ui_->action_remove_duplicates->setIcon(IconLoader::Load("list-remove"));
|
||||||
ui_->action_remove_unavailable->setIcon(IconLoader::Load("list-remove"));
|
ui_->action_remove_unavailable->setIcon(IconLoader::Load("list-remove"));
|
||||||
|
ui_->action_remove_from_playlist->setIcon(IconLoader::Load("list-remove"));
|
||||||
//ui_->action_remove_from_playlist->setIcon(IconLoader::Load("list-remove"));
|
|
||||||
|
|
||||||
// Configure
|
// Configure
|
||||||
|
|
||||||
@@ -416,7 +445,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
connect(ui_->action_remove_unavailable, SIGNAL(triggered()), app_->playlist_manager(), SLOT(RemoveUnavailableCurrent()));
|
connect(ui_->action_remove_unavailable, SIGNAL(triggered()), app_->playlist_manager(), SLOT(RemoveUnavailableCurrent()));
|
||||||
connect(ui_->action_remove_from_playlist, SIGNAL(triggered()), SLOT(PlaylistRemoveCurrent()));
|
connect(ui_->action_remove_from_playlist, SIGNAL(triggered()), SLOT(PlaylistRemoveCurrent()));
|
||||||
connect(ui_->action_edit_track, SIGNAL(triggered()), SLOT(EditTracks()));
|
connect(ui_->action_edit_track, SIGNAL(triggered()), SLOT(EditTracks()));
|
||||||
connect(ui_->action_rescan_songs, SIGNAL(triggered()), SLOT(RescanSongs()));
|
|
||||||
connect(ui_->action_renumber_tracks, SIGNAL(triggered()), SLOT(RenumberTracks()));
|
connect(ui_->action_renumber_tracks, SIGNAL(triggered()), SLOT(RenumberTracks()));
|
||||||
connect(ui_->action_selection_set_value, SIGNAL(triggered()), SLOT(SelectionSetValue()));
|
connect(ui_->action_selection_set_value, SIGNAL(triggered()), SLOT(SelectionSetValue()));
|
||||||
connect(ui_->action_edit_value, SIGNAL(triggered()), SLOT(EditValue()));
|
connect(ui_->action_edit_value, SIGNAL(triggered()), SLOT(EditValue()));
|
||||||
@@ -446,6 +474,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
connect(ui_->action_abort_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(AbortScan()));
|
connect(ui_->action_abort_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(AbortScan()));
|
||||||
#if defined(HAVE_GSTREAMER)
|
#if defined(HAVE_GSTREAMER)
|
||||||
connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()), SLOT(AddFilesToTranscoder()));
|
connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()), SLOT(AddFilesToTranscoder()));
|
||||||
|
ui_->action_add_files_to_transcoder->setIcon(IconLoader::Load("tools-wizard"));
|
||||||
#else
|
#else
|
||||||
ui_->action_add_files_to_transcoder->setDisabled(true);
|
ui_->action_add_files_to_transcoder->setDisabled(true);
|
||||||
#endif
|
#endif
|
||||||
@@ -621,8 +650,11 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
playlist_menu_->addAction(ui_->action_edit_value);
|
playlist_menu_->addAction(ui_->action_edit_value);
|
||||||
playlist_menu_->addAction(ui_->action_renumber_tracks);
|
playlist_menu_->addAction(ui_->action_renumber_tracks);
|
||||||
playlist_menu_->addAction(ui_->action_selection_set_value);
|
playlist_menu_->addAction(ui_->action_selection_set_value);
|
||||||
|
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||||
playlist_menu_->addAction(ui_->action_auto_complete_tags);
|
playlist_menu_->addAction(ui_->action_auto_complete_tags);
|
||||||
playlist_menu_->addAction(ui_->action_rescan_songs);
|
#endif
|
||||||
|
playlist_rescan_songs_ = playlist_menu_->addAction(IconLoader::Load("view-refresh"), tr("Rescan song(s)..."), this, SLOT(RescanSongs()));
|
||||||
|
playlist_menu_->addAction(playlist_rescan_songs_);
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
playlist_menu_->addAction(ui_->action_add_files_to_transcoder);
|
playlist_menu_->addAction(ui_->action_add_files_to_transcoder);
|
||||||
#endif
|
#endif
|
||||||
@@ -632,10 +664,11 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
#endif
|
#endif
|
||||||
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
|
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
|
||||||
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
|
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
|
||||||
playlist_organise_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(PlaylistMoveToCollection()));
|
playlist_organize_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organize files..."), this, SLOT(PlaylistMoveToCollection()));
|
||||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
||||||
playlist_open_in_browser_->setVisible(false);
|
playlist_open_in_browser_->setVisible(false);
|
||||||
playlist_show_in_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-find"), tr("Show in collection..."), this, SLOT(ShowInCollection()));
|
playlist_show_in_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-find"), tr("Show in collection..."), this, SLOT(ShowInCollection()));
|
||||||
|
playlist_copy_url_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy URL(s)..."), this, SLOT(PlaylistCopyUrl()));
|
||||||
playlist_menu_->addSeparator();
|
playlist_menu_->addSeparator();
|
||||||
playlistitem_actions_separator_ = playlist_menu_->addSeparator();
|
playlistitem_actions_separator_ = playlist_menu_->addSeparator();
|
||||||
playlist_menu_->addAction(ui_->action_clear_playlist);
|
playlist_menu_->addAction(ui_->action_clear_playlist);
|
||||||
@@ -681,8 +714,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
thumbbar_->SetActions(QList<QAction*>() << ui_->action_previous_track << ui_->action_play_pause << ui_->action_stop << ui_->action_next_track << nullptr << ui_->action_love);
|
thumbbar_->SetActions(QList<QAction*>() << ui_->action_previous_track << ui_->action_play_pause << ui_->action_stop << ui_->action_next_track << nullptr << ui_->action_love);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(Q_OS_MACOS) && defined(HAVE_SPARKLE))
|
#if defined(HAVE_SPARKLE) || defined(HAVE_QTSPARKLE)
|
||||||
// Add check for updates item to application menu.
|
|
||||||
QAction *check_updates = ui_->menu_tools->addAction(tr("Check for updates..."));
|
QAction *check_updates = ui_->menu_tools->addAction(tr("Check for updates..."));
|
||||||
check_updates->setMenuRole(QAction::ApplicationSpecificRole);
|
check_updates->setMenuRole(QAction::ApplicationSpecificRole);
|
||||||
connect(check_updates, SIGNAL(triggered(bool)), SLOT(CheckForUpdates()));
|
connect(check_updates, SIGNAL(triggered(bool)), SLOT(CheckForUpdates()));
|
||||||
@@ -822,42 +854,48 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
// Reload playlist settings, for BG and glowing
|
// Reload playlist settings, for BG and glowing
|
||||||
ui_->playlist->view()->ReloadSettings();
|
ui_->playlist->view()->ReloadSettings();
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS // Always show mainwindow on startup if on macos
|
#ifdef Q_OS_MACOS // Always show the mainwindow on startup for macOS
|
||||||
show();
|
show();
|
||||||
#else
|
#else
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
s.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||||
BehaviourSettingsPage::StartupBehaviour behaviour = BehaviourSettingsPage::StartupBehaviour(s.value("startupbehaviour", BehaviourSettingsPage::Startup_Remember).toInt());
|
BehaviourSettingsPage::StartupBehaviour behaviour = BehaviourSettingsPage::StartupBehaviour(s.value("startupbehaviour", BehaviourSettingsPage::Startup_Remember).toInt());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
bool hidden = settings_.value("hidden", false).toBool();
|
switch (behaviour) {
|
||||||
if (hidden && (!QSystemTrayIcon::isSystemTrayAvailable() || !tray_icon_ || !tray_icon_->IsVisible())) {
|
case BehaviourSettingsPage::Startup_Show:
|
||||||
hidden = false;
|
show();
|
||||||
settings_.setValue("hidden", false);
|
break;
|
||||||
show();
|
case BehaviourSettingsPage::Startup_ShowMaximized:
|
||||||
}
|
setWindowState(windowState() | Qt::WindowMaximized);
|
||||||
else {
|
show();
|
||||||
switch (behaviour) {
|
break;
|
||||||
case BehaviourSettingsPage::Startup_Remember:
|
case BehaviourSettingsPage::Startup_ShowMinimized:
|
||||||
was_maximized_ = settings_.value("maximized", true).toBool();
|
setWindowState(windowState() | Qt::WindowMinimized);
|
||||||
if (was_maximized_) setWindowState(windowState() | Qt::WindowMaximized);
|
show();
|
||||||
was_minimized_ = settings_.value("minimized", false).toBool();
|
break;
|
||||||
if (was_minimized_) setWindowState(windowState() | Qt::WindowMinimized);
|
case BehaviourSettingsPage::Startup_Hide:
|
||||||
setVisible(!hidden);
|
if (QSystemTrayIcon::isSystemTrayAvailable() && tray_icon_ && tray_icon_->IsVisible()) {
|
||||||
break;
|
|
||||||
case BehaviourSettingsPage::Startup_Show:
|
|
||||||
show();
|
|
||||||
break;
|
|
||||||
case BehaviourSettingsPage::Startup_Hide:
|
|
||||||
hide();
|
hide();
|
||||||
break;
|
break;
|
||||||
case BehaviourSettingsPage::Startup_ShowMaximized:
|
}
|
||||||
setWindowState(windowState() | Qt::WindowMaximized);
|
// fallthrough
|
||||||
|
case BehaviourSettingsPage::Startup_Remember:
|
||||||
|
default: {
|
||||||
|
|
||||||
|
was_maximized_ = settings_.value("maximized", true).toBool();
|
||||||
|
if (was_maximized_) setWindowState(windowState() | Qt::WindowMaximized);
|
||||||
|
|
||||||
|
was_minimized_ = settings_.value("minimized", false).toBool();
|
||||||
|
if (was_minimized_) setWindowState(windowState() | Qt::WindowMinimized);
|
||||||
|
|
||||||
|
if (!QSystemTrayIcon::isSystemTrayAvailable() || !tray_icon_ || !tray_icon_->IsVisible()) {
|
||||||
|
settings_.setValue("hidden", false);
|
||||||
show();
|
show();
|
||||||
break;
|
}
|
||||||
case BehaviourSettingsPage::Startup_ShowMinimized:
|
else {
|
||||||
setWindowState(windowState() | Qt::WindowMinimized);
|
setVisible(!settings_.value("hidden", false).toBool());
|
||||||
show();
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -881,6 +919,22 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
app_->scrobbler()->Submit();
|
app_->scrobbler()->Submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_QTSPARKLE
|
||||||
|
QUrl sparkle_url;
|
||||||
|
#if defined(Q_OS_MACOS)
|
||||||
|
sparkle_url.setUrl("https://www.strawberrymusicplayer.org/sparkle-macos");
|
||||||
|
#elif defined(Q_OS_WIN)
|
||||||
|
sparkle_url.setUrl("https://www.strawberrymusicplayer.org/sparkle-windows");
|
||||||
|
#endif
|
||||||
|
if (!sparkle_url.isEmpty()) {
|
||||||
|
qLog(Debug) << "Creating Qt Sparkle updater";
|
||||||
|
qtsparkle::Updater *updater = new qtsparkle::Updater(sparkle_url, this);
|
||||||
|
updater->SetNetworkAccessManager(new NetworkAccessManager(this));
|
||||||
|
updater->SetVersion(STRAWBERRY_VERSION_PACKAGE);
|
||||||
|
connect(check_updates, SIGNAL(triggered()), updater, SLOT(CheckNow()));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
qLog(Debug) << "Started" << QThread::currentThread();
|
qLog(Debug) << "Started" << QThread::currentThread();
|
||||||
initialized_ = true;
|
initialized_ = true;
|
||||||
|
|
||||||
@@ -936,6 +990,8 @@ void MainWindow::ReloadSettings() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osd_->ReloadSettings();
|
||||||
|
|
||||||
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings_.value("search_for_cover_auto", true).toBool());
|
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings_.value("search_for_cover_auto", true).toBool());
|
||||||
|
|
||||||
#ifdef HAVE_SUBSONIC
|
#ifdef HAVE_SUBSONIC
|
||||||
@@ -970,7 +1026,6 @@ void MainWindow::ReloadAllSettings() {
|
|||||||
app_->ReloadSettings();
|
app_->ReloadSettings();
|
||||||
app_->collection()->ReloadSettings();
|
app_->collection()->ReloadSettings();
|
||||||
app_->player()->ReloadSettings();
|
app_->player()->ReloadSettings();
|
||||||
osd_->ReloadSettings();
|
|
||||||
collection_view_->ReloadSettings();
|
collection_view_->ReloadSettings();
|
||||||
ui_->playlist->view()->ReloadSettings();
|
ui_->playlist->view()->ReloadSettings();
|
||||||
app_->playlist_manager()->playlist_container()->ReloadSettings();
|
app_->playlist_manager()->playlist_container()->ReloadSettings();
|
||||||
@@ -1052,7 +1107,7 @@ void MainWindow::ExitFinished() {
|
|||||||
|
|
||||||
void MainWindow::EngineChanged(Engine::EngineType enginetype) {
|
void MainWindow::EngineChanged(Engine::EngineType enginetype) {
|
||||||
|
|
||||||
ui_->action_equalizer->setEnabled(enginetype == Engine::EngineType::GStreamer || enginetype == Engine::EngineType::Xine);
|
ui_->action_equalizer->setEnabled(enginetype == Engine::EngineType::GStreamer);
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
ui_->action_open_cd->setEnabled(false);
|
ui_->action_open_cd->setEnabled(false);
|
||||||
ui_->action_open_cd->setVisible(false);
|
ui_->action_open_cd->setVisible(false);
|
||||||
@@ -1191,7 +1246,7 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
|||||||
|
|
||||||
void MainWindow::TabSwitched() {
|
void MainWindow::TabSwitched() {
|
||||||
|
|
||||||
if (playing_widget_ && ui_->action_toggle_show_sidebar->isChecked() && (ui_->tabs->tabBar()->tabData(ui_->tabs->currentIndex()).toString().toLower() != "context" || !context_view_->album_enabled())) {
|
if (playing_widget_ && ui_->action_toggle_show_sidebar->isChecked() && (ui_->tabs->currentIndex() != ui_->tabs->IndexOfTab(context_view_) || !context_view_->album_enabled())) {
|
||||||
ui_->widget_playing->SetEnabled();
|
ui_->widget_playing->SetEnabled();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1596,14 +1651,14 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Are we allowed to pause?
|
// Are we allowed to pause?
|
||||||
if (index.isValid()) {
|
if (source_index.isValid()) {
|
||||||
playlist_play_pause_->setEnabled(app_->playlist_manager()->current()->current_row() != source_index.row() || !(app_->playlist_manager()->current()->item_at(source_index.row())->options() & PlaylistItem::PauseDisabled));
|
playlist_play_pause_->setEnabled(app_->playlist_manager()->current()->current_row() != source_index.row() || !(app_->playlist_manager()->current()->item_at(source_index.row())->options() & PlaylistItem::PauseDisabled));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
playlist_play_pause_->setEnabled(false);
|
playlist_play_pause_->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
playlist_stop_after_->setEnabled(index.isValid());
|
playlist_stop_after_->setEnabled(source_index.isValid());
|
||||||
|
|
||||||
// Are any of the selected songs editable or queued?
|
// Are any of the selected songs editable or queued?
|
||||||
QModelIndexList selection = ui_->playlist->view()->selectionModel()->selectedRows();
|
QModelIndexList selection = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||||
@@ -1615,6 +1670,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
int in_skipped = 0;
|
int in_skipped = 0;
|
||||||
int not_in_skipped = 0;
|
int not_in_skipped = 0;
|
||||||
int local_songs = 0;
|
int local_songs = 0;
|
||||||
|
int collection_songs = 0;
|
||||||
|
|
||||||
for (const QModelIndex &idx : selection) {
|
for (const QModelIndex &idx : selection) {
|
||||||
|
|
||||||
@@ -1625,6 +1681,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
|
|
||||||
if (item->Metadata().url().isLocalFile()) ++local_songs;
|
if (item->Metadata().url().isLocalFile()) ++local_songs;
|
||||||
|
if (item->Metadata().source() == Song::Source_Collection) ++collection_songs;
|
||||||
|
|
||||||
if (item->Metadata().has_cue()) {
|
if (item->Metadata().has_cue()) {
|
||||||
cue_selected = true;
|
cue_selected = true;
|
||||||
@@ -1642,29 +1699,32 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this is available when we have one or many files and at least one of those is not CUE related
|
// this is available when we have one or many files and at least one of those is not CUE related
|
||||||
ui_->action_edit_track->setEnabled(editable);
|
ui_->action_edit_track->setEnabled(editable > 0);
|
||||||
ui_->action_edit_track->setVisible(editable);
|
ui_->action_edit_track->setVisible(editable > 0);
|
||||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||||
ui_->action_auto_complete_tags->setEnabled(editable);
|
ui_->action_auto_complete_tags->setEnabled(editable > 0);
|
||||||
ui_->action_auto_complete_tags->setVisible(editable);
|
ui_->action_auto_complete_tags->setVisible(editable > 0);
|
||||||
#else
|
|
||||||
ui_->action_auto_complete_tags->setEnabled(false);
|
|
||||||
ui_->action_auto_complete_tags->setVisible(false);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ui_->action_rescan_songs->setEnabled(editable);
|
playlist_rescan_songs_->setEnabled(editable > 0);
|
||||||
ui_->action_rescan_songs->setVisible(editable);
|
playlist_rescan_songs_->setVisible(editable > 0);
|
||||||
|
|
||||||
|
#ifdef HAVE_GSTREAMER
|
||||||
|
ui_->action_add_files_to_transcoder->setEnabled(editable);
|
||||||
|
ui_->action_add_files_to_transcoder->setVisible(editable);
|
||||||
|
#endif
|
||||||
|
|
||||||
// the rest of the read / write actions work only when there are no CUEs involved
|
// the rest of the read / write actions work only when there are no CUEs involved
|
||||||
if (cue_selected) editable = 0;
|
if (cue_selected) editable = 0;
|
||||||
|
|
||||||
playlist_open_in_browser_->setVisible(local_songs == selected);
|
playlist_open_in_browser_->setVisible(selected > 0 && local_songs == selected);
|
||||||
|
|
||||||
bool track_column = (index.column() == Playlist::Column_Track);
|
bool track_column = (index.column() == Playlist::Column_Track);
|
||||||
ui_->action_renumber_tracks->setVisible(editable >= 2 && track_column);
|
ui_->action_renumber_tracks->setVisible(editable >= 2 && track_column);
|
||||||
ui_->action_selection_set_value->setVisible(editable >= 2 && !track_column);
|
ui_->action_selection_set_value->setVisible(editable >= 2 && !track_column);
|
||||||
ui_->action_edit_value->setVisible(editable);
|
ui_->action_edit_value->setVisible(editable > 0);
|
||||||
ui_->action_remove_from_playlist->setEnabled(!selection.isEmpty());
|
ui_->action_remove_from_playlist->setEnabled(selected > 0);
|
||||||
|
ui_->action_remove_from_playlist->setVisible(selected > 0);
|
||||||
|
|
||||||
playlist_show_in_collection_->setVisible(false);
|
playlist_show_in_collection_->setVisible(false);
|
||||||
playlist_copy_to_collection_->setVisible(false);
|
playlist_copy_to_collection_->setVisible(false);
|
||||||
@@ -1672,7 +1732,9 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
playlist_copy_to_device_->setVisible(false);
|
playlist_copy_to_device_->setVisible(false);
|
||||||
#endif
|
#endif
|
||||||
playlist_organise_->setVisible(false);
|
playlist_organize_->setVisible(false);
|
||||||
|
|
||||||
|
playlist_copy_url_->setVisible(selected > 0);
|
||||||
|
|
||||||
if (selected < 1) {
|
if (selected < 1) {
|
||||||
playlist_queue_->setVisible(false);
|
playlist_queue_->setVisible(false);
|
||||||
@@ -1715,7 +1777,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
else {
|
else {
|
||||||
|
|
||||||
Playlist::Column column = static_cast<Playlist::Column>(index.column());
|
Playlist::Column column = static_cast<Playlist::Column>(index.column());
|
||||||
bool column_is_editable = Playlist::column_is_editable(column) && editable;
|
bool column_is_editable = Playlist::column_is_editable(column) && editable > 0;
|
||||||
|
|
||||||
ui_->action_selection_set_value->setVisible(ui_->action_selection_set_value->isVisible() && column_is_editable);
|
ui_->action_selection_set_value->setVisible(ui_->action_selection_set_value->isVisible() && column_is_editable);
|
||||||
ui_->action_edit_value->setVisible(ui_->action_edit_value->isVisible() && column_is_editable);
|
ui_->action_edit_value->setVisible(ui_->action_edit_value->isVisible() && column_is_editable);
|
||||||
@@ -1730,17 +1792,17 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
// Is it a collection item?
|
// Is it a collection item?
|
||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (item && item->IsLocalCollectionItem() && item->Metadata().id() != -1) {
|
if (item && item->IsLocalCollectionItem() && item->Metadata().id() != -1) {
|
||||||
playlist_organise_->setVisible(editable);
|
playlist_organize_->setVisible(editable > 0);
|
||||||
playlist_show_in_collection_->setVisible(editable);
|
playlist_show_in_collection_->setVisible(editable > 0);
|
||||||
playlist_open_in_browser_->setVisible(true);
|
playlist_open_in_browser_->setVisible(true);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
playlist_copy_to_collection_->setVisible(editable);
|
playlist_copy_to_collection_->setVisible(editable > 0);
|
||||||
playlist_move_to_collection_->setVisible(editable);
|
playlist_move_to_collection_->setVisible(editable > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
playlist_copy_to_device_->setVisible(editable);
|
playlist_copy_to_device_->setVisible(editable > 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Remove old item actions, if any.
|
// Remove old item actions, if any.
|
||||||
@@ -1758,32 +1820,36 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
if (playlist_add_to_another_ != nullptr) {
|
if (playlist_add_to_another_ != nullptr) {
|
||||||
playlist_menu_->removeAction(playlist_add_to_another_);
|
playlist_menu_->removeAction(playlist_add_to_another_);
|
||||||
delete playlist_add_to_another_;
|
delete playlist_add_to_another_;
|
||||||
|
playlist_add_to_another_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the playlist submenu
|
// Create the playlist submenu if songs are selected.
|
||||||
QMenu *add_to_another_menu = new QMenu(tr("Add to another playlist"), this);
|
if (selected > 0) {
|
||||||
add_to_another_menu->setIcon(IconLoader::Load("list-add"));
|
QMenu *add_to_another_menu = new QMenu(tr("Add to another playlist"), this);
|
||||||
|
add_to_another_menu->setIcon(IconLoader::Load("list-add"));
|
||||||
|
|
||||||
for (const PlaylistBackend::Playlist &playlist : app_->playlist_backend()->GetAllOpenPlaylists()) {
|
for (const PlaylistBackend::Playlist &playlist : app_->playlist_backend()->GetAllOpenPlaylists()) {
|
||||||
// don't add the current playlist
|
// don't add the current playlist
|
||||||
if (playlist.id != app_->playlist_manager()->current()->id()) {
|
if (playlist.id != app_->playlist_manager()->current()->id()) {
|
||||||
QAction *existing_playlist = new QAction(this);
|
QAction *existing_playlist = new QAction(this);
|
||||||
existing_playlist->setText(playlist.name);
|
existing_playlist->setText(playlist.name);
|
||||||
existing_playlist->setData(playlist.id);
|
existing_playlist->setData(playlist.id);
|
||||||
add_to_another_menu->addAction(existing_playlist);
|
add_to_another_menu->addAction(existing_playlist);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_to_another_menu->addSeparator();
|
||||||
|
// add to a new playlist
|
||||||
|
QAction *new_playlist = new QAction(this);
|
||||||
|
new_playlist->setText(tr("New playlist"));
|
||||||
|
new_playlist->setData(-1); // fake id
|
||||||
|
add_to_another_menu->addAction(new_playlist);
|
||||||
|
playlist_add_to_another_ = playlist_menu_->insertMenu(ui_->action_remove_from_playlist, add_to_another_menu);
|
||||||
|
|
||||||
|
connect(add_to_another_menu, SIGNAL(triggered(QAction*)), SLOT(AddToPlaylist(QAction*)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
add_to_another_menu->addSeparator();
|
|
||||||
// add to a new playlist
|
|
||||||
QAction *new_playlist = new QAction(this);
|
|
||||||
new_playlist->setText(tr("New playlist"));
|
|
||||||
new_playlist->setData(-1); // fake id
|
|
||||||
add_to_another_menu->addAction(new_playlist);
|
|
||||||
playlist_add_to_another_ = playlist_menu_->insertMenu(ui_->action_remove_from_playlist, add_to_another_menu);
|
|
||||||
|
|
||||||
connect(add_to_another_menu, SIGNAL(triggered(QAction*)), SLOT(AddToPlaylist(QAction*)));
|
|
||||||
|
|
||||||
playlist_menu_->popup(global_pos);
|
playlist_menu_->popup(global_pos);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1811,8 +1877,13 @@ void MainWindow::RescanSongs() {
|
|||||||
const QModelIndex source_index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
const QModelIndex source_index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
||||||
if (!item || !item->IsLocalCollectionItem()) continue;
|
if (!item) continue;
|
||||||
songs << item->Metadata();
|
if (item->IsLocalCollectionItem()) {
|
||||||
|
songs << item->Metadata();
|
||||||
|
}
|
||||||
|
else if (item->Metadata().source() == Song::Source_LocalFile) {
|
||||||
|
item->Reload();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (songs.isEmpty()) return;
|
if (songs.isEmpty()) return;
|
||||||
@@ -1831,7 +1902,7 @@ void MainWindow::EditTracks() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (song.IsEditable()) {
|
if (song.IsEditable()) {
|
||||||
songs << song;
|
songs << song;
|
||||||
items << item;
|
items << item;
|
||||||
@@ -1868,7 +1939,7 @@ void MainWindow::RenumberTracks() {
|
|||||||
|
|
||||||
// if first selected song has a track number set, start from that offset
|
// if first selected song has a track number set, start from that offset
|
||||||
if (!indexes.isEmpty()) {
|
if (!indexes.isEmpty()) {
|
||||||
const Song first_song = app_->playlist_manager()->current()->item_at(indexes[0].row())->Metadata();
|
const Song first_song = app_->playlist_manager()->current()->item_at(indexes[0].row())->OriginalMetadata();
|
||||||
if (first_song.track() > 0) track = first_song.track();
|
if (first_song.track() > 0) track = first_song.track();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1877,7 +1948,7 @@ void MainWindow::RenumberTracks() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (song.IsEditable()) {
|
if (song.IsEditable()) {
|
||||||
song.set_track(track);
|
song.set_track(track);
|
||||||
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||||
@@ -1907,7 +1978,7 @@ void MainWindow::SelectionSetValue() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
||||||
if (Playlist::set_column_value(song, column, column_value)) {
|
if (Playlist::set_column_value(song, column, column_value)) {
|
||||||
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
TagReaderReply *reply = TagReaderClient::Instance()->SaveFile(song.url().toLocalFile(), song);
|
||||||
@@ -2013,13 +2084,13 @@ void MainWindow::ShowInCollection() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (item && item->IsLocalCollectionItem()) {
|
if (item && item->IsLocalCollectionItem()) {
|
||||||
songs << item->Metadata();
|
songs << item->OriginalMetadata();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QString search;
|
QString search;
|
||||||
if (!songs.isEmpty()) {
|
if (!songs.isEmpty()) {
|
||||||
search ="artist:" + songs.first().artist() + " album:" + songs.first().album();
|
search = "artist:" + songs.first().artist() + " album:" + songs.first().album();
|
||||||
}
|
}
|
||||||
collection_view_->filter()->ShowInCollection(search);
|
collection_view_->filter()->ShowInCollection(search);
|
||||||
|
|
||||||
@@ -2210,7 +2281,7 @@ void MainWindow::AddFilesToTranscoder() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
||||||
filenames << song.url().toLocalFile();
|
filenames << song.url().toLocalFile();
|
||||||
}
|
}
|
||||||
@@ -2252,29 +2323,29 @@ void MainWindow::PlayingWidgetPositionChanged(const bool above_status_bar) {
|
|||||||
|
|
||||||
void MainWindow::CopyFilesToCollection(const QList<QUrl> &urls) {
|
void MainWindow::CopyFilesToCollection(const QList<QUrl> &urls) {
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||||
organise_dialog_->SetUrls(urls);
|
organize_dialog_->SetUrls(urls);
|
||||||
organise_dialog_->SetCopy(true);
|
organize_dialog_->SetCopy(true);
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::MoveFilesToCollection(const QList<QUrl> &urls) {
|
void MainWindow::MoveFilesToCollection(const QList<QUrl> &urls) {
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||||
organise_dialog_->SetUrls(urls);
|
organize_dialog_->SetUrls(urls);
|
||||||
organise_dialog_->SetCopy(false);
|
organize_dialog_->SetCopy(false);
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
|
void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
|
||||||
|
|
||||||
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||||
organise_dialog_->SetCopy(true);
|
organize_dialog_->SetCopy(true);
|
||||||
if (organise_dialog_->SetUrls(urls))
|
if (organize_dialog_->SetUrls(urls))
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
else {
|
else {
|
||||||
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||||
}
|
}
|
||||||
@@ -2301,14 +2372,14 @@ void MainWindow::EditFileTags(const QList<QUrl> &urls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::PlaylistCopyToCollection() {
|
void MainWindow::PlaylistCopyToCollection() {
|
||||||
PlaylistOrganiseSelected(true);
|
PlaylistOrganizeSelected(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::PlaylistMoveToCollection() {
|
void MainWindow::PlaylistMoveToCollection() {
|
||||||
PlaylistOrganiseSelected(false);
|
PlaylistOrganizeSelected(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::PlaylistOrganiseSelected(const bool copy) {
|
void MainWindow::PlaylistOrganizeSelected(const bool copy) {
|
||||||
|
|
||||||
SongList songs;
|
SongList songs;
|
||||||
for (const QModelIndex &proxy_index : ui_->playlist->view()->selectionModel()->selectedRows()) {
|
for (const QModelIndex &proxy_index : ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||||
@@ -2316,16 +2387,16 @@ void MainWindow::PlaylistOrganiseSelected(const bool copy) {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
||||||
songs << song;
|
songs << song;
|
||||||
}
|
}
|
||||||
if (songs.isEmpty()) return;
|
if (songs.isEmpty()) return;
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
organize_dialog_->SetDestinationModel(app_->collection_model()->directory_model());
|
||||||
organise_dialog_->SetSongs(songs);
|
organize_dialog_->SetSongs(songs);
|
||||||
organise_dialog_->SetCopy(copy);
|
organize_dialog_->SetCopy(copy);
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2342,6 +2413,25 @@ void MainWindow::PlaylistOpenInBrowser() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::PlaylistCopyUrl() {
|
||||||
|
|
||||||
|
QList<QUrl> urls;
|
||||||
|
for (const QModelIndex &proxy_index : ui_->playlist->view()->selectionModel()->selectedRows()) {
|
||||||
|
const QModelIndex source_index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||||
|
if (!source_index.isValid()) continue;
|
||||||
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
|
if (!item) continue;
|
||||||
|
urls << item->StreamUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (urls.count() > 0) {
|
||||||
|
QMimeData *mime_data = new QMimeData;
|
||||||
|
mime_data->setUrls(urls);
|
||||||
|
QApplication::clipboard()->setMimeData(mime_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::PlaylistQueue() {
|
void MainWindow::PlaylistQueue() {
|
||||||
|
|
||||||
QModelIndexList indexes;
|
QModelIndexList indexes;
|
||||||
@@ -2387,16 +2477,16 @@ void MainWindow::PlaylistCopyToDevice() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
PlaylistItemPtr item = app_->playlist_manager()->current()->item_at(source_index.row());
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
if (!song.is_valid() || !song.url().isLocalFile()) continue;
|
||||||
songs << song;
|
songs << song;
|
||||||
}
|
}
|
||||||
if (songs.isEmpty()) return;
|
if (songs.isEmpty()) return;
|
||||||
|
|
||||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
organize_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||||
organise_dialog_->SetCopy(true);
|
organize_dialog_->SetCopy(true);
|
||||||
if (organise_dialog_->SetSongs(songs))
|
if (organize_dialog_->SetSongs(songs))
|
||||||
organise_dialog_->show();
|
organize_dialog_->show();
|
||||||
else {
|
else {
|
||||||
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||||
}
|
}
|
||||||
@@ -2427,7 +2517,7 @@ void MainWindow::ShowCoverManager() {
|
|||||||
|
|
||||||
SettingsDialog *MainWindow::CreateSettingsDialog() {
|
SettingsDialog *MainWindow::CreateSettingsDialog() {
|
||||||
|
|
||||||
SettingsDialog *settings_dialog = new SettingsDialog(app_, this);
|
SettingsDialog *settings_dialog = new SettingsDialog(app_, osd_, this);
|
||||||
#ifdef HAVE_GLOBALSHORTCUTS
|
#ifdef HAVE_GLOBALSHORTCUTS
|
||||||
settings_dialog->SetGlobalShortcutManager(global_shortcuts_);
|
settings_dialog->SetGlobalShortcutManager(global_shortcuts_);
|
||||||
#endif
|
#endif
|
||||||
@@ -2436,7 +2526,7 @@ SettingsDialog *MainWindow::CreateSettingsDialog() {
|
|||||||
connect(settings_dialog, SIGNAL(ReloadSettings()), SLOT(ReloadAllSettings()));
|
connect(settings_dialog, SIGNAL(ReloadSettings()), SLOT(ReloadAllSettings()));
|
||||||
|
|
||||||
// Allows custom notification preview
|
// Allows custom notification preview
|
||||||
connect(settings_dialog, SIGNAL(NotificationPreview(OSD::Behaviour, QString, QString)), SLOT(HandleNotificationPreview(OSD::Behaviour, QString, QString)));
|
connect(settings_dialog, SIGNAL(NotificationPreview(OSDBase::Behaviour, QString, QString)), SLOT(HandleNotificationPreview(OSDBase::Behaviour, QString, QString)));
|
||||||
return settings_dialog;
|
return settings_dialog;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2531,7 +2621,11 @@ void MainWindow::Raise() {
|
|||||||
activateWindow();
|
activateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, qintptr *result) {
|
||||||
|
#else
|
||||||
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) {
|
bool MainWindow::nativeEvent(const QByteArray &eventType, void *message, long *result) {
|
||||||
|
#endif
|
||||||
|
|
||||||
Q_UNUSED(eventType);
|
Q_UNUSED(eventType);
|
||||||
Q_UNUSED(result);
|
Q_UNUSED(result);
|
||||||
@@ -2573,7 +2667,7 @@ void MainWindow::AutoCompleteTags() {
|
|||||||
if (!source_index.isValid()) continue;
|
if (!source_index.isValid()) continue;
|
||||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(source_index.row()));
|
||||||
if (!item) continue;
|
if (!item) continue;
|
||||||
Song song = item->Metadata();
|
Song song = item->OriginalMetadata();
|
||||||
if (song.IsEditable()) {
|
if (song.IsEditable()) {
|
||||||
songs << song;
|
songs << song;
|
||||||
autocomplete_tag_items_ << item;
|
autocomplete_tag_items_ << item;
|
||||||
@@ -2602,7 +2696,7 @@ void MainWindow::AutoCompleteTagsAccepted() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::HandleNotificationPreview(OSD::Behaviour type, QString line1, QString line2) {
|
void MainWindow::HandleNotificationPreview(OSDBase::Behaviour type, QString line1, QString line2) {
|
||||||
|
|
||||||
if (!app_->playlist_manager()->current()->GetAllSongs().isEmpty()) {
|
if (!app_->playlist_manager()->current()->GetAllSongs().isEmpty()) {
|
||||||
// Show a preview notification for the first song in the current playlist
|
// Show a preview notification for the first song in the current playlist
|
||||||
|
|||||||
@@ -54,7 +54,7 @@
|
|||||||
#include "engine/enginetype.h"
|
#include "engine/enginetype.h"
|
||||||
#include "engine/engine_fwd.h"
|
#include "engine/engine_fwd.h"
|
||||||
#include "mac_startup.h"
|
#include "mac_startup.h"
|
||||||
#include "widgets/osd.h"
|
#include "osd/osdbase.h"
|
||||||
#include "collection/collectionmodel.h"
|
#include "collection/collectionmodel.h"
|
||||||
#include "playlist/playlistitem.h"
|
#include "playlist/playlistitem.h"
|
||||||
#include "settings/settingsdialog.h"
|
#include "settings/settingsdialog.h"
|
||||||
@@ -77,7 +77,7 @@ class ErrorDialog;
|
|||||||
class FileView;
|
class FileView;
|
||||||
class GlobalShortcuts;
|
class GlobalShortcuts;
|
||||||
class MimeData;
|
class MimeData;
|
||||||
class OrganiseDialog;
|
class OrganizeDialog;
|
||||||
class PlaylistListContainer;
|
class PlaylistListContainer;
|
||||||
class QueueView;
|
class QueueView;
|
||||||
class SystemTrayIcon;
|
class SystemTrayIcon;
|
||||||
@@ -100,7 +100,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, const CommandlineOptions& options, QWidget *parent = nullptr);
|
explicit MainWindow(Application *app, SystemTrayIcon *tray_icon, OSDBase *osd, const CommandlineOptions& options, QWidget *parent = nullptr);
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
static const char *kSettingsGroup;
|
static const char *kSettingsGroup;
|
||||||
@@ -112,7 +112,11 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent *event) override;
|
void keyPressEvent(QKeyEvent *event) override;
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||||
|
#else
|
||||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
// PlatformInterface
|
// PlatformInterface
|
||||||
void Activate() override;
|
void Activate() override;
|
||||||
@@ -164,8 +168,9 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
void PlaylistCopyToCollection();
|
void PlaylistCopyToCollection();
|
||||||
void PlaylistMoveToCollection();
|
void PlaylistMoveToCollection();
|
||||||
void PlaylistCopyToDevice();
|
void PlaylistCopyToDevice();
|
||||||
void PlaylistOrganiseSelected(const bool copy);
|
void PlaylistOrganizeSelected(const bool copy);
|
||||||
void PlaylistOpenInBrowser();
|
void PlaylistOpenInBrowser();
|
||||||
|
void PlaylistCopyUrl();
|
||||||
void ShowInCollection();
|
void ShowInCollection();
|
||||||
|
|
||||||
void ChangeCollectionQueryMode(QAction *action);
|
void ChangeCollectionQueryMode(QAction *action);
|
||||||
@@ -238,7 +243,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
void Exit();
|
void Exit();
|
||||||
void DoExit();
|
void DoExit();
|
||||||
|
|
||||||
void HandleNotificationPreview(const OSD::Behaviour type, QString line1, QString line2);
|
void HandleNotificationPreview(const OSDBase::Behaviour type, QString line1, QString line2);
|
||||||
|
|
||||||
void ShowConsole();
|
void ShowConsole();
|
||||||
|
|
||||||
@@ -283,7 +288,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
|
|
||||||
Application *app_;
|
Application *app_;
|
||||||
SystemTrayIcon *tray_icon_;
|
SystemTrayIcon *tray_icon_;
|
||||||
OSD *osd_;
|
OSDBase *osd_;
|
||||||
Lazy<About> about_dialog_;
|
Lazy<About> about_dialog_;
|
||||||
Lazy<EditTagDialog> edit_tag_dialog_;
|
Lazy<EditTagDialog> edit_tag_dialog_;
|
||||||
AlbumCoverChoiceController *album_cover_choice_controller_;
|
AlbumCoverChoiceController *album_cover_choice_controller_;
|
||||||
@@ -303,7 +308,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
Lazy<SettingsDialog> settings_dialog_;
|
Lazy<SettingsDialog> settings_dialog_;
|
||||||
Lazy<AlbumCoverManager> cover_manager_;
|
Lazy<AlbumCoverManager> cover_manager_;
|
||||||
std::unique_ptr<Equalizer> equalizer_;
|
std::unique_ptr<Equalizer> equalizer_;
|
||||||
Lazy<OrganiseDialog> organise_dialog_;
|
Lazy<OrganizeDialog> organize_dialog_;
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
Lazy<TranscodeDialog> transcode_dialog_;
|
Lazy<TranscodeDialog> transcode_dialog_;
|
||||||
#endif
|
#endif
|
||||||
@@ -326,7 +331,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
QAction *playlist_play_pause_;
|
QAction *playlist_play_pause_;
|
||||||
QAction *playlist_stop_after_;
|
QAction *playlist_stop_after_;
|
||||||
QAction *playlist_undoredo_;
|
QAction *playlist_undoredo_;
|
||||||
QAction *playlist_organise_;
|
QAction *playlist_organize_;
|
||||||
QAction *playlist_show_in_collection_;
|
QAction *playlist_show_in_collection_;
|
||||||
QAction *playlist_copy_to_collection_;
|
QAction *playlist_copy_to_collection_;
|
||||||
QAction *playlist_move_to_collection_;
|
QAction *playlist_move_to_collection_;
|
||||||
@@ -334,14 +339,14 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
QAction *playlist_copy_to_device_;
|
QAction *playlist_copy_to_device_;
|
||||||
#endif
|
#endif
|
||||||
QAction *playlist_open_in_browser_;
|
QAction *playlist_open_in_browser_;
|
||||||
|
QAction *playlist_copy_url_;
|
||||||
QAction *playlist_queue_;
|
QAction *playlist_queue_;
|
||||||
QAction* playlist_queue_play_next_;
|
QAction* playlist_queue_play_next_;
|
||||||
QAction *playlist_skip_;
|
QAction *playlist_skip_;
|
||||||
QAction *playlist_add_to_another_;
|
QAction *playlist_add_to_another_;
|
||||||
QList<QAction*> playlistitem_actions_;
|
QList<QAction*> playlistitem_actions_;
|
||||||
QAction *playlistitem_actions_separator_;
|
QAction *playlistitem_actions_separator_;
|
||||||
QAction *search_for_artist_;
|
QAction *playlist_rescan_songs_;
|
||||||
QAction *search_for_album_;
|
|
||||||
|
|
||||||
QModelIndex playlist_menu_index_;
|
QModelIndex playlist_menu_index_;
|
||||||
|
|
||||||
|
|||||||
@@ -831,11 +831,6 @@
|
|||||||
<string notr="true">Ctrl+Shift+T</string>
|
<string notr="true">Ctrl+Shift+T</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_rescan_songs">
|
|
||||||
<property name="text">
|
|
||||||
<string>Rescan songs(s)</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_add_stream">
|
<action name="action_add_stream">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Add stream...</string>
|
<string>Add stream...</string>
|
||||||
|
|||||||
@@ -193,7 +193,7 @@ void MergedProxyModel::SourceModelReset() {
|
|||||||
|
|
||||||
void MergedProxyModel::SubModelReset() {
|
void MergedProxyModel::SubModelReset() {
|
||||||
|
|
||||||
QAbstractItemModel *submodel = static_cast<QAbstractItemModel*>(sender());
|
QAbstractItemModel *submodel = qobject_cast<QAbstractItemModel*>(sender());
|
||||||
|
|
||||||
// TODO: When we require Qt 4.6, use beginResetModel() and endResetModel() in CollectionModel and catch those here
|
// TODO: When we require Qt 4.6, use beginResetModel() and endResetModel() in CollectionModel and catch those here
|
||||||
// that will let us do away with this std::numeric_limits<int>::max() hack.
|
// that will let us do away with this std::numeric_limits<int>::max() hack.
|
||||||
@@ -241,7 +241,7 @@ QModelIndex MergedProxyModel::GetActualSourceParent(const QModelIndex &source_pa
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MergedProxyModel::RowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end) {
|
void MergedProxyModel::RowsAboutToBeInserted(const QModelIndex &source_parent, int start, int end) {
|
||||||
beginInsertRows(mapFromSource(GetActualSourceParent(source_parent, static_cast<QAbstractItemModel*>(sender()))), start, end);
|
beginInsertRows(mapFromSource(GetActualSourceParent(source_parent, qobject_cast<QAbstractItemModel*>(sender()))), start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergedProxyModel::RowsInserted(const QModelIndex&, int, int) {
|
void MergedProxyModel::RowsInserted(const QModelIndex&, int, int) {
|
||||||
@@ -249,7 +249,7 @@ void MergedProxyModel::RowsInserted(const QModelIndex&, int, int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MergedProxyModel::RowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end) {
|
void MergedProxyModel::RowsAboutToBeRemoved(const QModelIndex &source_parent, int start, int end) {
|
||||||
beginRemoveRows(mapFromSource(GetActualSourceParent(source_parent, static_cast<QAbstractItemModel*>(sender()))), start, end);
|
beginRemoveRows(mapFromSource(GetActualSourceParent(source_parent, qobject_cast<QAbstractItemModel*>(sender()))), start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MergedProxyModel::RowsRemoved(const QModelIndex&, int, int) {
|
void MergedProxyModel::RowsRemoved(const QModelIndex&, int, int) {
|
||||||
|
|||||||
@@ -32,12 +32,14 @@
|
|||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QVector>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QNetworkCookie>
|
#include <QNetworkCookie>
|
||||||
#include <QNetworkReply>
|
#include <QNetworkReply>
|
||||||
|
#include <QItemSelection>
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
# include <QDBusMetaType>
|
# include <QDBusMetaType>
|
||||||
#endif
|
#endif
|
||||||
@@ -55,6 +57,7 @@
|
|||||||
#include "playlist/playlistsequence.h"
|
#include "playlist/playlistsequence.h"
|
||||||
#include "covermanager/albumcoverloaderresult.h"
|
#include "covermanager/albumcoverloaderresult.h"
|
||||||
#include "covermanager/albumcoverfetcher.h"
|
#include "covermanager/albumcoverfetcher.h"
|
||||||
|
#include "covermanager/coversearchstatistics.h"
|
||||||
#include "equalizer/equalizer.h"
|
#include "equalizer/equalizer.h"
|
||||||
|
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
@@ -69,6 +72,7 @@ void RegisterMetaTypes() {
|
|||||||
qRegisterMetaType<const char*>("const char*");
|
qRegisterMetaType<const char*>("const char*");
|
||||||
qRegisterMetaType<QList<int>>("QList<int>");
|
qRegisterMetaType<QList<int>>("QList<int>");
|
||||||
qRegisterMetaType<QList<QUrl>>("QList<QUrl>");
|
qRegisterMetaType<QList<QUrl>>("QList<QUrl>");
|
||||||
|
qRegisterMetaType<QVector<int>>("QVector<int>");
|
||||||
qRegisterMetaType<QFileInfo>("QFileInfo");
|
qRegisterMetaType<QFileInfo>("QFileInfo");
|
||||||
qRegisterMetaType<QAbstractSocket::SocketState>();
|
qRegisterMetaType<QAbstractSocket::SocketState>();
|
||||||
qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
|
qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
|
||||||
@@ -76,7 +80,9 @@ void RegisterMetaTypes() {
|
|||||||
qRegisterMetaType<QList<QNetworkCookie> >("QList<QNetworkCookie>");
|
qRegisterMetaType<QList<QNetworkCookie> >("QList<QNetworkCookie>");
|
||||||
qRegisterMetaType<QNetworkReply*>("QNetworkReply*");
|
qRegisterMetaType<QNetworkReply*>("QNetworkReply*");
|
||||||
qRegisterMetaType<QNetworkReply**>("QNetworkReply**");
|
qRegisterMetaType<QNetworkReply**>("QNetworkReply**");
|
||||||
qRegisterMetaTypeStreamOperators<QMap<int, int> >("ColumnAlignmentMap");
|
qRegisterMetaType<QItemSelection>("QItemSelection");
|
||||||
|
qRegisterMetaTypeStreamOperators<QMap<int, Qt::Alignment>>("ColumnAlignmentMap");
|
||||||
|
qRegisterMetaTypeStreamOperators<QMap<int, int>>("ColumnAlignmentIntMap");
|
||||||
qRegisterMetaType<Directory>("Directory");
|
qRegisterMetaType<Directory>("Directory");
|
||||||
qRegisterMetaType<DirectoryList>("DirectoryList");
|
qRegisterMetaType<DirectoryList>("DirectoryList");
|
||||||
qRegisterMetaType<Subdirectory>("Subdirectory");
|
qRegisterMetaType<Subdirectory>("Subdirectory");
|
||||||
@@ -102,6 +108,7 @@ void RegisterMetaTypes() {
|
|||||||
qRegisterMetaType<AlbumCoverLoaderResult>("AlbumCoverLoaderResult");
|
qRegisterMetaType<AlbumCoverLoaderResult>("AlbumCoverLoaderResult");
|
||||||
qRegisterMetaType<AlbumCoverLoaderResult::Type>("AlbumCoverLoaderResult::Type");
|
qRegisterMetaType<AlbumCoverLoaderResult::Type>("AlbumCoverLoaderResult::Type");
|
||||||
qRegisterMetaType<CoverSearchResult>("CoverSearchResult");
|
qRegisterMetaType<CoverSearchResult>("CoverSearchResult");
|
||||||
|
qRegisterMetaType<CoverSearchStatistics>("CoverSearchStatistics");
|
||||||
qRegisterMetaType<QList<CoverSearchResult> >("QList<CoverSearchResult>");
|
qRegisterMetaType<QList<CoverSearchResult> >("QList<CoverSearchResult>");
|
||||||
qRegisterMetaType<CoverSearchResults>("CoverSearchResults");
|
qRegisterMetaType<CoverSearchResults>("CoverSearchResults");
|
||||||
qRegisterMetaType<Equalizer::Params>("Equalizer::Params");
|
qRegisterMetaType<Equalizer::Params>("Equalizer::Params");
|
||||||
|
|||||||
@@ -134,10 +134,9 @@ Mpris2::Mpris2(Application *app, QObject *parent)
|
|||||||
|
|
||||||
app_name_[0] = app_name_[0].toUpper();
|
app_name_[0] = app_name_[0].toUpper();
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
|
|
||||||
if (!QGuiApplication::desktopFileName().isEmpty())
|
if (!QGuiApplication::desktopFileName().isEmpty())
|
||||||
desktop_files_ << QGuiApplication::desktopFileName();
|
desktop_files_ << QGuiApplication::desktopFileName();
|
||||||
#endif
|
|
||||||
QStringList domain_split = QCoreApplication::organizationDomain().split(".");
|
QStringList domain_split = QCoreApplication::organizationDomain().split(".");
|
||||||
std::reverse(domain_split.begin(), domain_split.end());
|
std::reverse(domain_split.begin(), domain_split.end());
|
||||||
desktop_files_ << QStringList() << domain_split.join(".") + "." + QCoreApplication::applicationName().toLower();
|
desktop_files_ << QStringList() << domain_split.join(".") + "." + QCoreApplication::applicationName().toLower();
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ inline void AddMetadata(const QString &key, const QDateTime &metadata, QVariantM
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline QString AsMPRISDateTimeType(const int time) {
|
inline QString AsMPRISDateTimeType(const int time) {
|
||||||
return time != -1 ? QDateTime::fromTime_t(time).toString(Qt::ISODate) : "";
|
return time != -1 ? QDateTime::fromSecsSinceEpoch(time).toString(Qt::ISODate) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mpris
|
} // namespace mpris
|
||||||
|
|||||||
@@ -127,7 +127,11 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR
|
|||||||
}
|
}
|
||||||
|
|
||||||
QNetworkRequest new_request(request);
|
QNetworkRequest new_request(request);
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||||
|
new_request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||||
|
#else
|
||||||
new_request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
new_request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
#endif
|
||||||
new_request.setRawHeader("User-Agent", user_agent);
|
new_request.setRawHeader("User-Agent", user_agent);
|
||||||
|
|
||||||
if (op == QNetworkAccessManager::PostOperation && !new_request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
|
if (op == QNetworkAccessManager::PostOperation && !new_request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
|
||||||
|
|||||||
@@ -51,9 +51,6 @@
|
|||||||
# include "engine/gstengine.h"
|
# include "engine/gstengine.h"
|
||||||
# include "engine/gststartup.h"
|
# include "engine/gststartup.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_XINE
|
|
||||||
# include "engine/xineengine.h"
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_VLC
|
#ifdef HAVE_VLC
|
||||||
# include "engine/vlcengine.h"
|
# include "engine/vlcengine.h"
|
||||||
#endif
|
#endif
|
||||||
@@ -125,12 +122,6 @@ Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_XINE
|
|
||||||
case Engine::Xine:
|
|
||||||
use_enginetype=Engine::Xine;
|
|
||||||
engine_.reset(new XineEngine(app_->task_manager()));
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_VLC
|
#ifdef HAVE_VLC
|
||||||
case Engine::VLC:
|
case Engine::VLC:
|
||||||
use_enginetype=Engine::VLC;
|
use_enginetype=Engine::VLC;
|
||||||
@@ -267,8 +258,7 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
|||||||
switch (result.type_) {
|
switch (result.type_) {
|
||||||
case UrlHandler::LoadResult::Error:
|
case UrlHandler::LoadResult::Error:
|
||||||
if (is_current) {
|
if (is_current) {
|
||||||
EngineStateChanged(Engine::Error);
|
InvalidSongRequested(result.original_url_);
|
||||||
FatalError();
|
|
||||||
}
|
}
|
||||||
emit Error(result.error_);
|
emit Error(result.error_);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@@ -148,9 +148,9 @@ const QString Song::kFtsUpdateSpec = Utilities::Updateify(Song::kFtsColumns).joi
|
|||||||
const QString Song::kManuallyUnsetCover = "(unset)";
|
const QString Song::kManuallyUnsetCover = "(unset)";
|
||||||
const QString Song::kEmbeddedCover = "(embedded)";
|
const QString Song::kEmbeddedCover = "(embedded)";
|
||||||
|
|
||||||
const QRegExp Song::kAlbumRemoveDisc(" ?-? ((\\(|\\[)?)(Disc|CD) ?([0-9]{1,2})((\\)|\\])?)$");
|
const QRegularExpression Song::kAlbumRemoveDisc(" ?-? ((\\(|\\[)?)(Disc|CD) ?([0-9]{1,2})((\\)|\\])?)$");
|
||||||
const QRegExp Song::kAlbumRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|([0-9]{1,4}) *Remaster) ?((\\)|\\])?)$");
|
const QRegularExpression Song::kAlbumRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|([0-9]{1,4}) *Remaster) ?((\\)|\\])?)$");
|
||||||
const QRegExp Song::kTitleRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|Live|Remastered Version|([0-9]{1,4}) *Remaster) ?((\\)|\\])?)$");
|
const QRegularExpression Song::kTitleRemoveMisc(" ?-? ((\\(|\\[)?)(Remastered|Live|Remastered Version|([0-9]{1,4}) *Remaster) ?((\\)|\\])?)$");
|
||||||
const QString Song::kVariousArtists("various artists");
|
const QString Song::kVariousArtists("various artists");
|
||||||
|
|
||||||
const QStringList Song::kArticles = QStringList() << "the " << "a " << "an ";
|
const QStringList Song::kArticles = QStringList() << "the " << "a " << "an ";
|
||||||
@@ -199,8 +199,8 @@ struct Song::Private : public QSharedData {
|
|||||||
QUrl url_;
|
QUrl url_;
|
||||||
FileType filetype_;
|
FileType filetype_;
|
||||||
int filesize_;
|
int filesize_;
|
||||||
int mtime_;
|
qint64 mtime_;
|
||||||
int ctime_;
|
qint64 ctime_;
|
||||||
bool unavailable_;
|
bool unavailable_;
|
||||||
|
|
||||||
int playcount_;
|
int playcount_;
|
||||||
@@ -322,8 +322,8 @@ const QUrl &Song::url() const { return d->url_; }
|
|||||||
const QString &Song::basefilename() const { return d->basefilename_; }
|
const QString &Song::basefilename() const { return d->basefilename_; }
|
||||||
Song::FileType Song::filetype() const { return d->filetype_; }
|
Song::FileType Song::filetype() const { return d->filetype_; }
|
||||||
int Song::filesize() const { return d->filesize_; }
|
int Song::filesize() const { return d->filesize_; }
|
||||||
uint Song::mtime() const { return d->mtime_; }
|
qint64 Song::mtime() const { return d->mtime_; }
|
||||||
uint Song::ctime() const { return d->ctime_; }
|
qint64 Song::ctime() const { return d->ctime_; }
|
||||||
|
|
||||||
int Song::playcount() const { return d->playcount_; }
|
int Song::playcount() const { return d->playcount_; }
|
||||||
int Song::skipcount() const { return d->skipcount_; }
|
int Song::skipcount() const { return d->skipcount_; }
|
||||||
@@ -428,8 +428,8 @@ void Song::set_url(const QUrl &v) { d->url_ = v; }
|
|||||||
void Song::set_basefilename(const QString &v) { d->basefilename_ = v; }
|
void Song::set_basefilename(const QString &v) { d->basefilename_ = v; }
|
||||||
void Song::set_filetype(FileType v) { d->filetype_ = v; }
|
void Song::set_filetype(FileType v) { d->filetype_ = v; }
|
||||||
void Song::set_filesize(int v) { d->filesize_ = v; }
|
void Song::set_filesize(int v) { d->filesize_ = v; }
|
||||||
void Song::set_mtime(int v) { d->mtime_ = v; }
|
void Song::set_mtime(qint64 v) { d->mtime_ = v; }
|
||||||
void Song::set_ctime(int v) { d->ctime_ = v; }
|
void Song::set_ctime(qint64 v) { d->ctime_ = v; }
|
||||||
void Song::set_unavailable(bool v) { d->unavailable_ = v; }
|
void Song::set_unavailable(bool v) { d->unavailable_ = v; }
|
||||||
|
|
||||||
void Song::set_playcount(int v) { d->playcount_ = v; }
|
void Song::set_playcount(int v) { d->playcount_ = v; }
|
||||||
@@ -925,10 +925,10 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
|
|||||||
d->filesize_ = toint(x);
|
d->filesize_ = toint(x);
|
||||||
}
|
}
|
||||||
else if (Song::kColumns.value(i) == "mtime") {
|
else if (Song::kColumns.value(i) == "mtime") {
|
||||||
d->mtime_ = toint(x);
|
d->mtime_ = tolonglong(x);
|
||||||
}
|
}
|
||||||
else if (Song::kColumns.value(i) == "ctime") {
|
else if (Song::kColumns.value(i) == "ctime") {
|
||||||
d->ctime_ = toint(x);
|
d->ctime_ = tolonglong(x);
|
||||||
}
|
}
|
||||||
else if (Song::kColumns.value(i) == "unavailable") {
|
else if (Song::kColumns.value(i) == "unavailable") {
|
||||||
d->unavailable_ = q.value(x).toBool();
|
d->unavailable_ = q.value(x).toBool();
|
||||||
@@ -958,7 +958,7 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
|
|||||||
|
|
||||||
else if (Song::kColumns.value(i) == "art_automatic") {
|
else if (Song::kColumns.value(i) == "art_automatic") {
|
||||||
QString art_automatic = tostr(x);
|
QString art_automatic = tostr(x);
|
||||||
if (art_automatic.contains(QRegExp("..+:.*"))) {
|
if (art_automatic.contains(QRegularExpression("..+:.*"))) {
|
||||||
set_art_automatic(QUrl::fromEncoded(art_automatic.toUtf8()));
|
set_art_automatic(QUrl::fromEncoded(art_automatic.toUtf8()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -967,7 +967,7 @@ void Song::InitFromQuery(const SqlRow &q, bool reliable_metadata, int col) {
|
|||||||
}
|
}
|
||||||
else if (Song::kColumns.value(i) == "art_manual") {
|
else if (Song::kColumns.value(i) == "art_manual") {
|
||||||
QString art_manual = tostr(x);
|
QString art_manual = tostr(x);
|
||||||
if (art_manual.contains(QRegExp("..+:.*"))) {
|
if (art_manual.contains(QRegularExpression("..+:.*"))) {
|
||||||
set_art_manual(QUrl::fromEncoded(art_manual.toUtf8()));
|
set_art_manual(QUrl::fromEncoded(art_manual.toUtf8()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@@ -120,10 +120,9 @@ class Song {
|
|||||||
static const QString kManuallyUnsetCover;
|
static const QString kManuallyUnsetCover;
|
||||||
static const QString kEmbeddedCover;
|
static const QString kEmbeddedCover;
|
||||||
|
|
||||||
static const QRegExp kAlbumRemoveDisc;
|
static const QRegularExpression kAlbumRemoveDisc;
|
||||||
static const QRegExp kAlbumRemoveMisc;
|
static const QRegularExpression kAlbumRemoveMisc;
|
||||||
static const QRegExp kTitleRemoveMisc;
|
static const QRegularExpression kTitleRemoveMisc;
|
||||||
static const QRegExp kFilenameRemoveNonFatChars;
|
|
||||||
|
|
||||||
static const QString kVariousArtists;
|
static const QString kVariousArtists;
|
||||||
|
|
||||||
@@ -228,8 +227,8 @@ class Song {
|
|||||||
const QString &basefilename() const;
|
const QString &basefilename() const;
|
||||||
FileType filetype() const;
|
FileType filetype() const;
|
||||||
int filesize() const;
|
int filesize() const;
|
||||||
uint mtime() const;
|
qint64 mtime() const;
|
||||||
uint ctime() const;
|
qint64 ctime() const;
|
||||||
|
|
||||||
int playcount() const;
|
int playcount() const;
|
||||||
int skipcount() const;
|
int skipcount() const;
|
||||||
@@ -329,8 +328,8 @@ class Song {
|
|||||||
void set_basefilename(const QString &v);
|
void set_basefilename(const QString &v);
|
||||||
void set_filetype(FileType v);
|
void set_filetype(FileType v);
|
||||||
void set_filesize(int v);
|
void set_filesize(int v);
|
||||||
void set_mtime(int v);
|
void set_mtime(qint64 v);
|
||||||
void set_ctime(int v);
|
void set_ctime(qint64 v);
|
||||||
void set_unavailable(bool v);
|
void set_unavailable(bool v);
|
||||||
|
|
||||||
void set_playcount(int v);
|
void set_playcount(int v);
|
||||||
|
|||||||
@@ -90,9 +90,8 @@ void StyleSheetLoader::UpdateStyleSheet(QWidget *widget, StyleSheetData styledat
|
|||||||
.arg(alt.alpha()));
|
.arg(alt.alpha()));
|
||||||
|
|
||||||
ReplaceColor(&stylesheet, "Window", p, QPalette::Window);
|
ReplaceColor(&stylesheet, "Window", p, QPalette::Window);
|
||||||
ReplaceColor(&stylesheet, "Background", p, QPalette::Background);
|
ReplaceColor(&stylesheet, "Background", p, QPalette::Window);
|
||||||
ReplaceColor(&stylesheet, "WindowText", p, QPalette::WindowText);
|
ReplaceColor(&stylesheet, "WindowText", p, QPalette::WindowText);
|
||||||
ReplaceColor(&stylesheet, "Foreground", p, QPalette::Foreground);
|
|
||||||
ReplaceColor(&stylesheet, "Base", p, QPalette::Base);
|
ReplaceColor(&stylesheet, "Base", p, QPalette::Base);
|
||||||
ReplaceColor(&stylesheet, "AlternateBase", p, QPalette::AlternateBase);
|
ReplaceColor(&stylesheet, "AlternateBase", p, QPalette::AlternateBase);
|
||||||
ReplaceColor(&stylesheet, "ToolTipBase", p, QPalette::ToolTipBase);
|
ReplaceColor(&stylesheet, "ToolTipBase", p, QPalette::ToolTipBase);
|
||||||
|
|||||||
@@ -50,7 +50,8 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
|
#include <QRegularExpressionMatch>
|
||||||
#include <QTcpServer>
|
#include <QTcpServer>
|
||||||
#include <QTemporaryFile>
|
#include <QTemporaryFile>
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
@@ -157,7 +158,7 @@ QString WordyTimeNanosec(qint64 nanoseconds) {
|
|||||||
QString Ago(int seconds_since_epoch, const QLocale &locale) {
|
QString Ago(int seconds_since_epoch, const QLocale &locale) {
|
||||||
|
|
||||||
const QDateTime now = QDateTime::currentDateTime();
|
const QDateTime now = QDateTime::currentDateTime();
|
||||||
const QDateTime then = QDateTime::fromTime_t(seconds_since_epoch);
|
const QDateTime then = QDateTime::fromSecsSinceEpoch(seconds_since_epoch);
|
||||||
const int days_ago = then.date().daysTo(now.date());
|
const int days_ago = then.date().daysTo(now.date());
|
||||||
const QString time = then.time().toString(locale.timeFormat(QLocale::ShortFormat));
|
const QString time = then.time().toString(locale.timeFormat(QLocale::ShortFormat));
|
||||||
|
|
||||||
@@ -336,8 +337,10 @@ QString ColorToRgba(const QColor &c) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||||
void OpenInFileManager(const QString &path);
|
void OpenInFileManager(const QString path, const QUrl &url);
|
||||||
void OpenInFileManager(const QString &path) {
|
void OpenInFileManager(const QString path, const QUrl &url) {
|
||||||
|
|
||||||
|
if (!url.isLocalFile()) return;
|
||||||
|
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
|
proc.start("xdg-mime", QStringList() << "query" << "default" << "inode/directory");
|
||||||
@@ -375,29 +378,22 @@ void OpenInFileManager(const QString &path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (command.isEmpty() || command == "exo-open") {
|
if (command.isEmpty() || command == "exo-open") {
|
||||||
QFileInfo info(path);
|
QDesktopServices::openUrl(QUrl::fromLocalFile(path));
|
||||||
if (!info.exists()) return;
|
|
||||||
QString directory = info.dir().path();
|
|
||||||
if (directory.isEmpty()) return;
|
|
||||||
QDesktopServices::openUrl(QUrl::fromLocalFile(directory));
|
|
||||||
}
|
}
|
||||||
else if (command.startsWith("nautilus")) {
|
else if (command.startsWith("nautilus")) {
|
||||||
proc.startDetached(command, QStringList() << command_params << "--select" << path);
|
proc.startDetached(command, QStringList() << command_params << "--select" << url.toLocalFile());
|
||||||
}
|
}
|
||||||
else if (command.startsWith("dolphin") || command.startsWith("konqueror") || command.startsWith("kfmclient")) {
|
else if (command.startsWith("dolphin") || command.startsWith("konqueror") || command.startsWith("kfmclient")) {
|
||||||
proc.startDetached(command, QStringList() << command_params << "--select" << "--new-window" << path);
|
proc.startDetached(command, QStringList() << command_params << "--select" << "--new-window" << url.toLocalFile());
|
||||||
}
|
}
|
||||||
else if (command.startsWith("caja")) {
|
else if (command.startsWith("caja")) {
|
||||||
QFileInfo info(path);
|
proc.startDetached(command, QStringList() << command_params << "--no-desktop" << path);
|
||||||
if (!info.exists()) return;
|
|
||||||
QString directory = info.dir().path();
|
|
||||||
proc.startDetached(command, QStringList() << command_params << "--no-desktop" << directory);
|
|
||||||
}
|
}
|
||||||
else if (command.startsWith("pcmanfm")) {
|
else if (command.startsWith("pcmanfm")) {
|
||||||
proc.startDetached(command, QStringList() << command_params << QFileInfo(path).dir().path());
|
proc.startDetached(command, QStringList() << command_params << path);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
proc.startDetached(command, QStringList() << command_params << path);
|
proc.startDetached(command, QStringList() << command_params << url.toLocalFile());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -405,28 +401,42 @@ void OpenInFileManager(const QString &path) {
|
|||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
// Better than openUrl(dirname(path)) - also highlights file at path
|
// Better than openUrl(dirname(path)) - also highlights file at path
|
||||||
void RevealFileInFinder(QString const &path) {
|
void RevealFileInFinder(const QString &path) {
|
||||||
QProcess::execute("/usr/bin/open", QStringList() << "-R" << path);
|
QProcess::execute("/usr/bin/open", QStringList() << "-R" << path);
|
||||||
}
|
}
|
||||||
#endif // Q_OS_MACOS
|
#endif // Q_OS_MACOS
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
void ShowFileInExplorer(QString const &path);
|
void ShowFileInExplorer(const QString &path);
|
||||||
void ShowFileInExplorer(QString const &path) {
|
void ShowFileInExplorer(const QString &path) {
|
||||||
QProcess::execute("explorer.exe", QStringList() << "/select," << QDir::toNativeSeparators(path));
|
QProcess::execute("explorer.exe", QStringList() << "/select," << QDir::toNativeSeparators(path));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void OpenInFileBrowser(const QList<QUrl> &urls) {
|
void OpenInFileBrowser(const QList<QUrl> &urls) {
|
||||||
|
|
||||||
if (urls.count() > 50) {
|
QMap<QString, QUrl> dirs;
|
||||||
|
|
||||||
|
for (const QUrl &url : urls) {
|
||||||
|
if (!url.isLocalFile()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString path = url.toLocalFile();
|
||||||
|
if (!QFile::exists(path)) continue;
|
||||||
|
|
||||||
|
const QString directory = QFileInfo(path).dir().path();
|
||||||
|
if (dirs.contains(directory)) continue;
|
||||||
|
dirs.insert(directory, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dirs.count() > 50) {
|
||||||
QMessageBox messagebox(QMessageBox::Critical, tr("Show in file browser"), tr("Too many songs selected."));
|
QMessageBox messagebox(QMessageBox::Critical, tr("Show in file browser"), tr("Too many songs selected."));
|
||||||
messagebox.exec();
|
messagebox.exec();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (urls.count() > 5) {
|
if (dirs.count() > 5) {
|
||||||
QMessageBox messagebox(QMessageBox::Information, tr("Show in file browser"), tr("%1 songs selected, are you sure you want to open them all?").arg(urls.count()), QMessageBox::Open|QMessageBox::Cancel);
|
QMessageBox messagebox(QMessageBox::Information, tr("Show in file browser"), tr("%1 songs in %2 different directories selected, are you sure you want to open them all?").arg(urls.count()).arg(dirs.count()), QMessageBox::Open|QMessageBox::Cancel);
|
||||||
messagebox.setTextFormat(Qt::RichText);
|
messagebox.setTextFormat(Qt::RichText);
|
||||||
int result = messagebox.exec();
|
int result = messagebox.exec();
|
||||||
switch (result) {
|
switch (result) {
|
||||||
@@ -438,27 +448,15 @@ void OpenInFileBrowser(const QList<QUrl> &urls) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> dirs;
|
QMap<QString, QUrl>::iterator i;
|
||||||
|
for (i = dirs.begin(); i != dirs.end(); ++i) {
|
||||||
for (const QUrl &url : urls) {
|
|
||||||
if (!url.isLocalFile()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QString path = url.toLocalFile();
|
|
||||||
|
|
||||||
if (!QFile::exists(path)) continue;
|
|
||||||
|
|
||||||
const QString directory = QFileInfo(path).dir().path();
|
|
||||||
if (dirs.contains(directory)) continue;
|
|
||||||
dirs.insert(directory);
|
|
||||||
|
|
||||||
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
#if defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
|
||||||
OpenInFileManager(path);
|
OpenInFileManager(i.key(), i.value());
|
||||||
#elif defined(Q_OS_MACOS)
|
#elif defined(Q_OS_MACOS)
|
||||||
// Revealing multiple files in the finder only opens one window, so it also makes sense to reveal at most one per directory
|
// Revealing multiple files in the finder only opens one window, so it also makes sense to reveal at most one per directory
|
||||||
RevealFileInFinder(path);
|
RevealFileInFinder(i.value().toLocalFile());
|
||||||
#elif defined(Q_OS_WIN32)
|
#elif defined(Q_OS_WIN32)
|
||||||
ShowFileInExplorer(path);
|
ShowFileInExplorer(i.value().toLocalFile());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -533,16 +531,6 @@ QString PrettySize(const QSize &size) {
|
|||||||
return QString::number(size.width()) + "x" + QString::number(size.height());
|
return QString::number(size.width()) + "x" + QString::number(size.height());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ForwardMouseEvent(const QMouseEvent *e, QWidget *target) {
|
|
||||||
QMouseEvent c(e->type(), target->mapFromGlobal(e->globalPos()), e->globalPos(), e->button(), e->buttons(), e->modifiers());
|
|
||||||
|
|
||||||
QApplication::sendEvent(target, &c);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsMouseEventInWidget(const QMouseEvent *e, const QWidget *widget) {
|
|
||||||
return widget->rect().contains(widget->mapFromGlobal(e->globalPos()));
|
|
||||||
}
|
|
||||||
|
|
||||||
quint16 PickUnusedPort() {
|
quint16 PickUnusedPort() {
|
||||||
|
|
||||||
forever {
|
forever {
|
||||||
@@ -613,8 +601,9 @@ bool ParseUntilElementCI(QXmlStreamReader *reader, const QString &name) {
|
|||||||
|
|
||||||
QDateTime ParseRFC822DateTime(const QString &text) {
|
QDateTime ParseRFC822DateTime(const QString &text) {
|
||||||
|
|
||||||
QRegExp regexp("(\\d{1,2}) (\\w{3,12}) (\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})");
|
QRegularExpression regexp("(\\d{1,2}) (\\w{3,12}) (\\d+) (\\d{1,2}):(\\d{1,2}):(\\d{1,2})");
|
||||||
if (regexp.indexIn(text) == -1) {
|
QRegularExpressionMatch re_match = regexp.match(text);
|
||||||
|
if (!re_match.hasMatch()) {
|
||||||
return QDateTime();
|
return QDateTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,9 +635,9 @@ QDateTime ParseRFC822DateTime(const QString &text) {
|
|||||||
monthmap["November"] = 11;
|
monthmap["November"] = 11;
|
||||||
monthmap["December"] = 12;
|
monthmap["December"] = 12;
|
||||||
|
|
||||||
const QDate date(regexp.cap(static_cast<int>(MatchNames::YEARS)).toInt(), monthmap[regexp.cap(static_cast<int>(MatchNames::MONTHS))], regexp.cap(static_cast<int>(MatchNames::DAYS)).toInt());
|
const QDate date(re_match.captured(static_cast<int>(MatchNames::YEARS)).toInt(), monthmap[re_match.captured(static_cast<int>(MatchNames::MONTHS))], re_match.captured(static_cast<int>(MatchNames::DAYS)).toInt());
|
||||||
|
|
||||||
const QTime time(regexp.cap(static_cast<int>(MatchNames::HOURS)).toInt(), regexp.cap(static_cast<int>(MatchNames::MINUTES)).toInt(), regexp.cap(static_cast<int>(MatchNames::SECONDS)).toInt());
|
const QTime time(re_match.captured(static_cast<int>(MatchNames::HOURS)).toInt(), re_match.captured(static_cast<int>(MatchNames::MINUTES)).toInt(), re_match.captured(static_cast<int>(MatchNames::SECONDS)).toInt());
|
||||||
|
|
||||||
return QDateTime(date, time);
|
return QDateTime(date, time);
|
||||||
|
|
||||||
@@ -932,19 +921,20 @@ QString MacAddress() {
|
|||||||
|
|
||||||
QString ReplaceMessage(const QString &message, const Song &song, const QString &newline) {
|
QString ReplaceMessage(const QString &message, const Song &song, const QString &newline) {
|
||||||
|
|
||||||
QRegExp variable_replacer("[%][a-z]+[%]");
|
QRegularExpression variable_replacer("[%][a-z]+[%]");
|
||||||
QString copy(message);
|
QString copy(message);
|
||||||
|
|
||||||
// Replace the first line
|
// Replace the first line
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
variable_replacer.indexIn(message);
|
QRegularExpressionMatch match;
|
||||||
while ((pos = variable_replacer.indexIn(message, pos)) != -1) {
|
for (match = variable_replacer.match(message, pos) ; match.hasMatch() ; match = variable_replacer.match(message, pos)) {
|
||||||
QStringList captured = variable_replacer.capturedTexts();
|
pos = match.capturedStart();
|
||||||
|
QStringList captured = match.capturedTexts();
|
||||||
copy.replace(captured[0], ReplaceVariable(captured[0], song, newline));
|
copy.replace(captured[0], ReplaceVariable(captured[0], song, newline));
|
||||||
pos += variable_replacer.matchedLength();
|
pos += match.capturedLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
int index_of = copy.indexOf(QRegExp(" - (>|$)"));
|
int index_of = copy.indexOf(QRegularExpression(" - (>|$)"));
|
||||||
if (index_of >= 0) copy = copy.remove(index_of, 3);
|
if (index_of >= 0) copy = copy.remove(index_of, 3);
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
|
|||||||
@@ -85,12 +85,6 @@ QByteArray Sha1CoverHash(const QString &artist, const QString &album);
|
|||||||
// Picks an unused ephemeral port number. Doesn't hold the port open so there's the obvious race condition
|
// Picks an unused ephemeral port number. Doesn't hold the port open so there's the obvious race condition
|
||||||
quint16 PickUnusedPort();
|
quint16 PickUnusedPort();
|
||||||
|
|
||||||
// Forwards a mouse event to a different widget, remapping the event's widget coordinates relative to those of the target widget.
|
|
||||||
void ForwardMouseEvent(const QMouseEvent *e, QWidget *target);
|
|
||||||
|
|
||||||
// Checks if the mouse event was inside the widget's rectangle.
|
|
||||||
bool IsMouseEventInWidget(const QMouseEvent *e, const QWidget *widget);
|
|
||||||
|
|
||||||
// Reads all children of the current element,
|
// Reads all children of the current element,
|
||||||
// and returns with the stream reader either on the EndElement for the current element, or the end of the file - whichever came first.
|
// and returns with the stream reader either on the EndElement for the current element, or the end of the file - whichever came first.
|
||||||
void ConsumeCurrentElement(QXmlStreamReader *reader);
|
void ConsumeCurrentElement(QXmlStreamReader *reader);
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QRegExp>
|
#include <QRegularExpression>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
@@ -54,7 +54,7 @@
|
|||||||
|
|
||||||
#include "collection/collectionbackend.h"
|
#include "collection/collectionbackend.h"
|
||||||
#include "settings/collectionsettingspage.h"
|
#include "settings/collectionsettingspage.h"
|
||||||
#include "organise/organiseformat.h"
|
#include "organize/organizeformat.h"
|
||||||
#include "internet/internetservices.h"
|
#include "internet/internetservices.h"
|
||||||
#include "internet/internetservice.h"
|
#include "internet/internetservice.h"
|
||||||
#include "albumcoverchoicecontroller.h"
|
#include "albumcoverchoicecontroller.h"
|
||||||
@@ -163,8 +163,8 @@ void AlbumCoverChoiceController::SaveCoverToFileManual(const Song &song, const Q
|
|||||||
}
|
}
|
||||||
initial_file_name = initial_file_name + "-" + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + ".jpg";
|
initial_file_name = initial_file_name + "-" + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + ".jpg";
|
||||||
initial_file_name = initial_file_name.toLower();
|
initial_file_name = initial_file_name.toLower();
|
||||||
initial_file_name.replace(QRegExp("\\s"), "-");
|
initial_file_name.replace(QRegularExpression("\\s"), "-");
|
||||||
initial_file_name.remove(OrganiseFormat::kInvalidFatCharacters);
|
initial_file_name.remove(OrganizeFormat::kInvalidFatCharacters);
|
||||||
|
|
||||||
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + ";;" + tr(kAllFilesFilter));
|
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + ";;" + tr(kAllFilesFilter));
|
||||||
|
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ struct CoverSearchRequest {
|
|||||||
|
|
||||||
// This structure represents a single result of some album's cover search request.
|
// This structure represents a single result of some album's cover search request.
|
||||||
struct CoverSearchResult {
|
struct CoverSearchResult {
|
||||||
explicit CoverSearchResult() : score(0.0) {}
|
explicit CoverSearchResult() : score_provider(0.0), score_match(0.0), score_quality(0.0), number(0) {}
|
||||||
|
|
||||||
// Used for grouping in the user interface.
|
// Used for grouping in the user interface.
|
||||||
QString provider;
|
QString provider;
|
||||||
@@ -73,8 +73,23 @@ struct CoverSearchResult {
|
|||||||
// An URL of a cover image
|
// An URL of a cover image
|
||||||
QUrl image_url;
|
QUrl image_url;
|
||||||
|
|
||||||
|
// Image size
|
||||||
|
QSize image_size;
|
||||||
|
|
||||||
|
// Score for this provider
|
||||||
|
float score_provider;
|
||||||
|
|
||||||
|
// Score for match
|
||||||
|
float score_match;
|
||||||
|
|
||||||
|
// Score for image quality
|
||||||
|
float score_quality;
|
||||||
|
|
||||||
|
// The result number
|
||||||
|
int number;
|
||||||
|
|
||||||
// Total score for this result
|
// Total score for this result
|
||||||
float score;
|
float score() const { return score_provider + score_match + score_quality; }
|
||||||
|
|
||||||
};
|
};
|
||||||
Q_DECLARE_METATYPE(CoverSearchResult)
|
Q_DECLARE_METATYPE(CoverSearchResult)
|
||||||
|
|||||||
@@ -98,8 +98,8 @@ void AlbumCoverFetcherSearch::Start(CoverProviders *cover_providers) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If album is missing, check if we can still use this provider by searching using artist + title.
|
// If artist and album is missing, check if we can still use this provider by searching using title.
|
||||||
if (!provider->allow_missing_album() && request_.album.isEmpty()) {
|
if (!provider->allow_missing_album() && request_.album.isEmpty() && !request_.title.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,17 +133,81 @@ void AlbumCoverFetcherSearch::ProviderSearchResults(CoverProvider *provider, con
|
|||||||
|
|
||||||
CoverSearchResults results_copy(results);
|
CoverSearchResults results_copy(results);
|
||||||
for (int i = 0 ; i < results_copy.count() ; ++i) {
|
for (int i = 0 ; i < results_copy.count() ; ++i) {
|
||||||
|
|
||||||
results_copy[i].provider = provider->name();
|
results_copy[i].provider = provider->name();
|
||||||
results_copy[i].score = provider->quality();
|
results_copy[i].score_provider = provider->quality();
|
||||||
if (results_copy[i].artist.toLower() == request_.artist.toLower()) {
|
|
||||||
results_copy[i].score += 0.5;
|
QString request_artist = request_.artist.toLower();
|
||||||
|
QString request_album = request_.album.toLower();
|
||||||
|
QString result_artist = results_copy[i].artist.toLower();
|
||||||
|
QString result_album = results_copy[i].album.toLower();
|
||||||
|
|
||||||
|
if (result_artist == request_artist) {
|
||||||
|
results_copy[i].score_match += 0.5;
|
||||||
}
|
}
|
||||||
if (results_copy[i].album.toLower() == request_.album.toLower()) {
|
if (result_album == request_album) {
|
||||||
results_copy[i].score += 0.5;
|
results_copy[i].score_match += 0.5;
|
||||||
}
|
}
|
||||||
if (results_copy[i].artist.toLower() != request_.artist.toLower() && results_copy[i].album.toLower() != request_.album.toLower()) {
|
if (result_artist != request_artist && result_album != request_album) {
|
||||||
results_copy[i].score -= 1.5;
|
results_copy[i].score_match -= 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request_album.isEmpty() && result_artist != request_artist) {
|
||||||
|
results_copy[i].score_match -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrease score if the search was based on artist and song title, and the resulting album is a compilation or live album.
|
||||||
|
// This is done since we can't match the album titles, and we want to prevent compilation or live albums from being picked before studio albums for streams.
|
||||||
|
// TODO: Make these regular expressions.
|
||||||
|
if (request_album.isEmpty() && (
|
||||||
|
result_album.contains("hits") ||
|
||||||
|
result_album.contains("greatest") ||
|
||||||
|
result_album.contains("best") ||
|
||||||
|
result_album.contains("collection") ||
|
||||||
|
result_album.contains("classics") ||
|
||||||
|
result_album.contains("singles") ||
|
||||||
|
result_album.contains("bootleg") ||
|
||||||
|
result_album.contains("live") ||
|
||||||
|
result_album.contains("concert") ||
|
||||||
|
result_album.contains("essential") ||
|
||||||
|
result_album.contains("ultimate") ||
|
||||||
|
result_album.contains("karaoke") ||
|
||||||
|
result_album.contains("mixtape") ||
|
||||||
|
result_album.contains("country rock") ||
|
||||||
|
result_album.contains("indie folk") ||
|
||||||
|
result_album.contains("soft rock") ||
|
||||||
|
result_album.contains("folk music") ||
|
||||||
|
result_album.contains("60's rock") ||
|
||||||
|
result_album.contains("60's romance") ||
|
||||||
|
result_album.contains("60s music") ||
|
||||||
|
result_album.contains("late 60s") ||
|
||||||
|
result_album.contains("the 60s") ||
|
||||||
|
result_album.contains("folk and blues") ||
|
||||||
|
result_album.contains("60 from the 60's") ||
|
||||||
|
result_album.contains("classic psychedelic") ||
|
||||||
|
result_album.contains("playlist: acoustic") ||
|
||||||
|
result_album.contains("90's rnb playlist") ||
|
||||||
|
result_album.contains("rock 80s") ||
|
||||||
|
result_album.contains("classic 80s") ||
|
||||||
|
result_album.contains("rock anthems") ||
|
||||||
|
result_album.contains("rock songs") ||
|
||||||
|
result_album.contains("rock 2019") ||
|
||||||
|
result_album.contains("guitar anthems") ||
|
||||||
|
result_album.contains("driving anthems") ||
|
||||||
|
result_album.contains("traffic jam jams") ||
|
||||||
|
result_album.contains("perfect background music") ||
|
||||||
|
result_album.contains("70's gold") ||
|
||||||
|
result_album.contains("rockfluence") ||
|
||||||
|
result_album.contains("acoustic dinner accompaniment") ||
|
||||||
|
result_album.contains("complete studio albums") ||
|
||||||
|
result_album.contains("mellow rock")
|
||||||
|
)) {
|
||||||
|
results_copy[i].score_match -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the initial image quality score besed on the size returned by the API, this is recalculated when the image is received.
|
||||||
|
results_copy[i].score_quality += ScoreImage(results_copy[i].image_size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add results from the current provider to our pool
|
// Add results from the current provider to our pool
|
||||||
@@ -204,10 +268,14 @@ void AlbumCoverFetcherSearch::FetchMoreImages() {
|
|||||||
++i;
|
++i;
|
||||||
CoverSearchResult result = results_.takeFirst();
|
CoverSearchResult result = results_.takeFirst();
|
||||||
|
|
||||||
qLog(Debug) << "Loading" << result.image_url << "from" << result.provider << "with current score" << result.score;
|
qLog(Debug) << "Loading" << result.artist << result.album << result.image_url << "from" << result.provider << "with current score" << result.score();
|
||||||
|
|
||||||
QNetworkRequest req(result.image_url);
|
QNetworkRequest req(result.image_url);
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0)
|
||||||
|
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
|
||||||
|
#else
|
||||||
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
|
||||||
|
#endif
|
||||||
QNetworkReply *image_reply = network_->get(req);
|
QNetworkReply *image_reply = network_->get(req);
|
||||||
connect(image_reply, &QNetworkReply::finished, [=] { ProviderCoverFetchFinished(image_reply); });
|
connect(image_reply, &QNetworkReply::finished, [=] { ProviderCoverFetchFinished(image_reply); });
|
||||||
pending_image_loads_[image_reply] = result;
|
pending_image_loads_[image_reply] = result;
|
||||||
@@ -251,9 +319,13 @@ void AlbumCoverFetcherSearch::ProviderCoverFetchFinished(QNetworkReply *reply) {
|
|||||||
if (QImageReader::supportedMimeTypes().contains(mimetype.toUtf8())) {
|
if (QImageReader::supportedMimeTypes().contains(mimetype.toUtf8())) {
|
||||||
QImage image;
|
QImage image;
|
||||||
if (image.loadFromData(reply->readAll())) {
|
if (image.loadFromData(reply->readAll())) {
|
||||||
result.score += ScoreImage(image);
|
if (result.image_size != QSize(0,0) && result.image_size != image.size()) {
|
||||||
candidate_images_.insert(result.score, CandidateImage(result, image));
|
qLog(Debug) << "API size for image" << result.image_size << "for" << reply->url() << "from" << result.provider << "did not match retrieved size" << image.size();
|
||||||
qLog(Debug) << reply->url() << "from" << result.provider << "scored" << result.score;
|
}
|
||||||
|
result.image_size = image.size();
|
||||||
|
result.score_quality = ScoreImage(image.size());
|
||||||
|
candidate_images_.insert(result.score(), CandidateImage(result, image));
|
||||||
|
qLog(Debug) << reply->url() << "from" << result.provider << "scored" << result.score();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qLog(Error) << "Error decoding image data from" << reply->url();
|
qLog(Error) << "Error decoding image data from" << reply->url();
|
||||||
@@ -283,18 +355,15 @@ void AlbumCoverFetcherSearch::ProviderCoverFetchFinished(QNetworkReply *reply) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float AlbumCoverFetcherSearch::ScoreImage(const QImage &image) const {
|
float AlbumCoverFetcherSearch::ScoreImage(const QSize size) const {
|
||||||
|
|
||||||
// Invalid images score nothing
|
if (size.width() == 0 || size.height() == 0) return 0.0;
|
||||||
if (image.isNull()) {
|
|
||||||
return 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A 500x500px image scores 1.0, bigger scores higher
|
// A 500x500px image scores 1.0, bigger scores higher
|
||||||
const float size_score = std::sqrt(float(image.width() * image.height())) / kTargetSize;
|
const float size_score = std::sqrt(float(size.width() * size.height())) / kTargetSize;
|
||||||
|
|
||||||
// A 1:1 image scores 1.0, anything else scores less
|
// A 1:1 image scores 1.0, anything else scores less
|
||||||
const float aspect_score = 1.0 - float(std::max(image.width(), image.height()) - std::min(image.width(), image.height())) / std::max(image.height(), image.width());
|
const float aspect_score = 1.0 - float(std::max(size.width(), size.height()) - std::min(size.width(), size.height())) / std::max(size.height(), size.width());
|
||||||
|
|
||||||
return size_score + aspect_score;
|
return size_score + aspect_score;
|
||||||
|
|
||||||
@@ -310,7 +379,7 @@ void AlbumCoverFetcherSearch::SendBestImage() {
|
|||||||
cover_url = best_image.first.image_url;
|
cover_url = best_image.first.image_url;
|
||||||
image = best_image.second;
|
image = best_image.second;
|
||||||
|
|
||||||
qLog(Info) << "Using" << best_image.first.image_url << "from" << best_image.first.provider << "with score" << best_image.first.score;
|
qLog(Info) << "Using" << best_image.first.image_url << "from" << best_image.first.provider << "with score" << best_image.first.score();
|
||||||
|
|
||||||
statistics_.chosen_images_by_provider_[best_image.first.provider]++;
|
statistics_.chosen_images_by_provider_[best_image.first.provider]++;
|
||||||
statistics_.chosen_images_++;
|
statistics_.chosen_images_++;
|
||||||
@@ -348,5 +417,9 @@ bool AlbumCoverFetcherSearch::ProviderCompareOrder(CoverProvider *a, CoverProvid
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AlbumCoverFetcherSearch::CoverSearchResultCompareScore(const CoverSearchResult &a, const CoverSearchResult &b) {
|
bool AlbumCoverFetcherSearch::CoverSearchResultCompareScore(const CoverSearchResult &a, const CoverSearchResult &b) {
|
||||||
return a.score > b.score;
|
return a.score() > b.score();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AlbumCoverFetcherSearch::CoverSearchResultCompareNumber(const CoverSearchResult &a, const CoverSearchResult &b) {
|
||||||
|
return a.number < b.number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,8 @@ class AlbumCoverFetcherSearch : public QObject {
|
|||||||
|
|
||||||
CoverSearchStatistics statistics() const { return statistics_; }
|
CoverSearchStatistics statistics() const { return statistics_; }
|
||||||
|
|
||||||
|
static bool CoverSearchResultCompareNumber(const CoverSearchResult &a, const CoverSearchResult &b);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// It's the end of search (when there was no fetch-me-a-cover request).
|
// It's the end of search (when there was no fetch-me-a-cover request).
|
||||||
void SearchFinished(const quint64, const CoverSearchResults &results);
|
void SearchFinished(const quint64, const CoverSearchResults &results);
|
||||||
@@ -77,7 +79,7 @@ class AlbumCoverFetcherSearch : public QObject {
|
|||||||
void AllProvidersFinished();
|
void AllProvidersFinished();
|
||||||
|
|
||||||
void FetchMoreImages();
|
void FetchMoreImages();
|
||||||
float ScoreImage(const QImage &image) const;
|
float ScoreImage(const QSize size) const;
|
||||||
void SendBestImage();
|
void SendBestImage();
|
||||||
|
|
||||||
static bool ProviderCompareOrder(CoverProvider *a, CoverProvider *b);
|
static bool ProviderCompareOrder(CoverProvider *a, CoverProvider *b);
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user