Compare commits

..

8 Commits

Author SHA1 Message Date
John Maguire
f9f515d7f2 ffs 2023-07-11 00:09:42 +01:00
John Maguire
0123fe62b7 clang-format 2023-07-11 00:07:52 +01:00
John Maguire
5e9354c842 Maybe still support Linux 2023-07-11 00:05:52 +01:00
John Maguire
eeb0d0a40c Remove deprecated mac deps 2023-07-11 00:04:10 +01:00
John Maguire
2e359e6999 re-enable builds 2023-07-11 00:02:27 +01:00
John Maguire
ec98c3b850 Update gst search paths 2023-07-11 00:02:09 +01:00
John Maguire
b74564a06f Fixes for protobuf/absl C++17 requirement 2023-07-11 00:02:09 +01:00
John Maguire
126da35fef Try bumping to macOS 11 2023-07-11 00:02:09 +01:00
111 changed files with 221977 additions and 35258 deletions

View File

@ -10,7 +10,7 @@ on:
jobs: jobs:
lint: lint:
name: Lint name: Lint
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v2 uses: actions/checkout@v2
@ -24,16 +24,16 @@ jobs:
push_translations: push_translations:
name: Push translation sources to Transifex name: Push translation sources to Transifex
if: github.ref == 'refs/heads/master' # if: github.ref == 'refs/heads/master'
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: ubuntu:noble image: ubuntu:bionic
steps: steps:
- uses: supplypike/setup-bin@v3 - uses: supplypike/setup-bin@v3
with: with:
uri: https://github.com/transifex/cli/releases/download/v1.6.17/tx-linux-amd64.tar.gz uri: https://github.com/transifex/cli/releases/download/v1.6.7/tx-linux-amd64.tar.gz
name: tx name: tx
version: 1.6.17 version: 1.6.7
- name: Install dependencies - name: Install dependencies
env: env:
DEBIAN_FRONTEND: noninteractive DEBIAN_FRONTEND: noninteractive
@ -49,7 +49,7 @@ jobs:
libchromaprint-dev libchromaprint-dev
libdbus-1-dev libdbus-1-dev
libfftw3-dev libfftw3-dev
libglew-dev libglew1.5-dev
libglib2.0-dev libglib2.0-dev
libgpod-dev libgpod-dev
libgstreamer-plugins-base1.0-dev libgstreamer-plugins-base1.0-dev
@ -94,50 +94,43 @@ jobs:
create_release: create_release:
name: Create GitHub Release name: Create GitHub Release
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
if: github.ref == 'refs/heads/master' if: github.ref == 'refs/heads/master'
needs: needs:
- build_bionic_64
- build_bullseye_64 - build_bullseye_64
- build_buster_64 - build_buster_64
- build_fedora_39 - build_fedora_36
- build_fedora_40 - build_fedora_37
- build_fedora_38
- build_focal_64 - build_focal_64
- build_jammy_64 - build_jammy_64
- build_noble_64 - build_kinetic_64
# - build_mac # - build_mac
- build_mingw - build_mingw
- build_source - build_source
permissions:
contents: write
steps: steps:
- uses: actions/checkout@v1.2.0 - uses: actions/checkout@v1.2.0
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v2
with: with:
path: release_artifacts path: release_artifacts
- name: Create draft pre-release - name: Create draft pre-release
id: tag_name
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |
set -x set -x
VERSION=$(echo release_artifacts/**/*.tar.xz | sed -e 's/.*clementine-\(.*\).tar.xz/\1/') VERSION=$(echo release_artifacts/**/*.tar.xz | sed -e 's/.*clementine-\(.*\).tar.xz/\1/')
echo "Version: ${VERSION}" echo "Version: ${VERSION}"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT" assets=()
- name: Create draft pre-release for asset in $(find release_artifacts -type f); do
uses: softprops/action-gh-release@v2 echo "Adding asset: ${asset}"
env: assets+=("-a" "$asset")
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} done
with: hub release create -p "${assets[@]}" -m "$VERSION" -t "$GITHUB_SHA" "$VERSION"
name: ${{ steps.tag_name.outputs.version }}
tag_name: ${{ steps.tag_name.outputs.version }}
files: "release_artifacts/**/*"
fail_on_unmatched_files: true
draft: false
prerelease: false
build_source: build_source:
name: Build source tarball name: Build source tarball
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: ubuntu:focal image: ubuntu:focal
steps: steps:
@ -190,16 +183,16 @@ jobs:
- name: Build source tarball - name: Build source tarball
working-directory: bin working-directory: bin
run: ../dist/maketarball.sh run: ../dist/maketarball.sh
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_source name: release_source
path: bin/clementine-*.tar.xz path: bin/clementine-*.tar.xz
build_fedora_39: build_fedora_36:
name: Build Fedora 39 RPM name: Build Fedora 36 RPM
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: fedora:39 image: fedora:36
env: env:
RPM_BUILD_NCPUS: "2" RPM_BUILD_NCPUS: "2"
steps: steps:
@ -210,7 +203,6 @@ jobs:
alsa-lib-devel alsa-lib-devel
boost-devel boost-devel
cmake cmake
cryptopp
cryptopp-devel cryptopp-devel
dbus-devel dbus-devel
desktop-file-utils desktop-file-utils
@ -240,9 +232,8 @@ jobs:
qt5-qtbase-devel qt5-qtbase-devel
qt5-qtx11extras-devel qt5-qtx11extras-devel
qt5-rpm-macros qt5-rpm-macros
qtsingleapplication-qt5-devel
qtsinglecoreapplication-qt5-devel
rpmdevtools rpmdevtools
sha2-devel
sparsehash-devel sparsehash-devel
sqlite-devel sqlite-devel
taglib-devel taglib-devel
@ -252,7 +243,7 @@ jobs:
run: git config --global --add safe.directory ${GITHUB_WORKSPACE} run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: cmake - name: cmake
working-directory: bin working-directory: bin
run: cmake -DUSE_SYSTEM_QTSINGLEAPPLICATION=On .. run: cmake ..
- name: Build source tarball - name: Build source tarball
working-directory: bin working-directory: bin
run: ../dist/maketarball.sh run: ../dist/maketarball.sh
@ -264,16 +255,16 @@ jobs:
- name: Build RPM - name: Build RPM
working-directory: bin working-directory: bin
run: rpmbuild -ba ../dist/clementine.spec run: rpmbuild -ba ../dist/clementine.spec
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_fedora_39 name: release_fedora_36
path: ~/rpmbuild/RPMS/*/clementine-*.rpm path: ~/rpmbuild/RPMS/*/clementine-*.rpm
build_fedora_40: build_fedora_37:
name: Build Fedora 40 RPM name: Build Fedora 37 RPM
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: fedora:40 image: fedora:37
env: env:
RPM_BUILD_NCPUS: "2" RPM_BUILD_NCPUS: "2"
steps: steps:
@ -284,7 +275,6 @@ jobs:
alsa-lib-devel alsa-lib-devel
boost-devel boost-devel
cmake cmake
cryptopp
cryptopp-devel cryptopp-devel
dbus-devel dbus-devel
desktop-file-utils desktop-file-utils
@ -314,9 +304,8 @@ jobs:
qt5-qtbase-devel qt5-qtbase-devel
qt5-qtx11extras-devel qt5-qtx11extras-devel
qt5-rpm-macros qt5-rpm-macros
qtsingleapplication-qt5-devel
qtsinglecoreapplication-qt5-devel
rpmdevtools rpmdevtools
sha2-devel
sparsehash-devel sparsehash-devel
sqlite-devel sqlite-devel
taglib-devel taglib-devel
@ -326,7 +315,7 @@ jobs:
run: git config --global --add safe.directory ${GITHUB_WORKSPACE} run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: cmake - name: cmake
working-directory: bin working-directory: bin
run: cmake -DUSE_SYSTEM_QTSINGLEAPPLICATION=On .. run: cmake ..
- name: Build source tarball - name: Build source tarball
working-directory: bin working-directory: bin
run: ../dist/maketarball.sh run: ../dist/maketarball.sh
@ -338,14 +327,87 @@ jobs:
- name: Build RPM - name: Build RPM
working-directory: bin working-directory: bin
run: rpmbuild -ba ../dist/clementine.spec run: rpmbuild -ba ../dist/clementine.spec
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_fedora_40 name: release_fedora_37
path: ~/rpmbuild/RPMS/*/clementine-*.rpm path: ~/rpmbuild/RPMS/*/clementine-*.rpm
build_fedora_38:
name: Build Fedora 38 RPM
runs-on: ubuntu-22.04
container:
image: fedora:38
env:
RPM_BUILD_NCPUS: "2"
steps:
- name: Install dependencies
run: >
dnf install --assumeyes
@development-tools
alsa-lib-devel
boost-devel
cmake
cryptopp-devel
dbus-devel
desktop-file-utils
fftw-devel
gcc-c++
gettext
git
glew-devel
gstreamer1-devel
gstreamer1-plugins-base-devel
hicolor-icon-theme
libappstream-glib
libcdio-devel
libchromaprint-devel
libgpod-devel
liblastfm-qt5-devel
libmtp-devel
libnotify-devel
openssh
pkgconfig
protobuf-compiler
protobuf-devel
pulseaudio-libs-devel
qca-qt5-devel
qca-qt5-ossl
qt5-linguist
qt5-qtbase-devel
qt5-qtx11extras-devel
qt5-rpm-macros
rpmdevtools
sha2-devel
sparsehash-devel
sqlite-devel
taglib-devel
tar
- uses: actions/checkout@v1.2.0
- name: git hackery
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: cmake
working-directory: bin
run: cmake ..
- name: Build source tarball
working-directory: bin
run: ../dist/maketarball.sh
- name: Create rpmbuild directory
run: mkdir -p ~/rpmbuild/SOURCES
- name: Move source tarball
working-directory: bin
run: mv clementine-*.tar.xz ~/rpmbuild/SOURCES
- name: Build RPM
working-directory: bin
run: rpmbuild -ba ../dist/clementine.spec
- uses: actions/upload-artifact@v2
with:
name: release_fedora_38
path: ~/rpmbuild/RPMS/*/clementine-*.rpm
build_mingw: build_mingw:
name: Build Windows Installer name: Build Windows Installer
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: eu.gcr.io/clementine-data/mingw-w64:latest image: eu.gcr.io/clementine-data/mingw-w64:latest
env: env:
@ -531,14 +593,73 @@ jobs:
- name: Build Windows installer - name: Build Windows installer
working-directory: dist/windows working-directory: dist/windows
run: makensis clementine.nsi run: makensis clementine.nsi
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_mingw name: release_mingw
path: dist/windows/ClementineSetup*.exe path: dist/windows/ClementineSetup*.exe
build_bionic_64:
name: Build Ubuntu Bionic 64-bit deb
runs-on: ubuntu-22.04
container:
image: ubuntu:bionic
steps:
- name: Install dependencies
env:
DEBIAN_FRONTEND: noninteractive
run: >
apt-get update && apt-get install -y
build-essential
cmake
gettext
git
libasound2-dev
libboost-dev
libcdio-dev
libchromaprint-dev
libdbus-1-dev
libfftw3-dev
libglew1.5-dev
libglib2.0-dev
libgpod-dev
libgstreamer-plugins-base1.0-dev
libgstreamer1.0-dev
liblastfm5-dev
libmtp-dev
libprotobuf-dev
libpulse-dev
libqt5x11extras5-dev
libsqlite3-dev
libtag1-dev
pkg-config
protobuf-compiler
qtbase5-dev
qttools5-dev-tools
qttools5-dev
libsparsehash-dev
ssh
- uses: actions/checkout@v1.2.0
- name: git hackery
run: git config --global --add safe.directory ${GITHUB_WORKSPACE}
- name: cmake
working-directory: bin
run: >
cmake ..
-DWITH_DEBIAN=ON
-DDEB_ARCH=amd64
-DDEB_DIST=bionic
-DENABLE_SPOTIFY_BLOB=OFF
- name: make
working-directory: bin
run : make -j2 deb
- uses: actions/upload-artifact@v2
with:
name: release_bionic_64
path: bin/clementine_*.deb
build_bullseye_64: build_bullseye_64:
name: Build Debian Bullseye 64-bit deb name: Build Debian Bullseye 64-bit deb
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: debian:bullseye image: debian:bullseye
steps: steps:
@ -591,14 +712,14 @@ jobs:
- name: make - name: make
working-directory: bin working-directory: bin
run : make -j2 deb run : make -j2 deb
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_bullseye_64 name: release_bullseye_64
path: bin/clementine_*.deb path: bin/clementine_*.deb
build_buster_64: build_buster_64:
name: Build Debian Buster 64-bit deb name: Build Debian Buster 64-bit deb
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: debian:buster image: debian:buster
steps: steps:
@ -650,14 +771,14 @@ jobs:
- name: make - name: make
working-directory: bin working-directory: bin
run : make -j2 deb run : make -j2 deb
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_buster_64 name: release_buster_64
path: bin/clementine_*.deb path: bin/clementine_*.deb
build_focal_64: build_focal_64:
name: Build Ubuntu Focal 64-bit deb name: Build Ubuntu Focal 64-bit deb
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: ubuntu:focal image: ubuntu:focal
steps: steps:
@ -715,14 +836,14 @@ jobs:
- name: make - name: make
working-directory: bin working-directory: bin
run : make -j2 deb run : make -j2 deb
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_focal_64 name: release_focal_64
path: bin/clementine_*.deb path: bin/clementine_*.deb
build_jammy_64: build_jammy_64:
name: Build Ubuntu Jammy 64-bit deb name: Build Ubuntu Jammy 64-bit deb
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: ubuntu:jammy image: ubuntu:jammy
steps: steps:
@ -783,16 +904,16 @@ jobs:
- name: make - name: make
working-directory: bin working-directory: bin
run : make -j2 deb run : make -j2 deb
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_jammy_64 name: release_jammy_64
path: bin/clementine_*.deb path: bin/clementine_*.deb
build_noble_64: build_kinetic_64:
name: Build Ubuntu Noble 64-bit deb name: Build Ubuntu Kinetic 64-bit deb
runs-on: ubuntu-24.04 runs-on: ubuntu-22.04
container: container:
image: ubuntu:noble image: ubuntu:kinetic
steps: steps:
- name: Install dependencies - name: Install dependencies
env: env:
@ -846,20 +967,19 @@ jobs:
cmake .. cmake ..
-DWITH_DEBIAN=ON -DWITH_DEBIAN=ON
-DDEB_ARCH=amd64 -DDEB_ARCH=amd64
-DDEB_DIST=noble -DDEB_DIST=kinetic
-DENABLE_SPOTIFY_BLOB=OFF -DENABLE_SPOTIFY_BLOB=OFF
- name: make - name: make
working-directory: bin working-directory: bin
run : make -j2 deb run : make -j2 deb
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_noble_64 name: release_kinetic_64
path: bin/clementine_*.deb path: bin/clementine_*.deb
build_mac: build_mac:
if: false
name: Build Mac DMG name: Build Mac DMG
runs-on: macos-10.15 runs-on: macos-11
steps: steps:
- uses: actions/checkout@v1.2.0 - uses: actions/checkout@v1.2.0
- name: git hackery - name: git hackery
@ -899,7 +1019,6 @@ jobs:
Qt5LinguistTools_DIR: /usr/local/opt/qt5/lib/cmake/Qt5LinguistTools Qt5LinguistTools_DIR: /usr/local/opt/qt5/lib/cmake/Qt5LinguistTools
GST_SCANNER_PATH: /usr/local/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner GST_SCANNER_PATH: /usr/local/opt/gstreamer/libexec/gstreamer-1.0/gst-plugin-scanner
GST_PLUGIN_PATH: /usr/local/lib/gstreamer-1.0 GST_PLUGIN_PATH: /usr/local/lib/gstreamer-1.0
DEVELOPER_DIR: /Applications/Xcode_10.3.app/Contents/Developer
working-directory: bin working-directory: bin
run: > run: >
cmake .. cmake ..
@ -909,6 +1028,7 @@ jobs:
-DGETTEXT_MSGMERGE_EXECUTABLE=/usr/local/opt/gettext/bin/msgmerge -DGETTEXT_MSGMERGE_EXECUTABLE=/usr/local/opt/gettext/bin/msgmerge
-DGETTEXT_MSGFMT_EXECUTABLE=/usr/local/opt/gettext/bin/msgfmt -DGETTEXT_MSGFMT_EXECUTABLE=/usr/local/opt/gettext/bin/msgfmt
-DGETTEXT_XGETTEXT_EXECUTABLE=/usr/local/opt/gettext/bin/xgettext -DGETTEXT_XGETTEXT_EXECUTABLE=/usr/local/opt/gettext/bin/xgettext
-DDEVELOPER_DIR=$(xcode-select -p)
- name: make - name: make
working-directory: bin working-directory: bin
run: make -j2 run: make -j2
@ -918,7 +1038,7 @@ jobs:
- name: Build DMG - name: Build DMG
working-directory: bin working-directory: bin
run: make dmg run: make dmg
- uses: actions/upload-artifact@v4 - uses: actions/upload-artifact@v2
with: with:
name: release_mac name: release_mac
path: bin/clementine-*.dmg path: bin/clementine-*.dmg

View File

@ -0,0 +1,128 @@
/* Copyright 2014, Uwe L. Korn <uwelk@xhochy.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#include "Json.h"
// Qt version specific includes
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
#include <QJsonDocument>
#include <QMetaProperty>
#else
#include <qjson/parser.h>
#include <qjson/qobjecthelper.h>
#include <qjson/serializer.h>
#endif
namespace QJsonWrapper
{
QVariantMap
qobject2qvariant( const QObject* object )
{
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
QVariantMap map;
if ( object == NULL )
{
return map;
}
const QMetaObject* metaObject = object->metaObject();
for ( int i = 0; i < metaObject->propertyCount(); ++i )
{
QMetaProperty metaproperty = metaObject->property( i );
if ( metaproperty.isReadable() )
{
map[ QLatin1String( metaproperty.name() ) ] = object->property( metaproperty.name() );
}
}
return map;
#else
return QJson::QObjectHelper::qobject2qvariant( object );
#endif
}
void
qvariant2qobject( const QVariantMap& variant, QObject* object )
{
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
for ( QVariantMap::const_iterator iter = variant.begin(); iter != variant.end(); ++iter )
{
QVariant property = object->property( iter.key().toLatin1() );
Q_ASSERT( property.isValid() );
if ( property.isValid() )
{
QVariant value = iter.value();
if ( value.canConvert( property.type() ) )
{
value.convert( property.type() );
object->setProperty( iter.key().toLatin1(), value );
} else if ( QString( QLatin1String("QVariant") ).compare( QLatin1String( property.typeName() ) ) == 0 ) {
object->setProperty( iter.key().toLatin1(), value );
}
}
}
#else
QJson::QObjectHelper::qvariant2qobject( variant, object );
#endif
}
QVariant
parseJson( const QByteArray& jsonData, bool* ok )
{
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson( jsonData, &error );
if ( ok != NULL )
{
*ok = ( error.error == QJsonParseError::NoError );
}
return doc.toVariant();
#else
QJson::Parser p;
return p.parse( jsonData, ok );
#endif
}
QByteArray
toJson( const QVariant &variant, bool* ok )
{
#if QT_VERSION >= QT_VERSION_CHECK( 5, 0, 0 )
QJsonDocument doc = QJsonDocument::fromVariant( variant );
if ( ok != NULL )
{
*ok = !doc.isNull();
}
return doc.toJson( QJsonDocument::Compact );
#else
QJson::Serializer serializer;
QByteArray ret = serializer.serialize(variant);
if ( ok != NULL )
{
*ok = !ret.isNull();
}
return ret;
#endif
}
}

View File

@ -0,0 +1,36 @@
/* Copyright 2014, Uwe L. Korn <uwelk@xhochy.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
#pragma once
#ifndef QJSONWRAPPER_JSON_H
#define QJSONWRAPPER_JSON_H
#include <QVariant>
namespace QJsonWrapper
{
QVariantMap qobject2qvariant( const QObject* object );
void qvariant2qobject( const QVariantMap& variant, QObject* object );
QVariant parseJson( const QByteArray& jsonData, bool* ok = 0 );
QByteArray toJson( const QVariant &variant, bool* ok = 0 );
}
#endif // QJSONWRAPPER_JSON_H

View File

@ -24,6 +24,8 @@ set(BUILD_PROJECTM_STATIC ON)
set(DISABLE_NATIVE_PRESETS ON) set(DISABLE_NATIVE_PRESETS ON)
set(DISABLE_MILKDROP_PRESETS OFF) set(DISABLE_MILKDROP_PRESETS OFF)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
pkg_check_modules(GLEW glew) pkg_check_modules(GLEW glew)
if(DISABLE_NATIVE_PRESETS) if(DISABLE_NATIVE_PRESETS)
@ -173,7 +175,7 @@ if(BUNDLE_PROJECTM_PRESETS)
configure_file( configure_file(
"${preset}" "${preset}"
"${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources/projectm-presets/${PRESET_NAME}" "${CMAKE_BINARY_DIR}/clementine.app/Contents/Resources/projectm-presets/${PRESET_NAME}"
COPY_ONLY COPYONLY
) )
endforeach (preset) endforeach (preset)
else (APPLE) else (APPLE)

View File

@ -17,8 +17,11 @@
#include "Waveform.hpp" #include "Waveform.hpp"
#include <algorithm> #include <algorithm>
#include <functional>
#include "BeatDetect.hpp" #include "BeatDetect.hpp"
using std::placeholders::_1;
typedef float floatPair[2]; typedef float floatPair[2];
typedef float floatTriple[3]; typedef float floatTriple[3];
typedef float floatQuad[4]; typedef float floatQuad[4];
@ -65,8 +68,8 @@ void Waveform::Draw(RenderContext &context)
float mult= scaling*( spectrum ? 0.015f :1.0f); float mult= scaling*( spectrum ? 0.015f :1.0f);
std::transform(&value1[0],&value1[samples],&value1[0],std::bind2nd(std::multiplies<float>(),mult)); std::transform(&value1[0],&value1[samples],&value1[0],std::bind(std::multiplies<float>(),_1, mult));
std::transform(&value2[0],&value2[samples],&value2[0],std::bind2nd(std::multiplies<float>(),mult)); std::transform(&value2[0],&value2[samples],&value2[0],std::bind(std::multiplies<float>(),_1,mult));
WaveformContext waveContext(samples, context.beatDetect); WaveformContext waveContext(samples, context.beatDetect);

View File

@ -15,6 +15,7 @@
// License along with this library; if not, write to the Free Software // License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#include <random>
namespace omptl namespace omptl
{ {
@ -463,14 +464,15 @@ template <class RandomAccessIterator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
const unsigned P) const unsigned P)
{ {
return ::std::random_shuffle(first, last); std::random_device rd;
return ::std::shuffle(first, last, std::mt19937(rd()));
} }
template <class RandomAccessIterator, class RandomNumberGenerator> template <class RandomAccessIterator, class RandomNumberGenerator>
void random_shuffle(RandomAccessIterator first, RandomAccessIterator last, void random_shuffle(RandomAccessIterator first, RandomAccessIterator last,
RandomNumberGenerator &rgen, const unsigned P) RandomNumberGenerator &rgen, const unsigned P)
{ {
return ::std::random_shuffle(first, last, rgen); return ::std::shuffle(first, last, rgen);
} }
template <class ForwardIterator, class T> template <class ForwardIterator, class T>

View File

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.0.0) cmake_minimum_required(VERSION 3.0.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x")
set(SINGLEAPP-SOURCES set(SINGLEAPP-SOURCES
qtlocalpeer.cpp qtlocalpeer.cpp

View File

@ -9,11 +9,6 @@ brew 'glew'
brew 'glib' brew 'glib'
brew 'gnome-common' brew 'gnome-common'
brew 'google-sparsehash' brew 'google-sparsehash'
brew 'gst-libav'
brew 'gst-plugins-bad'
brew 'gst-plugins-base'
brew 'gst-plugins-good'
brew 'gst-plugins-ugly'
brew 'gstreamer' brew 'gstreamer'
brew 'gtk-doc' brew 'gtk-doc'
brew 'intltool' brew 'intltool'

View File

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.13.0)
project(clementine) project(clementine)
cmake_minimum_required(VERSION 3.0.0)
cmake_policy(SET CMP0053 OLD) cmake_policy(SET CMP0053 OLD)
include(CheckCXXCompilerFlag) include(CheckCXXCompilerFlag)
@ -15,14 +15,13 @@ include(cmake/Format.cmake)
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "")
set(CMAKE_CXX_STANDARD 17)
if (CMAKE_CXX_COMPILER MATCHES ".*clang") if (CMAKE_CXX_COMPILER MATCHES ".*clang")
set(CMAKE_COMPILER_IS_CLANGXX 1) set(CMAKE_COMPILER_IS_CLANGXX 1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-uninitialized") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-uninitialized")
if (APPLE) endif ()
if (APPLE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --stdlib=libc++")
endif ()
endif () endif ()
find_program(CCACHE_EXECUTABLE NAMES ccache) find_program(CCACHE_EXECUTABLE NAMES ccache)
@ -47,8 +46,9 @@ endif(OPENGL_FOUND)
find_package(Boost REQUIRED) find_package(Boost REQUIRED)
find_package(Gettext REQUIRED) find_package(Gettext REQUIRED)
find_package(PkgConfig REQUIRED) find_package(PkgConfig REQUIRED)
find_package(protobuf) if (APPLE)
if(NOT protobuf_FOUND) find_package(protobuf REQUIRED CONFIG)
else()
find_package(Protobuf REQUIRED) find_package(Protobuf REQUIRED)
endif() endif()
find_package(FFTW3) find_package(FFTW3)
@ -351,18 +351,11 @@ include_directories("3rdparty/qsqlite")
# When/if upstream accepts our patches then these options can be used to link # When/if upstream accepts our patches then these options can be used to link
# to system installed qtsingleapplication instead. # to system installed qtsingleapplication instead.
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use the system-provided QtSingleApplication library (needs to have clementine patches, but these seem to be in Qt5)" OFF) option(USE_SYSTEM_QTSINGLEAPPLICATION "Don't set this option unless your system QtSingleApplication library has been compiled with the Clementine patches in 3rdparty" OFF)
if(USE_SYSTEM_QTSINGLEAPPLICATION) if(USE_SYSTEM_QTSINGLEAPPLICATION)
find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES qt5/QtSolutions REQUIRED) find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES qt5/QtSolutions)
find_library(QTSINGLEAPPLICATION_LIBRARIES Qt5Solutions_SingleApplication-2.6 REQUIRED) find_library(QTSINGLEAPPLICATION_LIBRARIES Qt5Solutions_SingleApplication-2.6)
add_library(qtsingleapplication INTERFACE) find_library(QTSINGLECOREAPPLICATION_LIBRARIES Qt5Solutions_SingleCoreApplication-2.6)
target_link_libraries(qtsingleapplication INTERFACE QTSINGLEAPPLICATION_LIBRARIES)
target_include_directories(qtsingleapplication INTERFACE QTSINGLEAPPLICATION_INCLUDE_DIRS)
find_path(QTSINGLECOREAPPLICATION_INCLUDE_DIRS qtsinglecoreapplication.h PATH_SUFFIXES qt5/QtSolutions REQUIRED)
find_library(QTSINGLECOREAPPLICATION_LIBRARIES Qt5Solutions_SingleCoreApplication-2.6 REQUIRED)
add_library(qtsinglecoreapplication INTERFACE)
target_link_libraries(qtsinglecoreapplication INTERFACE QTSINGLECOREAPPLICATION_LIBRARIES)
target_include_directories(qtsinglecoreapplication INTERFACE QTSINGLECOREAPPLICATION_INCLUDE_DIRS)
else(USE_SYSTEM_QTSINGLEAPPLICATION) else(USE_SYSTEM_QTSINGLEAPPLICATION)
add_subdirectory(3rdparty/qtsingleapplication) add_subdirectory(3rdparty/qtsingleapplication)
set(QTSINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtsingleapplication) set(QTSINGLEAPPLICATION_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/qtsingleapplication)

View File

@ -41,7 +41,7 @@ Compile and install:
cd bin cd bin
cmake .. cmake ..
make -j$(nproc) make -j8
sudo make install sudo make install
See the Wiki for more instructions and a list of dependencies: See the Wiki for more instructions and a list of dependencies:

View File

@ -88,6 +88,17 @@
<item begin="&lt;/a" end="&gt;"/> <item begin="&lt;/a" end="&gt;"/>
</exclude> </exclude>
</provider> </provider>
<provider name="hindilyrics.net (Bollywood songs)" title="{title} ({album})" charset="utf-8" url="http://www.hindilyrics.net/lyrics/of-{Title}.html">
<urlFormat replace=" _@;\/&quot;'()[]" with="%20"/>
<urlFormat replace="?" with=""/>
<extract>
<item begin="&lt;div class=nm&gt;Movie&lt;/div&gt;:" end="&lt;/pre&gt;"/>
</extract>
<exclude>
<item begin="&lt;span class=" end="&quot;&gt;"/>
</exclude>
<invalidIndicator value="Couldn't find that page."/>
</provider>
<provider name="letras.mus.br" title="" charset="utf-8" url="https://www.letras.mus.br/winamp.php?musica={title}&amp;artista={artist}"> <provider name="letras.mus.br" title="" charset="utf-8" url="https://www.letras.mus.br/winamp.php?musica={title}&amp;artista={artist}">
<urlFormat replace="_@,;&amp;\/&quot;" with="_"/> <urlFormat replace="_@,;&amp;\/&quot;" with="_"/>
<urlFormat replace=" " with="+"/> <urlFormat replace=" " with="+"/>
@ -103,6 +114,13 @@
</extract> </extract>
<invalidIndicator value="ERROR"/> <invalidIndicator value="ERROR"/>
</provider> </provider>
<provider name="loudson.gs" title="" charset="utf-8" url="http://www.loudson.gs/{a}/{artist}/{album}/{title}">
<urlFormat replace=" _@,;&amp;\/&quot;" with="-"/>
<urlFormat replace="." with=""/>
<extract>
<item tag="&lt;div class=&quot;middle_col_TracksLyrics &quot;&gt;"/>
</extract>
</provider>
<provider name="lyrics.com" title="{artist} - {title} Lyrics" charset="utf-8" url="http://www.lyrics.com/lyrics/{artist}/{title}.html"> <provider name="lyrics.com" title="{artist} - {title} Lyrics" charset="utf-8" url="http://www.lyrics.com/lyrics/{artist}/{title}.html">
<urlFormat replace=" _@,;&amp;\/&quot;" with="-"/> <urlFormat replace=" _@,;&amp;\/&quot;" with="-"/>
<urlFormat replace="'." with=""/> <urlFormat replace="'." with=""/>
@ -176,6 +194,14 @@
</extract> </extract>
<invalidIndicator value="Page not Found"/> <invalidIndicator value="Page not Found"/>
</provider> </provider>
<provider name="lyricstime.com" title="{artist} - {title} Lyrics" charset="iso-8859-1" url="http://www.lyricstime.com/{artist}-{title}-lyrics.html">
<urlFormat replace=" _@,;&amp;\/&quot;'" with="-"/>
<urlFormat replace="." with=""/>
<extract>
<item tag="&lt;div id=&quot;songlyrics&quot; &gt;"/>
<item tag="&lt;p&gt;"/>
</extract>
</provider>
<provider name="lyriki.com" title="" charset="utf-8" url="http://www.lyriki.com/{artist}:{title}"> <provider name="lyriki.com" title="" charset="utf-8" url="http://www.lyriki.com/{artist}:{title}">
<urlFormat replace=" _@,;&amp;\/&quot;" with="_"/> <urlFormat replace=" _@,;&amp;\/&quot;" with="_"/>
<urlFormat replace="." with=""/> <urlFormat replace="." with=""/>
@ -184,6 +210,20 @@
<item tag="&lt;p&gt;"/> <item tag="&lt;p&gt;"/>
</extract> </extract>
</provider> </provider>
<provider name="metrolyrics.com" title="{artist} - {title} LYRICS" charset="utf-8" url="http://www.metrolyrics.com/{title}-lyrics-{artist}.html">
<urlFormat replace=" _@,;&amp;\/&quot;" with="-"/>
<urlFormat replace="'." with=""/>
<extract>
<item tag="&lt;span id=&quot;lyrics&quot;&gt;"/>
</extract>
<extract>
<item tag="&lt;div id=&quot;lyrics&quot;&gt;"/>
</extract>
<exclude>
<item tag="&lt;h5&gt;"/>
</exclude>
<invalidIndicator value="These lyrics are missing"/>
</provider>
<provider name="mp3lyrics.org" title="{artist} &amp;quot;{title}&amp;quot; Lyrics" charset="utf-8" url="http://www.mp3lyrics.org/{a}/{artist}/{title}/"> <provider name="mp3lyrics.org" title="{artist} &amp;quot;{title}&amp;quot; Lyrics" charset="utf-8" url="http://www.mp3lyrics.org/{a}/{artist}/{title}/">
<urlFormat replace=" _@,;&amp;\/&quot;" with="-"/> <urlFormat replace=" _@,;&amp;\/&quot;" with="-"/>
<urlFormat replace="'." with=""/> <urlFormat replace="'." with=""/>
@ -211,6 +251,13 @@
</exclude> </exclude>
<invalidIndicator value="We couldn't find that page."/> <invalidIndicator value="We couldn't find that page."/>
</provider> </provider>
<provider name="seeklyrics.com" title="{artist} - {title} Lyrics" charset="iso-8859-1" url="http://www.seeklyrics.com/lyrics/{Artist}/{Title}.html">
<urlFormat replace=" _@,;&amp;\/'&quot;" with="-"/>
<urlFormat replace="." with=""/>
<extract>
<item tag="&lt;div id=&quot;songlyrics&quot;&gt;"/>
</extract>
</provider>
<provider name="songlyrics.com" title="{title} LYRICS - {artist}" charset="utf-8" url="http://www.songlyrics.com/{artist}/{title}-lyrics/"> <provider name="songlyrics.com" title="{title} LYRICS - {artist}" charset="utf-8" url="http://www.songlyrics.com/{artist}/{title}-lyrics/">
<urlFormat replace=" ._@,;&amp;\/&quot;" with="-"/> <urlFormat replace=" ._@,;&amp;\/&quot;" with="-"/>
<urlFormat replace="'" with="_"/> <urlFormat replace="'" with="_"/>

View File

@ -18,7 +18,6 @@ BuildRequires: liblastfm-qt5-devel
BuildRequires: desktop-file-utils BuildRequires: desktop-file-utils
BuildRequires: hicolor-icon-theme BuildRequires: hicolor-icon-theme
BuildRequires: libappstream-glib BuildRequires: libappstream-glib
BuildRequires: qtsingleapplication-qt5-devel
BuildRequires: pkgconfig BuildRequires: pkgconfig
BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(gio-2.0) BuildRequires: pkgconfig(gio-2.0)
@ -30,6 +29,7 @@ BuildRequires: pkgconfig(protobuf)
BuildRequires: pkgconfig(sqlite3) >= 3.7 BuildRequires: pkgconfig(sqlite3) >= 3.7
BuildRequires: pkgconfig(taglib) >= 1.11 BuildRequires: pkgconfig(taglib) >= 1.11
BuildRequires: pkgconfig(glew) BuildRequires: pkgconfig(glew)
BuildRequires: pkgconfig(cryptopp)
BuildRequires: pkgconfig(Qt5Core) BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5Gui) BuildRequires: pkgconfig(Qt5Gui)
BuildRequires: pkgconfig(Qt5Widgets) BuildRequires: pkgconfig(Qt5Widgets)
@ -46,13 +46,12 @@ BuildRequires: pkgconfig(gstreamer-app-1.0)
BuildRequires: pkgconfig(gstreamer-audio-1.0) BuildRequires: pkgconfig(gstreamer-audio-1.0)
BuildRequires: pkgconfig(gstreamer-base-1.0) BuildRequires: pkgconfig(gstreamer-base-1.0)
BuildRequires: pkgconfig(gstreamer-tag-1.0) BuildRequires: pkgconfig(gstreamer-tag-1.0)
BuildRequires: pkgconfig(libpulse)
BuildRequires: pkgconfig(libcdio) BuildRequires: pkgconfig(libcdio)
BuildRequires: pkgconfig(libchromaprint) BuildRequires: pkgconfig(libchromaprint)
BuildRequires: pkgconfig(libcryptopp)
BuildRequires: pkgconfig(libgpod-1.0) BuildRequires: pkgconfig(libgpod-1.0)
BuildRequires: pkgconfig(libmtp) BuildRequires: pkgconfig(libmtp)
BuildRequires: pkgconfig(libnotify) BuildRequires: pkgconfig(libnotify)
BuildRequires: pkgconfig(libpulse)
BuildRequires: pkgconfig(libudf) BuildRequires: pkgconfig(libudf)
# GStreamer codec dependencies # GStreamer codec dependencies

17
dist/macdeploy.py vendored
View File

@ -35,11 +35,11 @@ STRIP_PREFIX = [
'@@HOMEBREW_CELLAR@@/qt5/5.8.0_1/lib/', '@@HOMEBREW_CELLAR@@/qt5/5.8.0_1/lib/',
] ]
LIBRARY_SEARCH_PATH = ['/target', '/target/lib', '/usr/local/lib', '/sw/lib'] LIBRARY_SEARCH_PATH = ['/opt/homebrew/lib', '/target', '/target/lib', '/usr/local/lib', '/sw/lib']
GSTREAMER_PLUGINS = [ GSTREAMER_PLUGINS = [
# Core plugins # Core plugins
'libgstapp.dylib', 'libgstapp-1.0.dylib',
'libgstaudioconvert.dylib', 'libgstaudioconvert.dylib',
'libgstaudiofx.dylib', 'libgstaudiofx.dylib',
'libgstaudiotestsrc.dylib', 'libgstaudiotestsrc.dylib',
@ -88,10 +88,13 @@ GSTREAMER_PLUGINS = [
] ]
GSTREAMER_SEARCH_PATH = [ GSTREAMER_SEARCH_PATH = [
'/opt/homebrew/lib',
'/opt/homebrew/opt/gstreamer/libexec/gstreamer-1.0',
'/usr/local/lib',
'/usr/local/lib/gstreamer-1.0', '/usr/local/lib/gstreamer-1.0',
'/usr/local/opt/gstreamer/libexec/gstreamer-1.0',
'/target/lib/gstreamer-1.0', '/target/lib/gstreamer-1.0',
'/target/libexec/gstreamer-1.0', '/target/libexec/gstreamer-1.0',
'/usr/local/opt/gstreamer/libexec/gstreamer-1.0',
] ]
QT_PLUGINS = [ QT_PLUGINS = [
@ -110,6 +113,7 @@ QT_PLUGINS = [
'styles/libqmacstyle.dylib', 'styles/libqmacstyle.dylib',
] ]
QT_PLUGINS_SEARCH_PATH = [ QT_PLUGINS_SEARCH_PATH = [
'/opt/homebrew/Cellar/qt@5/5.15.10/plugins',
'/usr/local/opt/qt5/plugins', '/usr/local/opt/qt5/plugins',
'/target/plugins', '/target/plugins',
'/usr/local/Trolltech/Qt-4.7.0/plugins', '/usr/local/Trolltech/Qt-4.7.0/plugins',
@ -117,6 +121,7 @@ QT_PLUGINS_SEARCH_PATH = [
] ]
GIO_MODULES_SEARCH_PATH = [ GIO_MODULES_SEARCH_PATH = [
'/opt/homebrew/lib/gio/modules',
'/usr/local/lib/gio/modules', '/usr/local/lib/gio/modules',
'/target/lib/gio/modules', '/target/lib/gio/modules',
] ]
@ -204,6 +209,12 @@ def GetBrokenLibraries(binary):
*os.path.split(line)[1:], *os.path.split(line)[1:],
) )
broken_libs['libs'].append(abs_path) broken_libs['libs'].append(abs_path)
elif re.match(r'^\s*@rpath', line):
abs_path = os.path.join(
os.path.dirname(binary),
*os.path.split(line)[1:],
)
broken_libs['libs'].append(abs_path)
elif re.match(r'^\s*@executable_path', line): elif re.match(r'^\s*@executable_path', line):
# Potentially already fixed library # Potentially already fixed library
relative_path = os.path.join(*line.split('/')[3:]) relative_path = os.path.join(*line.split('/')[3:])

View File

@ -32,6 +32,11 @@ target_link_libraries(clementine-tagreader
z z
) )
set_property(
TARGET clementine-tagreader
PROPERTY CXX_STANDARD 17
)
if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
target_link_libraries(clementine-tagreader target_link_libraries(clementine-tagreader
execinfo execinfo

View File

@ -2,6 +2,8 @@ include_directories(${PROTOBUF_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_SOURCE_DIR})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x")
set(SOURCES set(SOURCES
core/closure.cpp core/closure.cpp
core/latch.cpp core/latch.cpp
@ -31,6 +33,11 @@ add_library(libclementine-common STATIC
${MOC} ${MOC}
) )
set_property(
TARGET libclementine-common
PROPERTY CXX_STANDARD 17
)
target_link_libraries(libclementine-common target_link_libraries(libclementine-common
Qt5::Core Qt5::Core
Qt5::Network Qt5::Network

View File

@ -1,17 +1,32 @@
include_directories(${PROTOBUF_INCLUDE_DIRS}) include_directories(${PROTOBUF_INCLUDE_DIRS})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x")
set(MESSAGES set(MESSAGES
remotecontrolmessages.proto remotecontrolmessages.proto
) )
add_library(libclementine-remote STATIC add_library(libclementine-remote STATIC)
${MESSAGES}
protobuf_generate(
LANGUAGE cpp
TARGET libclementine-remote
PROTOS ${MESSAGES}
) )
protobuf_generate(TARGET libclementine-remote LANGUAGE cpp) set_property(
TARGET libclementine-remote
PROPERTY CXX_STANDARD 17
)
get_cmake_property(_variableNames VARIABLES)
list (SORT _variableNames)
foreach (_variableName ${_variableNames})
message(STATUS "${_variableName}=${${_variableName}}")
endforeach()
target_link_libraries(libclementine-remote target_link_libraries(libclementine-remote
libclementine-common
protobuf::libprotobuf protobuf::libprotobuf
libclementine-common
) )

View File

@ -3,6 +3,8 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-common) include_directories(${CMAKE_SOURCE_DIR}/ext/libclementine-common)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --std=c++0x")
set(MESSAGES set(MESSAGES
tagreadermessages.proto tagreadermessages.proto
) )
@ -27,15 +29,23 @@ optional_source(HAVE_GOOGLE_DRIVE
qt5_wrap_cpp(MOC ${HEADERS}) qt5_wrap_cpp(MOC ${HEADERS})
add_library(libclementine-tagreader STATIC add_library(libclementine-tagreader STATIC
${MESSAGES}
${SOURCES} ${SOURCES}
${MOC} ${MOC}
) )
protobuf_generate(TARGET libclementine-tagreader LANGUAGE cpp) protobuf_generate(
LANGUAGE cpp
target_link_libraries(libclementine-tagreader TARGET libclementine-tagreader
libclementine-common PROTOS ${MESSAGES}
protobuf::libprotobuf )
set_property(
TARGET libclementine-tagreader
PROPERTY CXX_STANDARD 17
)
target_link_libraries(libclementine-tagreader
protobuf::libprotobuf
libclementine-common
) )

View File

@ -91,13 +91,9 @@ void CloudStream::Precache() {
clear(); clear();
} }
#if (TAGLIB_MAJOR_VERSION == 2)
TagLib::ByteVector CloudStream::readBlock(size_t length) {
#else
TagLib::ByteVector CloudStream::readBlock(ulong length) { TagLib::ByteVector CloudStream::readBlock(ulong length) {
#endif
const uint start = cursor_; const uint start = cursor_;
const uint end = qMin((size_t)(cursor_ + length - 1), (size_t)(length_ - 1)); const uint end = qMin(cursor_ + length - 1, length_ - 1);
if (end < start) { if (end < start) {
return TagLib::ByteVector(); return TagLib::ByteVector();
@ -148,19 +144,11 @@ void CloudStream::writeBlock(const TagLib::ByteVector&) {
qLog(Debug) << Q_FUNC_INFO << "not implemented"; qLog(Debug) << Q_FUNC_INFO << "not implemented";
} }
#if (TAGLIB_MAJOR_VERSION == 2)
void CloudStream::insert(const TagLib::ByteVector&, TagLib::offset_t, size_t) {
#else
void CloudStream::insert(const TagLib::ByteVector&, ulong, ulong) { void CloudStream::insert(const TagLib::ByteVector&, ulong, ulong) {
#endif
qLog(Debug) << Q_FUNC_INFO << "not implemented"; qLog(Debug) << Q_FUNC_INFO << "not implemented";
} }
#if (TAGLIB_MAJOR_VERSION == 2)
void CloudStream::removeBlock(TagLib::offset_t, size_t) {
#else
void CloudStream::removeBlock(ulong, ulong) { void CloudStream::removeBlock(ulong, ulong) {
#endif
qLog(Debug) << Q_FUNC_INFO << "not implemented"; qLog(Debug) << Q_FUNC_INFO << "not implemented";
} }
@ -171,11 +159,7 @@ bool CloudStream::readOnly() const {
bool CloudStream::isOpen() const { return true; } bool CloudStream::isOpen() const { return true; }
#if (TAGLIB_MAJOR_VERSION == 2)
void CloudStream::seek(TagLib::offset_t offset, TagLib::IOStream::Position p) {
#else
void CloudStream::seek(long offset, TagLib::IOStream::Position p) { void CloudStream::seek(long offset, TagLib::IOStream::Position p) {
#endif
switch (p) { switch (p) {
case TagLib::IOStream::Beginning: case TagLib::IOStream::Beginning:
cursor_ = offset; cursor_ = offset;
@ -187,26 +171,18 @@ void CloudStream::seek(long offset, TagLib::IOStream::Position p) {
case TagLib::IOStream::End: case TagLib::IOStream::End:
// This should really not have qAbs(), but OGG reading needs it. // This should really not have qAbs(), but OGG reading needs it.
cursor_ = qMax(0UL, (unsigned long)(length_ - qAbs(offset))); cursor_ = qMax(0UL, length_ - qAbs(offset));
break; break;
} }
} }
void CloudStream::clear() { cursor_ = 0; } void CloudStream::clear() { cursor_ = 0; }
#if (TAGLIB_MAJOR_VERSION == 2)
TagLib::offset_t CloudStream::tell() const { return cursor_; }
TagLib::offset_t CloudStream::length() { return length_; }
void CloudStream::truncate(TagLib::offset_t) {
#else
long CloudStream::tell() const { return cursor_; } long CloudStream::tell() const { return cursor_; }
long CloudStream::length() { return length_; } long CloudStream::length() { return length_; }
void CloudStream::truncate(long) { void CloudStream::truncate(long) {
#endif
qLog(Debug) << Q_FUNC_INFO << "not implemented"; qLog(Debug) << Q_FUNC_INFO << "not implemented";
} }

View File

@ -35,19 +35,6 @@ class CloudStream : public QObject, public TagLib::IOStream {
// Taglib::IOStream // Taglib::IOStream
virtual TagLib::FileName name() const; virtual TagLib::FileName name() const;
#if (TAGLIB_MAJOR_VERSION == 2)
virtual TagLib::ByteVector readBlock(size_t length);
virtual void writeBlock(const TagLib::ByteVector&);
virtual void insert(const TagLib::ByteVector&, TagLib::offset_t, size_t);
virtual void removeBlock(TagLib::offset_t, size_t);
virtual bool readOnly() const;
virtual bool isOpen() const;
virtual void seek(TagLib::offset_t offset, TagLib::IOStream::Position p);
virtual void clear();
virtual TagLib::offset_t tell() const;
virtual TagLib::offset_t length();
virtual void truncate(TagLib::offset_t);
#else
virtual TagLib::ByteVector readBlock(ulong length); virtual TagLib::ByteVector readBlock(ulong length);
virtual void writeBlock(const TagLib::ByteVector&); virtual void writeBlock(const TagLib::ByteVector&);
virtual void insert(const TagLib::ByteVector&, ulong, ulong); virtual void insert(const TagLib::ByteVector&, ulong, ulong);
@ -59,7 +46,6 @@ class CloudStream : public QObject, public TagLib::IOStream {
virtual long tell() const; virtual long tell() const;
virtual long length(); virtual long length();
virtual void truncate(long); virtual void truncate(long);
#endif
google::sparsetable<char>::size_type cached_bytes() const { google::sparsetable<char>::size_type cached_bytes() const {
return cache_.num_nonempty(); return cache_.num_nonempty();

View File

@ -198,7 +198,7 @@ void TagReader::ReadFile(const QString& filename,
// Find album artists // Find album artists
TagLib::APE::ItemListMap::ConstIterator it = items.find("ALBUM ARTIST"); TagLib::APE::ItemListMap::ConstIterator it = items.find("ALBUM ARTIST");
if (it != items.end()) { if (it != items.end()) {
TagLib::StringList album_artists = it->second.values(); TagLib::StringList album_artists = it->second.toStringList();
if (!album_artists.isEmpty()) { if (!album_artists.isEmpty()) {
Decode(album_artists.front(), nullptr, song->mutable_albumartist()); Decode(album_artists.front(), nullptr, song->mutable_albumartist());
} }
@ -243,22 +243,22 @@ void TagReader::ReadFile(const QString& filename,
} }
if (items.contains("BPM")) { if (items.contains("BPM")) {
Decode(items["BPM"].values().toString(", "), nullptr, Decode(items["BPM"].toStringList().toString(", "), nullptr,
song->mutable_performer()); song->mutable_performer());
} }
if (items.contains("PERFORMER")) { if (items.contains("PERFORMER")) {
Decode(items["PERFORMER"].values().toString(", "), nullptr, Decode(items["PERFORMER"].toStringList().toString(", "), nullptr,
song->mutable_performer()); song->mutable_performer());
} }
if (items.contains("COMPOSER")) { if (items.contains("COMPOSER")) {
Decode(items["COMPOSER"].values().toString(", "), nullptr, Decode(items["COMPOSER"].toStringList().toString(", "), nullptr,
song->mutable_composer()); song->mutable_composer());
} }
if (items.contains("GROUPING")) { if (items.contains("GROUPING")) {
Decode(items["GROUPING"].values().toString(" "), nullptr, Decode(items["GROUPING"].toStringList().toString(" "), nullptr,
song->mutable_grouping()); song->mutable_grouping());
} }
@ -565,8 +565,8 @@ void TagReader::ReadFile(const QString& filename,
if (fileref->audioProperties()) { if (fileref->audioProperties()) {
song->set_bitrate(fileref->audioProperties()->bitrate()); song->set_bitrate(fileref->audioProperties()->bitrate());
song->set_samplerate(fileref->audioProperties()->sampleRate()); song->set_samplerate(fileref->audioProperties()->sampleRate());
song->set_length_nanosec(fileref->audioProperties()->lengthInMilliseconds() * song->set_length_nanosec(fileref->audioProperties()->length() *
kNsecPerMsec); kNsecPerSec);
} }
// Get the filetype if we can // Get the filetype if we can
@ -1376,15 +1376,9 @@ bool TagReader::ReadCloudFile(const QUrl& download_url, const QString& title,
std::unique_ptr<TagLib::File> tag; std::unique_ptr<TagLib::File> tag;
if (mime_type == "audio/mpeg" && if (mime_type == "audio/mpeg" &&
title.endsWith(".mp3", Qt::CaseInsensitive)) { title.endsWith(".mp3", Qt::CaseInsensitive)) {
#if (TAGLIB_MAJOR_VERSION == 2)
tag.reset(new TagLib::MPEG::File(stream.get(), true,
TagLib::AudioProperties::Accurate,
TagLib::ID3v2::FrameFactory::instance()));
#else
tag.reset(new TagLib::MPEG::File(stream.get(), tag.reset(new TagLib::MPEG::File(stream.get(),
TagLib::ID3v2::FrameFactory::instance(), TagLib::ID3v2::FrameFactory::instance(),
TagLib::AudioProperties::Accurate)); TagLib::AudioProperties::Accurate));
#endif
} else if (mime_type == "audio/mp4" || } else if (mime_type == "audio/mp4" ||
(mime_type == "audio/mpeg" && (mime_type == "audio/mpeg" &&
title.endsWith(".m4a", Qt::CaseInsensitive))) { title.endsWith(".m4a", Qt::CaseInsensitive))) {
@ -1404,15 +1398,9 @@ bool TagReader::ReadCloudFile(const QUrl& download_url, const QString& title,
TagLib::AudioProperties::Accurate)); TagLib::AudioProperties::Accurate));
} else if (mime_type == "application/x-flac" || mime_type == "audio/flac" || } else if (mime_type == "application/x-flac" || mime_type == "audio/flac" ||
mime_type == "audio/x-flac") { mime_type == "audio/x-flac") {
#if (TAGLIB_MAJOR_VERSION == 2)
tag.reset(new TagLib::FLAC::File(stream.get(), true,
TagLib::AudioProperties::Accurate,
TagLib::ID3v2::FrameFactory::instance()));
#else
tag.reset(new TagLib::FLAC::File(stream.get(), tag.reset(new TagLib::FLAC::File(stream.get(),
TagLib::ID3v2::FrameFactory::instance(), TagLib::ID3v2::FrameFactory::instance(),
true, TagLib::AudioProperties::Accurate)); true, TagLib::AudioProperties::Accurate));
#endif
} else if (mime_type == "audio/x-ms-wma") { } else if (mime_type == "audio/x-ms-wma") {
tag.reset(new TagLib::ASF::File(stream.get(), true, tag.reset(new TagLib::ASF::File(stream.get(), true,
TagLib::AudioProperties::Accurate)); TagLib::AudioProperties::Accurate));
@ -1443,7 +1431,7 @@ bool TagReader::ReadCloudFile(const QUrl& download_url, const QString& title,
song->set_type(cpb::tagreader::SongMetadata_Type_STREAM); song->set_type(cpb::tagreader::SongMetadata_Type_STREAM);
if (tag->audioProperties()) { if (tag->audioProperties()) {
song->set_length_nanosec(tag->audioProperties()->lengthInMilliseconds() * kNsecPerMsec); song->set_length_nanosec(tag->audioProperties()->length() * kNsecPerSec);
} }
return true; return true;
} }

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.0.0) cmake_minimum_required(VERSION 3.0.0)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual -Wall --std=c++0x")
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -1244,6 +1244,11 @@ add_library(clementine_lib STATIC
${OTHER_UIC_SOURCES} ${OTHER_UIC_SOURCES}
) )
set_property(
TARGET clementine_lib
PROPERTY CXX_STANDARD 17
)
target_link_libraries(clementine_lib target_link_libraries(clementine_lib
libclementine-common libclementine-common
libclementine-tagreader libclementine-tagreader

View File

@ -26,7 +26,7 @@
#include "core/closure.h" #include "core/closure.h"
#include "core/network.h" #include "core/network.h"
using std::mem_fun; using std::mem_fn;
namespace { namespace {
@ -89,7 +89,7 @@ void MusicbrainzCoverProvider::ReleaseSearchFinished(QNetworkReply* reply,
void MusicbrainzCoverProvider::ImageCheckFinished(int id) { void MusicbrainzCoverProvider::ImageCheckFinished(int id) {
QList<QNetworkReply*> replies = image_checks_.values(id); QList<QNetworkReply*> replies = image_checks_.values(id);
int finished_count = std::count_if(replies.constBegin(), replies.constEnd(), int finished_count = std::count_if(replies.constBegin(), replies.constEnd(),
mem_fun(&QNetworkReply::isFinished)); mem_fn(&QNetworkReply::isFinished));
if (finished_count == replies.size()) { if (finished_count == replies.size()) {
QString cover_name = cover_names_.take(id); QString cover_name = cover_names_.take(id);
QList<CoverSearchResult> results; QList<CoverSearchResult> results;

View File

@ -22,6 +22,7 @@
#include <QTimerEvent> #include <QTimerEvent>
#include <QUrl> #include <QUrl>
#include <algorithm> #include <algorithm>
#include <random>
#include "core/application.h" #include "core/application.h"
#include "core/logging.h" #include "core/logging.h"
@ -371,7 +372,9 @@ QStringList GlobalSearch::GetSuggestions(int count) {
} }
// Randomize the suggestions // Randomize the suggestions
std::random_shuffle(ret.begin(), ret.end()); std::random_device rd;
std::mt19937 g(rd());
std::shuffle(ret.begin(), ret.end(), g);
// Only return the first count // Only return the first count
while (ret.length() > count) { while (ret.length() > count) {

View File

@ -41,16 +41,16 @@ class DigitallyImportedServiceBase : public InternetService {
const QString& api_service_name, const QString& api_service_name,
Application* app, InternetModel* model, Application* app, InternetModel* model,
bool has_premium, QObject* parent = nullptr); bool has_premium, QObject* parent = nullptr);
~DigitallyImportedServiceBase() override; ~DigitallyImportedServiceBase();
static const char* kSettingsGroup; static const char* kSettingsGroup;
static const int kStreamsCacheDurationSecs; static const int kStreamsCacheDurationSecs;
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* parent) override; void LazyPopulate(QStandardItem* parent);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
void ReloadSettings() override; void ReloadSettings();
bool is_premium_account() const; bool is_premium_account() const;

View File

@ -40,7 +40,7 @@ class IcecastService : public InternetService {
public: public:
IcecastService(Application* app, InternetModel* parent); IcecastService(Application* app, InternetModel* parent);
~IcecastService() override; ~IcecastService();
static const char* kServiceName; static const char* kServiceName;
static const char* kDirectoryUrl; static const char* kDirectoryUrl;
@ -51,12 +51,12 @@ class IcecastService : public InternetService {
Type_Genre, Type_Genre,
}; };
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
QWidget* HeaderWidget() const override; QWidget* HeaderWidget() const;
private slots: private slots:
void LoadDirectory(); void LoadDirectory();

View File

@ -39,7 +39,7 @@ class IntergalacticFMServiceBase : public InternetService {
const QString& name, const QUrl& channel_list_url, const QString& name, const QUrl& channel_list_url,
const QUrl& homepage_url, const QUrl& homepage_url,
const QUrl& donate_page_url, const QIcon& icon); const QUrl& donate_page_url, const QIcon& icon);
~IntergalacticFMServiceBase() override; ~IntergalacticFMServiceBase();
enum ItemType { enum ItemType {
Type_Stream = 2000, Type_Stream = 2000,
@ -59,14 +59,14 @@ class IntergalacticFMServiceBase : public InternetService {
const QString& url_scheme() const { return url_scheme_; } const QString& url_scheme() const { return url_scheme_; }
const QIcon& icon() const { return icon_; } const QIcon& icon() const { return icon_; }
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
PlaylistItem::Options playlistitem_options() const override; PlaylistItem::Options playlistitem_options() const;
QNetworkAccessManager* network() const { return network_; } QNetworkAccessManager* network() const { return network_; }
void ReloadSettings() override; void ReloadSettings();
bool IsStreamListStale() const { return streams_.IsStale(); } bool IsStreamListStale() const { return streams_.IsStale(); }
StreamList Streams(); StreamList Streams();

View File

@ -34,7 +34,7 @@ class SavedRadio : public InternetService {
public: public:
SavedRadio(Application* app, InternetModel* parent); SavedRadio(Application* app, InternetModel* parent);
~SavedRadio() override; ~SavedRadio();
enum ItemType { enum ItemType {
Type_Stream = 2000, Type_Stream = 2000,
@ -57,10 +57,10 @@ class SavedRadio : public InternetService {
static const char* kServiceName; static const char* kServiceName;
static const char* kSettingsGroup; static const char* kSettingsGroup;
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
void Add(const QUrl& url, const QString& name = QString(), void Add(const QUrl& url, const QString& name = QString(),
const QUrl& url_logo = QUrl()); const QUrl& url_logo = QUrl());

View File

@ -43,14 +43,14 @@ class JamendoService : public InternetService {
public: public:
JamendoService(Application* app, InternetModel* parent); JamendoService(Application* app, InternetModel* parent);
~JamendoService() override; ~JamendoService();
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
QWidget* HeaderWidget() const override; QWidget* HeaderWidget() const;
LibraryBackend* library_backend() const { return library_backend_.get(); } LibraryBackend* library_backend() const { return library_backend_.get(); }

View File

@ -38,7 +38,7 @@ class MagnatuneService : public InternetService {
public: public:
MagnatuneService(Application* app, InternetModel* parent); MagnatuneService(Application* app, InternetModel* parent);
~MagnatuneService() override; ~MagnatuneService();
// Values are saved in QSettings and are indices into the combo box in // Values are saved in QSettings and are indices into the combo box in
// MagnatuneConfig // MagnatuneConfig
@ -71,14 +71,14 @@ class MagnatuneService : public InternetService {
static QString ReadElementText(QXmlStreamReader& reader); static QString ReadElementText(QXmlStreamReader& reader);
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
QWidget* HeaderWidget() const override; QWidget* HeaderWidget() const;
void ReloadSettings() override; void ReloadSettings();
// Magnatune specific stuff // Magnatune specific stuff
MembershipType membership_type() const { return membership_; } MembershipType membership_type() const { return membership_; }
@ -99,7 +99,7 @@ class MagnatuneService : public InternetService {
void Download(); void Download();
void Homepage(); void Homepage();
void ShowConfig() override; void ShowConfig();
private: private:
void EnsureMenuCreated(); void EnsureMenuCreated();

View File

@ -44,7 +44,7 @@ class PodcastService : public InternetService {
public: public:
PodcastService(Application* app, InternetModel* parent); PodcastService(Application* app, InternetModel* parent);
~PodcastService() override; ~PodcastService();
static const char* kServiceName; static const char* kServiceName;
static const char* kSettingsGroup; static const char* kSettingsGroup;
@ -57,12 +57,12 @@ class PodcastService : public InternetService {
enum Role { Role_Podcast = InternetModel::RoleCount, Role_Episode }; enum Role { Role_Podcast = InternetModel::RoleCount, Role_Episode };
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* parent) override; void LazyPopulate(QStandardItem* parent);
bool has_initial_load_settings() const override { return true; } bool has_initial_load_settings() const { return true; }
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
void ReloadSettings() override; void ReloadSettings();
void InitialLoadSettings() override; void InitialLoadSettings();
// Called by SongLoader when the user adds a Podcast URL directly. Adds a // Called by SongLoader when the user adds a Podcast URL directly. Adds a
// subscription to the podcast and displays it in the UI. If the QVariant // subscription to the podcast and displays it in the UI. If the QVariant
// contains an OPML file then this displays it in the Add Podcast dialog. // contains an OPML file then this displays it in the Add Podcast dialog.
@ -81,7 +81,7 @@ class PodcastService : public InternetService {
void DeleteDownloadedData(); void DeleteDownloadedData();
void SetNew(); void SetNew();
void SetListened(); void SetListened();
void ShowConfig() override; void ShowConfig();
void SubscriptionAdded(const Podcast& podcast); void SubscriptionAdded(const Podcast& podcast);
void SubscriptionRemoved(const Podcast& podcast); void SubscriptionRemoved(const Podcast& podcast);

View File

@ -35,7 +35,7 @@ class RadioBrowserService : public InternetService {
public: public:
RadioBrowserService(Application* app, InternetModel* parent); RadioBrowserService(Application* app, InternetModel* parent);
~RadioBrowserService() override{}; ~RadioBrowserService(){};
enum ItemType { enum ItemType {
Type_Stream = 2000, Type_Stream = 2000,

View File

@ -39,7 +39,7 @@ class SomaFMServiceBase : public InternetService {
const QString& name, const QUrl& channel_list_url, const QString& name, const QUrl& channel_list_url,
const QUrl& homepage_url, const QUrl& donate_page_url, const QUrl& homepage_url, const QUrl& donate_page_url,
const QIcon& icon); const QIcon& icon);
~SomaFMServiceBase() override; ~SomaFMServiceBase();
enum ItemType { enum ItemType {
Type_Stream = 2000, Type_Stream = 2000,
@ -59,14 +59,14 @@ class SomaFMServiceBase : public InternetService {
const QString& url_scheme() const { return url_scheme_; } const QString& url_scheme() const { return url_scheme_; }
const QIcon& icon() const { return icon_; } const QIcon& icon() const { return icon_; }
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
PlaylistItem::Options playlistitem_options() const override; PlaylistItem::Options playlistitem_options() const;
QNetworkAccessManager* network() const { return network_; } QNetworkAccessManager* network() const { return network_; }
void ReloadSettings() override; void ReloadSettings();
bool IsStreamListStale() const { return streams_.IsStale(); } bool IsStreamListStale() const { return streams_.IsStale(); }
StreamList Streams(); StreamList Streams();

View File

@ -530,11 +530,6 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
// Read song information // Read song information
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
// skip multi-artist and multi-genre tags
if ((reader.name() == "artists") || (reader.name() == "genres")) {
reader.skipCurrentElement();
continue;
}
if (reader.name() != "song") { if (reader.name() != "song") {
ParsingError("song tag expected. Aborting scan."); ParsingError("song tag expected. Aborting scan.");
return; return;

View File

@ -42,7 +42,7 @@ class SubsonicService : public InternetService {
public: public:
SubsonicService(Application* app, InternetModel* parent); SubsonicService(Application* app, InternetModel* parent);
~SubsonicService() override; ~SubsonicService();
enum LoginState { enum LoginState {
LoginState_Loggedin, LoginState_Loggedin,
@ -90,11 +90,11 @@ class SubsonicService : public InternetService {
bool IsConfigured() const; bool IsConfigured() const;
bool IsAmpache() const; bool IsAmpache() const;
QStandardItem* CreateRootItem() override; QStandardItem* CreateRootItem();
void LazyPopulate(QStandardItem* item) override; void LazyPopulate(QStandardItem* item);
void ShowContextMenu(const QPoint& global_pos) override; void ShowContextMenu(const QPoint& global_pos);
QWidget* HeaderWidget() const override; QWidget* HeaderWidget() const;
void ReloadSettings() override; void ReloadSettings();
void Login(); void Login();
void Login(const QString& server, const QString& username, void Login(const QString& server, const QString& username,
@ -175,7 +175,7 @@ class SubsonicService : public InternetService {
void OnLoginStateChanged(SubsonicService::LoginState newstate); void OnLoginStateChanged(SubsonicService::LoginState newstate);
void OnPingFinished(QNetworkReply* reply); void OnPingFinished(QNetworkReply* reply);
void ShowConfig() override; void ShowConfig();
}; };
class SubsonicLibraryScanner : public QObject { class SubsonicLibraryScanner : public QObject {
@ -184,7 +184,7 @@ class SubsonicLibraryScanner : public QObject {
public: public:
explicit SubsonicLibraryScanner(SubsonicService* service, explicit SubsonicLibraryScanner(SubsonicService* service,
QObject* parent = nullptr); QObject* parent = nullptr);
~SubsonicLibraryScanner() override; ~SubsonicLibraryScanner();
void Scan(); void Scan();
const SongList& GetSongs() const { return songs_; } const SongList& GetSongs() const { return songs_; }

View File

@ -896,7 +896,7 @@ LibraryBackend::AlbumList LibraryBackend::GetAlbums(const QString& artist,
QString last_artist; QString last_artist;
QString last_album_artist; QString last_album_artist;
while (query.Next()) { while (query.Next()) {
bool compilation = query.Value(3).toBool() || query.Value(4).toBool(); bool compilation = query.Value(3).toBool() | query.Value(4).toBool();
Album info; Album info;
info.artist = compilation ? QString() : query.Value(1).toString(); info.artist = compilation ? QString() : query.Value(1).toString();

View File

@ -92,10 +92,12 @@ void MoodbarBuilder::Normalize(QList<Rgb>* vals, double Rgb::*member) {
} }
double avg = 0; double avg = 0;
int t = 0;
for (const Rgb& rgb : *vals) { for (const Rgb& rgb : *vals) {
const double value = rgb.*member; const double value = rgb.*member;
if (value != mini && value != maxi) { if (value != mini && value != maxi) {
avg += value / vals->count(); avg += value / vals->count();
t++;
} }
} }

View File

@ -98,6 +98,7 @@ void OutgoingDataCreator::CheckEnabledProviders() {
<< "lyricstime.com" << "lyricstime.com"
<< "lyricsreg.com" << "lyricsreg.com"
<< "lyricsmania.com" << "lyricsmania.com"
<< "metrolyrics.com"
<< "azlyrics.com" << "azlyrics.com"
<< "songlyrics.com" << "songlyrics.com"
<< "elyrics.net" << "elyrics.net"
@ -105,6 +106,7 @@ void OutgoingDataCreator::CheckEnabledProviders() {
<< "lyrics.com" << "lyrics.com"
<< "lyricsbay.com" << "lyricsbay.com"
<< "directlyrics.com" << "directlyrics.com"
<< "loudson.gs"
<< "teksty.org" << "teksty.org"
<< "tekstowo.pl (Polish translations)" << "tekstowo.pl (Polish translations)"
<< "vagalume.uol.com.br" << "vagalume.uol.com.br"

View File

@ -32,6 +32,7 @@
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <random>
#include <unordered_map> #include <unordered_map>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)) #if (QT_VERSION >= QT_VERSION_CHECK(5, 10, 0))
@ -1729,11 +1730,13 @@ PlaylistItemList Playlist::RemoveItemsWithoutUndo(int row, int count) {
endRemoveRows(); endRemoveRows();
QList<int>::iterator it = virtual_items_.begin(); QList<int>::iterator it = virtual_items_.begin();
int i = 0;
while (it != virtual_items_.end()) { while (it != virtual_items_.end()) {
if (*it >= items_.count()) if (*it >= items_.count())
it = virtual_items_.erase(it); it = virtual_items_.erase(it);
else else
++it; ++it;
++i;
} }
// Reset current_virtual_index_ // Reset current_virtual_index_
@ -2077,6 +2080,8 @@ void Playlist::ReshuffleIndices() {
if (current_virtual_index_ != -1) if (current_virtual_index_ != -1)
std::advance(begin, current_virtual_index_ + 1); std::advance(begin, current_virtual_index_ + 1);
std::random_device rd;
switch (playlist_sequence_->shuffle_mode()) { switch (playlist_sequence_->shuffle_mode()) {
case PlaylistSequence::Shuffle_Off: case PlaylistSequence::Shuffle_Off:
// Handled above. // Handled above.
@ -2084,7 +2089,7 @@ void Playlist::ReshuffleIndices() {
case PlaylistSequence::Shuffle_All: case PlaylistSequence::Shuffle_All:
case PlaylistSequence::Shuffle_InsideAlbum: case PlaylistSequence::Shuffle_InsideAlbum:
std::random_shuffle(begin, end); std::shuffle(begin, end, std::mt19937(rd()));
break; break;
case PlaylistSequence::Shuffle_Albums: { case PlaylistSequence::Shuffle_Albums: {
@ -2101,8 +2106,8 @@ void Playlist::ReshuffleIndices() {
// Shuffle them // Shuffle them
QStringList shuffled_album_keys = album_key_set.values(); QStringList shuffled_album_keys = album_key_set.values();
std::random_shuffle(shuffled_album_keys.begin(), std::shuffle(shuffled_album_keys.begin(), shuffled_album_keys.end(),
shuffled_album_keys.end()); std::mt19937(rd()));
// If the user is currently playing a song, force its album to be first // If the user is currently playing a song, force its album to be first
// Or if the song was not playing but it was selected, force its album // Or if the song was not playing but it was selected, force its album

View File

@ -34,6 +34,12 @@
#undef AddJob #undef AddJob
#endif #endif
namespace {
const char kWavHeaderRiffMarker[] = "RIFF";
const char kWavFileTypeFormatChunk[] = "WAVEfmt ";
const char kWavDataString[] = "data";
} // namespace
Ripper::Ripper(int track_count, QObject* parent) Ripper::Ripper(int track_count, QObject* parent)
: QObject(parent), : QObject(parent),
track_count_(track_count), track_count_(track_count),

View File

@ -90,8 +90,10 @@ void SongInfoView::ReloadSettings() {
QVariantList default_order; QVariantList default_order;
default_order << "lyrics.wikia.com" default_order << "lyrics.wikia.com"
<< "lyricstime.com"
<< "lyricsreg.com" << "lyricsreg.com"
<< "lyricsmania.com" << "lyricsmania.com"
<< "metrolyrics.com"
<< "azlyrics.com" << "azlyrics.com"
<< "songlyrics.com" << "songlyrics.com"
<< "elyrics.net" << "elyrics.net"
@ -99,6 +101,7 @@ void SongInfoView::ReloadSettings() {
<< "lyrics.com" << "lyrics.com"
<< "lyricsbay.com" << "lyricsbay.com"
<< "directlyrics.com" << "directlyrics.com"
<< "loudson.gs"
<< "teksty.org" << "teksty.org"
<< "tekstowo.pl (Polish translations)" << "tekstowo.pl (Polish translations)"
<< "vagalume.uol.com.br" << "vagalume.uol.com.br"

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

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