Compare commits
99 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d8725f268 | ||
|
|
373c7cdbc4 | ||
|
|
a4855bb33b | ||
|
|
57c1358ded | ||
|
|
eb4ce1feab | ||
|
|
838c17e144 | ||
|
|
4499cbca3c | ||
|
|
a835a4a2f7 | ||
|
|
9cc6a94353 | ||
|
|
5ed9d9c4a0 | ||
|
|
9c5ac7080d | ||
|
|
6346370e86 | ||
|
|
80697f8f30 | ||
|
|
18b8b56367 | ||
|
|
760aacca26 | ||
|
|
1a4f0dcf5a | ||
|
|
947484a71c | ||
|
|
a74439d038 | ||
|
|
c338618593 | ||
|
|
011897da53 | ||
|
|
3fcaa58947 | ||
|
|
ef8bd4362a | ||
|
|
627a2ef6dd | ||
|
|
2732536d6e | ||
|
|
5a1b4b3ff8 | ||
|
|
d93ec82e4f | ||
|
|
15080972f3 | ||
|
|
171b58f737 | ||
|
|
c008ab6141 | ||
|
|
f14c3654dc | ||
|
|
ae05a61551 | ||
|
|
8e1def225b | ||
|
|
6e061764ee | ||
|
|
ac55b22839 | ||
|
|
49f77d3b75 | ||
|
|
4abc650edf | ||
|
|
5ba00b61be | ||
|
|
bc16a6c4cb | ||
|
|
ea4dc6f040 | ||
|
|
749ae8d5eb | ||
|
|
7a56ffb7c3 | ||
|
|
e62ab23de2 | ||
|
|
c6f6118506 | ||
|
|
8a5d5ad952 | ||
|
|
49e2615d14 | ||
|
|
9289394261 | ||
|
|
8da4c88fd3 | ||
|
|
a303850341 | ||
|
|
fb33610672 | ||
|
|
d024dd6563 | ||
|
|
0be48f9f59 | ||
|
|
df9292bafe | ||
|
|
c1dcef3477 | ||
|
|
48bc1f8361 | ||
|
|
2b2b4dbcf4 | ||
|
|
a1eadecdef | ||
|
|
f0b529952d | ||
|
|
c1ac2debb8 | ||
|
|
ac40094d37 | ||
|
|
cb2bb4cb67 | ||
|
|
f2965940cc | ||
|
|
c9ca147898 | ||
|
|
c379d7f846 | ||
|
|
45ae1ed265 | ||
|
|
9bf00eff40 | ||
|
|
1677b3d5b9 | ||
|
|
2a6806004a | ||
|
|
39347d69df | ||
|
|
a2c0e4d4b1 | ||
|
|
ab2ffd9ac1 | ||
|
|
c69fff52cc | ||
|
|
1cfe61dc72 | ||
|
|
a23f39d81e | ||
|
|
b7724ff583 | ||
|
|
e5dba60fab | ||
|
|
2ccf489a83 | ||
|
|
068939ca0b | ||
|
|
94ba8614ec | ||
|
|
f12a0c2379 | ||
|
|
8ab257645b | ||
|
|
6331a0615f | ||
|
|
a21855fa20 | ||
|
|
12150c2180 | ||
|
|
d90aecb164 | ||
|
|
e738f2bc9f | ||
|
|
2f72c41cda | ||
|
|
aa43d42cdb | ||
|
|
be8228e33c | ||
|
|
5591472dbd | ||
|
|
30e6ced4e9 | ||
|
|
5f4c2bae89 | ||
|
|
0f036d9a43 | ||
|
|
1695ac3a32 | ||
|
|
07a19ba619 | ||
|
|
4dd78d89a0 | ||
|
|
8f4056faa6 | ||
|
|
7b40c33892 | ||
|
|
b06bb5142f | ||
|
|
d576156ee1 |
@@ -35,7 +35,7 @@ commands:
|
||||
working_directory: build
|
||||
- run:
|
||||
name: Build RPM
|
||||
command: rpmbuild -ba ../dist/rpm/strawberry.spec
|
||||
command: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||
working_directory: build
|
||||
|
||||
|
||||
@@ -59,14 +59,12 @@ commands:
|
||||
zypper --non-interactive --gpg-auto-import-keys install
|
||||
lsb-release
|
||||
rpm-build
|
||||
rpmdevtools
|
||||
git
|
||||
tar
|
||||
make
|
||||
cmake
|
||||
gcc
|
||||
gcc-c++
|
||||
pkg-config
|
||||
gettext-tools
|
||||
glibc-devel
|
||||
libboost_headers-devel
|
||||
@@ -84,7 +82,6 @@ commands:
|
||||
gstreamer-plugins-base-devel
|
||||
libxine-devel
|
||||
vlc-devel
|
||||
taglib-devel
|
||||
libQt5Core-devel
|
||||
libQt5Gui-devel
|
||||
libQt5Widgets-devel
|
||||
@@ -333,7 +330,7 @@ jobs:
|
||||
|
||||
build_source:
|
||||
docker:
|
||||
- image: opensuse/tumbleweed
|
||||
- image: opensuse/leap:15.1
|
||||
steps:
|
||||
- install_opensuse_dependencies
|
||||
- checkout
|
||||
@@ -347,6 +344,12 @@ jobs:
|
||||
environment:
|
||||
RPM_BUILD_NCPUS: "2"
|
||||
steps:
|
||||
- run:
|
||||
name: Update packages
|
||||
command: zypper --non-interactive --gpg-auto-import-keys ref
|
||||
- run:
|
||||
name: Upgrade packages
|
||||
command: zypper --non-interactive --gpg-auto-import-keys dup
|
||||
- install_opensuse_dependencies
|
||||
- checkout
|
||||
- cmake
|
||||
|
||||
8
.github/workflows/ccpp.yml
vendored
@@ -6,13 +6,13 @@ jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: opensuse/tumbleweed
|
||||
image: opensuse/leap:15.1
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Update Packages
|
||||
run: zypper ref
|
||||
- name: Install Packages
|
||||
run: zypper --non-interactive --gpg-auto-import-keys install lsb-release rpm-build rpmdevtools git tar make cmake gcc gcc-c++ pkg-config 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 libxine-devel vlc-devel taglib-devel libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel libQt5DBus-devel libQt5Test-devel libqt5-qtx11extras-devel libqt5-qtbase-common-devel libQt5Sql5-sqlite libqt5-linguist-devel libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files appstream-glib hicolor-icon-theme
|
||||
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 libxine-devel vlc-devel taglib-devel libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel libQt5DBus-devel libQt5Test-devel libqt5-qtx11extras-devel libqt5-qtbase-common-devel libQt5Sql5-sqlite libqt5-linguist-devel libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files appstream-glib hicolor-icon-theme
|
||||
- name: Create Build Environment
|
||||
run: mkdir -p build
|
||||
- name: Configure CMake
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
- name: Unlink python
|
||||
run: brew unlink python@2
|
||||
- name: Install Packages
|
||||
run: brew install glib pkgconfig boost libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav libcdio libmtp libimobiledevice libplist create-dmg
|
||||
run: brew install glib pkgconfig boost libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav libcdio libmtp libimobiledevice libplist create-dmg taglib
|
||||
- name: Create Build Environment
|
||||
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||
- name: Configure CMake
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
Qt5LinguistTools_DIR: /usr/local/opt/qt5/lib/cmake/Qt5LinguistTools
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_BUNDLE=ON
|
||||
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_BUNDLE=ON -DUSE_SYSTEM_TAGLIB=ON
|
||||
- name: Build
|
||||
working-directory: ${{runner.workspace}}/build
|
||||
shell: bash
|
||||
|
||||
@@ -21,7 +21,7 @@ before_install:
|
||||
git fetch --unshallow || travis_terminate 1;
|
||||
git pull || 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;
|
||||
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 libcdio libmtp libimobiledevice libplist;
|
||||
brew install create-dmg;
|
||||
@@ -33,7 +33,7 @@ before_install:
|
||||
fi
|
||||
before_script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DUSE_SYSTEM_TAGLIB=ON ; fi
|
||||
script:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||
|
||||
15
3rdparty/singleapplication/CMakeLists.txt
vendored
@@ -1,16 +1,8 @@
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
include(CheckIncludeFiles)
|
||||
include(CheckFunctionExists)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
endif()
|
||||
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.0)
|
||||
check_function_exists(geteuid HAVE_GETEUID)
|
||||
check_function_exists(getpwuid HAVE_GETPWUID)
|
||||
@@ -19,14 +11,15 @@ endif()
|
||||
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
|
||||
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)
|
||||
QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
|
||||
ADD_LIBRARY(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
|
||||
add_library(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
|
||||
target_link_libraries(singleapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
||||
|
||||
set(SINGLECOREAPP-SOURCES singlecoreapplication.cpp singlecoreapplication_p.cpp)
|
||||
set(SINGLECOREAPP-MOC-HEADERS singlecoreapplication.h singlecoreapplication_p.h)
|
||||
QT5_WRAP_CPP(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
|
||||
ADD_LIBRARY(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
|
||||
add_library(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
|
||||
target_link_libraries(singlecoreapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
||||
|
||||
configure_file(config.h.in "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
@@ -61,8 +61,8 @@
|
||||
# include <lmcons.h>
|
||||
#endif
|
||||
|
||||
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication *q_ptr)
|
||||
: q_ptr(q_ptr),
|
||||
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication *_q_ptr)
|
||||
: q_ptr(_q_ptr),
|
||||
memory(nullptr),
|
||||
socket(nullptr),
|
||||
server(nullptr),
|
||||
@@ -186,7 +186,7 @@ void SingleApplicationPrivate::startPrimary() {
|
||||
|
||||
void SingleApplicationPrivate::startSecondary() {}
|
||||
|
||||
void SingleApplicationPrivate::connectToPrimary(int msecs, ConnectionType connectionType) {
|
||||
void SingleApplicationPrivate::connectToPrimary(const int msecs, const ConnectionType connectionType) {
|
||||
|
||||
// Connect to the Local Server of the Primary Instance if not already connected.
|
||||
if (socket == nullptr) {
|
||||
@@ -386,14 +386,14 @@ void SingleApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
|
||||
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, quint32 instanceId) {
|
||||
void SingleApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const quint32 instanceId) {
|
||||
|
||||
Q_Q(SingleApplication);
|
||||
Q_EMIT q->receivedMessage(instanceId, dataSocket->readAll());
|
||||
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, quint32 instanceId) {
|
||||
void SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
|
||||
|
||||
if (closedSocket->bytesAvailable() > 0)
|
||||
Q_EMIT slotDataAvailable(closedSocket, instanceId);
|
||||
|
||||
@@ -74,14 +74,14 @@ class SingleApplicationPrivate : public QObject {
|
||||
};
|
||||
Q_DECLARE_PUBLIC(SingleApplication)
|
||||
|
||||
SingleApplicationPrivate( SingleApplication *q_ptr );
|
||||
SingleApplicationPrivate(SingleApplication *_q_ptr);
|
||||
~SingleApplicationPrivate();
|
||||
|
||||
void genBlockServerName();
|
||||
void initializeMemoryBlock();
|
||||
void startPrimary();
|
||||
void startSecondary();
|
||||
void connectToPrimary(int msecs, ConnectionType connectionType );
|
||||
void connectToPrimary(const int msecs, const ConnectionType connectionType);
|
||||
quint16 blockChecksum();
|
||||
qint64 primaryPid();
|
||||
void readInitMessageHeader(QLocalSocket *socket);
|
||||
@@ -98,8 +98,8 @@ class SingleApplicationPrivate : public QObject {
|
||||
|
||||
public slots:
|
||||
void slotConnectionEstablished();
|
||||
void slotDataAvailable(QLocalSocket*, quint32);
|
||||
void slotClientConnectionClosed(QLocalSocket*, quint32);
|
||||
void slotDataAvailable(QLocalSocket*, const quint32);
|
||||
void slotClientConnectionClosed(QLocalSocket*, const quint32);
|
||||
};
|
||||
|
||||
#endif // SINGLEAPPLICATION_P_H
|
||||
|
||||
@@ -61,8 +61,8 @@
|
||||
# include <lmcons.h>
|
||||
#endif
|
||||
|
||||
SingleCoreApplicationPrivate::SingleCoreApplicationPrivate(SingleCoreApplication *q_ptr)
|
||||
: q_ptr(q_ptr),
|
||||
SingleCoreApplicationPrivate::SingleCoreApplicationPrivate(SingleCoreApplication *_q_ptr)
|
||||
: q_ptr(_q_ptr),
|
||||
memory(nullptr),
|
||||
socket(nullptr),
|
||||
server(nullptr),
|
||||
@@ -186,7 +186,7 @@ void SingleCoreApplicationPrivate::startPrimary() {
|
||||
|
||||
void SingleCoreApplicationPrivate::startSecondary() {}
|
||||
|
||||
void SingleCoreApplicationPrivate::connectToPrimary(int msecs, ConnectionType connectionType) {
|
||||
void SingleCoreApplicationPrivate::connectToPrimary(const int msecs, const ConnectionType connectionType) {
|
||||
|
||||
// Connect to the Local Server of the Primary Instance if not already connected.
|
||||
if (socket == nullptr) {
|
||||
@@ -386,14 +386,14 @@ void SingleCoreApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
|
||||
|
||||
}
|
||||
|
||||
void SingleCoreApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, quint32 instanceId) {
|
||||
void SingleCoreApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const quint32 instanceId) {
|
||||
|
||||
Q_Q(SingleCoreApplication);
|
||||
Q_EMIT q->receivedMessage(instanceId, dataSocket->readAll());
|
||||
|
||||
}
|
||||
|
||||
void SingleCoreApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, quint32 instanceId) {
|
||||
void SingleCoreApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
|
||||
|
||||
if (closedSocket->bytesAvailable() > 0)
|
||||
Q_EMIT slotDataAvailable(closedSocket, instanceId);
|
||||
|
||||
@@ -74,14 +74,14 @@ class SingleCoreApplicationPrivate : public QObject {
|
||||
};
|
||||
Q_DECLARE_PUBLIC(SingleCoreApplication)
|
||||
|
||||
SingleCoreApplicationPrivate( SingleCoreApplication *q_ptr );
|
||||
SingleCoreApplicationPrivate(SingleCoreApplication *_q_ptr);
|
||||
~SingleCoreApplicationPrivate();
|
||||
|
||||
void genBlockServerName();
|
||||
void initializeMemoryBlock();
|
||||
void startPrimary();
|
||||
void startSecondary();
|
||||
void connectToPrimary(int msecs, ConnectionType connectionType );
|
||||
void connectToPrimary(const int msecs, const ConnectionType connectionType);
|
||||
quint16 blockChecksum();
|
||||
qint64 primaryPid();
|
||||
void readInitMessageHeader(QLocalSocket *socket);
|
||||
@@ -98,8 +98,8 @@ class SingleCoreApplicationPrivate : public QObject {
|
||||
|
||||
public slots:
|
||||
void slotConnectionEstablished();
|
||||
void slotDataAvailable(QLocalSocket*, quint32);
|
||||
void slotClientConnectionClosed(QLocalSocket*, quint32);
|
||||
void slotDataAvailable(QLocalSocket*, const quint32);
|
||||
void slotClientConnectionClosed(QLocalSocket*, const quint32);
|
||||
};
|
||||
|
||||
#endif // SINGLECOREAPPLICATION_P_H
|
||||
|
||||
6
3rdparty/taglib/CMakeLists.txt
vendored
@@ -1,8 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -fpermissive -Wall -Woverloaded-virtual -Wno-sign-compare -Wno-delete-non-virtual-dtor")
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
set(TAGLIB_SOVERSION_CURRENT 17)
|
||||
set(TAGLIB_SOVERSION_REVISION 0)
|
||||
|
||||
2
3rdparty/taglib/ape/apefile.cpp
vendored
@@ -87,7 +87,7 @@ public:
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool APE::File::isSupported(IOStream *stream)
|
||||
bool APE::File::isSupported(IOStream*)
|
||||
{
|
||||
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
||||
|
||||
|
||||
2
3rdparty/taglib/asf/asfattribute.cpp
vendored
@@ -264,6 +264,7 @@ int ASF::Attribute::dataSize() const
|
||||
case BytesType:
|
||||
if(d->pictureValue.isValid())
|
||||
return d->pictureValue.dataSize();
|
||||
break;
|
||||
case GuidType:
|
||||
return d->byteVectorValue.size();
|
||||
}
|
||||
@@ -305,6 +306,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
|
||||
data.append(d->pictureValue.render());
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GuidType:
|
||||
data.append(d->byteVectorValue);
|
||||
break;
|
||||
|
||||
8
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
@@ -51,7 +51,7 @@ namespace
|
||||
|
||||
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
|
||||
{
|
||||
for(int i = 0; i < chunks.size(); i++) {
|
||||
for (unsigned long int i = 0 ; i < chunks.size() ; i++) {
|
||||
if(chunks[i].name == id)
|
||||
return i;
|
||||
}
|
||||
@@ -64,8 +64,8 @@ namespace
|
||||
if(name.size() != 4)
|
||||
return false;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(name[i] < 32 || name[i] > 127)
|
||||
for (int i = 0 ; i < 4 ; i++) {
|
||||
if (name[i] < 32)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ bool DSDIFF::File::save()
|
||||
return save(AllTags);
|
||||
}
|
||||
|
||||
bool DSDIFF::File::save(TagTypes tags, StripTags strip, ID3v2::Version version)
|
||||
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
|
||||
{
|
||||
if(readOnly()) {
|
||||
debug("DSDIFF::File::save() -- File is read only.");
|
||||
|
||||
2
3rdparty/taglib/dsf/dsffile.cpp
vendored
@@ -180,7 +180,7 @@ bool DSF::File::save()
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
|
||||
void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
||||
{
|
||||
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
|
||||
// The file format is not chunked in the sense of a RIFF File, though
|
||||
|
||||
8
3rdparty/taglib/fileref.cpp
vendored
@@ -228,10 +228,10 @@ namespace
|
||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "OGA") {
|
||||
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
|
||||
File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(file->isValid())
|
||||
return file;
|
||||
delete file;
|
||||
File *file_flac = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if (file_flac->isValid())
|
||||
return file_flac;
|
||||
delete file_flac;
|
||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
if(ext == "FLAC")
|
||||
|
||||
4
3rdparty/taglib/fileref.h
vendored
@@ -92,8 +92,8 @@ namespace TagLib {
|
||||
|
||||
class TAGLIB_EXPORT FileTypeResolver
|
||||
{
|
||||
TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
||||
public:
|
||||
virtual ~FileTypeResolver();
|
||||
/*!
|
||||
* This method must be overridden to provide an additional file type
|
||||
* resolver. If the resolver is able to determine the file type it should
|
||||
@@ -286,4 +286,4 @@ namespace TagLib {
|
||||
}
|
||||
} // namespace Strawberry_TagLib::TagLib
|
||||
|
||||
#endif
|
||||
#endif // TAGLIB_FILEREF_H
|
||||
|
||||
8
3rdparty/taglib/mod/modfilebase.cpp
vendored
@@ -60,9 +60,9 @@ bool Mod::FileBase::readString(String &s, unsigned long size)
|
||||
return true;
|
||||
}
|
||||
|
||||
void Mod::FileBase::writeByte(unsigned char byte)
|
||||
void Mod::FileBase::writeByte(unsigned char _byte)
|
||||
{
|
||||
ByteVector data(1, byte);
|
||||
ByteVector data(1, _byte);
|
||||
writeBlock(data);
|
||||
}
|
||||
|
||||
@@ -86,11 +86,11 @@ void Mod::FileBase::writeU32B(unsigned long number)
|
||||
writeBlock(ByteVector::fromUInt(number, true));
|
||||
}
|
||||
|
||||
bool Mod::FileBase::readByte(unsigned char &byte)
|
||||
bool Mod::FileBase::readByte(unsigned char &_byte)
|
||||
{
|
||||
ByteVector data(readBlock(1));
|
||||
if(data.size() < 1) return false;
|
||||
byte = data[0];
|
||||
_byte = data[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
6
3rdparty/taglib/mp4/mp4atom.cpp
vendored
@@ -122,15 +122,15 @@ MP4::Atom::find(const char *name1, const char *name2, const char *name3, const c
|
||||
}
|
||||
|
||||
MP4::AtomList
|
||||
MP4::Atom::findall(const char *name, bool recursive)
|
||||
MP4::Atom::findall(const char *_name, bool recursive)
|
||||
{
|
||||
MP4::AtomList result;
|
||||
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
||||
if((*it)->name == name) {
|
||||
if((*it)->name == _name) {
|
||||
result.append(*it);
|
||||
}
|
||||
if(recursive) {
|
||||
result.append((*it)->findall(name, recursive));
|
||||
result.append((*it)->findall(_name, recursive));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
2
3rdparty/taglib/mp4/mp4atom.h
vendored
@@ -67,7 +67,7 @@ namespace TagLib {
|
||||
};
|
||||
|
||||
struct AtomData {
|
||||
AtomData(AtomDataType type, ByteVector data) : type(type), locale(0), data(data) {}
|
||||
AtomData(AtomDataType _type, ByteVector _data) : type(_type), locale(0), data(_data) {}
|
||||
AtomDataType type;
|
||||
int locale;
|
||||
ByteVector data;
|
||||
|
||||
@@ -334,14 +334,14 @@ ByteVector TableOfContentsFrame::renderFields() const
|
||||
data.append(flags);
|
||||
data.append((char)(entryCount()));
|
||||
ByteVectorList::ConstIterator it = d->childElements.begin();
|
||||
while(it != d->childElements.end()) {
|
||||
while (it != d->childElements.end()) {
|
||||
data.append(*it);
|
||||
data.append('\0');
|
||||
it++;
|
||||
}
|
||||
FrameList l = d->embeddedFrameList;
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
data.append((*it)->render());
|
||||
for (FrameList::ConstIterator it2 = l.begin(); it2 != l.end(); ++it2)
|
||||
data.append((*it2)->render());
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
2
3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp
vendored
@@ -417,7 +417,7 @@ namespace
|
||||
{"TYER", "TDRC"}, // 2.3 -> 2.4
|
||||
{"TIME", "TDRC"}, // 2.3 -> 2.4
|
||||
};
|
||||
const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]);;
|
||||
const size_t deprecatedFramesSize = sizeof(deprecatedFrames) / sizeof(deprecatedFrames[0]);
|
||||
}
|
||||
|
||||
String Frame::frameIDToKey(const ByteVector &id)
|
||||
|
||||
2
3rdparty/taglib/mpeg/mpegheader.cpp
vendored
@@ -69,7 +69,7 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MPEG::Header::Header(const ByteVector &data) :
|
||||
MPEG::Header::Header(const ByteVector&) :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
debug("MPEG::Header::Header() - This constructor is no longer used.");
|
||||
|
||||
4
3rdparty/taglib/ogg/oggfile.cpp
vendored
@@ -296,10 +296,10 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
break;
|
||||
|
||||
page.setPageSequenceNumber(page.pageSequenceNumber() + numberOfNewPages);
|
||||
const ByteVector data = page.render();
|
||||
const ByteVector data2 = page.render();
|
||||
|
||||
seek(pageOffset + 18);
|
||||
writeBlock(data.mid(18, 8));
|
||||
writeBlock(data2.mid(18, 8));
|
||||
|
||||
if(page.header()->lastPageOfStream())
|
||||
break;
|
||||
|
||||
5
3rdparty/taglib/ogg/xiphcomment.cpp
vendored
@@ -379,8 +379,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
// std::pair<String, StringList> where the first String is the field name and
|
||||
// the StringList is the values associated with that field.
|
||||
|
||||
FieldListMap::ConstIterator it = d->fieldListMap.begin();
|
||||
for(; it != d->fieldListMap.end(); ++it) {
|
||||
for(FieldListMap::ConstIterator it = d->fieldListMap.begin() ; it != d->fieldListMap.end() ; ++it) {
|
||||
|
||||
// And now iterate over the values of the current list.
|
||||
|
||||
@@ -398,7 +397,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
}
|
||||
}
|
||||
|
||||
for(PictureConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
|
||||
for (PictureConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
|
||||
ByteVector picture = (*it)->render().toBase64();
|
||||
data.append(ByteVector::fromUInt(picture.size() + 23, false));
|
||||
data.append("METADATA_BLOCK_PICTURE=");
|
||||
|
||||
4
3rdparty/taglib/riff/rifffile.cpp
vendored
@@ -46,8 +46,8 @@ struct Chunk
|
||||
class RIFF::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
explicit FilePrivate(Endianness endianness) :
|
||||
endianness(endianness),
|
||||
explicit FilePrivate(Endianness _endianness) :
|
||||
endianness(_endianness),
|
||||
size(0),
|
||||
sizeOffset(0) {}
|
||||
|
||||
|
||||
5
3rdparty/taglib/toolkit/tbytevectorlist.cpp
vendored
@@ -77,11 +77,6 @@ ByteVectorList::ByteVectorList() :
|
||||
|
||||
}
|
||||
|
||||
ByteVectorList::ByteVectorList(const ByteVectorList &l) : List<ByteVector>(l)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
ByteVectorList::~ByteVectorList()
|
||||
{
|
||||
|
||||
|
||||
7
3rdparty/taglib/toolkit/tbytevectorlist.h
vendored
@@ -53,13 +53,6 @@ namespace TagLib {
|
||||
*/
|
||||
virtual ~ByteVectorList();
|
||||
|
||||
/*!
|
||||
* Make a shallow, implicitly shared, copy of \a l. Because this is
|
||||
* implicitly shared, this method is lightweight and suitable for
|
||||
* pass-by-value usage.
|
||||
*/
|
||||
ByteVectorList(const ByteVectorList &l);
|
||||
|
||||
/*!
|
||||
* Convert the ByteVectorList to a ByteVector separated by \a separator. By
|
||||
* default a space is used.
|
||||
|
||||
@@ -43,8 +43,8 @@ public:
|
||||
long position;
|
||||
};
|
||||
|
||||
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &data) :
|
||||
data(data),
|
||||
ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVector &_data) :
|
||||
data(_data),
|
||||
position(0)
|
||||
{
|
||||
}
|
||||
|
||||
6
3rdparty/taglib/toolkit/tfile.cpp
vendored
@@ -71,9 +71,9 @@ using namespace Strawberry_TagLib::TagLib;
|
||||
class File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate(IOStream *stream, bool owner) :
|
||||
stream(stream),
|
||||
streamOwner(owner),
|
||||
FilePrivate(IOStream *_stream, bool _owner) :
|
||||
stream(_stream),
|
||||
streamOwner(_owner),
|
||||
valid(true) {}
|
||||
|
||||
~FilePrivate()
|
||||
|
||||
2
3rdparty/taglib/toolkit/tfilestream.cpp
vendored
@@ -58,7 +58,7 @@ namespace
|
||||
#endif
|
||||
}
|
||||
|
||||
FileHandle openFile(const int fileDescriptor, bool readOnly)
|
||||
FileHandle openFile(const int, bool)
|
||||
{
|
||||
return InvalidFileHandle;
|
||||
}
|
||||
|
||||
20
3rdparty/taglib/toolkit/tpropertymap.cpp
vendored
@@ -28,16 +28,10 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
|
||||
PropertyMap::PropertyMap() : SimplePropertyMap()
|
||||
{
|
||||
}
|
||||
PropertyMap::PropertyMap() : SimplePropertyMap() {}
|
||||
|
||||
PropertyMap::PropertyMap(const PropertyMap &m) : SimplePropertyMap(m), unsupported(m.unsupported)
|
||||
{
|
||||
}
|
||||
PropertyMap::PropertyMap(const SimplePropertyMap &m) {
|
||||
|
||||
PropertyMap::PropertyMap(const SimplePropertyMap &m)
|
||||
{
|
||||
for(SimplePropertyMap::ConstIterator it = m.begin(); it != m.end(); ++it){
|
||||
String key = it->first.upper();
|
||||
if(!key.isEmpty())
|
||||
@@ -45,14 +39,13 @@ PropertyMap::PropertyMap(const SimplePropertyMap &m)
|
||||
else
|
||||
unsupported.append(it->first);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PropertyMap::~PropertyMap()
|
||||
{
|
||||
}
|
||||
PropertyMap::~PropertyMap() {}
|
||||
|
||||
bool PropertyMap::insert(const String &key, const StringList &values) {
|
||||
|
||||
bool PropertyMap::insert(const String &key, const StringList &values)
|
||||
{
|
||||
String realKey = key.upper();
|
||||
Iterator result = SimplePropertyMap::find(realKey);
|
||||
if(result == end())
|
||||
@@ -60,6 +53,7 @@ bool PropertyMap::insert(const String &key, const StringList &values)
|
||||
else
|
||||
SimplePropertyMap::operator[](realKey).append(values);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
bool PropertyMap::replace(const String &key, const StringList &values)
|
||||
|
||||
2
3rdparty/taglib/toolkit/tpropertymap.h
vendored
@@ -115,8 +115,6 @@ namespace TagLib {
|
||||
|
||||
PropertyMap();
|
||||
|
||||
PropertyMap(const PropertyMap &m);
|
||||
|
||||
/*!
|
||||
* Creates a PropertyMap initialized from a SimplePropertyMap. Copies all
|
||||
* entries from \a m that have valid keys.
|
||||
|
||||
7
3rdparty/taglib/toolkit/tstringlist.cpp
vendored
@@ -62,13 +62,6 @@ StringList::StringList() :
|
||||
|
||||
}
|
||||
|
||||
StringList::StringList(const StringList &l) :
|
||||
List<String>(l),
|
||||
d(nullptr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
StringList::StringList(const String &s) :
|
||||
List<String>(),
|
||||
d(nullptr)
|
||||
|
||||
2
3rdparty/taglib/toolkit/tstringlist.h
vendored
@@ -57,7 +57,7 @@ namespace TagLib {
|
||||
* implicitly shared, this method is lightweight and suitable for
|
||||
* pass-by-value usage.
|
||||
*/
|
||||
StringList(const StringList &l);
|
||||
StringList(const StringList &l) = default;
|
||||
|
||||
/*!
|
||||
* Constructs a StringList with \a s as a member.
|
||||
|
||||
2
3rdparty/taglib/toolkit/tutils.h
vendored
@@ -193,7 +193,7 @@ namespace TagLib
|
||||
// The last resort. May cause a buffer overflow.
|
||||
|
||||
length = vsprintf(buf, format, args);
|
||||
if(length >= BufferSize) {
|
||||
if(length >= (int)BufferSize) {
|
||||
debug("Utils::formatString() - Buffer overflow! Returning an empty string.");
|
||||
length = -1;
|
||||
}
|
||||
|
||||
44
3rdparty/taglib/xm/xmfile.cpp
vendored
@@ -110,7 +110,7 @@ template<typename T>
|
||||
class ValueReader : public Reader
|
||||
{
|
||||
public:
|
||||
explicit ValueReader(T &value) : value(value)
|
||||
explicit ValueReader(T &_value) : value(_value)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -151,7 +151,7 @@ private:
|
||||
class ByteReader : public ValueReader<unsigned char>
|
||||
{
|
||||
public:
|
||||
explicit ByteReader(unsigned char &byte) : ValueReader<unsigned char>(byte) {}
|
||||
explicit ByteReader(unsigned char &_byte) : ValueReader<unsigned char>(_byte) {}
|
||||
|
||||
unsigned int read(Strawberry_TagLib::TagLib::File &file, unsigned int limit)
|
||||
{
|
||||
@@ -172,8 +172,8 @@ template<typename T>
|
||||
class NumberReader : public ValueReader<T>
|
||||
{
|
||||
public:
|
||||
NumberReader(T &value, bool bigEndian) :
|
||||
ValueReader<T>(value), bigEndian(bigEndian)
|
||||
NumberReader(T &_value, bool _bigEndian) :
|
||||
ValueReader<T>(_value), bigEndian(_bigEndian)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -184,8 +184,8 @@ protected:
|
||||
class U16Reader : public NumberReader<unsigned short>
|
||||
{
|
||||
public:
|
||||
U16Reader(unsigned short &value, bool bigEndian)
|
||||
: NumberReader<unsigned short>(value, bigEndian) {}
|
||||
U16Reader(unsigned short &_value, bool _bigEndian)
|
||||
: NumberReader<unsigned short>(_value, _bigEndian) {}
|
||||
|
||||
unsigned int read(Strawberry_TagLib::TagLib::File &file, unsigned int limit)
|
||||
{
|
||||
@@ -203,8 +203,8 @@ public:
|
||||
class U32Reader : public NumberReader<unsigned long>
|
||||
{
|
||||
public:
|
||||
U32Reader(unsigned long &value, bool bigEndian = true) :
|
||||
NumberReader<unsigned long>(value, bigEndian)
|
||||
U32Reader(unsigned long &_value, bool _bigEndian = true) :
|
||||
NumberReader<unsigned long>(_value, _bigEndian)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -479,11 +479,11 @@ bool XM::File::save()
|
||||
|
||||
if(sampleHeaderSize > 18U) {
|
||||
seek(pos + 18);
|
||||
const unsigned int len = std::min(sampleHeaderSize - 18U, 22UL);
|
||||
const unsigned int len2 = std::min(sampleHeaderSize - 18U, 22UL);
|
||||
if(sampleNameIndex >= lines.size())
|
||||
writeString(String(), len);
|
||||
writeString(String(), len2);
|
||||
else
|
||||
writeString(lines[sampleNameIndex ++], len);
|
||||
writeString(lines[sampleNameIndex ++], len2);
|
||||
}
|
||||
}
|
||||
pos += sampleHeaderSize;
|
||||
@@ -560,10 +560,10 @@ void XM::File::read(bool)
|
||||
StructReader pattern;
|
||||
pattern.byte(packingType).u16L(rowCount).u16L(dataSize);
|
||||
|
||||
unsigned int count = pattern.read(*this, patternHeaderLength - 4U);
|
||||
READ_ASSERT(count == std::min(patternHeaderLength - 4U, (unsigned long)pattern.size()));
|
||||
unsigned int count2 = pattern.read(*this, patternHeaderLength - 4U);
|
||||
READ_ASSERT(count2 == std::min(patternHeaderLength - 4U, (unsigned long)pattern.size()));
|
||||
|
||||
seek(patternHeaderLength - (4 + count) + dataSize, Current);
|
||||
seek(patternHeaderLength - (4 + count2) + dataSize, Current);
|
||||
}
|
||||
|
||||
StringList intrumentNames;
|
||||
@@ -583,17 +583,17 @@ void XM::File::read(bool)
|
||||
instrument.string(instrumentName, 22).byte(instrumentType).u16L(sampleCount);
|
||||
|
||||
// 4 for instrumentHeaderSize
|
||||
unsigned int count = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
|
||||
READ_ASSERT(count == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
|
||||
unsigned int count2 = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
|
||||
READ_ASSERT(count2 == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
|
||||
|
||||
long offset = 0;
|
||||
if(sampleCount > 0) {
|
||||
unsigned long sampleHeaderSize = 0;
|
||||
sumSampleCount += sampleCount;
|
||||
// wouldn't know which header size to assume otherwise:
|
||||
READ_ASSERT(instrumentHeaderSize >= count + 4 && readU32L(sampleHeaderSize));
|
||||
READ_ASSERT(instrumentHeaderSize >= count2 + 4 && readU32L(sampleHeaderSize));
|
||||
// skip unhandled header proportion:
|
||||
seek(instrumentHeaderSize - count - 4, Current);
|
||||
seek(instrumentHeaderSize - count2 - 4, Current);
|
||||
|
||||
for(unsigned short j = 0; j < sampleCount; ++ j) {
|
||||
unsigned long sampleLength = 0;
|
||||
@@ -618,17 +618,17 @@ void XM::File::read(bool)
|
||||
.byte(compression)
|
||||
.string(sampleName, 22);
|
||||
|
||||
unsigned int count = sample.read(*this, sampleHeaderSize);
|
||||
READ_ASSERT(count == std::min(sampleHeaderSize, (unsigned long)sample.size()));
|
||||
unsigned int count3 = sample.read(*this, sampleHeaderSize);
|
||||
READ_ASSERT(count3 == std::min(sampleHeaderSize, (unsigned long)sample.size()));
|
||||
// skip unhandled header proportion:
|
||||
seek(sampleHeaderSize - count, Current);
|
||||
seek(sampleHeaderSize - count3, Current);
|
||||
|
||||
offset += sampleLength;
|
||||
sampleNames.append(sampleName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
offset = instrumentHeaderSize - count;
|
||||
offset = instrumentHeaderSize - count2;
|
||||
}
|
||||
intrumentNames.append(instrumentName);
|
||||
seek(offset, Current);
|
||||
|
||||
@@ -1,24 +1,7 @@
|
||||
# Strawberry Music Player
|
||||
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
#
|
||||
# Strawberry is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Strawberry is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
project(strawberry)
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
if(CMAKE_VERSION VERSION_GREATER 3.0)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckCXXSourceRuns)
|
||||
@@ -32,6 +15,8 @@ include(cmake/Rpm.cmake)
|
||||
include(cmake/Deb.cmake)
|
||||
include(cmake/Dmg.cmake)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
|
||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||
set(LINUX ON)
|
||||
endif()
|
||||
@@ -42,8 +27,46 @@ if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||
set(OPENBSD ON)
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
list(APPEND COMPILE_OPTIONS
|
||||
$<$<COMPILE_LANGUAGE:C>:--std=c99>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:--std=c++11>
|
||||
-U__STRICT_ANSI__
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wpedantic
|
||||
-Wunused
|
||||
-Wshadow
|
||||
-Wundef
|
||||
-Wuninitialized
|
||||
-Wredundant-decls
|
||||
-Wcast-align
|
||||
-Winit-self
|
||||
-Wmissing-include-dirs
|
||||
-Wmissing-declarations
|
||||
-Wstrict-overflow=2
|
||||
-Wunused-parameter
|
||||
-Wformat=2
|
||||
-Wdisabled-optimization
|
||||
-Wno-sign-conversion
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Woverloaded-virtual>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-Wno-old-style-cast>
|
||||
$<$<COMPILE_LANGUAGE:CXX>:-fpermissive>
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
list(APPEND COMPILE_OPTIONS -Wno-unused-parameter)
|
||||
endif()
|
||||
|
||||
option(BUILD_WERROR "Build with -Werror" OFF)
|
||||
if(BUILD_WERROR)
|
||||
list(APPEND COMPILE_OPTIONS -Werror)
|
||||
endif(BUILD_WERROR)
|
||||
|
||||
add_compile_options(${COMPILE_OPTIONS})
|
||||
|
||||
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
add_definitions(-DNDEBUG)
|
||||
@@ -98,7 +121,6 @@ pkg_check_modules(GSTREAMER_TAG gstreamer-tag-1.0)
|
||||
pkg_check_modules(GSTREAMER_PBUTILS gstreamer-pbutils-1.0)
|
||||
pkg_check_modules(LIBXINE libxine)
|
||||
pkg_check_modules(LIBVLC libvlc)
|
||||
pkg_check_modules(PHONON phonon4qt5)
|
||||
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.9)
|
||||
pkg_check_modules(LIBPULSE libpulse)
|
||||
pkg_check_modules(CHROMAPRINT libchromaprint)
|
||||
@@ -175,11 +197,10 @@ pkg_check_modules(TAGLIB taglib)
|
||||
# - Audio file detection by content.
|
||||
# - DSF and DSDIFF support
|
||||
#
|
||||
if (TAGLIB_VERSION VERSION_GREATER 1.11.1)
|
||||
option(USE_SYSTEM_TAGLIB "Use system taglib" ON)
|
||||
else()
|
||||
option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
|
||||
endif()
|
||||
# Some distros create their own version numbers for taglib so versions are not reliable anymore.
|
||||
# Force to use our own copy of taglib unless USE_SYSTEM_TAGLIB is set.
|
||||
|
||||
option(USE_SYSTEM_TAGLIB "Use system taglib" OFF)
|
||||
if (TAGLIB_FOUND AND USE_SYSTEM_TAGLIB)
|
||||
if (TAGLIB_VERSION VERSION_GREATER 1.11.1)
|
||||
message(STATUS "Using system taglib library")
|
||||
@@ -275,10 +296,6 @@ optional_component(VLC ON "Engine: VLC backend"
|
||||
DEPENDS "libvlc" LIBVLC_FOUND
|
||||
)
|
||||
|
||||
optional_component(PHONON OFF "Engine: Phonon backend (UNSTABLE)"
|
||||
DEPENDS "phonon4qt5" PHONON_FOUND
|
||||
)
|
||||
|
||||
optional_component(CHROMAPRINT ON "Chromaprint (Tag fetching from Musicbrainz)"
|
||||
DEPENDS "chromaprint" CHROMAPRINT_FOUND
|
||||
)
|
||||
@@ -330,6 +347,7 @@ optional_component(TRANSLATIONS ON "Translations"
|
||||
)
|
||||
|
||||
optional_component(SUBSONIC ON "Subsonic support")
|
||||
optional_component(TIDAL ON "Tidal support")
|
||||
|
||||
optional_component(MOODBAR ON "Moodbar"
|
||||
DEPENDS "fftw3" FFTW3_FOUND
|
||||
@@ -387,17 +405,14 @@ if(HAVE_XINE)
|
||||
XINE_ANALYZER)
|
||||
endif()
|
||||
|
||||
# Set up definitions and paths
|
||||
# Set up definitions
|
||||
|
||||
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
add_definitions(-DQT_STRICT_ITERATORS)
|
||||
add_definitions(-DQT_USE_QSTRINGBUILDER)
|
||||
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
|
||||
add_definitions(-DQT_NO_CAST_TO_ASCII -DQT_STRICT_ITERATORS)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS})
|
||||
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
||||
include_directories(${TAGLIB_INCLUDE_DIRS})
|
||||
add_definitions(-DQT_NO_CAST_TO_ASCII)
|
||||
|
||||
# Subdirectories
|
||||
add_subdirectory(src)
|
||||
@@ -421,8 +436,8 @@ add_custom_target(uninstall
|
||||
|
||||
# Show a summary of what we have enabled
|
||||
summary_show()
|
||||
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON)
|
||||
message(FATAL_ERROR "You need to have either GStreamer, Xine, VLC or Phonon to compile!")
|
||||
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC)
|
||||
message(FATAL_ERROR "You need to have either GStreamer, Xine or VLC to compile!")
|
||||
elseif(NOT HAVE_GSTREAMER)
|
||||
message(WARNING "GStreamer is the only engine that is fully implemented. Using other engines is possible but not recommended.")
|
||||
endif()
|
||||
|
||||
40
Changelog
@@ -2,6 +2,46 @@ Strawberry Music Player
|
||||
=======================
|
||||
ChangeLog
|
||||
|
||||
0.6.10:
|
||||
|
||||
Bugfixes:
|
||||
* Fixed Subsonic album covers not working for albums with non ASCII charcters.
|
||||
* Fixed reading date and genre from individual tracks in CUE sheets.
|
||||
* Fixed resume playback on startup for CUE songs.
|
||||
* Fixed album cover manager not showing complete album titles in the list of album covers.
|
||||
* Fixed save album cover to file saving "no cover" image instead of actual album cover.
|
||||
* Fixed device state text color in devices not being visible when using a dark theme.
|
||||
* Fixed engine and device in context using too large icons when icons were loaded from the system theme.
|
||||
* Fixed "Secure connection setup failed" problem on Windows when playing streams.
|
||||
* Fixed margin for song title text in context.
|
||||
* Fixed UNC paths with non ASCII charcters not working.
|
||||
|
||||
Enhancements:
|
||||
* Allowing all characters except slash and backslash when organising music unless options to strip characters is checked.
|
||||
* New option in organising music to remove problematic filename characters that removes less characters than the FAT option.
|
||||
* General improvements to the album cover loader and album cover providers code.
|
||||
* Fixed loading album cover images from album directory for songs added to the playlist from outside of the collection.
|
||||
* Made automatic album cover search work for songs outside of the collection and for streams.
|
||||
* Made album cover search work based on artist + title if album title is not present for providers supporting song/track search.
|
||||
* Update art manual in playlist for local files, devices and CDDA to avoid loading covers multiple times.
|
||||
* Made lyrics search work for streams.
|
||||
* Added "add stream" to menu.
|
||||
* Only showing song length in context when available.
|
||||
* Sort album cover search results by score and pick the best 3 first before trying others to improve album cover search speed.
|
||||
* Make scrobbler work for streams.
|
||||
* Added search for lyrics as a seperate option in context.
|
||||
* Made font and font sizes in context configurable.
|
||||
* Splitting artist and song title to the relevant metadata when artist and song title is sent as title seperated by a dash in streams.
|
||||
* Added label to show collection pixmap disk cache used in settings.
|
||||
* Icreased default collection pixmap disk cache to 360.
|
||||
|
||||
New features:
|
||||
* Added back Tidal streaming support.
|
||||
* Added Qobuz album cover provider.
|
||||
|
||||
Removed features:
|
||||
* Removed Phonon engine support.
|
||||
|
||||
Version 0.6.9:
|
||||
|
||||
BugFixes:
|
||||
|
||||
@@ -63,7 +63,7 @@ To build Strawberry from source you need the following installed on your system
|
||||
* [ALSA library (linux)](https://www.alsa-project.org/)
|
||||
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
|
||||
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
|
||||
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org), [VLC](https://www.videolan.org) or [Phonon](https://techbase.kde.org/Phonon)
|
||||
* [GStreamer](https://gstreamer.freedesktop.org/), [Xine](https://www.xine-project.org) or [VLC](https://www.videolan.org)
|
||||
* [GnuTLS](https://www.gnutls.org/)
|
||||
|
||||
Optional dependencies:
|
||||
@@ -74,7 +74,7 @@ Optional dependencies:
|
||||
* iPhone, iPod Touch, iPad and Apple TV devices: [libimobiledevice, libplist and libusbmuxd](https://www.libimobiledevice.org/)
|
||||
* Moodbar: [fftw3](http://www.fftw.org/)
|
||||
|
||||
Either GStreamer, Xine, VLC or Phonon engine is required, but only GStreamer is fully implemented so far.
|
||||
Either GStreamer, Xine 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.
|
||||
|
||||
### :wrench: Compiling from source
|
||||
|
||||
@@ -57,12 +57,12 @@ if (LSB_RELEASE_EXEC AND RPMBUILD_EXEC)
|
||||
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||
endif()
|
||||
message(STATUS "RPM Suffix: ${RPM_DISTRO}")
|
||||
configure_file(${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec.in ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec @ONLY)
|
||||
configure_file(${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec.in ${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec @ONLY)
|
||||
add_custom_target(rpm
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
|
||||
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
|
||||
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
|
||||
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/rpm/strawberry.spec
|
||||
COMMAND ${RPMBUILD_EXEC} -bs ${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec
|
||||
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/unix/strawberry.spec
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
9
cmake/Toolchain-i686-w64-mingw32-shared.cmake
Normal file
@@ -0,0 +1,9 @@
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(HOME "$ENV{HOME}")
|
||||
SET(CMAKE_C_COMPILER "${HOME}/mxe-shared/usr/bin/i686-w64-mingw32.shared-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "${HOME}/mxe-shared/usr/bin/i686-w64-mingw32.shared-g++")
|
||||
SET(CMAKE_RC_COMPILER "${HOME}/mxe-shared/usr/bin/i686-w64-mingw32.shared-windres")
|
||||
SET(CMAKE_FIND_ROOT_PATH "${HOME}/mxe-shared/usr/i686-w64-mingw32.shared/")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
9
cmake/Toolchain-x86_64-w64-mingw32-shared.cmake
Normal file
@@ -0,0 +1,9 @@
|
||||
SET(CMAKE_SYSTEM_NAME Windows)
|
||||
SET(HOME "$ENV{HOME}")
|
||||
SET(CMAKE_C_COMPILER "${HOME}/mxe-shared/usr/bin/x86_64-w64-mingw32.shared-gcc")
|
||||
SET(CMAKE_CXX_COMPILER "${HOME}/mxe-shared/usr/bin/x86_64-w64-mingw32.shared-g++")
|
||||
SET(CMAKE_RC_COMPILER "${HOME}/mxe-shared/usr/bin/x86_64-w64-mingw32.shared-windres")
|
||||
SET(CMAKE_FIND_ROOT_PATH "${HOME}/mxe-shared/usr/x86_64-w64-mingw32.shared/")
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
|
||||
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
|
||||
@@ -1,6 +1,6 @@
|
||||
set(STRAWBERRY_VERSION_MAJOR 0)
|
||||
set(STRAWBERRY_VERSION_MINOR 6)
|
||||
set(STRAWBERRY_VERSION_PATCH 9)
|
||||
set(STRAWBERRY_VERSION_PATCH 10)
|
||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||
|
||||
set(INCLUDE_GIT_REVISION OFF)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
<file>schema/schema-8.sql</file>
|
||||
<file>schema/schema-9.sql</file>
|
||||
<file>schema/schema-10.sql</file>
|
||||
<file>schema/schema-11.sql</file>
|
||||
<file>schema/schema-12.sql</file>
|
||||
<file>schema/device-schema.sql</file>
|
||||
<file>style/strawberry.css</file>
|
||||
<file>html/playing-tooltip-plain.html</file>
|
||||
@@ -40,5 +42,6 @@
|
||||
<file>pictures/rainbowdash.png</file>
|
||||
<file>fonts/HumongousofEternitySt.ttf</file>
|
||||
<file>mood/sample.mood</file>
|
||||
<file>text/ghosts.txt</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -89,6 +89,7 @@
|
||||
<file>icons/128x128/moodbar.png</file>
|
||||
<file>icons/128x128/love.png</file>
|
||||
<file>icons/128x128/subsonic.png</file>
|
||||
<file>icons/128x128/tidal.png</file>
|
||||
<file>icons/64x64/albums.png</file>
|
||||
<file>icons/64x64/alsa.png</file>
|
||||
<file>icons/64x64/application-exit.png</file>
|
||||
@@ -179,6 +180,7 @@
|
||||
<file>icons/64x64/moodbar.png</file>
|
||||
<file>icons/64x64/love.png</file>
|
||||
<file>icons/64x64/subsonic.png</file>
|
||||
<file>icons/64x64/tidal.png</file>
|
||||
<file>icons/48x48/albums.png</file>
|
||||
<file>icons/48x48/alsa.png</file>
|
||||
<file>icons/48x48/application-exit.png</file>
|
||||
@@ -201,6 +203,7 @@
|
||||
<file>icons/48x48/document-download.png</file>
|
||||
<file>icons/48x48/document-new.png</file>
|
||||
<file>icons/48x48/document-open-folder.png</file>
|
||||
<file>icons/48x48/document-open-remote.png</file>
|
||||
<file>icons/48x48/document-open.png</file>
|
||||
<file>icons/48x48/document-save.png</file>
|
||||
<file>icons/48x48/document-search.png</file>
|
||||
@@ -272,6 +275,7 @@
|
||||
<file>icons/48x48/moodbar.png</file>
|
||||
<file>icons/48x48/love.png</file>
|
||||
<file>icons/48x48/subsonic.png</file>
|
||||
<file>icons/48x48/tidal.png</file>
|
||||
<file>icons/32x32/albums.png</file>
|
||||
<file>icons/32x32/alsa.png</file>
|
||||
<file>icons/32x32/application-exit.png</file>
|
||||
@@ -294,6 +298,7 @@
|
||||
<file>icons/32x32/document-download.png</file>
|
||||
<file>icons/32x32/document-new.png</file>
|
||||
<file>icons/32x32/document-open-folder.png</file>
|
||||
<file>icons/32x32/document-open-remote.png</file>
|
||||
<file>icons/32x32/document-open.png</file>
|
||||
<file>icons/32x32/document-save.png</file>
|
||||
<file>icons/32x32/document-search.png</file>
|
||||
@@ -365,6 +370,7 @@
|
||||
<file>icons/32x32/moodbar.png</file>
|
||||
<file>icons/32x32/love.png</file>
|
||||
<file>icons/32x32/subsonic.png</file>
|
||||
<file>icons/32x32/tidal.png</file>
|
||||
<file>icons/22x22/albums.png</file>
|
||||
<file>icons/22x22/alsa.png</file>
|
||||
<file>icons/22x22/application-exit.png</file>
|
||||
@@ -387,6 +393,7 @@
|
||||
<file>icons/22x22/document-download.png</file>
|
||||
<file>icons/22x22/document-new.png</file>
|
||||
<file>icons/22x22/document-open-folder.png</file>
|
||||
<file>icons/22x22/document-open-remote.png</file>
|
||||
<file>icons/22x22/document-open.png</file>
|
||||
<file>icons/22x22/document-save.png</file>
|
||||
<file>icons/22x22/document-search.png</file>
|
||||
@@ -458,5 +465,6 @@
|
||||
<file>icons/22x22/moodbar.png</file>
|
||||
<file>icons/22x22/love.png</file>
|
||||
<file>icons/22x22/subsonic.png</file>
|
||||
<file>icons/22x22/tidal.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
BIN
data/icons/128x128/tidal.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
data/icons/22x22/document-open-remote.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
data/icons/22x22/tidal.png
Normal file
|
After Width: | Height: | Size: 933 B |
BIN
data/icons/32x32/document-open-remote.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
data/icons/32x32/tidal.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
data/icons/48x48/document-open-remote.png
Normal file
|
After Width: | Height: | Size: 3.3 KiB |
BIN
data/icons/48x48/tidal.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
data/icons/64x64/tidal.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
data/icons/full/tidal.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
@@ -11,25 +11,25 @@ CREATE TABLE device_%deviceid_subdirectories (
|
||||
|
||||
CREATE TABLE device_%deviceid_songs (
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
albumartist TEXT NOT NULL,
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT NOT NULL,
|
||||
compilation INTEGER NOT NULL DEFAULT -1,
|
||||
composer TEXT NOT NULL,
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id INTEGER NOT NULL DEFAULT -1,
|
||||
album_id TEXT NOT NULL,
|
||||
song_id INTEGER NOT NULL DEFAULT -1,
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
247
data/schema/schema-11.sql
Normal file
@@ -0,0 +1,247 @@
|
||||
DROP VIEW IF EXISTS duplicated_songs;
|
||||
|
||||
DROP INDEX IF EXISTS idx_url;
|
||||
|
||||
DROP INDEX IF EXISTS idx_comp_artist;
|
||||
|
||||
DROP INDEX IF EXISTS idx_albumartist;
|
||||
|
||||
DROP INDEX IF EXISTS idx_artist;
|
||||
|
||||
DROP INDEX IF EXISTS idx_album;
|
||||
|
||||
DROP INDEX IF EXISTS idx_title;
|
||||
|
||||
ALTER TABLE songs RENAME TO songs_old;
|
||||
|
||||
ALTER TABLE subsonic_songs RENAME TO subsonic_songs_old;
|
||||
|
||||
ALTER TABLE playlist_items RENAME TO playlist_items_old;
|
||||
|
||||
CREATE TABLE songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_url ON songs (url);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_comp_artist ON songs (compilation_effective, artist);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_albumartist ON songs (albumartist);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_artist ON songs (artist);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_album ON songs (album);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_title ON songs (title);
|
||||
|
||||
CREATE VIEW duplicated_songs as select artist dup_artist, album dup_album, title dup_title from songs as inner_songs where artist != '' and album != '' and title != '' and unavailable = 0 group by artist, album , title having count(*) > 1;
|
||||
|
||||
CREATE TABLE subsonic_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
INSERT INTO songs (ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path)
|
||||
SELECT ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path
|
||||
FROM songs_old;
|
||||
|
||||
DROP TABLE songs_old;
|
||||
|
||||
DELETE FROM songs_fts;
|
||||
|
||||
INSERT INTO songs_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
|
||||
FROM songs;
|
||||
|
||||
INSERT INTO subsonic_songs (ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path)
|
||||
SELECT ROWID, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path
|
||||
FROM subsonic_songs_old;
|
||||
|
||||
DROP TABLE subsonic_songs_old;
|
||||
|
||||
DELETE FROM subsonic_songs_fts;
|
||||
|
||||
INSERT INTO subsonic_songs_fts (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
|
||||
FROM subsonic_songs;
|
||||
|
||||
CREATE TABLE playlist_items (
|
||||
|
||||
playlist INTEGER NOT NULL,
|
||||
type INTEGER NOT NULL DEFAULT 0,
|
||||
collection_id INTEGER,
|
||||
playlist_url TEXT,
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER,
|
||||
disc INTEGER,
|
||||
year INTEGER,
|
||||
originalyear INTEGER,
|
||||
genre TEXT,
|
||||
compilation INTEGER DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER,
|
||||
length INTEGER,
|
||||
|
||||
bitrate INTEGER,
|
||||
samplerate INTEGER,
|
||||
bitdepth INTEGER,
|
||||
|
||||
source INTEGER,
|
||||
directory_id INTEGER,
|
||||
url TEXT,
|
||||
filetype INTEGER,
|
||||
filesize INTEGER,
|
||||
mtime INTEGER,
|
||||
ctime INTEGER,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER DEFAULT 0,
|
||||
skipcount INTEGER DEFAULT 0,
|
||||
lastplayed INTEGER DEFAULT 0,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER DEFAULT 0,
|
||||
compilation_off INTEGER DEFAULT 0,
|
||||
compilation_effective INTEGER DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
INSERT INTO playlist_items (ROWID, playlist, type, collection_id, playlist_url, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path)
|
||||
SELECT ROWID, playlist, type, collection_id, playlist_url, title, album, artist, albumartist, track, disc, year, originalyear, genre, compilation, composer, performer, grouping, comment, lyrics, artist_id, album_id, song_id, beginning, length, bitrate, samplerate, bitdepth, source, directory_id, url, filetype, filesize, mtime, ctime, unavailable, playcount, skipcount, lastplayed, compilation_detected, compilation_on, compilation_off, compilation_effective, art_automatic, art_manual, effective_albumartist, effective_originalyear, cue_path
|
||||
FROM playlist_items_old;
|
||||
|
||||
DROP TABLE playlist_items_old;
|
||||
|
||||
DELETE FROM playlist_items_fts_;
|
||||
|
||||
INSERT INTO playlist_items_fts_ (ROWID, ftstitle, ftsalbum, ftsartist, ftsalbumartist, ftscomposer, ftsperformer, ftsgrouping, ftsgenre, ftscomment)
|
||||
SELECT ROWID, title, album, artist, albumartist, composer, performer, grouping, genre, comment
|
||||
FROM playlist_items;
|
||||
|
||||
UPDATE schema_version SET version=11;
|
||||
217
data/schema/schema-12.sql
Normal file
@@ -0,0 +1,217 @@
|
||||
CREATE TABLE IF NOT EXISTS tidal_artists_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tidal_albums_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tidal_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 0"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 0"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 0"
|
||||
|
||||
);
|
||||
|
||||
UPDATE schema_version SET version=12;
|
||||
@@ -4,7 +4,7 @@ CREATE TABLE IF NOT EXISTS schema_version (
|
||||
|
||||
DELETE FROM schema_version;
|
||||
|
||||
INSERT INTO schema_version (version) VALUES (10);
|
||||
INSERT INTO schema_version (version) VALUES (12);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS directories (
|
||||
path TEXT NOT NULL,
|
||||
@@ -19,25 +19,196 @@ CREATE TABLE IF NOT EXISTS subdirectories (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS songs (
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
albumartist TEXT NOT NULL,
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT NOT NULL,
|
||||
compilation INTEGER NOT NULL DEFAULT -1,
|
||||
composer TEXT NOT NULL,
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id INTEGER NOT NULL DEFAULT -1,
|
||||
album_id TEXT NOT NULL,
|
||||
song_id INTEGER NOT NULL DEFAULT -1,
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tidal_artists_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tidal_albums_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
directory_id INTEGER NOT NULL DEFAULT -1,
|
||||
url TEXT NOT NULL,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filesize INTEGER NOT NULL DEFAULT -1,
|
||||
mtime INTEGER NOT NULL DEFAULT -1,
|
||||
ctime INTEGER NOT NULL DEFAULT -1,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS tidal_songs (
|
||||
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -76,25 +247,25 @@ CREATE TABLE IF NOT EXISTS songs (
|
||||
|
||||
CREATE TABLE IF NOT EXISTS subsonic_songs (
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
albumartist TEXT NOT NULL,
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT NOT NULL,
|
||||
compilation INTEGER NOT NULL DEFAULT -1,
|
||||
composer TEXT NOT NULL,
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
genre TEXT,
|
||||
compilation INTEGER NOT NULL DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id INTEGER NOT NULL DEFAULT -1,
|
||||
album_id TEXT NOT NULL,
|
||||
song_id INTEGER NOT NULL DEFAULT -1,
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
@@ -149,56 +320,56 @@ CREATE TABLE IF NOT EXISTS playlist_items (
|
||||
collection_id INTEGER,
|
||||
playlist_url TEXT,
|
||||
|
||||
title TEXT NOT NULL,
|
||||
album TEXT NOT NULL,
|
||||
artist TEXT NOT NULL,
|
||||
albumartist TEXT NOT NULL,
|
||||
track INTEGER NOT NULL DEFAULT -1,
|
||||
disc INTEGER NOT NULL DEFAULT -1,
|
||||
year INTEGER NOT NULL DEFAULT -1,
|
||||
originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
genre TEXT NOT NULL,
|
||||
compilation INTEGER NOT NULL DEFAULT -1,
|
||||
composer TEXT NOT NULL,
|
||||
performer TEXT NOT NULL,
|
||||
grouping TEXT NOT NULL,
|
||||
comment TEXT NOT NULL,
|
||||
lyrics TEXT NOT NULL,
|
||||
title TEXT,
|
||||
album TEXT,
|
||||
artist TEXT,
|
||||
albumartist TEXT,
|
||||
track INTEGER,
|
||||
disc INTEGER,
|
||||
year INTEGER,
|
||||
originalyear INTEGER,
|
||||
genre TEXT,
|
||||
compilation INTEGER DEFAULT 0,
|
||||
composer TEXT,
|
||||
performer TEXT,
|
||||
grouping TEXT,
|
||||
comment TEXT,
|
||||
lyrics TEXT,
|
||||
|
||||
artist_id INTEGER NOT NULL DEFAULT -1,
|
||||
album_id TEXT NOT NULL,
|
||||
song_id INTEGER NOT NULL DEFAULT -1,
|
||||
artist_id TEXT,
|
||||
album_id TEXT,
|
||||
song_id TEXT,
|
||||
|
||||
beginning INTEGER NOT NULL DEFAULT 0,
|
||||
length INTEGER NOT NULL DEFAULT 0,
|
||||
beginning INTEGER,
|
||||
length INTEGER,
|
||||
|
||||
bitrate INTEGER NOT NULL DEFAULT -1,
|
||||
samplerate INTEGER NOT NULL DEFAULT -1,
|
||||
bitdepth INTEGER NOT NULL DEFAULT -1,
|
||||
bitrate INTEGER,
|
||||
samplerate INTEGER,
|
||||
bitdepth INTEGER,
|
||||
|
||||
source INTEGER NOT NULL DEFAULT 0,
|
||||
source INTEGER,
|
||||
directory_id INTEGER,
|
||||
url TEXT,
|
||||
filetype INTEGER NOT NULL DEFAULT 0,
|
||||
filetype INTEGER,
|
||||
filesize INTEGER,
|
||||
mtime INTEGER,
|
||||
ctime INTEGER,
|
||||
unavailable INTEGER DEFAULT 0,
|
||||
|
||||
playcount INTEGER NOT NULL DEFAULT 0,
|
||||
skipcount INTEGER NOT NULL DEFAULT 0,
|
||||
lastplayed INTEGER NOT NULL DEFAULT -1,
|
||||
playcount INTEGER DEFAULT 0,
|
||||
skipcount INTEGER DEFAULT 0,
|
||||
lastplayed INTEGER DEFAULT 0,
|
||||
|
||||
compilation_detected INTEGER DEFAULT 0,
|
||||
compilation_on INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_off INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_effective INTEGER NOT NULL DEFAULT 0,
|
||||
compilation_on INTEGER DEFAULT 0,
|
||||
compilation_off INTEGER DEFAULT 0,
|
||||
compilation_effective INTEGER DEFAULT 0,
|
||||
|
||||
art_automatic TEXT,
|
||||
art_manual TEXT,
|
||||
|
||||
effective_albumartist TEXT,
|
||||
effective_originalyear INTEGER NOT NULL DEFAULT 0,
|
||||
effective_originalyear INTEGER,
|
||||
|
||||
cue_path TEXT
|
||||
|
||||
@@ -243,6 +414,51 @@ CREATE VIRTUAL TABLE IF NOT EXISTS songs_fts USING fts5(
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_artists_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 0"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_albums_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 0"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS tidal_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
ftsalbum,
|
||||
ftsartist,
|
||||
ftsalbumartist,
|
||||
ftscomposer,
|
||||
ftsperformer,
|
||||
ftsgrouping,
|
||||
ftsgenre,
|
||||
ftscomment,
|
||||
tokenize = "unicode61 remove_diacritics 0"
|
||||
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS subsonic_songs_fts USING fts5(
|
||||
|
||||
ftstitle,
|
||||
|
||||
42
data/text/ghosts.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
Go to sleep my babies
|
||||
Don't you wake up
|
||||
The stars will keep you company
|
||||
So close your eyes
|
||||
Old Uncle Moon will shine his dearest sweetest dreams
|
||||
And hold you in your arms
|
||||
Until the morning comes.
|
||||
|
||||
Night Light
|
||||
|
||||
Dark the night, not a sound
|
||||
Damp and cold, frosty ground
|
||||
Above your head the lion screams
|
||||
To tear you from your moonlit dreams.
|
||||
Damp with sweat, mouth is dry
|
||||
Twisted branches catch the eye
|
||||
Beside your bed the angel stands
|
||||
You cannot touch his withered hands.
|
||||
|
||||
Guardian Angel
|
||||
|
||||
As the lion's eyes dance before me
|
||||
They are kindly yet bloody red
|
||||
I can see that he is smiling
|
||||
But I cannot live inside his head.
|
||||
There the needle stands before me
|
||||
I climb inside it towards the light
|
||||
Where the angel stands in glory
|
||||
His sword of peace defends the night.
|
||||
So the world is spread before
|
||||
As I fly high on angel wings
|
||||
But the angel is deceiving
|
||||
For he is weeping as he sings.
|
||||
|
||||
Night Light (continued)
|
||||
|
||||
Early birds, morning breeze
|
||||
Spinning leaves, sleepy trees
|
||||
Gently tap the window pane
|
||||
It's good to see the sun again.
|
||||
|
||||
(Dave Cousins)
|
||||
2
debian/copyright
vendored
@@ -34,8 +34,6 @@ Files: src/core/main.h
|
||||
src/engine/devicefinder.h
|
||||
src/engine/enginedevice.cpp
|
||||
src/engine/enginedevice.h
|
||||
src/engine/phononengine.cpp
|
||||
src/engine/phononengine.h
|
||||
src/internet/internetservice.cpp
|
||||
src/internet/internetservice.h
|
||||
src/internet/internettabsview.cpp
|
||||
|
||||
4
debian/rules
vendored
@@ -6,8 +6,8 @@
|
||||
override_dh_auto_clean:
|
||||
rm -f dist/macos/Info.plist
|
||||
rm -f dist/macos/create-dmg.sh
|
||||
rm -f dist/pacman/PKGBUILD
|
||||
rm -f dist/rpm/strawberry.spec
|
||||
rm -f dist/unix/PKGBUILD
|
||||
rm -f dist/unix/strawberry.spec
|
||||
rm -f dist/scripts/maketarball.sh
|
||||
rm -f dist/windows/strawberry.nsi
|
||||
rm -f src/translations/translations.pot
|
||||
|
||||
4
dist/CMakeLists.txt
vendored
@@ -1,5 +1,5 @@
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/pacman/PKGBUILD @ONLY)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD.in ${CMAKE_CURRENT_SOURCE_DIR}/unix/PKGBUILD @ONLY)
|
||||
|
||||
if (APPLE)
|
||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
|
||||
@@ -16,7 +16,7 @@ if (UNIX AND NOT APPLE)
|
||||
install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/)
|
||||
install(FILES unix/org.strawberrymusicplayer.strawberry.desktop DESTINATION share/applications)
|
||||
install(FILES unix/org.strawberrymusicplayer.strawberry.appdata.xml DESTINATION share/metainfo)
|
||||
install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1)
|
||||
install(FILES unix/strawberry.1 unix/strawberry-tagreader.1 DESTINATION share/man/man1)
|
||||
endif (UNIX AND NOT APPLE)
|
||||
|
||||
if (APPLE)
|
||||
|
||||
2
dist/scripts/maketarball.sh.in
vendored
@@ -36,7 +36,7 @@ tar -cJf $name-$version.tar.xz \
|
||||
--exclude="$root/.zanata-cache" \
|
||||
--exclude="$root/debian/changelog" \
|
||||
--exclude="$root/dist/scripts/maketarball.sh" \
|
||||
--exclude="$root/dist/pacman/PKGBUILD" \
|
||||
--exclude="$root/dist/unix/PKGBUILD" \
|
||||
--exclude="$root/dist/macos/create-dmg.sh" \
|
||||
--exclude="$root/dist/macos/Info.plist" \
|
||||
--exclude="$root/dist/windows/windres.rc" \
|
||||
|
||||
@@ -32,7 +32,6 @@ depends=(
|
||||
libusbmuxd
|
||||
libplist
|
||||
libimobiledevice
|
||||
phonon-qt5
|
||||
fftw
|
||||
)
|
||||
optdepends=(
|
||||
@@ -54,7 +53,6 @@ build() {
|
||||
cmake ../${pkgname}-@STRAWBERRY_VERSION_PACKAGE@ \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DUSE_SYSTEM_TAGLIB=ON \
|
||||
-DENABLE_PHONON=ON \
|
||||
-DENABLE_TRANSLATIONS=ON
|
||||
make -j$(nproc)
|
||||
}
|
||||
@@ -10,5 +10,5 @@ Icon=strawberry
|
||||
Terminal=false
|
||||
Categories=AudioVideo;Player;Qt;Audio;
|
||||
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
|
||||
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
|
||||
|
||||
2
dist/windows/strawberry.nsi.in
vendored
@@ -201,7 +201,7 @@ Section "Strawberry" Strawberry
|
||||
File "libspeex-1.dll"
|
||||
File "libsqlite3-0.dll"
|
||||
File "libstdc++-6.dll"
|
||||
;File "libtag.dll"
|
||||
File "libtag.dll"
|
||||
File "libunistring-2.dll"
|
||||
File "libvorbis-0.dll"
|
||||
File "libvorbisenc-2.dll"
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS})
|
||||
include_directories(${GOBJECT_INCLUDE_DIRS})
|
||||
include_directories(${GSTREAMER_INCLUDE_DIRS})
|
||||
|
||||
@@ -1,13 +1,7 @@
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
endif()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
@@ -17,6 +11,8 @@ if (Backtrace_FOUND)
|
||||
include_directories(${Backtrace_INCLUDE_DIRS})
|
||||
endif(Backtrace_FOUND)
|
||||
|
||||
include_directories(${GLIB_INCLUDE_DIRS})
|
||||
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
|
||||
set(SOURCES
|
||||
@@ -41,18 +37,11 @@ endif(APPLE)
|
||||
|
||||
qt5_wrap_cpp(MOC ${HEADERS})
|
||||
|
||||
add_library(libstrawberry-common STATIC
|
||||
${SOURCES}
|
||||
${MOC}
|
||||
)
|
||||
add_library(libstrawberry-common STATIC ${SOURCES} ${MOC})
|
||||
|
||||
if (Backtrace_FOUND)
|
||||
if(Backtrace_FOUND)
|
||||
target_link_libraries(libstrawberry-common ${Backtrace_LIBRARIES})
|
||||
endif (Backtrace_FOUND)
|
||||
|
||||
target_link_libraries(libstrawberry-common
|
||||
${TAGLIB_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
endif(Backtrace_FOUND)
|
||||
|
||||
target_link_libraries(libstrawberry-common ${TAGLIB_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(libstrawberry-common Qt5::Core Qt5::Network)
|
||||
|
||||
@@ -273,6 +273,8 @@ static T CreateLogger(Level level, const QString &class_name, int line, const ch
|
||||
return ret.space();
|
||||
}
|
||||
|
||||
QString CXXDemangle(const QString &mangled_function);
|
||||
|
||||
QString CXXDemangle(const QString &mangled_function) {
|
||||
|
||||
int status;
|
||||
@@ -286,6 +288,8 @@ QString CXXDemangle(const QString &mangled_function) {
|
||||
|
||||
}
|
||||
|
||||
QString DarwinDemangle(const QString &symbol);
|
||||
|
||||
QString DarwinDemangle(const QString &symbol) {
|
||||
|
||||
QStringList split = symbol.split(' ', QString::SkipEmptyParts);
|
||||
@@ -294,6 +298,8 @@ QString DarwinDemangle(const QString &symbol) {
|
||||
|
||||
}
|
||||
|
||||
QString LinuxDemangle(const QString &symbol);
|
||||
|
||||
QString LinuxDemangle(const QString &symbol) {
|
||||
|
||||
QRegExp regex("\\(([^+]+)");
|
||||
@@ -305,6 +311,8 @@ QString LinuxDemangle(const QString &symbol) {
|
||||
|
||||
}
|
||||
|
||||
QString DemangleSymbol(const QString &symbol);
|
||||
|
||||
QString DemangleSymbol(const QString &symbol) {
|
||||
#ifdef Q_OS_MACOS
|
||||
return DarwinDemangle(symbol);
|
||||
|
||||
@@ -47,13 +47,13 @@ void _MessageHandlerBase::SetDevice(QIODevice *device) {
|
||||
connect(device, SIGNAL(readyRead()), SLOT(DeviceReadyRead()));
|
||||
|
||||
// Yeah I know.
|
||||
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(device)) {
|
||||
if (QAbstractSocket *abstractsocket = qobject_cast<QAbstractSocket*>(device)) {
|
||||
flush_abstract_socket_ = &QAbstractSocket::flush;
|
||||
connect(socket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
|
||||
connect(abstractsocket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
|
||||
}
|
||||
else if (QLocalSocket* socket = qobject_cast<QLocalSocket*>(device)) {
|
||||
else if (QLocalSocket *localsocket = qobject_cast<QLocalSocket*>(device)) {
|
||||
flush_local_socket_ = &QLocalSocket::flush;
|
||||
connect(socket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
|
||||
connect(localsocket, SIGNAL(disconnected()), SLOT(DeviceClosed()));
|
||||
}
|
||||
else {
|
||||
qFatal("Unsupported device type passed to _MessageHandlerBase");
|
||||
|
||||
@@ -26,13 +26,16 @@ _MessageReplyBase::_MessageReplyBase(QObject *parent)
|
||||
: QObject(parent), finished_(false), success_(false) {}
|
||||
|
||||
bool _MessageReplyBase::WaitForFinished() {
|
||||
|
||||
qLog(Debug) << "Waiting on ID" << id();
|
||||
semaphore_.acquire();
|
||||
qLog(Debug) << "Acquired ID" << id();
|
||||
return success_;
|
||||
|
||||
}
|
||||
|
||||
void _MessageReplyBase::Abort() {
|
||||
|
||||
Q_ASSERT(!finished_);
|
||||
finished_ = true;
|
||||
success_ = false;
|
||||
@@ -40,4 +43,5 @@ void _MessageReplyBase::Abort() {
|
||||
emit Finished(success_);
|
||||
qLog(Debug) << "Releasing ID" << id() << "(aborted)";
|
||||
semaphore_.release();
|
||||
|
||||
}
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
@@ -12,31 +6,16 @@ include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
include_directories(${CMAKE_BINARY_DIR}/src)
|
||||
|
||||
link_directories(${PROTOBUF_LIBRARY_DIRS})
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
|
||||
set(MESSAGES
|
||||
tagreadermessages.proto
|
||||
)
|
||||
link_directories(${TAGLIB_LIBRARY_DIRS})
|
||||
include_directories(${TAGLIB_INCLUDE_DIRS})
|
||||
|
||||
set(SOURCES
|
||||
fmpsparser.cpp
|
||||
tagreader.cpp
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
)
|
||||
|
||||
qt5_wrap_cpp(MOC ${HEADERS})
|
||||
set(MESSAGES tagreadermessages.proto)
|
||||
set(SOURCES fmpsparser.cpp tagreader.cpp)
|
||||
|
||||
protobuf_generate_cpp(PROTO_SOURCES PROTO_HEADERS ${MESSAGES})
|
||||
|
||||
add_library(libstrawberry-tagreader STATIC
|
||||
${PROTO_SOURCES}
|
||||
${SOURCES}
|
||||
${MOC}
|
||||
)
|
||||
|
||||
target_link_libraries(libstrawberry-tagreader
|
||||
${PROTOBUF_LIBRARY}
|
||||
libstrawberry-common
|
||||
)
|
||||
add_library(libstrawberry-tagreader STATIC ${PROTO_SOURCES} ${SOURCES})
|
||||
target_link_libraries(libstrawberry-tagreader ${PROTOBUF_LIBRARY} libstrawberry-common)
|
||||
|
||||
@@ -212,46 +212,46 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
|
||||
// Handle all the files which have VorbisComments (Ogg, OPUS, ...) in the same way;
|
||||
// apart, so we keep specific behavior for some formats by adding another "else if" block below.
|
||||
if (TagLib::Ogg::XiphComment *tag = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
|
||||
ParseOggTag(tag->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
if (!tag->pictureList().isEmpty()) {
|
||||
if (TagLib::Ogg::XiphComment *tag_ogg = dynamic_cast<TagLib::Ogg::XiphComment*>(fileref->file()->tag())) {
|
||||
ParseOggTag(tag_ogg->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
if (!tag_ogg->pictureList().isEmpty()) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
}
|
||||
}
|
||||
|
||||
if (TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>(fileref->file())) {
|
||||
if (TagLib::FLAC::File *file_flac = dynamic_cast<TagLib::FLAC::File *>(fileref->file())) {
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
song->set_bitdepth(file_flac->audioProperties()->bitsPerSample());
|
||||
|
||||
if (file->xiphComment()) {
|
||||
ParseOggTag(file->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
if (!file->pictureList().isEmpty()) {
|
||||
if (file_flac->xiphComment()) {
|
||||
ParseOggTag(file_flac->xiphComment()->fieldListMap(), nullptr, &disc, &compilation, song);
|
||||
if (!file_flac->pictureList().isEmpty()) {
|
||||
song->set_art_automatic(kEmbeddedCover);
|
||||
}
|
||||
}
|
||||
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
|
||||
else if (TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File *>(fileref->file())) {
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
if (file->tag()) {
|
||||
ParseAPETag(file->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
|
||||
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File *>(fileref->file())) {
|
||||
song->set_bitdepth(file_wavpack->audioProperties()->bitsPerSample());
|
||||
if (file_wavpack->tag()) {
|
||||
ParseAPETag(file_wavpack->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
|
||||
}
|
||||
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
|
||||
else if (TagLib::APE::File *file = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
||||
if (file->tag()) {
|
||||
ParseAPETag(file->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
|
||||
else if (TagLib::APE::File *file_ape = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
||||
if (file_ape->tag()) {
|
||||
ParseAPETag(file_ape->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
|
||||
}
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
song->set_bitdepth(file_ape->audioProperties()->bitsPerSample());
|
||||
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
|
||||
else if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
|
||||
if (file->ID3v2Tag()) {
|
||||
const TagLib::ID3v2::FrameListMap &map = file->ID3v2Tag()->frameListMap();
|
||||
if (file_mpeg->ID3v2Tag()) {
|
||||
const TagLib::ID3v2::FrameListMap &map = file_mpeg->ID3v2Tag()->frameListMap();
|
||||
|
||||
if (!map["TPOS"].isEmpty()) disc = TStringToQString(map["TPOS"].front()->toString()).trimmed();
|
||||
if (!map["TCOM"].isEmpty()) Decode(map["TCOM"].front()->toString(), nullptr, song->mutable_composer());
|
||||
@@ -309,12 +309,12 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
}
|
||||
}
|
||||
|
||||
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
||||
else if (TagLib::MP4::File *file_mp4 = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
song->set_bitdepth(file_mp4->audioProperties()->bitsPerSample());
|
||||
|
||||
if (file->tag()) {
|
||||
TagLib::MP4::Tag *mp4_tag = file->tag();
|
||||
if (file_mp4->tag()) {
|
||||
TagLib::MP4::Tag *mp4_tag = file_mp4->tag();
|
||||
|
||||
// Find album artists
|
||||
if (mp4_tag->item("aART").isValid()) {
|
||||
@@ -348,11 +348,11 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
}
|
||||
}
|
||||
|
||||
else if (TagLib::ASF::File *file = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
|
||||
else if (TagLib::ASF::File *file_asf = dynamic_cast<TagLib::ASF::File*>(fileref->file())) {
|
||||
|
||||
song->set_bitdepth(file->audioProperties()->bitsPerSample());
|
||||
song->set_bitdepth(file_asf->audioProperties()->bitsPerSample());
|
||||
|
||||
const TagLib::ASF::AttributeListMap &attributes_map = file->tag()->attributeListMap();
|
||||
const TagLib::ASF::AttributeListMap &attributes_map = file_asf->tag()->attributeListMap();
|
||||
|
||||
if (attributes_map.contains(kASF_OriginalDate_ID)) {
|
||||
const TagLib::ASF::AttributeList &attributes = attributes_map[kASF_OriginalDate_ID];
|
||||
@@ -368,9 +368,9 @@ void TagReader::ReadFile(const QString &filename, pb::tagreader::SongMetadata *s
|
||||
}
|
||||
}
|
||||
|
||||
else if (TagLib::MPC::File* file = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
|
||||
if (file->tag()) {
|
||||
ParseAPETag(file->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
|
||||
else if (TagLib::MPC::File* file_mpc = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
|
||||
if (file_mpc->tag()) {
|
||||
ParseAPETag(file_mpc->APETag()->itemListMap(), nullptr, &disc, &compilation, song);
|
||||
}
|
||||
if (tag) Decode(tag->comment(), nullptr, song->mutable_comment());
|
||||
}
|
||||
@@ -578,26 +578,26 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
|
||||
SetVorbisComments(tag, song);
|
||||
}
|
||||
|
||||
else if (TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file->APETag(true);
|
||||
else if (TagLib::WavPack::File *file_wavpack = dynamic_cast<TagLib::WavPack::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file_wavpack->APETag(true);
|
||||
if (!tag) return false;
|
||||
SaveAPETag(tag, song);
|
||||
}
|
||||
|
||||
else if (TagLib::APE::File *file = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file->APETag(true);
|
||||
else if (TagLib::APE::File *file_ape = dynamic_cast<TagLib::APE::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file_ape->APETag(true);
|
||||
if (!tag) return false;
|
||||
SaveAPETag(tag, song);
|
||||
}
|
||||
|
||||
else if (TagLib::MPC::File *file = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file->APETag(true);
|
||||
else if (TagLib::MPC::File *file_mpc = dynamic_cast<TagLib::MPC::File*>(fileref->file())) {
|
||||
TagLib::APE::Tag *tag = file_mpc->APETag(true);
|
||||
if (!tag) return false;
|
||||
SaveAPETag(tag, song);
|
||||
}
|
||||
|
||||
else if (TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
TagLib::ID3v2::Tag *tag = file->ID3v2Tag(true);
|
||||
else if (TagLib::MPEG::File *file_mpeg = dynamic_cast<TagLib::MPEG::File*>(fileref->file())) {
|
||||
TagLib::ID3v2::Tag *tag = file_mpeg->ID3v2Tag(true);
|
||||
if (!tag) return false;
|
||||
SetTextFrame("TPOS", song.disc() <= 0 -1 ? QString() : QString::number(song.disc()), tag);
|
||||
SetTextFrame("TCOM", song.composer(), tag);
|
||||
@@ -609,8 +609,8 @@ bool TagReader::SaveFile(const QString &filename, const pb::tagreader::SongMetad
|
||||
SetUnsyncLyricsFrame(song.lyrics(), tag);
|
||||
}
|
||||
|
||||
else if (TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
||||
TagLib::MP4::Tag *tag = file->tag();
|
||||
else if (TagLib::MP4::File *file_mp4 = dynamic_cast<TagLib::MP4::File*>(fileref->file())) {
|
||||
TagLib::MP4::Tag *tag = file_mp4->tag();
|
||||
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("\251grp", TagLib::StringList(song.grouping().c_str()));
|
||||
|
||||
@@ -26,28 +26,18 @@
|
||||
#include <QByteArray>
|
||||
#include <QString>
|
||||
|
||||
#include <taglib/tstring.h>
|
||||
#include <taglib/fileref.h>
|
||||
#include <taglib/xiphcomment.h>
|
||||
#include <taglib/apetag.h>
|
||||
#include <taglib/apefile.h>
|
||||
#include <taglib/id3v2tag.h>
|
||||
|
||||
#include "tagreadermessages.pb.h"
|
||||
|
||||
class QTextCodec;
|
||||
|
||||
#ifndef USE_SYSTEM_TAGLIB
|
||||
namespace Strawberry_TagLib {
|
||||
#endif
|
||||
namespace TagLib {
|
||||
class FileRef;
|
||||
class String;
|
||||
|
||||
namespace ID3v2 {
|
||||
class Tag;
|
||||
class PopularimeterFrame;
|
||||
}
|
||||
}
|
||||
#ifndef USE_SYSTEM_TAGLIB
|
||||
}
|
||||
using namespace Strawberry_TagLib;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
|
||||
@@ -7,29 +8,20 @@ include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/src)
|
||||
include_directories(${CMAKE_BINARY_DIR}/src)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
|
||||
link_directories(${PROTOBUF_LIBRARY_DIRS})
|
||||
include_directories(${PROTOBUF_INCLUDE_DIRS})
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
endif()
|
||||
link_directories(${TAGLIB_LIBRARY_DIRS})
|
||||
include_directories(${TAGLIB_INCLUDE_DIRS})
|
||||
|
||||
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR})
|
||||
|
||||
set(SOURCES
|
||||
main.cpp
|
||||
tagreaderworker.cpp
|
||||
)
|
||||
set(SOURCES main.cpp tagreaderworker.cpp)
|
||||
|
||||
qt5_wrap_cpp(MOC ${HEADERS})
|
||||
qt5_add_resources(QRC data/data.qrc)
|
||||
|
||||
add_executable(strawberry-tagreader
|
||||
${SOURCES}
|
||||
${MOC}
|
||||
${QRC}
|
||||
)
|
||||
add_executable(strawberry-tagreader ${SOURCES} ${MOC} ${QRC})
|
||||
|
||||
target_link_libraries(strawberry-tagreader
|
||||
${TAGLIB_LIBRARIES}
|
||||
@@ -40,16 +32,11 @@ target_link_libraries(strawberry-tagreader
|
||||
)
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
target_link_libraries(strawberry-tagreader
|
||||
execinfo
|
||||
)
|
||||
target_link_libraries(strawberry-tagreader execinfo)
|
||||
endif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
|
||||
|
||||
if(APPLE)
|
||||
target_link_libraries(strawberry-tagreader
|
||||
/System/Library/Frameworks/Foundation.framework
|
||||
)
|
||||
target_link_libraries(strawberry-tagreader /System/Library/Frameworks/Foundation.framework)
|
||||
endif(APPLE)
|
||||
|
||||
|
||||
install(TARGETS strawberry-tagreader RUNTIME DESTINATION bin)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: strawberry
|
||||
version: '0.6.8+git'
|
||||
version: '0.6.10+git'
|
||||
summary: music player and collection organizer
|
||||
description: |
|
||||
Strawberry is a music player and collection organizer.
|
||||
|
||||
@@ -1,49 +1,16 @@
|
||||
# Strawberry Music Player
|
||||
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||
#
|
||||
# Strawberry is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Strawberry is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++11 -U__STRICT_ANSI__ -Wall -Wextra -Wpedantic -Woverloaded-virtual -fpermissive")
|
||||
|
||||
if(APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter")
|
||||
endif()
|
||||
|
||||
option(BUILD_WERROR "Build with -Werror" OFF)
|
||||
|
||||
if(BUILD_WERROR)
|
||||
if (LINUX)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||
endif (LINUX)
|
||||
endif(BUILD_WERROR)
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
|
||||
if(HAVE_TRANSLATIONS)
|
||||
include(../cmake/Translations.cmake)
|
||||
endif(HAVE_TRANSLATIONS)
|
||||
|
||||
# Set up definitions and paths
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-tagreader)
|
||||
include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
|
||||
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
add_definitions(-DQT_USE_QSTRINGBUILDER)
|
||||
add_definitions(-DQT_NO_URL_CAST_FROM_STRING)
|
||||
add_definitions(-DBOOST_BIND_NO_PLACEHOLDERS)
|
||||
|
||||
include_directories(${CMAKE_BINARY_DIR})
|
||||
include_directories(${Boost_INCLUDE_DIRS})
|
||||
include_directories(${GLIBCONFIG_INCLUDE_DIRS})
|
||||
include_directories(${GLIB_INCLUDE_DIRS})
|
||||
@@ -69,10 +36,6 @@ if(HAVE_GSTREAMER)
|
||||
include_directories(${GSTREAMER_PBUTILS_INCLUDE_DIRS})
|
||||
endif(HAVE_GSTREAMER)
|
||||
|
||||
if(HAVE_PHONON)
|
||||
include_directories(${PHONON_INCLUDE_DIRS})
|
||||
endif(HAVE_PHONON)
|
||||
|
||||
if(HAVE_CHROMAPRINT)
|
||||
link_directories(${CHROMAPRINT_LIBRARY_DIRS})
|
||||
include_directories(${CHROMAPRINT_INCLUDE_DIRS})
|
||||
@@ -96,10 +59,6 @@ if(HAVE_LIBMTP)
|
||||
include_directories(${LIBMTP_INCLUDE_DIRS})
|
||||
endif(HAVE_LIBMTP)
|
||||
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-common)
|
||||
include_directories(${CMAKE_SOURCE_DIR}/ext/libstrawberry-tagreader)
|
||||
include_directories(${CMAKE_BINARY_DIR}/ext/libstrawberry-tagreader)
|
||||
|
||||
set(SOURCES
|
||||
core/mainwindow.cpp
|
||||
core/application.cpp
|
||||
@@ -227,6 +186,7 @@ set(SOURCES
|
||||
covermanager/musicbrainzcoverprovider.cpp
|
||||
covermanager/discogscoverprovider.cpp
|
||||
covermanager/deezercoverprovider.cpp
|
||||
covermanager/qobuzcoverprovider.cpp
|
||||
|
||||
lyrics/lyricsproviders.cpp
|
||||
lyrics/lyricsprovider.cpp
|
||||
@@ -254,6 +214,7 @@ set(SOURCES
|
||||
dialogs/errordialog.cpp
|
||||
dialogs/edittagdialog.cpp
|
||||
dialogs/trackselectiondialog.cpp
|
||||
dialogs/addstreamdialog.cpp
|
||||
|
||||
widgets/autoexpandingtreeview.cpp
|
||||
widgets/busyindicator.cpp
|
||||
@@ -286,7 +247,6 @@ set(SOURCES
|
||||
internet/internetservices.cpp
|
||||
internet/internetservice.cpp
|
||||
internet/internetplaylistitem.cpp
|
||||
internet/internetsearch.cpp
|
||||
internet/internetsearchview.cpp
|
||||
internet/internetsearchmodel.cpp
|
||||
internet/internetsearchsortmodel.cpp
|
||||
@@ -413,6 +373,7 @@ set(HEADERS
|
||||
covermanager/musicbrainzcoverprovider.h
|
||||
covermanager/discogscoverprovider.h
|
||||
covermanager/deezercoverprovider.h
|
||||
covermanager/qobuzcoverprovider.h
|
||||
|
||||
lyrics/lyricsproviders.h
|
||||
lyrics/lyricsprovider.h
|
||||
@@ -440,6 +401,7 @@ set(HEADERS
|
||||
dialogs/console.h
|
||||
dialogs/edittagdialog.h
|
||||
dialogs/trackselectiondialog.h
|
||||
dialogs/addstreamdialog.h
|
||||
|
||||
widgets/autoexpandingtreeview.h
|
||||
widgets/busyindicator.h
|
||||
@@ -472,7 +434,6 @@ set(HEADERS
|
||||
internet/internetservices.h
|
||||
internet/internetservice.h
|
||||
internet/internetsongmimedata.h
|
||||
internet/internetsearch.h
|
||||
internet/internetsearchview.h
|
||||
internet/internetsearchmodel.h
|
||||
internet/localredirectserver.h
|
||||
@@ -539,6 +500,7 @@ set(UI
|
||||
dialogs/console.ui
|
||||
dialogs/edittagdialog.ui
|
||||
dialogs/trackselectiondialog.ui
|
||||
dialogs/addstreamdialog.ui
|
||||
|
||||
widgets/trackslider.ui
|
||||
widgets/osdpretty.ui
|
||||
@@ -622,12 +584,6 @@ optional_source(HAVE_VLC
|
||||
HEADERS engine/vlcengine.h
|
||||
)
|
||||
|
||||
# Phonon
|
||||
optional_source(HAVE_PHONON
|
||||
SOURCES engine/phononengine.cpp
|
||||
HEADERS engine/phononengine.h
|
||||
)
|
||||
|
||||
# DBUS and MPRIS - Unix specific
|
||||
if(UNIX AND HAVE_DBUS)
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/dbus)
|
||||
@@ -923,6 +879,29 @@ optional_source(HAVE_SUBSONIC
|
||||
settings/subsonicsettingspage.ui
|
||||
)
|
||||
|
||||
optional_source(HAVE_TIDAL
|
||||
SOURCES
|
||||
tidal/tidalservice.cpp
|
||||
tidal/tidalurlhandler.cpp
|
||||
tidal/tidalbaserequest.cpp
|
||||
tidal/tidalrequest.cpp
|
||||
tidal/tidalstreamurlrequest.cpp
|
||||
tidal/tidalfavoriterequest.cpp
|
||||
settings/tidalsettingspage.cpp
|
||||
covermanager/tidalcoverprovider.cpp
|
||||
HEADERS
|
||||
tidal/tidalservice.h
|
||||
tidal/tidalurlhandler.h
|
||||
tidal/tidalbaserequest.h
|
||||
tidal/tidalrequest.h
|
||||
tidal/tidalstreamurlrequest.h
|
||||
tidal/tidalfavoriterequest.h
|
||||
settings/tidalsettingspage.h
|
||||
covermanager/tidalcoverprovider.h
|
||||
UI
|
||||
settings/tidalsettingspage.ui
|
||||
)
|
||||
|
||||
# Moodbar
|
||||
optional_source(HAVE_MOODBAR
|
||||
SOURCES
|
||||
@@ -1034,10 +1013,6 @@ if(HAVE_VLC)
|
||||
target_link_libraries(strawberry_lib ${LIBVLC_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_PHONON)
|
||||
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_LIBGPOD)
|
||||
target_link_libraries(strawberry_lib ${LIBGPOD_LIBRARIES})
|
||||
endif(HAVE_LIBGPOD)
|
||||
@@ -1051,11 +1026,7 @@ if(HAVE_AUDIOCD)
|
||||
endif(HAVE_AUDIOCD)
|
||||
|
||||
if(HAVE_IMOBILEDEVICE)
|
||||
target_link_libraries(strawberry_lib
|
||||
${LIBIMOBILEDEVICE_LIBRARIES}
|
||||
${LIBPLIST_LIBRARIES}
|
||||
${LIBUSBMUXD_LIBRARIES}
|
||||
)
|
||||
target_link_libraries(strawberry_lib ${LIBIMOBILEDEVICE_LIBRARIES} ${LIBPLIST_LIBRARIES} ${LIBUSBMUXD_LIBRARIES})
|
||||
link_directories(${LIBIMOBILEDEVICE_LIBRARY_DIRS})
|
||||
link_directories(${LIBUSBMUXD_LIBRARY_DIRS})
|
||||
endif(HAVE_IMOBILEDEVICE)
|
||||
@@ -1083,7 +1054,6 @@ if (APPLE)
|
||||
"-framework ScriptingBridge"
|
||||
)
|
||||
|
||||
target_link_libraries(strawberry_lib ${SPMEDIAKEYTAP_LIBRARIES})
|
||||
if (HAVE_SPARKLE)
|
||||
include_directories(${SPARKLE}/Headers)
|
||||
target_link_libraries(strawberry_lib ${SPARKLE})
|
||||
@@ -1106,9 +1076,9 @@ if (UNIX AND NOT APPLE)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if(NOT USE_SYSTEM_SINGLEAPPLICATION)
|
||||
add_dependencies(strawberry_lib ${SINGLEAPPLICATION_LIBRARIES} ${SINGLECOREAPPLICATION_LIBRARIES})
|
||||
endif()
|
||||
if (NOT USE_SYSTEM_SINGLEAPPLICATION)
|
||||
add_dependencies(strawberry_lib ${SINGLEAPPLICATION_LIBRARIES} ${SINGLECOREAPPLICATION_LIBRARIES})
|
||||
endif ()
|
||||
|
||||
###############################################################################
|
||||
|
||||
@@ -1136,9 +1106,7 @@ if(FREEBSD)
|
||||
target_link_libraries(strawberry execinfo)
|
||||
endif()
|
||||
|
||||
target_link_libraries(strawberry
|
||||
strawberry_lib
|
||||
)
|
||||
target_link_libraries(strawberry strawberry_lib)
|
||||
|
||||
# macdeploy.py relies on the blob being built first.
|
||||
add_dependencies(strawberry strawberry-tagreader)
|
||||
|
||||
@@ -185,8 +185,8 @@ void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_fram
|
||||
|
||||
if (fade_intensity_[x] > 0) {
|
||||
const uint offset = --fade_intensity_[x];
|
||||
const uint y = y_ + (fade_pos_[x] * (kHeight + 1));
|
||||
canvas_painter.drawPixmap(x * (kWidth + 1), y, fade_bars_[offset], 0, 0, kWidth, height() - y);
|
||||
const uint y2 = y_ + (fade_pos_[x] * (kHeight + 1));
|
||||
canvas_painter.drawPixmap(x * (kWidth + 1), y2, fade_bars_[offset], 0, 0, kWidth, height() - y2);
|
||||
}
|
||||
|
||||
if (fade_intensity_[x] == 0) fade_pos_[x] = rows_;
|
||||
@@ -237,7 +237,8 @@ static inline void adjustToLimits(int &b, int &f, uint &amount) {
|
||||
* It won't modify the hue of fg unless absolutely necessary
|
||||
* @return the adjusted form of fg
|
||||
*/
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount = 150) {
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount = 150);
|
||||
QColor ensureContrast(const QColor &bg, const QColor &fg, uint amount) {
|
||||
|
||||
class OutputOnExit {
|
||||
public:
|
||||
@@ -344,18 +345,18 @@ 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)));
|
||||
|
||||
{
|
||||
const QColor bg = palette().color(QPalette::Background).darker(112);
|
||||
const QColor bg2 = palette().color(QPalette::Background).darker(112);
|
||||
|
||||
// make a complimentary fadebar colour
|
||||
// TODO dark is not always correct, dumbo!
|
||||
int h, s, v;
|
||||
palette().color(QPalette::Background).darker(150).getHsv(&h, &s, &v);
|
||||
const QColor fg(QColor::fromHsv(h + 120, s, v));
|
||||
const QColor fg2(QColor::fromHsv(h + 120, s, v));
|
||||
|
||||
const double dr = fg.red() - bg.red();
|
||||
const double dg = fg.green() - bg.green();
|
||||
const double db = fg.blue() - bg.blue();
|
||||
const int r = bg.red(), g = bg.green(), b = bg.blue();
|
||||
const double dr2 = fg2.red() - bg2.red();
|
||||
const double dg2 = fg2.green() - bg2.green();
|
||||
const double db2 = fg2.blue() - bg2.blue();
|
||||
const int r2 = bg2.red(), g2 = bg2.green(), b2 = bg2.blue();
|
||||
|
||||
// Precalculate all fade-bar pixmaps
|
||||
for (uint y = 0; y < kFadeSize; ++y) {
|
||||
@@ -363,7 +364,7 @@ void BlockAnalyzer::paletteChange(const QPalette&) {
|
||||
QPainter f(&fade_bars_[y]);
|
||||
for (int z = 0; static_cast<uint>(z) < rows_; ++z) {
|
||||
const double Y = 1.0 - (log10(kFadeSize - y) / log10(kFadeSize));
|
||||
f.fillRect(0, z * (kHeight + 1), kWidth, kHeight, QColor(r + static_cast<int>(dr * Y), g + static_cast<int>(dg * Y), b + static_cast<int>(db * Y)));
|
||||
f.fillRect(0, z * (kHeight + 1), kWidth, kHeight, QColor(r2 + static_cast<int>(dr2 * Y), g2 + static_cast<int>(dg2 * Y), b2 + static_cast<int>(db2 * Y)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,20 +75,20 @@ class RainbowAnalyzer : public Analyzer::Base {
|
||||
|
||||
static RainbowType rainbowtype;
|
||||
|
||||
inline QRect SourceRect(RainbowType rainbowtype) const {
|
||||
return QRect(0, kHeight[rainbowtype] * frame_, kWidth[rainbowtype], kHeight[rainbowtype]);
|
||||
inline QRect SourceRect(RainbowType _rainbowtype) const {
|
||||
return QRect(0, kHeight[_rainbowtype] * frame_, kWidth[_rainbowtype], kHeight[_rainbowtype]);
|
||||
}
|
||||
|
||||
inline QRect SleepingSourceRect(RainbowType rainbowtype) const {
|
||||
return QRect(0, kHeight[rainbowtype] * kFrameCount[rainbowtype], kWidth[rainbowtype], kSleepingHeight[rainbowtype]);
|
||||
inline QRect SleepingSourceRect(RainbowType _rainbowtype) const {
|
||||
return QRect(0, kHeight[_rainbowtype] * kFrameCount[_rainbowtype], kWidth[_rainbowtype], kSleepingHeight[_rainbowtype]);
|
||||
}
|
||||
|
||||
inline QRect DestRect(RainbowType rainbowtype) const {
|
||||
return QRect(width() - kWidth[rainbowtype], (height() - kHeight[rainbowtype]) / 2, kWidth[rainbowtype], kHeight[rainbowtype]);
|
||||
inline QRect DestRect(RainbowType _rainbowtype) const {
|
||||
return QRect(width() - kWidth[_rainbowtype], (height() - kHeight[_rainbowtype]) / 2, kWidth[_rainbowtype], kHeight[_rainbowtype]);
|
||||
}
|
||||
|
||||
inline QRect SleepingDestRect(RainbowType rainbowtype) const {
|
||||
return QRect(width() - kWidth[rainbowtype], (height() - kSleepingHeight[rainbowtype]) / 2, kWidth[rainbowtype], kSleepingHeight[rainbowtype]);
|
||||
inline QRect SleepingDestRect(RainbowType _rainbowtype) const {
|
||||
return QRect(width() - kWidth[_rainbowtype], (height() - kSleepingHeight[_rainbowtype]) / 2, kWidth[_rainbowtype], kSleepingHeight[_rainbowtype]);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -467,7 +467,7 @@ void CollectionBackend::AddOrUpdateSongs(const SongList &songs) {
|
||||
continue;
|
||||
|
||||
}
|
||||
else if (song.song_id() != -1) { // Song has a unique id, check if the song exists.
|
||||
else if (!song.song_id().isEmpty()) { // Song has a unique id, check if the song exists.
|
||||
|
||||
// Get the previous song data first
|
||||
Song old_song(GetSongBySongId(song.song_id()));
|
||||
@@ -822,35 +822,29 @@ SongList CollectionBackend::GetSongsByUrl(const QUrl &url) {
|
||||
}
|
||||
|
||||
|
||||
Song CollectionBackend::GetSongBySongId(int song_id) {
|
||||
Song CollectionBackend::GetSongBySongId(const QString &song_id) {
|
||||
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
return GetSongBySongId(song_id, db);
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsBySongId(const QList<int> &song_ids) {
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
|
||||
QStringList str_song_ids;
|
||||
for (int song_id : song_ids) {
|
||||
str_song_ids << QString::number(song_id);
|
||||
}
|
||||
|
||||
return GetSongsBySongId(str_song_ids, db);
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsBySongId(const QStringList &song_ids) {
|
||||
|
||||
QMutexLocker l(db_->Mutex());
|
||||
QSqlDatabase db(db_->Connect());
|
||||
|
||||
return GetSongsBySongId(song_ids, db);
|
||||
|
||||
}
|
||||
|
||||
Song CollectionBackend::GetSongBySongId(int song_id, QSqlDatabase &db) {
|
||||
SongList list = GetSongsBySongId(QStringList() << QString::number(song_id), db);
|
||||
Song CollectionBackend::GetSongBySongId(const QString &song_id, QSqlDatabase &db) {
|
||||
|
||||
SongList list = GetSongsBySongId(QStringList() << song_id, db);
|
||||
if (list.isEmpty()) return Song();
|
||||
return list.first();
|
||||
|
||||
}
|
||||
|
||||
SongList CollectionBackend::GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db) {
|
||||
@@ -1001,7 +995,7 @@ void CollectionBackend::UpdateCompilations(QSqlQuery &find_song, QSqlQuery &upda
|
||||
|
||||
}
|
||||
|
||||
CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, bool compilation, const QueryOptions &opt) {
|
||||
CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt) {
|
||||
|
||||
AlbumList ret;
|
||||
|
||||
@@ -1009,7 +1003,7 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
||||
query.SetColumnSpec("album, artist, albumartist, compilation, compilation_detected, art_automatic, art_manual, url");
|
||||
query.SetOrderBy("album");
|
||||
|
||||
if (compilation) {
|
||||
if (compilation_required) {
|
||||
query.AddCompilationRequirement(true);
|
||||
}
|
||||
else if (!artist.isEmpty()) {
|
||||
@@ -1026,11 +1020,11 @@ CollectionBackend::AlbumList CollectionBackend::GetAlbums(const QString &artist,
|
||||
QString last_artist;
|
||||
QString last_album_artist;
|
||||
while (query.Next()) {
|
||||
bool compilation = query.Value(3).toBool() | query.Value(4).toBool();
|
||||
bool is_compilation = query.Value(3).toBool() | query.Value(4).toBool();
|
||||
|
||||
Album info;
|
||||
info.artist = compilation ? QString() : query.Value(1).toString();
|
||||
info.album_artist = compilation ? QString() : query.Value(2).toString();
|
||||
info.artist = is_compilation ? QString() : query.Value(1).toString();
|
||||
info.album_artist = is_compilation ? QString() : query.Value(2).toString();
|
||||
info.album_name = query.Value(0).toString();
|
||||
info.first_url = QUrl::fromEncoded(query.Value(7).toByteArray());
|
||||
|
||||
|
||||
@@ -141,10 +141,10 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
void UpdateTotalArtistCountAsync();
|
||||
void UpdateTotalAlbumCountAsync();
|
||||
|
||||
SongList FindSongsInDirectory(int id);
|
||||
SubdirectoryList SubdirsInDirectory(int id);
|
||||
SongList FindSongsInDirectory(const int id);
|
||||
SubdirectoryList SubdirsInDirectory(const int id);
|
||||
DirectoryList GetAllDirectories();
|
||||
void ChangeDirPath(int id, const QString &old_path, const QString &new_path);
|
||||
void ChangeDirPath(const int id, const QString &old_path, const QString &new_path);
|
||||
|
||||
QStringList GetAll(const QString &column, const QueryOptions &opt = QueryOptions());
|
||||
QStringList GetAllArtists(const QueryOptions &opt = QueryOptions());
|
||||
@@ -161,7 +161,7 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
void UpdateManualAlbumArtAsync(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url);
|
||||
Album GetAlbumArt(const QString &artist, const QString &albumartist, const QString &album);
|
||||
|
||||
Song GetSongById(int id);
|
||||
Song GetSongById(const int id);
|
||||
SongList GetSongsById(const QList<int> &ids);
|
||||
SongList GetSongsById(const QStringList &ids);
|
||||
SongList GetSongsByForeignId(const QStringList &ids, const QString &table, const QString &column);
|
||||
@@ -175,14 +175,13 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
bool ExecQuery(CollectionQuery *q);
|
||||
SongList ExecCollectionQuery(CollectionQuery *query);
|
||||
|
||||
void IncrementPlayCountAsync(int id);
|
||||
void IncrementSkipCountAsync(int id, float progress);
|
||||
void ResetStatisticsAsync(int id);
|
||||
void IncrementPlayCountAsync(const int id);
|
||||
void IncrementSkipCountAsync(const int id, const float progress);
|
||||
void ResetStatisticsAsync(const int id);
|
||||
|
||||
void DeleteAll();
|
||||
|
||||
Song GetSongBySongId(int song_id);
|
||||
SongList GetSongsBySongId(const QList<int> &song_ids);
|
||||
Song GetSongBySongId(const QString &song_id);
|
||||
SongList GetSongsBySongId(const QStringList &song_ids);
|
||||
|
||||
Song::Source Source() const;
|
||||
@@ -200,10 +199,10 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
void AddOrUpdateSubdirs(const SubdirectoryList &subdirs);
|
||||
void UpdateCompilations();
|
||||
void UpdateManualAlbumArt(const QString &artist, const QString &albumartist, const QString &album, const QUrl &cover_url);
|
||||
void ForceCompilation(const QString &album, const QList<QString> &artists, bool on);
|
||||
void IncrementPlayCount(int id);
|
||||
void IncrementSkipCount(int id, float progress);
|
||||
void ResetStatistics(int id);
|
||||
void ForceCompilation(const QString &album, const QList<QString> &artists, const bool on);
|
||||
void IncrementPlayCount(const int id);
|
||||
void IncrementSkipCount(const int id, const float progress);
|
||||
void ResetStatistics(const int id);
|
||||
void SongPathChanged(const Song &song, const QFileInfo &new_file);
|
||||
|
||||
signals:
|
||||
@@ -216,9 +215,9 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
|
||||
void DatabaseReset();
|
||||
|
||||
void TotalSongCountUpdated(int total);
|
||||
void TotalArtistCountUpdated(int total);
|
||||
void TotalAlbumCountUpdated(int total);
|
||||
void TotalSongCountUpdated(const int total);
|
||||
void TotalArtistCountUpdated(const int total);
|
||||
void TotalAlbumCountUpdated(const int total);
|
||||
|
||||
void ExitFinished();
|
||||
|
||||
@@ -234,14 +233,14 @@ class CollectionBackend : public CollectionBackendInterface {
|
||||
};
|
||||
|
||||
void UpdateCompilations(QSqlQuery &find_song, QSqlQuery &update_song, SongList &deleted_songs, SongList &added_songs, const QUrl &url, const bool compilation_detected);
|
||||
AlbumList GetAlbums(const QString &artist, const QString &album_artist, bool compilation = false, const QueryOptions &opt = QueryOptions());
|
||||
AlbumList GetAlbums(const QString &artist, bool compilation, const QueryOptions &opt = QueryOptions());
|
||||
SubdirectoryList SubdirsInDirectory(int id, QSqlDatabase &db);
|
||||
AlbumList GetAlbums(const QString &artist, const QString &album_artist, const bool compilation_required = false, const QueryOptions &opt = QueryOptions());
|
||||
AlbumList GetAlbums(const QString &artist, const bool compilation_required, const QueryOptions &opt = QueryOptions());
|
||||
SubdirectoryList SubdirsInDirectory(const int id, QSqlDatabase &db);
|
||||
|
||||
Song GetSongById(int id, QSqlDatabase &db);
|
||||
Song GetSongById(const int id, QSqlDatabase &db);
|
||||
SongList GetSongsById(const QStringList &ids, QSqlDatabase &db);
|
||||
|
||||
Song GetSongBySongId(int song_id, QSqlDatabase &db);
|
||||
Song GetSongBySongId(const QString &song_id, QSqlDatabase &db);
|
||||
SongList GetSongsBySongId(const QStringList &song_ids, QSqlDatabase &db);
|
||||
|
||||
private:
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
#include "collectionbackend.h"
|
||||
#include "collectiondirectorymodel.h"
|
||||
|
||||
using std::shared_ptr;
|
||||
|
||||
CollectionDirectoryModel::CollectionDirectoryModel(CollectionBackend *backend, QObject *parent)
|
||||
: QStandardItemModel(parent),
|
||||
dir_icon_(IconLoader::Load("document-open-folder")),
|
||||
|
||||
@@ -297,6 +297,7 @@ void CollectionFilterWidget::SetCollectionModel(CollectionModel *model) {
|
||||
}
|
||||
|
||||
void CollectionFilterWidget::GroupByClicked(QAction *action) {
|
||||
|
||||
if (action->property("group_by").isNull()) {
|
||||
group_by_dialog_->show();
|
||||
return;
|
||||
@@ -304,6 +305,7 @@ void CollectionFilterWidget::GroupByClicked(QAction *action) {
|
||||
|
||||
CollectionModel::Grouping g = action->property("group_by").value<CollectionModel::Grouping>();
|
||||
model_->SetGroupBy(g);
|
||||
|
||||
}
|
||||
|
||||
void CollectionFilterWidget::GroupingChanged(const CollectionModel::Grouping &g) {
|
||||
|
||||
@@ -37,13 +37,13 @@ class CollectionItem : public SimpleTreeItem<CollectionItem> {
|
||||
Type_LoadingIndicator,
|
||||
};
|
||||
|
||||
explicit CollectionItem(SimpleTreeModel<CollectionItem> *model)
|
||||
: SimpleTreeItem<CollectionItem>(Type_Root, model),
|
||||
explicit CollectionItem(SimpleTreeModel<CollectionItem> *_model)
|
||||
: SimpleTreeItem<CollectionItem>(Type_Root, _model),
|
||||
container_level(-1),
|
||||
compilation_artist_node_(nullptr) {}
|
||||
|
||||
explicit CollectionItem(Type type, CollectionItem *parent = nullptr)
|
||||
: SimpleTreeItem<CollectionItem>(type, parent),
|
||||
explicit CollectionItem(Type _type, CollectionItem *_parent = nullptr)
|
||||
: SimpleTreeItem<CollectionItem>(_type, _parent),
|
||||
container_level(-1),
|
||||
compilation_artist_node_(nullptr) {}
|
||||
|
||||
|
||||
@@ -66,16 +66,15 @@
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/songmimedata.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
#include "settings/collectionsettingspage.h"
|
||||
|
||||
using std::bind;
|
||||
using std::sort;
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
const char *CollectionModel::kSavedGroupingsSettingsGroup = "SavedGroupings";
|
||||
const int CollectionModel::kPrettyCoverSize = 32;
|
||||
const char *CollectionModel::kPixmapDiskCacheDir = "/pixmapcache";
|
||||
const char *CollectionModel::kPixmapDiskCacheDir = "pixmapcache";
|
||||
|
||||
QNetworkDiskCache *CollectionModel::sIconCache = nullptr;
|
||||
|
||||
@@ -115,17 +114,18 @@ CollectionModel::CollectionModel(CollectionBackend *backend, Application *app, Q
|
||||
cover_loader_options_.pad_output_image_ = true;
|
||||
cover_loader_options_.scale_output_image_ = true;
|
||||
|
||||
if (app_)
|
||||
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(AlbumCoverLoaded(quint64, QUrl, QImage)));
|
||||
if (app_) {
|
||||
connect(app_->album_cover_loader(), SIGNAL(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)));
|
||||
}
|
||||
|
||||
QIcon nocover = IconLoader::Load("cdcase");
|
||||
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
//no_cover_icon_ = QPixmap(":/pictures/noalbumart.png").scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
// When running under gdb, all calls to this constructor came from the same thread.
|
||||
// If this ever changes, these two lines might need to be protected by a mutex.
|
||||
if (sIconCache == nullptr)
|
||||
if (sIconCache == nullptr) {
|
||||
sIconCache = new QNetworkDiskCache(this);
|
||||
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + "/" + kPixmapDiskCacheDir);
|
||||
}
|
||||
|
||||
connect(backend_, SIGNAL(SongsDiscovered(SongList)), SLOT(SongsDiscovered(SongList)));
|
||||
connect(backend_, SIGNAL(SongsDeleted(SongList)), SLOT(SongsDeleted(SongList)));
|
||||
@@ -187,16 +187,16 @@ void CollectionModel::ReloadSettings() {
|
||||
|
||||
use_disk_cache_ = s.value(CollectionSettingsPage::kSettingsDiskCacheEnable, false).toBool();
|
||||
|
||||
if (!use_disk_cache_) {
|
||||
sIconCache->clear();
|
||||
}
|
||||
QPixmapCache::setCacheLimit(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit, CollectionSettingsPage::kSettingsCacheSizeDefault) / 1024);
|
||||
|
||||
sIconCache->setCacheDirectory(QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + kPixmapDiskCacheDir);
|
||||
sIconCache->setMaximumCacheSize(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit));
|
||||
|
||||
QPixmapCache::setCacheLimit(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsCacheSize, CollectionSettingsPage::kSettingsCacheSizeUnit) / 1024);
|
||||
sIconCache->setMaximumCacheSize(MaximumCacheSize(&s, CollectionSettingsPage::kSettingsDiskCacheSize, CollectionSettingsPage::kSettingsDiskCacheSizeUnit, CollectionSettingsPage::kSettingsDiskCacheSizeDefault));
|
||||
|
||||
s.endGroup();
|
||||
|
||||
if (!use_disk_cache_) {
|
||||
ClearDiskCache();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CollectionModel::Init(bool async) {
|
||||
@@ -588,10 +588,10 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
|
||||
if (use_disk_cache_) {
|
||||
std::unique_ptr<QIODevice> cache(sIconCache->data(QUrl(cache_key)));
|
||||
if (cache) {
|
||||
QImage cached_pixmap;
|
||||
if (cached_pixmap.load(cache.get(), "XPM")) {
|
||||
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_pixmap));
|
||||
return QPixmap::fromImage(cached_pixmap);
|
||||
QImage cached_image;
|
||||
if (cached_image.load(cache.get(), "XPM")) {
|
||||
QPixmapCache::insert(cache_key, QPixmap::fromImage(cached_image));
|
||||
return QPixmap::fromImage(cached_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -613,9 +613,7 @@ QVariant CollectionModel::AlbumIcon(const QModelIndex &idx) {
|
||||
|
||||
}
|
||||
|
||||
void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
|
||||
|
||||
Q_UNUSED(cover_url);
|
||||
void CollectionModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result) {
|
||||
|
||||
if (!pending_art_.contains(id)) return;
|
||||
|
||||
@@ -628,26 +626,26 @@ void CollectionModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url,
|
||||
pending_cache_keys_.remove(cache_key);
|
||||
|
||||
// Insert this image in the cache.
|
||||
if (image.isNull()) {
|
||||
if (result.image_scaled.isNull()) {
|
||||
// Set the no_cover image so we don't continually try to load art.
|
||||
QPixmapCache::insert(cache_key, no_cover_icon_);
|
||||
}
|
||||
else {
|
||||
QPixmap image_pixmap;
|
||||
image_pixmap = QPixmap::fromImage(image);
|
||||
image_pixmap = QPixmap::fromImage(result.image_scaled);
|
||||
QPixmapCache::insert(cache_key, image_pixmap);
|
||||
}
|
||||
|
||||
// If we have a valid cover not already in the disk cache
|
||||
if (use_disk_cache_) {
|
||||
std::unique_ptr<QIODevice> cached_img(sIconCache->data(QUrl(cache_key)));
|
||||
if (!cached_img && !image.isNull()) {
|
||||
if (!cached_img && !result.image_scaled.isNull()) {
|
||||
QNetworkCacheMetaData item_metadata;
|
||||
item_metadata.setSaveToDisk(true);
|
||||
item_metadata.setUrl(QUrl(cache_key));
|
||||
QIODevice* cache = sIconCache->prepare(item_metadata);
|
||||
QIODevice *cache = sIconCache->prepare(item_metadata);
|
||||
if (cache) {
|
||||
image.save(cache, "XPM");
|
||||
result.image_scaled.save(cache, "XPM");
|
||||
sIconCache->insert(cache);
|
||||
}
|
||||
}
|
||||
@@ -1541,9 +1539,9 @@ bool CollectionModel::CompareItems(const CollectionItem *a, const CollectionItem
|
||||
|
||||
}
|
||||
|
||||
int CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id) const {
|
||||
int CollectionModel::MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const int cache_size_default) const {
|
||||
|
||||
int size = s->value(size_id, 80).toInt();
|
||||
int size = s->value(size_id, cache_size_default).toInt();
|
||||
int unit = s->value(size_unit_id, CollectionSettingsPage::CacheSizeUnit::CacheSizeUnit_MB).toInt() + 1;
|
||||
|
||||
do {
|
||||
|
||||
@@ -41,16 +41,17 @@
|
||||
#include <QImage>
|
||||
#include <QIcon>
|
||||
#include <QPixmap>
|
||||
#include <QNetworkDiskCache>
|
||||
|
||||
#include "core/simpletreemodel.h"
|
||||
#include "core/song.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "collectionquery.h"
|
||||
#include "collectionitem.h"
|
||||
#include "sqlrow.h"
|
||||
#include "covermanager/albumcoverloaderoptions.h"
|
||||
|
||||
class QSettings;
|
||||
class QNetworkDiskCache;
|
||||
|
||||
class Application;
|
||||
class CollectionBackend;
|
||||
@@ -176,7 +177,9 @@ class CollectionModel : public SimpleTreeModel<CollectionItem> {
|
||||
static QString SortTextForYear(int year);
|
||||
static QString SortTextForBitrate(int bitrate);
|
||||
|
||||
signals:
|
||||
quint64 icon_cache_disk_size() { return sIconCache->cacheSize(); }
|
||||
|
||||
signals:
|
||||
void TotalSongCountUpdated(int count);
|
||||
void TotalArtistCountUpdated(int count);
|
||||
void TotalAlbumCountUpdated(int count);
|
||||
@@ -210,7 +213,7 @@ signals:
|
||||
// Called after ResetAsync
|
||||
void ResetAsyncQueryFinished(QFuture<CollectionModel::QueryResult> future);
|
||||
|
||||
void AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
|
||||
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result);
|
||||
|
||||
private:
|
||||
// Provides some optimisations for loading the list of items in the root.
|
||||
@@ -247,7 +250,7 @@ signals:
|
||||
QVariant AlbumIcon(const QModelIndex &idx);
|
||||
QVariant data(const CollectionItem *item, int role) const;
|
||||
bool CompareItems(const CollectionItem *a, const CollectionItem *b) const;
|
||||
int MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id) const;
|
||||
int MaximumCacheSize(QSettings *s, const char *size_id, const char *size_unit_id, const int cache_size_default) const;
|
||||
|
||||
private:
|
||||
CollectionBackend *backend_;
|
||||
|
||||
@@ -43,20 +43,33 @@ void CollectionPlaylistItem::Reload() {
|
||||
}
|
||||
|
||||
bool CollectionPlaylistItem::InitFromQuery(const SqlRow &query) {
|
||||
|
||||
// Rows from the songs tables come first
|
||||
song_.InitFromQuery(query, true);
|
||||
song_.set_source(Song::Source_Collection);
|
||||
return song_.is_valid();
|
||||
|
||||
}
|
||||
|
||||
QVariant CollectionPlaylistItem::DatabaseValue(DatabaseColumn column) const {
|
||||
|
||||
switch (column) {
|
||||
case Column_CollectionId: return song_.id();
|
||||
default: return PlaylistItem::DatabaseValue(column);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Song CollectionPlaylistItem::Metadata() const {
|
||||
|
||||
if (HasTemporaryMetadata()) return temp_metadata_;
|
||||
return song_;
|
||||
|
||||
}
|
||||
|
||||
void CollectionPlaylistItem::SetArtManual(const QUrl &cover_url) {
|
||||
|
||||
song_.set_art_manual(cover_url);
|
||||
temp_metadata_.set_art_manual(cover_url);
|
||||
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ class CollectionPlaylistItem : public PlaylistItem {
|
||||
|
||||
bool IsLocalCollectionItem() const { return true; }
|
||||
|
||||
void SetArtManual(const QUrl &cover_url);
|
||||
|
||||
protected:
|
||||
QVariant DatabaseValue(DatabaseColumn column) const;
|
||||
Song DatabaseSongMetadata() const { return Song(Song::Source_Collection); }
|
||||
|
||||
@@ -64,8 +64,6 @@
|
||||
#include "organise/organisedialog.h"
|
||||
#include "settings/collectionsettingspage.h"
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
CollectionView::CollectionView(QWidget *parent)
|
||||
: AutoExpandingTreeView(parent),
|
||||
app_(nullptr),
|
||||
@@ -463,11 +461,11 @@ void CollectionView::ShowInVarious(bool on) {
|
||||
|
||||
void CollectionView::Load() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->clear_first_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->clear_first_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
@@ -479,31 +477,31 @@ void CollectionView::AddToPlaylist() {
|
||||
|
||||
void CollectionView::AddToPlaylistEnqueue() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->enqueue_now_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData* mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->enqueue_now_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
void CollectionView::AddToPlaylistEnqueueNext() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->enqueue_next_now_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->enqueue_next_now_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
void CollectionView::OpenInNewPlaylist() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->open_in_new_playlist_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData* mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->open_in_new_playlist_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ class CollectionFilterWidget;
|
||||
class EditTagDialog;
|
||||
class OrganiseDialog;
|
||||
|
||||
using std::unique_ptr;
|
||||
|
||||
class CollectionView : public AutoExpandingTreeView {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
@@ -650,7 +650,7 @@ void CollectionWatcher::AddWatch(const Directory &dir, const QString &path) {
|
||||
|
||||
if (!QFile::exists(path)) return;
|
||||
|
||||
connect(fs_watcher_, SIGNAL(PathChanged(const QString&)), this, SLOT(DirectoryChanged(const QString&)), Qt::UniqueConnection);
|
||||
connect(fs_watcher_, SIGNAL(PathChanged(QString)), this, SLOT(DirectoryChanged(QString)), Qt::UniqueConnection);
|
||||
fs_watcher_->AddPath(path);
|
||||
subdir_mapping_[path] = dir;
|
||||
|
||||
|
||||
@@ -45,10 +45,10 @@
|
||||
#cmakedefine HAVE_GSTREAMER
|
||||
#cmakedefine HAVE_VLC
|
||||
#cmakedefine HAVE_XINE
|
||||
#cmakedefine HAVE_PHONON
|
||||
#cmakedefine XINE_ANALYZER
|
||||
|
||||
#cmakedefine HAVE_SUBSONIC
|
||||
#cmakedefine HAVE_TIDAL
|
||||
|
||||
#cmakedefine HAVE_MOODBAR
|
||||
|
||||
|
||||
@@ -33,17 +33,22 @@
|
||||
#include <QTimeLine>
|
||||
#include <QPainter>
|
||||
#include <QSizePolicy>
|
||||
#include <QMenu>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QPaintEvent>
|
||||
|
||||
#include "covermanager/albumcoverchoicecontroller.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
|
||||
#include "contextview.h"
|
||||
#include "contextalbum.h"
|
||||
|
||||
const int ContextAlbum::kWidgetSpacing = 40;
|
||||
|
||||
ContextAlbum::ContextAlbum(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
menu_(new QMenu(this)),
|
||||
context_view_(nullptr),
|
||||
album_cover_choice_controller_(nullptr),
|
||||
downloading_covers_(false),
|
||||
timeline_fade_(new QTimeLine(1000, this)),
|
||||
@@ -57,18 +62,39 @@ ContextAlbum::ContextAlbum(QWidget *parent) :
|
||||
cover_loader_options_.desired_height_ = 600;
|
||||
cover_loader_options_.pad_output_image_ = true;
|
||||
cover_loader_options_.scale_output_image_ = true;
|
||||
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_strawberry_));
|
||||
QPair<QImage, QImage> images = AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_strawberry_);
|
||||
pixmap_current_ = QPixmap::fromImage(images.first);
|
||||
|
||||
connect(timeline_fade_, SIGNAL(valueChanged(qreal)), SLOT(FadePreviousTrack(qreal)));
|
||||
timeline_fade_->setDirection(QTimeLine::Backward); // 1.0 -> 0.0
|
||||
|
||||
}
|
||||
|
||||
void ContextAlbum::Init(AlbumCoverChoiceController *album_cover_choice_controller) {
|
||||
void ContextAlbum::Init(ContextView *context_view, AlbumCoverChoiceController *album_cover_choice_controller) {
|
||||
|
||||
context_view_ = context_view;
|
||||
|
||||
album_cover_choice_controller_ = album_cover_choice_controller;
|
||||
connect(album_cover_choice_controller_, SIGNAL(AutomaticCoverSearchDone()), this, SLOT(AutomaticCoverSearchDone()));
|
||||
|
||||
QList<QAction*> cover_actions = album_cover_choice_controller_->GetAllActions();
|
||||
cover_actions.append(album_cover_choice_controller_->search_cover_auto_action());
|
||||
menu_->addActions(cover_actions);
|
||||
menu_->addSeparator();
|
||||
|
||||
}
|
||||
|
||||
void ContextAlbum::contextMenuEvent(QContextMenuEvent *e) {
|
||||
if (menu_ && image_original_ != image_strawberry_) menu_->popup(mapToGlobal(e->pos()));
|
||||
}
|
||||
|
||||
void ContextAlbum::mouseDoubleClickEvent(QMouseEvent *e) {
|
||||
|
||||
// Same behaviour as right-click > Show Fullsize
|
||||
if (image_original_ != image_strawberry_ && e->button() == Qt::LeftButton && context_view_->song_playing().is_valid()) {
|
||||
album_cover_choice_controller_->ShowCover(context_view_->song_playing(), image_original_);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void ContextAlbum::paintEvent(QPaintEvent*) {
|
||||
@@ -89,7 +115,7 @@ void ContextAlbum::DrawImage(QPainter *p) {
|
||||
|
||||
if (width() != prev_width_) {
|
||||
cover_loader_options_.desired_height_ = width() - kWidgetSpacing;
|
||||
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_));
|
||||
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_).first);
|
||||
prev_width_ = width();
|
||||
}
|
||||
|
||||
@@ -118,7 +144,7 @@ void ContextAlbum::FadePreviousTrack(const qreal value) {
|
||||
void ContextAlbum::ScaleCover() {
|
||||
|
||||
cover_loader_options_.desired_height_ = width() - kWidgetSpacing;
|
||||
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_));
|
||||
pixmap_current_ = QPixmap::fromImage(AlbumCoverLoader::ScaleAndPad(cover_loader_options_, image_original_).first);
|
||||
prev_width_ = width();
|
||||
update();
|
||||
|
||||
@@ -162,7 +188,7 @@ void ContextAlbum::SearchCoverInProgress() {
|
||||
|
||||
// Show a spinner animation
|
||||
spinner_animation_.reset(new QMovie(":/pictures/spinner.gif", QByteArray(), this));
|
||||
connect(spinner_animation_.get(), SIGNAL(updated(const QRect&)), SLOT(update()));
|
||||
connect(spinner_animation_.get(), SIGNAL(updated(QRect)), SLOT(update()));
|
||||
spinner_animation_->start();
|
||||
update();
|
||||
|
||||
|
||||
@@ -34,10 +34,12 @@
|
||||
|
||||
#include "covermanager/albumcoverloaderoptions.h"
|
||||
|
||||
class QMenu;
|
||||
class QTimeLine;
|
||||
class QPainter;
|
||||
class QPaintEvent;
|
||||
|
||||
class ContextView;
|
||||
class AlbumCoverChoiceController;
|
||||
|
||||
class ContextAlbum : public QWidget {
|
||||
@@ -46,11 +48,13 @@ class ContextAlbum : public QWidget {
|
||||
public:
|
||||
explicit ContextAlbum(QWidget *parent = nullptr);
|
||||
|
||||
void Init(AlbumCoverChoiceController *album_cover_choice_controller);
|
||||
void Init(ContextView *context_view, AlbumCoverChoiceController *album_cover_choice_controller);
|
||||
void SetImage(QImage image = QImage());
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent*);
|
||||
void contextMenuEvent(QContextMenuEvent *e);
|
||||
void mouseDoubleClickEvent(QMouseEvent *e);
|
||||
|
||||
private:
|
||||
void DrawImage(QPainter *p);
|
||||
@@ -67,6 +71,10 @@ class ContextAlbum : public QWidget {
|
||||
|
||||
private:
|
||||
static const int kWidgetSpacing;
|
||||
|
||||
private:
|
||||
QMenu *menu_;
|
||||
ContextView *context_view_;
|
||||
AlbumCoverChoiceController *album_cover_choice_controller_;
|
||||
AlbumCoverLoaderOptions cover_loader_options_;
|
||||
bool downloading_covers_;
|
||||
|
||||
@@ -48,11 +48,11 @@
|
||||
#include "playlist/playlistmanager.h"
|
||||
#include "playlist/songmimedata.h"
|
||||
#include "covermanager/albumcoverloader.h"
|
||||
#include "covermanager/albumcoverloaderoptions.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
|
||||
#include "contextalbumsmodel.h"
|
||||
|
||||
using std::bind;
|
||||
using std::sort;
|
||||
using std::placeholders::_1;
|
||||
using std::placeholders::_2;
|
||||
|
||||
@@ -71,7 +71,7 @@ ContextAlbumsModel::ContextAlbumsModel(CollectionBackend *backend, Application *
|
||||
cover_loader_options_.pad_output_image_ = true;
|
||||
cover_loader_options_.scale_output_image_ = true;
|
||||
|
||||
connect(app_->album_cover_loader(), SIGNAL(ImageLoaded(quint64, QUrl, QImage)), SLOT(AlbumCoverLoaded(quint64, QUrl, QImage)));
|
||||
connect(app_->album_cover_loader(), SIGNAL(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)), SLOT(AlbumCoverLoaded(quint64, AlbumCoverLoaderResult)));
|
||||
|
||||
QIcon nocover = IconLoader::Load("cdcase");
|
||||
no_cover_icon_ = nocover.pixmap(nocover.availableSizes().last()).scaled(kPrettyCoverSize, kPrettyCoverSize, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
@@ -146,9 +146,7 @@ QVariant ContextAlbumsModel::AlbumIcon(const QModelIndex &index) {
|
||||
|
||||
}
|
||||
|
||||
void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image) {
|
||||
|
||||
Q_UNUSED(cover_url);
|
||||
void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result) {
|
||||
|
||||
if (!pending_art_.contains(id)) return;
|
||||
|
||||
@@ -161,13 +159,13 @@ void ContextAlbumsModel::AlbumCoverLoaded(const quint64 id, const QUrl &cover_ur
|
||||
pending_cache_keys_.remove(cache_key);
|
||||
|
||||
// Insert this image in the cache.
|
||||
if (image.isNull()) {
|
||||
if (result.image_scaled.isNull()) {
|
||||
// Set the no_cover image so we don't continually try to load art.
|
||||
QPixmapCache::insert(cache_key, no_cover_icon_);
|
||||
}
|
||||
else {
|
||||
QPixmap image_pixmap;
|
||||
image_pixmap = QPixmap::fromImage(image);
|
||||
image_pixmap = QPixmap::fromImage(result.image_scaled);
|
||||
QPixmapCache::insert(cache_key, image_pixmap);
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "collection/collectionitem.h"
|
||||
#include "collection/sqlrow.h"
|
||||
#include "covermanager/albumcoverloaderoptions.h"
|
||||
#include "covermanager/albumcoverloaderresult.h"
|
||||
|
||||
class QMimeData;
|
||||
|
||||
@@ -99,7 +100,7 @@ class ContextAlbumsModel : public SimpleTreeModel<CollectionItem> {
|
||||
void LazyPopulate(CollectionItem *item, bool signal);
|
||||
|
||||
private slots:
|
||||
void AlbumCoverLoaded(const quint64 id, const QUrl &cover_url, const QImage &image);
|
||||
void AlbumCoverLoaded(const quint64 id, const AlbumCoverLoaderResult &result);
|
||||
|
||||
private:
|
||||
QueryResult RunQuery(CollectionItem *parent);
|
||||
|
||||
@@ -321,11 +321,11 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
||||
|
||||
void ContextAlbumsView::Load() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->clear_first_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->clear_first_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
@@ -337,21 +337,21 @@ void ContextAlbumsView::AddToPlaylist() {
|
||||
|
||||
void ContextAlbumsView::AddToPlaylistEnqueue() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->enqueue_now_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->enqueue_now_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
void ContextAlbumsView::OpenInNewPlaylist() {
|
||||
|
||||
QMimeData *data = model()->mimeData(selectedIndexes());
|
||||
if (MimeData* mime_data = qobject_cast<MimeData*>(data)) {
|
||||
mime_data->open_in_new_playlist_ = true;
|
||||
QMimeData *q_mimedata = model()->mimeData(selectedIndexes());
|
||||
if (MimeData *mimedata = qobject_cast<MimeData*>(q_mimedata)) {
|
||||
mimedata->open_in_new_playlist_ = true;
|
||||
}
|
||||
emit AddToPlaylistSignal(data);
|
||||
emit AddToPlaylistSignal(q_mimedata);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <QUrl>
|
||||
#include <QImage>
|
||||
#include <QIcon>
|
||||
#include <QFont>
|
||||
#include <QSize>
|
||||
#include <QSizePolicy>
|
||||
#include <QMenu>
|
||||
@@ -80,6 +81,7 @@ ContextView::ContextView(QWidget *parent) :
|
||||
action_show_output_(nullptr),
|
||||
action_show_albums_(nullptr),
|
||||
action_show_lyrics_(nullptr),
|
||||
action_search_lyrics_(nullptr),
|
||||
layout_container_(new QVBoxLayout()),
|
||||
widget_scrollarea_(new QWidget(this)),
|
||||
layout_scrollarea_(new QVBoxLayout()),
|
||||
@@ -124,6 +126,7 @@ ContextView::ContextView(QWidget *parent) :
|
||||
label_device_icon_(new QLabel(this)),
|
||||
label_engine_icon_(new QLabel(this)),
|
||||
spacer_bottom_(new QSpacerItem(20, 20, QSizePolicy::Expanding, QSizePolicy::Expanding)),
|
||||
lyrics_tried_(false),
|
||||
lyrics_id_(-1),
|
||||
prev_width_(0)
|
||||
{
|
||||
@@ -144,9 +147,10 @@ ContextView::ContextView(QWidget *parent) :
|
||||
widget_scrollarea_->setLayout(layout_scrollarea_);
|
||||
widget_scrollarea_->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
label_top_->setWordWrap(true);
|
||||
label_top_->setAlignment(Qt::AlignTop|Qt::AlignLeft);
|
||||
label_top_->setWordWrap(true);
|
||||
label_top_->setMinimumHeight(50);
|
||||
label_top_->setContentsMargins(0, 0, 32, 0);
|
||||
|
||||
layout_scrollarea_->setObjectName("context-layout-scrollarea");
|
||||
layout_scrollarea_->setContentsMargins(15, 15, 15, 15);
|
||||
@@ -241,6 +245,8 @@ ContextView::ContextView(QWidget *parent) :
|
||||
label_play_lyrics_->setWordWrap(true);
|
||||
label_play_lyrics_->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
|
||||
label_play_albums_->setWordWrap(true);
|
||||
|
||||
layout_play_->setContentsMargins(5, 0, 40, 0);
|
||||
layout_play_->addWidget(widget_play_output_);
|
||||
layout_play_->addSpacerItem(spacer_play_output_);
|
||||
@@ -252,6 +258,30 @@ ContextView::ContextView(QWidget *parent) :
|
||||
layout_play_->addWidget(label_play_lyrics_);
|
||||
layout_play_->addSpacerItem(spacer_play_bottom_);
|
||||
|
||||
labels_play_ << label_engine_title_
|
||||
<< label_device_title_
|
||||
<< label_filetype_title_
|
||||
<< label_length_title_
|
||||
<< label_samplerate_title_
|
||||
<< label_bitdepth_title_
|
||||
<< label_bitrate_title_
|
||||
<< label_play_albums_
|
||||
<< label_play_lyrics_;
|
||||
|
||||
labels_play_data_ << label_engine_icon_
|
||||
<< label_engine_
|
||||
<< label_device_
|
||||
<< label_device_icon_
|
||||
<< label_filetype_
|
||||
<< label_length_
|
||||
<< label_samplerate_
|
||||
<< label_bitdepth_
|
||||
<< label_bitrate_
|
||||
<< label_play_albums_
|
||||
<< label_play_lyrics_;
|
||||
|
||||
labels_play_all_ = labels_play_ << labels_play_data_;
|
||||
|
||||
QFontDatabase::addApplicationFont(":/fonts/HumongousofEternitySt.ttf");
|
||||
|
||||
connect(widget_album_, SIGNAL(FadeStopFinished()), SLOT(FadeStopFinished()));
|
||||
@@ -270,14 +300,14 @@ void ContextView::Init(Application *app, CollectionView *collectionview, AlbumCo
|
||||
collectionview_ = collectionview;
|
||||
album_cover_choice_controller_ = album_cover_choice_controller;
|
||||
|
||||
widget_album_->Init(album_cover_choice_controller_);
|
||||
widget_album_->Init(this, album_cover_choice_controller_);
|
||||
widget_albums_->Init(app_);
|
||||
lyrics_fetcher_ = new LyricsFetcher(app_->lyrics_providers(), this);
|
||||
|
||||
connect(collectionview_, SIGNAL(TotalSongCountUpdated_()), this, SLOT(UpdateNoSong()));
|
||||
connect(collectionview_, SIGNAL(TotalArtistCountUpdated_()), this, SLOT(UpdateNoSong()));
|
||||
connect(collectionview_, SIGNAL(TotalAlbumCountUpdated_()), this, SLOT(UpdateNoSong()));
|
||||
connect(lyrics_fetcher_, SIGNAL(LyricsFetched(const quint64, const QString&, const QString&)), this, SLOT(UpdateLyrics(const quint64, const QString&, const QString&)));
|
||||
connect(lyrics_fetcher_, SIGNAL(LyricsFetched(quint64, QString, QString)), this, SLOT(UpdateLyrics(quint64, QString, QString)));
|
||||
|
||||
AddActions();
|
||||
|
||||
@@ -299,22 +329,22 @@ void ContextView::AddActions() {
|
||||
|
||||
action_show_albums_ = new QAction(tr("Show albums by artist"), this);
|
||||
action_show_albums_->setCheckable(true);
|
||||
action_show_albums_->setChecked(true);
|
||||
action_show_albums_->setChecked(false);
|
||||
|
||||
action_show_lyrics_ = new QAction(tr("Show song lyrics"), this);
|
||||
action_show_lyrics_->setCheckable(true);
|
||||
action_show_lyrics_->setChecked(false);
|
||||
action_show_lyrics_->setChecked(true);
|
||||
|
||||
action_search_lyrics_ = new QAction(tr("Automatically search for song lyrics"), this);
|
||||
action_search_lyrics_->setCheckable(true);
|
||||
action_search_lyrics_->setChecked(true);
|
||||
|
||||
menu_->addAction(action_show_album_);
|
||||
menu_->addAction(action_show_data_);
|
||||
menu_->addAction(action_show_output_);
|
||||
menu_->addAction(action_show_albums_);
|
||||
menu_->addAction(action_show_lyrics_);
|
||||
menu_->addSeparator();
|
||||
|
||||
QList<QAction*> cover_actions = album_cover_choice_controller_->GetAllActions();
|
||||
cover_actions.append(album_cover_choice_controller_->search_cover_auto_action());
|
||||
menu_->addActions(cover_actions);
|
||||
menu_->addAction(action_search_lyrics_);
|
||||
menu_->addSeparator();
|
||||
|
||||
ReloadSettings();
|
||||
@@ -324,6 +354,7 @@ void ContextView::AddActions() {
|
||||
connect(action_show_output_, SIGNAL(triggered()), this, SLOT(ActionShowOutput()));
|
||||
connect(action_show_albums_, SIGNAL(triggered()), this, SLOT(ActionShowAlbums()));
|
||||
connect(action_show_lyrics_, SIGNAL(triggered()), this, SLOT(ActionShowLyrics()));
|
||||
connect(action_search_lyrics_, SIGNAL(triggered()), this, SLOT(ActionSearchLyrics()));
|
||||
|
||||
}
|
||||
|
||||
@@ -338,8 +369,15 @@ void ContextView::ReloadSettings() {
|
||||
action_show_output_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ENGINE_AND_DEVICE], true).toBool());
|
||||
action_show_albums_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::ALBUMS_BY_ARTIST], false).toBool());
|
||||
action_show_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS], true).toBool());
|
||||
action_search_lyrics_->setChecked(s.value(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SEARCH_LYRICS], true).toBool());
|
||||
font_headline_ = s.value("font_headline", font().family()).toString();
|
||||
font_normal_ = s.value("font_normal", font().family()).toString();
|
||||
font_size_headline_ = s.value("font_size_headline", ContextSettingsPage::kDefaultFontSizeHeadline).toReal();
|
||||
font_size_normal_ = s.value("font_size_normal", font().pointSizeF()).toReal();
|
||||
s.endGroup();
|
||||
|
||||
UpdateFonts();
|
||||
|
||||
if (widget_stacked_->currentWidget() == widget_stop_) {
|
||||
NoSong();
|
||||
}
|
||||
@@ -355,7 +393,7 @@ void ContextView::Stopped() {
|
||||
|
||||
song_playing_ = Song();
|
||||
song_prev_ = Song();
|
||||
lyrics_ = QString();
|
||||
lyrics_.clear();
|
||||
image_original_ = QImage();
|
||||
widget_album_->SetImage();
|
||||
|
||||
@@ -365,19 +403,28 @@ void ContextView::Error() {}
|
||||
|
||||
void ContextView::SongChanged(const Song &song) {
|
||||
|
||||
if (widget_stacked_->currentWidget() == widget_play_ && song_playing_.is_valid() && song == song_playing_) {
|
||||
if (widget_stacked_->currentWidget() == widget_play_ && song_playing_.is_valid() && song == song_playing_ && song.title() == song_playing_.title() && song.album() == song_playing_.album() && song.artist() == song_playing_.artist()) {
|
||||
UpdateSong(song);
|
||||
}
|
||||
else {
|
||||
song_prev_ = song_playing_;
|
||||
song_playing_ = song;
|
||||
lyrics_ = song.lyrics();
|
||||
lyrics_id_ = -1;
|
||||
song_playing_ = song;
|
||||
lyrics_tried_ = false;
|
||||
SetSong();
|
||||
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && !song.artist().isEmpty() && !song.title().isEmpty()) {
|
||||
lyrics_fetcher_->Clear();
|
||||
lyrics_id_ = lyrics_fetcher_->Search(song.effective_albumartist(), song.album(), song.title());
|
||||
}
|
||||
}
|
||||
|
||||
SearchLyrics();
|
||||
|
||||
}
|
||||
|
||||
void ContextView::SearchLyrics() {
|
||||
|
||||
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && action_search_lyrics_->isChecked() && !song_playing_.artist().isEmpty() && !song_playing_.title().isEmpty() && !lyrics_tried_ && lyrics_id_ == -1) {
|
||||
lyrics_fetcher_->Clear();
|
||||
lyrics_tried_ = true;
|
||||
lyrics_id_ = lyrics_fetcher_->Search(song_playing_.effective_albumartist(), song_playing_.album(), song_playing_.title());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -421,14 +468,23 @@ void ContextView::NoSong() {
|
||||
else html += tr("%1 albums").arg(collectionview_->TotalAlbums());
|
||||
html += "<br />";
|
||||
|
||||
label_stop_summary_->setStyleSheet("font: 12pt; font-weight: regular;");
|
||||
label_stop_summary_->setStyleSheet(QString("font: %1pt \"%2\"; font-weight: regular;").arg(font_size_normal_).arg(font_normal_));
|
||||
label_stop_summary_->setText(html);
|
||||
|
||||
}
|
||||
|
||||
void ContextView::UpdateFonts() {
|
||||
|
||||
for (QLabel *l: labels_play_all_) {
|
||||
l->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_normal_).arg(font_size_normal_));
|
||||
}
|
||||
label_play_albums_->setStyleSheet(QString("background-color: #3DADE8; color: rgb(255, 255, 255); font: %1pt \"%2\"; font-weight: regular;").arg(font_size_normal_).arg(font_normal_));
|
||||
|
||||
}
|
||||
|
||||
void ContextView::SetSong() {
|
||||
|
||||
label_top_->setStyleSheet("font: 11pt; font-weight: regular;");
|
||||
label_top_->setStyleSheet(QString("font: %2pt \"%1\"; font-weight: regular;").arg(font_headline_).arg(font_size_headline_));
|
||||
label_top_->setText(QString("<b>%1</b><br/>%2").arg(Utilities::ReplaceMessage(title_fmt_, song_playing_, "<br/>"), Utilities::ReplaceMessage(summary_fmt_, song_playing_, "<br/>")));
|
||||
|
||||
label_stop_summary_->clear();
|
||||
@@ -447,7 +503,16 @@ void ContextView::SetSong() {
|
||||
if (action_show_data_->isChecked()) {
|
||||
widget_play_data_->show();
|
||||
label_filetype_->setText(song_playing_.TextForFiletype());
|
||||
label_length_->setText(Utilities::PrettyTimeNanosec(song_playing_.length_nanosec()));
|
||||
if (song_playing_.length_nanosec() <= 0) {
|
||||
label_length_title_->hide();
|
||||
label_length_->hide();
|
||||
label_length_->clear();
|
||||
}
|
||||
else {
|
||||
label_length_title_->show();
|
||||
label_length_->show();
|
||||
label_length_->setText(Utilities::PrettyTimeNanosec(song_playing_.length_nanosec()));
|
||||
}
|
||||
if (song_playing_.samplerate() <= 0) {
|
||||
label_samplerate_title_->hide();
|
||||
label_samplerate_->hide();
|
||||
@@ -496,7 +561,7 @@ void ContextView::SetSong() {
|
||||
if (app_->player()->engine()) enginetype = app_->player()->engine()->type();
|
||||
QIcon icon_engine = IconLoader::Load(EngineName(enginetype), 32);
|
||||
|
||||
label_engine_icon_->setPixmap(icon_engine.pixmap(icon_engine.availableSizes().last()));
|
||||
label_engine_icon_->setPixmap(icon_engine.pixmap(QSize(32, 32)));
|
||||
label_engine_->setText(EngineDescription(enginetype));
|
||||
spacer_play_output_->changeSize(20, 20, QSizePolicy::Fixed);
|
||||
|
||||
@@ -513,7 +578,7 @@ void ContextView::SetSong() {
|
||||
label_device_icon_->show();
|
||||
label_device_->show();
|
||||
QIcon icon_device = IconLoader::Load(device.iconname, 32);
|
||||
label_device_icon_->setPixmap(icon_device.pixmap(icon_device.availableSizes().last()));
|
||||
label_device_icon_->setPixmap(icon_device.pixmap(QSize(32, 32)));
|
||||
label_device_->setText(device.description);
|
||||
}
|
||||
else {
|
||||
@@ -542,7 +607,6 @@ void ContextView::SetSong() {
|
||||
label_play_albums_->show();
|
||||
widget_albums_->show();
|
||||
label_play_albums_->setText("<b>" + tr("Albums by %1").arg( song_playing_.artist().toHtmlEscaped()) + "</b>");
|
||||
label_play_albums_->setStyleSheet("background-color: #3DADE8; color: rgb(255, 255, 255); font: 11pt;");
|
||||
for (CollectionBackend::Album album : albumlist) {
|
||||
SongList songs = app_->collection_backend()->GetSongs(song_playing_.artist(), album.album_name, opt);
|
||||
widget_albums_->albums_model()->AddSongs(songs);
|
||||
@@ -583,7 +647,18 @@ void ContextView::UpdateSong(const Song &song) {
|
||||
|
||||
if (action_show_data_->isChecked()) {
|
||||
if (song.filetype() != song_playing_.filetype()) label_filetype_->setText(song.TextForFiletype());
|
||||
if (song.length_nanosec() != song_playing_.length_nanosec()) label_length_->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
|
||||
if (song.length_nanosec() != song_playing_.length_nanosec()){
|
||||
if (song.length_nanosec() <= 0) {
|
||||
label_length_title_->hide();
|
||||
label_length_->hide();
|
||||
label_length_->clear();
|
||||
}
|
||||
else {
|
||||
label_length_title_->show();
|
||||
label_length_->show();
|
||||
label_length_->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
|
||||
}
|
||||
}
|
||||
if (song.samplerate() != song_playing_.samplerate()) {
|
||||
if (song.samplerate() <= 0) {
|
||||
label_samplerate_title_->hide();
|
||||
@@ -628,21 +703,7 @@ void ContextView::UpdateSong(const Song &song) {
|
||||
|
||||
void ContextView::ResetSong() {
|
||||
|
||||
QList <QLabel *> labels_play_data;
|
||||
|
||||
labels_play_data << label_engine_icon_
|
||||
<< label_engine_
|
||||
<< label_device_
|
||||
<< label_device_icon_
|
||||
<< label_filetype_
|
||||
<< label_length_
|
||||
<< label_samplerate_
|
||||
<< label_bitdepth_
|
||||
<< label_bitrate_
|
||||
<< label_play_albums_
|
||||
<< label_play_lyrics_;
|
||||
|
||||
for (QLabel *l: labels_play_data) {
|
||||
for (QLabel *l: labels_play_data_) {
|
||||
l->clear();
|
||||
}
|
||||
|
||||
@@ -661,7 +722,7 @@ void ContextView::UpdateLyrics(const quint64 id, const QString &provider, const
|
||||
}
|
||||
|
||||
void ContextView::contextMenuEvent(QContextMenuEvent *e) {
|
||||
if (menu_ && widget_stacked_->currentWidget() == widget_play_) menu_->popup(mapToGlobal(e->pos()));
|
||||
if (menu_) menu_->popup(mapToGlobal(e->pos()));
|
||||
}
|
||||
|
||||
void ContextView::dragEnterEvent(QDragEnterEvent *e) {
|
||||
@@ -684,9 +745,7 @@ void ContextView::dropEvent(QDropEvent *e) {
|
||||
|
||||
}
|
||||
|
||||
void ContextView::AlbumCoverLoaded(const Song &song, const QUrl &cover_url, const QImage &image) {
|
||||
|
||||
Q_UNUSED(cover_url);
|
||||
void ContextView::AlbumCoverLoaded(const Song &song, const QImage &image) {
|
||||
|
||||
if (song != song_playing_ || image == image_original_) return;
|
||||
|
||||
@@ -742,11 +801,22 @@ void ContextView::ActionShowLyrics() {
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
s.setValue(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SONG_LYRICS], action_show_lyrics_->isChecked());
|
||||
s.endGroup();
|
||||
|
||||
if (song_playing_.is_valid()) SetSong();
|
||||
|
||||
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked() && !song_playing_.artist().isEmpty() && !song_playing_.title().isEmpty()) {
|
||||
lyrics_fetcher_->Clear();
|
||||
lyrics_id_ = lyrics_fetcher_->Search(song_playing_.artist(), song_playing_.album(), song_playing_.title());
|
||||
}
|
||||
SearchLyrics();
|
||||
|
||||
}
|
||||
|
||||
void ContextView::ActionSearchLyrics() {
|
||||
|
||||
QSettings s;
|
||||
s.beginGroup(ContextSettingsPage::kSettingsGroup);
|
||||
s.setValue(ContextSettingsPage::kSettingsGroupEnable[ContextSettingsPage::ContextSettingsOrder::SEARCH_LYRICS], action_search_lyrics_->isChecked());
|
||||
s.endGroup();
|
||||
|
||||
if (song_playing_.is_valid()) SetSong();
|
||||
|
||||
SearchLyrics();
|
||||
|
||||
}
|
||||
|
||||