Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b782a2c8a2 | ||
|
|
298783e2c5 | ||
|
|
bc9ec8025c | ||
|
|
26459763e5 | ||
|
|
1213306657 | ||
|
|
50add12e4b | ||
|
|
67c889f982 | ||
|
|
08cba25071 | ||
|
|
ff35b01bac | ||
|
|
faee1977fe | ||
|
|
6105b99a7f | ||
|
|
4993201b70 | ||
|
|
f456ca674d | ||
|
|
2ba350f76f | ||
|
|
3fe92a62ac | ||
|
|
f4dcf6821f | ||
|
|
0c10013858 | ||
|
|
3e9530fa8d | ||
|
|
0f4ffe4fce | ||
|
|
e1c01e5d25 | ||
|
|
51021131d7 | ||
|
|
89a08d1d5e | ||
|
|
ba8717f95a | ||
|
|
c8dfb9b0db | ||
|
|
3a02ece169 | ||
|
|
262df6b461 | ||
|
|
b9516fdfd4 | ||
|
|
9de41bc027 | ||
|
|
53b5cf3855 | ||
|
|
0567358783 | ||
|
|
c97bc55c6f | ||
|
|
3ef0bf60d0 | ||
|
|
b7b8084a38 | ||
|
|
5221f13498 | ||
|
|
0c0a8d70f3 | ||
|
|
2ff971878d | ||
|
|
1a0dc1e614 | ||
|
|
4a0bd99654 | ||
|
|
5cb98e44cb | ||
|
|
13ed99b9c3 | ||
|
|
0cda4e27aa | ||
|
|
0969e7f504 | ||
|
|
cad73e18e2 | ||
|
|
9eadeddfd9 | ||
|
|
de11cb173b | ||
|
|
5853bc68d1 | ||
|
|
7d1fd9d46f | ||
|
|
c977c822d5 | ||
|
|
c05fb33ea2 | ||
|
|
b9d0b3e152 | ||
|
|
a9e905b301 | ||
|
|
a8a714c820 | ||
|
|
9349ad9383 | ||
|
|
f686f00951 | ||
|
|
3d13c12cb7 | ||
|
|
2384a42d33 | ||
|
|
f507fec905 | ||
|
|
83a9724d17 | ||
|
|
4156e26f76 | ||
|
|
6d269e1786 | ||
|
|
ea447cab37 | ||
|
|
4f3e7de441 | ||
|
|
0a81fa99fc | ||
|
|
4aad44cb62 | ||
|
|
69dda39d02 | ||
|
|
ca3ba6f136 | ||
|
|
044cf4624a | ||
|
|
1fbfabdf66 | ||
|
|
db035351be | ||
|
|
2883ef840e | ||
|
|
8254ee911d | ||
|
|
560bc0a150 | ||
|
|
827898cd38 | ||
|
|
184dec146c | ||
|
|
298dbe96c8 | ||
|
|
6d888eb51a | ||
|
|
3694765611 | ||
|
|
b07ae3d34e | ||
|
|
64bcdf4734 | ||
|
|
1c23756fc4 | ||
|
|
50e3eeaafd | ||
|
|
843f528ebc | ||
|
|
faa0076988 | ||
|
|
59622c52ad | ||
|
|
a8e9aba58b | ||
|
|
36563cd1e1 | ||
|
|
072e712f0d | ||
|
|
121a186160 | ||
|
|
15a2ccc21e | ||
|
|
dbd8ea69eb | ||
|
|
8a57356f64 | ||
|
|
c77cb002f3 | ||
|
|
aa83a2b40b | ||
|
|
65b04cac6e | ||
|
|
5e577190a8 | ||
|
|
0143617056 | ||
|
|
a77dde7d3b | ||
|
|
7dcdb7c673 | ||
|
|
6de8eb56cd | ||
|
|
04e272d9bc | ||
|
|
17fe201473 | ||
|
|
25249be37f | ||
|
|
97ec12b5b3 | ||
|
|
246f82bfad | ||
|
|
db5679bbe9 | ||
|
|
feb0e1c45b | ||
|
|
edba837295 | ||
|
|
55882360ef | ||
|
|
6039370ad6 | ||
|
|
2d238c08d3 | ||
|
|
9b337b6a34 | ||
|
|
370db791aa | ||
|
|
9e3c547580 | ||
|
|
ab5d9b62b8 |
1
.gitignore
vendored
@@ -38,6 +38,7 @@ Thumbs.db
|
|||||||
*.nsi
|
*.nsi
|
||||||
*.plist
|
*.plist
|
||||||
maketarball.sh
|
maketarball.sh
|
||||||
|
dist/debian/changelog
|
||||||
|
|
||||||
# qtcreator generated files
|
# qtcreator generated files
|
||||||
*.pro.user*
|
*.pro.user*
|
||||||
|
|||||||
13
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
@@ -28,6 +28,7 @@
|
|||||||
#include <id3v2tag.h>
|
#include <id3v2tag.h>
|
||||||
#include <tstringlist.h>
|
#include <tstringlist.h>
|
||||||
#include <tpropertymap.h>
|
#include <tpropertymap.h>
|
||||||
|
#include <tagutils.h>
|
||||||
|
|
||||||
#include "tagunion.h"
|
#include "tagunion.h"
|
||||||
#include "dsdifffile.h"
|
#include "dsdifffile.h"
|
||||||
@@ -97,6 +98,18 @@ public:
|
|||||||
bool hasDiin;
|
bool hasDiin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// static members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool DSDIFF::File::isSupported(IOStream *stream)
|
||||||
|
{
|
||||||
|
// A DSDIFF file has to start with "FRM8????????DSD ".
|
||||||
|
|
||||||
|
const ByteVector id = Utils::readHeader(stream, 16, false);
|
||||||
|
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
9
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
@@ -185,6 +185,15 @@ namespace TagLib {
|
|||||||
*/
|
*/
|
||||||
bool hasDIINTag() const;
|
bool hasDIINTag() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns whether or not the given \a stream can be opened as a DSDIFF
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* \note This method is designed to do a quick check. The result may
|
||||||
|
* not necessarily be correct.
|
||||||
|
*/
|
||||||
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum Endianness { BigEndian, LittleEndian };
|
enum Endianness { BigEndian, LittleEndian };
|
||||||
|
|
||||||
|
|||||||
14
3rdparty/taglib/dsf/dsffile.cpp
vendored
@@ -1,5 +1,5 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
copyright : (C) 2013 by Stephen F. Booth
|
copyright : (C) 2013 - 2018 by Stephen F. Booth
|
||||||
email : me@sbooth.org
|
email : me@sbooth.org
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@
|
|||||||
#include <id3v2tag.h>
|
#include <id3v2tag.h>
|
||||||
#include <tstringlist.h>
|
#include <tstringlist.h>
|
||||||
#include <tpropertymap.h>
|
#include <tpropertymap.h>
|
||||||
|
#include <tagutils.h>
|
||||||
|
|
||||||
#include "dsffile.h"
|
#include "dsffile.h"
|
||||||
|
|
||||||
@@ -56,6 +57,17 @@ public:
|
|||||||
ID3v2::Tag *tag;
|
ID3v2::Tag *tag;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// static members
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool DSF::File::isSupported(IOStream *stream)
|
||||||
|
{
|
||||||
|
// A DSF file has to start with "DSD "
|
||||||
|
const ByteVector id = Utils::readHeader(stream, 4, false);
|
||||||
|
return id.startsWith("DSD ");
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
11
3rdparty/taglib/dsf/dsffile.h
vendored
@@ -1,5 +1,5 @@
|
|||||||
/***************************************************************************
|
/***************************************************************************
|
||||||
copyright : (C) 2013 by Stephen F. Booth
|
copyright : (C) 2013 - 2018 by Stephen F. Booth
|
||||||
email : me@sbooth.org
|
email : me@sbooth.org
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
@@ -103,6 +103,15 @@ namespace TagLib {
|
|||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Returns whether or not the given \a stream can be opened as a DSF
|
||||||
|
* file.
|
||||||
|
*
|
||||||
|
* \note This method is designed to do a quick check. The result may
|
||||||
|
* not necessarily be correct.
|
||||||
|
*/
|
||||||
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|||||||
8
3rdparty/taglib/fileref.cpp
vendored
@@ -180,10 +180,10 @@ namespace
|
|||||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
else if(APE::File::isSupported(stream))
|
else if(APE::File::isSupported(stream))
|
||||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
//else if(DSF::File::isSupported(stream))
|
else if(DSDIFF::File::isSupported(stream))
|
||||||
//return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
//else if(DSDIFF::File::isSupported(stream))
|
else if(DSF::File::isSupported(stream))
|
||||||
//return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
|
||||||
// isSupported() only does a quick check, so double check the file here.
|
// isSupported() only does a quick check, so double check the file here.
|
||||||
|
|
||||||
|
|||||||
@@ -216,7 +216,23 @@ void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id)
|
|||||||
|
|
||||||
String TableOfContentsFrame::toString() const
|
String TableOfContentsFrame::toString() const
|
||||||
{
|
{
|
||||||
return String();
|
String s = String(d->elementID) +
|
||||||
|
": top level: " + (d->isTopLevel ? "true" : "false") +
|
||||||
|
", ordered: " + (d->isOrdered ? "true" : "false");
|
||||||
|
|
||||||
|
if(!d->childElements.isEmpty()) {
|
||||||
|
s+= ", chapters: [ " + String(d->childElements.toByteVector(", ")) + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!d->embeddedFrameList.isEmpty()) {
|
||||||
|
StringList frameIDs;
|
||||||
|
for(FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
||||||
|
it != d->embeddedFrameList.end(); ++it)
|
||||||
|
frameIDs.append((*it)->frameID());
|
||||||
|
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap TableOfContentsFrame::asProperties() const
|
PropertyMap TableOfContentsFrame::asProperties() const
|
||||||
|
|||||||
@@ -339,7 +339,13 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const String &descripti
|
|||||||
|
|
||||||
String UserTextIdentificationFrame::toString() const
|
String UserTextIdentificationFrame::toString() const
|
||||||
{
|
{
|
||||||
return "[" + description() + "] " + fieldList().toString();
|
// first entry is the description itself, drop from values list
|
||||||
|
StringList l = fieldList();
|
||||||
|
for(StringList::Iterator it = l.begin(); it != l.end(); ++it) {
|
||||||
|
l.erase(it);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return "[" + description() + "] " + l.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
String UserTextIdentificationFrame::description() const
|
String UserTextIdentificationFrame::description() const
|
||||||
|
|||||||
14
3rdparty/taglib/ogg/flac/oggflacfile.cpp
vendored
@@ -231,11 +231,21 @@ void Ogg::FLAC::File::scan()
|
|||||||
|
|
||||||
if(!metadataHeader.startsWith("fLaC")) {
|
if(!metadataHeader.startsWith("fLaC")) {
|
||||||
// FLAC 1.1.2+
|
// FLAC 1.1.2+
|
||||||
|
// See https://xiph.org/flac/ogg_mapping.html for the header specification.
|
||||||
|
if(metadataHeader.size() < 13)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(metadataHeader[0] != 0x7f)
|
||||||
|
return;
|
||||||
|
|
||||||
if(metadataHeader.mid(1, 4) != "FLAC")
|
if(metadataHeader.mid(1, 4) != "FLAC")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(metadataHeader[5] != 1)
|
if(metadataHeader[5] != 1 && metadataHeader[6] != 0)
|
||||||
return; // not version 1
|
return; // not version 1.0
|
||||||
|
|
||||||
|
if(metadataHeader.mid(9, 4) != "fLaC")
|
||||||
|
return;
|
||||||
|
|
||||||
metadataHeader = metadataHeader.mid(13);
|
metadataHeader = metadataHeader.mid(13);
|
||||||
}
|
}
|
||||||
|
|||||||
41
3rdparty/taglib/toolkit/tfilestream.cpp
vendored
@@ -58,6 +58,11 @@ namespace
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHandle openFile(const int fileDescriptor, bool readOnly)
|
||||||
|
{
|
||||||
|
return InvalidFileHandle;
|
||||||
|
}
|
||||||
|
|
||||||
void closeFile(FileHandle file)
|
void closeFile(FileHandle file)
|
||||||
{
|
{
|
||||||
CloseHandle(file);
|
CloseHandle(file);
|
||||||
@@ -98,6 +103,11 @@ namespace
|
|||||||
return fopen(path, readOnly ? "rb" : "rb+");
|
return fopen(path, readOnly ? "rb" : "rb+");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHandle openFile(const int fileDescriptor, bool readOnly)
|
||||||
|
{
|
||||||
|
return fdopen(fileDescriptor, readOnly ? "rb" : "rb+");
|
||||||
|
}
|
||||||
|
|
||||||
void closeFile(FileHandle file)
|
void closeFile(FileHandle file)
|
||||||
{
|
{
|
||||||
fclose(file);
|
fclose(file);
|
||||||
@@ -149,13 +159,28 @@ FileStream::FileStream(FileName fileName, bool openReadOnly)
|
|||||||
d->file = openFile(fileName, true);
|
d->file = openFile(fileName, true);
|
||||||
|
|
||||||
if(d->file == InvalidFileHandle)
|
if(d->file == InvalidFileHandle)
|
||||||
{
|
|
||||||
# ifdef _WIN32
|
# ifdef _WIN32
|
||||||
debug("Could not open file " + fileName.toString());
|
debug("Could not open file " + fileName.toString());
|
||||||
# else
|
# else
|
||||||
debug("Could not open file " + String(static_cast<const char *>(d->name)));
|
debug("Could not open file " + String(static_cast<const char *>(d->name)));
|
||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileStream::FileStream(int fileDescriptor, bool openReadOnly)
|
||||||
|
: d(new FileStreamPrivate(""))
|
||||||
|
{
|
||||||
|
// First try with read / write mode, if that fails, fall back to read only.
|
||||||
|
|
||||||
|
if(!openReadOnly)
|
||||||
|
d->file = openFile(fileDescriptor, false);
|
||||||
|
|
||||||
|
if(d->file != InvalidFileHandle)
|
||||||
|
d->readOnly = false;
|
||||||
|
else
|
||||||
|
d->file = openFile(fileDescriptor, true);
|
||||||
|
|
||||||
|
if(d->file == InvalidFileHandle)
|
||||||
|
debug("Could not open file using file descriptor");
|
||||||
}
|
}
|
||||||
|
|
||||||
FileStream::~FileStream()
|
FileStream::~FileStream()
|
||||||
@@ -255,8 +280,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
|
|||||||
ByteVector buffer = data;
|
ByteVector buffer = data;
|
||||||
ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
|
ByteVector aboutToOverwrite(static_cast<unsigned int>(bufferLength));
|
||||||
|
|
||||||
while(true)
|
while(true) {
|
||||||
{
|
|
||||||
// Seek to the current read position and read the data that we're about
|
// Seek to the current read position and read the data that we're about
|
||||||
// to overwrite. Appropriately increment the readPosition.
|
// to overwrite. Appropriately increment the readPosition.
|
||||||
|
|
||||||
@@ -304,8 +328,7 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
|
|||||||
|
|
||||||
ByteVector buffer(static_cast<unsigned int>(bufferLength));
|
ByteVector buffer(static_cast<unsigned int>(bufferLength));
|
||||||
|
|
||||||
for(unsigned int bytesRead = -1; bytesRead != 0;)
|
for(unsigned int bytesRead = -1; bytesRead != 0;) {
|
||||||
{
|
|
||||||
seek(readPosition);
|
seek(readPosition);
|
||||||
bytesRead = static_cast<unsigned int>(readFile(d->file, buffer));
|
bytesRead = static_cast<unsigned int>(readFile(d->file, buffer));
|
||||||
readPosition += bytesRead;
|
readPosition += bytesRead;
|
||||||
@@ -401,7 +424,8 @@ long FileStream::tell() const
|
|||||||
const LARGE_INTEGER zero = {};
|
const LARGE_INTEGER zero = {};
|
||||||
LARGE_INTEGER position;
|
LARGE_INTEGER position;
|
||||||
|
|
||||||
if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) && position.QuadPart <= LONG_MAX) {
|
if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) &&
|
||||||
|
position.QuadPart <= LONG_MAX) {
|
||||||
return static_cast<long>(position.QuadPart);
|
return static_cast<long>(position.QuadPart);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -470,9 +494,8 @@ void FileStream::truncate(long length)
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
const int error = ftruncate(fileno(d->file), length);
|
const int error = ftruncate(fileno(d->file), length);
|
||||||
if(error != 0) {
|
if(error != 0)
|
||||||
debug("FileStream::truncate() -- Coundn't truncate the file.");
|
debug("FileStream::truncate() -- Coundn't truncate the file.");
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
5
3rdparty/taglib/toolkit/tfilestream.h
vendored
@@ -54,6 +54,11 @@ namespace TagLib {
|
|||||||
*/
|
*/
|
||||||
FileStream(FileName file, bool openReadOnly = false);
|
FileStream(FileName file, bool openReadOnly = false);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Construct a File object and opens the \a file using file descriptor.
|
||||||
|
*/
|
||||||
|
FileStream(int fileDescriptor, bool openReadOnly = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this FileStream instance.
|
* Destroys this FileStream instance.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Strawberry Music Player
|
# Strawberry Music Player
|
||||||
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
# This file was part of Clementine.
|
|
||||||
# Copyright 2010, David Sansome <me@davidsansome.com>
|
|
||||||
#
|
#
|
||||||
# Strawberry is free software: you can redistribute it and/or modify
|
# Strawberry is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -37,24 +35,27 @@ include(cmake/Rpm.cmake)
|
|||||||
include(cmake/Deb.cmake)
|
include(cmake/Deb.cmake)
|
||||||
|
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
|
||||||
set(LINUX 1)
|
set(LINUX ON)
|
||||||
endif()
|
endif()
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||||
set(FREEBSD 1)
|
set(FREEBSD ON)
|
||||||
endif()
|
endif()
|
||||||
if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
if (${CMAKE_SYSTEM_NAME} STREQUAL "OpenBSD")
|
||||||
set(OPENBSD 1)
|
set(OPENBSD ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
|
||||||
#set(CMAKE_BUILD_TYPE Debug)
|
|
||||||
|
|
||||||
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||||
add_definitions(-DNDEBUG)
|
add_definitions(-DNDEBUG)
|
||||||
add_definitions(-DQT_NO_DEBUG_OUTPUT)
|
add_definitions(-DQT_NO_DEBUG_OUTPUT)
|
||||||
#add_definitions(-DQT_NO_WARNING_OUTPUT)
|
#add_definitions(-DQT_NO_WARNING_OUTPUT)
|
||||||
endif(${CMAKE_BUILD_TYPE} MATCHES "Release")
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
||||||
|
set(DEBUG ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER MATCHES ".*clang")
|
if (CMAKE_CXX_COMPILER MATCHES ".*clang")
|
||||||
set(CMAKE_COMPILER_IS_CLANGXX 1)
|
set(CMAKE_COMPILER_IS_CLANGXX 1)
|
||||||
@@ -111,21 +112,20 @@ pkg_check_modules(PHONON phonon4qt5)
|
|||||||
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7)
|
pkg_check_modules(SQLITE REQUIRED sqlite3>=3.7)
|
||||||
pkg_check_modules(LIBPULSE libpulse)
|
pkg_check_modules(LIBPULSE libpulse)
|
||||||
pkg_check_modules(CHROMAPRINT libchromaprint)
|
pkg_check_modules(CHROMAPRINT libchromaprint)
|
||||||
#if(CHROMAPRINT_FOUND)
|
|
||||||
# set(HAVE_CHROMAPRINT ON)
|
|
||||||
#endif()
|
|
||||||
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
|
pkg_check_modules(LIBGPOD libgpod-1.0>=0.7.92)
|
||||||
pkg_check_modules(LIBMTP libmtp>=1.0)
|
pkg_check_modules(LIBMTP libmtp>=1.0)
|
||||||
pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0)
|
pkg_check_modules(IMOBILEDEVICE libimobiledevice-1.0)
|
||||||
pkg_check_modules(USBMUXD libusbmuxd)
|
pkg_check_modules(USBMUXD libusbmuxd)
|
||||||
pkg_check_modules(PLIST libplist)
|
pkg_check_modules(PLIST libplist)
|
||||||
|
pkg_check_modules(LIBDEEZER libdeezer)
|
||||||
|
pkg_check_modules(LIBDZMEDIA libdzmedia)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
find_package(ZLIB REQUIRED)
|
find_package(ZLIB REQUIRED)
|
||||||
endif(WIN32)
|
endif(WIN32)
|
||||||
|
|
||||||
# QT
|
# QT
|
||||||
set(QT_MIN_VERSION 5.6.0)
|
set(QT_MIN_VERSION 5.5.1)
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql OpenGL Xml)
|
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS Core Concurrent Widgets Network Sql OpenGL Xml)
|
||||||
if(X11_FOUND)
|
if(X11_FOUND)
|
||||||
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras)
|
find_package(Qt5 ${QT_MIN_VERSION} REQUIRED COMPONENTS X11Extras)
|
||||||
@@ -211,9 +211,9 @@ endif()
|
|||||||
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication library" OFF)
|
option(USE_SYSTEM_QTSINGLEAPPLICATION "Use system QtSingleApplication library" OFF)
|
||||||
if(USE_SYSTEM_QTSINGLEAPPLICATION)
|
if(USE_SYSTEM_QTSINGLEAPPLICATION)
|
||||||
message(STATUS "Using system QtSingleApplication library")
|
message(STATUS "Using system QtSingleApplication library")
|
||||||
find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES QtSolutions)
|
find_path(QTSINGLEAPPLICATION_INCLUDE_DIRS qtsingleapplication.h PATH_SUFFIXES qt5/QtSolutions)
|
||||||
find_library(QTSINGLEAPPLICATION_LIBRARIES QtSolutions_SingleApplication-2.6)
|
find_library(QTSINGLEAPPLICATION_LIBRARIES Qt5Solutions_SingleApplication-2.6)
|
||||||
find_library(QTSINGLECOREAPPLICATION_LIBRARIES QtSolutions_SingleCoreApplication-2.6)
|
find_library(QTSINGLECOREAPPLICATION_LIBRARIES Qt5Solutions_SingleCoreApplication-2.6)
|
||||||
else(USE_SYSTEM_QTSINGLEAPPLICATION)
|
else(USE_SYSTEM_QTSINGLEAPPLICATION)
|
||||||
message(STATUS "Using builtin QtSingleApplication library")
|
message(STATUS "Using builtin QtSingleApplication library")
|
||||||
add_subdirectory(3rdparty/qtsingleapplication)
|
add_subdirectory(3rdparty/qtsingleapplication)
|
||||||
@@ -225,11 +225,11 @@ endif(USE_SYSTEM_QTSINGLEAPPLICATION)
|
|||||||
option(USE_SYSTEM_QXT "Use system Qxt library" OFF)
|
option(USE_SYSTEM_QXT "Use system Qxt library" OFF)
|
||||||
if (USE_SYSTEM_QXT)
|
if (USE_SYSTEM_QXT)
|
||||||
message(STATUS "Using system Qxt library")
|
message(STATUS "Using system Qxt library")
|
||||||
find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES QxtCore)
|
find_path(QXTCORE_INCLUDE_DIRS qxtglobal.h PATH_SUFFIXES qt5/QxtCore)
|
||||||
find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES QxtGui)
|
find_path(QXTGUI_INCLUDE_DIRS qxtglobalshortcut.h PATH_SUFFIXES qt5/QxtWidgets)
|
||||||
set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS})
|
set(QXT_INCLUDE_DIRS ${QXTCORE_INCLUDE_DIRS} ${QXTGUI_INCLUDE_DIRS})
|
||||||
# We only need its header. We don't need to link to QxtCore.
|
# We only need its header. We don't need to link to QxtCore.
|
||||||
find_library(QXT_LIBRARIES QxtGui)
|
find_library(QXT_LIBRARIES QxtWidgets-qt5)
|
||||||
else (USE_SYSTEM_QXT)
|
else (USE_SYSTEM_QXT)
|
||||||
message(STATUS "Using builtin Qxt library")
|
message(STATUS "Using builtin Qxt library")
|
||||||
add_definitions(-DQXT_STATIC -DBUILD_QXT_GUI -DBUILD_QXT_CORE)
|
add_definitions(-DQXT_STATIC -DBUILD_QXT_GUI -DBUILD_QXT_CORE)
|
||||||
@@ -283,10 +283,22 @@ optional_component(VLC ON "Engine: VLC backend"
|
|||||||
DEPENDS "libvlc" LIBVLC_FOUND
|
DEPENDS "libvlc" LIBVLC_FOUND
|
||||||
)
|
)
|
||||||
|
|
||||||
optional_component(PHONON OFF "Engine: Phonon backend"
|
optional_component(PHONON OFF "Engine: Phonon backend (UNSTABLE)"
|
||||||
DEPENDS "phonon4qt5" PHONON_FOUND
|
DEPENDS "phonon4qt5" PHONON_FOUND
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
optional_component(DEEZER ON "Engine: Deezer backend"
|
||||||
|
DEPENDS "libdeezer" LIBDEEZER_FOUND
|
||||||
|
)
|
||||||
|
else ()
|
||||||
|
optional_component(DEEZER ON "Engine: Deezer backend"
|
||||||
|
DEPENDS "Linux" LINUX
|
||||||
|
DEPENDS "libdeezer" LIBDEEZER_FOUND
|
||||||
|
DEPENDS "libpulse" LIBPULSE_FOUND
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
optional_component(LIBPULSE ON "Pulse audio integration"
|
optional_component(LIBPULSE ON "Pulse audio integration"
|
||||||
DEPENDS "libpulse" LIBPULSE_FOUND
|
DEPENDS "libpulse" LIBPULSE_FOUND
|
||||||
)
|
)
|
||||||
@@ -336,6 +348,18 @@ optional_component(SPARKLE ON "Sparkle integration"
|
|||||||
DEPENDS "Sparkle" SPARKLE
|
DEPENDS "Sparkle" SPARKLE
|
||||||
)
|
)
|
||||||
|
|
||||||
|
optional_component(STREAM_TIDAL ON "Streaming: Tidal support")
|
||||||
|
optional_component(STREAM_DEEZER ON "Streaming: Deezer support")
|
||||||
|
|
||||||
|
optional_component(DZMEDIA ON "DZMedia"
|
||||||
|
DEPENDS "libdzmedia" LIBDZMEDIA_FOUND
|
||||||
|
DEPENDS "Deezer support" HAVE_STREAM_DEEZER
|
||||||
|
)
|
||||||
|
|
||||||
|
if (HAVE_STREAM_DEEZER AND NOT HAVE_DZMEDIA AND NOT HAVE_DEEZER)
|
||||||
|
message(STATUS "Deezer is enabled, but not DZMedia or Deezer engine, only preview streams will be available.")
|
||||||
|
endif()
|
||||||
|
|
||||||
#if(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
|
#if(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
|
||||||
#add_subdirectory(ext/gstafc)
|
#add_subdirectory(ext/gstafc)
|
||||||
#endif(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
|
#endif(IMOBILEDEVICE_FOUND AND PLIST_FOUND)
|
||||||
@@ -374,6 +398,8 @@ add_custom_target(uninstall
|
|||||||
|
|
||||||
# Show a summary of what we have enabled
|
# Show a summary of what we have enabled
|
||||||
summary_show()
|
summary_show()
|
||||||
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON)
|
if(NOT HAVE_GSTREAMER AND NOT HAVE_XINE AND NOT HAVE_VLC AND NOT HAVE_PHONON AND NOT HAVE_DEEZER)
|
||||||
message(FATAL_ERROR "You need to enable either GStreamer, Xine, VLC or Phonon to compile!")
|
message(FATAL_ERROR "You need to have either GStreamer, Xine, VLC, Phonon or Deezer 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()
|
endif()
|
||||||
|
|||||||
36
Changelog
@@ -2,6 +2,40 @@ Strawberry Music Player
|
|||||||
=======================
|
=======================
|
||||||
ChangeLog
|
ChangeLog
|
||||||
|
|
||||||
|
Version 0.4.1:
|
||||||
|
|
||||||
|
* Fixed crash in analyzer
|
||||||
|
* Fixed trying to use systray even if the desktop had no systray
|
||||||
|
* Fixed Tidal login loop bug
|
||||||
|
* Added Deezer support
|
||||||
|
* New improved fancy tabwidget
|
||||||
|
* Fixed bug not loading engine settings
|
||||||
|
* Moved queue manager into tabbar for easier access
|
||||||
|
* Fixed crash when changing appearance colors
|
||||||
|
* Improved error handling between player and engine
|
||||||
|
* Added setting to allow continue to the next song in the playlist based on error
|
||||||
|
* Improved Xine engine code
|
||||||
|
* Moved some settings
|
||||||
|
* Updated builtin taglib
|
||||||
|
* Added AppStream data file
|
||||||
|
* Fixed compiling with Qt 5 versions of system QtSingleApplication and Qxt library
|
||||||
|
|
||||||
|
Version 0.3.3:
|
||||||
|
|
||||||
|
* Fixed Tidal login
|
||||||
|
|
||||||
|
Version 0.3.2:
|
||||||
|
|
||||||
|
* Fixed search error not shown in Tidal search
|
||||||
|
* Added URL handler for Tidal, now retrieving URL's when playing instead of when searching
|
||||||
|
* Fixed bug in pipeline not setting url
|
||||||
|
* Fixed bug setting wrong temporary metadata
|
||||||
|
* Removed device module from windows, since it's not implemented for windows
|
||||||
|
* Added support for both ALSA hw and plughw
|
||||||
|
* Added option to change url stream scheme for Tidal
|
||||||
|
* Added encoding of Tidal token in the source code
|
||||||
|
* Added encoding of Tidal password in the configuration
|
||||||
|
|
||||||
Version 0.3.1:
|
Version 0.3.1:
|
||||||
|
|
||||||
* Added new lyrics provider with lyrics from AudD and API Seeds
|
* Added new lyrics provider with lyrics from AudD and API Seeds
|
||||||
@@ -49,7 +83,7 @@ Version 0.1.4:
|
|||||||
Version 0.1.3:
|
Version 0.1.3:
|
||||||
* Audio file detection by content
|
* Audio file detection by content
|
||||||
* Added builtin taglib to 3rdparty to support detecting audio by content instead of just file extension
|
* Added builtin taglib to 3rdparty to support detecting audio by content instead of just file extension
|
||||||
* Removed unneeded bulitin qsqlite from 3rdparty
|
* Removed unneeded qsqlite from 3rdparty
|
||||||
* Added sqldrivers\qsqlite.dll for windows build
|
* Added sqldrivers\qsqlite.dll for windows build
|
||||||
* Replaced incorrect DLL libgstdirectsoundsink.dll (from gst 1.12.4) instead of libgstdirectsound.dll (from gst 1.14.0) for windows build
|
* Replaced incorrect DLL libgstdirectsoundsink.dll (from gst 1.12.4) instead of libgstdirectsound.dll (from gst 1.14.0) for windows build
|
||||||
* Fixed git versioning
|
* Fixed git versioning
|
||||||
|
|||||||
11
README.md
@@ -25,7 +25,7 @@ It's written in C++ and Qt 5. The name is inspired by the band Strawbs.
|
|||||||
* Audio analyzer
|
* Audio analyzer
|
||||||
* Equalizer
|
* Equalizer
|
||||||
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
* Transfer music to iPod, iPhone, MTP or mass-storage USB player
|
||||||
* Integrated Tidal support
|
* Integrated Tidal and Deezer support
|
||||||
|
|
||||||
It has so far been tested to work on Linux, OpenBSD, MacOs and Windows.
|
It has so far been tested to work on Linux, OpenBSD, MacOs and Windows.
|
||||||
|
|
||||||
@@ -47,9 +47,13 @@ To build Strawberry from source you need the following installed on your system
|
|||||||
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
|
* [DBus (linux)](https://www.freedesktop.org/wiki/Software/dbus/)
|
||||||
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
|
* [PulseAudio (linux optional)](https://www.freedesktop.org/wiki/Software/PulseAudio/?)
|
||||||
|
|
||||||
Either GStreamer, Xine or VLC engine is required, but only GStreamer is fully implemented so far.
|
Either GStreamer, Xine, VLC, Deezer or Phonon engine is required, but only GStreamer is fully implemented so far.
|
||||||
You should also install the gstreamer plugins base and good, and optionally bad and ugly.
|
You should also install the gstreamer plugins base and good, and optionally bad and ugly.
|
||||||
|
|
||||||
|
Deezer streams with full songs are encrypted and only urls for preview streams (MP3) are exposed by the API.
|
||||||
|
Full length songs requires the use of deezers own engine (Deezer SDK) or the dzmedia library (I dont have it).
|
||||||
|
Deezer SDK can be found here: https://build-repo.deezer.com/native_sdk/deezer-native-sdk-v1.2.10.zip
|
||||||
|
|
||||||
Optional:
|
Optional:
|
||||||
|
|
||||||
* The Qt 5 LastFM library is required for fetching album covers from LastFM.
|
* The Qt 5 LastFM library is required for fetching album covers from LastFM.
|
||||||
@@ -73,4 +77,7 @@ Optional:
|
|||||||
|
|
||||||
(dont change to the source directory, if you created the build directory inside the source directory type: cmake .. instead).
|
(dont change to the source directory, if you created the build directory inside the source directory type: cmake .. instead).
|
||||||
|
|
||||||
|
### :computer: Screenshot
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|||||||
@@ -1,28 +1,66 @@
|
|||||||
find_program(LSB_RELEASE_EXEC lsb_release)
|
find_program(LSB_RELEASE_EXEC lsb_release)
|
||||||
execute_process(COMMAND ${LSB_RELEASE_EXEC} -is
|
find_program(RPMBUILD_EXEC rpmbuild)
|
||||||
OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT
|
|
||||||
OUTPUT_STRIP_TRAILING_WHITESPACE
|
|
||||||
)
|
|
||||||
|
|
||||||
if (LSB_RELEASE_EXEC)
|
if (LSB_RELEASE_EXEC AND RPMBUILD_EXEC)
|
||||||
set(RPMBUILD_DIR ~/rpmbuild CACHE STRING "Rpmbuild directory, for the rpm target")
|
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -is | tr '[:upper:]' '[:lower:]' | cut -d' ' -f1"
|
||||||
set(RPM_ARCH x86_64 CACHE STRING "Architecture of the rpm file")
|
OUTPUT_VARIABLE DIST_NAME
|
||||||
if (${LSB_RELEASE_ID_SHORT} STREQUAL "openSUSE")
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
set(RPM_DISTRO opensuse CACHE STRING "Suffix of the rpm file")
|
)
|
||||||
add_custom_target(rpm
|
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -ds | tr '[:upper:]' '[:lower:]' | sed 's/\"//g' | cut -d' ' -f2"
|
||||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
|
OUTPUT_VARIABLE DIST_RELEASE
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
|
)
|
||||||
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
|
execute_process(COMMAND /bin/sh "-c" "${LSB_RELEASE_EXEC} -ds | tr '[:upper:]' '[:lower:]' | sed 's/\"//g' | sed 's/\\.//g' | cut -d' ' -f3"
|
||||||
)
|
OUTPUT_VARIABLE DIST_VERSION
|
||||||
endif()
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
if (${LSB_RELEASE_ID_SHORT} STREQUAL "Fedora")
|
)
|
||||||
set(RPM_DISTRO fedora CACHE STRING "Suffix of the rpm file")
|
if (DIST_NAME)
|
||||||
add_custom_target(rpm
|
message(STATUS "Distro Name: ${DIST_NAME}")
|
||||||
COMMAND ${CMAKE_SOURCE_DIR}/dist/scripts/maketarball.sh
|
if (DIST_RELEASE)
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy strawberry-${STRAWBERRY_VERSION_PACKAGE}.tar.xz ${RPMBUILD_DIR}/SOURCES/
|
message(STATUS "Distro Release: ${DIST_RELEASE}")
|
||||||
COMMAND rpmbuild -bs ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
|
endif()
|
||||||
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
|
if (DIST_VERSION)
|
||||||
)
|
message(STATUS "Distro Version: ${DIST_VERSION}")
|
||||||
|
endif()
|
||||||
|
set(RPM_ARCH x86_64 CACHE STRING "Architecture of the rpm file")
|
||||||
|
set(RPMBUILD_DIR ~/rpmbuild CACHE STRING "Rpmbuild directory, for the rpm target")
|
||||||
|
if (${DIST_NAME} STREQUAL "opensuse")
|
||||||
|
if (DIST_RELEASE)
|
||||||
|
if (${DIST_RELEASE} STREQUAL "leap")
|
||||||
|
if (DIST_VERSION)
|
||||||
|
set(RPM_DISTRO "lp${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
|
||||||
|
else()
|
||||||
|
set(RPM_DISTRO ${DIST_RELEASE} CACHE STRING "Suffix of the rpm file")
|
||||||
|
endif()
|
||||||
|
elseif (${DIST_RELEASE} STREQUAL "tumbleweed")
|
||||||
|
set(RPM_DISTRO ${DIST_RELEASE} CACHE STRING "Suffix of the rpm file")
|
||||||
|
else ()
|
||||||
|
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||||
|
endif()
|
||||||
|
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/opensuse/strawberry.spec
|
||||||
|
COMMAND ${RPMBUILD_EXEC} -bb ${CMAKE_SOURCE_DIR}/dist/opensuse/strawberry.spec
|
||||||
|
)
|
||||||
|
elseif (${DIST_NAME} STREQUAL "fedora")
|
||||||
|
if (DIST_VERSION)
|
||||||
|
set(RPM_DISTRO "${DIST_NAME}${DIST_VERSION}" CACHE STRING "Suffix of the rpm file")
|
||||||
|
else ()
|
||||||
|
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||||
|
endif()
|
||||||
|
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 -bs ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
|
||||||
|
COMMAND rpmbuild -bb ${CMAKE_SOURCE_DIR}/dist/fedora/strawberry.spec
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
set(RPM_DISTRO ${DIST_NAME} CACHE STRING "Suffix of the rpm file")
|
||||||
|
endif()
|
||||||
|
message(STATUS "RPM Suffix: ${RPM_DISTRO}")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
set(STRAWBERRY_VERSION_MAJOR 0)
|
set(STRAWBERRY_VERSION_MAJOR 0)
|
||||||
set(STRAWBERRY_VERSION_MINOR 3)
|
set(STRAWBERRY_VERSION_MINOR 4)
|
||||||
set(STRAWBERRY_VERSION_PATCH 1)
|
set(STRAWBERRY_VERSION_PATCH 1)
|
||||||
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
#set(STRAWBERRY_VERSION_PRERELEASE rc1)
|
||||||
|
|
||||||
|
|||||||
438
data/data.qrc
@@ -7,6 +7,7 @@
|
|||||||
<file>schema/device-schema.sql</file>
|
<file>schema/device-schema.sql</file>
|
||||||
<file>style/strawberry.css</file>
|
<file>style/strawberry.css</file>
|
||||||
<file>misc/playing_tooltip.txt</file>
|
<file>misc/playing_tooltip.txt</file>
|
||||||
|
<file>misc/oauthsuccess.html</file>
|
||||||
<file>pictures/strawberry.png</file>
|
<file>pictures/strawberry.png</file>
|
||||||
<file>pictures/strawbs-transparent.png</file>
|
<file>pictures/strawbs-transparent.png</file>
|
||||||
<file>pictures/noalbumart.png</file>
|
<file>pictures/noalbumart.png</file>
|
||||||
@@ -27,442 +28,7 @@
|
|||||||
<file>pictures/osd_background.png</file>
|
<file>pictures/osd_background.png</file>
|
||||||
<file>pictures/osd_shadow_corner.png</file>
|
<file>pictures/osd_shadow_corner.png</file>
|
||||||
<file>pictures/osd_shadow_edge.png</file>
|
<file>pictures/osd_shadow_edge.png</file>
|
||||||
<file>icons/128x128/albums.png</file>
|
<file>pictures/deezer.png</file>
|
||||||
<file>icons/128x128/alsa.png</file>
|
|
||||||
<file>icons/128x128/application-exit.png</file>
|
|
||||||
<file>icons/128x128/applications-internet.png</file>
|
|
||||||
<file>icons/128x128/bluetooth.png</file>
|
|
||||||
<file>icons/128x128/cdcase.png</file>
|
|
||||||
<file>icons/128x128/cd.png</file>
|
|
||||||
<file>icons/128x128/configure.png</file>
|
|
||||||
<file>icons/128x128/device-ipod-nano.png</file>
|
|
||||||
<file>icons/128x128/device-ipod.png</file>
|
|
||||||
<file>icons/128x128/device-phone.png</file>
|
|
||||||
<file>icons/128x128/device.png</file>
|
|
||||||
<file>icons/128x128/device-usb-drive.png</file>
|
|
||||||
<file>icons/128x128/device-usb-flash.png</file>
|
|
||||||
<file>icons/128x128/dialog-error.png</file>
|
|
||||||
<file>icons/128x128/dialog-information.png</file>
|
|
||||||
<file>icons/128x128/dialog-ok-apply.png</file>
|
|
||||||
<file>icons/128x128/dialog-password.png</file>
|
|
||||||
<file>icons/128x128/dialog-warning.png</file>
|
|
||||||
<file>icons/128x128/document-download.png</file>
|
|
||||||
<file>icons/128x128/document-new.png</file>
|
|
||||||
<file>icons/128x128/document-open-folder.png</file>
|
|
||||||
<file>icons/128x128/document-open.png</file>
|
|
||||||
<file>icons/128x128/document-save.png</file>
|
|
||||||
<file>icons/128x128/document-search.png</file>
|
|
||||||
<file>icons/128x128/download.png</file>
|
|
||||||
<file>icons/128x128/edit-clear-list.png</file>
|
|
||||||
<file>icons/128x128/edit-clear-locationbar-ltr.png</file>
|
|
||||||
<file>icons/128x128/edit-copy.png</file>
|
|
||||||
<file>icons/128x128/edit-delete.png</file>
|
|
||||||
<file>icons/128x128/edit-find.png</file>
|
|
||||||
<file>icons/128x128/edit-redo.png</file>
|
|
||||||
<file>icons/128x128/edit-rename.png</file>
|
|
||||||
<file>icons/128x128/edit-undo.png</file>
|
|
||||||
<file>icons/128x128/electrocompaniet.png</file>
|
|
||||||
<file>icons/128x128/equalizer.png</file>
|
|
||||||
<file>icons/128x128/folder-new.png</file>
|
|
||||||
<file>icons/128x128/folder.png</file>
|
|
||||||
<file>icons/128x128/folder-sound.png</file>
|
|
||||||
<file>icons/128x128/footsteps.png</file>
|
|
||||||
<file>icons/128x128/go-down.png</file>
|
|
||||||
<file>icons/128x128/go-home.png</file>
|
|
||||||
<file>icons/128x128/go-jump.png</file>
|
|
||||||
<file>icons/128x128/go-next.png</file>
|
|
||||||
<file>icons/128x128/go-previous.png</file>
|
|
||||||
<file>icons/128x128/go-up.png</file>
|
|
||||||
<file>icons/128x128/gstreamer.png</file>
|
|
||||||
<file>icons/128x128/headset.png</file>
|
|
||||||
<file>icons/128x128/help-hint.png</file>
|
|
||||||
<file>icons/128x128/intel.png</file>
|
|
||||||
<file>icons/128x128/jack.png</file>
|
|
||||||
<file>icons/128x128/keyboard.png</file>
|
|
||||||
<file>icons/128x128/list-add.png</file>
|
|
||||||
<file>icons/128x128/list-remove.png</file>
|
|
||||||
<file>icons/128x128/mcintosh-player.png</file>
|
|
||||||
<file>icons/128x128/mcintosh-text.png</file>
|
|
||||||
<file>icons/128x128/media-eject.png</file>
|
|
||||||
<file>icons/128x128/media-forward.png</file>
|
|
||||||
<file>icons/128x128/media-pause.png</file>
|
|
||||||
<file>icons/128x128/media-play.png</file>
|
|
||||||
<file>icons/128x128/media-rewind.png</file>
|
|
||||||
<file>icons/128x128/media-stop.png</file>
|
|
||||||
<file>icons/128x128/nvidia.png</file>
|
|
||||||
<file>icons/128x128/play2.png</file>
|
|
||||||
<file>icons/128x128/realtek.png</file>
|
|
||||||
<file>icons/128x128/search.png</file>
|
|
||||||
<file>icons/128x128/soundcard.png</file>
|
|
||||||
<file>icons/128x128/speaker.png</file>
|
|
||||||
<file>icons/128x128/star-grey.png</file>
|
|
||||||
<file>icons/128x128/star.png</file>
|
|
||||||
<file>icons/128x128/strawberry.png</file>
|
|
||||||
<file>icons/128x128/strawberry.svg</file>
|
|
||||||
<file>icons/128x128/tools-wizard.png</file>
|
|
||||||
<file>icons/128x128/view-choose.png</file>
|
|
||||||
<file>icons/128x128/view-fullscreen.png</file>
|
|
||||||
<file>icons/128x128/view-media-lyrics.png</file>
|
|
||||||
<file>icons/128x128/view-media-playlist.png</file>
|
|
||||||
<file>icons/128x128/view-media-visualization.png</file>
|
|
||||||
<file>icons/128x128/view-refresh.png</file>
|
|
||||||
<file>icons/128x128/vinyl.png</file>
|
|
||||||
<file>icons/128x128/vlc.png</file>
|
|
||||||
<file>icons/128x128/xine.png</file>
|
|
||||||
<file>icons/128x128/zoom-in.png</file>
|
|
||||||
<file>icons/128x128/zoom-out.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>
|
|
||||||
<file>icons/64x64/applications-internet.png</file>
|
|
||||||
<file>icons/64x64/bluetooth.png</file>
|
|
||||||
<file>icons/64x64/cdcase.png</file>
|
|
||||||
<file>icons/64x64/cd.png</file>
|
|
||||||
<file>icons/64x64/configure.png</file>
|
|
||||||
<file>icons/64x64/device-ipod-nano.png</file>
|
|
||||||
<file>icons/64x64/device-ipod.png</file>
|
|
||||||
<file>icons/64x64/device-phone.png</file>
|
|
||||||
<file>icons/64x64/device.png</file>
|
|
||||||
<file>icons/64x64/device-usb-drive.png</file>
|
|
||||||
<file>icons/64x64/device-usb-flash.png</file>
|
|
||||||
<file>icons/64x64/dialog-error.png</file>
|
|
||||||
<file>icons/64x64/dialog-information.png</file>
|
|
||||||
<file>icons/64x64/dialog-ok-apply.png</file>
|
|
||||||
<file>icons/64x64/dialog-password.png</file>
|
|
||||||
<file>icons/64x64/dialog-warning.png</file>
|
|
||||||
<file>icons/64x64/document-download.png</file>
|
|
||||||
<file>icons/64x64/document-new.png</file>
|
|
||||||
<file>icons/64x64/document-open-folder.png</file>
|
|
||||||
<file>icons/64x64/document-open.png</file>
|
|
||||||
<file>icons/64x64/document-save.png</file>
|
|
||||||
<file>icons/64x64/document-search.png</file>
|
|
||||||
<file>icons/64x64/download.png</file>
|
|
||||||
<file>icons/64x64/edit-clear-list.png</file>
|
|
||||||
<file>icons/64x64/edit-clear-locationbar-ltr.png</file>
|
|
||||||
<file>icons/64x64/edit-copy.png</file>
|
|
||||||
<file>icons/64x64/edit-delete.png</file>
|
|
||||||
<file>icons/64x64/edit-find.png</file>
|
|
||||||
<file>icons/64x64/edit-redo.png</file>
|
|
||||||
<file>icons/64x64/edit-rename.png</file>
|
|
||||||
<file>icons/64x64/edit-undo.png</file>
|
|
||||||
<file>icons/64x64/electrocompaniet.png</file>
|
|
||||||
<file>icons/64x64/equalizer.png</file>
|
|
||||||
<file>icons/64x64/folder-new.png</file>
|
|
||||||
<file>icons/64x64/folder.png</file>
|
|
||||||
<file>icons/64x64/folder-sound.png</file>
|
|
||||||
<file>icons/64x64/footsteps.png</file>
|
|
||||||
<file>icons/64x64/go-down.png</file>
|
|
||||||
<file>icons/64x64/go-home.png</file>
|
|
||||||
<file>icons/64x64/go-jump.png</file>
|
|
||||||
<file>icons/64x64/go-next.png</file>
|
|
||||||
<file>icons/64x64/go-previous.png</file>
|
|
||||||
<file>icons/64x64/go-up.png</file>
|
|
||||||
<file>icons/64x64/gstreamer.png</file>
|
|
||||||
<file>icons/64x64/headset.png</file>
|
|
||||||
<file>icons/64x64/help-hint.png</file>
|
|
||||||
<file>icons/64x64/intel.png</file>
|
|
||||||
<file>icons/64x64/jack.png</file>
|
|
||||||
<file>icons/64x64/keyboard.png</file>
|
|
||||||
<file>icons/64x64/list-add.png</file>
|
|
||||||
<file>icons/64x64/list-remove.png</file>
|
|
||||||
<file>icons/64x64/mcintosh-player.png</file>
|
|
||||||
<file>icons/64x64/mcintosh-text.png</file>
|
|
||||||
<file>icons/64x64/media-eject.png</file>
|
|
||||||
<file>icons/64x64/media-forward.png</file>
|
|
||||||
<file>icons/64x64/media-pause.png</file>
|
|
||||||
<file>icons/64x64/media-play.png</file>
|
|
||||||
<file>icons/64x64/media-rewind.png</file>
|
|
||||||
<file>icons/64x64/media-stop.png</file>
|
|
||||||
<file>icons/64x64/nvidia.png</file>
|
|
||||||
<file>icons/64x64/play2.png</file>
|
|
||||||
<file>icons/64x64/pulseaudio.png</file>
|
|
||||||
<file>icons/64x64/realtek.png</file>
|
|
||||||
<file>icons/64x64/search.png</file>
|
|
||||||
<file>icons/64x64/soundcard.png</file>
|
|
||||||
<file>icons/64x64/speaker.png</file>
|
|
||||||
<file>icons/64x64/star-grey.png</file>
|
|
||||||
<file>icons/64x64/star.png</file>
|
|
||||||
<file>icons/64x64/strawberry.png</file>
|
|
||||||
<file>icons/64x64/tools-wizard.png</file>
|
|
||||||
<file>icons/64x64/view-choose.png</file>
|
|
||||||
<file>icons/64x64/view-fullscreen.png</file>
|
|
||||||
<file>icons/64x64/view-media-lyrics.png</file>
|
|
||||||
<file>icons/64x64/view-media-playlist.png</file>
|
|
||||||
<file>icons/64x64/view-media-visualization.png</file>
|
|
||||||
<file>icons/64x64/view-refresh.png</file>
|
|
||||||
<file>icons/64x64/vinyl.png</file>
|
|
||||||
<file>icons/64x64/vlc.png</file>
|
|
||||||
<file>icons/64x64/xine.png</file>
|
|
||||||
<file>icons/64x64/zoom-in.png</file>
|
|
||||||
<file>icons/64x64/zoom-out.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>
|
|
||||||
<file>icons/48x48/applications-internet.png</file>
|
|
||||||
<file>icons/48x48/bluetooth.png</file>
|
|
||||||
<file>icons/48x48/cdcase.png</file>
|
|
||||||
<file>icons/48x48/cd.png</file>
|
|
||||||
<file>icons/48x48/configure.png</file>
|
|
||||||
<file>icons/48x48/device-ipod-nano.png</file>
|
|
||||||
<file>icons/48x48/device-ipod.png</file>
|
|
||||||
<file>icons/48x48/device-phone.png</file>
|
|
||||||
<file>icons/48x48/device.png</file>
|
|
||||||
<file>icons/48x48/device-usb-drive.png</file>
|
|
||||||
<file>icons/48x48/device-usb-flash.png</file>
|
|
||||||
<file>icons/48x48/dialog-error.png</file>
|
|
||||||
<file>icons/48x48/dialog-information.png</file>
|
|
||||||
<file>icons/48x48/dialog-ok-apply.png</file>
|
|
||||||
<file>icons/48x48/dialog-password.png</file>
|
|
||||||
<file>icons/48x48/dialog-warning.png</file>
|
|
||||||
<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.png</file>
|
|
||||||
<file>icons/48x48/document-save.png</file>
|
|
||||||
<file>icons/48x48/document-search.png</file>
|
|
||||||
<file>icons/48x48/download.png</file>
|
|
||||||
<file>icons/48x48/edit-clear-list.png</file>
|
|
||||||
<file>icons/48x48/edit-clear-locationbar-ltr.png</file>
|
|
||||||
<file>icons/48x48/edit-copy.png</file>
|
|
||||||
<file>icons/48x48/edit-delete.png</file>
|
|
||||||
<file>icons/48x48/edit-find.png</file>
|
|
||||||
<file>icons/48x48/edit-redo.png</file>
|
|
||||||
<file>icons/48x48/edit-rename.png</file>
|
|
||||||
<file>icons/48x48/edit-undo.png</file>
|
|
||||||
<file>icons/48x48/electrocompaniet.png</file>
|
|
||||||
<file>icons/48x48/equalizer.png</file>
|
|
||||||
<file>icons/48x48/folder-new.png</file>
|
|
||||||
<file>icons/48x48/folder.png</file>
|
|
||||||
<file>icons/48x48/folder-sound.png</file>
|
|
||||||
<file>icons/48x48/footsteps.png</file>
|
|
||||||
<file>icons/48x48/go-down.png</file>
|
|
||||||
<file>icons/48x48/go-home.png</file>
|
|
||||||
<file>icons/48x48/go-jump.png</file>
|
|
||||||
<file>icons/48x48/go-next.png</file>
|
|
||||||
<file>icons/48x48/go-previous.png</file>
|
|
||||||
<file>icons/48x48/go-up.png</file>
|
|
||||||
<file>icons/48x48/gstreamer.png</file>
|
|
||||||
<file>icons/48x48/headset.png</file>
|
|
||||||
<file>icons/48x48/help-hint.png</file>
|
|
||||||
<file>icons/48x48/intel.png</file>
|
|
||||||
<file>icons/48x48/jack.png</file>
|
|
||||||
<file>icons/48x48/keyboard.png</file>
|
|
||||||
<file>icons/48x48/list-add.png</file>
|
|
||||||
<file>icons/48x48/list-remove.png</file>
|
|
||||||
<file>icons/48x48/mcintosh-player.png</file>
|
|
||||||
<file>icons/48x48/mcintosh.png</file>
|
|
||||||
<file>icons/48x48/mcintosh-text.png</file>
|
|
||||||
<file>icons/48x48/media-eject.png</file>
|
|
||||||
<file>icons/48x48/media-forward.png</file>
|
|
||||||
<file>icons/48x48/media-pause.png</file>
|
|
||||||
<file>icons/48x48/media-playlist-repeat.png</file>
|
|
||||||
<file>icons/48x48/media-playlist-shuffle.png</file>
|
|
||||||
<file>icons/48x48/media-play.png</file>
|
|
||||||
<file>icons/48x48/media-rewind.png</file>
|
|
||||||
<file>icons/48x48/media-stop.png</file>
|
|
||||||
<file>icons/48x48/nvidia.png</file>
|
|
||||||
<file>icons/48x48/play2.png</file>
|
|
||||||
<file>icons/48x48/pulseaudio.png</file>
|
|
||||||
<file>icons/48x48/realtek.png</file>
|
|
||||||
<file>icons/48x48/search.png</file>
|
|
||||||
<file>icons/48x48/soundcard.png</file>
|
|
||||||
<file>icons/48x48/speaker.png</file>
|
|
||||||
<file>icons/48x48/star-grey.png</file>
|
|
||||||
<file>icons/48x48/star.png</file>
|
|
||||||
<file>icons/48x48/strawberry.png</file>
|
|
||||||
<file>icons/48x48/tools-wizard.png</file>
|
|
||||||
<file>icons/48x48/view-choose.png</file>
|
|
||||||
<file>icons/48x48/view-fullscreen.png</file>
|
|
||||||
<file>icons/48x48/view-media-lyrics.png</file>
|
|
||||||
<file>icons/48x48/view-media-playlist.png</file>
|
|
||||||
<file>icons/48x48/view-media-visualization.png</file>
|
|
||||||
<file>icons/48x48/view-refresh.png</file>
|
|
||||||
<file>icons/48x48/vinyl.png</file>
|
|
||||||
<file>icons/48x48/vlc.png</file>
|
|
||||||
<file>icons/48x48/xine.png</file>
|
|
||||||
<file>icons/48x48/zoom-in.png</file>
|
|
||||||
<file>icons/48x48/zoom-out.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>
|
|
||||||
<file>icons/32x32/applications-internet.png</file>
|
|
||||||
<file>icons/32x32/bluetooth.png</file>
|
|
||||||
<file>icons/32x32/cdcase.png</file>
|
|
||||||
<file>icons/32x32/cd.png</file>
|
|
||||||
<file>icons/32x32/configure.png</file>
|
|
||||||
<file>icons/32x32/device-ipod-nano.png</file>
|
|
||||||
<file>icons/32x32/device-ipod.png</file>
|
|
||||||
<file>icons/32x32/device-phone.png</file>
|
|
||||||
<file>icons/32x32/device.png</file>
|
|
||||||
<file>icons/32x32/device-usb-drive.png</file>
|
|
||||||
<file>icons/32x32/device-usb-flash.png</file>
|
|
||||||
<file>icons/32x32/dialog-error.png</file>
|
|
||||||
<file>icons/32x32/dialog-information.png</file>
|
|
||||||
<file>icons/32x32/dialog-ok-apply.png</file>
|
|
||||||
<file>icons/32x32/dialog-password.png</file>
|
|
||||||
<file>icons/32x32/dialog-warning.png</file>
|
|
||||||
<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.png</file>
|
|
||||||
<file>icons/32x32/document-save.png</file>
|
|
||||||
<file>icons/32x32/document-search.png</file>
|
|
||||||
<file>icons/32x32/download.png</file>
|
|
||||||
<file>icons/32x32/edit-clear-list.png</file>
|
|
||||||
<file>icons/32x32/edit-clear-locationbar-ltr.png</file>
|
|
||||||
<file>icons/32x32/edit-copy.png</file>
|
|
||||||
<file>icons/32x32/edit-delete.png</file>
|
|
||||||
<file>icons/32x32/edit-find.png</file>
|
|
||||||
<file>icons/32x32/edit-redo.png</file>
|
|
||||||
<file>icons/32x32/edit-rename.png</file>
|
|
||||||
<file>icons/32x32/edit-undo.png</file>
|
|
||||||
<file>icons/32x32/electrocompaniet.png</file>
|
|
||||||
<file>icons/32x32/equalizer.png</file>
|
|
||||||
<file>icons/32x32/folder-new.png</file>
|
|
||||||
<file>icons/32x32/folder.png</file>
|
|
||||||
<file>icons/32x32/folder-sound.png</file>
|
|
||||||
<file>icons/32x32/footsteps.png</file>
|
|
||||||
<file>icons/32x32/go-down.png</file>
|
|
||||||
<file>icons/32x32/go-home.png</file>
|
|
||||||
<file>icons/32x32/go-jump.png</file>
|
|
||||||
<file>icons/32x32/go-next.png</file>
|
|
||||||
<file>icons/32x32/go-previous.png</file>
|
|
||||||
<file>icons/32x32/go-up.png</file>
|
|
||||||
<file>icons/32x32/gstreamer.png</file>
|
|
||||||
<file>icons/32x32/headset.png</file>
|
|
||||||
<file>icons/32x32/help-hint.png</file>
|
|
||||||
<file>icons/32x32/intel.png</file>
|
|
||||||
<file>icons/32x32/jack.png</file>
|
|
||||||
<file>icons/32x32/keyboard.png</file>
|
|
||||||
<file>icons/32x32/list-add.png</file>
|
|
||||||
<file>icons/32x32/list-remove.png</file>
|
|
||||||
<file>icons/32x32/mcintosh-player.png</file>
|
|
||||||
<file>icons/32x32/mcintosh.png</file>
|
|
||||||
<file>icons/32x32/mcintosh-text.png</file>
|
|
||||||
<file>icons/32x32/media-eject.png</file>
|
|
||||||
<file>icons/32x32/media-forward.png</file>
|
|
||||||
<file>icons/32x32/media-pause.png</file>
|
|
||||||
<file>icons/32x32/media-playlist-repeat.png</file>
|
|
||||||
<file>icons/32x32/media-playlist-shuffle.png</file>
|
|
||||||
<file>icons/32x32/media-play.png</file>
|
|
||||||
<file>icons/32x32/media-rewind.png</file>
|
|
||||||
<file>icons/32x32/media-stop.png</file>
|
|
||||||
<file>icons/32x32/nvidia.png</file>
|
|
||||||
<file>icons/32x32/play2.png</file>
|
|
||||||
<file>icons/32x32/pulseaudio.png</file>
|
|
||||||
<file>icons/32x32/realtek.png</file>
|
|
||||||
<file>icons/32x32/search.png</file>
|
|
||||||
<file>icons/32x32/soundcard.png</file>
|
|
||||||
<file>icons/32x32/speaker.png</file>
|
|
||||||
<file>icons/32x32/star-grey.png</file>
|
|
||||||
<file>icons/32x32/star.png</file>
|
|
||||||
<file>icons/32x32/strawberry.png</file>
|
|
||||||
<file>icons/32x32/strawberry.svg</file>
|
|
||||||
<file>icons/32x32/tools-wizard.png</file>
|
|
||||||
<file>icons/32x32/view-choose.png</file>
|
|
||||||
<file>icons/32x32/view-fullscreen.png</file>
|
|
||||||
<file>icons/32x32/view-media-lyrics.png</file>
|
|
||||||
<file>icons/32x32/view-media-playlist.png</file>
|
|
||||||
<file>icons/32x32/view-media-visualization.png</file>
|
|
||||||
<file>icons/32x32/view-refresh.png</file>
|
|
||||||
<file>icons/32x32/vinyl.png</file>
|
|
||||||
<file>icons/32x32/vlc.png</file>
|
|
||||||
<file>icons/32x32/xine.png</file>
|
|
||||||
<file>icons/32x32/zoom-in.png</file>
|
|
||||||
<file>icons/32x32/zoom-out.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>
|
|
||||||
<file>icons/22x22/applications-internet.png</file>
|
|
||||||
<file>icons/22x22/bluetooth.png</file>
|
|
||||||
<file>icons/22x22/cdcase.png</file>
|
|
||||||
<file>icons/22x22/cd.png</file>
|
|
||||||
<file>icons/22x22/configure.png</file>
|
|
||||||
<file>icons/22x22/device-ipod-nano.png</file>
|
|
||||||
<file>icons/22x22/device-ipod.png</file>
|
|
||||||
<file>icons/22x22/device-phone.png</file>
|
|
||||||
<file>icons/22x22/device.png</file>
|
|
||||||
<file>icons/22x22/device-usb-drive.png</file>
|
|
||||||
<file>icons/22x22/device-usb-flash.png</file>
|
|
||||||
<file>icons/22x22/dialog-error.png</file>
|
|
||||||
<file>icons/22x22/dialog-information.png</file>
|
|
||||||
<file>icons/22x22/dialog-ok-apply.png</file>
|
|
||||||
<file>icons/22x22/dialog-password.png</file>
|
|
||||||
<file>icons/22x22/dialog-warning.png</file>
|
|
||||||
<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.png</file>
|
|
||||||
<file>icons/22x22/document-save.png</file>
|
|
||||||
<file>icons/22x22/document-search.png</file>
|
|
||||||
<file>icons/22x22/download.png</file>
|
|
||||||
<file>icons/22x22/edit-clear-list.png</file>
|
|
||||||
<file>icons/22x22/edit-clear-locationbar-ltr.png</file>
|
|
||||||
<file>icons/22x22/edit-copy.png</file>
|
|
||||||
<file>icons/22x22/edit-delete.png</file>
|
|
||||||
<file>icons/22x22/edit-find.png</file>
|
|
||||||
<file>icons/22x22/edit-redo.png</file>
|
|
||||||
<file>icons/22x22/edit-rename.png</file>
|
|
||||||
<file>icons/22x22/edit-undo.png</file>
|
|
||||||
<file>icons/22x22/electrocompaniet.png</file>
|
|
||||||
<file>icons/22x22/equalizer.png</file>
|
|
||||||
<file>icons/22x22/folder-new.png</file>
|
|
||||||
<file>icons/22x22/folder.png</file>
|
|
||||||
<file>icons/22x22/folder-sound.png</file>
|
|
||||||
<file>icons/22x22/footsteps.png</file>
|
|
||||||
<file>icons/22x22/go-down.png</file>
|
|
||||||
<file>icons/22x22/go-home.png</file>
|
|
||||||
<file>icons/22x22/go-jump.png</file>
|
|
||||||
<file>icons/22x22/go-next.png</file>
|
|
||||||
<file>icons/22x22/go-previous.png</file>
|
|
||||||
<file>icons/22x22/go-up.png</file>
|
|
||||||
<file>icons/22x22/gstreamer.png</file>
|
|
||||||
<file>icons/22x22/headset.png</file>
|
|
||||||
<file>icons/22x22/help-hint.png</file>
|
|
||||||
<file>icons/22x22/intel.png</file>
|
|
||||||
<file>icons/22x22/jack.png</file>
|
|
||||||
<file>icons/22x22/keyboard.png</file>
|
|
||||||
<file>icons/22x22/list-add.png</file>
|
|
||||||
<file>icons/22x22/list-remove.png</file>
|
|
||||||
<file>icons/22x22/mcintosh-player.png</file>
|
|
||||||
<file>icons/22x22/mcintosh.png</file>
|
|
||||||
<file>icons/22x22/mcintosh-text.png</file>
|
|
||||||
<file>icons/22x22/media-eject.png</file>
|
|
||||||
<file>icons/22x22/media-forward.png</file>
|
|
||||||
<file>icons/22x22/media-pause.png</file>
|
|
||||||
<file>icons/22x22/media-playlist-repeat.png</file>
|
|
||||||
<file>icons/22x22/media-playlist-shuffle.png</file>
|
|
||||||
<file>icons/22x22/media-play.png</file>
|
|
||||||
<file>icons/22x22/media-rewind.png</file>
|
|
||||||
<file>icons/22x22/media-stop.png</file>
|
|
||||||
<file>icons/22x22/nvidia.png</file>
|
|
||||||
<file>icons/22x22/play2.png</file>
|
|
||||||
<file>icons/22x22/pulseaudio.png</file>
|
|
||||||
<file>icons/22x22/realtek.png</file>
|
|
||||||
<file>icons/22x22/search.png</file>
|
|
||||||
<file>icons/22x22/soundcard.png</file>
|
|
||||||
<file>icons/22x22/speaker.png</file>
|
|
||||||
<file>icons/22x22/star-grey.png</file>
|
|
||||||
<file>icons/22x22/star.png</file>
|
|
||||||
<file>icons/22x22/strawberry.png</file>
|
|
||||||
<file>icons/22x22/strawberry.svg</file>
|
|
||||||
<file>icons/22x22/tools-wizard.png</file>
|
|
||||||
<file>icons/22x22/view-choose.png</file>
|
|
||||||
<file>icons/22x22/view-fullscreen.png</file>
|
|
||||||
<file>icons/22x22/view-media-lyrics.png</file>
|
|
||||||
<file>icons/22x22/view-media-playlist.png</file>
|
|
||||||
<file>icons/22x22/view-media-visualization.png</file>
|
|
||||||
<file>icons/22x22/view-refresh.png</file>
|
|
||||||
<file>icons/22x22/vinyl.png</file>
|
|
||||||
<file>icons/22x22/vlc.png</file>
|
|
||||||
<file>icons/22x22/xine.png</file>
|
|
||||||
<file>icons/22x22/zoom-in.png</file>
|
|
||||||
<file>icons/22x22/zoom-out.png</file>
|
|
||||||
<file>icons/22x22/tidal.png</file>
|
|
||||||
<file>fonts/HumongousofEternitySt.ttf</file>
|
<file>fonts/HumongousofEternitySt.ttf</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
444
data/icons.qrc
@@ -1,4 +1,444 @@
|
|||||||
<RCC>
|
<RCC>
|
||||||
<qresource prefix="/">
|
<qresource prefix="/">
|
||||||
</qresource>
|
<file>icons/128x128/albums.png</file>
|
||||||
|
<file>icons/128x128/alsa.png</file>
|
||||||
|
<file>icons/128x128/application-exit.png</file>
|
||||||
|
<file>icons/128x128/applications-internet.png</file>
|
||||||
|
<file>icons/128x128/bluetooth.png</file>
|
||||||
|
<file>icons/128x128/cdcase.png</file>
|
||||||
|
<file>icons/128x128/cd.png</file>
|
||||||
|
<file>icons/128x128/configure.png</file>
|
||||||
|
<file>icons/128x128/device-ipod-nano.png</file>
|
||||||
|
<file>icons/128x128/device-ipod.png</file>
|
||||||
|
<file>icons/128x128/device-phone.png</file>
|
||||||
|
<file>icons/128x128/device.png</file>
|
||||||
|
<file>icons/128x128/device-usb-drive.png</file>
|
||||||
|
<file>icons/128x128/device-usb-flash.png</file>
|
||||||
|
<file>icons/128x128/dialog-error.png</file>
|
||||||
|
<file>icons/128x128/dialog-information.png</file>
|
||||||
|
<file>icons/128x128/dialog-ok-apply.png</file>
|
||||||
|
<file>icons/128x128/dialog-password.png</file>
|
||||||
|
<file>icons/128x128/dialog-warning.png</file>
|
||||||
|
<file>icons/128x128/document-download.png</file>
|
||||||
|
<file>icons/128x128/document-new.png</file>
|
||||||
|
<file>icons/128x128/document-open-folder.png</file>
|
||||||
|
<file>icons/128x128/document-open.png</file>
|
||||||
|
<file>icons/128x128/document-save.png</file>
|
||||||
|
<file>icons/128x128/document-search.png</file>
|
||||||
|
<file>icons/128x128/download.png</file>
|
||||||
|
<file>icons/128x128/edit-clear-list.png</file>
|
||||||
|
<file>icons/128x128/edit-clear-locationbar-ltr.png</file>
|
||||||
|
<file>icons/128x128/edit-copy.png</file>
|
||||||
|
<file>icons/128x128/edit-delete.png</file>
|
||||||
|
<file>icons/128x128/edit-find.png</file>
|
||||||
|
<file>icons/128x128/edit-redo.png</file>
|
||||||
|
<file>icons/128x128/edit-rename.png</file>
|
||||||
|
<file>icons/128x128/edit-undo.png</file>
|
||||||
|
<file>icons/128x128/electrocompaniet.png</file>
|
||||||
|
<file>icons/128x128/equalizer.png</file>
|
||||||
|
<file>icons/128x128/folder-new.png</file>
|
||||||
|
<file>icons/128x128/folder.png</file>
|
||||||
|
<file>icons/128x128/folder-sound.png</file>
|
||||||
|
<file>icons/128x128/footsteps.png</file>
|
||||||
|
<file>icons/128x128/go-down.png</file>
|
||||||
|
<file>icons/128x128/go-home.png</file>
|
||||||
|
<file>icons/128x128/go-jump.png</file>
|
||||||
|
<file>icons/128x128/go-next.png</file>
|
||||||
|
<file>icons/128x128/go-previous.png</file>
|
||||||
|
<file>icons/128x128/go-up.png</file>
|
||||||
|
<file>icons/128x128/gstreamer.png</file>
|
||||||
|
<file>icons/128x128/headset.png</file>
|
||||||
|
<file>icons/128x128/help-hint.png</file>
|
||||||
|
<file>icons/128x128/intel.png</file>
|
||||||
|
<file>icons/128x128/jack.png</file>
|
||||||
|
<file>icons/128x128/keyboard.png</file>
|
||||||
|
<file>icons/128x128/list-add.png</file>
|
||||||
|
<file>icons/128x128/list-remove.png</file>
|
||||||
|
<file>icons/128x128/mcintosh-player.png</file>
|
||||||
|
<file>icons/128x128/mcintosh-text.png</file>
|
||||||
|
<file>icons/128x128/media-eject.png</file>
|
||||||
|
<file>icons/128x128/media-forward.png</file>
|
||||||
|
<file>icons/128x128/media-pause.png</file>
|
||||||
|
<file>icons/128x128/media-play.png</file>
|
||||||
|
<file>icons/128x128/media-rewind.png</file>
|
||||||
|
<file>icons/128x128/media-stop.png</file>
|
||||||
|
<file>icons/128x128/nvidia.png</file>
|
||||||
|
<file>icons/128x128/play2.png</file>
|
||||||
|
<file>icons/128x128/realtek.png</file>
|
||||||
|
<file>icons/128x128/search.png</file>
|
||||||
|
<file>icons/128x128/soundcard.png</file>
|
||||||
|
<file>icons/128x128/speaker.png</file>
|
||||||
|
<file>icons/128x128/star-grey.png</file>
|
||||||
|
<file>icons/128x128/star.png</file>
|
||||||
|
<file>icons/128x128/strawberry.png</file>
|
||||||
|
<file>icons/128x128/strawberry.svg</file>
|
||||||
|
<file>icons/128x128/tools-wizard.png</file>
|
||||||
|
<file>icons/128x128/view-choose.png</file>
|
||||||
|
<file>icons/128x128/view-fullscreen.png</file>
|
||||||
|
<file>icons/128x128/view-media-lyrics.png</file>
|
||||||
|
<file>icons/128x128/view-media-playlist.png</file>
|
||||||
|
<file>icons/128x128/view-media-visualization.png</file>
|
||||||
|
<file>icons/128x128/view-refresh.png</file>
|
||||||
|
<file>icons/128x128/vinyl.png</file>
|
||||||
|
<file>icons/128x128/vlc.png</file>
|
||||||
|
<file>icons/128x128/xine.png</file>
|
||||||
|
<file>icons/128x128/zoom-in.png</file>
|
||||||
|
<file>icons/128x128/zoom-out.png</file>
|
||||||
|
<file>icons/128x128/tidal.png</file>
|
||||||
|
<file>icons/128x128/deezer.png</file>
|
||||||
|
<file>icons/64x64/albums.png</file>
|
||||||
|
<file>icons/64x64/alsa.png</file>
|
||||||
|
<file>icons/64x64/application-exit.png</file>
|
||||||
|
<file>icons/64x64/applications-internet.png</file>
|
||||||
|
<file>icons/64x64/bluetooth.png</file>
|
||||||
|
<file>icons/64x64/cdcase.png</file>
|
||||||
|
<file>icons/64x64/cd.png</file>
|
||||||
|
<file>icons/64x64/configure.png</file>
|
||||||
|
<file>icons/64x64/device-ipod-nano.png</file>
|
||||||
|
<file>icons/64x64/device-ipod.png</file>
|
||||||
|
<file>icons/64x64/device-phone.png</file>
|
||||||
|
<file>icons/64x64/device.png</file>
|
||||||
|
<file>icons/64x64/device-usb-drive.png</file>
|
||||||
|
<file>icons/64x64/device-usb-flash.png</file>
|
||||||
|
<file>icons/64x64/dialog-error.png</file>
|
||||||
|
<file>icons/64x64/dialog-information.png</file>
|
||||||
|
<file>icons/64x64/dialog-ok-apply.png</file>
|
||||||
|
<file>icons/64x64/dialog-password.png</file>
|
||||||
|
<file>icons/64x64/dialog-warning.png</file>
|
||||||
|
<file>icons/64x64/document-download.png</file>
|
||||||
|
<file>icons/64x64/document-new.png</file>
|
||||||
|
<file>icons/64x64/document-open-folder.png</file>
|
||||||
|
<file>icons/64x64/document-open.png</file>
|
||||||
|
<file>icons/64x64/document-save.png</file>
|
||||||
|
<file>icons/64x64/document-search.png</file>
|
||||||
|
<file>icons/64x64/download.png</file>
|
||||||
|
<file>icons/64x64/edit-clear-list.png</file>
|
||||||
|
<file>icons/64x64/edit-clear-locationbar-ltr.png</file>
|
||||||
|
<file>icons/64x64/edit-copy.png</file>
|
||||||
|
<file>icons/64x64/edit-delete.png</file>
|
||||||
|
<file>icons/64x64/edit-find.png</file>
|
||||||
|
<file>icons/64x64/edit-redo.png</file>
|
||||||
|
<file>icons/64x64/edit-rename.png</file>
|
||||||
|
<file>icons/64x64/edit-undo.png</file>
|
||||||
|
<file>icons/64x64/electrocompaniet.png</file>
|
||||||
|
<file>icons/64x64/equalizer.png</file>
|
||||||
|
<file>icons/64x64/folder-new.png</file>
|
||||||
|
<file>icons/64x64/folder.png</file>
|
||||||
|
<file>icons/64x64/folder-sound.png</file>
|
||||||
|
<file>icons/64x64/footsteps.png</file>
|
||||||
|
<file>icons/64x64/go-down.png</file>
|
||||||
|
<file>icons/64x64/go-home.png</file>
|
||||||
|
<file>icons/64x64/go-jump.png</file>
|
||||||
|
<file>icons/64x64/go-next.png</file>
|
||||||
|
<file>icons/64x64/go-previous.png</file>
|
||||||
|
<file>icons/64x64/go-up.png</file>
|
||||||
|
<file>icons/64x64/gstreamer.png</file>
|
||||||
|
<file>icons/64x64/headset.png</file>
|
||||||
|
<file>icons/64x64/help-hint.png</file>
|
||||||
|
<file>icons/64x64/intel.png</file>
|
||||||
|
<file>icons/64x64/jack.png</file>
|
||||||
|
<file>icons/64x64/keyboard.png</file>
|
||||||
|
<file>icons/64x64/list-add.png</file>
|
||||||
|
<file>icons/64x64/list-remove.png</file>
|
||||||
|
<file>icons/64x64/mcintosh-player.png</file>
|
||||||
|
<file>icons/64x64/mcintosh-text.png</file>
|
||||||
|
<file>icons/64x64/media-eject.png</file>
|
||||||
|
<file>icons/64x64/media-forward.png</file>
|
||||||
|
<file>icons/64x64/media-pause.png</file>
|
||||||
|
<file>icons/64x64/media-play.png</file>
|
||||||
|
<file>icons/64x64/media-rewind.png</file>
|
||||||
|
<file>icons/64x64/media-stop.png</file>
|
||||||
|
<file>icons/64x64/nvidia.png</file>
|
||||||
|
<file>icons/64x64/play2.png</file>
|
||||||
|
<file>icons/64x64/pulseaudio.png</file>
|
||||||
|
<file>icons/64x64/realtek.png</file>
|
||||||
|
<file>icons/64x64/search.png</file>
|
||||||
|
<file>icons/64x64/soundcard.png</file>
|
||||||
|
<file>icons/64x64/speaker.png</file>
|
||||||
|
<file>icons/64x64/star-grey.png</file>
|
||||||
|
<file>icons/64x64/star.png</file>
|
||||||
|
<file>icons/64x64/strawberry.png</file>
|
||||||
|
<file>icons/64x64/tools-wizard.png</file>
|
||||||
|
<file>icons/64x64/view-choose.png</file>
|
||||||
|
<file>icons/64x64/view-fullscreen.png</file>
|
||||||
|
<file>icons/64x64/view-media-lyrics.png</file>
|
||||||
|
<file>icons/64x64/view-media-playlist.png</file>
|
||||||
|
<file>icons/64x64/view-media-visualization.png</file>
|
||||||
|
<file>icons/64x64/view-refresh.png</file>
|
||||||
|
<file>icons/64x64/vinyl.png</file>
|
||||||
|
<file>icons/64x64/vlc.png</file>
|
||||||
|
<file>icons/64x64/xine.png</file>
|
||||||
|
<file>icons/64x64/zoom-in.png</file>
|
||||||
|
<file>icons/64x64/zoom-out.png</file>
|
||||||
|
<file>icons/64x64/tidal.png</file>
|
||||||
|
<file>icons/64x64/deezer.png</file>
|
||||||
|
<file>icons/48x48/albums.png</file>
|
||||||
|
<file>icons/48x48/alsa.png</file>
|
||||||
|
<file>icons/48x48/application-exit.png</file>
|
||||||
|
<file>icons/48x48/applications-internet.png</file>
|
||||||
|
<file>icons/48x48/bluetooth.png</file>
|
||||||
|
<file>icons/48x48/cdcase.png</file>
|
||||||
|
<file>icons/48x48/cd.png</file>
|
||||||
|
<file>icons/48x48/configure.png</file>
|
||||||
|
<file>icons/48x48/device-ipod-nano.png</file>
|
||||||
|
<file>icons/48x48/device-ipod.png</file>
|
||||||
|
<file>icons/48x48/device-phone.png</file>
|
||||||
|
<file>icons/48x48/device.png</file>
|
||||||
|
<file>icons/48x48/device-usb-drive.png</file>
|
||||||
|
<file>icons/48x48/device-usb-flash.png</file>
|
||||||
|
<file>icons/48x48/dialog-error.png</file>
|
||||||
|
<file>icons/48x48/dialog-information.png</file>
|
||||||
|
<file>icons/48x48/dialog-ok-apply.png</file>
|
||||||
|
<file>icons/48x48/dialog-password.png</file>
|
||||||
|
<file>icons/48x48/dialog-warning.png</file>
|
||||||
|
<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.png</file>
|
||||||
|
<file>icons/48x48/document-save.png</file>
|
||||||
|
<file>icons/48x48/document-search.png</file>
|
||||||
|
<file>icons/48x48/download.png</file>
|
||||||
|
<file>icons/48x48/edit-clear-list.png</file>
|
||||||
|
<file>icons/48x48/edit-clear-locationbar-ltr.png</file>
|
||||||
|
<file>icons/48x48/edit-copy.png</file>
|
||||||
|
<file>icons/48x48/edit-delete.png</file>
|
||||||
|
<file>icons/48x48/edit-find.png</file>
|
||||||
|
<file>icons/48x48/edit-redo.png</file>
|
||||||
|
<file>icons/48x48/edit-rename.png</file>
|
||||||
|
<file>icons/48x48/edit-undo.png</file>
|
||||||
|
<file>icons/48x48/electrocompaniet.png</file>
|
||||||
|
<file>icons/48x48/equalizer.png</file>
|
||||||
|
<file>icons/48x48/folder-new.png</file>
|
||||||
|
<file>icons/48x48/folder.png</file>
|
||||||
|
<file>icons/48x48/folder-sound.png</file>
|
||||||
|
<file>icons/48x48/footsteps.png</file>
|
||||||
|
<file>icons/48x48/go-down.png</file>
|
||||||
|
<file>icons/48x48/go-home.png</file>
|
||||||
|
<file>icons/48x48/go-jump.png</file>
|
||||||
|
<file>icons/48x48/go-next.png</file>
|
||||||
|
<file>icons/48x48/go-previous.png</file>
|
||||||
|
<file>icons/48x48/go-up.png</file>
|
||||||
|
<file>icons/48x48/gstreamer.png</file>
|
||||||
|
<file>icons/48x48/headset.png</file>
|
||||||
|
<file>icons/48x48/help-hint.png</file>
|
||||||
|
<file>icons/48x48/intel.png</file>
|
||||||
|
<file>icons/48x48/jack.png</file>
|
||||||
|
<file>icons/48x48/keyboard.png</file>
|
||||||
|
<file>icons/48x48/list-add.png</file>
|
||||||
|
<file>icons/48x48/list-remove.png</file>
|
||||||
|
<file>icons/48x48/mcintosh-player.png</file>
|
||||||
|
<file>icons/48x48/mcintosh.png</file>
|
||||||
|
<file>icons/48x48/mcintosh-text.png</file>
|
||||||
|
<file>icons/48x48/media-eject.png</file>
|
||||||
|
<file>icons/48x48/media-forward.png</file>
|
||||||
|
<file>icons/48x48/media-pause.png</file>
|
||||||
|
<file>icons/48x48/media-playlist-repeat.png</file>
|
||||||
|
<file>icons/48x48/media-playlist-shuffle.png</file>
|
||||||
|
<file>icons/48x48/media-play.png</file>
|
||||||
|
<file>icons/48x48/media-rewind.png</file>
|
||||||
|
<file>icons/48x48/media-stop.png</file>
|
||||||
|
<file>icons/48x48/nvidia.png</file>
|
||||||
|
<file>icons/48x48/play2.png</file>
|
||||||
|
<file>icons/48x48/pulseaudio.png</file>
|
||||||
|
<file>icons/48x48/realtek.png</file>
|
||||||
|
<file>icons/48x48/search.png</file>
|
||||||
|
<file>icons/48x48/soundcard.png</file>
|
||||||
|
<file>icons/48x48/speaker.png</file>
|
||||||
|
<file>icons/48x48/star-grey.png</file>
|
||||||
|
<file>icons/48x48/star.png</file>
|
||||||
|
<file>icons/48x48/strawberry.png</file>
|
||||||
|
<file>icons/48x48/tools-wizard.png</file>
|
||||||
|
<file>icons/48x48/view-choose.png</file>
|
||||||
|
<file>icons/48x48/view-fullscreen.png</file>
|
||||||
|
<file>icons/48x48/view-media-lyrics.png</file>
|
||||||
|
<file>icons/48x48/view-media-playlist.png</file>
|
||||||
|
<file>icons/48x48/view-media-visualization.png</file>
|
||||||
|
<file>icons/48x48/view-refresh.png</file>
|
||||||
|
<file>icons/48x48/vinyl.png</file>
|
||||||
|
<file>icons/48x48/vlc.png</file>
|
||||||
|
<file>icons/48x48/xine.png</file>
|
||||||
|
<file>icons/48x48/zoom-in.png</file>
|
||||||
|
<file>icons/48x48/zoom-out.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>
|
||||||
|
<file>icons/32x32/applications-internet.png</file>
|
||||||
|
<file>icons/32x32/bluetooth.png</file>
|
||||||
|
<file>icons/32x32/cdcase.png</file>
|
||||||
|
<file>icons/32x32/cd.png</file>
|
||||||
|
<file>icons/32x32/configure.png</file>
|
||||||
|
<file>icons/32x32/device-ipod-nano.png</file>
|
||||||
|
<file>icons/32x32/device-ipod.png</file>
|
||||||
|
<file>icons/32x32/device-phone.png</file>
|
||||||
|
<file>icons/32x32/device.png</file>
|
||||||
|
<file>icons/32x32/device-usb-drive.png</file>
|
||||||
|
<file>icons/32x32/device-usb-flash.png</file>
|
||||||
|
<file>icons/32x32/dialog-error.png</file>
|
||||||
|
<file>icons/32x32/dialog-information.png</file>
|
||||||
|
<file>icons/32x32/dialog-ok-apply.png</file>
|
||||||
|
<file>icons/32x32/dialog-password.png</file>
|
||||||
|
<file>icons/32x32/dialog-warning.png</file>
|
||||||
|
<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.png</file>
|
||||||
|
<file>icons/32x32/document-save.png</file>
|
||||||
|
<file>icons/32x32/document-search.png</file>
|
||||||
|
<file>icons/32x32/download.png</file>
|
||||||
|
<file>icons/32x32/edit-clear-list.png</file>
|
||||||
|
<file>icons/32x32/edit-clear-locationbar-ltr.png</file>
|
||||||
|
<file>icons/32x32/edit-copy.png</file>
|
||||||
|
<file>icons/32x32/edit-delete.png</file>
|
||||||
|
<file>icons/32x32/edit-find.png</file>
|
||||||
|
<file>icons/32x32/edit-redo.png</file>
|
||||||
|
<file>icons/32x32/edit-rename.png</file>
|
||||||
|
<file>icons/32x32/edit-undo.png</file>
|
||||||
|
<file>icons/32x32/electrocompaniet.png</file>
|
||||||
|
<file>icons/32x32/equalizer.png</file>
|
||||||
|
<file>icons/32x32/folder-new.png</file>
|
||||||
|
<file>icons/32x32/folder.png</file>
|
||||||
|
<file>icons/32x32/folder-sound.png</file>
|
||||||
|
<file>icons/32x32/footsteps.png</file>
|
||||||
|
<file>icons/32x32/go-down.png</file>
|
||||||
|
<file>icons/32x32/go-home.png</file>
|
||||||
|
<file>icons/32x32/go-jump.png</file>
|
||||||
|
<file>icons/32x32/go-next.png</file>
|
||||||
|
<file>icons/32x32/go-previous.png</file>
|
||||||
|
<file>icons/32x32/go-up.png</file>
|
||||||
|
<file>icons/32x32/gstreamer.png</file>
|
||||||
|
<file>icons/32x32/headset.png</file>
|
||||||
|
<file>icons/32x32/help-hint.png</file>
|
||||||
|
<file>icons/32x32/intel.png</file>
|
||||||
|
<file>icons/32x32/jack.png</file>
|
||||||
|
<file>icons/32x32/keyboard.png</file>
|
||||||
|
<file>icons/32x32/list-add.png</file>
|
||||||
|
<file>icons/32x32/list-remove.png</file>
|
||||||
|
<file>icons/32x32/mcintosh-player.png</file>
|
||||||
|
<file>icons/32x32/mcintosh.png</file>
|
||||||
|
<file>icons/32x32/mcintosh-text.png</file>
|
||||||
|
<file>icons/32x32/media-eject.png</file>
|
||||||
|
<file>icons/32x32/media-forward.png</file>
|
||||||
|
<file>icons/32x32/media-pause.png</file>
|
||||||
|
<file>icons/32x32/media-playlist-repeat.png</file>
|
||||||
|
<file>icons/32x32/media-playlist-shuffle.png</file>
|
||||||
|
<file>icons/32x32/media-play.png</file>
|
||||||
|
<file>icons/32x32/media-rewind.png</file>
|
||||||
|
<file>icons/32x32/media-stop.png</file>
|
||||||
|
<file>icons/32x32/nvidia.png</file>
|
||||||
|
<file>icons/32x32/play2.png</file>
|
||||||
|
<file>icons/32x32/pulseaudio.png</file>
|
||||||
|
<file>icons/32x32/realtek.png</file>
|
||||||
|
<file>icons/32x32/search.png</file>
|
||||||
|
<file>icons/32x32/soundcard.png</file>
|
||||||
|
<file>icons/32x32/speaker.png</file>
|
||||||
|
<file>icons/32x32/star-grey.png</file>
|
||||||
|
<file>icons/32x32/star.png</file>
|
||||||
|
<file>icons/32x32/strawberry.png</file>
|
||||||
|
<file>icons/32x32/strawberry.svg</file>
|
||||||
|
<file>icons/32x32/tools-wizard.png</file>
|
||||||
|
<file>icons/32x32/view-choose.png</file>
|
||||||
|
<file>icons/32x32/view-fullscreen.png</file>
|
||||||
|
<file>icons/32x32/view-media-lyrics.png</file>
|
||||||
|
<file>icons/32x32/view-media-playlist.png</file>
|
||||||
|
<file>icons/32x32/view-media-visualization.png</file>
|
||||||
|
<file>icons/32x32/view-refresh.png</file>
|
||||||
|
<file>icons/32x32/vinyl.png</file>
|
||||||
|
<file>icons/32x32/vlc.png</file>
|
||||||
|
<file>icons/32x32/xine.png</file>
|
||||||
|
<file>icons/32x32/zoom-in.png</file>
|
||||||
|
<file>icons/32x32/zoom-out.png</file>
|
||||||
|
<file>icons/32x32/tidal.png</file>
|
||||||
|
<file>icons/32x32/deezer.png</file>
|
||||||
|
<file>icons/22x22/albums.png</file>
|
||||||
|
<file>icons/22x22/alsa.png</file>
|
||||||
|
<file>icons/22x22/application-exit.png</file>
|
||||||
|
<file>icons/22x22/applications-internet.png</file>
|
||||||
|
<file>icons/22x22/bluetooth.png</file>
|
||||||
|
<file>icons/22x22/cdcase.png</file>
|
||||||
|
<file>icons/22x22/cd.png</file>
|
||||||
|
<file>icons/22x22/configure.png</file>
|
||||||
|
<file>icons/22x22/device-ipod-nano.png</file>
|
||||||
|
<file>icons/22x22/device-ipod.png</file>
|
||||||
|
<file>icons/22x22/device-phone.png</file>
|
||||||
|
<file>icons/22x22/device.png</file>
|
||||||
|
<file>icons/22x22/device-usb-drive.png</file>
|
||||||
|
<file>icons/22x22/device-usb-flash.png</file>
|
||||||
|
<file>icons/22x22/dialog-error.png</file>
|
||||||
|
<file>icons/22x22/dialog-information.png</file>
|
||||||
|
<file>icons/22x22/dialog-ok-apply.png</file>
|
||||||
|
<file>icons/22x22/dialog-password.png</file>
|
||||||
|
<file>icons/22x22/dialog-warning.png</file>
|
||||||
|
<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.png</file>
|
||||||
|
<file>icons/22x22/document-save.png</file>
|
||||||
|
<file>icons/22x22/document-search.png</file>
|
||||||
|
<file>icons/22x22/download.png</file>
|
||||||
|
<file>icons/22x22/edit-clear-list.png</file>
|
||||||
|
<file>icons/22x22/edit-clear-locationbar-ltr.png</file>
|
||||||
|
<file>icons/22x22/edit-copy.png</file>
|
||||||
|
<file>icons/22x22/edit-delete.png</file>
|
||||||
|
<file>icons/22x22/edit-find.png</file>
|
||||||
|
<file>icons/22x22/edit-redo.png</file>
|
||||||
|
<file>icons/22x22/edit-rename.png</file>
|
||||||
|
<file>icons/22x22/edit-undo.png</file>
|
||||||
|
<file>icons/22x22/electrocompaniet.png</file>
|
||||||
|
<file>icons/22x22/equalizer.png</file>
|
||||||
|
<file>icons/22x22/folder-new.png</file>
|
||||||
|
<file>icons/22x22/folder.png</file>
|
||||||
|
<file>icons/22x22/folder-sound.png</file>
|
||||||
|
<file>icons/22x22/footsteps.png</file>
|
||||||
|
<file>icons/22x22/go-down.png</file>
|
||||||
|
<file>icons/22x22/go-home.png</file>
|
||||||
|
<file>icons/22x22/go-jump.png</file>
|
||||||
|
<file>icons/22x22/go-next.png</file>
|
||||||
|
<file>icons/22x22/go-previous.png</file>
|
||||||
|
<file>icons/22x22/go-up.png</file>
|
||||||
|
<file>icons/22x22/gstreamer.png</file>
|
||||||
|
<file>icons/22x22/headset.png</file>
|
||||||
|
<file>icons/22x22/help-hint.png</file>
|
||||||
|
<file>icons/22x22/intel.png</file>
|
||||||
|
<file>icons/22x22/jack.png</file>
|
||||||
|
<file>icons/22x22/keyboard.png</file>
|
||||||
|
<file>icons/22x22/list-add.png</file>
|
||||||
|
<file>icons/22x22/list-remove.png</file>
|
||||||
|
<file>icons/22x22/mcintosh-player.png</file>
|
||||||
|
<file>icons/22x22/mcintosh.png</file>
|
||||||
|
<file>icons/22x22/mcintosh-text.png</file>
|
||||||
|
<file>icons/22x22/media-eject.png</file>
|
||||||
|
<file>icons/22x22/media-forward.png</file>
|
||||||
|
<file>icons/22x22/media-pause.png</file>
|
||||||
|
<file>icons/22x22/media-playlist-repeat.png</file>
|
||||||
|
<file>icons/22x22/media-playlist-shuffle.png</file>
|
||||||
|
<file>icons/22x22/media-play.png</file>
|
||||||
|
<file>icons/22x22/media-rewind.png</file>
|
||||||
|
<file>icons/22x22/media-stop.png</file>
|
||||||
|
<file>icons/22x22/nvidia.png</file>
|
||||||
|
<file>icons/22x22/play2.png</file>
|
||||||
|
<file>icons/22x22/pulseaudio.png</file>
|
||||||
|
<file>icons/22x22/realtek.png</file>
|
||||||
|
<file>icons/22x22/search.png</file>
|
||||||
|
<file>icons/22x22/soundcard.png</file>
|
||||||
|
<file>icons/22x22/speaker.png</file>
|
||||||
|
<file>icons/22x22/star-grey.png</file>
|
||||||
|
<file>icons/22x22/star.png</file>
|
||||||
|
<file>icons/22x22/strawberry.png</file>
|
||||||
|
<file>icons/22x22/strawberry.svg</file>
|
||||||
|
<file>icons/22x22/tools-wizard.png</file>
|
||||||
|
<file>icons/22x22/view-choose.png</file>
|
||||||
|
<file>icons/22x22/view-fullscreen.png</file>
|
||||||
|
<file>icons/22x22/view-media-lyrics.png</file>
|
||||||
|
<file>icons/22x22/view-media-playlist.png</file>
|
||||||
|
<file>icons/22x22/view-media-visualization.png</file>
|
||||||
|
<file>icons/22x22/view-refresh.png</file>
|
||||||
|
<file>icons/22x22/vinyl.png</file>
|
||||||
|
<file>icons/22x22/vlc.png</file>
|
||||||
|
<file>icons/22x22/xine.png</file>
|
||||||
|
<file>icons/22x22/zoom-in.png</file>
|
||||||
|
<file>icons/22x22/zoom-out.png</file>
|
||||||
|
<file>icons/22x22/tidal.png</file>
|
||||||
|
<file>icons/22x22/deezer.png</file>
|
||||||
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
BIN
data/icons/128x128/deezer.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
data/icons/22x22/deezer.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
data/icons/32x32/deezer.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
data/icons/48x48/deezer.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
data/icons/64x64/deezer.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
data/icons/full/deezer.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
41
data/misc/oauthsuccess.html
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link href="http://www.strawbs.org/favicon.ico" rel="shortcut icon">
|
||||||
|
<title>tr("Return to Strawberry")</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#container {
|
||||||
|
margin: 6em auto 0px auto;
|
||||||
|
max-width: 400px;
|
||||||
|
font-family: 'arial regular', arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container img {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
float: left;
|
||||||
|
margin-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container h1 {
|
||||||
|
margin: 0px 0px 0.75em 0px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#container p {
|
||||||
|
margin-top: 0px;
|
||||||
|
margin-left: 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="container">
|
||||||
|
<h1>tr("Success!")</h1>
|
||||||
|
<img src="data:image/png;base64,@IMAGE_DATA@"/>
|
||||||
|
<p>tr("Please close your browser and return to Strawberry.")</p>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
data/pictures/deezer.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
data/pictures/deezer_black_big.jpg
Normal file
|
After Width: | Height: | Size: 29 KiB |
BIN
data/pictures/deezer_white_big.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
@@ -1,7 +1,6 @@
|
|||||||
#playlist {
|
#playlist {
|
||||||
background-color: %palette-base;
|
background-color: %palette-base;
|
||||||
alternate-background-color: %palette-alternate-base;
|
alternate-background-color: %palette-alternate-base;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#playlist[default_background_enabled = "true"] {
|
#playlist[default_background_enabled = "true"] {
|
||||||
@@ -45,11 +44,11 @@ QToolButton:pressed[popupMode="1"] {
|
|||||||
padding-right: 16px;
|
padding-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
darwin {
|
macos {
|
||||||
font-size: 11pt;
|
font-size: 11pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
darwin QMenu {
|
macos QMenu {
|
||||||
font-size: 13pt;
|
font-size: 13pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
9
dist/CMakeLists.txt
vendored
@@ -2,12 +2,16 @@ execute_process(COMMAND env LC_ALL="en_US.utf8" date "+%a %b %d %Y" OUTPUT_VARIA
|
|||||||
execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
execute_process(COMMAND env LC_ALL=C date "+%a, %-d %b %Y %H:%M:%S %z" OUTPUT_VARIABLE DEB_DATE OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh.in ${CMAKE_CURRENT_SOURCE_DIR}/scripts/maketarball.sh @ONLY)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec @ONLY)
|
if (RPM_DISTRO)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/opensuse/strawberry.spec @ONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec.in ${CMAKE_CURRENT_SOURCE_DIR}/fedora/strawberry.spec @ONLY)
|
||||||
|
endif()
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog.in ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog.in ${CMAKE_CURRENT_SOURCE_DIR}/debian/changelog)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist.in ${CMAKE_CURRENT_SOURCE_DIR}/macos/Info.plist)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry.nsi @ONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-64.nsi @ONLY)
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi @ONLY)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug.nsi @ONLY)
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-64.nsi.in ${CMAKE_CURRENT_SOURCE_DIR}/windows/strawberry-debug-64.nsi @ONLY)
|
||||||
|
|
||||||
if (UNIX AND NOT APPLE)
|
if (UNIX AND NOT APPLE)
|
||||||
install(FILES ../data/icons/48x48/strawberry.png DESTINATION share/icons/hicolor/48x48/apps/)
|
install(FILES ../data/icons/48x48/strawberry.png DESTINATION share/icons/hicolor/48x48/apps/)
|
||||||
@@ -15,6 +19,7 @@ if (UNIX AND NOT APPLE)
|
|||||||
install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/)
|
install(FILES ../data/icons/128x128/strawberry.png DESTINATION share/icons/hicolor/128x128/apps/)
|
||||||
install(FILES ../data/icons/128x128/strawberry.svg DESTINATION share/icons/hicolor/scalable/apps/)
|
install(FILES ../data/icons/128x128/strawberry.svg DESTINATION share/icons/hicolor/scalable/apps/)
|
||||||
install(FILES unix/strawberry.desktop DESTINATION share/applications)
|
install(FILES unix/strawberry.desktop DESTINATION share/applications)
|
||||||
|
install(FILES unix/strawberry.appdata.xml DESTINATION share/metainfo)
|
||||||
install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1)
|
install(FILES man/strawberry.1 man/strawberry-tagreader.1 DESTINATION share/man/man1)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
2
dist/debian/control
vendored
@@ -1,7 +1,7 @@
|
|||||||
Source: strawberry
|
Source: strawberry
|
||||||
Section: sound
|
Section: sound
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: "Jonas Kvinge" <jonas@jkvinge.net>
|
Maintainer: Jonas Kvinge <jonas@jkvinge.net>
|
||||||
Build-Depends: debhelper (>= 7),
|
Build-Depends: debhelper (>= 7),
|
||||||
make,
|
make,
|
||||||
cmake,
|
cmake,
|
||||||
|
|||||||
15
dist/fedora/strawberry.spec.in
vendored
@@ -2,9 +2,8 @@ Name: strawberry
|
|||||||
Version: @STRAWBERRY_VERSION_RPM_V@
|
Version: @STRAWBERRY_VERSION_RPM_V@
|
||||||
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
||||||
Summary: A audio player and music collection organiser
|
Summary: A audio player and music collection organiser
|
||||||
|
|
||||||
Group: Applications/Multimedia
|
Group: Applications/Multimedia
|
||||||
License: GPL-3.0+
|
License: GPLv3+
|
||||||
URL: http://www.strawbs.org/
|
URL: http://www.strawbs.org/
|
||||||
Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz
|
Source0: %{name}-@STRAWBERRY_VERSION_PACKAGE@.tar.xz
|
||||||
|
|
||||||
@@ -82,7 +81,6 @@ export CXXFLAGS="%{optflags} -fpermissive"
|
|||||||
|
|
||||||
mkdir %{_target_platform}
|
mkdir %{_target_platform}
|
||||||
pushd %{_target_platform}
|
pushd %{_target_platform}
|
||||||
|
|
||||||
%{cmake} \
|
%{cmake} \
|
||||||
-DBUILD_WERROR:BOOL=OFF \
|
-DBUILD_WERROR:BOOL=OFF \
|
||||||
-DCMAKE_BUILD_TYPE:STRING=Release \
|
-DCMAKE_BUILD_TYPE:STRING=Release \
|
||||||
@@ -93,18 +91,15 @@ popd
|
|||||||
|
|
||||||
%install
|
%install
|
||||||
make install DESTDIR=%{buildroot} -C %{_target_platform}
|
make install DESTDIR=%{buildroot} -C %{_target_platform}
|
||||||
rm -rf %{buildroot}%{_datadir}/man
|
rm -rf %{buildroot}%{_datadir}/metainfo
|
||||||
|
|
||||||
%check
|
%check
|
||||||
desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop
|
desktop-file-validate %{buildroot}%{_datadir}/applications/strawberry.desktop
|
||||||
pushd %{_target_platform}
|
|
||||||
popd
|
|
||||||
|
|
||||||
%clean
|
|
||||||
|
|
||||||
%files
|
%files
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%doc
|
%doc README.md Changelog
|
||||||
|
%license COPYING
|
||||||
%{_bindir}/strawberry
|
%{_bindir}/strawberry
|
||||||
%{_bindir}/strawberry-tagreader
|
%{_bindir}/strawberry-tagreader
|
||||||
%{_datadir}/applications/strawberry.desktop
|
%{_datadir}/applications/strawberry.desktop
|
||||||
@@ -112,6 +107,8 @@ popd
|
|||||||
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png
|
%{_datadir}/icons/hicolor/64x64/apps/strawberry.png
|
||||||
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png
|
%{_datadir}/icons/hicolor/128x128/apps/strawberry.png
|
||||||
%{_datadir}/icons/hicolor/scalable/apps/strawberry.svg
|
%{_datadir}/icons/hicolor/scalable/apps/strawberry.svg
|
||||||
|
%{_mandir}/man1/strawberry.1.*
|
||||||
|
%{_mandir}/man1/strawberry-tagreader.1.*
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@
|
* @RPM_DATE@ Jonas Kvinge <jonas@strawbs.net> - @STRAWBERRY_VERSION_RPM_V@
|
||||||
|
|||||||
5
dist/opensuse/strawberry.spec.in
vendored
@@ -2,7 +2,6 @@ Name: strawberry
|
|||||||
Version: @STRAWBERRY_VERSION_RPM_V@
|
Version: @STRAWBERRY_VERSION_RPM_V@
|
||||||
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
Release: @STRAWBERRY_VERSION_RPM_R@.@RPM_DISTRO@
|
||||||
Summary: A audio player and music collection organiser
|
Summary: A audio player and music collection organiser
|
||||||
|
|
||||||
Group: Applications/Multimedia
|
Group: Applications/Multimedia
|
||||||
License: GPL-3.0+
|
License: GPL-3.0+
|
||||||
URL: http://www.strawbs.org/
|
URL: http://www.strawbs.org/
|
||||||
@@ -89,6 +88,7 @@ make %{?_smp_mflags}
|
|||||||
%install
|
%install
|
||||||
cd build
|
cd build
|
||||||
make install DESTDIR=$RPM_BUILD_ROOT
|
make install DESTDIR=$RPM_BUILD_ROOT
|
||||||
|
rm -rf %{buildroot}%{_datadir}/metainfo
|
||||||
|
|
||||||
%clean
|
%clean
|
||||||
cd build
|
cd build
|
||||||
@@ -96,7 +96,8 @@ make clean
|
|||||||
|
|
||||||
%files
|
%files
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
%doc
|
%doc README.md Changelog
|
||||||
|
%license COPYING
|
||||||
%{_bindir}/strawberry
|
%{_bindir}/strawberry
|
||||||
%{_bindir}/strawberry-tagreader
|
%{_bindir}/strawberry-tagreader
|
||||||
%{_datadir}/applications/strawberry.desktop
|
%{_datadir}/applications/strawberry.desktop
|
||||||
|
|||||||
19
dist/scripts/maketarball.sh.in
vendored
@@ -16,12 +16,15 @@ echo "Creating $name-$version.tar.xz..."
|
|||||||
rm -f "$name-$version.tar.xz"
|
rm -f "$name-$version.tar.xz"
|
||||||
tar -cJf $name-$version.tar.xz \
|
tar -cJf $name-$version.tar.xz \
|
||||||
--transform "s,^$rootnoslash,$name-$version," $exclude_vcs \
|
--transform "s,^$rootnoslash,$name-$version," $exclude_vcs \
|
||||||
--exclude "*.tar" \
|
--exclude="*.tar" \
|
||||||
--exclude "*.tar.*" \
|
--exclude="*.tar.*" \
|
||||||
--exclude "*.bz" \
|
--exclude="*.bz" \
|
||||||
--exclude "*.bz2" \
|
--exclude="*.bz2" \
|
||||||
--exclude "*.xz" \
|
--exclude="*.xz" \
|
||||||
--exclude ".directory" \
|
--exclude=".directory" \
|
||||||
--exclude "$root/CMakeLists.txt.user" \
|
--exclude="*.spec" \
|
||||||
--exclude "$root/build" \
|
--exclude="*.nsi" \
|
||||||
|
--exclude="$root/CMakeLists.txt.user" \
|
||||||
|
--exclude="$root/build" \
|
||||||
|
--exclude="$root/dist/debian/changelog" \
|
||||||
"$root"
|
"$root"
|
||||||
|
|||||||
38
dist/unix/strawberry.appdata.xml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<application>
|
||||||
|
<id type="desktop">strawberry.desktop</id>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-3.0+</project_license>
|
||||||
|
<name>Strawberry Music Player</name>
|
||||||
|
<summary>An audio player and music collection organizer</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Strawberry is a audio player and music collection organizer.
|
||||||
|
It is a fork of Clementine. The name is inspired by the band Strawbs.
|
||||||
|
</p>
|
||||||
|
<p>Features::</p>
|
||||||
|
<ul>
|
||||||
|
<li>Play and organize music</li>
|
||||||
|
<li>Supports WAV, FLAC, WavPack, DSF, DSDIFF, Ogg Vorbis, Speex, MPC, TrueAudio, AIFF, MP4, MP3 and ASF</li>
|
||||||
|
<li>Audio CD playback</li>
|
||||||
|
<li>Native desktop notifications</li>
|
||||||
|
<li>Playlists in multiple formats</li>
|
||||||
|
<li>Advanced output and device options with support for bit perfect playback on Linux</li>
|
||||||
|
<li>Edit tags on music files</li>
|
||||||
|
<li>Fetch tags from MusicBrainz</li>
|
||||||
|
<li>Album cover art from Last.fm, Musicbrainz and Discogs</li>
|
||||||
|
<li>Song lyrics from AudD and API Seeds</li>
|
||||||
|
<li>Support for multiple backends</li>
|
||||||
|
<li>Audio analyzer</li>
|
||||||
|
<li>Equalizer</li>
|
||||||
|
<li>Transfer music to iPod, iPhone, MTP or mass-storage USB player</li>
|
||||||
|
<li>Integrated Tidal support</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default" width="1920" height="1049">https://www.strawbs.org/pictures/screenshot-002-large.png</screenshot>
|
||||||
|
<screenshot width="1920" height="1080">https://www.strawbs.org/pictures/screenshot-006-large.png</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<url type="homepage">http://www.strawbs.org/</url>
|
||||||
|
<updatecontact>eclipseo@fedoraproject.org</updatecontact>
|
||||||
|
</application>
|
||||||
447
dist/windows/strawberry-64.nsi.in
vendored
Normal file
@@ -0,0 +1,447 @@
|
|||||||
|
!define PRODUCT_NAME "Strawberry"
|
||||||
|
!define PRODUCT_PUBLISHER "Strawberry"
|
||||||
|
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
|
||||||
|
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
|
||||||
|
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
|
||||||
|
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
|
||||||
|
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
|
||||||
|
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
|
||||||
|
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||||
|
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||||
|
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
|
||||||
|
|
||||||
|
; Set Application Capabilities info
|
||||||
|
!define CAPABILITIES_NAME "Strawberry Music Player"
|
||||||
|
!define CAPABILITIES_LOCAL_NAME "Strawberry"
|
||||||
|
!define CAPABILITIES_PROGID "Strawberry Music Player"
|
||||||
|
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
|
||||||
|
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
|
||||||
|
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
|
||||||
|
!define CAPABILITIES_REINSTALL "Command to reinstall"
|
||||||
|
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
|
||||||
|
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
|
||||||
|
|
||||||
|
SetCompressor /SOLID lzma
|
||||||
|
!addplugindir nsisplugins
|
||||||
|
!include "MUI2.nsh"
|
||||||
|
!include "FileAssociation.nsh"
|
||||||
|
!include "Capabilities.nsh"
|
||||||
|
|
||||||
|
!define MUI_ICON "strawberry.ico"
|
||||||
|
|
||||||
|
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||||
|
;!define MUI_FINISHPAGE_RUN
|
||||||
|
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
|
||||||
|
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
|
||||||
|
|
||||||
|
; Installer pages
|
||||||
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
|
||||||
|
; Uninstaller pages
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro MUI_UNPAGE_FINISH
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||||
|
|
||||||
|
Name "${PRODUCT_NAME}"
|
||||||
|
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Release-x64.exe"
|
||||||
|
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||||
|
|
||||||
|
; Get the path where Strawberry was installed previously and set it as default path
|
||||||
|
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||||
|
|
||||||
|
ShowInstDetails show
|
||||||
|
ShowUnInstDetails show
|
||||||
|
RequestExecutionLevel admin
|
||||||
|
;RequestExecutionLevel user
|
||||||
|
|
||||||
|
; Check for previous installation, and call the uninstaller if any
|
||||||
|
Function CheckPreviousInstall
|
||||||
|
|
||||||
|
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||||
|
StrCmp $R0 "" done
|
||||||
|
|
||||||
|
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||||
|
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
|
||||||
|
previous version or `Cancel` to cancel this upgrade." \
|
||||||
|
IDOK uninst
|
||||||
|
Abort
|
||||||
|
; Run the uninstaller
|
||||||
|
uninst:
|
||||||
|
ClearErrors
|
||||||
|
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function .onInit
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGDLL_DISPLAY
|
||||||
|
|
||||||
|
Call CheckPreviousInstall
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
;Function RunStrawberry
|
||||||
|
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
|
||||||
|
;FunctionEnd
|
||||||
|
|
||||||
|
Section "Delete old files" oldfiles
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Strawberry" Strawberry
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
|
File "strawberry.exe"
|
||||||
|
File "strawberry-tagreader.exe"
|
||||||
|
File "strawberry.ico"
|
||||||
|
|
||||||
|
File "libbz2.dll"
|
||||||
|
File "libcdio-18.dll"
|
||||||
|
File "libchromaprint.dll"
|
||||||
|
File "libcrypto-1_1-x64.dll"
|
||||||
|
File "libfaad-2.dll"
|
||||||
|
File "libffi-6.dll"
|
||||||
|
File "libFLAC-8.dll"
|
||||||
|
File "libfreetype-6.dll"
|
||||||
|
File "libgcc_s_seh-1.dll"
|
||||||
|
File "libgio-2.0-0.dll"
|
||||||
|
File "libglib-2.0-0.dll"
|
||||||
|
File "libgmodule-2.0-0.dll"
|
||||||
|
File "libgobject-2.0-0.dll"
|
||||||
|
File "libgstapp-1.0-0.dll"
|
||||||
|
File "libgstaudio-1.0-0.dll"
|
||||||
|
File "libgstbase-1.0-0.dll"
|
||||||
|
File "libgstfft-1.0-0.dll"
|
||||||
|
File "libgstpbutils-1.0-0.dll"
|
||||||
|
File "libgstreamer-1.0-0.dll"
|
||||||
|
File "libgstriff-1.0-0.dll"
|
||||||
|
File "libgstrtp-1.0-0.dll"
|
||||||
|
File "libgstrtsp-1.0-0.dll"
|
||||||
|
File "libgstsdp-1.0-0.dll"
|
||||||
|
File "libgsttag-1.0-0.dll"
|
||||||
|
File "libgstvideo-1.0-0.dll"
|
||||||
|
File "libgstnet-1.0-0.dll"
|
||||||
|
File "libharfbuzz-0.dll"
|
||||||
|
File "libiconv-2.dll"
|
||||||
|
File "libintl-8.dll"
|
||||||
|
File "libjpeg-9.dll"
|
||||||
|
File "liblastfm5.dll"
|
||||||
|
File "libmp3lame-0.dll"
|
||||||
|
File "libogg-0.dll"
|
||||||
|
File "libopus-0.dll"
|
||||||
|
File "libpcre-1.dll"
|
||||||
|
File "libpcre2-16-0.dll"
|
||||||
|
File "libpng16-16.dll"
|
||||||
|
File "libprotobuf-15.dll"
|
||||||
|
File "libspeex-1.dll"
|
||||||
|
File "libsqlite3-0.dll"
|
||||||
|
File "libssl-1_1-x64.dll"
|
||||||
|
File "libstdc++-6.dll"
|
||||||
|
File "libtag.dll"
|
||||||
|
File "libvorbis-0.dll"
|
||||||
|
File "libvorbisenc-2.dll"
|
||||||
|
File "libwavpack-1.dll"
|
||||||
|
File "libwinpthread-1.dll"
|
||||||
|
File "Qt5Concurrent.dll"
|
||||||
|
File "Qt5Core.dll"
|
||||||
|
File "Qt5Gui.dll"
|
||||||
|
File "Qt5Network.dll"
|
||||||
|
File "Qt5Sql.dll"
|
||||||
|
File "Qt5Widgets.dll"
|
||||||
|
File "Qt5Xml.dll"
|
||||||
|
File "Qt5WinExtras.dll"
|
||||||
|
File "zlib1.dll"
|
||||||
|
;File "libmpcdec-5.dll"
|
||||||
|
;File "libtheora-0.dll"
|
||||||
|
File "libfftw3-3.dll"
|
||||||
|
File "libxml2-2.dll"
|
||||||
|
File "libsoup-2.4-1.dll"
|
||||||
|
File "liblzma-5.dll"
|
||||||
|
File "libdeezer.x64.dll"
|
||||||
|
|
||||||
|
; Register Strawberry with Default Programs
|
||||||
|
Var /GLOBAL AppIcon
|
||||||
|
Var /GLOBAL AppExe
|
||||||
|
StrCpy $AppExe "$INSTDIR\strawberry.exe"
|
||||||
|
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
|
||||||
|
|
||||||
|
${RegisterCapabilities}
|
||||||
|
|
||||||
|
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
|
||||||
|
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
|
||||||
|
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
|
||||||
|
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
|
||||||
|
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
|
||||||
|
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
|
||||||
|
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
|
||||||
|
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
|
||||||
|
|
||||||
|
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
|
||||||
|
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
|
||||||
|
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
|
||||||
|
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
|
||||||
|
|
||||||
|
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
|
||||||
|
|
||||||
|
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Qt Platforms" platforms
|
||||||
|
SetOutPath "$INSTDIR\platforms"
|
||||||
|
File "/oname=qwindows.dll" "platforms\qwindows.dll"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Qt SQL Drivers" sqldrivers
|
||||||
|
SetOutPath "$INSTDIR\sqldrivers"
|
||||||
|
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Qt image format plugins" imageformats
|
||||||
|
SetOutPath "$INSTDIR\imageformats"
|
||||||
|
File "/oname=qgif.dll" "imageformats\qgif.dll"
|
||||||
|
File "/oname=qico.dll" "imageformats\qico.dll"
|
||||||
|
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Gstreamer plugins" gstreamer-plugins
|
||||||
|
SetOutPath "$INSTDIR\gstreamer-plugins"
|
||||||
|
|
||||||
|
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
|
||||||
|
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
|
||||||
|
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
||||||
|
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
|
||||||
|
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
||||||
|
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
|
||||||
|
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
|
||||||
|
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
|
||||||
|
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||||
|
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
||||||
|
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
||||||
|
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
|
||||||
|
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
||||||
|
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
||||||
|
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
||||||
|
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
||||||
|
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
||||||
|
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
|
||||||
|
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
|
||||||
|
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
|
||||||
|
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
||||||
|
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
|
||||||
|
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
|
||||||
|
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
||||||
|
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
||||||
|
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
|
||||||
|
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
|
||||||
|
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||||
|
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
|
||||||
|
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
|
||||||
|
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
|
||||||
|
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
|
||||||
|
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||||
|
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
|
||||||
|
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
|
||||||
|
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
|
||||||
|
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Start menu items" startmenu
|
||||||
|
; Create Start Menu folders and shortcuts.
|
||||||
|
SetShellVarContext all
|
||||||
|
|
||||||
|
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||||
|
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
|
||||||
|
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstaller"
|
||||||
|
; Create uninstaller
|
||||||
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
|
||||||
|
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
|
||||||
|
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
; Kill strawberry.exe if it's running
|
||||||
|
; This calling convention is retarded...
|
||||||
|
;StrCpy $0 "strawberry.exe"
|
||||||
|
;KillProc::FindProcesses
|
||||||
|
;StrCmp $1 "-1" wooops
|
||||||
|
|
||||||
|
;StrCmp $0 "0" completed
|
||||||
|
|
||||||
|
;DetailPrint "Killing running strawberry.exe..."
|
||||||
|
|
||||||
|
;StrCpy $0 "strawberry.exe"
|
||||||
|
;KillProc::KillProcesses
|
||||||
|
;StrCmp $1 "-1" wooops
|
||||||
|
|
||||||
|
;Sleep 2000
|
||||||
|
;Goto completed
|
||||||
|
|
||||||
|
;wooops:
|
||||||
|
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
|
||||||
|
;Abort
|
||||||
|
|
||||||
|
;completed:
|
||||||
|
|
||||||
|
; Delete all the files
|
||||||
|
|
||||||
|
Delete "$INSTDIR\strawberry.ico"
|
||||||
|
Delete "$INSTDIR\strawberry.exe"
|
||||||
|
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\libbz2.dll"
|
||||||
|
Delete "$INSTDIR\libcdio-18.dll"
|
||||||
|
Delete "$INSTDIR\libchromaprint.dll"
|
||||||
|
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||||
|
Delete "$INSTDIR\libfaad-2.dll"
|
||||||
|
Delete "$INSTDIR\libffi-6.dll"
|
||||||
|
Delete "$INSTDIR\libFLAC-8.dll"
|
||||||
|
Delete "$INSTDIR\libfreetype-6.dll"
|
||||||
|
Delete "$INSTDIR\libgcc_s_sjlj-1.dll"
|
||||||
|
Delete "$INSTDIR\libgio-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libglib-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgmodule-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgobject-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstapp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstbase-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstfft-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstriff-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgsttag-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstnet-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libharfbuzz-0.dll"
|
||||||
|
Delete "$INSTDIR\libiconv-2.dll"
|
||||||
|
Delete "$INSTDIR\libintl-8.dll"
|
||||||
|
Delete "$INSTDIR\libjpeg-9.dll"
|
||||||
|
Delete "$INSTDIR\liblastfm5.dll"
|
||||||
|
Delete "$INSTDIR\libmp3lame-0.dll"
|
||||||
|
Delete "$INSTDIR\libogg-0.dll"
|
||||||
|
Delete "$INSTDIR\libopus-0.dll"
|
||||||
|
Delete "$INSTDIR\libpcre-1.dll"
|
||||||
|
Delete "$INSTDIR\libpcre2-16-0.dll"
|
||||||
|
Delete "$INSTDIR\libpng16-16.dll"
|
||||||
|
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||||
|
Delete "$INSTDIR\libspeex-1.dll"
|
||||||
|
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||||
|
Delete "$INSTDIR\libssl-1_1.dll"
|
||||||
|
Delete "$INSTDIR\libstdc++-6.dll"
|
||||||
|
Delete "$INSTDIR\libtag.dll"
|
||||||
|
Delete "$INSTDIR\libvorbis-0.dll"
|
||||||
|
Delete "$INSTDIR\libvorbisenc-2.dll"
|
||||||
|
Delete "$INSTDIR\libwavpack-1.dll"
|
||||||
|
Delete "$INSTDIR\libwinpthread-1.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Concurrent.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Core.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Gui.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Network.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Sql.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Xml.dll"
|
||||||
|
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||||
|
Delete "$INSTDIR\zlib1.dll"
|
||||||
|
;Delete "$INSTDIR\libmpcdec-5.dll"
|
||||||
|
;Delete "$INSTDIR\libtheora-0.dll"
|
||||||
|
Delete "$INSTDIR\libfftw3-3.dll"
|
||||||
|
Delete "$INSTDIR\libxml2-2.dll"
|
||||||
|
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||||
|
Delete "$INSTDIR\liblzma-5.dll"
|
||||||
|
Delete "$INSTDIR\libdeezer.x64.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||||
|
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\imageformats\qgif.dll"
|
||||||
|
Delete "$INSTDIR\imageformats\qico.dll"
|
||||||
|
Delete "$INSTDIR\imageformats\qjpeg.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
; Remove the installation folders.
|
||||||
|
RMDir "$INSTDIR\platforms"
|
||||||
|
RMDir "$INSTDIR\sqldrivers"
|
||||||
|
RMDir "$INSTDIR\imageformats"
|
||||||
|
RMDir "$INSTDIR\gstreamer-plugins"
|
||||||
|
RMDir "$INSTDIR\xine-plugins"
|
||||||
|
RMDir "$INSTDIR"
|
||||||
|
|
||||||
|
; Remove the Shortcuts
|
||||||
|
SetShellVarContext all
|
||||||
|
|
||||||
|
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
|
||||||
|
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
|
||||||
|
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||||
|
|
||||||
|
; Remove the entry from 'installed programs list'
|
||||||
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||||
|
|
||||||
|
; Unregister from Default Programs
|
||||||
|
${UnRegisterCapabilities}
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
507
dist/windows/strawberry-debug-64.nsi.in
vendored
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
!define PRODUCT_NAME "Strawberry"
|
||||||
|
!define PRODUCT_PUBLISHER "Strawberry"
|
||||||
|
!define PRODUCT_VERSION_MAJOR @STRAWBERRY_VERSION_MAJOR@
|
||||||
|
!define PRODUCT_VERSION_MINOR @STRAWBERRY_VERSION_MINOR@
|
||||||
|
!define PRODUCT_VERSION_PATCH @STRAWBERRY_VERSION_PATCH@
|
||||||
|
!define PRODUCT_DISPLAY_VERSION "@STRAWBERRY_VERSION_PACKAGE@"
|
||||||
|
!define PRODUCT_DISPLAY_VERSION_SHORT "@STRAWBERRY_VERSION_PACKAGE@"
|
||||||
|
!define PRODUCT_WEB_SITE "http://www.strawbs.org/"
|
||||||
|
!define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}"
|
||||||
|
!define PRODUCT_UNINST_ROOT_KEY "HKLM"
|
||||||
|
!define PRODUCT_INSTALL_DIR "$PROGRAMFILES\Strawberry Music Player"
|
||||||
|
|
||||||
|
; Set Application Capabilities info
|
||||||
|
!define CAPABILITIES_NAME "Strawberry Music Player"
|
||||||
|
!define CAPABILITIES_LOCAL_NAME "Strawberry"
|
||||||
|
!define CAPABILITIES_PROGID "Strawberry Music Player"
|
||||||
|
!define CAPABILITIES_PATH "Software\Clients\Media\Strawberry"
|
||||||
|
!define CAPABILITIES_DESCRIPTION "Strawberry Music Player"
|
||||||
|
!define CAPABILITIES_ICON "$INSTDIR\strawberry.ico"
|
||||||
|
!define CAPABILITIES_REINSTALL "Command to reinstall"
|
||||||
|
!define CAPABILITIES_HIDE_ICONS "Command to hide icons"
|
||||||
|
!define CAPABILITIES_SHOW_ICONS "Command to show icons"
|
||||||
|
|
||||||
|
SetCompressor /SOLID lzma
|
||||||
|
!addplugindir nsisplugins
|
||||||
|
!include "MUI2.nsh"
|
||||||
|
!include "FileAssociation.nsh"
|
||||||
|
!include "Capabilities.nsh"
|
||||||
|
|
||||||
|
!define MUI_ICON "strawberry.ico"
|
||||||
|
|
||||||
|
!define MUI_COMPONENTSPAGE_SMALLDESC
|
||||||
|
;!define MUI_FINISHPAGE_RUN
|
||||||
|
;!define MUI_FINISHPAGE_RUN_TEXT "Run Strawberry"
|
||||||
|
;!define MUI_FINISHPAGE_RUN_FUNCTION "RunStrawberry"
|
||||||
|
|
||||||
|
; Installer pages
|
||||||
|
!insertmacro MUI_PAGE_WELCOME
|
||||||
|
!insertmacro MUI_PAGE_DIRECTORY
|
||||||
|
!insertmacro MUI_PAGE_INSTFILES
|
||||||
|
!insertmacro MUI_PAGE_FINISH
|
||||||
|
|
||||||
|
; Uninstaller pages
|
||||||
|
!insertmacro MUI_UNPAGE_CONFIRM
|
||||||
|
!insertmacro MUI_UNPAGE_INSTFILES
|
||||||
|
!insertmacro MUI_UNPAGE_FINISH
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||||
|
|
||||||
|
Name "${PRODUCT_NAME}"
|
||||||
|
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Debug-x64.exe"
|
||||||
|
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||||
|
|
||||||
|
; Get the path where Strawberry was installed previously and set it as default path
|
||||||
|
InstallDirRegKey ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||||
|
|
||||||
|
ShowInstDetails show
|
||||||
|
ShowUnInstDetails show
|
||||||
|
RequestExecutionLevel admin
|
||||||
|
;RequestExecutionLevel user
|
||||||
|
|
||||||
|
; Check for previous installation, and call the uninstaller if any
|
||||||
|
Function CheckPreviousInstall
|
||||||
|
|
||||||
|
ReadRegStr $R0 ${PRODUCT_UNINST_ROOT_KEY} ${PRODUCT_UNINST_KEY} "UninstallString"
|
||||||
|
StrCmp $R0 "" done
|
||||||
|
|
||||||
|
MessageBox MB_OKCANCEL|MB_ICONEXCLAMATION \
|
||||||
|
"${PRODUCT_NAME} is already installed. $\n$\nClick `OK` to remove the \
|
||||||
|
previous version or `Cancel` to cancel this upgrade." \
|
||||||
|
IDOK uninst
|
||||||
|
Abort
|
||||||
|
; Run the uninstaller
|
||||||
|
uninst:
|
||||||
|
ClearErrors
|
||||||
|
ExecWait '$R0' ; Do not copy the uninstaller to a temp file
|
||||||
|
|
||||||
|
done:
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
Function .onInit
|
||||||
|
|
||||||
|
!insertmacro MUI_LANGDLL_DISPLAY
|
||||||
|
|
||||||
|
Call CheckPreviousInstall
|
||||||
|
|
||||||
|
FunctionEnd
|
||||||
|
|
||||||
|
;Function RunStrawberry
|
||||||
|
;ShellExecAsUser::ShellExecAsUser "" "$INSTDIR/strawberry.exe" ""
|
||||||
|
;FunctionEnd
|
||||||
|
|
||||||
|
Section "Delete old files" oldfiles
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Strawberry" Strawberry
|
||||||
|
SetOutPath "$INSTDIR"
|
||||||
|
|
||||||
|
File "strawberry.exe"
|
||||||
|
File "strawberry-tagreader.exe"
|
||||||
|
File "strawberry.ico"
|
||||||
|
|
||||||
|
File "libbz2.dll"
|
||||||
|
File "libcdio-18.dll"
|
||||||
|
File "libchromaprint.dll"
|
||||||
|
File "libcrypto-1_1-x64.dll"
|
||||||
|
File "libfaad-2.dll"
|
||||||
|
File "libffi-6.dll"
|
||||||
|
File "libFLAC-8.dll"
|
||||||
|
File "libfreetype-6.dll"
|
||||||
|
File "libgcc_s_seh-1.dll"
|
||||||
|
File "libgio-2.0-0.dll"
|
||||||
|
File "libglib-2.0-0.dll"
|
||||||
|
File "libgmodule-2.0-0.dll"
|
||||||
|
File "libgobject-2.0-0.dll"
|
||||||
|
File "libgstapp-1.0-0.dll"
|
||||||
|
File "libgstaudio-1.0-0.dll"
|
||||||
|
File "libgstbase-1.0-0.dll"
|
||||||
|
File "libgstfft-1.0-0.dll"
|
||||||
|
File "libgstpbutils-1.0-0.dll"
|
||||||
|
File "libgstreamer-1.0-0.dll"
|
||||||
|
File "libgstriff-1.0-0.dll"
|
||||||
|
File "libgstrtp-1.0-0.dll"
|
||||||
|
File "libgstrtsp-1.0-0.dll"
|
||||||
|
File "libgstsdp-1.0-0.dll"
|
||||||
|
File "libgsttag-1.0-0.dll"
|
||||||
|
File "libgstvideo-1.0-0.dll"
|
||||||
|
File "libgstnet-1.0-0.dll"
|
||||||
|
File "libharfbuzz-0.dll"
|
||||||
|
File "libiconv-2.dll"
|
||||||
|
File "libintl-8.dll"
|
||||||
|
File "libjpeg-9.dll"
|
||||||
|
File "liblastfm5.dll"
|
||||||
|
File "libmp3lame-0.dll"
|
||||||
|
File "libogg-0.dll"
|
||||||
|
File "libopus-0.dll"
|
||||||
|
File "libpcre-1.dll"
|
||||||
|
File "libpcre2-16-0.dll"
|
||||||
|
File "libpng16-16.dll"
|
||||||
|
File "libprotobuf-15.dll"
|
||||||
|
File "libspeex-1.dll"
|
||||||
|
File "libsqlite3-0.dll"
|
||||||
|
File "libssl-1_1-x64.dll"
|
||||||
|
File "libstdc++-6.dll"
|
||||||
|
File "libtag.dll"
|
||||||
|
File "libvorbis-0.dll"
|
||||||
|
File "libvorbisenc-2.dll"
|
||||||
|
File "libwavpack-1.dll"
|
||||||
|
File "libwinpthread-1.dll"
|
||||||
|
File "Qt5Concurrent.dll"
|
||||||
|
File "Qt5Core.dll"
|
||||||
|
File "Qt5Gui.dll"
|
||||||
|
File "Qt5Network.dll"
|
||||||
|
File "Qt5Sql.dll"
|
||||||
|
File "Qt5Widgets.dll"
|
||||||
|
File "Qt5Xml.dll"
|
||||||
|
File "Qt5WinExtras.dll"
|
||||||
|
File "zlib1.dll"
|
||||||
|
File "libxine-2.dll"
|
||||||
|
File "libmpcdec-5.dll"
|
||||||
|
File "libtheora-0.dll"
|
||||||
|
File "libfftw3-3.dll"
|
||||||
|
File "libxml2-2.dll"
|
||||||
|
File "libsoup-2.4-1.dll"
|
||||||
|
File "liblzma-5.dll"
|
||||||
|
File "libdeezer.x64.dll"
|
||||||
|
|
||||||
|
; Register Strawberry with Default Programs
|
||||||
|
Var /GLOBAL AppIcon
|
||||||
|
Var /GLOBAL AppExe
|
||||||
|
StrCpy $AppExe "$INSTDIR\strawberry.exe"
|
||||||
|
StrCpy $AppIcon "$INSTDIR\strawberry.ico"
|
||||||
|
|
||||||
|
${RegisterCapabilities}
|
||||||
|
|
||||||
|
${RegisterMediaType} ".mp3" $AppExe $AppIcon "MP3 Audio File"
|
||||||
|
${RegisterMediaType} ".flac" $AppExe $AppIcon "FLAC Audio File"
|
||||||
|
${RegisterMediaType} ".ogg" $AppExe $AppIcon "OGG Audio File"
|
||||||
|
${RegisterMediaType} ".spx" $AppExe $AppIcon "OGG Speex Audio File"
|
||||||
|
${RegisterMediaType} ".m4a" $AppExe $AppIcon "MP4 Audio File"
|
||||||
|
${RegisterMediaType} ".aac" $AppExe $AppIcon "AAC Audio File"
|
||||||
|
${RegisterMediaType} ".wma" $AppExe $AppIcon "WMA Audio File"
|
||||||
|
${RegisterMediaType} ".wav" $AppExe $AppIcon "WAV Audio File"
|
||||||
|
|
||||||
|
${RegisterMediaType} ".pls" $AppExe $AppIcon "PLS Audio File"
|
||||||
|
${RegisterMediaType} ".m3u" $AppExe $AppIcon "M3U Audio File"
|
||||||
|
${RegisterMediaType} ".xspf" $AppExe $AppIcon "XSPF Audio File"
|
||||||
|
${RegisterMediaType} ".asx" $AppExe $AppIcon "Windows Media Audio/Video playlist"
|
||||||
|
|
||||||
|
${RegisterMimeType} "audio/mp3" "mp3" "{cd3afa76-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "audio/mp4" "m4a" "{cd3afa7c-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "audio/x-ms-wma" "wma" "{cd3afa84-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "audio/wav" "wav" "{cd3afa7b-b84f-48f0-9393-7edc34128127}"
|
||||||
|
|
||||||
|
${RegisterMimeType} "audio/mpegurl" "m3u" "{cd3afa78-b84f-48f0-9393-7edc34128127}"
|
||||||
|
${RegisterMimeType} "application/x-wmplayer" "asx" "{cd3afa96-b84f-48f0-9393-7edc34128127}"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Qt Platforms" platforms
|
||||||
|
SetOutPath "$INSTDIR\platforms"
|
||||||
|
File "/oname=qwindows.dll" "platforms\qwindows.dll"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Qt SQL Drivers" sqldrivers
|
||||||
|
SetOutPath "$INSTDIR\sqldrivers"
|
||||||
|
File "/oname=qsqlite.dll" "sqldrivers\qsqlite.dll"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Qt image format plugins" imageformats
|
||||||
|
SetOutPath "$INSTDIR\imageformats"
|
||||||
|
File "/oname=qgif.dll" "imageformats\qgif.dll"
|
||||||
|
File "/oname=qico.dll" "imageformats\qico.dll"
|
||||||
|
File "/oname=qjpeg.dll" "imageformats\qjpeg.dll"
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Gstreamer plugins" gstreamer-plugins
|
||||||
|
SetOutPath "$INSTDIR\gstreamer-plugins"
|
||||||
|
|
||||||
|
File "/oname=libgstapetag.dll" "gstreamer-plugins\libgstapetag.dll"
|
||||||
|
File "/oname=libgstapp.dll" "gstreamer-plugins\libgstapp.dll"
|
||||||
|
File "/oname=libgstasf.dll" "gstreamer-plugins\libgstasf.dll"
|
||||||
|
File "/oname=libgstaiff.dll" "gstreamer-plugins\libgstaiff.dll"
|
||||||
|
File "/oname=libgstaudioconvert.dll" "gstreamer-plugins\libgstaudioconvert.dll"
|
||||||
|
File "/oname=libgstaudiofx.dll" "gstreamer-plugins\libgstaudiofx.dll"
|
||||||
|
File "/oname=libgstaudioparsers.dll" "gstreamer-plugins\libgstaudioparsers.dll"
|
||||||
|
File "/oname=libgstaudioresample.dll" "gstreamer-plugins\libgstaudioresample.dll"
|
||||||
|
File "/oname=libgstaudiotestsrc.dll" "gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||||
|
File "/oname=libgstautodetect.dll" "gstreamer-plugins\libgstautodetect.dll"
|
||||||
|
File "/oname=libgstcoreelements.dll" "gstreamer-plugins\libgstcoreelements.dll"
|
||||||
|
File "/oname=libgstdirectsound.dll" "gstreamer-plugins\libgstdirectsound.dll"
|
||||||
|
File "/oname=libgstequalizer.dll" "gstreamer-plugins\libgstequalizer.dll"
|
||||||
|
File "/oname=libgstfaad.dll" "gstreamer-plugins\libgstfaad.dll"
|
||||||
|
File "/oname=libgstflac.dll" "gstreamer-plugins\libgstflac.dll"
|
||||||
|
File "/oname=libgstgio.dll" "gstreamer-plugins\libgstgio.dll"
|
||||||
|
File "/oname=libgsticydemux.dll" "gstreamer-plugins\libgsticydemux.dll"
|
||||||
|
File "/oname=libgstid3demux.dll" "gstreamer-plugins\libgstid3demux.dll"
|
||||||
|
File "/oname=libgstisomp4.dll" "gstreamer-plugins\libgstisomp4.dll"
|
||||||
|
File "/oname=libgstlame.dll" "gstreamer-plugins\libgstlame.dll"
|
||||||
|
File "/oname=libgstogg.dll" "gstreamer-plugins\libgstogg.dll"
|
||||||
|
File "/oname=libgstopusparse.dll" "gstreamer-plugins\libgstopusparse.dll"
|
||||||
|
File "/oname=libgstplayback.dll" "gstreamer-plugins\libgstplayback.dll"
|
||||||
|
File "/oname=libgstreplaygain.dll" "gstreamer-plugins\libgstreplaygain.dll"
|
||||||
|
File "/oname=libgstspectrum.dll" "gstreamer-plugins\libgstspectrum.dll"
|
||||||
|
File "/oname=libgstspeex.dll" "gstreamer-plugins\libgstspeex.dll"
|
||||||
|
File "/oname=libgsttaglib.dll" "gstreamer-plugins\libgsttaglib.dll"
|
||||||
|
File "/oname=libgsttypefindfunctions.dll" "gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||||
|
File "/oname=libgstvolume.dll" "gstreamer-plugins\libgstvolume.dll"
|
||||||
|
File "/oname=libgstvorbis.dll" "gstreamer-plugins\libgstvorbis.dll"
|
||||||
|
File "/oname=libgstwavpack.dll" "gstreamer-plugins\libgstwavpack.dll"
|
||||||
|
File "/oname=libgstwavparse.dll" "gstreamer-plugins\libgstwavparse.dll"
|
||||||
|
File "/oname=libgstcdio.dll" "gstreamer-plugins\libgstcdio.dll"
|
||||||
|
File "/oname=libgsttcp.dll" "gstreamer-plugins\libgsttcp.dll"
|
||||||
|
File "/oname=libgstudp.dll" "gstreamer-plugins\libgstudp.dll"
|
||||||
|
File "/oname=libgstsoup.dll" "gstreamer-plugins\libgstsoup.dll"
|
||||||
|
File "/oname=libgstlibav.dll" "gstreamer-plugins\libgstlibav.dll"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Xine plugins" xine-plugins
|
||||||
|
SetOutPath "$INSTDIR\xine-plugins"
|
||||||
|
File "/oname=xineplug_ao_out_directx2.dll" "xine-plugins\xineplug_ao_out_directx2.dll"
|
||||||
|
File "/oname=xineplug_ao_out_directx.dll" "xine-plugins\xineplug_ao_out_directx.dll"
|
||||||
|
File "/oname=xineplug_decode_dts.dll" "xine-plugins\xineplug_decode_dts.dll"
|
||||||
|
File "/oname=xineplug_decode_dvaudio.dll" "xine-plugins\xineplug_decode_dvaudio.dll"
|
||||||
|
File "/oname=xineplug_decode_faad.dll" "xine-plugins\xineplug_decode_faad.dll"
|
||||||
|
File "/oname=xineplug_decode_gsm610.dll" "xine-plugins\xineplug_decode_gsm610.dll"
|
||||||
|
File "/oname=xineplug_decode_lpcm.dll" "xine-plugins\xineplug_decode_lpcm.dll"
|
||||||
|
File "/oname=xineplug_decode_mad.dll" "xine-plugins\xineplug_decode_mad.dll"
|
||||||
|
File "/oname=xineplug_decode_mpc.dll" "xine-plugins\xineplug_decode_mpc.dll"
|
||||||
|
File "/oname=xineplug_decode_mpeg2.dll" "xine-plugins\xineplug_decode_mpeg2.dll"
|
||||||
|
File "/oname=xineplug_dmx_asf.dll" "xine-plugins\xineplug_dmx_asf.dll"
|
||||||
|
File "/oname=xineplug_dmx_audio.dll" "xine-plugins\xineplug_dmx_audio.dll"
|
||||||
|
File "/oname=xineplug_dmx_playlist.dll" "xine-plugins\xineplug_dmx_playlist.dll"
|
||||||
|
File "/oname=xineplug_dmx_slave.dll" "xine-plugins\xineplug_dmx_slave.dll"
|
||||||
|
File "/oname=xineplug_flac.dll" "xine-plugins\xineplug_flac.dll"
|
||||||
|
File "/oname=xineplug_wavpack.dll" "xine-plugins\xineplug_wavpack.dll"
|
||||||
|
File "/oname=xineplug_xiph.dll" "xine-plugins\xineplug_xiph.dll"
|
||||||
|
File "/oname=xineplug_inp_cdda.dll" "xine-plugins\xineplug_inp_cdda.dll"
|
||||||
|
|
||||||
|
File "/oname=xineplug_post_audio_filters.dll" "xine-plugins\xineplug_post_audio_filters.dll"
|
||||||
|
File "/oname=xineplug_post_goom.dll" "xine-plugins\xineplug_post_goom.dll"
|
||||||
|
File "/oname=xineplug_post_mosaico.dll" "xine-plugins\xineplug_post_mosaico.dll"
|
||||||
|
File "/oname=xineplug_post_planar.dll" "xine-plugins\xineplug_post_planar.dll"
|
||||||
|
File "/oname=xineplug_post_switch.dll" "xine-plugins\xineplug_post_switch.dll"
|
||||||
|
File "/oname=xineplug_post_tvtime.dll" "xine-plugins\xineplug_post_tvtime.dll"
|
||||||
|
File "/oname=xineplug_post_visualizations.dll" "xine-plugins\xineplug_post_visualizations.dll"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Start menu items" startmenu
|
||||||
|
; Create Start Menu folders and shortcuts.
|
||||||
|
SetShellVarContext all
|
||||||
|
|
||||||
|
CreateDirectory "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||||
|
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk" "$INSTDIR\strawberry.exe"
|
||||||
|
CreateShortCut "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk" "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstaller"
|
||||||
|
; Create uninstaller
|
||||||
|
WriteUninstaller "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "${PRODUCT_NAME}"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\Uninstall.exe"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\strawberry.ico"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_DISPLAY_VERSION}"
|
||||||
|
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMajor" "${PRODUCT_VERSION_MAJOR}"
|
||||||
|
WriteRegDWORD ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "VersionMinor" "${PRODUCT_VERSION_MINOR}"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}"
|
||||||
|
WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
|
|
||||||
|
Section "Uninstall"
|
||||||
|
; Kill strawberry.exe if it's running
|
||||||
|
; This calling convention is retarded...
|
||||||
|
;StrCpy $0 "strawberry.exe"
|
||||||
|
;KillProc::FindProcesses
|
||||||
|
;StrCmp $1 "-1" wooops
|
||||||
|
|
||||||
|
;StrCmp $0 "0" completed
|
||||||
|
|
||||||
|
;DetailPrint "Killing running strawberry.exe..."
|
||||||
|
|
||||||
|
;StrCpy $0 "strawberry.exe"
|
||||||
|
;KillProc::KillProcesses
|
||||||
|
;StrCmp $1 "-1" wooops
|
||||||
|
|
||||||
|
;Sleep 2000
|
||||||
|
;Goto completed
|
||||||
|
|
||||||
|
;wooops:
|
||||||
|
;DetailPrint "-> Error: Something went wrong while killing running strawberry.exe"
|
||||||
|
;Abort
|
||||||
|
|
||||||
|
;completed:
|
||||||
|
|
||||||
|
; Delete all the files
|
||||||
|
|
||||||
|
Delete "$INSTDIR\strawberry.ico"
|
||||||
|
Delete "$INSTDIR\strawberry.exe"
|
||||||
|
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\libbz2.dll"
|
||||||
|
Delete "$INSTDIR\libcdio-18.dll"
|
||||||
|
Delete "$INSTDIR\libchromaprint.dll"
|
||||||
|
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||||
|
Delete "$INSTDIR\libfaad-2.dll"
|
||||||
|
Delete "$INSTDIR\libffi-6.dll"
|
||||||
|
Delete "$INSTDIR\libFLAC-8.dll"
|
||||||
|
Delete "$INSTDIR\libfreetype-6.dll"
|
||||||
|
Delete "$INSTDIR\libgcc_s_sjlj-1.dll"
|
||||||
|
Delete "$INSTDIR\libgio-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libglib-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgmodule-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgobject-2.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstapp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstaudio-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstbase-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstfft-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstpbutils-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstreamer-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstriff-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstrtp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstrtsp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstsdp-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgsttag-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstvideo-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libgstnet-1.0-0.dll"
|
||||||
|
Delete "$INSTDIR\libharfbuzz-0.dll"
|
||||||
|
Delete "$INSTDIR\libiconv-2.dll"
|
||||||
|
Delete "$INSTDIR\libintl-8.dll"
|
||||||
|
Delete "$INSTDIR\libjpeg-9.dll"
|
||||||
|
Delete "$INSTDIR\liblastfm5.dll"
|
||||||
|
Delete "$INSTDIR\libmp3lame-0.dll"
|
||||||
|
Delete "$INSTDIR\libogg-0.dll"
|
||||||
|
Delete "$INSTDIR\libopus-0.dll"
|
||||||
|
Delete "$INSTDIR\libpcre-1.dll"
|
||||||
|
Delete "$INSTDIR\libpcre2-16-0.dll"
|
||||||
|
Delete "$INSTDIR\libpng16-16.dll"
|
||||||
|
Delete "$INSTDIR\libprotobuf-15.dll"
|
||||||
|
Delete "$INSTDIR\libspeex-1.dll"
|
||||||
|
Delete "$INSTDIR\libsqlite3-0.dll"
|
||||||
|
Delete "$INSTDIR\libssl-1_1.dll"
|
||||||
|
Delete "$INSTDIR\libstdc++-6.dll"
|
||||||
|
Delete "$INSTDIR\libtag.dll"
|
||||||
|
Delete "$INSTDIR\libvorbis-0.dll"
|
||||||
|
Delete "$INSTDIR\libvorbisenc-2.dll"
|
||||||
|
Delete "$INSTDIR\libwavpack-1.dll"
|
||||||
|
Delete "$INSTDIR\libwinpthread-1.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Concurrent.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Core.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Gui.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Network.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Sql.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Widgets.dll"
|
||||||
|
Delete "$INSTDIR\Qt5Xml.dll"
|
||||||
|
Delete "$INSTDIR\Qt5WinExtras.dll"
|
||||||
|
Delete "$INSTDIR\zlib1.dll"
|
||||||
|
Delete "$INSTDIR\libxine-2.dll"
|
||||||
|
Delete "$INSTDIR\libmpcdec-5.dll"
|
||||||
|
Delete "$INSTDIR\libtheora-0.dll"
|
||||||
|
Delete "$INSTDIR\libfftw3-3.dll"
|
||||||
|
Delete "$INSTDIR\libxml2-2.dll"
|
||||||
|
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||||
|
Delete "$INSTDIR\liblzma-5.dll"
|
||||||
|
Delete "$INSTDIR\libdeezer.x64.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||||
|
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\imageformats\qgif.dll"
|
||||||
|
Delete "$INSTDIR\imageformats\qico.dll"
|
||||||
|
Delete "$INSTDIR\imageformats\qjpeg.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstapetag.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstapp.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstasf.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaiff.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudioconvert.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudiofx.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudioparsers.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudioresample.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstaudiotestsrc.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstautodetect.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstcoreelements.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstdirectsound.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstequalizer.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstfaad.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstflac.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstgio.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsticydemux.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstid3demux.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstisomp4.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstlame.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstogg.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstopusparse.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstplayback.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstreplaygain.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstspectrum.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstspeex.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsttaglib.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsttypefindfunctions.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstvolume.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstvorbis.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstwavpack.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstwavparse.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstcdio.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgsttcp.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstudp.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstsoup.dll"
|
||||||
|
Delete "$INSTDIR\gstreamer-plugins\libgstlibav.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx2.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_ao_out_directx.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_dts.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_dvaudio.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_faad.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_gsm610.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_lpcm.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_mad.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpc.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_decode_mpeg2.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_dmx_asf.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_dmx_audio.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_dmx_playlist.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_dmx_slave.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_flac.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_wavpack.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_xiph.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_inp_cdda.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_audio_filters.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_goom.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_mosaico.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_planar.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_switch.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_tvtime.dll"
|
||||||
|
Delete "$INSTDIR\xine-plugins\xineplug_post_visualizations.dll"
|
||||||
|
|
||||||
|
Delete "$INSTDIR\Uninstall.exe"
|
||||||
|
|
||||||
|
; Remove the installation folders.
|
||||||
|
RMDir "$INSTDIR\platforms"
|
||||||
|
RMDir "$INSTDIR\sqldrivers"
|
||||||
|
RMDir "$INSTDIR\imageformats"
|
||||||
|
RMDir "$INSTDIR\gstreamer-plugins"
|
||||||
|
RMDir "$INSTDIR\xine-plugins"
|
||||||
|
RMDir "$INSTDIR"
|
||||||
|
|
||||||
|
; Remove the Shortcuts
|
||||||
|
SetShellVarContext all
|
||||||
|
|
||||||
|
Delete "$SMPROGRAMS\${PRODUCT_NAME}\${PRODUCT_NAME}.lnk"
|
||||||
|
Delete "$SMPROGRAMS\${PRODUCT_NAME}\Uninstall.lnk"
|
||||||
|
RMDir /r "$SMPROGRAMS\${PRODUCT_NAME}"
|
||||||
|
|
||||||
|
; Remove the entry from 'installed programs list'
|
||||||
|
DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}"
|
||||||
|
|
||||||
|
; Unregister from Default Programs
|
||||||
|
${UnRegisterCapabilities}
|
||||||
|
|
||||||
|
SectionEnd
|
||||||
6
dist/windows/strawberry-debug.nsi.in
vendored
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
|
|||||||
File "strawberry.ico"
|
File "strawberry.ico"
|
||||||
|
|
||||||
File "libbz2.dll"
|
File "libbz2.dll"
|
||||||
File "libcdio-16.dll"
|
File "libcdio-18.dll"
|
||||||
File "libchromaprint.dll"
|
File "libchromaprint.dll"
|
||||||
File "libcrypto-1_1.dll"
|
File "libcrypto-1_1.dll"
|
||||||
File "libfaad-2.dll"
|
File "libfaad-2.dll"
|
||||||
@@ -164,6 +164,7 @@ Section "Strawberry" Strawberry
|
|||||||
File "libxml2-2.dll"
|
File "libxml2-2.dll"
|
||||||
File "libsoup-2.4-1.dll"
|
File "libsoup-2.4-1.dll"
|
||||||
File "liblzma-5.dll"
|
File "liblzma-5.dll"
|
||||||
|
File "libdeezer.x86.dll"
|
||||||
|
|
||||||
; Register Strawberry with Default Programs
|
; Register Strawberry with Default Programs
|
||||||
Var /GLOBAL AppIcon
|
Var /GLOBAL AppIcon
|
||||||
@@ -344,7 +345,7 @@ Section "Uninstall"
|
|||||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||||
|
|
||||||
Delete "$INSTDIR\libbz2.dll"
|
Delete "$INSTDIR\libbz2.dll"
|
||||||
Delete "$INSTDIR\libcdio-16.dll"
|
Delete "$INSTDIR\libcdio-18.dll"
|
||||||
Delete "$INSTDIR\libchromaprint.dll"
|
Delete "$INSTDIR\libchromaprint.dll"
|
||||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||||
Delete "$INSTDIR\libfaad-2.dll"
|
Delete "$INSTDIR\libfaad-2.dll"
|
||||||
@@ -406,6 +407,7 @@ Section "Uninstall"
|
|||||||
Delete "$INSTDIR\libxml2-2.dll"
|
Delete "$INSTDIR\libxml2-2.dll"
|
||||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||||
Delete "$INSTDIR\liblzma-5.dll"
|
Delete "$INSTDIR\liblzma-5.dll"
|
||||||
|
Delete "$INSTDIR\libdeezer.x86.dll"
|
||||||
|
|
||||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||||
|
|||||||
8
dist/windows/strawberry.nsi.in
vendored
@@ -48,7 +48,7 @@ SetCompressor /SOLID lzma
|
|||||||
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
!insertmacro MUI_LANGUAGE "English" ;first language is the default language
|
||||||
|
|
||||||
Name "${PRODUCT_NAME}"
|
Name "${PRODUCT_NAME}"
|
||||||
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}.exe"
|
OutFile "${PRODUCT_NAME}Setup-${PRODUCT_DISPLAY_VERSION}-Release.exe"
|
||||||
InstallDir "${PRODUCT_INSTALL_DIR}"
|
InstallDir "${PRODUCT_INSTALL_DIR}"
|
||||||
|
|
||||||
; Get the path where Strawberry was installed previously and set it as default path
|
; Get the path where Strawberry was installed previously and set it as default path
|
||||||
@@ -102,7 +102,7 @@ Section "Strawberry" Strawberry
|
|||||||
File "strawberry.ico"
|
File "strawberry.ico"
|
||||||
|
|
||||||
File "libbz2.dll"
|
File "libbz2.dll"
|
||||||
File "libcdio-16.dll"
|
File "libcdio-18.dll"
|
||||||
File "libchromaprint.dll"
|
File "libchromaprint.dll"
|
||||||
File "libcrypto-1_1.dll"
|
File "libcrypto-1_1.dll"
|
||||||
File "libfaad-2.dll"
|
File "libfaad-2.dll"
|
||||||
@@ -163,6 +163,7 @@ Section "Strawberry" Strawberry
|
|||||||
File "libxml2-2.dll"
|
File "libxml2-2.dll"
|
||||||
File "libsoup-2.4-1.dll"
|
File "libsoup-2.4-1.dll"
|
||||||
File "liblzma-5.dll"
|
File "liblzma-5.dll"
|
||||||
|
File "libdeezer.x86.dll"
|
||||||
|
|
||||||
; Register Strawberry with Default Programs
|
; Register Strawberry with Default Programs
|
||||||
Var /GLOBAL AppIcon
|
Var /GLOBAL AppIcon
|
||||||
@@ -312,7 +313,7 @@ Section "Uninstall"
|
|||||||
Delete "$INSTDIR\strawberry-tagreader.exe"
|
Delete "$INSTDIR\strawberry-tagreader.exe"
|
||||||
|
|
||||||
Delete "$INSTDIR\libbz2.dll"
|
Delete "$INSTDIR\libbz2.dll"
|
||||||
Delete "$INSTDIR\libcdio-16.dll"
|
Delete "$INSTDIR\libcdio-18.dll"
|
||||||
Delete "$INSTDIR\libchromaprint.dll"
|
Delete "$INSTDIR\libchromaprint.dll"
|
||||||
Delete "$INSTDIR\libcrypto-1_1.dll"
|
Delete "$INSTDIR\libcrypto-1_1.dll"
|
||||||
Delete "$INSTDIR\libfaad-2.dll"
|
Delete "$INSTDIR\libfaad-2.dll"
|
||||||
@@ -373,6 +374,7 @@ Section "Uninstall"
|
|||||||
Delete "$INSTDIR\libxml2-2.dll"
|
Delete "$INSTDIR\libxml2-2.dll"
|
||||||
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
Delete "$INSTDIR\libsoup-2.4-1.dll"
|
||||||
Delete "$INSTDIR\liblzma-5.dll"
|
Delete "$INSTDIR\liblzma-5.dll"
|
||||||
|
Delete "$INSTDIR\libdeezer.x86.dll"
|
||||||
|
|
||||||
Delete "$INSTDIR\platforms\qwindows.dll"
|
Delete "$INSTDIR\platforms\qwindows.dll"
|
||||||
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
Delete "$INSTDIR\sqldrivers\qsqlite.dll"
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
#include <taglib/tag.h>
|
#include <taglib/tag.h>
|
||||||
#include <taglib/apetag.h>
|
#include <taglib/apetag.h>
|
||||||
#include <taglib/id3v2tag.h>
|
#include <taglib/id3v2tag.h>
|
||||||
#include "taglib/id3v2frame.h"
|
#include <taglib/id3v2frame.h>
|
||||||
#include <taglib/flacfile.h>
|
#include <taglib/flacfile.h>
|
||||||
#include <taglib/oggflacfile.h>
|
#include <taglib/oggflacfile.h>
|
||||||
#include <taglib/flacproperties.h>
|
#include <taglib/flacproperties.h>
|
||||||
@@ -54,12 +54,12 @@
|
|||||||
#include <taglib/wavpackfile.h>
|
#include <taglib/wavpackfile.h>
|
||||||
#include <taglib/aifffile.h>
|
#include <taglib/aifffile.h>
|
||||||
#include <taglib/asffile.h>
|
#include <taglib/asffile.h>
|
||||||
#include "taglib/asftag.h"
|
#include <taglib/asftag.h>
|
||||||
#include "taglib/asfattribute.h"
|
#include <taglib/asfattribute.h>
|
||||||
#include "taglib/asfproperties.h"
|
#include <taglib/asfproperties.h>
|
||||||
#include <taglib/mp4file.h>
|
#include <taglib/mp4file.h>
|
||||||
#include <taglib/mp4tag.h>
|
#include <taglib/mp4tag.h>
|
||||||
#include "taglib/mp4item.h"
|
#include <taglib/mp4item.h>
|
||||||
#include <taglib/mp4coverart.h>
|
#include <taglib/mp4coverart.h>
|
||||||
#include <taglib/mp4properties.h>
|
#include <taglib/mp4properties.h>
|
||||||
#include <taglib/mpcfile.h>
|
#include <taglib/mpcfile.h>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ message SongMetadata {
|
|||||||
TRUEAUDIO = 13;
|
TRUEAUDIO = 13;
|
||||||
DSF = 14;
|
DSF = 14;
|
||||||
DSDIFF = 15;
|
DSDIFF = 15;
|
||||||
|
PCM = 16;
|
||||||
CDDA = 90;
|
CDDA = 90;
|
||||||
STREAM = 91;
|
STREAM = 91;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
# Strawberry Music Player
|
# Strawberry Music Player
|
||||||
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
# Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
# This file was part of Clementine.
|
|
||||||
# Copyright 2010, David Sansome <me@davidsansome.com>
|
|
||||||
#
|
#
|
||||||
# Strawberry is free software: you can redistribute it and/or modify
|
# Strawberry is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -59,6 +57,14 @@ if(HAVE_PHONON)
|
|||||||
include_directories(${PHONON_INCLUDE_DIRS})
|
include_directories(${PHONON_INCLUDE_DIRS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_LIBDEEZER)
|
||||||
|
include_directories(${DEEZER_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_LIBDZMEDIA)
|
||||||
|
include_directories(${DZMEDIA_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
|
||||||
link_directories(${TAGLIB_LIBRARY_DIRS})
|
link_directories(${TAGLIB_LIBRARY_DIRS})
|
||||||
include_directories(${TAGLIB_INCLUDE_DIRS})
|
include_directories(${TAGLIB_INCLUDE_DIRS})
|
||||||
|
|
||||||
@@ -158,11 +164,12 @@ set(SOURCES
|
|||||||
playlist/playlisttabbar.cpp
|
playlist/playlisttabbar.cpp
|
||||||
playlist/playlistundocommands.cpp
|
playlist/playlistundocommands.cpp
|
||||||
playlist/playlistview.cpp
|
playlist/playlistview.cpp
|
||||||
playlist/queue.cpp
|
|
||||||
playlist/queuemanager.cpp
|
|
||||||
playlist/songloaderinserter.cpp
|
playlist/songloaderinserter.cpp
|
||||||
playlist/songplaylistitem.cpp
|
playlist/songplaylistitem.cpp
|
||||||
|
|
||||||
|
queue/queue.cpp
|
||||||
|
queue/queueview.cpp
|
||||||
|
|
||||||
playlistparsers/asxiniparser.cpp
|
playlistparsers/asxiniparser.cpp
|
||||||
playlistparsers/asxparser.cpp
|
playlistparsers/asxparser.cpp
|
||||||
playlistparsers/cueparser.cpp
|
playlistparsers/cueparser.cpp
|
||||||
@@ -192,7 +199,13 @@ set(SOURCES
|
|||||||
covermanager/coverfromurldialog.cpp
|
covermanager/coverfromurldialog.cpp
|
||||||
covermanager/musicbrainzcoverprovider.cpp
|
covermanager/musicbrainzcoverprovider.cpp
|
||||||
covermanager/discogscoverprovider.cpp
|
covermanager/discogscoverprovider.cpp
|
||||||
#covermanager/amazoncoverprovider.cpp
|
|
||||||
|
lyrics/lyricsproviders.cpp
|
||||||
|
lyrics/lyricsprovider.cpp
|
||||||
|
lyrics/lyricsfetcher.cpp
|
||||||
|
lyrics/lyricsfetchersearch.cpp
|
||||||
|
lyrics/auddlyricsprovider.cpp
|
||||||
|
lyrics/apiseedslyricsprovider.cpp
|
||||||
|
|
||||||
settings/settingsdialog.cpp
|
settings/settingsdialog.cpp
|
||||||
settings/settingspage.cpp
|
settings/settingspage.cpp
|
||||||
@@ -205,7 +218,6 @@ set(SOURCES
|
|||||||
settings/shortcutssettingspage.cpp
|
settings/shortcutssettingspage.cpp
|
||||||
settings/appearancesettingspage.cpp
|
settings/appearancesettingspage.cpp
|
||||||
settings/notificationssettingspage.cpp
|
settings/notificationssettingspage.cpp
|
||||||
settings/tidalsettingspage.cpp
|
|
||||||
|
|
||||||
dialogs/about.cpp
|
dialogs/about.cpp
|
||||||
dialogs/console.cpp
|
dialogs/console.cpp
|
||||||
@@ -248,33 +260,15 @@ set(SOURCES
|
|||||||
globalshortcuts/qxtglobalshortcutbackend.cpp
|
globalshortcuts/qxtglobalshortcutbackend.cpp
|
||||||
globalshortcuts/globalshortcutgrabber.cpp
|
globalshortcuts/globalshortcutgrabber.cpp
|
||||||
|
|
||||||
device/connecteddevice.cpp
|
internet/internetservices.cpp
|
||||||
device/devicedatabasebackend.cpp
|
|
||||||
device/devicelister.cpp
|
|
||||||
device/devicemanager.cpp
|
|
||||||
device/deviceproperties.cpp
|
|
||||||
device/devicestatefiltermodel.cpp
|
|
||||||
device/deviceview.cpp
|
|
||||||
device/deviceviewcontainer.cpp
|
|
||||||
device/filesystemdevice.cpp
|
|
||||||
|
|
||||||
internet/internetmodel.cpp
|
|
||||||
internet/internetservice.cpp
|
internet/internetservice.cpp
|
||||||
internet/internetplaylistitem.cpp
|
internet/internetplaylistitem.cpp
|
||||||
|
internet/internetsearch.cpp
|
||||||
tidal/tidalservice.cpp
|
internet/internetsearchview.cpp
|
||||||
tidal/tidalsearch.cpp
|
internet/internetsearchmodel.cpp
|
||||||
tidal/tidalsearchview.cpp
|
internet/internetsearchsortmodel.cpp
|
||||||
tidal/tidalsearchmodel.cpp
|
internet/internetsearchitemdelegate.cpp
|
||||||
tidal/tidalsearchsortmodel.cpp
|
internet/localredirectserver.cpp
|
||||||
tidal/tidalsearchitemdelegate.cpp
|
|
||||||
|
|
||||||
lyrics/lyricsproviders.cpp
|
|
||||||
lyrics/lyricsprovider.cpp
|
|
||||||
lyrics/lyricsfetcher.cpp
|
|
||||||
lyrics/lyricsfetchersearch.cpp
|
|
||||||
lyrics/auddlyricsprovider.cpp
|
|
||||||
lyrics/apiseedslyricsprovider.cpp
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -338,11 +332,12 @@ set(HEADERS
|
|||||||
playlist/playlisttabbar.h
|
playlist/playlisttabbar.h
|
||||||
playlist/playlistview.h
|
playlist/playlistview.h
|
||||||
playlist/playlistitemmimedata.h
|
playlist/playlistitemmimedata.h
|
||||||
playlist/queue.h
|
|
||||||
playlist/queuemanager.h
|
|
||||||
playlist/songloaderinserter.h
|
playlist/songloaderinserter.h
|
||||||
playlist/songmimedata.h
|
playlist/songmimedata.h
|
||||||
|
|
||||||
|
queue/queue.h
|
||||||
|
queue/queueview.h
|
||||||
|
|
||||||
playlistparsers/asxiniparser.h
|
playlistparsers/asxiniparser.h
|
||||||
playlistparsers/asxparser.h
|
playlistparsers/asxparser.h
|
||||||
playlistparsers/cueparser.h
|
playlistparsers/cueparser.h
|
||||||
@@ -369,7 +364,13 @@ set(HEADERS
|
|||||||
covermanager/coverfromurldialog.h
|
covermanager/coverfromurldialog.h
|
||||||
covermanager/musicbrainzcoverprovider.h
|
covermanager/musicbrainzcoverprovider.h
|
||||||
covermanager/discogscoverprovider.h
|
covermanager/discogscoverprovider.h
|
||||||
#covermanager/amazoncoverprovider.h
|
|
||||||
|
lyrics/lyricsproviders.h
|
||||||
|
lyrics/lyricsprovider.h
|
||||||
|
lyrics/lyricsfetcher.h
|
||||||
|
lyrics/lyricsfetchersearch.h
|
||||||
|
lyrics/auddlyricsprovider.h
|
||||||
|
lyrics/apiseedslyricsprovider.h
|
||||||
|
|
||||||
settings/settingsdialog.h
|
settings/settingsdialog.h
|
||||||
settings/settingspage.h
|
settings/settingspage.h
|
||||||
@@ -382,7 +383,6 @@ set(HEADERS
|
|||||||
settings/shortcutssettingspage.h
|
settings/shortcutssettingspage.h
|
||||||
settings/appearancesettingspage.h
|
settings/appearancesettingspage.h
|
||||||
settings/notificationssettingspage.h
|
settings/notificationssettingspage.h
|
||||||
settings/tidalsettingspage.h
|
|
||||||
|
|
||||||
dialogs/about.h
|
dialogs/about.h
|
||||||
dialogs/errordialog.h
|
dialogs/errordialog.h
|
||||||
@@ -422,32 +422,13 @@ set(HEADERS
|
|||||||
globalshortcuts/gnomeglobalshortcutbackend.h
|
globalshortcuts/gnomeglobalshortcutbackend.h
|
||||||
globalshortcuts/globalshortcutgrabber.h
|
globalshortcuts/globalshortcutgrabber.h
|
||||||
|
|
||||||
device/connecteddevice.h
|
internet/internetservices.h
|
||||||
device/devicedatabasebackend.h
|
|
||||||
device/devicelister.h
|
|
||||||
device/devicemanager.h
|
|
||||||
device/deviceproperties.h
|
|
||||||
device/devicestatefiltermodel.h
|
|
||||||
device/deviceviewcontainer.h
|
|
||||||
device/deviceview.h
|
|
||||||
device/filesystemdevice.h
|
|
||||||
|
|
||||||
internet/internetmodel.h
|
|
||||||
internet/internetservice.h
|
internet/internetservice.h
|
||||||
internet/internetmimedata.h
|
|
||||||
internet/internetsongmimedata.h
|
internet/internetsongmimedata.h
|
||||||
|
internet/internetsearch.h
|
||||||
tidal/tidalservice.h
|
internet/internetsearchview.h
|
||||||
tidal/tidalsearch.h
|
internet/internetsearchmodel.h
|
||||||
tidal/tidalsearchview.h
|
internet/localredirectserver.h
|
||||||
tidal/tidalsearchmodel.h
|
|
||||||
|
|
||||||
lyrics/lyricsproviders.h
|
|
||||||
lyrics/lyricsprovider.h
|
|
||||||
lyrics/lyricsfetcher.h
|
|
||||||
lyrics/lyricsfetchersearch.h
|
|
||||||
lyrics/auddlyricsprovider.h
|
|
||||||
lyrics/apiseedslyricsprovider.h
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -466,7 +447,8 @@ set(UI
|
|||||||
playlist/playlistlistcontainer.ui
|
playlist/playlistlistcontainer.ui
|
||||||
playlist/playlistsaveoptionsdialog.ui
|
playlist/playlistsaveoptionsdialog.ui
|
||||||
playlist/playlistsequence.ui
|
playlist/playlistsequence.ui
|
||||||
playlist/queuemanager.ui
|
|
||||||
|
queue/queueview.ui
|
||||||
|
|
||||||
covermanager/albumcoverexport.ui
|
covermanager/albumcoverexport.ui
|
||||||
covermanager/albumcovermanager.ui
|
covermanager/albumcovermanager.ui
|
||||||
@@ -484,7 +466,6 @@ set(UI
|
|||||||
settings/shortcutssettingspage.ui
|
settings/shortcutssettingspage.ui
|
||||||
settings/appearancesettingspage.ui
|
settings/appearancesettingspage.ui
|
||||||
settings/notificationssettingspage.ui
|
settings/notificationssettingspage.ui
|
||||||
settings/tidalsettingspage.ui
|
|
||||||
|
|
||||||
equalizer/equalizer.ui
|
equalizer/equalizer.ui
|
||||||
equalizer/equalizerslider.ui
|
equalizer/equalizerslider.ui
|
||||||
@@ -500,16 +481,13 @@ set(UI
|
|||||||
widgets/fileview.ui
|
widgets/fileview.ui
|
||||||
widgets/loginstatewidget.ui
|
widgets/loginstatewidget.ui
|
||||||
|
|
||||||
device/deviceproperties.ui
|
|
||||||
device/deviceviewcontainer.ui
|
|
||||||
|
|
||||||
globalshortcuts/globalshortcutgrabber.ui
|
globalshortcuts/globalshortcutgrabber.ui
|
||||||
|
|
||||||
tidal/tidalsearchview.ui
|
internet/internetsearchview.ui
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(RESOURCES ../data/data.qrc)
|
set(RESOURCES ../data/data.qrc ../data/icons.qrc)
|
||||||
set(OTHER_SOURCES)
|
set(OTHER_SOURCES)
|
||||||
|
|
||||||
option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON)
|
option(USE_INSTALL_PREFIX "Look for data in CMAKE_INSTALL_PREFIX" ON)
|
||||||
@@ -547,6 +525,12 @@ optional_source(HAVE_PHONON
|
|||||||
HEADERS engine/phononengine.h
|
HEADERS engine/phononengine.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Deezer
|
||||||
|
optional_source(HAVE_DEEZER
|
||||||
|
SOURCES engine/deezerengine.cpp
|
||||||
|
HEADERS engine/deezerengine.h
|
||||||
|
)
|
||||||
|
|
||||||
# Lastfm
|
# Lastfm
|
||||||
optional_source(HAVE_LIBLASTFM
|
optional_source(HAVE_LIBLASTFM
|
||||||
SOURCES
|
SOURCES
|
||||||
@@ -679,6 +663,32 @@ optional_source(HAVE_DBUS
|
|||||||
core/mpris2.h
|
core/mpris2.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
optional_source(UNIX
|
||||||
|
SOURCES
|
||||||
|
device/connecteddevice.cpp
|
||||||
|
device/devicedatabasebackend.cpp
|
||||||
|
device/devicelister.cpp
|
||||||
|
device/devicemanager.cpp
|
||||||
|
device/devicestatefiltermodel.cpp
|
||||||
|
device/filesystemdevice.cpp
|
||||||
|
device/deviceviewcontainer.cpp
|
||||||
|
device/deviceview.cpp
|
||||||
|
device/deviceproperties.cpp
|
||||||
|
HEADERS
|
||||||
|
device/connecteddevice.h
|
||||||
|
device/devicedatabasebackend.h
|
||||||
|
device/devicelister.h
|
||||||
|
device/devicemanager.h
|
||||||
|
device/devicestatefiltermodel.h
|
||||||
|
device/filesystemdevice.h
|
||||||
|
device/deviceviewcontainer.h
|
||||||
|
device/deviceview.h
|
||||||
|
device/deviceproperties.h
|
||||||
|
UI
|
||||||
|
device/deviceproperties.ui
|
||||||
|
device/deviceviewcontainer.ui
|
||||||
|
)
|
||||||
|
|
||||||
if(HAVE_DBUS)
|
if(HAVE_DBUS)
|
||||||
optional_source(HAVE_DEVICEKIT
|
optional_source(HAVE_DEVICEKIT
|
||||||
SOURCES device/devicekitlister.cpp
|
SOURCES device/devicekitlister.cpp
|
||||||
@@ -845,6 +855,32 @@ optional_source(WIN32
|
|||||||
widgets/osd_win.cpp
|
widgets/osd_win.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
optional_source(HAVE_STREAM_TIDAL
|
||||||
|
SOURCES
|
||||||
|
tidal/tidalservice.cpp
|
||||||
|
tidal/tidalurlhandler.cpp
|
||||||
|
settings/tidalsettingspage.cpp
|
||||||
|
HEADERS
|
||||||
|
tidal/tidalservice.h
|
||||||
|
tidal/tidalurlhandler.h
|
||||||
|
settings/tidalsettingspage.h
|
||||||
|
UI
|
||||||
|
settings/tidalsettingspage.ui
|
||||||
|
)
|
||||||
|
|
||||||
|
optional_source(HAVE_STREAM_DEEZER
|
||||||
|
SOURCES
|
||||||
|
deezer/deezerservice.cpp
|
||||||
|
deezer/deezerurlhandler.cpp
|
||||||
|
settings/deezersettingspage.cpp
|
||||||
|
HEADERS
|
||||||
|
deezer/deezerservice.h
|
||||||
|
deezer/deezerurlhandler.h
|
||||||
|
settings/deezersettingspage.h
|
||||||
|
UI
|
||||||
|
settings/deezersettingspage.ui
|
||||||
|
)
|
||||||
|
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
@@ -877,6 +913,7 @@ target_link_libraries(strawberry_lib
|
|||||||
${QT_LIBRARIES}
|
${QT_LIBRARIES}
|
||||||
${CHROMAPRINT_LIBRARIES}
|
${CHROMAPRINT_LIBRARIES}
|
||||||
${QTSINGLEAPPLICATION_LIBRARIES}
|
${QTSINGLEAPPLICATION_LIBRARIES}
|
||||||
|
${QTSINGLECOREAPPLICATION_LIBRARIES}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${SQLITE_LIBRARIES}
|
${SQLITE_LIBRARIES}
|
||||||
${QOCOA_LIBRARIES}
|
${QOCOA_LIBRARIES}
|
||||||
@@ -903,6 +940,14 @@ if(HAVE_PHONON)
|
|||||||
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
|
target_link_libraries(strawberry_lib ${PHONON_LIBRARIES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_DEEZER)
|
||||||
|
target_link_libraries(strawberry_lib ${LIBDEEZER_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(HAVE_DZMEDIA)
|
||||||
|
target_link_libraries(strawberry_lib ${LIBDZMEDIA_LIBRARIES})
|
||||||
|
endif()
|
||||||
|
|
||||||
if(HAVE_LIBLASTFM)
|
if(HAVE_LIBLASTFM)
|
||||||
target_link_libraries(strawberry_lib ${LASTFM5_LIBRARIES})
|
target_link_libraries(strawberry_lib ${LASTFM5_LIBRARIES})
|
||||||
endif(HAVE_LIBLASTFM)
|
endif(HAVE_LIBLASTFM)
|
||||||
|
|||||||
@@ -27,14 +27,13 @@
|
|||||||
|
|
||||||
#include "analyzerbase.h"
|
#include "analyzerbase.h"
|
||||||
|
|
||||||
|
#include "core/logging.h"
|
||||||
#include "engine/enginebase.h"
|
#include "engine/enginebase.h"
|
||||||
|
|
||||||
// INSTRUCTIONS Base2D
|
// INSTRUCTIONS Base2D
|
||||||
// 1. do anything that depends on height() in init(), Base2D will call it before
|
// 1. do anything that depends on height() in init(), Base2D will call it before you are shown
|
||||||
// you are shown
|
|
||||||
// 2. otherwise you can use the constructor to initialise things
|
// 2. otherwise you can use the constructor to initialise things
|
||||||
// 3. reimplement analyze(), and paint to canvas(), Base2D will update the
|
// 3. reimplement analyze(), and paint to canvas(), Base2D will update the widget when you return control to it
|
||||||
// widget when you return control to it
|
|
||||||
// 4. if you want to manipulate the scope, reimplement transform()
|
// 4. if you want to manipulate the scope, reimplement transform()
|
||||||
// 5. for convenience <vector> <qpixmap.h> <qwdiget.h> are pre-included
|
// 5. for convenience <vector> <qpixmap.h> <qwdiget.h> are pre-included
|
||||||
// TODO make an INSTRUCTIONS file
|
// TODO make an INSTRUCTIONS file
|
||||||
@@ -50,37 +49,32 @@ template class Analyzer::Base<QWidget>;
|
|||||||
|
|
||||||
Analyzer::Base::Base(QWidget *parent, uint scopeSize)
|
Analyzer::Base::Base(QWidget *parent, uint scopeSize)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
m_timeout(40) // msec
|
timeout_(40),
|
||||||
,
|
fht_(new FHT(scopeSize)),
|
||||||
m_fht(new FHT(scopeSize)),
|
engine_(nullptr),
|
||||||
m_engine(nullptr),
|
lastscope_(512),
|
||||||
m_lastScope(512),
|
|
||||||
current_chunk_(0),
|
current_chunk_(0),
|
||||||
new_frame_(false),
|
new_frame_(false),
|
||||||
is_playing_(false) {}
|
is_playing_(false) {}
|
||||||
|
|
||||||
void Analyzer::Base::hideEvent(QHideEvent*) { m_timer.stop(); }
|
void Analyzer::Base::hideEvent(QHideEvent*) { timer_.stop(); }
|
||||||
|
|
||||||
void Analyzer::Base::showEvent(QShowEvent*) { m_timer.start(timeout(), this); }
|
void Analyzer::Base::showEvent(QShowEvent*) { timer_.start(timeout(), this); }
|
||||||
|
|
||||||
void Analyzer::Base::transform(Scope& scope) // virtual
|
void Analyzer::Base::transform(Scope& scope) {
|
||||||
{
|
|
||||||
|
|
||||||
// this is a standard transformation that should give
|
// This is a standard transformation that should give an FFT scope that has bands for pretty analyzers
|
||||||
// an FFT scope that has bands for pretty analyzers
|
|
||||||
|
|
||||||
// NOTE resizing here is redundant as FHT routines only calculate FHT::size()
|
// NOTE: Resizing here is redundant as FHT routines only calculate FHT::size() values scope.resize( fht_->size() );
|
||||||
// values
|
|
||||||
// scope.resize( m_fht->size() );
|
|
||||||
|
|
||||||
float *front = static_cast<float*>(&scope.front());
|
float *front = static_cast<float*>(&scope.front());
|
||||||
|
|
||||||
float *f = new float[m_fht->size()];
|
float *f = new float[fht_->size()];
|
||||||
m_fht->copy(&f[0], front);
|
fht_->copy(&f[0], front);
|
||||||
m_fht->logSpectrum(front, &f[0]);
|
fht_->logSpectrum(front, &f[0]);
|
||||||
m_fht->scale(front, 1.0 / 20);
|
fht_->scale(front, 1.0 / 20);
|
||||||
|
|
||||||
scope.resize(m_fht->size() / 2); // second half of values are rubbish
|
scope.resize(fht_->size() / 2); // second half of values are rubbish
|
||||||
delete[] f;
|
delete[] f;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -90,28 +84,28 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
|
|||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
p.fillRect(e->rect(), palette().color(QPalette::Window));
|
p.fillRect(e->rect(), palette().color(QPalette::Window));
|
||||||
|
|
||||||
switch (m_engine->state()) {
|
switch (engine_->state()) {
|
||||||
case Engine::Playing: {
|
case Engine::Playing: {
|
||||||
const Engine::Scope& thescope = m_engine->scope(m_timeout);
|
const Engine::Scope& thescope = engine_->scope(timeout_);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
// convert to mono here - our built in analyzers need mono, but the engines provide interleaved pcm
|
// convert to mono here - our built in analyzers need mono, but the engines provide interleaved pcm
|
||||||
for (uint x = 0; (int)x < m_fht->size(); ++x) {
|
for (uint x = 0; (int)x < fht_->size(); ++x) {
|
||||||
m_lastScope[x] = double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
|
lastscope_[x] = double(thescope[i] + thescope[i + 1]) / (2 * (1 << 15));
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_playing_ = true;
|
is_playing_ = true;
|
||||||
transform(m_lastScope);
|
transform(lastscope_);
|
||||||
analyze(p, m_lastScope, new_frame_);
|
analyze(p, lastscope_, new_frame_);
|
||||||
|
|
||||||
// scope.resize( m_fht->size() );
|
lastscope_.resize(fht_->size());
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Engine::Paused:
|
case Engine::Paused:
|
||||||
is_playing_ = false;
|
is_playing_ = false;
|
||||||
analyze(p, m_lastScope, new_frame_);
|
analyze(p, lastscope_, new_frame_);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -124,16 +118,18 @@ void Analyzer::Base::paintEvent(QPaintEvent *e) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Analyzer::Base::resizeExponent(int exp) {
|
int Analyzer::Base::resizeExponent(int exp) {
|
||||||
|
|
||||||
if (exp < 3)
|
if (exp < 3)
|
||||||
exp = 3;
|
exp = 3;
|
||||||
else if (exp > 9)
|
else if (exp > 9)
|
||||||
exp = 9;
|
exp = 9;
|
||||||
|
|
||||||
if (exp != m_fht->sizeExp()) {
|
if (exp != fht_->sizeExp()) {
|
||||||
delete m_fht;
|
delete fht_;
|
||||||
m_fht = new FHT(exp);
|
fht_ = new FHT(exp);
|
||||||
}
|
}
|
||||||
return exp;
|
return exp;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Analyzer::Base::resizeForBands(int bands) {
|
int Analyzer::Base::resizeForBands(int bands) {
|
||||||
@@ -153,12 +149,11 @@ int Analyzer::Base::resizeForBands(int bands) {
|
|||||||
exp = 9;
|
exp = 9;
|
||||||
|
|
||||||
resizeExponent(exp);
|
resizeExponent(exp);
|
||||||
return m_fht->size() / 2;
|
return fht_->size() / 2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::Base::demo(QPainter& p) // virtual
|
void Analyzer::Base::demo(QPainter& p) {
|
||||||
{
|
|
||||||
|
|
||||||
static int t = 201; // FIXME make static to namespace perhaps
|
static int t = 201; // FIXME make static to namespace perhaps
|
||||||
|
|
||||||
@@ -171,7 +166,8 @@ void Analyzer::Base::demo(QPainter& p) // virtual
|
|||||||
s[i] = dt * (sin(M_PI + (i * M_PI) / s.size()) + 1.0);
|
s[i] = dt * (sin(M_PI + (i * M_PI) / s.size()) + 1.0);
|
||||||
|
|
||||||
analyze(p, s, new_frame_);
|
analyze(p, s, new_frame_);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
analyze(p, Scope(32, 0), new_frame_);
|
analyze(p, Scope(32, 0), new_frame_);
|
||||||
|
|
||||||
++t;
|
++t;
|
||||||
@@ -179,7 +175,7 @@ void Analyzer::Base::demo(QPainter& p) // virtual
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::Base::polishEvent() {
|
void Analyzer::Base::polishEvent() {
|
||||||
init(); // virtual
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
|
void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
|
||||||
@@ -189,13 +185,13 @@ void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
|
|||||||
|
|
||||||
for (uint i = 0; i < outVec.size(); ++i, pos += step) {
|
for (uint i = 0; i < outVec.size(); ++i, pos += step) {
|
||||||
const double error = pos - std::floor(pos);
|
const double error = pos - std::floor(pos);
|
||||||
const unsigned long offset = (unsigned long)pos;
|
const uint64_t offset = (uint64_t)pos;
|
||||||
|
|
||||||
unsigned long indexLeft = offset + 0;
|
uint64_t indexLeft = offset + 0;
|
||||||
|
|
||||||
if (indexLeft >= inVec.size()) indexLeft = inVec.size() - 1;
|
if (indexLeft >= inVec.size()) indexLeft = inVec.size() - 1;
|
||||||
|
|
||||||
unsigned long indexRight = offset + 1;
|
uint64_t indexRight = offset + 1;
|
||||||
|
|
||||||
if (indexRight >= inVec.size()) indexRight = inVec.size() - 1;
|
if (indexRight >= inVec.size()) indexRight = inVec.size() - 1;
|
||||||
|
|
||||||
@@ -205,6 +201,7 @@ void Analyzer::interpolate(const Scope& inVec, Scope& outVec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::initSin(Scope& v, const uint size) {
|
void Analyzer::initSin(Scope& v, const uint size) {
|
||||||
|
|
||||||
double step = (M_PI * 2) / size;
|
double step = (M_PI * 2) / size;
|
||||||
double radian = 0;
|
double radian = 0;
|
||||||
|
|
||||||
@@ -212,12 +209,15 @@ void Analyzer::initSin(Scope& v, const uint size) {
|
|||||||
v.push_back(sin(radian));
|
v.push_back(sin(radian));
|
||||||
radian += step;
|
radian += step;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::Base::timerEvent(QTimerEvent *e) {
|
void Analyzer::Base::timerEvent(QTimerEvent *e) {
|
||||||
|
|
||||||
QWidget::timerEvent(e);
|
QWidget::timerEvent(e);
|
||||||
if (e->timerId() != m_timer.timerId()) return;
|
if (e->timerId() != timer_.timerId()) return;
|
||||||
|
|
||||||
new_frame_ = true;
|
new_frame_ = true;
|
||||||
update();
|
update();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,17 +37,17 @@ class Base : public QWidget {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~Base() { delete m_fht; }
|
~Base() { delete fht_; }
|
||||||
|
|
||||||
uint timeout() const { return m_timeout; }
|
uint timeout() const { return timeout_; }
|
||||||
|
|
||||||
void set_engine(EngineBase *engine) { m_engine = engine; }
|
void set_engine(EngineBase *engine) { engine_ = engine; }
|
||||||
|
|
||||||
void changeTimeout(uint newTimeout) {
|
void changeTimeout(uint newTimeout) {
|
||||||
m_timeout = newTimeout;
|
timeout_ = newTimeout;
|
||||||
if (m_timer.isActive()) {
|
if (timer_.isActive()) {
|
||||||
m_timer.stop();
|
timer_.stop();
|
||||||
m_timer.start(m_timeout, this);
|
timer_.start(timeout_, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,13 +71,12 @@ class Base : public QWidget {
|
|||||||
virtual void demo(QPainter& p);
|
virtual void demo(QPainter& p);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QBasicTimer m_timer;
|
QBasicTimer timer_;
|
||||||
uint m_timeout;
|
uint timeout_;
|
||||||
FHT* m_fht;
|
FHT *fht_;
|
||||||
EngineBase* m_engine;
|
EngineBase *engine_;
|
||||||
Scope m_lastScope;
|
Scope lastscope_;
|
||||||
int current_chunk_;
|
int current_chunk_;
|
||||||
|
|
||||||
bool new_frame_;
|
bool new_frame_;
|
||||||
bool is_playing_;
|
bool is_playing_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,109 +26,105 @@ const uint BlockAnalyzer::MIN_COLUMNS = 32; // arbituary
|
|||||||
const uint BlockAnalyzer::MAX_COLUMNS = 256; // must be 2**n
|
const uint BlockAnalyzer::MAX_COLUMNS = 256; // must be 2**n
|
||||||
const uint BlockAnalyzer::FADE_SIZE = 90;
|
const uint BlockAnalyzer::FADE_SIZE = 90;
|
||||||
|
|
||||||
const char *BlockAnalyzer::kName =
|
const char *BlockAnalyzer::kName = QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
|
||||||
QT_TRANSLATE_NOOP("AnalyzerContainer", "Block analyzer");
|
|
||||||
|
|
||||||
BlockAnalyzer::BlockAnalyzer(QWidget *parent)
|
BlockAnalyzer::BlockAnalyzer(QWidget *parent)
|
||||||
: Analyzer::Base(parent, 9),
|
: Analyzer::Base(parent, 9),
|
||||||
m_columns(0) // uint
|
columns_(0),
|
||||||
,
|
rows_(0),
|
||||||
m_rows(0) // uint
|
y_(0),
|
||||||
,
|
barpixmap_(1, 1),
|
||||||
m_y(0) // uint
|
topbarpixmap_(WIDTH, HEIGHT),
|
||||||
,
|
scope_(MIN_COLUMNS),
|
||||||
m_barPixmap(1, 1) // null qpixmaps cause crashes
|
store_(1 << 8, 0),
|
||||||
,
|
fade_bars_(FADE_SIZE),
|
||||||
m_topBarPixmap(WIDTH, HEIGHT),
|
fade_pos_(1 << 8, 50),
|
||||||
m_scope(MIN_COLUMNS) // Scope
|
fade_intensity_(1 << 8, 32) {
|
||||||
,
|
|
||||||
m_store(1 << 8, 0) // vector<uint>
|
|
||||||
,
|
|
||||||
m_fade_bars(FADE_SIZE) // vector<QPixmap>
|
|
||||||
,
|
|
||||||
m_fade_pos(1 << 8, 50) // vector<uint>
|
|
||||||
,
|
|
||||||
m_fade_intensity(1 << 8, 32) // vector<uint>
|
|
||||||
{
|
|
||||||
setMinimumSize(MIN_COLUMNS * (WIDTH + 1) - 1, MIN_ROWS * (HEIGHT + 1) - 1); //-1 is padding, no drawing takes place there
|
setMinimumSize(MIN_COLUMNS * (WIDTH + 1) - 1, MIN_ROWS * (HEIGHT + 1) - 1); //-1 is padding, no drawing takes place there
|
||||||
setMaximumWidth(MAX_COLUMNS * (WIDTH + 1) - 1);
|
setMaximumWidth(MAX_COLUMNS * (WIDTH + 1) - 1);
|
||||||
|
|
||||||
// mxcl says null pixmaps cause crashes, so let's play it safe
|
// mxcl says null pixmaps cause crashes, so let's play it safe
|
||||||
for (uint i = 0; i < FADE_SIZE; ++i) m_fade_bars[i] = QPixmap(1, 1);
|
for (uint i = 0; i < FADE_SIZE; ++i) fade_bars_[i] = QPixmap(1, 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockAnalyzer::~BlockAnalyzer() {}
|
BlockAnalyzer::~BlockAnalyzer() {}
|
||||||
|
|
||||||
void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
|
void BlockAnalyzer::resizeEvent(QResizeEvent *e) {
|
||||||
|
|
||||||
QWidget::resizeEvent(e);
|
QWidget::resizeEvent(e);
|
||||||
|
|
||||||
m_background = QPixmap(size());
|
background_ = QPixmap(size());
|
||||||
canvas_ = QPixmap(size());
|
canvas_ = QPixmap(size());
|
||||||
|
|
||||||
const uint oldRows = m_rows;
|
const uint oldRows = rows_;
|
||||||
|
|
||||||
// all is explained in analyze()..
|
// all is explained in analyze()..
|
||||||
//+1 to counter -1 in maxSizes, trust me we need this!
|
//+1 to counter -1 in maxSizes, trust me we need this!
|
||||||
m_columns = qMax(uint(double(width() + 1) / (WIDTH + 1)), MAX_COLUMNS);
|
columns_ = qMax(uint(double(width() + 1) / (WIDTH + 1)), MAX_COLUMNS);
|
||||||
m_rows = uint(double(height() + 1) / (HEIGHT + 1));
|
rows_ = uint(double(height() + 1) / (HEIGHT + 1));
|
||||||
|
|
||||||
// this is the y-offset for drawing from the top of the widget
|
// this is the y-offset for drawing from the top of the widget
|
||||||
m_y = (height() - (m_rows * (HEIGHT + 1)) + 2) / 2;
|
y_ = (height() - (rows_ * (HEIGHT + 1)) + 2) / 2;
|
||||||
|
|
||||||
m_scope.resize(m_columns);
|
scope_.resize(columns_);
|
||||||
|
|
||||||
if (m_rows != oldRows) {
|
if (rows_ != oldRows) {
|
||||||
m_barPixmap = QPixmap(WIDTH, m_rows * (HEIGHT + 1));
|
barpixmap_ = QPixmap(WIDTH, rows_ * (HEIGHT + 1));
|
||||||
|
|
||||||
for (uint i = 0; i < FADE_SIZE; ++i)
|
for (uint i = 0; i < FADE_SIZE; ++i)
|
||||||
m_fade_bars[i] = QPixmap(WIDTH, m_rows * (HEIGHT + 1));
|
fade_bars_[i] = QPixmap(WIDTH, rows_ * (HEIGHT + 1));
|
||||||
|
|
||||||
m_yscale.resize(m_rows + 1);
|
yscale_.resize(rows_ + 1);
|
||||||
|
|
||||||
const uint PRE = 1,
|
const uint PRE = 1, PRO = 1; // PRE and PRO allow us to restrict the range somewhat
|
||||||
PRO = 1; // PRE and PRO allow us to restrict the range somewhat
|
|
||||||
|
|
||||||
for (uint z = 0; z < m_rows; ++z)
|
for (uint z = 0; z < rows_; ++z)
|
||||||
m_yscale[z] = 1 - (log10(PRE + z) / log10(PRE + m_rows + PRO));
|
yscale_[z] = 1 - (log10(PRE + z) / log10(PRE + rows_ + PRO));
|
||||||
|
|
||||||
m_yscale[m_rows] = 0;
|
yscale_[rows_] = 0;
|
||||||
|
|
||||||
determineStep();
|
determineStep();
|
||||||
paletteChange(palette());
|
paletteChange(palette());
|
||||||
}
|
}
|
||||||
|
|
||||||
drawBackground();
|
drawBackground();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::determineStep() {
|
void BlockAnalyzer::determineStep() {
|
||||||
|
|
||||||
// falltime is dependent on rowcount due to our digital resolution (ie we have boxes/blocks of pixels)
|
// falltime is dependent on rowcount due to our digital resolution (ie we have boxes/blocks of pixels)
|
||||||
// I calculated the value 30 based on some trial and error
|
// I calculated the value 30 based on some trial and error
|
||||||
|
|
||||||
// the fall time of 30 is too slow on framerates above 50fps
|
// the fall time of 30 is too slow on framerates above 50fps
|
||||||
const double fallTime = timeout() < 20 ? 20 * m_rows : 30 * m_rows;
|
const double fallTime = timeout() < 20 ? 20 * rows_ : 30 * rows_;
|
||||||
|
|
||||||
|
step_ = double(rows_ * timeout()) / fallTime;
|
||||||
|
|
||||||
m_step = double(m_rows * timeout()) / fallTime;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::framerateChanged() { // virtual
|
void BlockAnalyzer::framerateChanged() {
|
||||||
determineStep();
|
determineStep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::transform(Analyzer::Scope& s) // pure virtual
|
void BlockAnalyzer::transform(Analyzer::Scope &s) {
|
||||||
{
|
|
||||||
for (uint x = 0; x < s.size(); ++x) s[x] *= 2;
|
for (uint x = 0; x < s.size(); ++x) s[x] *= 2;
|
||||||
|
|
||||||
float* front = static_cast<float*>(&s.front());
|
float* front = static_cast<float*>(&s.front());
|
||||||
|
|
||||||
m_fht->spectrum(front);
|
fht_->spectrum(front);
|
||||||
m_fht->scale(front, 1.0 / 20);
|
fht_->scale(front, 1.0 / 20);
|
||||||
|
|
||||||
|
// the second half is pretty dull, so only show it if the user has a large analyzer by setting to scope_.size() if large we prevent interpolation of large analyzers, this is good!
|
||||||
|
s.resize(scope_.size() <= MAX_COLUMNS / 2 ? MAX_COLUMNS / 2 : scope_.size());
|
||||||
|
|
||||||
// the second half is pretty dull, so only show it if the user has a large analyzer by setting to m_scope.size() if large we prevent interpolation of large analyzers, this is good!
|
|
||||||
s.resize(m_scope.size() <= MAX_COLUMNS / 2 ? MAX_COLUMNS / 2 : m_scope.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
void BlockAnalyzer::analyze(QPainter &p, const Analyzer::Scope &s, bool new_frame) {
|
||||||
bool new_frame) {
|
|
||||||
// y = 2 3 2 1 0 2
|
// y = 2 3 2 1 0 2
|
||||||
// . . . . # .
|
// . . . . # .
|
||||||
// . . . # # .
|
// . . . # # .
|
||||||
@@ -139,7 +135,7 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
|||||||
// y represents the number of blanks
|
// y represents the number of blanks
|
||||||
// y starts from the top and increases in units of blocks
|
// y starts from the top and increases in units of blocks
|
||||||
|
|
||||||
// m_yscale looks similar to: { 0.7, 0.5, 0.25, 0.15, 0.1, 0 }
|
// yscale_ looks similar to: { 0.7, 0.5, 0.25, 0.15, 0.1, 0 }
|
||||||
// if it contains 6 elements there are 5 rows in the analyzer
|
// if it contains 6 elements there are 5 rows in the analyzer
|
||||||
|
|
||||||
if (!new_frame) {
|
if (!new_frame) {
|
||||||
@@ -149,50 +145,51 @@ void BlockAnalyzer::analyze(QPainter& p, const Analyzer::Scope& s,
|
|||||||
|
|
||||||
QPainter canvas_painter(&canvas_);
|
QPainter canvas_painter(&canvas_);
|
||||||
|
|
||||||
Analyzer::interpolate(s, m_scope);
|
Analyzer::interpolate(s, scope_);
|
||||||
|
|
||||||
// Paint the background
|
// Paint the background
|
||||||
canvas_painter.drawPixmap(0, 0, m_background);
|
canvas_painter.drawPixmap(0, 0, background_);
|
||||||
|
|
||||||
for (uint y, x = 0; x < m_scope.size(); ++x) {
|
for (uint y, x = 0; x < scope_.size(); ++x) {
|
||||||
// determine y
|
// determine y
|
||||||
for (y = 0; m_scope[x] < m_yscale[y]; ++y)
|
for (y = 0; scope_[x] < yscale_[y]; ++y) continue;
|
||||||
;
|
|
||||||
|
|
||||||
// this is opposite to what you'd think, higher than y means the bar is lower than y (physically)
|
// this is opposite to what you'd think, higher than y means the bar is lower than y (physically)
|
||||||
if ((float)y > m_store[x])
|
if ((float)y > store_[x])
|
||||||
y = int(m_store[x] += m_step);
|
y = int(store_[x] += step_);
|
||||||
else
|
else
|
||||||
m_store[x] = y;
|
store_[x] = y;
|
||||||
|
|
||||||
// if y is lower than m_fade_pos, then the bar has exceeded the height of the fadeout
|
// if y is lower than fade_pos_, then the bar has exceeded the height of the fadeout
|
||||||
// if the fadeout is quite faded now, then display the new one
|
// if the fadeout is quite faded now, then display the new one
|
||||||
if (y <= m_fade_pos[x] /*|| m_fade_intensity[x] < FADE_SIZE / 3*/) {
|
if (y <= fade_pos_[x] /*|| fade_intensity_[x] < FADE_SIZE / 3*/) {
|
||||||
m_fade_pos[x] = y;
|
fade_pos_[x] = y;
|
||||||
m_fade_intensity[x] = FADE_SIZE;
|
fade_intensity_[x] = FADE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fade_intensity[x] > 0) {
|
if (fade_intensity_[x] > 0) {
|
||||||
const uint offset = --m_fade_intensity[x];
|
const uint offset = --fade_intensity_[x];
|
||||||
const uint y = m_y + (m_fade_pos[x] * (HEIGHT + 1));
|
const uint y = y_ + (fade_pos_[x] * (HEIGHT + 1));
|
||||||
canvas_painter.drawPixmap(x * (WIDTH + 1), y, m_fade_bars[offset], 0, 0, WIDTH, height() - y);
|
canvas_painter.drawPixmap(x * (WIDTH + 1), y, fade_bars_[offset], 0, 0, WIDTH, height() - y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fade_intensity[x] == 0) m_fade_pos[x] = m_rows;
|
if (fade_intensity_[x] == 0) fade_pos_[x] = rows_;
|
||||||
|
|
||||||
// REMEMBER: y is a number from 0 to m_rows, 0 means all blocks are glowing, m_rows means none are
|
// REMEMBER: y is a number from 0 to rows_, 0 means all blocks are glowing, rows_ means none are
|
||||||
canvas_painter.drawPixmap(x * (WIDTH + 1), y * (HEIGHT + 1) + m_y, *bar(),
|
canvas_painter.drawPixmap(x * (WIDTH + 1), y * (HEIGHT + 1) + y_, *bar(),
|
||||||
0, y * (HEIGHT + 1), bar()->width(),
|
0, y * (HEIGHT + 1), bar()->width(),
|
||||||
bar()->height());
|
bar()->height());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint x = 0; x < m_store.size(); ++x)
|
for (uint x = 0; x < store_.size(); ++x)
|
||||||
canvas_painter.drawPixmap(x * (WIDTH + 1), int(m_store[x]) * (HEIGHT + 1) + m_y, m_topBarPixmap);
|
canvas_painter.drawPixmap(x * (WIDTH + 1), int(store_[x]) * (HEIGHT + 1) + y_, topbarpixmap_);
|
||||||
|
|
||||||
p.drawPixmap(0, 0, canvas_);
|
p.drawPixmap(0, 0, canvas_);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void adjustToLimits(int& b, int& f, uint& amount) {
|
static inline void adjustToLimits(int &b, int &f, uint &amount) {
|
||||||
|
|
||||||
// with a range of 0-255 and maximum adjustment of amount, maximise the difference between f and b
|
// with a range of 0-255 and maximum adjustment of amount, maximise the difference between f and b
|
||||||
|
|
||||||
if (b < f) {
|
if (b < f) {
|
||||||
@@ -215,6 +212,7 @@ static inline void adjustToLimits(int& b, int& f, uint& amount) {
|
|||||||
f = 255;
|
f = 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -225,17 +223,18 @@ static inline void adjustToLimits(int& b, int& f, uint& amount) {
|
|||||||
* It won't modify the hue of fg unless absolutely necessary
|
* It won't modify the hue of fg unless absolutely necessary
|
||||||
* @return the adjusted form of fg
|
* @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) {
|
||||||
|
|
||||||
class OutputOnExit {
|
class OutputOnExit {
|
||||||
public:
|
public:
|
||||||
OutputOnExit(const QColor& color) : c(color) {}
|
OutputOnExit(const QColor &color) : c(color) {}
|
||||||
~OutputOnExit() {
|
~OutputOnExit() {
|
||||||
int h, s, v;
|
int h, s, v;
|
||||||
c.getHsv(&h, &s, &v);
|
c.getHsv(&h, &s, &v);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const QColor& c;
|
const QColor &c;
|
||||||
};
|
};
|
||||||
|
|
||||||
// hack so I don't have to cast everywhere
|
// hack so I don't have to cast everywhere
|
||||||
@@ -352,24 +351,25 @@ QColor ensureContrast(const QColor& bg, const QColor& fg, uint _amount = 150) {
|
|||||||
|
|
||||||
#undef amount
|
#undef amount
|
||||||
// #undef STAMP
|
// #undef STAMP
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
void BlockAnalyzer::paletteChange(const QPalette&) {
|
||||||
{
|
|
||||||
const QColor bg = palette().color(QPalette::Background);
|
const QColor bg = palette().color(QPalette::Background);
|
||||||
const QColor fg = ensureContrast(bg, palette().color(QPalette::Highlight));
|
const QColor fg = ensureContrast(bg, palette().color(QPalette::Highlight));
|
||||||
|
|
||||||
m_topBarPixmap.fill(fg);
|
topbarpixmap_.fill(fg);
|
||||||
|
|
||||||
const double dr = 15 * double(bg.red() - fg.red()) / (m_rows * 16);
|
const double dr = 15 * double(bg.red() - fg.red()) / (rows_ * 16);
|
||||||
const double dg = 15 * double(bg.green() - fg.green()) / (m_rows * 16);
|
const double dg = 15 * double(bg.green() - fg.green()) / (rows_ * 16);
|
||||||
const double db = 15 * double(bg.blue() - fg.blue()) / (m_rows * 16);
|
const double db = 15 * double(bg.blue() - fg.blue()) / (rows_ * 16);
|
||||||
const int r = fg.red(), g = fg.green(), b = fg.blue();
|
const int r = fg.red(), g = fg.green(), b = fg.blue();
|
||||||
|
|
||||||
bar()->fill(bg);
|
bar()->fill(bg);
|
||||||
|
|
||||||
QPainter p(bar());
|
QPainter p(bar());
|
||||||
for (int y = 0; (uint)y < m_rows; ++y)
|
for (int y = 0; (uint)y < rows_; ++y)
|
||||||
// graduate the fg color
|
// graduate the fg color
|
||||||
p.fillRect(0, y * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * y), g + int(dg * y), b + int(db * y)));
|
p.fillRect(0, y * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * y), g + int(dg * y), b + int(db * y)));
|
||||||
|
|
||||||
@@ -389,9 +389,9 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
|||||||
|
|
||||||
// Precalculate all fade-bar pixmaps
|
// Precalculate all fade-bar pixmaps
|
||||||
for (uint y = 0; y < FADE_SIZE; ++y) {
|
for (uint y = 0; y < FADE_SIZE; ++y) {
|
||||||
m_fade_bars[y].fill(palette().color(QPalette::Background));
|
fade_bars_[y].fill(palette().color(QPalette::Background));
|
||||||
QPainter f(&m_fade_bars[y]);
|
QPainter f(&fade_bars_[y]);
|
||||||
for (int z = 0; (uint)z < m_rows; ++z) {
|
for (int z = 0; (uint)z < rows_; ++z) {
|
||||||
const double Y = 1.0 - (log10(FADE_SIZE - y) / log10(FADE_SIZE));
|
const double Y = 1.0 - (log10(FADE_SIZE - y) / log10(FADE_SIZE));
|
||||||
f.fillRect(0, z * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * Y), g + int(dg * Y), b + int(db * Y)));
|
f.fillRect(0, z * (HEIGHT + 1), WIDTH, HEIGHT, QColor(r + int(dr * Y), g + int(dg * Y), b + int(db * Y)));
|
||||||
}
|
}
|
||||||
@@ -399,16 +399,19 @@ void BlockAnalyzer::paletteChange(const QPalette&) // virtual
|
|||||||
}
|
}
|
||||||
|
|
||||||
drawBackground();
|
drawBackground();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockAnalyzer::drawBackground() {
|
void BlockAnalyzer::drawBackground() {
|
||||||
|
|
||||||
const QColor bg = palette().color(QPalette::Background);
|
const QColor bg = palette().color(QPalette::Background);
|
||||||
const QColor bgdark = bg.dark(112);
|
const QColor bgdark = bg.dark(112);
|
||||||
|
|
||||||
m_background.fill(bg);
|
background_.fill(bg);
|
||||||
|
|
||||||
|
QPainter p(&background_);
|
||||||
|
for (int x = 0; (uint)x < columns_; ++x)
|
||||||
|
for (int y = 0; (uint)y < rows_; ++y)
|
||||||
|
p.fillRect(x * (WIDTH + 1), y * (HEIGHT + 1) + y_, WIDTH, HEIGHT, bgdark);
|
||||||
|
|
||||||
QPainter p(&m_background);
|
|
||||||
for (int x = 0; (uint)x < m_columns; ++x)
|
|
||||||
for (int y = 0; (uint)y < m_rows; ++y)
|
|
||||||
p.fillRect(x * (WIDTH + 1), y * (HEIGHT + 1) + m_y, WIDTH, HEIGHT, bgdark);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,24 +51,24 @@ class BlockAnalyzer : public Analyzer::Base {
|
|||||||
void determineStep();
|
void determineStep();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QPixmap* bar() { return &m_barPixmap; }
|
QPixmap *bar() { return &barpixmap_; }
|
||||||
|
|
||||||
uint m_columns, m_rows; // number of rows and columns of blocks
|
uint columns_, rows_; // number of rows and columns of blocks
|
||||||
uint m_y; // y-offset from top of widget
|
uint y_; // y-offset from top of widget
|
||||||
QPixmap m_barPixmap;
|
QPixmap barpixmap_;
|
||||||
QPixmap m_topBarPixmap;
|
QPixmap topbarpixmap_;
|
||||||
QPixmap m_background;
|
QPixmap background_;
|
||||||
QPixmap canvas_;
|
QPixmap canvas_;
|
||||||
Analyzer::Scope m_scope; // so we don't create a vector every frame
|
Analyzer::Scope scope_; // so we don't create a vector every frame
|
||||||
std::vector<float> m_store; // current bar heights
|
std::vector<float> store_; // current bar heights
|
||||||
std::vector<float> m_yscale;
|
std::vector<float> yscale_;
|
||||||
|
|
||||||
// FIXME why can't I namespace these? c++ issue?
|
// FIXME why can't I namespace these? c++ issue?
|
||||||
std::vector<QPixmap> m_fade_bars;
|
std::vector<QPixmap> fade_bars_;
|
||||||
std::vector<uint> m_fade_pos;
|
std::vector<uint> fade_pos_;
|
||||||
std::vector<int> m_fade_intensity;
|
std::vector<int> fade_intensity_;
|
||||||
|
|
||||||
float m_step; // rows to fall per frame
|
float step_; // rows to fall per frame
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
@@ -61,6 +62,8 @@
|
|||||||
#include "playlist/songmimedata.h"
|
#include "playlist/songmimedata.h"
|
||||||
#include "covermanager/albumcoverloader.h"
|
#include "covermanager/albumcoverloader.h"
|
||||||
|
|
||||||
|
using std::bind;
|
||||||
|
using std::sort;
|
||||||
using std::placeholders::_1;
|
using std::placeholders::_1;
|
||||||
using std::placeholders::_2;
|
using std::placeholders::_2;
|
||||||
|
|
||||||
@@ -1312,7 +1315,7 @@ void CollectionModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls, Son
|
|||||||
const_cast<CollectionModel*>(this)->LazyPopulate(item);
|
const_cast<CollectionModel*>(this)->LazyPopulate(item);
|
||||||
|
|
||||||
QList<CollectionItem*> children = item->children;
|
QList<CollectionItem*> children = item->children;
|
||||||
qSort(children.begin(), children.end(), std::bind(&CollectionModel::CompareItems, this, _1, _2));
|
std::sort(children.begin(), children.end(), std::bind(&CollectionModel::CompareItems, this, _1, _2));
|
||||||
|
|
||||||
for (CollectionItem *child : children)
|
for (CollectionItem *child : children)
|
||||||
GetChildSongs(child, urls, songs, song_ids);
|
GetChildSongs(child, urls, songs, song_ids);
|
||||||
|
|||||||
@@ -68,8 +68,10 @@
|
|||||||
#include "collectionitem.h"
|
#include "collectionitem.h"
|
||||||
#include "collectionmodel.h"
|
#include "collectionmodel.h"
|
||||||
#include "collectionview.h"
|
#include "collectionview.h"
|
||||||
#include "device/devicemanager.h"
|
#ifndef Q_OS_WIN
|
||||||
#include "device/devicestatefiltermodel.h"
|
# include "device/devicemanager.h"
|
||||||
|
# include "device/devicestatefiltermodel.h"
|
||||||
|
#endif
|
||||||
#include "dialogs/edittagdialog.h"
|
#include "dialogs/edittagdialog.h"
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
#include "dialogs/organisedialog.h"
|
#include "dialogs/organisedialog.h"
|
||||||
@@ -460,7 +462,9 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
|
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
||||||
|
#endif
|
||||||
//delete_ = context_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(Delete()));
|
//delete_ = context_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(Delete()));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -477,7 +481,7 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
|
|
||||||
context_menu_->addMenu(filter_->menu());
|
context_menu_->addMenu(filter_->menu());
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
||||||
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool)));
|
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool)));
|
||||||
#endif
|
#endif
|
||||||
@@ -518,7 +522,9 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
// only when no smart playlists selected
|
// only when no smart playlists selected
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
organise_->setVisible(regular_elements_only);
|
organise_->setVisible(regular_elements_only);
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setVisible(regular_elements_only);
|
copy_to_device_->setVisible(regular_elements_only);
|
||||||
|
#endif
|
||||||
//delete_->setVisible(regular_elements_only);
|
//delete_->setVisible(regular_elements_only);
|
||||||
#endif
|
#endif
|
||||||
show_in_various_->setVisible(regular_elements_only);
|
show_in_various_->setVisible(regular_elements_only);
|
||||||
@@ -527,7 +533,9 @@ void CollectionView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
// only when all selected items are editable
|
// only when all selected items are editable
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
organise_->setEnabled(regular_elements == regular_editable);
|
organise_->setEnabled(regular_elements == regular_editable);
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
||||||
|
#endif
|
||||||
//delete_->setEnabled(regular_elements == regular_editable);
|
//delete_->setEnabled(regular_elements == regular_editable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -670,7 +678,7 @@ void CollectionView::EditTracks() {
|
|||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
void CollectionView::CopyToDevice() {
|
void CollectionView::CopyToDevice() {
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
if (!organise_dialog_)
|
if (!organise_dialog_)
|
||||||
organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
|
organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
|
||||||
|
|
||||||
@@ -678,7 +686,7 @@ void CollectionView::CopyToDevice() {
|
|||||||
organise_dialog_->SetCopy(true);
|
organise_dialog_->SetCopy(true);
|
||||||
organise_dialog_->SetSongs(GetSelectedSongs());
|
organise_dialog_->SetSongs(GetSelectedSongs());
|
||||||
organise_dialog_->show();
|
organise_dialog_->show();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,9 @@ signals:
|
|||||||
QAction *open_in_new_playlist_;
|
QAction *open_in_new_playlist_;
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
QAction *organise_;
|
QAction *organise_;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
QAction *copy_to_device_;
|
QAction *copy_to_device_;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
QAction *delete_;
|
QAction *delete_;
|
||||||
QAction *edit_track_;
|
QAction *edit_track_;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Collection advanced grouping</string>
|
<string>Collection advanced grouping</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
@@ -358,6 +358,7 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -106,6 +106,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -1,25 +1,30 @@
|
|||||||
/* This file is part of Strawberry.
|
/*
|
||||||
|
* Strawberry Music Player
|
||||||
Strawberry is free software: you can redistribute it and/or modify
|
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
it under the terms of the GNU General Public License as published by
|
*
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
(at your option) any later version.
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
Strawberry is distributed in the hope that it will be useful,
|
* (at your option) any later version.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
*
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* Strawberry is distributed in the hope that it will be useful,
|
||||||
GNU General Public License for more details.
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
You should have received a copy of the GNU General Public License
|
* GNU General Public License for more details.
|
||||||
along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
*
|
||||||
*/
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef CONFIG_H_IN
|
#ifndef CONFIG_H_IN
|
||||||
#define CONFIG_H_IN
|
#define CONFIG_H_IN
|
||||||
|
|
||||||
|
#define CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}"
|
||||||
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
#define CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||||
#define CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}"
|
#define CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}"
|
||||||
|
|
||||||
|
#cmakedefine DEBUG
|
||||||
#cmakedefine HAVE_GIO
|
#cmakedefine HAVE_GIO
|
||||||
#cmakedefine HAVE_DBUS
|
#cmakedefine HAVE_DBUS
|
||||||
#cmakedefine HAVE_X11
|
#cmakedefine HAVE_X11
|
||||||
@@ -38,6 +43,7 @@
|
|||||||
#cmakedefine HAVE_SPARKLE
|
#cmakedefine HAVE_SPARKLE
|
||||||
#cmakedefine HAVE_CHROMAPRINT
|
#cmakedefine HAVE_CHROMAPRINT
|
||||||
#cmakedefine HAVE_TAGLIB_DSFFILE
|
#cmakedefine HAVE_TAGLIB_DSFFILE
|
||||||
|
#cmakedefine HAVE_DZMEDIA
|
||||||
#cmakedefine IMOBILEDEVICE_USES_UDIDS
|
#cmakedefine IMOBILEDEVICE_USES_UDIDS
|
||||||
#cmakedefine USE_INSTALL_PREFIX
|
#cmakedefine USE_INSTALL_PREFIX
|
||||||
#cmakedefine USE_SYSTEM_SHA2
|
#cmakedefine USE_SYSTEM_SHA2
|
||||||
@@ -46,6 +52,10 @@
|
|||||||
#cmakedefine HAVE_VLC
|
#cmakedefine HAVE_VLC
|
||||||
#cmakedefine HAVE_XINE
|
#cmakedefine HAVE_XINE
|
||||||
#cmakedefine HAVE_PHONON
|
#cmakedefine HAVE_PHONON
|
||||||
|
#cmakedefine HAVE_DEEZER
|
||||||
|
|
||||||
|
#cmakedefine HAVE_STREAM_TIDAL
|
||||||
|
#cmakedefine HAVE_STREAM_DEEZER
|
||||||
|
|
||||||
#endif // CONFIG_H_IN
|
#endif // CONFIG_H_IN
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
@@ -55,6 +56,8 @@
|
|||||||
|
|
||||||
#include "contextalbumsmodel.h"
|
#include "contextalbumsmodel.h"
|
||||||
|
|
||||||
|
using std::bind;
|
||||||
|
using std::sort;
|
||||||
using std::placeholders::_1;
|
using std::placeholders::_1;
|
||||||
using std::placeholders::_2;
|
using std::placeholders::_2;
|
||||||
|
|
||||||
@@ -479,7 +482,7 @@ void ContextAlbumsModel::GetChildSongs(CollectionItem *item, QList<QUrl> *urls,
|
|||||||
const_cast<ContextAlbumsModel*>(this)->LazyPopulate(item);
|
const_cast<ContextAlbumsModel*>(this)->LazyPopulate(item);
|
||||||
|
|
||||||
QList<CollectionItem*> children = item->children;
|
QList<CollectionItem*> children = item->children;
|
||||||
qSort(children.begin(), children.end(), std::bind(&ContextAlbumsModel::CompareItems, this, _1, _2));
|
std::sort(children.begin(), children.end(), std::bind(&ContextAlbumsModel::CompareItems, this, _1, _2));
|
||||||
|
|
||||||
for (CollectionItem *child : children)
|
for (CollectionItem *child : children)
|
||||||
GetChildSongs(child, urls, songs, song_ids);
|
GetChildSongs(child, urls, songs, song_ids);
|
||||||
|
|||||||
@@ -66,9 +66,12 @@
|
|||||||
#include "core/utilities.h"
|
#include "core/utilities.h"
|
||||||
#include "collection/collectionbackend.h"
|
#include "collection/collectionbackend.h"
|
||||||
#include "collection/collectiondirectorymodel.h"
|
#include "collection/collectiondirectorymodel.h"
|
||||||
|
#include "collection/collectionmodel.h"
|
||||||
#include "collection/collectionitem.h"
|
#include "collection/collectionitem.h"
|
||||||
#include "device/devicemanager.h"
|
#ifndef Q_OS_WIN
|
||||||
#include "device/devicestatefiltermodel.h"
|
# include "device/devicemanager.h"
|
||||||
|
# include "device/devicestatefiltermodel.h"
|
||||||
|
#endif
|
||||||
#include "dialogs/edittagdialog.h"
|
#include "dialogs/edittagdialog.h"
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
#include "dialogs/organisedialog.h"
|
#include "dialogs/organisedialog.h"
|
||||||
@@ -264,9 +267,6 @@ void ContextAlbumsView::SaveFocus() {
|
|||||||
|
|
||||||
void ContextAlbumsView::SaveContainerPath(const QModelIndex &child) {
|
void ContextAlbumsView::SaveContainerPath(const QModelIndex &child) {
|
||||||
|
|
||||||
|
|
||||||
// return;
|
|
||||||
|
|
||||||
QModelIndex current = model()->parent(child);
|
QModelIndex current = model()->parent(child);
|
||||||
QVariant type = model()->data(current, ContextAlbumsModel::Role_Type);
|
QVariant type = model()->data(current, ContextAlbumsModel::Role_Type);
|
||||||
if (!type.isValid() || !(type.toInt() == CollectionItem::Type_Container || type.toInt() == CollectionItem::Type_Divider)) {
|
if (!type.isValid() || !(type.toInt() == CollectionItem::Type_Container || type.toInt() == CollectionItem::Type_Divider)) {
|
||||||
@@ -359,7 +359,6 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
|
|
||||||
if (!context_menu_) {
|
if (!context_menu_) {
|
||||||
context_menu_ = new QMenu(this);
|
context_menu_ = new QMenu(this);
|
||||||
//context_menu_->setStyleSheet("background-color: #3DADE8;");
|
|
||||||
|
|
||||||
add_to_playlist_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Append to current playlist"), this, SLOT(AddToPlaylist()));
|
add_to_playlist_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Append to current playlist"), this, SLOT(AddToPlaylist()));
|
||||||
load_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Replace current playlist"), this, SLOT(Load()));
|
load_ = context_menu_->addAction(IconLoader::Load("media-play"), tr("Replace current playlist"), this, SLOT(Load()));
|
||||||
@@ -371,7 +370,9 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
|
organise_ = context_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(Organise()));
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
copy_to_device_ = context_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(CopyToDevice()));
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
@@ -381,7 +382,7 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
|
|
||||||
context_menu_->addSeparator();
|
context_menu_->addSeparator();
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
||||||
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool)));
|
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), copy_to_device_, SLOT(setDisabled(bool)));
|
||||||
#endif
|
#endif
|
||||||
@@ -418,13 +419,17 @@ void ContextAlbumsView::contextMenuEvent(QContextMenuEvent *e) {
|
|||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
organise_->setVisible(regular_elements_only);
|
organise_->setVisible(regular_elements_only);
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setVisible(regular_elements_only);
|
copy_to_device_->setVisible(regular_elements_only);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// only when all selected items are editable
|
// only when all selected items are editable
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
organise_->setEnabled(regular_elements == regular_editable);
|
organise_->setEnabled(regular_elements == regular_editable);
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
copy_to_device_->setEnabled(regular_elements == regular_editable);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
context_menu_->popup(e->globalPos());
|
context_menu_->popup(e->globalPos());
|
||||||
@@ -509,7 +514,7 @@ void ContextAlbumsView::EditTracks() {
|
|||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
void ContextAlbumsView::CopyToDevice() {
|
void ContextAlbumsView::CopyToDevice() {
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
if (!organise_dialog_)
|
if (!organise_dialog_)
|
||||||
organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
|
organise_dialog_.reset(new OrganiseDialog(app_->task_manager()));
|
||||||
|
|
||||||
@@ -517,7 +522,7 @@ void ContextAlbumsView::CopyToDevice() {
|
|||||||
organise_dialog_->SetCopy(true);
|
organise_dialog_->SetCopy(true);
|
||||||
organise_dialog_->SetSongs(GetSelectedSongs());
|
organise_dialog_->SetSongs(GetSelectedSongs());
|
||||||
organise_dialog_->show();
|
organise_dialog_->show();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -103,7 +103,9 @@ signals:
|
|||||||
void OpenInNewPlaylist();
|
void OpenInNewPlaylist();
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
void Organise();
|
void Organise();
|
||||||
|
//#ifndef Q_OS_WIN
|
||||||
void CopyToDevice();
|
void CopyToDevice();
|
||||||
|
//#endif
|
||||||
#endif
|
#endif
|
||||||
void EditTracks();
|
void EditTracks();
|
||||||
void ShowInBrowser();
|
void ShowInBrowser();
|
||||||
@@ -124,7 +126,9 @@ signals:
|
|||||||
QAction *open_in_new_playlist_;
|
QAction *open_in_new_playlist_;
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
QAction *organise_;
|
QAction *organise_;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
QAction *copy_to_device_;
|
QAction *copy_to_device_;
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
QAction *delete_;
|
QAction *delete_;
|
||||||
QAction *edit_track_;
|
QAction *edit_track_;
|
||||||
|
|||||||
@@ -82,7 +82,8 @@ ContextView::ContextView(QWidget *parent) :
|
|||||||
timeline_fade_(new QTimeLine(1000, this)),
|
timeline_fade_(new QTimeLine(1000, this)),
|
||||||
image_strawberry_(":/pictures/strawberry.png"),
|
image_strawberry_(":/pictures/strawberry.png"),
|
||||||
active_(false),
|
active_(false),
|
||||||
downloading_covers_(false)
|
downloading_covers_(false),
|
||||||
|
lyrics_id_(-1)
|
||||||
{
|
{
|
||||||
|
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
@@ -173,10 +174,10 @@ void ContextView::Playing() {}
|
|||||||
void ContextView::Stopped() {
|
void ContextView::Stopped() {
|
||||||
|
|
||||||
active_ = false;
|
active_ = false;
|
||||||
song_playing_ = song_empty_;
|
song_playing_ = Song();
|
||||||
song_ = song_empty_;
|
song_ = Song();
|
||||||
downloading_covers_ = false;
|
downloading_covers_ = false;
|
||||||
prev_artist_ = QString();
|
song_prev_ = Song();
|
||||||
lyrics_ = QString();
|
lyrics_ = QString();
|
||||||
SetImage(image_strawberry_);
|
SetImage(image_strawberry_);
|
||||||
|
|
||||||
@@ -190,21 +191,40 @@ void ContextView::UpdateNoSong() {
|
|||||||
|
|
||||||
void ContextView::SongChanged(const Song &song) {
|
void ContextView::SongChanged(const Song &song) {
|
||||||
|
|
||||||
image_previous_ = image_original_;
|
if (song_playing_.is_valid() && song.id() == song_playing_.id() && song.url() == song_playing_.url()) {
|
||||||
prev_artist_ = song_playing_.artist();
|
UpdateSong(song);
|
||||||
lyrics_ = song.lyrics();
|
}
|
||||||
song_playing_ = song;
|
else {
|
||||||
song_ = song;
|
song_prev_ = song_playing_;
|
||||||
UpdateSong();
|
lyrics_ = song.lyrics();
|
||||||
update();
|
lyrics_id_ = -1;
|
||||||
if (action_show_lyrics_->isChecked()) lyrics_fetcher_->Search(song.artist(), song.album(), song.title());
|
song_playing_ = song;
|
||||||
|
song_ = song;
|
||||||
|
SetSong(song);
|
||||||
|
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked()) {
|
||||||
|
lyrics_fetcher_->Clear();
|
||||||
|
lyrics_id_ = lyrics_fetcher_->Search(song.artist(), song.album(), song.title());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextView::SetText(QLabel *label, int value, const QString &suffix, const QString &def) {
|
void ContextView::SetLabelEnabled(QLabel *label) {
|
||||||
|
label->setEnabled(true);
|
||||||
|
label->setVisible(true);
|
||||||
|
label->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ContextView::SetLabelText(QLabel *label, int value, const QString &suffix, const QString &def) {
|
||||||
label->setText(value <= 0 ? def : (QString::number(value) + " " + suffix));
|
label->setText(value <= 0 ? def : (QString::number(value) + " " + suffix));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContextView::SetLabelDisabled(QLabel *label) {
|
||||||
|
label->setEnabled(false);
|
||||||
|
label->setVisible(false);
|
||||||
|
label->setMaximumSize(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void ContextView::NoSong() {
|
void ContextView::NoSong() {
|
||||||
|
|
||||||
ui_->label_stop_top->setStyleSheet(
|
ui_->label_stop_top->setStyleSheet(
|
||||||
@@ -232,7 +252,7 @@ void ContextView::NoSong() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextView::UpdateSong() {
|
void ContextView::SetSong(const Song &song) {
|
||||||
|
|
||||||
QList <QLabel *> labels_play_data;
|
QList <QLabel *> labels_play_data;
|
||||||
|
|
||||||
@@ -251,85 +271,58 @@ void ContextView::UpdateSong() {
|
|||||||
"font: 11pt;"
|
"font: 11pt;"
|
||||||
"font-weight: regular;"
|
"font-weight: regular;"
|
||||||
);
|
);
|
||||||
ui_->label_play_top->setText( QString("<b>%1 - %2</b><br/>%3").arg(song_.PrettyTitle().toHtmlEscaped(), song_.artist().toHtmlEscaped(), song_.album().toHtmlEscaped()));
|
ui_->label_play_top->setText( QString("<b>%1 - %2</b><br/>%3").arg(song.PrettyTitle().toHtmlEscaped(), song.artist().toHtmlEscaped(), song.album().toHtmlEscaped()));
|
||||||
|
|
||||||
if (action_show_data_->isChecked()) {
|
if (action_show_data_->isChecked()) {
|
||||||
for (QLabel *l : labels_play_data) {
|
|
||||||
l->setEnabled(true);
|
|
||||||
l->setVisible(true);
|
|
||||||
l->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
|
||||||
}
|
|
||||||
ui_->layout_play_data->setEnabled(true);
|
ui_->layout_play_data->setEnabled(true);
|
||||||
ui_->filetype->setText(song_.TextForFiletype());
|
SetLabelEnabled(ui_->label_filetype);
|
||||||
ui_->length->setText(Utilities::PrettyTimeNanosec(song_.length_nanosec()));
|
SetLabelEnabled(ui_->filetype);
|
||||||
if (song_.samplerate() <= 0) {
|
SetLabelEnabled(ui_->label_length);
|
||||||
ui_->label_samplerate->setEnabled(false);
|
SetLabelEnabled(ui_->length);
|
||||||
ui_->label_samplerate->setVisible(false);
|
ui_->filetype->setText(song.TextForFiletype());
|
||||||
ui_->label_samplerate->setMaximumSize(0, 0);
|
ui_->length->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
|
||||||
ui_->samplerate->setEnabled(false);
|
if (song.samplerate() <= 0) {
|
||||||
ui_->samplerate->setVisible(false);
|
SetLabelDisabled(ui_->label_samplerate);
|
||||||
ui_->samplerate->setMaximumSize(0, 0);
|
SetLabelDisabled(ui_->samplerate);
|
||||||
ui_->samplerate->clear();
|
ui_->samplerate->clear();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ui_->label_samplerate->setEnabled(true);
|
SetLabelEnabled(ui_->label_samplerate);
|
||||||
ui_->label_samplerate->setVisible(true);
|
SetLabelEnabled(ui_->samplerate);
|
||||||
ui_->label_samplerate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
SetLabelText(ui_->samplerate, song.samplerate(), "Hz");
|
||||||
ui_->samplerate->setEnabled(true);
|
|
||||||
ui_->samplerate->setVisible(true);
|
|
||||||
ui_->samplerate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
|
||||||
SetText(ui_->samplerate, song_.samplerate(), "Hz");
|
|
||||||
}
|
}
|
||||||
if (song_.bitdepth() <= 0) {
|
if (song.bitdepth() <= 0) {
|
||||||
ui_->label_bitdepth->setEnabled(false);
|
SetLabelDisabled(ui_->label_bitdepth);
|
||||||
ui_->label_bitdepth->setVisible(false);
|
SetLabelDisabled(ui_->bitdepth);
|
||||||
ui_->label_bitdepth->setMaximumSize(0, 0);
|
|
||||||
ui_->bitdepth->setEnabled(false);
|
|
||||||
ui_->bitdepth->setVisible(false);
|
|
||||||
ui_->bitdepth->setMaximumSize(0, 0);
|
|
||||||
ui_->bitdepth->clear();
|
ui_->bitdepth->clear();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ui_->label_bitdepth->setEnabled(true);
|
SetLabelEnabled(ui_->label_bitdepth);
|
||||||
ui_->label_bitdepth->setVisible(true);
|
SetLabelEnabled(ui_->bitdepth);
|
||||||
ui_->label_bitdepth->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
SetLabelText(ui_->bitdepth, song.bitdepth(), "Bit");
|
||||||
ui_->bitdepth->setEnabled(true);
|
|
||||||
ui_->bitdepth->setVisible(true);
|
|
||||||
ui_->bitdepth->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
|
||||||
SetText(ui_->bitdepth, song_.bitdepth(), "Bit");
|
|
||||||
}
|
}
|
||||||
if (song_.bitrate() <= 0) {
|
if (song.bitrate() <= 0) {
|
||||||
ui_->label_bitrate->setEnabled(false);
|
SetLabelDisabled(ui_->label_bitrate);
|
||||||
ui_->label_bitrate->setVisible(false);
|
SetLabelDisabled(ui_->bitrate);
|
||||||
ui_->label_bitrate->setMaximumSize(0, 0);
|
|
||||||
ui_->bitrate->setEnabled(false);
|
|
||||||
ui_->bitrate->setVisible(false);
|
|
||||||
ui_->bitrate->setMaximumSize(0, 0);
|
|
||||||
ui_->bitrate->clear();
|
ui_->bitrate->clear();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ui_->label_bitrate->setEnabled(true);
|
SetLabelEnabled(ui_->label_bitrate);
|
||||||
ui_->label_bitrate->setVisible(true);
|
SetLabelEnabled(ui_->bitrate);
|
||||||
ui_->label_bitrate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
SetLabelText(ui_->bitrate, song.bitrate(), tr("kbps"));
|
||||||
ui_->bitrate->setEnabled(true);
|
|
||||||
ui_->bitrate->setVisible(true);
|
|
||||||
ui_->bitrate->setMaximumSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
|
||||||
SetText(ui_->bitrate, song_.bitrate(), tr("kbps"));
|
|
||||||
}
|
}
|
||||||
ui_->spacer_play_data->changeSize(20, 20, QSizePolicy::Fixed);
|
ui_->spacer_play_data->changeSize(20, 20, QSizePolicy::Fixed);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (QLabel *l : labels_play_data) {
|
|
||||||
l->setEnabled(false);
|
|
||||||
l->setVisible(false);
|
|
||||||
l->setMaximumSize(0, 0);
|
|
||||||
}
|
|
||||||
ui_->layout_play_data->setEnabled(false);
|
|
||||||
ui_->filetype->clear();
|
ui_->filetype->clear();
|
||||||
ui_->length->clear();
|
ui_->length->clear();
|
||||||
ui_->samplerate->clear();
|
ui_->samplerate->clear();
|
||||||
ui_->bitdepth->clear();
|
ui_->bitdepth->clear();
|
||||||
ui_->bitrate->clear();
|
ui_->bitrate->clear();
|
||||||
|
for (QLabel *l : labels_play_data) {
|
||||||
|
SetLabelDisabled(l);
|
||||||
|
}
|
||||||
|
ui_->layout_play_data->setEnabled(false);
|
||||||
ui_->spacer_play_data->changeSize(0, 0, QSizePolicy::Fixed);
|
ui_->spacer_play_data->changeSize(0, 0, QSizePolicy::Fixed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -403,18 +396,18 @@ void ContextView::UpdateSong() {
|
|||||||
ui_->device->setMaximumSize(0, 0);
|
ui_->device->setMaximumSize(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (action_show_albums_->isChecked() && prev_artist_ != song_.artist()) {
|
if (action_show_albums_->isChecked() && song_prev_.artist() != song.artist()) {
|
||||||
const QueryOptions opt;
|
const QueryOptions opt;
|
||||||
CollectionBackend::AlbumList albumlist;
|
CollectionBackend::AlbumList albumlist;
|
||||||
ui_->widget_play_albums->albums_model()->Reset();
|
ui_->widget_play_albums->albums_model()->Reset();
|
||||||
albumlist = app_->collection_backend()->GetAlbumsByArtist(song_.artist(), opt);
|
albumlist = app_->collection_backend()->GetAlbumsByArtist(song.artist(), opt);
|
||||||
if (albumlist.count() > 1) {
|
if (albumlist.count() > 1) {
|
||||||
ui_->label_play_albums->setVisible(true);
|
ui_->label_play_albums->setVisible(true);
|
||||||
ui_->label_play_albums->setMinimumSize(0, 20);
|
ui_->label_play_albums->setMinimumSize(0, 20);
|
||||||
ui_->label_play_albums->setText(QString("<b>Albums by %1</b>").arg( song_.artist().toHtmlEscaped()));
|
ui_->label_play_albums->setText(QString("<b>Albums by %1</b>").arg( song.artist().toHtmlEscaped()));
|
||||||
ui_->label_play_albums->setStyleSheet("background-color: #3DADE8; color: rgb(255, 255, 255); font: 11pt;");
|
ui_->label_play_albums->setStyleSheet("background-color: #3DADE8; color: rgb(255, 255, 255); font: 11pt;");
|
||||||
for (CollectionBackend::Album album : albumlist) {
|
for (CollectionBackend::Album album : albumlist) {
|
||||||
SongList songs = app_->collection_backend()->GetSongs(song_.artist(), album.album_name, opt);
|
SongList songs = app_->collection_backend()->GetSongs(song.artist(), album.album_name, opt);
|
||||||
ui_->widget_play_albums->albums_model()->AddSongs(songs);
|
ui_->widget_play_albums->albums_model()->AddSongs(songs);
|
||||||
}
|
}
|
||||||
ui_->widget_play_albums->setEnabled(true);
|
ui_->widget_play_albums->setEnabled(true);
|
||||||
@@ -454,9 +447,62 @@ void ContextView::UpdateSong() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ContextView::UpdateSong(const Song &song) {
|
||||||
|
|
||||||
|
if (song.artist() != song_playing_.artist() || song.album() != song_playing_.album() || song.title() != song_playing_.title()) {
|
||||||
|
ui_->label_play_top->setText( QString("<b>%1 - %2</b><br/>%3").arg(song.PrettyTitle().toHtmlEscaped(), song.artist().toHtmlEscaped(), song.album().toHtmlEscaped()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (action_show_data_->isChecked()) {
|
||||||
|
if (song.filetype() != song_playing_.filetype()) ui_->filetype->setText(song.TextForFiletype());
|
||||||
|
if (song.length_nanosec() != song_playing_.length_nanosec()) ui_->label_length->setText(Utilities::PrettyTimeNanosec(song.length_nanosec()));
|
||||||
|
if (song.samplerate() != song_playing_.samplerate()) {
|
||||||
|
if (song.samplerate() <= 0) {
|
||||||
|
SetLabelDisabled(ui_->label_samplerate);
|
||||||
|
SetLabelDisabled(ui_->samplerate);
|
||||||
|
ui_->samplerate->clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetLabelEnabled(ui_->label_samplerate);
|
||||||
|
SetLabelEnabled(ui_->samplerate);
|
||||||
|
SetLabelText(ui_->samplerate, song.samplerate(), "Hz");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (song.bitdepth() != song_playing_.bitdepth()) {
|
||||||
|
if (song.bitdepth() <= 0) {
|
||||||
|
SetLabelDisabled(ui_->label_bitdepth);
|
||||||
|
SetLabelDisabled(ui_->bitdepth);
|
||||||
|
ui_->bitdepth->clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetLabelEnabled(ui_->label_bitdepth);
|
||||||
|
SetLabelEnabled(ui_->bitdepth);
|
||||||
|
SetLabelText(ui_->bitdepth, song.bitdepth(), "Bit");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (song.bitrate() != song_playing_.bitrate()) {
|
||||||
|
if (song.bitrate() <= 0) {
|
||||||
|
SetLabelDisabled(ui_->label_bitrate);
|
||||||
|
SetLabelDisabled(ui_->bitrate);
|
||||||
|
ui_->bitrate->clear();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SetLabelEnabled(ui_->label_bitrate);
|
||||||
|
SetLabelEnabled(ui_->bitrate);
|
||||||
|
SetLabelText(ui_->bitrate, song.bitrate(), tr("kbps"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
song_playing_ = song;
|
||||||
|
song_ = song;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void ContextView::UpdateLyrics(quint64 id, const QString lyrics) {
|
void ContextView::UpdateLyrics(quint64 id, const QString lyrics) {
|
||||||
|
|
||||||
|
if (id != lyrics_id_) return;
|
||||||
lyrics_ = lyrics;
|
lyrics_ = lyrics;
|
||||||
|
lyrics_id_ = -1;
|
||||||
if (action_show_lyrics_->isChecked()) {
|
if (action_show_lyrics_->isChecked()) {
|
||||||
ui_->label_play_lyrics->setText(lyrics);
|
ui_->label_play_lyrics->setText(lyrics);
|
||||||
}
|
}
|
||||||
@@ -551,7 +597,9 @@ void ContextView::ScaleCover() {
|
|||||||
|
|
||||||
void ContextView::AlbumArtLoaded(const Song &song, const QString&, const QImage &image) {
|
void ContextView::AlbumArtLoaded(const Song &song, const QString&, const QImage &image) {
|
||||||
|
|
||||||
|
if (song.id() != song_playing_.id() || song.url() != song_playing_.url()) return;
|
||||||
if (song.effective_albumartist() != song_playing_.effective_albumartist() || song.effective_album() != song_playing_.effective_album() || song.title() != song_playing_.title()) return;
|
if (song.effective_albumartist() != song_playing_.effective_albumartist() || song.effective_album() != song_playing_.effective_album() || song.title() != song_playing_.title()) return;
|
||||||
|
if (image == image_original_) return;
|
||||||
|
|
||||||
active_ = true;
|
active_ = true;
|
||||||
downloading_covers_ = false;
|
downloading_covers_ = false;
|
||||||
@@ -572,6 +620,7 @@ void ContextView::SetImage(const QImage &image) {
|
|||||||
DrawImage(&p);
|
DrawImage(&p);
|
||||||
p.end();
|
p.end();
|
||||||
|
|
||||||
|
image_previous_ = image_original_;
|
||||||
image_original_ = image;
|
image_original_ = image;
|
||||||
|
|
||||||
ScaleCover();
|
ScaleCover();
|
||||||
@@ -623,7 +672,7 @@ void ContextView::ActionShowData() {
|
|||||||
s.beginGroup(kSettingsGroup);
|
s.beginGroup(kSettingsGroup);
|
||||||
s.setValue("show_data", action_show_data_->isChecked());
|
s.setValue("show_data", action_show_data_->isChecked());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
UpdateSong();
|
SetSong(song_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextView::ActionShowOutput() {
|
void ContextView::ActionShowOutput() {
|
||||||
@@ -631,7 +680,7 @@ void ContextView::ActionShowOutput() {
|
|||||||
s.beginGroup(kSettingsGroup);
|
s.beginGroup(kSettingsGroup);
|
||||||
s.setValue("show_output", action_show_output_->isChecked());
|
s.setValue("show_output", action_show_output_->isChecked());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
UpdateSong();
|
SetSong(song_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextView::ActionShowAlbums() {
|
void ContextView::ActionShowAlbums() {
|
||||||
@@ -639,8 +688,8 @@ void ContextView::ActionShowAlbums() {
|
|||||||
s.beginGroup(kSettingsGroup);
|
s.beginGroup(kSettingsGroup);
|
||||||
s.setValue("show_albums", action_show_albums_->isChecked());
|
s.setValue("show_albums", action_show_albums_->isChecked());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
prev_artist_ = QString();
|
song_prev_ = Song();
|
||||||
UpdateSong();
|
SetSong(song_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextView::ActionShowLyrics() {
|
void ContextView::ActionShowLyrics() {
|
||||||
@@ -648,8 +697,11 @@ void ContextView::ActionShowLyrics() {
|
|||||||
s.beginGroup(kSettingsGroup);
|
s.beginGroup(kSettingsGroup);
|
||||||
s.setValue("show_lyrics", action_show_lyrics_->isChecked());
|
s.setValue("show_lyrics", action_show_lyrics_->isChecked());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
UpdateSong();
|
SetSong(song_);
|
||||||
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked()) lyrics_fetcher_->Search(song_.artist(), song_.album(), song_.title());
|
if (lyrics_.isEmpty() && action_show_lyrics_->isChecked()) {
|
||||||
|
lyrics_fetcher_->Clear();
|
||||||
|
lyrics_id_ = lyrics_fetcher_->Search(song_.artist(), song_.album(), song_.title());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ContextView::SearchCoverAutomatically() {
|
void ContextView::SearchCoverAutomatically() {
|
||||||
|
|||||||
@@ -94,21 +94,23 @@ class ContextView : public QWidget {
|
|||||||
AlbumCoverLoaderOptions cover_loader_options_;
|
AlbumCoverLoaderOptions cover_loader_options_;
|
||||||
Song song_;
|
Song song_;
|
||||||
Song song_playing_;
|
Song song_playing_;
|
||||||
Song song_empty_;
|
Song song_prev_;
|
||||||
QImage image_original_;
|
QImage image_original_;
|
||||||
QImage image_previous_;
|
QImage image_previous_;
|
||||||
QPixmap pixmap_current_;
|
QPixmap pixmap_current_;
|
||||||
QPixmap pixmap_previous_;
|
QPixmap pixmap_previous_;
|
||||||
qreal pixmap_previous_opacity_;
|
qreal pixmap_previous_opacity_;
|
||||||
std::unique_ptr<QMovie> spinner_animation_;
|
std::unique_ptr<QMovie> spinner_animation_;
|
||||||
|
qint64 lyrics_id_;
|
||||||
QString prev_artist_;
|
|
||||||
QString lyrics_;
|
QString lyrics_;
|
||||||
|
|
||||||
void AddActions();
|
void AddActions();
|
||||||
void SetText(QLabel *label, int value, const QString &suffix, const QString &def = QString());
|
void SetLabelEnabled(QLabel *label);
|
||||||
|
void SetLabelDisabled(QLabel *label);
|
||||||
|
void SetLabelText(QLabel *label, int value, const QString &suffix, const QString &def = QString());
|
||||||
void NoSong();
|
void NoSong();
|
||||||
void UpdateSong();
|
void SetSong(const Song &song);
|
||||||
|
void UpdateSong(const Song &song);
|
||||||
void SetImage(const QImage &image);
|
void SetImage(const QImage &image);
|
||||||
void DrawImage(QPainter *p);
|
void DrawImage(QPainter *p);
|
||||||
void ScaleCover();
|
void ScaleCover();
|
||||||
|
|||||||
@@ -562,6 +562,7 @@
|
|||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
@@ -26,11 +26,13 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
|
#include <QVariant>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
|
||||||
#include "core/closure.h"
|
#include "core/closure.h"
|
||||||
#include "core/lazy.h"
|
#include "core/lazy.h"
|
||||||
#include "core/tagreaderclient.h"
|
#include "core/tagreaderclient.h"
|
||||||
|
#include "core/song.h"
|
||||||
|
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
#include "taskmanager.h"
|
#include "taskmanager.h"
|
||||||
@@ -38,7 +40,9 @@
|
|||||||
#include "appearance.h"
|
#include "appearance.h"
|
||||||
|
|
||||||
#include "engine/enginedevice.h"
|
#include "engine/enginedevice.h"
|
||||||
#include "device/devicemanager.h"
|
#ifndef Q_OS_WIN
|
||||||
|
# include "device/devicemanager.h"
|
||||||
|
#endif
|
||||||
#include "collection/collection.h"
|
#include "collection/collection.h"
|
||||||
#include "playlist/playlistbackend.h"
|
#include "playlist/playlistbackend.h"
|
||||||
#include "playlist/playlistmanager.h"
|
#include "playlist/playlistmanager.h"
|
||||||
@@ -48,7 +52,6 @@
|
|||||||
#ifdef HAVE_LIBLASTFM
|
#ifdef HAVE_LIBLASTFM
|
||||||
#include "covermanager/lastfmcoverprovider.h"
|
#include "covermanager/lastfmcoverprovider.h"
|
||||||
#endif
|
#endif
|
||||||
//#include "covermanager/amazoncoverprovider.h"
|
|
||||||
#include "covermanager/discogscoverprovider.h"
|
#include "covermanager/discogscoverprovider.h"
|
||||||
#include "covermanager/musicbrainzcoverprovider.h"
|
#include "covermanager/musicbrainzcoverprovider.h"
|
||||||
|
|
||||||
@@ -57,8 +60,15 @@
|
|||||||
#include "lyrics/auddlyricsprovider.h"
|
#include "lyrics/auddlyricsprovider.h"
|
||||||
#include "lyrics/apiseedslyricsprovider.h"
|
#include "lyrics/apiseedslyricsprovider.h"
|
||||||
|
|
||||||
#include "internet/internetmodel.h"
|
#include "internet/internetservices.h"
|
||||||
#include "tidal/tidalsearch.h"
|
#include "internet/internetsearch.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
# include "tidal/tidalservice.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
# include "deezer/deezerservice.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Application::kIsPortable = false;
|
bool Application::kIsPortable = false;
|
||||||
|
|
||||||
@@ -81,7 +91,9 @@ class ApplicationImpl {
|
|||||||
task_manager_([=]() { return new TaskManager(app); }),
|
task_manager_([=]() { return new TaskManager(app); }),
|
||||||
player_([=]() { return new Player(app, app); }),
|
player_([=]() { return new Player(app, app); }),
|
||||||
enginedevice_([=]() { return new EngineDevice(app); }),
|
enginedevice_([=]() { return new EngineDevice(app); }),
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
device_manager_([=]() { return new DeviceManager(app, app); }),
|
device_manager_([=]() { return new DeviceManager(app, app); }),
|
||||||
|
#endif
|
||||||
collection_([=]() { return new SCollection(app, app); }),
|
collection_([=]() { return new SCollection(app, app); }),
|
||||||
playlist_backend_([=]() {
|
playlist_backend_([=]() {
|
||||||
PlaylistBackend *backend = new PlaylistBackend(app, app);
|
PlaylistBackend *backend = new PlaylistBackend(app, app);
|
||||||
@@ -95,7 +107,6 @@ class ApplicationImpl {
|
|||||||
#ifdef HAVE_LIBLASTFM
|
#ifdef HAVE_LIBLASTFM
|
||||||
cover_providers->AddProvider(new LastFmCoverProvider(app));
|
cover_providers->AddProvider(new LastFmCoverProvider(app));
|
||||||
#endif
|
#endif
|
||||||
//cover_providers->AddProvider(new AmazonCoverProvider(app));
|
|
||||||
cover_providers->AddProvider(new DiscogsCoverProvider(app));
|
cover_providers->AddProvider(new DiscogsCoverProvider(app));
|
||||||
cover_providers->AddProvider(new MusicbrainzCoverProvider(app));
|
cover_providers->AddProvider(new MusicbrainzCoverProvider(app));
|
||||||
return cover_providers;
|
return cover_providers;
|
||||||
@@ -106,15 +117,30 @@ class ApplicationImpl {
|
|||||||
return loader;
|
return loader;
|
||||||
}),
|
}),
|
||||||
current_art_loader_([=]() { return new CurrentArtLoader(app, app); }),
|
current_art_loader_([=]() { return new CurrentArtLoader(app, app); }),
|
||||||
internet_model_([=]() { return new InternetModel(app, app); }),
|
|
||||||
tidal_search_([=]() { return new TidalSearch(app, app); }),
|
|
||||||
lyrics_providers_([=]() {
|
lyrics_providers_([=]() {
|
||||||
LyricsProviders *lyrics_providers = new LyricsProviders(app);
|
LyricsProviders *lyrics_providers = new LyricsProviders(app);
|
||||||
lyrics_providers->AddProvider(new AuddLyricsProvider(app));
|
lyrics_providers->AddProvider(new AuddLyricsProvider(app));
|
||||||
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
|
lyrics_providers->AddProvider(new APISeedsLyricsProvider(app));
|
||||||
return lyrics_providers;
|
return lyrics_providers;
|
||||||
})
|
}),
|
||||||
{ }
|
internet_services_([=]() {
|
||||||
|
InternetServices *internet_services = new InternetServices(app);
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
internet_services->AddService(new TidalService(app, internet_services));
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
internet_services->AddService(new DeezerService(app, internet_services));
|
||||||
|
#endif
|
||||||
|
return internet_services;
|
||||||
|
}),
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
tidal_search_([=]() { return new InternetSearch(app, Song::Source_Tidal, app); }),
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
deezer_search_([=]() { return new InternetSearch(app, Song::Source_Deezer, app); }),
|
||||||
|
#endif
|
||||||
|
dummy_([=]() { return new QVariant; })
|
||||||
|
{}
|
||||||
|
|
||||||
Lazy<TagReaderClient> tag_reader_client_;
|
Lazy<TagReaderClient> tag_reader_client_;
|
||||||
Lazy<Database> database_;
|
Lazy<Database> database_;
|
||||||
@@ -122,16 +148,24 @@ class ApplicationImpl {
|
|||||||
Lazy<TaskManager> task_manager_;
|
Lazy<TaskManager> task_manager_;
|
||||||
Lazy<Player> player_;
|
Lazy<Player> player_;
|
||||||
Lazy<EngineDevice> enginedevice_;
|
Lazy<EngineDevice> enginedevice_;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
Lazy<DeviceManager> device_manager_;
|
Lazy<DeviceManager> device_manager_;
|
||||||
|
#endif
|
||||||
Lazy<SCollection> collection_;
|
Lazy<SCollection> collection_;
|
||||||
Lazy<PlaylistBackend> playlist_backend_;
|
Lazy<PlaylistBackend> playlist_backend_;
|
||||||
Lazy<PlaylistManager> playlist_manager_;
|
Lazy<PlaylistManager> playlist_manager_;
|
||||||
Lazy<CoverProviders> cover_providers_;
|
Lazy<CoverProviders> cover_providers_;
|
||||||
Lazy<AlbumCoverLoader> album_cover_loader_;
|
Lazy<AlbumCoverLoader> album_cover_loader_;
|
||||||
Lazy<CurrentArtLoader> current_art_loader_;
|
Lazy<CurrentArtLoader> current_art_loader_;
|
||||||
Lazy<InternetModel> internet_model_;
|
|
||||||
Lazy<TidalSearch> tidal_search_;
|
|
||||||
Lazy<LyricsProviders> lyrics_providers_;
|
Lazy<LyricsProviders> lyrics_providers_;
|
||||||
|
Lazy<InternetServices> internet_services_;
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
Lazy<InternetSearch> tidal_search_;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
Lazy<InternetSearch> deezer_search_;
|
||||||
|
#endif
|
||||||
|
Lazy<QVariant> dummy_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -148,7 +182,9 @@ Application::~Application() {
|
|||||||
|
|
||||||
// It's important that the device manager is deleted before the database.
|
// It's important that the device manager is deleted before the database.
|
||||||
// Deleting the database deletes all objects that have been created in its thread, including some device collection backends.
|
// Deleting the database deletes all objects that have been created in its thread, including some device collection backends.
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
p_->device_manager_.reset();
|
p_->device_manager_.reset();
|
||||||
|
#endif
|
||||||
|
|
||||||
for (QThread *thread : threads_) {
|
for (QThread *thread : threads_) {
|
||||||
thread->quit();
|
thread->quit();
|
||||||
@@ -175,71 +211,31 @@ void Application::MoveToThread(QObject *object, QThread *thread) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::AddError(const QString& message) { emit ErrorAdded(message); }
|
void Application::AddError(const QString& message) { emit ErrorAdded(message); }
|
||||||
|
|
||||||
void Application::ReloadSettings() { emit SettingsChanged(); }
|
void Application::ReloadSettings() { emit SettingsChanged(); }
|
||||||
|
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) { emit SettingsDialogRequested(page); }
|
||||||
|
|
||||||
void Application::OpenSettingsDialogAtPage(SettingsDialog::Page page) {
|
TagReaderClient *Application::tag_reader_client() const { return p_->tag_reader_client_.get(); }
|
||||||
emit SettingsDialogRequested(page);
|
|
||||||
}
|
|
||||||
|
|
||||||
AlbumCoverLoader *Application::album_cover_loader() const {
|
|
||||||
return p_->album_cover_loader_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Appearance *Application::appearance() const { return p_->appearance_.get(); }
|
Appearance *Application::appearance() const { return p_->appearance_.get(); }
|
||||||
|
|
||||||
CoverProviders *Application::cover_providers() const {
|
|
||||||
return p_->cover_providers_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
CurrentArtLoader *Application::current_art_loader() const {
|
|
||||||
return p_->current_art_loader_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
Database *Application::database() const { return p_->database_.get(); }
|
Database *Application::database() const { return p_->database_.get(); }
|
||||||
|
TaskManager *Application::task_manager() const { return p_->task_manager_.get(); }
|
||||||
DeviceManager *Application::device_manager() const {
|
|
||||||
return p_->device_manager_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
SCollection *Application::collection() const { return p_->collection_.get(); }
|
|
||||||
|
|
||||||
CollectionBackend *Application::collection_backend() const {
|
|
||||||
return collection()->backend();
|
|
||||||
}
|
|
||||||
|
|
||||||
CollectionModel *Application::collection_model() const { return collection()->model(); }
|
|
||||||
|
|
||||||
Player *Application::player() const { return p_->player_.get(); }
|
Player *Application::player() const { return p_->player_.get(); }
|
||||||
|
EngineDevice *Application::enginedevice() const { return p_->enginedevice_.get(); }
|
||||||
PlaylistBackend *Application::playlist_backend() const {
|
#ifndef Q_OS_WIN
|
||||||
return p_->playlist_backend_.get();
|
DeviceManager *Application::device_manager() const { return p_->device_manager_.get(); }
|
||||||
}
|
#endif
|
||||||
|
SCollection *Application::collection() const { return p_->collection_.get(); }
|
||||||
PlaylistManager *Application::playlist_manager() const {
|
CollectionBackend *Application::collection_backend() const { return collection()->backend(); }
|
||||||
return p_->playlist_manager_.get();
|
CollectionModel *Application::collection_model() const { return collection()->model(); }
|
||||||
}
|
AlbumCoverLoader *Application::album_cover_loader() const { return p_->album_cover_loader_.get(); }
|
||||||
|
CoverProviders *Application::cover_providers() const { return p_->cover_providers_.get(); }
|
||||||
TagReaderClient *Application::tag_reader_client() const {
|
CurrentArtLoader *Application::current_art_loader() const { return p_->current_art_loader_.get(); }
|
||||||
return p_->tag_reader_client_.get();
|
LyricsProviders *Application::lyrics_providers() const { return p_->lyrics_providers_.get(); }
|
||||||
}
|
PlaylistBackend *Application::playlist_backend() const { return p_->playlist_backend_.get(); }
|
||||||
|
PlaylistManager *Application::playlist_manager() const { return p_->playlist_manager_.get(); }
|
||||||
TaskManager *Application::task_manager() const {
|
InternetServices *Application::internet_services() const { return p_->internet_services_.get(); }
|
||||||
return p_->task_manager_.get();
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
}
|
InternetSearch *Application::tidal_search() const { return p_->tidal_search_.get(); }
|
||||||
|
#endif
|
||||||
EngineDevice *Application::enginedevice() const {
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
return p_->enginedevice_.get();
|
InternetSearch *Application::deezer_search() const { return p_->deezer_search_.get(); }
|
||||||
}
|
#endif
|
||||||
|
|
||||||
InternetModel* Application::internet_model() const {
|
|
||||||
return p_->internet_model_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
TidalSearch* Application::tidal_search() const {
|
|
||||||
return p_->tidal_search_.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
LyricsProviders *Application::lyrics_providers() const {
|
|
||||||
return p_->lyrics_providers_.get();
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -33,6 +33,8 @@
|
|||||||
|
|
||||||
#include "settings/settingsdialog.h"
|
#include "settings/settingsdialog.h"
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
|
||||||
class TaskManager;
|
class TaskManager;
|
||||||
class ApplicationImpl;
|
class ApplicationImpl;
|
||||||
class TagReaderClient;
|
class TagReaderClient;
|
||||||
@@ -45,13 +47,15 @@ class CollectionBackend;
|
|||||||
class CollectionModel;
|
class CollectionModel;
|
||||||
class PlaylistBackend;
|
class PlaylistBackend;
|
||||||
class PlaylistManager;
|
class PlaylistManager;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
class DeviceManager;
|
class DeviceManager;
|
||||||
|
#endif
|
||||||
class CoverProviders;
|
class CoverProviders;
|
||||||
class AlbumCoverLoader;
|
class AlbumCoverLoader;
|
||||||
class CurrentArtLoader;
|
class CurrentArtLoader;
|
||||||
class InternetModel;
|
|
||||||
class TidalSearch;
|
|
||||||
class LyricsProviders;
|
class LyricsProviders;
|
||||||
|
class InternetServices;
|
||||||
|
class InternetSearch;
|
||||||
|
|
||||||
class Application : public QObject {
|
class Application : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -68,9 +72,13 @@ class Application : public QObject {
|
|||||||
TaskManager *task_manager() const;
|
TaskManager *task_manager() const;
|
||||||
Player *player() const;
|
Player *player() const;
|
||||||
EngineDevice *enginedevice() const;
|
EngineDevice *enginedevice() const;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
DeviceManager *device_manager() const;
|
DeviceManager *device_manager() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
SCollection *collection() const;
|
SCollection *collection() const;
|
||||||
|
CollectionBackend *collection_backend() const;
|
||||||
|
CollectionModel *collection_model() const;
|
||||||
|
|
||||||
PlaylistBackend *playlist_backend() const;
|
PlaylistBackend *playlist_backend() const;
|
||||||
PlaylistManager *playlist_manager() const;
|
PlaylistManager *playlist_manager() const;
|
||||||
@@ -79,14 +87,16 @@ class Application : public QObject {
|
|||||||
AlbumCoverLoader *album_cover_loader() const;
|
AlbumCoverLoader *album_cover_loader() const;
|
||||||
CurrentArtLoader *current_art_loader() const;
|
CurrentArtLoader *current_art_loader() const;
|
||||||
|
|
||||||
CollectionBackend *collection_backend() const;
|
|
||||||
CollectionModel *collection_model() const;
|
|
||||||
|
|
||||||
InternetModel *internet_model() const;
|
|
||||||
TidalSearch *tidal_search() const;
|
|
||||||
|
|
||||||
LyricsProviders *lyrics_providers() const;
|
LyricsProviders *lyrics_providers() const;
|
||||||
|
|
||||||
|
InternetServices *internet_services() const;
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
InternetSearch *tidal_search() const;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
InternetSearch *deezer_search() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
void MoveToNewThread(QObject *object);
|
void MoveToNewThread(QObject *object);
|
||||||
void MoveToThread(QObject *object, QThread *thread);
|
void MoveToThread(QObject *object, QThread *thread);
|
||||||
|
|
||||||
|
|||||||
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* Strawberry Music Player
|
|
||||||
* This file was part of Clementine.
|
|
||||||
* Copyright 2011, David Sansome <me@davidsansome.com>
|
|
||||||
*
|
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Strawberry is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CACHEDLIST_H
|
|
||||||
#define CACHEDLIST_H
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <QList>
|
|
||||||
#include <QString>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QSettings>
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
class CachedList {
|
|
||||||
public:
|
|
||||||
// Use a CachedList when you want to download and save a list of things from a
|
|
||||||
// remote service, updating it only periodically.
|
|
||||||
// T must be a registered metatype and must support being stored in
|
|
||||||
// QSettings. This usually means you have to implement QDataStream streaming
|
|
||||||
// operators, and use qRegisterMetaTypeStreamOperators.
|
|
||||||
|
|
||||||
typedef QList<T> ListType;
|
|
||||||
|
|
||||||
CachedList(const QString &settings_group, const QString &name, int cache_duration_secs)
|
|
||||||
: settings_group_(settings_group), name_(name), cache_duration_secs_(cache_duration_secs) {
|
|
||||||
}
|
|
||||||
|
|
||||||
void Load() {
|
|
||||||
QSettings s;
|
|
||||||
s.beginGroup(settings_group_);
|
|
||||||
|
|
||||||
last_updated_ = s.value("last_refreshed_" + name_).toDateTime();
|
|
||||||
data_.clear();
|
|
||||||
|
|
||||||
const int count = s.beginReadArray(name_ + "_data");
|
|
||||||
for (int i = 0; i < count; ++i) {
|
|
||||||
s.setArrayIndex(i);
|
|
||||||
data_ << s.value("value").value<T>();
|
|
||||||
}
|
|
||||||
s.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Save() const {
|
|
||||||
QSettings s;
|
|
||||||
s.beginGroup(settings_group_);
|
|
||||||
|
|
||||||
s.setValue("last_refreshed_" + name_, last_updated_);
|
|
||||||
|
|
||||||
s.beginWriteArray(name_ + "_data", data_.size());
|
|
||||||
for (int i = 0; i < data_.size(); ++i) {
|
|
||||||
s.setArrayIndex(i);
|
|
||||||
s.setValue("value", QVariant::fromValue(data_[i]));
|
|
||||||
}
|
|
||||||
s.endArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Update(const ListType &data) {
|
|
||||||
data_ = data;
|
|
||||||
last_updated_ = QDateTime::currentDateTime();
|
|
||||||
Save();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsStale() const {
|
|
||||||
return last_updated_.isNull() || last_updated_.secsTo(QDateTime::currentDateTime()) > cache_duration_secs_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Sort() { qSort(data_); }
|
|
||||||
|
|
||||||
const ListType &Data() const { return data_; }
|
|
||||||
operator ListType() const { return data_; }
|
|
||||||
|
|
||||||
// Q_FOREACH support
|
|
||||||
typedef typename ListType::const_iterator const_iterator;
|
|
||||||
const_iterator begin() const { return data_.begin(); }
|
|
||||||
const_iterator end() const { return data_.end(); }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const QString settings_group_;
|
|
||||||
const QString name_;
|
|
||||||
const int cache_duration_secs_;
|
|
||||||
|
|
||||||
QDateTime last_updated_;
|
|
||||||
ListType data_;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // CACHEDLIST_H
|
|
||||||
|
|
||||||
@@ -283,7 +283,11 @@ QSqlDatabase Database::Connect() {
|
|||||||
QVariant v = db.driver()->handle();
|
QVariant v = db.driver()->handle();
|
||||||
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
|
if (v.isValid() && qstrcmp(v.typeName(), "sqlite3*") == 0) {
|
||||||
sqlite3 *handle = *static_cast<sqlite3**>(v.data());
|
sqlite3 *handle = *static_cast<sqlite3**>(v.data());
|
||||||
if (handle) sqlite3_db_config(handle, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, NULL);
|
if (handle) {
|
||||||
|
int result = sqlite3_db_config(handle, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, 1, NULL);
|
||||||
|
if (result != SQLITE_OK) qLog(Fatal) << "Unable to enable FTS3 tokenizer";
|
||||||
|
}
|
||||||
|
else qLog(Fatal) << "Unable to enable FTS3 tokenizer";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
QSqlQuery set_fts_tokenizer(db);
|
QSqlQuery set_fts_tokenizer(db);
|
||||||
|
|||||||
@@ -58,6 +58,7 @@
|
|||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QLoggingCategory>
|
||||||
#include <QtDebug>
|
#include <QtDebug>
|
||||||
#ifdef HAVE_DBUS
|
#ifdef HAVE_DBUS
|
||||||
# include <QDBusArgument>
|
# include <QDBusArgument>
|
||||||
@@ -200,6 +201,11 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
// Resources
|
// Resources
|
||||||
Q_INIT_RESOURCE(data);
|
Q_INIT_RESOURCE(data);
|
||||||
|
Q_INIT_RESOURCE(icons);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
|
||||||
|
#endif
|
||||||
|
|
||||||
Application app;
|
Application app;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -29,6 +29,7 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
#include <QSortFilterProxyModel>
|
#include <QSortFilterProxyModel>
|
||||||
#include <QByteArray>
|
#include <QByteArray>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@@ -111,8 +112,8 @@
|
|||||||
#include "playlist/playlistmanager.h"
|
#include "playlist/playlistmanager.h"
|
||||||
#include "playlist/playlistsequence.h"
|
#include "playlist/playlistsequence.h"
|
||||||
#include "playlist/playlistview.h"
|
#include "playlist/playlistview.h"
|
||||||
#include "playlist/queue.h"
|
#include "queue/queue.h"
|
||||||
#include "playlist/queuemanager.h"
|
#include "queue/queueview.h"
|
||||||
#include "playlistparsers/playlistparser.h"
|
#include "playlistparsers/playlistparser.h"
|
||||||
#include "analyzer/analyzercontainer.h"
|
#include "analyzer/analyzercontainer.h"
|
||||||
#include "equalizer/equalizer.h"
|
#include "equalizer/equalizer.h"
|
||||||
@@ -121,17 +122,27 @@
|
|||||||
#include "covermanager/albumcoverchoicecontroller.h"
|
#include "covermanager/albumcoverchoicecontroller.h"
|
||||||
#include "covermanager/albumcoverloader.h"
|
#include "covermanager/albumcoverloader.h"
|
||||||
#include "covermanager/currentartloader.h"
|
#include "covermanager/currentartloader.h"
|
||||||
#include "device/devicemanager.h"
|
#ifndef Q_OS_WIN
|
||||||
#include "device/devicestatefiltermodel.h"
|
# include "device/devicemanager.h"
|
||||||
#include "device/deviceview.h"
|
# include "device/devicestatefiltermodel.h"
|
||||||
#include "device/deviceviewcontainer.h"
|
# include "device/deviceview.h"
|
||||||
|
# include "device/deviceviewcontainer.h"
|
||||||
|
#endif
|
||||||
#include "transcoder/transcodedialog.h"
|
#include "transcoder/transcodedialog.h"
|
||||||
|
#include "settings/settingsdialog.h"
|
||||||
#include "settings/behavioursettingspage.h"
|
#include "settings/behavioursettingspage.h"
|
||||||
#include "settings/playbacksettingspage.h"
|
#include "settings/playbacksettingspage.h"
|
||||||
#include "settings/playlistsettingspage.h"
|
#include "settings/playlistsettingspage.h"
|
||||||
#include "settings/settingsdialog.h"
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
# include "settings/tidalsettingspage.h"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
# include "settings/deezersettingspage.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tidal/tidalsearchview.h"
|
#include "internet/internetservices.h"
|
||||||
|
#include "internet/internetservice.h"
|
||||||
|
#include "internet/internetsearchview.h"
|
||||||
|
|
||||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||||
# include "musicbrainz/tagfetcher.h"
|
# include "musicbrainz/tagfetcher.h"
|
||||||
@@ -141,6 +152,10 @@
|
|||||||
# include "core/macsystemtrayicon.h"
|
# include "core/macsystemtrayicon.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
using std::bind;
|
||||||
|
using std::floor;
|
||||||
|
using std::stable_sort;
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
// Non exported mac-specific function.
|
// Non exported mac-specific function.
|
||||||
void qt_mac_set_dock_menu(QMenu*);
|
void qt_mac_set_dock_menu(QMenu*);
|
||||||
@@ -150,7 +165,7 @@ const char *MainWindow::kSettingsGroup = "MainWindow";
|
|||||||
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
const char *MainWindow::kAllFilesFilterSpec = QT_TR_NOOP("All Files (*)");
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
const int kTrackSliderUpdateTimeMs = 40;
|
const int kTrackSliderUpdateTimeMs = 200;
|
||||||
const int kTrackPositionUpdateTimeMs = 1000;
|
const int kTrackPositionUpdateTimeMs = 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,9 +182,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
context_view_(new ContextView(this)),
|
context_view_(new ContextView(this)),
|
||||||
collection_view_(new CollectionViewContainer(this)),
|
collection_view_(new CollectionViewContainer(this)),
|
||||||
file_view_(new FileView(this)),
|
file_view_(new FileView(this)),
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
device_view_container_(new DeviceViewContainer(this)),
|
device_view_container_(new DeviceViewContainer(this)),
|
||||||
device_view_(device_view_container_->view()),
|
device_view_(device_view_container_->view()),
|
||||||
|
#endif
|
||||||
playlist_list_(new PlaylistListContainer(this)),
|
playlist_list_(new PlaylistListContainer(this)),
|
||||||
|
queue_view_(new QueueView(this)),
|
||||||
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
|
settings_dialog_(std::bind(&MainWindow::CreateSettingsDialog, this)),
|
||||||
cover_manager_([=]() {
|
cover_manager_([=]() {
|
||||||
AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend());
|
AlbumCoverManager *cover_manager = new AlbumCoverManager(app, app->collection_backend());
|
||||||
@@ -189,12 +207,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
return dialog;
|
return dialog;
|
||||||
}),
|
}),
|
||||||
#endif
|
#endif
|
||||||
queue_manager_([=]() {
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
QueueManager *manager = new QueueManager;
|
tidal_search_view_(new InternetSearchView(app_, app_->tidal_search(), TidalSettingsPage::kSettingsGroup, SettingsDialog::Page_Tidal, this)),
|
||||||
manager->SetPlaylistManager(app->playlist_manager());
|
#endif
|
||||||
return manager;
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
}),
|
deezer_search_view_(new InternetSearchView(app_, app_->deezer_search(), DeezerSettingsPage::kSettingsGroup, SettingsDialog::Page_Deezer, this)),
|
||||||
tidal_search_view_(new TidalSearchView(app_, this)),
|
#endif
|
||||||
playlist_menu_(new QMenu(this)),
|
playlist_menu_(new QMenu(this)),
|
||||||
playlist_add_to_another_(nullptr),
|
playlist_add_to_another_(nullptr),
|
||||||
playlistitem_actions_separator_(nullptr),
|
playlistitem_actions_separator_(nullptr),
|
||||||
@@ -238,22 +256,29 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
ui_->volume->setValue(volume);
|
ui_->volume->setValue(volume);
|
||||||
VolumeChanged(volume);
|
VolumeChanged(volume);
|
||||||
|
|
||||||
// Initialise the tidal search widget
|
// Initialise the search widget
|
||||||
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
|
StyleHelper::setBaseColor(palette().color(QPalette::Highlight).darker());
|
||||||
|
|
||||||
// Add tabs to the fancy tab widget
|
// Add tabs to the fancy tab widget
|
||||||
ui_->tabs->addTab(context_view_, IconLoader::Load("strawberry"), tr("Context"));
|
ui_->tabs->addTab(context_view_, IconLoader::Load("strawberry"), "Context");
|
||||||
ui_->tabs->addTab(collection_view_, IconLoader::Load("vinyl"), tr("Collection"));
|
ui_->tabs->addTab(collection_view_, IconLoader::Load("vinyl"), "Collection");
|
||||||
ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), tr("Files"));
|
ui_->tabs->addTab(file_view_, IconLoader::Load("document-open"), "Files");
|
||||||
ui_->tabs->addTab(playlist_list_, IconLoader::Load("view-media-playlist"), tr("Playlists"));
|
ui_->tabs->addTab(playlist_list_, IconLoader::Load("view-media-playlist"), "Playlists");
|
||||||
ui_->tabs->addTab(device_view_, IconLoader::Load("device"), tr("Devices"));
|
ui_->tabs->addTab(queue_view_, IconLoader::Load("footsteps"), "Queue");
|
||||||
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), tr("Tidal", "Tidal"));
|
#ifndef Q_OS_WIN
|
||||||
//ui_->tabs->AddSpacer();
|
ui_->tabs->addTab(device_view_, IconLoader::Load("device"), "Devices");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), "Tidal");
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), "Deezer");
|
||||||
|
#endif
|
||||||
|
|
||||||
// Add the playing widget to the fancy tab widget
|
// Add the playing widget to the fancy tab widget
|
||||||
ui_->tabs->addBottomWidget(ui_->widget_playing);
|
ui_->tabs->addBottomWidget(ui_->widget_playing);
|
||||||
|
|
||||||
//ui_->tabs->SetBackgroundPixmap(QPixmap(":/pictures/strawberry-background.png"));
|
//ui_->tabs->SetBackgroundPixmap(QPixmap(":/pictures/strawberry-background.png"));
|
||||||
|
ui_->tabs->loadSettings(kSettingsGroup);
|
||||||
|
|
||||||
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
|
track_position_timer_->setInterval(kTrackPositionUpdateTimeMs);
|
||||||
connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition()));
|
connect(track_position_timer_, SIGNAL(timeout()), SLOT(UpdateTrackPosition()));
|
||||||
@@ -284,7 +309,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
|
|
||||||
collection_view_->view()->setModel(collection_sort_model_);
|
collection_view_->view()->setModel(collection_sort_model_);
|
||||||
collection_view_->view()->SetApplication(app_);
|
collection_view_->view()->SetApplication(app_);
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
device_view_->SetApplication(app_);
|
device_view_->SetApplication(app_);
|
||||||
|
#endif
|
||||||
playlist_list_->SetApplication(app_);
|
playlist_list_->SetApplication(app_);
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
@@ -330,7 +357,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
// Configure
|
// Configure
|
||||||
|
|
||||||
ui_->action_cover_manager->setIcon(IconLoader::Load("document-download"));
|
ui_->action_cover_manager->setIcon(IconLoader::Load("document-download"));
|
||||||
ui_->action_queue_manager->setIcon(IconLoader::Load("footsteps"));
|
|
||||||
ui_->action_edit_track->setIcon(IconLoader::Load("edit-rename"));
|
ui_->action_edit_track->setIcon(IconLoader::Load("edit-rename"));
|
||||||
ui_->action_equalizer->setIcon(IconLoader::Load("equalizer"));
|
ui_->action_equalizer->setIcon(IconLoader::Load("equalizer"));
|
||||||
ui_->action_update_collection->setIcon(IconLoader::Load("view-refresh"));
|
ui_->action_update_collection->setIcon(IconLoader::Load("view-refresh"));
|
||||||
@@ -344,7 +370,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
connect(file_view_, SIGNAL(CopyToCollection(QList<QUrl>)), SLOT(CopyFilesToCollection(QList<QUrl>)));
|
connect(file_view_, SIGNAL(CopyToCollection(QList<QUrl>)), SLOT(CopyFilesToCollection(QList<QUrl>)));
|
||||||
connect(file_view_, SIGNAL(MoveToCollection(QList<QUrl>)), SLOT(MoveFilesToCollection(QList<QUrl>)));
|
connect(file_view_, SIGNAL(MoveToCollection(QList<QUrl>)), SLOT(MoveFilesToCollection(QList<QUrl>)));
|
||||||
connect(file_view_, SIGNAL(EditTags(QList<QUrl>)), SLOT(EditFileTags(QList<QUrl>)));
|
connect(file_view_, SIGNAL(EditTags(QList<QUrl>)), SLOT(EditFileTags(QList<QUrl>)));
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
connect(file_view_, SIGNAL(CopyToDevice(QList<QUrl>)), SLOT(CopyFilesToDevice(QList<QUrl>)));
|
connect(file_view_, SIGNAL(CopyToDevice(QList<QUrl>)), SLOT(CopyFilesToDevice(QList<QUrl>)));
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
file_view_->SetTaskManager(app_->task_manager());
|
file_view_->SetTaskManager(app_->task_manager());
|
||||||
|
|
||||||
@@ -381,7 +409,6 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
connect(ui_->action_jump, SIGNAL(triggered()), ui_->playlist->view(), SLOT(JumpToCurrentlyPlayingTrack()));
|
connect(ui_->action_jump, SIGNAL(triggered()), ui_->playlist->view(), SLOT(JumpToCurrentlyPlayingTrack()));
|
||||||
connect(ui_->action_update_collection, SIGNAL(triggered()), app_->collection(), SLOT(IncrementalScan()));
|
connect(ui_->action_update_collection, SIGNAL(triggered()), app_->collection(), SLOT(IncrementalScan()));
|
||||||
connect(ui_->action_full_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(FullScan()));
|
connect(ui_->action_full_collection_scan, SIGNAL(triggered()), app_->collection(), SLOT(FullScan()));
|
||||||
connect(ui_->action_queue_manager, SIGNAL(triggered()), SLOT(ShowQueueManager()));
|
|
||||||
//connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()), SLOT(AddFilesToTranscoder()));
|
//connect(ui_->action_add_files_to_transcoder, SIGNAL(triggered()), SLOT(AddFilesToTranscoder()));
|
||||||
|
|
||||||
// Playlist view actions
|
// Playlist view actions
|
||||||
@@ -469,8 +496,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
connect(app_->task_manager(), SIGNAL(PauseCollectionWatchers()), app_->collection(), SLOT(PauseWatcher()));
|
connect(app_->task_manager(), SIGNAL(PauseCollectionWatchers()), app_->collection(), SLOT(PauseWatcher()));
|
||||||
connect(app_->task_manager(), SIGNAL(ResumeCollectionWatchers()), app_->collection(), SLOT(ResumeWatcher()));
|
connect(app_->task_manager(), SIGNAL(ResumeCollectionWatchers()), app_->collection(), SLOT(ResumeWatcher()));
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
// Devices connections
|
// Devices connections
|
||||||
connect(device_view_, SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
connect(device_view_, SIGNAL(AddToPlaylistSignal(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Collection filter widget
|
// Collection filter widget
|
||||||
QActionGroup *collection_view_group = new QActionGroup(this);
|
QActionGroup *collection_view_group = new QActionGroup(this);
|
||||||
@@ -500,8 +529,12 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
collection_view_->filter()->AddMenuAction(separator);
|
collection_view_->filter()->AddMenuAction(separator);
|
||||||
collection_view_->filter()->AddMenuAction(collection_config_action);
|
collection_view_->filter()->AddMenuAction(collection_config_action);
|
||||||
|
|
||||||
// Tidal
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
connect(tidal_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
connect(tidal_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
connect(deezer_search_view_, SIGNAL(AddToPlaylist(QMimeData*)), SLOT(AddToPlaylist(QMimeData*)));
|
||||||
|
#endif
|
||||||
|
|
||||||
// Playlist menu
|
// Playlist menu
|
||||||
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
|
playlist_play_pause_ = playlist_menu_->addAction(tr("Play"), this, SLOT(PlaylistPlay()));
|
||||||
@@ -529,7 +562,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
|
playlist_copy_to_collection_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Copy to collection..."), this, SLOT(PlaylistCopyToCollection()));
|
||||||
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
|
playlist_move_to_collection_ = playlist_menu_->addAction(IconLoader::Load("go-jump"), tr("Move to collection..."), this, SLOT(PlaylistMoveToCollection()));
|
||||||
//playlist_organise_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(PlaylistMoveToCollection()));
|
//playlist_organise_ = playlist_menu_->addAction(IconLoader::Load("edit-copy"), tr("Organise files..."), this, SLOT(PlaylistMoveToCollection()));
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice()));
|
playlist_copy_to_device_ = playlist_menu_->addAction(IconLoader::Load("device"), tr("Copy to device..."), this, SLOT(PlaylistCopyToDevice()));
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
//playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete()));
|
//playlist_delete_ = playlist_menu_->addAction(IconLoader::Load("edit-delete"), tr("Delete from disk..."), this, SLOT(PlaylistDelete()));
|
||||||
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
playlist_open_in_browser_ = playlist_menu_->addAction(IconLoader::Load("document-open-folder"), tr("Show in file browser..."), this, SLOT(PlaylistOpenInBrowser()));
|
||||||
@@ -551,7 +586,7 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
|
|
||||||
connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*, QAction*)), SLOT(PlaylistUndoRedoChanged(QAction*, QAction*)));
|
connect(ui_->playlist, SIGNAL(UndoRedoActionsChanged(QAction*, QAction*)), SLOT(PlaylistUndoRedoChanged(QAction*, QAction*)));
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
playlist_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
playlist_copy_to_device_->setDisabled(app_->device_manager()->connected_devices_model()->rowCount() == 0);
|
||||||
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), playlist_copy_to_device_, SLOT(setDisabled(bool)));
|
connect(app_->device_manager()->connected_devices_model(), SIGNAL(IsEmptyChanged(bool)), playlist_copy_to_device_, SLOT(setDisabled(bool)));
|
||||||
#endif
|
#endif
|
||||||
@@ -560,15 +595,16 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
mac::SetApplicationHandler(this);
|
mac::SetApplicationHandler(this);
|
||||||
#endif
|
#endif
|
||||||
// Tray icon
|
// Tray icon
|
||||||
tray_icon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause, ui_->action_stop, ui_->action_stop_after_this_track, ui_->action_next_track, ui_->action_mute, ui_->action_quit);
|
if (tray_icon_) {
|
||||||
|
tray_icon_->SetupMenu(ui_->action_previous_track, ui_->action_play_pause, ui_->action_stop, ui_->action_stop_after_this_track, ui_->action_next_track, ui_->action_mute, ui_->action_quit);
|
||||||
connect(tray_icon_, SIGNAL(PlayPause()), app_->player(), SLOT(PlayPause()));
|
connect(tray_icon_, SIGNAL(PlayPause()), app_->player(), SLOT(PlayPause()));
|
||||||
connect(tray_icon_, SIGNAL(SeekForward()), app_->player(), SLOT(SeekForward()));
|
connect(tray_icon_, SIGNAL(SeekForward()), app_->player(), SLOT(SeekForward()));
|
||||||
connect(tray_icon_, SIGNAL(SeekBackward()), app_->player(), SLOT(SeekBackward()));
|
connect(tray_icon_, SIGNAL(SeekBackward()), app_->player(), SLOT(SeekBackward()));
|
||||||
connect(tray_icon_, SIGNAL(NextTrack()), app_->player(), SLOT(Next()));
|
connect(tray_icon_, SIGNAL(NextTrack()), app_->player(), SLOT(Next()));
|
||||||
connect(tray_icon_, SIGNAL(PreviousTrack()), app_->player(), SLOT(Previous()));
|
connect(tray_icon_, SIGNAL(PreviousTrack()), app_->player(), SLOT(Previous()));
|
||||||
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
|
connect(tray_icon_, SIGNAL(ShowHide()), SLOT(ToggleShowHide()));
|
||||||
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
|
connect(tray_icon_, SIGNAL(ChangeVolume(int)), SLOT(VolumeWheelEvent(int)));
|
||||||
|
}
|
||||||
|
|
||||||
// Windows 7 thumbbar buttons
|
// Windows 7 thumbbar buttons
|
||||||
thumbbar_->SetActions(QList<QAction*>() << ui_->action_previous_track << ui_->action_play_pause << ui_->action_stop << ui_->action_next_track << nullptr); // spacer
|
thumbbar_->SetActions(QList<QAction*>() << ui_->action_previous_track << ui_->action_play_pause << ui_->action_stop << ui_->action_next_track << nullptr); // spacer
|
||||||
@@ -658,6 +694,8 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
// Load playlists
|
// Load playlists
|
||||||
app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist);
|
app_->playlist_manager()->Init(app_->collection_backend(), app_->playlist_backend(), ui_->playlist_sequence, ui_->playlist);
|
||||||
|
|
||||||
|
queue_view_->SetPlaylistManager(app_->playlist_manager());
|
||||||
|
|
||||||
// This connection must be done after the playlists have been initialized.
|
// This connection must be done after the playlists have been initialized.
|
||||||
connect(this, SIGNAL(StopAfterToggled(bool)), osd_, SLOT(StopAfterToggle(bool)));
|
connect(this, SIGNAL(StopAfterToggled(bool)), osd_, SLOT(StopAfterToggle(bool)));
|
||||||
|
|
||||||
@@ -684,7 +722,10 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
|
|
||||||
ui_->tabs->setCurrentIndex(settings_.value("current_tab", 1 /* Collection tab */ ).toInt());
|
ui_->tabs->setCurrentIndex(settings_.value("current_tab", 1 /* Collection tab */ ).toInt());
|
||||||
FancyTabWidget::Mode default_mode = FancyTabWidget::Mode_LargeSidebar;
|
FancyTabWidget::Mode default_mode = FancyTabWidget::Mode_LargeSidebar;
|
||||||
ui_->tabs->SetMode(FancyTabWidget::Mode(settings_.value("tab_mode", default_mode).toInt()));
|
int tab_mode_int = settings_.value("tab_mode", default_mode).toInt();
|
||||||
|
FancyTabWidget::Mode tab_mode = FancyTabWidget::Mode(tab_mode_int);
|
||||||
|
if (tab_mode == FancyTabWidget::Mode_None) tab_mode = default_mode;
|
||||||
|
ui_->tabs->SetMode(tab_mode);
|
||||||
file_view_->SetPath(settings_.value("file_path", QDir::homePath()).toString());
|
file_view_->SetPath(settings_.value("file_path", QDir::homePath()).toString());
|
||||||
|
|
||||||
TabSwitched();
|
TabSwitched();
|
||||||
@@ -694,43 +735,38 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
|
|
||||||
ReloadSettings();
|
ReloadSettings();
|
||||||
|
|
||||||
// Tidal search shortcut
|
|
||||||
QAction *tidal_search_action = new QAction(this);
|
|
||||||
tidal_search_action->setShortcuts(QList<QKeySequence>() << QKeySequence("Ctrl+F") << QKeySequence("Ctrl+L"));
|
|
||||||
addAction(tidal_search_action);
|
|
||||||
connect(tidal_search_action, SIGNAL(triggered()), SLOT(FocusTidalSearchField()));
|
|
||||||
|
|
||||||
// Reload pretty OSD to avoid issues with fonts
|
// Reload pretty OSD to avoid issues with fonts
|
||||||
osd_->ReloadPrettyOSDSettings();
|
osd_->ReloadPrettyOSDSettings();
|
||||||
|
|
||||||
// Reload playlist settings, for BG and glowing
|
// Reload playlist settings, for BG and glowing
|
||||||
ui_->playlist->view()->ReloadSettings();
|
ui_->playlist->view()->ReloadSettings();
|
||||||
|
|
||||||
|
#ifdef Q_OS_MACOS // Always show mainwindow on startup if on macos
|
||||||
#ifndef Q_OS_MACOS
|
show();
|
||||||
|
#else
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||||
StartupBehaviour behaviour = StartupBehaviour(settings.value("startupbehaviour", Startup_Remember).toInt());
|
StartupBehaviour behaviour = StartupBehaviour(settings.value("startupbehaviour", Startup_Remember).toInt());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
bool hidden = settings_.value("hidden", false).toBool();
|
bool hidden = settings_.value("hidden", false).toBool();
|
||||||
|
if (hidden && (!QSystemTrayIcon::isSystemTrayAvailable() || !tray_icon_ || !tray_icon_->IsVisible())) {
|
||||||
|
hidden = false;
|
||||||
switch (behaviour) {
|
|
||||||
case Startup_AlwaysHide: hide(); break;
|
|
||||||
case Startup_AlwaysShow: show(); break;
|
|
||||||
case Startup_Remember:
|
|
||||||
setVisible(!hidden);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Force the window to show in case somehow the config has tray and window set to hide
|
|
||||||
if (hidden && !tray_icon_->IsVisible()) {
|
|
||||||
settings_.setValue("hidden", false);
|
settings_.setValue("hidden", false);
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
#else // Q_OS_MACOS
|
else {
|
||||||
// Always show mainwindow on startup on OS X.
|
switch (behaviour) {
|
||||||
show();
|
case Startup_AlwaysHide:
|
||||||
|
hide();
|
||||||
|
break;
|
||||||
|
case Startup_AlwaysShow:
|
||||||
|
show();
|
||||||
|
break;
|
||||||
|
case Startup_Remember:
|
||||||
|
setVisible(!hidden);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QShortcut *close_window_shortcut = new QShortcut(this);
|
QShortcut *close_window_shortcut = new QShortcut(this);
|
||||||
@@ -743,9 +779,9 @@ MainWindow::MainWindow(Application *app, SystemTrayIcon *tray_icon, OSD *osd, co
|
|||||||
|
|
||||||
if (!options.contains_play_options()) LoadPlaybackStatus();
|
if (!options.contains_play_options()) LoadPlaybackStatus();
|
||||||
|
|
||||||
qLog(Debug) << "Started";
|
|
||||||
RefreshStyleSheet();
|
RefreshStyleSheet();
|
||||||
|
|
||||||
|
qLog(Debug) << "Started";
|
||||||
initialised_ = true;
|
initialised_ = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -760,16 +796,14 @@ void MainWindow::ReloadSettings() {
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
|
|
||||||
#ifndef Q_OS_MACOS
|
#ifndef Q_OS_MACOS
|
||||||
|
|
||||||
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||||
bool showtrayicon = settings.value("showtrayicon", true).toBool();
|
bool showtrayicon = settings.value("showtrayicon", QSystemTrayIcon::isSystemTrayAvailable()).toBool();
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
if (tray_icon_) tray_icon_->SetVisible(showtrayicon);
|
||||||
tray_icon_->SetVisible(showtrayicon);
|
if ((!showtrayicon || !QSystemTrayIcon::isSystemTrayAvailable()) && !isVisible()) show();
|
||||||
if (!showtrayicon && !isVisible()) show();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
settings.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
settings.beginGroup(BehaviourSettingsPage::kSettingsGroup);
|
||||||
doubleclick_addmode_ = AddBehaviour(settings.value("doubleclick_addmode", AddBehaviour_Append).toInt());
|
doubleclick_addmode_ = AddBehaviour(settings.value("doubleclick_addmode", AddBehaviour_Append).toInt());
|
||||||
doubleclick_playmode_ = PlayBehaviour(settings.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt());
|
doubleclick_playmode_ = PlayBehaviour(settings.value("doubleclick_playmode", PlayBehaviour_IfStopped).toInt());
|
||||||
doubleclick_playlist_addmode_ = PlaylistAddBehaviour(settings.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play).toInt());
|
doubleclick_playlist_addmode_ = PlaylistAddBehaviour(settings.value("doubleclick_playlist_addmode", PlaylistAddBehaviour_Play).toInt());
|
||||||
@@ -780,6 +814,26 @@ void MainWindow::ReloadSettings() {
|
|||||||
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings.value("search_for_cover_auto", true).toBool());
|
album_cover_choice_controller_->search_cover_auto_action()->setChecked(settings.value("search_for_cover_auto", true).toBool());
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
|
settings.beginGroup(TidalSettingsPage::kSettingsGroup);
|
||||||
|
bool enable_tidal = settings.value("enabled", false).toBool();
|
||||||
|
settings.endGroup();
|
||||||
|
if (enable_tidal)
|
||||||
|
ui_->tabs->addTab(tidal_search_view_, IconLoader::Load("tidal"), "Tidal");
|
||||||
|
else
|
||||||
|
ui_->tabs->delTab("Tidal");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
settings.beginGroup(DeezerSettingsPage::kSettingsGroup);
|
||||||
|
bool enable_deezer = settings.value("enabled", false).toBool();
|
||||||
|
settings.endGroup();
|
||||||
|
if (enable_deezer)
|
||||||
|
ui_->tabs->addTab(deezer_search_view_, IconLoader::Load("deezer"), "Deezer");
|
||||||
|
else
|
||||||
|
ui_->tabs->delTab("Deezer");
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::ReloadAllSettings() {
|
void MainWindow::ReloadAllSettings() {
|
||||||
@@ -793,13 +847,21 @@ void MainWindow::ReloadAllSettings() {
|
|||||||
osd_->ReloadSettings();
|
osd_->ReloadSettings();
|
||||||
collection_view_->ReloadSettings();
|
collection_view_->ReloadSettings();
|
||||||
ui_->playlist->view()->ReloadSettings();
|
ui_->playlist->view()->ReloadSettings();
|
||||||
|
#ifdef HAVE_STREAM_TIDAL
|
||||||
tidal_search_view_->ReloadSettings();
|
tidal_search_view_->ReloadSettings();
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_STREAM_DEEZER
|
||||||
|
deezer_search_view_->ReloadSettings();
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::RefreshStyleSheet() {
|
void MainWindow::RefreshStyleSheet() {
|
||||||
setStyleSheet(styleSheet());
|
QString contents(styleSheet());
|
||||||
|
setStyleSheet("");
|
||||||
|
setStyleSheet(contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::MediaStopped() {
|
void MainWindow::MediaStopped() {
|
||||||
|
|
||||||
setWindowTitle("Strawberry Music Player");
|
setWindowTitle("Strawberry Music Player");
|
||||||
@@ -814,11 +876,13 @@ void MainWindow::MediaStopped() {
|
|||||||
track_position_timer_->stop();
|
track_position_timer_->stop();
|
||||||
track_slider_timer_->stop();
|
track_slider_timer_->stop();
|
||||||
ui_->track_slider->SetStopped();
|
ui_->track_slider->SetStopped();
|
||||||
tray_icon_->SetProgress(0);
|
if (tray_icon_) {
|
||||||
tray_icon_->SetStopped();
|
tray_icon_->SetProgress(0);
|
||||||
|
tray_icon_->SetStopped();
|
||||||
|
}
|
||||||
|
|
||||||
song_playing_ = song_empty_;
|
song_playing_ = Song();
|
||||||
song_ = song_empty_;
|
song_ = Song();
|
||||||
image_original_ = QImage();
|
image_original_ = QImage();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -835,7 +899,7 @@ void MainWindow::MediaPaused() {
|
|||||||
track_position_timer_->stop();
|
track_position_timer_->stop();
|
||||||
track_slider_timer_->stop();
|
track_slider_timer_->stop();
|
||||||
|
|
||||||
tray_icon_->SetPaused();
|
if (tray_icon_) tray_icon_->SetPaused();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,13 +910,15 @@ void MainWindow::MediaPlaying() {
|
|||||||
ui_->action_play_pause->setIcon(IconLoader::Load("media-pause"));
|
ui_->action_play_pause->setIcon(IconLoader::Load("media-pause"));
|
||||||
ui_->action_play_pause->setText(tr("Pause"));
|
ui_->action_play_pause->setText(tr("Pause"));
|
||||||
|
|
||||||
bool enable_play_pause = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::PauseDisabled);
|
bool enable_play_pause(false);
|
||||||
|
bool can_seek(false);
|
||||||
|
if (app_->player()->GetCurrentItem()) {
|
||||||
|
enable_play_pause = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::PauseDisabled);
|
||||||
|
can_seek = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::SeekDisabled);
|
||||||
|
}
|
||||||
ui_->action_play_pause->setEnabled(enable_play_pause);
|
ui_->action_play_pause->setEnabled(enable_play_pause);
|
||||||
|
|
||||||
bool can_seek = !(app_->player()->GetCurrentItem()->options() & PlaylistItem::SeekDisabled);
|
|
||||||
ui_->track_slider->SetCanSeek(can_seek);
|
ui_->track_slider->SetCanSeek(can_seek);
|
||||||
|
if (tray_icon_) tray_icon_->SetPlaying(enable_play_pause);
|
||||||
tray_icon_->SetPlaying(enable_play_pause);
|
|
||||||
|
|
||||||
track_position_timer_->start();
|
track_position_timer_->start();
|
||||||
track_slider_timer_->start();
|
track_slider_timer_->start();
|
||||||
@@ -862,7 +928,7 @@ void MainWindow::MediaPlaying() {
|
|||||||
|
|
||||||
void MainWindow::VolumeChanged(int volume) {
|
void MainWindow::VolumeChanged(int volume) {
|
||||||
ui_->action_mute->setChecked(!volume);
|
ui_->action_mute->setChecked(!volume);
|
||||||
tray_icon_->MuteButtonStateChanged(!volume);
|
if (tray_icon_) tray_icon_->MuteButtonStateChanged(!volume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SongChanged(const Song &song) {
|
void MainWindow::SongChanged(const Song &song) {
|
||||||
@@ -870,11 +936,12 @@ void MainWindow::SongChanged(const Song &song) {
|
|||||||
song_playing_ = song;
|
song_playing_ = song;
|
||||||
song_ = song;
|
song_ = song;
|
||||||
setWindowTitle(song.PrettyTitleWithArtist());
|
setWindowTitle(song.PrettyTitleWithArtist());
|
||||||
tray_icon_->SetProgress(0);
|
if (tray_icon_) tray_icon_->SetProgress(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
||||||
|
|
||||||
// If it was a collection item then we have to increment its skipped count in the database.
|
// If it was a collection item then we have to increment its skipped count in the database.
|
||||||
|
|
||||||
if (item && item->IsLocalCollectionItem() && item->Metadata().id() != -1) {
|
if (item && item->IsLocalCollectionItem() && item->Metadata().id() != -1) {
|
||||||
@@ -891,6 +958,7 @@ void MainWindow::TrackSkipped(PlaylistItemPtr item) {
|
|||||||
app_->collection_backend()->IncrementSkipCountAsync(song.id(), percentage);
|
app_->collection_backend()->IncrementSkipCountAsync(song.id(), percentage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::changeEvent(QEvent *event) {
|
void MainWindow::changeEvent(QEvent *event) {
|
||||||
@@ -899,16 +967,18 @@ void MainWindow::changeEvent(QEvent *event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::resizeEvent(QResizeEvent *event) {
|
void MainWindow::resizeEvent(QResizeEvent *event) {
|
||||||
|
if (!initialised_) return;
|
||||||
SaveGeometry();
|
SaveGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::TabSwitched() {
|
void MainWindow::TabSwitched() {
|
||||||
|
|
||||||
if (ui_->tabs->currentIndex() > 0)
|
if (ui_->tabs->tabBar()->tabData(ui_->tabs->currentIndex()).toString().toLower() == "context")
|
||||||
ui_->widget_playing->SetEnabled();
|
|
||||||
else
|
|
||||||
ui_->widget_playing->SetDisabled();
|
ui_->widget_playing->SetDisabled();
|
||||||
|
else
|
||||||
|
ui_->widget_playing->SetEnabled();
|
||||||
|
|
||||||
|
if (!initialised_) return;
|
||||||
SaveGeometry();
|
SaveGeometry();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -922,6 +992,7 @@ void MainWindow::SaveGeometry() {
|
|||||||
settings_.setValue("splitter_state", ui_->splitter->saveState());
|
settings_.setValue("splitter_state", ui_->splitter->saveState());
|
||||||
settings_.setValue("current_tab", ui_->tabs->currentIndex());
|
settings_.setValue("current_tab", ui_->tabs->currentIndex());
|
||||||
settings_.setValue("tab_mode", ui_->tabs->mode());
|
settings_.setValue("tab_mode", ui_->tabs->mode());
|
||||||
|
ui_->tabs->saveSettings(kSettingsGroup);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1064,7 +1135,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
|
|||||||
bool keep_running = settings.value("keeprunning", false).toBool();
|
bool keep_running = settings.value("keeprunning", false).toBool();
|
||||||
settings.endGroup();
|
settings.endGroup();
|
||||||
|
|
||||||
if (keep_running && event->spontaneous()) {
|
if (keep_running && event->spontaneous() && QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||||
event->ignore();
|
event->ignore();
|
||||||
SetHiddenInTray(true);
|
SetHiddenInTray(true);
|
||||||
}
|
}
|
||||||
@@ -1097,7 +1168,7 @@ void MainWindow::Seeked(qlonglong microseconds) {
|
|||||||
|
|
||||||
const int position = microseconds / kUsecPerSec;
|
const int position = microseconds / kUsecPerSec;
|
||||||
const int length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec;
|
const int length = app_->player()->GetCurrentItem()->Metadata().length_nanosec() / kNsecPerSec;
|
||||||
tray_icon_->SetProgress(double(position) / length * 100);
|
if (tray_icon_) tray_icon_->SetProgress(double(position) / length * 100);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1107,6 +1178,7 @@ void MainWindow::UpdateTrackPosition() {
|
|||||||
//Playlist *playlist = app_->playlist_manager()->active();
|
//Playlist *playlist = app_->playlist_manager()->active();
|
||||||
|
|
||||||
PlaylistItemPtr item(app_->player()->GetCurrentItem());
|
PlaylistItemPtr item(app_->player()->GetCurrentItem());
|
||||||
|
if (!item) return;
|
||||||
const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5);
|
const int position = std::floor(float(app_->player()->engine()->position_nanosec()) / kNsecPerSec + 0.5);
|
||||||
const int length = item->Metadata().length_nanosec() / kNsecPerSec;
|
const int length = item->Metadata().length_nanosec() / kNsecPerSec;
|
||||||
|
|
||||||
@@ -1118,9 +1190,8 @@ void MainWindow::UpdateTrackPosition() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Update the tray icon every 10 seconds
|
// Update the tray icon every 10 seconds
|
||||||
if (position % 10 == 0) {
|
if (position % 10 == 0 && tray_icon_) tray_icon_->SetProgress(double(position) / length * 100);
|
||||||
tray_icon_->SetProgress(double(position) / length * 100);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::UpdateTrackSliderPosition() {
|
void MainWindow::UpdateTrackSliderPosition() {
|
||||||
@@ -1324,14 +1395,12 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
playlist_copy_to_collection_->setVisible(false);
|
playlist_copy_to_collection_->setVisible(false);
|
||||||
playlist_move_to_collection_->setVisible(false);
|
playlist_move_to_collection_->setVisible(false);
|
||||||
//playlist_organise_->setVisible(false);
|
//playlist_organise_->setVisible(false);
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
playlist_copy_to_device_->setVisible(false);
|
playlist_copy_to_device_->setVisible(false);
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
playlist_open_in_browser_->setVisible(false);
|
playlist_open_in_browser_->setVisible(false);
|
||||||
|
|
||||||
//qLog(Debug) << "selected" << selected;
|
|
||||||
//qLog(Debug) << "in_queue" << in_queue << "not_in_queue" << not_in_queue;
|
|
||||||
//qLog(Debug) << "in_skipped" << in_skipped << "not_in_skipped" << not_in_skipped;
|
|
||||||
|
|
||||||
if (selected < 1) {
|
if (selected < 1) {
|
||||||
playlist_queue_->setVisible(false);
|
playlist_queue_->setVisible(false);
|
||||||
playlist_skip_->setVisible(false);
|
playlist_skip_->setVisible(false);
|
||||||
@@ -1393,7 +1462,7 @@ void MainWindow::PlaylistRightClick(const QPoint &global_pos, const QModelIndex
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#if defined(HAVE_GSTREAMER) && !defined(Q_OS_WIN)
|
||||||
playlist_copy_to_device_->setVisible(editable);
|
playlist_copy_to_device_->setVisible(editable);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1455,6 +1524,7 @@ void MainWindow::PlaylistStopAfter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::EditTracks() {
|
void MainWindow::EditTracks() {
|
||||||
|
|
||||||
SongList songs;
|
SongList songs;
|
||||||
PlaylistItemList items;
|
PlaylistItemList items;
|
||||||
|
|
||||||
@@ -1473,9 +1543,11 @@ void MainWindow::EditTracks() {
|
|||||||
//EnsureEditTagDialogCreated();
|
//EnsureEditTagDialogCreated();
|
||||||
edit_tag_dialog_->SetSongs(songs, items);
|
edit_tag_dialog_->SetSongs(songs, items);
|
||||||
edit_tag_dialog_->show();
|
edit_tag_dialog_->show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::EditTagDialogAccepted() {
|
void MainWindow::EditTagDialogAccepted() {
|
||||||
|
|
||||||
for (PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) {
|
for (PlaylistItemPtr item : edit_tag_dialog_->playlist_items()) {
|
||||||
item->Reload();
|
item->Reload();
|
||||||
}
|
}
|
||||||
@@ -1484,14 +1556,16 @@ void MainWindow::EditTagDialogAccepted() {
|
|||||||
ui_->playlist->view()->update();
|
ui_->playlist->view()->update();
|
||||||
|
|
||||||
app_->playlist_manager()->current()->Save();
|
app_->playlist_manager()->current()->Save();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::RenumberTracks() {
|
void MainWindow::RenumberTracks() {
|
||||||
|
|
||||||
QModelIndexList indexes =ui_->playlist->view()->selectionModel()->selection().indexes();
|
QModelIndexList indexes =ui_->playlist->view()->selectionModel()->selection().indexes();
|
||||||
int track = 1;
|
int track = 1;
|
||||||
|
|
||||||
// Get the index list in order
|
// Get the index list in order
|
||||||
qStableSort(indexes);
|
std::stable_sort(indexes.begin(), indexes.end());
|
||||||
|
|
||||||
// if first selected song has a track number set, start from that offset
|
// if first selected song has a track number set, start from that offset
|
||||||
if (!indexes.isEmpty()) {
|
if (!indexes.isEmpty()) {
|
||||||
@@ -1516,6 +1590,7 @@ void MainWindow::RenumberTracks() {
|
|||||||
}
|
}
|
||||||
track++;
|
track++;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIndex &index) {
|
void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIndex &index) {
|
||||||
@@ -1526,6 +1601,7 @@ void MainWindow::SongSaveComplete(TagReaderReply *reply,const QPersistentModelIn
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::SelectionSetValue() {
|
void MainWindow::SelectionSetValue() {
|
||||||
|
|
||||||
Playlist::Column column = (Playlist::Column)playlist_menu_index_.column();
|
Playlist::Column column = (Playlist::Column)playlist_menu_index_.column();
|
||||||
QVariant column_value =app_->playlist_manager()->current()->data(playlist_menu_index_);
|
QVariant column_value =app_->playlist_manager()->current()->data(playlist_menu_index_);
|
||||||
|
|
||||||
@@ -1544,9 +1620,11 @@ void MainWindow::SelectionSetValue() {
|
|||||||
NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index));
|
NewClosure(reply, SIGNAL(Finished(bool)), this, SLOT(SongSaveComplete(TagReaderReply*, QPersistentModelIndex)),reply, QPersistentModelIndex(source_index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::EditValue() {
|
void MainWindow::EditValue() {
|
||||||
|
|
||||||
QModelIndex current = ui_->playlist->view()->currentIndex();
|
QModelIndex current = ui_->playlist->view()->currentIndex();
|
||||||
|
|
||||||
if (!current.isValid()) return;
|
if (!current.isValid()) return;
|
||||||
@@ -1589,9 +1667,11 @@ void MainWindow::AddFile() {
|
|||||||
MimeData *data = new MimeData;
|
MimeData *data = new MimeData;
|
||||||
data->setUrls(urls);
|
data->setUrls(urls);
|
||||||
AddToPlaylist(data);
|
AddToPlaylist(data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::AddFolder() {
|
void MainWindow::AddFolder() {
|
||||||
|
|
||||||
// Last used directory
|
// Last used directory
|
||||||
QString directory =settings_.value("add_folder_path", QDir::currentPath()).toString();
|
QString directory =settings_.value("add_folder_path", QDir::currentPath()).toString();
|
||||||
|
|
||||||
@@ -1606,6 +1686,7 @@ void MainWindow::AddFolder() {
|
|||||||
MimeData *data = new MimeData;
|
MimeData *data = new MimeData;
|
||||||
data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath()));
|
data->setUrls(QList<QUrl>() << QUrl::fromLocalFile(QFileInfo(directory).canonicalFilePath()));
|
||||||
AddToPlaylist(data);
|
AddToPlaylist(data);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::AddCDTracks() {
|
void MainWindow::AddCDTracks() {
|
||||||
@@ -1830,6 +1911,7 @@ void MainWindow::MoveFilesToCollection(const QList<QUrl> &urls) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
|
void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
organise_dialog_->SetDestinationModel(app_->device_manager()->connected_devices_model(), true);
|
||||||
organise_dialog_->SetCopy(true);
|
organise_dialog_->SetCopy(true);
|
||||||
if (organise_dialog_->SetUrls(urls))
|
if (organise_dialog_->SetUrls(urls))
|
||||||
@@ -1837,6 +1919,7 @@ void MainWindow::CopyFilesToDevice(const QList<QUrl> &urls) {
|
|||||||
else {
|
else {
|
||||||
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1968,15 +2051,14 @@ void MainWindow::PlaylistSkip() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#if defined(HAVE_GSTREAMER)
|
||||||
void MainWindow::PlaylistCopyToDevice() {
|
void MainWindow::PlaylistCopyToDevice() {
|
||||||
|
#if !defined(Q_OS_WIN)
|
||||||
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
QModelIndexList proxy_indexes = ui_->playlist->view()->selectionModel()->selectedRows();
|
||||||
SongList songs;
|
SongList songs;
|
||||||
|
|
||||||
for (const QModelIndex &proxy_index : proxy_indexes) {
|
for (const QModelIndex &proxy_index : proxy_indexes) {
|
||||||
QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
QModelIndex index = app_->playlist_manager()->current()->proxy()->mapToSource(proxy_index);
|
||||||
|
|
||||||
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
songs << app_->playlist_manager()->current()->item_at(index.row())->Metadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1985,9 +2067,9 @@ void MainWindow::PlaylistCopyToDevice() {
|
|||||||
if (organise_dialog_->SetSongs(songs))
|
if (organise_dialog_->SetSongs(songs))
|
||||||
organise_dialog_->show();
|
organise_dialog_->show();
|
||||||
else {
|
else {
|
||||||
QMessageBox::warning(this, tr("Error"),
|
QMessageBox::warning(this, tr("Error"), tr("None of the selected songs were suitable for copying to a device"));
|
||||||
tr("None of the selected songs were suitable for copying to a device"));
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2135,20 +2217,12 @@ void MainWindow::CheckFullRescanRevisions() {
|
|||||||
}
|
}
|
||||||
message += "</ul>" + tr("Would you like to run a full rescan right now?");
|
message += "</ul>" + tr("Would you like to run a full rescan right now?");
|
||||||
|
|
||||||
if(QMessageBox::question(this, tr("Collection rescan notice"), message, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
if (QMessageBox::question(this, tr("Collection rescan notice"), message, QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes) {
|
||||||
app_->collection()->FullScan();
|
app_->collection()->FullScan();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::ShowQueueManager() {
|
|
||||||
//if (!queue_manager_) {
|
|
||||||
//queue_manager_.reset(new QueueManager);
|
|
||||||
//queue_manager_->SetPlaylistManager(app_->playlist_manager());
|
|
||||||
//}
|
|
||||||
queue_manager_->show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::PlaylistViewSelectionModelChanged() {
|
void MainWindow::PlaylistViewSelectionModelChanged() {
|
||||||
|
|
||||||
connect(ui_->playlist->view()->selectionModel(),SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(PlaylistCurrentChanged(QModelIndex)));
|
connect(ui_->playlist->view()->selectionModel(),SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(PlaylistCurrentChanged(QModelIndex)));
|
||||||
@@ -2176,8 +2250,8 @@ bool MainWindow::winEvent(MSG *msg, long*) {
|
|||||||
|
|
||||||
void MainWindow::Exit() {
|
void MainWindow::Exit() {
|
||||||
|
|
||||||
|
SaveGeometry();
|
||||||
SavePlaybackStatus();
|
SavePlaybackStatus();
|
||||||
//settings_.setValue("show_sidebar", ui_->action_toggle_show_sidebar->isChecked());
|
|
||||||
|
|
||||||
if (app_->player()->engine()->is_fadeout_enabled()) {
|
if (app_->player()->engine()->is_fadeout_enabled()) {
|
||||||
// To shut down the application when fadeout will be finished
|
// To shut down the application when fadeout will be finished
|
||||||
@@ -2185,7 +2259,7 @@ void MainWindow::Exit() {
|
|||||||
if (app_->player()->GetState() == Engine::Playing) {
|
if (app_->player()->GetState() == Engine::Playing) {
|
||||||
app_->player()->Stop();
|
app_->player()->Stop();
|
||||||
hide();
|
hide();
|
||||||
tray_icon_->SetVisible(false);
|
if (tray_icon_) tray_icon_->SetVisible(false);
|
||||||
return; // Don't quit the application now: wait for the fadeout finished signal
|
return; // Don't quit the application now: wait for the fadeout finished signal
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2292,39 +2366,6 @@ void MainWindow::keyPressEvent(QKeyEvent *event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::FocusTidalSearchField() {
|
|
||||||
ui_->tabs->setCurrentWidget(tidal_search_view_);
|
|
||||||
tidal_search_view_->FocusSearchField();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::DoTidalSearch(const QString& query) {
|
|
||||||
FocusTidalSearchField();
|
|
||||||
tidal_search_view_->StartSearch(query);
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::SearchForArtist() {
|
|
||||||
|
|
||||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
|
|
||||||
Song song = item->Metadata();
|
|
||||||
if (!song.albumartist().isEmpty()) {
|
|
||||||
DoTidalSearch(song.albumartist().simplified());
|
|
||||||
}
|
|
||||||
else if (!song.artist().isEmpty()) {
|
|
||||||
DoTidalSearch(song.artist().simplified());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::SearchForAlbum() {
|
|
||||||
|
|
||||||
PlaylistItemPtr item(app_->playlist_manager()->current()->item_at(playlist_menu_index_.row()));
|
|
||||||
Song song = item->Metadata();
|
|
||||||
if (!song.album().isEmpty()) {
|
|
||||||
DoTidalSearch(song.album().simplified());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void MainWindow::LoadCoverFromFile() {
|
void MainWindow::LoadCoverFromFile() {
|
||||||
album_cover_choice_controller_->LoadCoverFromFile(&song_);
|
album_cover_choice_controller_->LoadCoverFromFile(&song_);
|
||||||
}
|
}
|
||||||
@@ -2383,4 +2424,3 @@ void MainWindow::GetCoverAutomatically() {
|
|||||||
if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_);
|
if (search) album_cover_choice_controller_->SearchCoverAutomatically(song_);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -56,6 +57,8 @@
|
|||||||
#include "playlist/playlistitem.h"
|
#include "playlist/playlistitem.h"
|
||||||
#include "settings/settingsdialog.h"
|
#include "settings/settingsdialog.h"
|
||||||
|
|
||||||
|
using std::unique_ptr;
|
||||||
|
|
||||||
class About;
|
class About;
|
||||||
class AlbumCoverManager;;
|
class AlbumCoverManager;;
|
||||||
class Application;
|
class Application;
|
||||||
@@ -63,8 +66,10 @@ class ContextView;
|
|||||||
class CollectionViewContainer;
|
class CollectionViewContainer;
|
||||||
class AlbumCoverChoiceController;
|
class AlbumCoverChoiceController;
|
||||||
class CommandlineOptions;
|
class CommandlineOptions;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
class DeviceView;
|
class DeviceView;
|
||||||
class DeviceViewContainer;
|
class DeviceViewContainer;
|
||||||
|
#endif
|
||||||
class EditTagDialog;
|
class EditTagDialog;
|
||||||
class Equalizer;
|
class Equalizer;
|
||||||
class ErrorDialog;
|
class ErrorDialog;
|
||||||
@@ -73,7 +78,7 @@ class GlobalShortcuts;
|
|||||||
class MimeData;
|
class MimeData;
|
||||||
class OrganiseDialog;
|
class OrganiseDialog;
|
||||||
class PlaylistListContainer;
|
class PlaylistListContainer;
|
||||||
class QueueManager;
|
class QueueView;
|
||||||
class Song;
|
class Song;
|
||||||
class SystemTrayIcon;
|
class SystemTrayIcon;
|
||||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||||
@@ -85,7 +90,7 @@ class TranscodeDialog;
|
|||||||
#endif
|
#endif
|
||||||
class Ui_MainWindow;
|
class Ui_MainWindow;
|
||||||
class Windows7ThumbBar;
|
class Windows7ThumbBar;
|
||||||
class TidalSearchView;
|
class InternetSearchView;
|
||||||
|
|
||||||
class MainWindow : public QMainWindow, public PlatformInterface {
|
class MainWindow : public QMainWindow, public PlatformInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -134,7 +139,7 @@ class MainWindow : public QMainWindow, public PlatformInterface {
|
|||||||
void resizeEvent(QResizeEvent *event);
|
void resizeEvent(QResizeEvent *event);
|
||||||
void closeEvent(QCloseEvent *event);
|
void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN32
|
#ifdef Q_OS_WIN
|
||||||
bool winEvent(MSG *message, long *result);
|
bool winEvent(MSG *message, long *result);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -183,7 +188,9 @@ signals:
|
|||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
void PlaylistCopyToCollection();
|
void PlaylistCopyToCollection();
|
||||||
void PlaylistMoveToCollection();
|
void PlaylistMoveToCollection();
|
||||||
|
#ifndef Q_OS_WIN_
|
||||||
void PlaylistCopyToDevice();
|
void PlaylistCopyToDevice();
|
||||||
|
#endif
|
||||||
void PlaylistOrganiseSelected(bool copy);
|
void PlaylistOrganiseSelected(bool copy);
|
||||||
#endif
|
#endif
|
||||||
//void PlaylistDelete();
|
//void PlaylistDelete();
|
||||||
@@ -202,7 +209,9 @@ signals:
|
|||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
void CopyFilesToCollection(const QList<QUrl>& urls);
|
void CopyFilesToCollection(const QList<QUrl>& urls);
|
||||||
void MoveFilesToCollection(const QList<QUrl>& urls);
|
void MoveFilesToCollection(const QList<QUrl>& urls);
|
||||||
|
//#ifndef Q_OS_WIN
|
||||||
void CopyFilesToDevice(const QList<QUrl>& urls);
|
void CopyFilesToDevice(const QList<QUrl>& urls);
|
||||||
|
//#endif
|
||||||
#endif
|
#endif
|
||||||
void EditFileTags(const QList<QUrl>& urls);
|
void EditFileTags(const QList<QUrl>& urls);
|
||||||
|
|
||||||
@@ -243,7 +252,6 @@ signals:
|
|||||||
void ShowTranscodeDialog();
|
void ShowTranscodeDialog();
|
||||||
#endif
|
#endif
|
||||||
void ShowErrorDialog(const QString& message);
|
void ShowErrorDialog(const QString& message);
|
||||||
void ShowQueueManager();
|
|
||||||
void EnsureSettingsDialogCreated();
|
void EnsureSettingsDialogCreated();
|
||||||
void EnsureEditTagDialogCreated();
|
void EnsureEditTagDialogCreated();
|
||||||
SettingsDialog *CreateSettingsDialog();
|
SettingsDialog *CreateSettingsDialog();
|
||||||
@@ -266,11 +274,6 @@ signals:
|
|||||||
|
|
||||||
void ShowConsole();
|
void ShowConsole();
|
||||||
|
|
||||||
void FocusTidalSearchField();
|
|
||||||
void DoTidalSearch(const QString& query);
|
|
||||||
void SearchForArtist();
|
|
||||||
void SearchForAlbum();
|
|
||||||
|
|
||||||
void LoadCoverFromFile();
|
void LoadCoverFromFile();
|
||||||
void SaveCoverToFile();
|
void SaveCoverToFile();
|
||||||
void LoadCoverFromURL();
|
void LoadCoverFromURL();
|
||||||
@@ -308,9 +311,12 @@ signals:
|
|||||||
ContextView *context_view_;
|
ContextView *context_view_;
|
||||||
CollectionViewContainer *collection_view_;
|
CollectionViewContainer *collection_view_;
|
||||||
FileView *file_view_;
|
FileView *file_view_;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
DeviceViewContainer *device_view_container_;
|
DeviceViewContainer *device_view_container_;
|
||||||
DeviceView *device_view_;
|
DeviceView *device_view_;
|
||||||
|
#endif
|
||||||
PlaylistListContainer *playlist_list_;
|
PlaylistListContainer *playlist_list_;
|
||||||
|
QueueView *queue_view_;
|
||||||
|
|
||||||
Lazy<SettingsDialog> settings_dialog_;
|
Lazy<SettingsDialog> settings_dialog_;
|
||||||
Lazy<AlbumCoverManager> cover_manager_;
|
Lazy<AlbumCoverManager> cover_manager_;
|
||||||
@@ -322,7 +328,6 @@ signals:
|
|||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
Lazy<OrganiseDialog> organise_dialog_;
|
Lazy<OrganiseDialog> organise_dialog_;
|
||||||
#endif
|
#endif
|
||||||
Lazy<QueueManager> queue_manager_;
|
|
||||||
|
|
||||||
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
#if defined(HAVE_GSTREAMER) && defined(HAVE_CHROMAPRINT)
|
||||||
std::unique_ptr<TagFetcher> tag_fetcher_;
|
std::unique_ptr<TagFetcher> tag_fetcher_;
|
||||||
@@ -332,7 +337,8 @@ signals:
|
|||||||
PlaylistItemList autocomplete_tag_items_;
|
PlaylistItemList autocomplete_tag_items_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TidalSearchView *tidal_search_view_;
|
InternetSearchView *tidal_search_view_;
|
||||||
|
InternetSearchView *deezer_search_view_;
|
||||||
|
|
||||||
QAction *collection_show_all_;
|
QAction *collection_show_all_;
|
||||||
QAction *collection_show_duplicates_;
|
QAction *collection_show_duplicates_;
|
||||||
@@ -347,7 +353,9 @@ signals:
|
|||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
QAction *playlist_copy_to_collection_;
|
QAction *playlist_copy_to_collection_;
|
||||||
QAction *playlist_move_to_collection_;
|
QAction *playlist_move_to_collection_;
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
QAction *playlist_copy_to_device_;
|
QAction *playlist_copy_to_device_;
|
||||||
|
#endif
|
||||||
//QAction *playlist_delete_;
|
//QAction *playlist_delete_;
|
||||||
#endif
|
#endif
|
||||||
QAction *playlist_open_in_browser_;
|
QAction *playlist_open_in_browser_;
|
||||||
@@ -378,7 +386,6 @@ signals:
|
|||||||
|
|
||||||
Song song_;
|
Song song_;
|
||||||
Song song_playing_;
|
Song song_playing_;
|
||||||
Song song_empty_;
|
|
||||||
QImage image_original_;
|
QImage image_original_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Strawberry Music Player</string>
|
<string>Strawberry Music Player</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
@@ -435,7 +435,6 @@
|
|||||||
<string>&Tools</string>
|
<string>&Tools</string>
|
||||||
</property>
|
</property>
|
||||||
<addaction name="action_cover_manager"/>
|
<addaction name="action_cover_manager"/>
|
||||||
<addaction name="action_queue_manager"/>
|
|
||||||
<addaction name="action_equalizer"/>
|
<addaction name="action_equalizer"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_update_collection"/>
|
<addaction name="action_update_collection"/>
|
||||||
@@ -553,7 +552,7 @@
|
|||||||
</action>
|
</action>
|
||||||
<action name="action_about_strawberry">
|
<action name="action_about_strawberry">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -674,11 +673,6 @@
|
|||||||
<string>&Update changed collection folders</string>
|
<string>&Update changed collection folders</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="action_queue_manager">
|
|
||||||
<property name="text">
|
|
||||||
<string>&Queue Manager</string>
|
|
||||||
</property>
|
|
||||||
</action>
|
|
||||||
<action name="action_about_qt">
|
<action name="action_about_qt">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>About &Qt</string>
|
<string>About &Qt</string>
|
||||||
@@ -782,6 +776,7 @@
|
|||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
@@ -60,7 +60,7 @@
|
|||||||
# include "dbus/metatypes.h"
|
# include "dbus/metatypes.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "tidal/tidalsearch.h"
|
#include "internet/internetsearch.h"
|
||||||
|
|
||||||
void RegisterMetaTypes() {
|
void RegisterMetaTypes() {
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ void RegisterMetaTypes() {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
qRegisterMetaType<TidalSearch::ResultList>("TidalSearch::ResultList");
|
qRegisterMetaType<InternetSearch::ResultList>("InternetSearch::ResultList");
|
||||||
qRegisterMetaType<TidalSearch::Result>("TidalSearch::Result");
|
qRegisterMetaType<InternetSearch::Result>("InternetSearch::Result");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,9 @@
|
|||||||
#ifdef HAVE_VLC
|
#ifdef HAVE_VLC
|
||||||
# include "engine/vlcengine.h"
|
# include "engine/vlcengine.h"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_DEEZER
|
||||||
|
# include "engine/deezerengine.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "collection/collectionbackend.h"
|
#include "collection/collectionbackend.h"
|
||||||
#include "playlist/playlist.h"
|
#include "playlist/playlist.h"
|
||||||
@@ -68,8 +71,11 @@
|
|||||||
#include "equalizer/equalizer.h"
|
#include "equalizer/equalizer.h"
|
||||||
#include "analyzer/analyzercontainer.h"
|
#include "analyzer/analyzercontainer.h"
|
||||||
#include "settings/backendsettingspage.h"
|
#include "settings/backendsettingspage.h"
|
||||||
|
#include "settings/playbacksettingspage.h"
|
||||||
#include "settings/behavioursettingspage.h"
|
#include "settings/behavioursettingspage.h"
|
||||||
#include "settings/playlistsettingspage.h"
|
#include "settings/playlistsettingspage.h"
|
||||||
|
#include "internet/internetservices.h"
|
||||||
|
#include "internet/internetservice.h"
|
||||||
|
|
||||||
using std::shared_ptr;
|
using std::shared_ptr;
|
||||||
|
|
||||||
@@ -81,6 +87,8 @@ Player::Player(Application *app, QObject *parent)
|
|||||||
nb_errors_received_(0),
|
nb_errors_received_(0),
|
||||||
volume_before_mute_(50),
|
volume_before_mute_(50),
|
||||||
last_pressed_previous_(QDateTime::currentDateTime()),
|
last_pressed_previous_(QDateTime::currentDateTime()),
|
||||||
|
continue_on_error_(false),
|
||||||
|
greyout_(true),
|
||||||
menu_previousmode_(PreviousBehaviour_DontRestart),
|
menu_previousmode_(PreviousBehaviour_DontRestart),
|
||||||
seek_step_sec_(10) {
|
seek_step_sec_(10) {
|
||||||
|
|
||||||
@@ -101,9 +109,9 @@ Player::~Player() {
|
|||||||
settings_.endGroup();
|
settings_.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::CreateEngine(Engine::EngineType enginetype) {
|
Engine::EngineType Player::CreateEngine(Engine::EngineType enginetype) {
|
||||||
|
|
||||||
Engine::EngineType use_enginetype = Engine::None;
|
Engine::EngineType use_enginetype(Engine::None);
|
||||||
|
|
||||||
for (int i = 0 ; use_enginetype == Engine::None ; i++) {
|
for (int i = 0 ; use_enginetype == Engine::None ; i++) {
|
||||||
switch(enginetype) {
|
switch(enginetype) {
|
||||||
@@ -131,6 +139,15 @@ void Player::CreateEngine(Engine::EngineType enginetype) {
|
|||||||
use_enginetype=Engine::Phonon;
|
use_enginetype=Engine::Phonon;
|
||||||
engine_.reset(new PhononEngine(app_->task_manager()));
|
engine_.reset(new PhononEngine(app_->task_manager()));
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_DEEZER
|
||||||
|
case Engine::Deezer:{
|
||||||
|
use_enginetype=Engine::Deezer;
|
||||||
|
DeezerEngine *deezerengine = new DeezerEngine(app_->task_manager());
|
||||||
|
connect(this, SIGNAL(Authenticated()), deezerengine, SLOT(LoadAccessToken()));
|
||||||
|
engine_.reset(deezerengine);
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
if (i > 0) { qFatal("No engine available!"); }
|
if (i > 0) { qFatal("No engine available!"); }
|
||||||
@@ -144,7 +161,7 @@ void Player::CreateEngine(Engine::EngineType enginetype) {
|
|||||||
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
s.beginGroup(BackendSettingsPage::kSettingsGroup);
|
||||||
s.setValue("engine", EngineName(use_enginetype));
|
s.setValue("engine", EngineName(use_enginetype));
|
||||||
s.setValue("output", engine_->DefaultOutput());
|
s.setValue("output", engine_->DefaultOutput());
|
||||||
s.setValue("device", QVariant(""));
|
s.setValue("device", QVariant());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,6 +169,8 @@ void Player::CreateEngine(Engine::EngineType enginetype) {
|
|||||||
qFatal("Failed to create engine!");
|
qFatal("Failed to create engine!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return use_enginetype;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::Init() {
|
void Player::Init() {
|
||||||
@@ -161,6 +180,7 @@ void Player::Init() {
|
|||||||
analyzer_->SetEngine(engine_.get());
|
analyzer_->SetEngine(engine_.get());
|
||||||
|
|
||||||
connect(engine_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
connect(engine_.get(), SIGNAL(Error(QString)), SIGNAL(Error(QString)));
|
||||||
|
connect(engine_.get(), SIGNAL(FatalError()), SLOT(FatalError()));
|
||||||
connect(engine_.get(), SIGNAL(ValidSongRequested(QUrl)), SLOT(ValidSongRequested(QUrl)));
|
connect(engine_.get(), SIGNAL(ValidSongRequested(QUrl)), SLOT(ValidSongRequested(QUrl)));
|
||||||
connect(engine_.get(), SIGNAL(InvalidSongRequested(QUrl)), SLOT(InvalidSongRequested(QUrl)));
|
connect(engine_.get(), SIGNAL(InvalidSongRequested(QUrl)), SLOT(InvalidSongRequested(QUrl)));
|
||||||
connect(engine_.get(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
|
connect(engine_.get(), SIGNAL(StateChanged(Engine::State)), SLOT(EngineStateChanged(Engine::State)));
|
||||||
@@ -190,6 +210,8 @@ void Player::ReloadSettings() {
|
|||||||
QSettings s;
|
QSettings s;
|
||||||
|
|
||||||
s.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
s.beginGroup(PlaylistSettingsPage::kSettingsGroup);
|
||||||
|
continue_on_error_ = s.value("continue_on_error", false).toBool();
|
||||||
|
greyout_ = s.value("greyout_songs_play", true).toBool();
|
||||||
menu_previousmode_ = PreviousBehaviour(s.value("menu_previousmode", PreviousBehaviour_DontRestart).toInt());
|
menu_previousmode_ = PreviousBehaviour(s.value("menu_previousmode", PreviousBehaviour_DontRestart).toInt());
|
||||||
s.endGroup();
|
s.endGroup();
|
||||||
|
|
||||||
@@ -224,14 +246,29 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
|||||||
|
|
||||||
qLog(Debug) << "URL handler for" << result.original_url_ << "returned" << result.media_url_;
|
qLog(Debug) << "URL handler for" << result.original_url_ << "returned" << result.media_url_;
|
||||||
|
|
||||||
|
Song song = item->Metadata();
|
||||||
|
bool update(false);
|
||||||
|
|
||||||
|
// If there was no filetype in the song's metadata, use the one provided by URL handler, if there is one
|
||||||
|
if (
|
||||||
|
(item->Metadata().filetype() == Song::FileType_Unknown && result.filetype_ != Song::FileType_Unknown)
|
||||||
|
||
|
||||||
|
(item->Metadata().filetype() == Song::FileType_Stream && result.filetype_ != Song::FileType_Stream)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
song.set_filetype(result.filetype_);
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
// If there was no length info in song's metadata, use the one provided by URL handler, if there is one
|
// If there was no length info in song's metadata, use the one provided by URL handler, if there is one
|
||||||
if (item->Metadata().length_nanosec() <= 0 && result.length_nanosec_ != -1) {
|
if (item->Metadata().length_nanosec() <= 0 && result.length_nanosec_ != -1) {
|
||||||
Song song = item->Metadata();
|
|
||||||
song.set_length_nanosec(result.length_nanosec_);
|
song.set_length_nanosec(result.length_nanosec_);
|
||||||
|
update = true;
|
||||||
|
}
|
||||||
|
if (update) {
|
||||||
item->SetTemporaryMetadata(song);
|
item->SetTemporaryMetadata(song);
|
||||||
app_->playlist_manager()->active()->InformOfCurrentSongChange();
|
app_->playlist_manager()->active()->InformOfCurrentSongChange();
|
||||||
}
|
}
|
||||||
engine_->Play(result.media_url_, stream_change_type_, item->Metadata().has_cue(), item->Metadata().beginning_nanosec(), item->Metadata().end_nanosec());
|
engine_->Play(result.media_url_, result.original_url_, stream_change_type_, item->Metadata().has_cue(), item->Metadata().beginning_nanosec(), item->Metadata().end_nanosec());
|
||||||
|
|
||||||
current_item_ = item;
|
current_item_ = item;
|
||||||
loading_async_ = QUrl();
|
loading_async_ = QUrl();
|
||||||
@@ -245,6 +282,7 @@ void Player::HandleLoadResult(const UrlHandler::LoadResult &result) {
|
|||||||
loading_async_ = result.original_url_;
|
loading_async_ = result.original_url_;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::Next() { NextInternal(Engine::Manual); }
|
void Player::Next() { NextInternal(Engine::Manual); }
|
||||||
@@ -256,7 +294,7 @@ void Player::NextInternal(Engine::TrackChangeFlags change) {
|
|||||||
if (app_->playlist_manager()->active()->current_item()) {
|
if (app_->playlist_manager()->active()->current_item()) {
|
||||||
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
|
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
|
||||||
|
|
||||||
if (url_handlers_.contains(url.scheme())) {
|
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
|
||||||
// The next track is already being loaded
|
// The next track is already being loaded
|
||||||
if (url == loading_async_) return;
|
if (url == loading_async_) return;
|
||||||
|
|
||||||
@@ -267,6 +305,7 @@ void Player::NextInternal(Engine::TrackChangeFlags change) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NextItem(change);
|
NextItem(change);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::NextItem(Engine::TrackChangeFlags change) {
|
void Player::NextItem(Engine::TrackChangeFlags change) {
|
||||||
@@ -316,6 +355,7 @@ bool Player::HandleStopAfter() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::TrackEnded() {
|
void Player::TrackEnded() {
|
||||||
@@ -327,6 +367,7 @@ void Player::TrackEnded() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NextInternal(Engine::Auto);
|
NextInternal(Engine::Auto);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::PlayPause() {
|
void Player::PlayPause() {
|
||||||
@@ -460,10 +501,10 @@ int Player::GetVolume() const { return engine_->volume(); }
|
|||||||
|
|
||||||
void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle) {
|
void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle) {
|
||||||
|
|
||||||
if (change == Engine::Manual && engine_->position_nanosec() != engine_->length_nanosec()) {
|
if (current_item_ && change == Engine::Manual && engine_->position_nanosec() != engine_->length_nanosec()) {
|
||||||
emit TrackSkipped(current_item_);
|
emit TrackSkipped(current_item_);
|
||||||
const QUrl &url = current_item_->Url();
|
const QUrl &url = current_item_->Url();
|
||||||
if (url_handlers_.contains(url.scheme())) {
|
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
|
||||||
url_handlers_[url.scheme()]->TrackSkipped();
|
url_handlers_[url.scheme()]->TrackSkipped();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -474,7 +515,6 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
|
|||||||
|
|
||||||
if (reshuffle) app_->playlist_manager()->active()->ReshuffleIndices();
|
if (reshuffle) app_->playlist_manager()->active()->ReshuffleIndices();
|
||||||
app_->playlist_manager()->active()->set_current_row(index);
|
app_->playlist_manager()->active()->set_current_row(index);
|
||||||
|
|
||||||
if (app_->playlist_manager()->active()->current_row() == -1) {
|
if (app_->playlist_manager()->active()->current_row() == -1) {
|
||||||
// Maybe index didn't exist in the playlist.
|
// Maybe index didn't exist in the playlist.
|
||||||
return;
|
return;
|
||||||
@@ -483,7 +523,7 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
|
|||||||
current_item_ = app_->playlist_manager()->active()->current_item();
|
current_item_ = app_->playlist_manager()->active()->current_item();
|
||||||
const QUrl url = current_item_->Url();
|
const QUrl url = current_item_->Url();
|
||||||
|
|
||||||
if (url_handlers_.contains(url.scheme())) {
|
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
|
||||||
// It's already loading
|
// It's already loading
|
||||||
if (url == loading_async_) return;
|
if (url == loading_async_) return;
|
||||||
|
|
||||||
@@ -492,8 +532,7 @@ void Player::PlayAt(int index, Engine::TrackChangeFlags change, bool reshuffle)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
loading_async_ = QUrl();
|
loading_async_ = QUrl();
|
||||||
engine_->Play(current_item_->Url(), change, current_item_->Metadata().has_cue(), current_item_->Metadata().beginning_nanosec(), current_item_->Metadata().end_nanosec());
|
engine_->Play(current_item_->Url(), current_item_->Url(), change, current_item_->Metadata().has_cue(), current_item_->Metadata().beginning_nanosec(), current_item_->Metadata().end_nanosec());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -535,6 +574,8 @@ void Player::EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle) {
|
|||||||
PlaylistItemPtr item = app_->playlist_manager()->active()->current_item();
|
PlaylistItemPtr item = app_->playlist_manager()->active()->current_item();
|
||||||
if (!item) return;
|
if (!item) return;
|
||||||
|
|
||||||
|
if (bundle.url != item->Metadata().url()) return;
|
||||||
|
|
||||||
Engine::SimpleMetaBundle bundle_copy = bundle;
|
Engine::SimpleMetaBundle bundle_copy = bundle;
|
||||||
|
|
||||||
// Maybe the metadata is from icycast and has "Artist - Title" shoved together in the title field.
|
// Maybe the metadata is from icycast and has "Artist - Title" shoved together in the title field.
|
||||||
@@ -545,7 +586,8 @@ void Player::EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle) {
|
|||||||
if (space_dash_pos != -1) {
|
if (space_dash_pos != -1) {
|
||||||
bundle_copy.artist = bundle_copy.title.left(space_dash_pos).trimmed();
|
bundle_copy.artist = bundle_copy.title.left(space_dash_pos).trimmed();
|
||||||
bundle_copy.title = bundle_copy.title.mid(space_dash_pos + 3).trimmed();
|
bundle_copy.title = bundle_copy.title.mid(space_dash_pos + 3).trimmed();
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
bundle_copy.artist = bundle_copy.title.left(dash_pos).trimmed();
|
bundle_copy.artist = bundle_copy.title.left(dash_pos).trimmed();
|
||||||
bundle_copy.title = bundle_copy.title.mid(dash_pos + 1).trimmed();
|
bundle_copy.title = bundle_copy.title.mid(dash_pos + 1).trimmed();
|
||||||
}
|
}
|
||||||
@@ -613,7 +655,7 @@ void Player::TrackAboutToEnd() {
|
|||||||
// We don't want to preload (and scrobble) the next item in the playlist if it's just going to be stopped again immediately after.
|
// We don't want to preload (and scrobble) the next item in the playlist if it's just going to be stopped again immediately after.
|
||||||
if (app_->playlist_manager()->active()->current_item()) {
|
if (app_->playlist_manager()->active()->current_item()) {
|
||||||
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
|
const QUrl url = app_->playlist_manager()->active()->current_item()->Url();
|
||||||
if (url_handlers_.contains(url.scheme())) {
|
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
|
||||||
url_handlers_[url.scheme()]->TrackAboutToEnd();
|
url_handlers_[url.scheme()]->TrackAboutToEnd();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -646,7 +688,7 @@ void Player::TrackAboutToEnd() {
|
|||||||
QUrl url = next_item->Url();
|
QUrl url = next_item->Url();
|
||||||
|
|
||||||
// Get the actual track URL rather than the stream URL.
|
// Get the actual track URL rather than the stream URL.
|
||||||
if (url_handlers_.contains(url.scheme())) {
|
if (url_handlers_.contains(url.scheme()) && !(engine_->type() == Engine::Deezer && url.scheme() == "dzmedia")) {
|
||||||
UrlHandler::LoadResult result = url_handlers_[url.scheme()]->LoadNext(url);
|
UrlHandler::LoadResult result = url_handlers_[url.scheme()]->LoadNext(url);
|
||||||
switch (result.type_) {
|
switch (result.type_) {
|
||||||
case UrlHandler::LoadResult::NoMoreTracks:
|
case UrlHandler::LoadResult::NoMoreTracks:
|
||||||
@@ -661,23 +703,31 @@ void Player::TrackAboutToEnd() {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
engine_->StartPreloading(url, next_item->Metadata().has_cue(), next_item->Metadata().beginning_nanosec(), next_item->Metadata().end_nanosec());
|
engine_->StartPreloading(url, next_item->Url(), next_item->Metadata().has_cue(), next_item->Metadata().beginning_nanosec(), next_item->Metadata().end_nanosec());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::IntroPointReached() { NextInternal(Engine::Intro); }
|
void Player::IntroPointReached() { NextInternal(Engine::Intro); }
|
||||||
|
|
||||||
|
void Player::FatalError() {
|
||||||
|
nb_errors_received_ = 0;
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
|
||||||
void Player::ValidSongRequested(const QUrl &url) {
|
void Player::ValidSongRequested(const QUrl &url) {
|
||||||
emit SongChangeRequestProcessed(url, true);
|
emit SongChangeRequestProcessed(url, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::InvalidSongRequested(const QUrl &url) {
|
void Player::InvalidSongRequested(const QUrl &url) {
|
||||||
|
|
||||||
// first send the notification to others...
|
if (greyout_) emit SongChangeRequestProcessed(url, false);
|
||||||
emit SongChangeRequestProcessed(url, false);
|
|
||||||
// ... and now when our listeners have completed their processing of the current item we can change
|
if (!continue_on_error_) {
|
||||||
// the current item by skipping to the next song
|
FatalError();
|
||||||
//NextItem(Engine::Auto);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NextItem(Engine::Auto);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -731,3 +781,7 @@ void Player::UrlHandlerDestroyed(QObject *object) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::HandleAuthentication() {
|
||||||
|
emit Authenticated();
|
||||||
|
}
|
||||||
|
|||||||
@@ -114,6 +114,9 @@ class PlayerInterface : public QObject {
|
|||||||
|
|
||||||
// The toggle parameter is true when user requests to toggle visibility for Pretty OSD
|
// The toggle parameter is true when user requests to toggle visibility for Pretty OSD
|
||||||
void ForceShowOSD(Song, bool toogle);
|
void ForceShowOSD(Song, bool toogle);
|
||||||
|
|
||||||
|
void Authenticated();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Player : public PlayerInterface {
|
class Player : public PlayerInterface {
|
||||||
@@ -131,7 +134,7 @@ class Player : public PlayerInterface {
|
|||||||
PreviousBehaviour_Restart = 2
|
PreviousBehaviour_Restart = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
void CreateEngine(Engine::EngineType enginetype);
|
Engine::EngineType CreateEngine(Engine::EngineType enginetype);
|
||||||
void Init();
|
void Init();
|
||||||
|
|
||||||
EngineBase *engine() const { return engine_.get(); }
|
EngineBase *engine() const { return engine_.get(); }
|
||||||
@@ -177,6 +180,8 @@ class Player : public PlayerInterface {
|
|||||||
void ShowOSD();
|
void ShowOSD();
|
||||||
void TogglePrettyOSD();
|
void TogglePrettyOSD();
|
||||||
|
|
||||||
|
void HandleAuthentication();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void EngineStateChanged(Engine::State);
|
void EngineStateChanged(Engine::State);
|
||||||
void EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle);
|
void EngineMetadataReceived(const Engine::SimpleMetaBundle &bundle);
|
||||||
@@ -188,6 +193,7 @@ class Player : public PlayerInterface {
|
|||||||
|
|
||||||
void NextInternal(Engine::TrackChangeFlags);
|
void NextInternal(Engine::TrackChangeFlags);
|
||||||
|
|
||||||
|
void FatalError();
|
||||||
void ValidSongRequested(const QUrl&);
|
void ValidSongRequested(const QUrl&);
|
||||||
void InvalidSongRequested(const QUrl&);
|
void InvalidSongRequested(const QUrl&);
|
||||||
|
|
||||||
@@ -214,10 +220,11 @@ class Player : public PlayerInterface {
|
|||||||
QMap<QString, UrlHandler*> url_handlers_;
|
QMap<QString, UrlHandler*> url_handlers_;
|
||||||
|
|
||||||
QUrl loading_async_;
|
QUrl loading_async_;
|
||||||
|
|
||||||
int volume_before_mute_;
|
int volume_before_mute_;
|
||||||
|
|
||||||
QDateTime last_pressed_previous_;
|
QDateTime last_pressed_previous_;
|
||||||
|
|
||||||
|
bool continue_on_error_;
|
||||||
|
bool greyout_;
|
||||||
PreviousBehaviour menu_previousmode_;
|
PreviousBehaviour menu_previousmode_;
|
||||||
int seek_step_sec_;
|
int seek_step_sec_;
|
||||||
|
|
||||||
|
|||||||
@@ -44,23 +44,12 @@ QtSystemTrayIcon::QtSystemTrayIcon(QObject *parent)
|
|||||||
action_play_pause_(nullptr),
|
action_play_pause_(nullptr),
|
||||||
action_stop_(nullptr),
|
action_stop_(nullptr),
|
||||||
action_stop_after_this_track_(nullptr),
|
action_stop_after_this_track_(nullptr),
|
||||||
action_mute_(nullptr)
|
action_mute_(nullptr) {
|
||||||
{
|
|
||||||
|
|
||||||
QIcon theme_icon = IconLoader::Load("strawberry", 48);
|
QIcon icon(":/icons/48x48/strawberry.png");
|
||||||
QIcon theme_icon_grey = IconLoader::Load("strawberry-grey", 48);
|
|
||||||
|
|
||||||
if (theme_icon.isNull() || theme_icon_grey.isNull()) {
|
normal_icon_ = icon.pixmap(48, QIcon::Normal);
|
||||||
// Load the default icon
|
grey_icon_ = icon.pixmap(48, QIcon::Disabled);
|
||||||
QIcon icon(":/icons/48x48/strawberry.png");
|
|
||||||
normal_icon_ = icon.pixmap(48, QIcon::Normal);
|
|
||||||
grey_icon_ = icon.pixmap(48, QIcon::Disabled);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Use the icons from the theme
|
|
||||||
normal_icon_ = theme_icon.pixmap(48);
|
|
||||||
grey_icon_ = theme_icon_grey.pixmap(48);
|
|
||||||
}
|
|
||||||
|
|
||||||
tray_->setIcon(normal_icon_);
|
tray_->setIcon(normal_icon_);
|
||||||
tray_->installEventFilter(this);
|
tray_->installEventFilter(this);
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <taglib/fileref.h>
|
#include <taglib/fileref.h>
|
||||||
#include <taglib/id3v1genres.h>
|
#include <taglib/id3v1genres.h>
|
||||||
|
|
||||||
@@ -66,6 +68,8 @@
|
|||||||
#include "covermanager/albumcoverloader.h"
|
#include "covermanager/albumcoverloader.h"
|
||||||
#include "tagreadermessages.pb.h"
|
#include "tagreadermessages.pb.h"
|
||||||
|
|
||||||
|
using std::sort;
|
||||||
|
|
||||||
const QStringList Song::kColumns = QStringList() << "title"
|
const QStringList Song::kColumns = QStringList() << "title"
|
||||||
<< "album"
|
<< "album"
|
||||||
<< "artist"
|
<< "artist"
|
||||||
@@ -298,7 +302,7 @@ uint Song::mtime() const { return d->mtime_; }
|
|||||||
uint Song::ctime() const { return d->ctime_; }
|
uint Song::ctime() const { return d->ctime_; }
|
||||||
int Song::filesize() const { return d->filesize_; }
|
int Song::filesize() const { return d->filesize_; }
|
||||||
Song::FileType Song::filetype() const { return d->filetype_; }
|
Song::FileType Song::filetype() const { return d->filetype_; }
|
||||||
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal; }
|
bool Song::is_stream() const { return d->source_ == Source_Stream || d->source_ == Source_Tidal || d->source_ == Source_Deezer; }
|
||||||
bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
|
bool Song::is_cdda() const { return d->source_ == Source_CDDA; }
|
||||||
bool Song::is_collection_song() const {
|
bool Song::is_collection_song() const {
|
||||||
return !is_cdda() && !is_stream() && id() != -1;
|
return !is_cdda() && !is_stream() && id() != -1;
|
||||||
@@ -384,6 +388,7 @@ QString Song::TextForSource(Source source) {
|
|||||||
case Song::Source_Device: return QObject::tr("Device");
|
case Song::Source_Device: return QObject::tr("Device");
|
||||||
case Song::Source_Stream: return QObject::tr("Stream");
|
case Song::Source_Stream: return QObject::tr("Stream");
|
||||||
case Song::Source_Tidal: return QObject::tr("Tidal");
|
case Song::Source_Tidal: return QObject::tr("Tidal");
|
||||||
|
case Song::Source_Deezer: return QObject::tr("Deezer");
|
||||||
default: return QObject::tr("Unknown");
|
default: return QObject::tr("Unknown");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,6 +403,7 @@ QIcon Song::IconForSource(Source source) {
|
|||||||
case Song::Source_Device: return IconLoader::Load("device");
|
case Song::Source_Device: return IconLoader::Load("device");
|
||||||
case Song::Source_Stream: return IconLoader::Load("applications-internet");
|
case Song::Source_Stream: return IconLoader::Load("applications-internet");
|
||||||
case Song::Source_Tidal: return IconLoader::Load("tidal");
|
case Song::Source_Tidal: return IconLoader::Load("tidal");
|
||||||
|
case Song::Source_Deezer: return IconLoader::Load("deezer");
|
||||||
default: return IconLoader::Load("edit-delete");
|
default: return IconLoader::Load("edit-delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,6 +427,7 @@ QString Song::TextForFiletype(FileType filetype) {
|
|||||||
case Song::FileType_TrueAudio: return QObject::tr("TrueAudio");
|
case Song::FileType_TrueAudio: return QObject::tr("TrueAudio");
|
||||||
case Song::FileType_DSF: return QObject::tr("DSF");
|
case Song::FileType_DSF: return QObject::tr("DSF");
|
||||||
case Song::FileType_DSDIFF: return QObject::tr("DSDIFF");
|
case Song::FileType_DSDIFF: return QObject::tr("DSDIFF");
|
||||||
|
case Song::FileType_PCM: return QObject::tr("PCM");
|
||||||
case Song::FileType_CDDA: return QObject::tr("CDDA");
|
case Song::FileType_CDDA: return QObject::tr("CDDA");
|
||||||
case Song::FileType_Stream: return QObject::tr("Stream");
|
case Song::FileType_Stream: return QObject::tr("Stream");
|
||||||
case Song::FileType_Unknown:
|
case Song::FileType_Unknown:
|
||||||
@@ -447,6 +454,7 @@ QIcon Song::IconForFiletype(FileType filetype) {
|
|||||||
case Song::FileType_TrueAudio: return IconLoader::Load("trueaudio");
|
case Song::FileType_TrueAudio: return IconLoader::Load("trueaudio");
|
||||||
case Song::FileType_DSF: return IconLoader::Load("dsf");
|
case Song::FileType_DSF: return IconLoader::Load("dsf");
|
||||||
case Song::FileType_DSDIFF: return IconLoader::Load("dsd");
|
case Song::FileType_DSDIFF: return IconLoader::Load("dsd");
|
||||||
|
case Song::FileType_PCM: return IconLoader::Load("pcm");
|
||||||
case Song::FileType_CDDA: return IconLoader::Load("cd");
|
case Song::FileType_CDDA: return IconLoader::Load("cd");
|
||||||
case Song::FileType_Stream: return IconLoader::Load("applications-internet");
|
case Song::FileType_Stream: return IconLoader::Load("applications-internet");
|
||||||
case Song::FileType_Unknown:
|
case Song::FileType_Unknown:
|
||||||
@@ -462,6 +470,8 @@ bool Song::IsFileLossless() const {
|
|||||||
case Song::FileType_OggFlac:
|
case Song::FileType_OggFlac:
|
||||||
case Song::FileType_WavPack:
|
case Song::FileType_WavPack:
|
||||||
case Song::FileType_AIFF:
|
case Song::FileType_AIFF:
|
||||||
|
case Song::FileType_DSF:
|
||||||
|
case Song::FileType_DSDIFF:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -493,7 +503,7 @@ int CompareSongsName(const Song &song1, const Song &song2) {
|
|||||||
|
|
||||||
void Song::SortSongsListAlphabetically(SongList *songs) {
|
void Song::SortSongsListAlphabetically(SongList *songs) {
|
||||||
Q_ASSERT(songs);
|
Q_ASSERT(songs);
|
||||||
qSort(songs->begin(), songs->end(), CompareSongsName);
|
std::sort(songs->begin(), songs->end(), CompareSongsName);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Song::Init(const QString &title, const QString &artist, const QString &album, qint64 length_nanosec) {
|
void Song::Init(const QString &title, const QString &artist, const QString &album, qint64 length_nanosec) {
|
||||||
@@ -996,12 +1006,14 @@ void Song::MergeFromSimpleMetaBundle(const Engine::SimpleMetaBundle &bundle) {
|
|||||||
if (!bundle.album.isEmpty()) d->album_ = bundle.album;
|
if (!bundle.album.isEmpty()) d->album_ = bundle.album;
|
||||||
if (!bundle.comment.isEmpty()) d->comment_ = bundle.comment;
|
if (!bundle.comment.isEmpty()) d->comment_ = bundle.comment;
|
||||||
if (!bundle.genre.isEmpty()) d->genre_ = bundle.genre;
|
if (!bundle.genre.isEmpty()) d->genre_ = bundle.genre;
|
||||||
if (!bundle.bitrate.isEmpty()) d->bitrate_ = bundle.bitrate.toInt();
|
if (bundle.length > 0) set_length_nanosec(bundle.length);
|
||||||
if (!bundle.samplerate.isEmpty()) d->samplerate_ = bundle.samplerate.toInt();
|
if (bundle.year > 0) d->year_ = bundle.year;
|
||||||
if (!bundle.bitdepth.isEmpty()) d->samplerate_ = bundle.bitdepth.toInt();
|
if (bundle.tracknr > 0) d->track_ = bundle.tracknr;
|
||||||
if (!bundle.length.isEmpty()) set_length_nanosec(bundle.length.toLongLong());
|
if (bundle.filetype != FileType_Unknown) d->filetype_ = bundle.filetype;
|
||||||
if (!bundle.year.isEmpty()) d->year_ = bundle.year.toInt();
|
if (bundle.samplerate > 0) d->samplerate_ = bundle.samplerate;
|
||||||
if (!bundle.tracknr.isEmpty()) d->track_ = bundle.tracknr.toInt();
|
if (bundle.bitdepth > 0) d->samplerate_ = bundle.bitdepth;
|
||||||
|
if (bundle.bitrate > 0) d->bitrate_ = bundle.bitrate;
|
||||||
|
if (!bundle.lyrics.isEmpty()) d->lyrics_ = bundle.lyrics;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ class Song {
|
|||||||
Source_Device = 4,
|
Source_Device = 4,
|
||||||
Source_Stream = 5,
|
Source_Stream = 5,
|
||||||
Source_Tidal = 6,
|
Source_Tidal = 6,
|
||||||
|
Source_Deezer = 7,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileType {
|
enum FileType {
|
||||||
@@ -117,6 +118,7 @@ class Song {
|
|||||||
FileType_TrueAudio = 13,
|
FileType_TrueAudio = 13,
|
||||||
FileType_DSF = 14,
|
FileType_DSF = 14,
|
||||||
FileType_DSDIFF = 15,
|
FileType_DSDIFF = 15,
|
||||||
|
FileType_PCM = 16,
|
||||||
FileType_CDDA = 90,
|
FileType_CDDA = 90,
|
||||||
FileType_Stream = 91,
|
FileType_Stream = 91,
|
||||||
};
|
};
|
||||||
@@ -308,7 +310,6 @@ class Song {
|
|||||||
|
|
||||||
void set_image(const QImage &i);
|
void set_image(const QImage &i);
|
||||||
|
|
||||||
|
|
||||||
// Comparison functions
|
// Comparison functions
|
||||||
bool IsMetadataEqual(const Song &other) const;
|
bool IsMetadataEqual(const Song &other) const;
|
||||||
bool IsOnSameAlbum(const Song &other) const;
|
bool IsOnSameAlbum(const Song &other) const;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#ifdef HAVE_GSTREAMER
|
#ifdef HAVE_GSTREAMER
|
||||||
# include <gst/gst.h>
|
# include <gst/gst.h>
|
||||||
@@ -65,6 +66,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
using std::placeholders::_1;
|
using std::placeholders::_1;
|
||||||
|
using std::bind;
|
||||||
|
using std::stable_sort;
|
||||||
|
using std::shared_ptr;
|
||||||
|
|
||||||
QSet<QString> SongLoader::sRawUriSchemes;
|
QSet<QString> SongLoader::sRawUriSchemes;
|
||||||
const int SongLoader::kDefaultTimeout = 5000;
|
const int SongLoader::kDefaultTimeout = 5000;
|
||||||
@@ -323,7 +327,7 @@ void SongLoader::LoadLocalDirectory(const QString &filename) {
|
|||||||
LoadLocalPartial(it.next());
|
LoadLocalPartial(it.next());
|
||||||
}
|
}
|
||||||
|
|
||||||
qStableSort(songs_.begin(), songs_.end(), CompareSongs);
|
std::stable_sort(songs_.begin(), songs_.end(), CompareSongs);
|
||||||
|
|
||||||
// Load the first song:
|
// Load the first song:
|
||||||
// all songs will be loaded async, but we want the first one in our list to be fully loaded,
|
// all songs will be loaded async, but we want the first one in our list to be fully loaded,
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ void StyleSheetLoader::SetStyleSheet(QWidget *widget, const QString &filename) {
|
|||||||
|
|
||||||
void StyleSheetLoader::UpdateStyleSheet(QWidget *widget) {
|
void StyleSheetLoader::UpdateStyleSheet(QWidget *widget) {
|
||||||
|
|
||||||
|
if (!widget || !filenames_.contains(widget)) return;
|
||||||
|
|
||||||
QString filename(filenames_[widget]);
|
QString filename(filenames_[widget]);
|
||||||
|
|
||||||
// Load the file
|
// Load the file
|
||||||
@@ -88,9 +90,10 @@ void StyleSheetLoader::UpdateStyleSheet(QWidget *widget) {
|
|||||||
ReplaceColor(&contents, "LinkVisited", p, QPalette::LinkVisited);
|
ReplaceColor(&contents, "LinkVisited", p, QPalette::LinkVisited);
|
||||||
|
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
contents.replace("darwin", "*");
|
contents.replace("macos", "*");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
widget->setStyleSheet("");
|
||||||
widget->setStyleSheet(contents);
|
widget->setStyleSheet(contents);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
@@ -105,10 +106,11 @@ void SystemTrayIcon::SetStopped() {
|
|||||||
UpdateIcon();
|
UpdateIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemTrayIcon* SystemTrayIcon::CreateSystemTrayIcon(QObject *parent) {
|
SystemTrayIcon *SystemTrayIcon::CreateSystemTrayIcon(QObject *parent) {
|
||||||
#ifdef Q_OS_MACOS
|
#ifdef Q_OS_MACOS
|
||||||
return new MacSystemTrayIcon(parent);
|
return new MacSystemTrayIcon(parent);
|
||||||
#else
|
#else
|
||||||
return new QtSystemTrayIcon(parent);
|
if (QSystemTrayIcon::isSystemTrayAvailable()) return new QtSystemTrayIcon(parent);
|
||||||
|
else return nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -23,12 +24,10 @@
|
|||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QIcon>
|
|
||||||
|
|
||||||
|
#include "song.h"
|
||||||
#include "urlhandler.h"
|
#include "urlhandler.h"
|
||||||
|
|
||||||
UrlHandler::LoadResult::LoadResult(const QUrl &original_url, Type type, const QUrl &media_url, qint64 length_nanosec) : original_url_(original_url), type_(type), media_url_(media_url), length_nanosec_(length_nanosec) {}
|
UrlHandler::LoadResult::LoadResult(const QUrl &original_url, Type type, const QUrl &media_url, const Song::FileType &filetype, qint64 length_nanosec) : original_url_(original_url), type_(type), media_url_(media_url), filetype_(filetype), length_nanosec_(length_nanosec) {}
|
||||||
|
|
||||||
UrlHandler::UrlHandler(QObject *parent) : QObject(parent) {}
|
UrlHandler::UrlHandler(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
QIcon UrlHandler::icon() const { return QIcon(); }
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -27,7 +28,8 @@
|
|||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QIcon>
|
|
||||||
|
#include "song.h"
|
||||||
|
|
||||||
class UrlHandler : public QObject {
|
class UrlHandler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -37,7 +39,6 @@ class UrlHandler : public QObject {
|
|||||||
|
|
||||||
// The URL scheme that this handler handles.
|
// The URL scheme that this handler handles.
|
||||||
virtual QString scheme() const = 0;
|
virtual QString scheme() const = 0;
|
||||||
virtual QIcon icon() const;
|
|
||||||
|
|
||||||
// Returned by StartLoading() and LoadNext(), indicates what the player should do when it wants to load a URL.
|
// Returned by StartLoading() and LoadNext(), indicates what the player should do when it wants to load a URL.
|
||||||
struct LoadResult {
|
struct LoadResult {
|
||||||
@@ -53,7 +54,7 @@ class UrlHandler : public QObject {
|
|||||||
TrackAvailable,
|
TrackAvailable,
|
||||||
};
|
};
|
||||||
|
|
||||||
LoadResult(const QUrl &original_url = QUrl(), Type type = NoMoreTracks, const QUrl &media_url = QUrl(), qint64 length_nanosec_ = -1);
|
LoadResult(const QUrl &original_url = QUrl(), Type type = NoMoreTracks, const QUrl &media_url = QUrl(), const Song::FileType &filetype = Song::FileType_Stream, qint64 length_nanosec_ = -1);
|
||||||
|
|
||||||
// The url that the playlist item has in Url().
|
// The url that the playlist item has in Url().
|
||||||
// Might be something unplayable like lastfm://...
|
// Might be something unplayable like lastfm://...
|
||||||
@@ -64,6 +65,9 @@ class UrlHandler : public QObject {
|
|||||||
// The actual url to something that gstreamer can play.
|
// The actual url to something that gstreamer can play.
|
||||||
QUrl media_url_;
|
QUrl media_url_;
|
||||||
|
|
||||||
|
// The type of the stream
|
||||||
|
Song::FileType filetype_;
|
||||||
|
|
||||||
// Track length, if we are able to get it only now
|
// Track length, if we are able to get it only now
|
||||||
qint64 length_nanosec_;
|
qint64 length_nanosec_;
|
||||||
};
|
};
|
||||||
@@ -78,8 +82,9 @@ class UrlHandler : public QObject {
|
|||||||
virtual void TrackAboutToEnd() {};
|
virtual void TrackAboutToEnd() {};
|
||||||
virtual void TrackSkipped() {};
|
virtual void TrackSkipped() {};
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void AsyncLoadComplete(const UrlHandler::LoadResult &result);
|
void AsyncLoadComplete(const UrlHandler::LoadResult &result);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // URLHANDLER_H
|
#endif // URLHANDLER_H
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -690,21 +691,6 @@ bool IsLaptop() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SystemLanguageName() {
|
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040800
|
|
||||||
QString system_language = QLocale::system().uiLanguages().empty() ? QLocale::system().name() : QLocale::system().uiLanguages().first();
|
|
||||||
// uiLanguages returns strings with "-" as separators for language/region;
|
|
||||||
// however QTranslator needs "_" separators
|
|
||||||
system_language.replace("-", "_");
|
|
||||||
#else
|
|
||||||
QString system_language = QLocale::system().name();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return system_language;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
bool UrlOnSameDriveAsStrawberry(const QUrl &url) {
|
bool UrlOnSameDriveAsStrawberry(const QUrl &url) {
|
||||||
|
|
||||||
if (url.scheme() != "file") return false;
|
if (url.scheme() != "file") return false;
|
||||||
@@ -723,18 +709,13 @@ bool UrlOnSameDriveAsStrawberry(const QUrl &url) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QUrl GetRelativePathToStrawberryBin(const QUrl &url) {
|
QUrl GetRelativePathToStrawberryBin(const QUrl &url) {
|
||||||
|
|
||||||
QDir appPath(QCoreApplication::applicationDirPath());
|
QDir appPath(QCoreApplication::applicationDirPath());
|
||||||
return QUrl::fromLocalFile(appPath.relativeFilePath(url.toLocalFile()));
|
return QUrl::fromLocalFile(appPath.relativeFilePath(url.toLocalFile()));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PathWithoutFilenameExtension(const QString &filename) {
|
QString PathWithoutFilenameExtension(const QString &filename) {
|
||||||
|
if (filename.section('/', -1, -1).contains('.')) return filename.section('.', 0, -2);
|
||||||
if (filename.section('/', -1, -1).contains('.'))
|
|
||||||
return filename.section('.', 0, -2);
|
|
||||||
return filename;
|
return filename;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FiddleFileExtension(const QString &filename, const QString &new_extension) {
|
QString FiddleFileExtension(const QString &filename, const QString &new_extension) {
|
||||||
@@ -786,6 +767,28 @@ void CheckPortable() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString GetRandomStringWithChars(const int len) {
|
||||||
|
const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
|
||||||
|
return GetRandomString(len, UseCharacters);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetRandomStringWithCharsAndNumbers(const int len) {
|
||||||
|
const QString UseCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
|
||||||
|
return GetRandomString(len, UseCharacters);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetRandomString(const int len, const QString &UseCharacters) {
|
||||||
|
|
||||||
|
QString randstr;
|
||||||
|
for(int i=0 ; i < len ; ++i) {
|
||||||
|
int index = qrand() % UseCharacters.length();
|
||||||
|
QChar nextchar = UseCharacters.at(index);
|
||||||
|
randstr.append(nextchar);
|
||||||
|
}
|
||||||
|
return randstr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Utilities
|
} // namespace Utilities
|
||||||
|
|
||||||
ScopedWCharArray::ScopedWCharArray(const QString &str)
|
ScopedWCharArray::ScopedWCharArray(const QString &str)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -149,7 +150,10 @@ int GetThreadId();
|
|||||||
// Returns true if this machine has a battery.
|
// Returns true if this machine has a battery.
|
||||||
bool IsLaptop();
|
bool IsLaptop();
|
||||||
|
|
||||||
QString SystemLanguageName();
|
QString GetRandomStringWithChars(const int len);
|
||||||
|
QString GetRandomStringWithCharsAndNumbers(const int len);
|
||||||
|
QString GetRandomString(const int len, const QString &UseCharacters);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ScopedWCharArray {
|
class ScopedWCharArray {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<string>Export covers</string>
|
<string>Export covers</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
@@ -202,6 +202,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -43,6 +43,8 @@
|
|||||||
#include "coverprovider.h"
|
#include "coverprovider.h"
|
||||||
#include "coverproviders.h"
|
#include "coverproviders.h"
|
||||||
|
|
||||||
|
using std::stable_sort;
|
||||||
|
|
||||||
const int AlbumCoverFetcherSearch::kSearchTimeoutMs = 12000;
|
const int AlbumCoverFetcherSearch::kSearchTimeoutMs = 12000;
|
||||||
const int AlbumCoverFetcherSearch::kImageLoadTimeoutMs = 3000;
|
const int AlbumCoverFetcherSearch::kImageLoadTimeoutMs = 3000;
|
||||||
const int AlbumCoverFetcherSearch::kTargetSize = 500;
|
const int AlbumCoverFetcherSearch::kTargetSize = 500;
|
||||||
@@ -148,7 +150,7 @@ void AlbumCoverFetcherSearch::AllProvidersFinished() {
|
|||||||
// Now we have to load some images and figure out which one is the best.
|
// Now we have to load some images and figure out which one is the best.
|
||||||
// We'll sort the list of results by category, then load the first few images from each category and use some heuristics to score them.
|
// We'll sort the list of results by category, then load the first few images from each category and use some heuristics to score them.
|
||||||
// If no images are good enough we'll keep loading more images until we find one that is or we run out of results.
|
// If no images are good enough we'll keep loading more images until we find one that is or we run out of results.
|
||||||
qStableSort(results_.begin(), results_.end(), CompareProviders);
|
std::stable_sort(results_.begin(), results_.end(), CompareProviders);
|
||||||
FetchMoreImages();
|
FetchMoreImages();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -81,6 +82,8 @@
|
|||||||
|
|
||||||
#include "ui_albumcovermanager.h"
|
#include "ui_albumcovermanager.h"
|
||||||
|
|
||||||
|
using std::stable_sort;
|
||||||
|
|
||||||
const char *AlbumCoverManager::kSettingsGroup = "CoverManager";
|
const char *AlbumCoverManager::kSettingsGroup = "CoverManager";
|
||||||
|
|
||||||
AlbumCoverManager::AlbumCoverManager(Application *app, CollectionBackend *collection_backend, QWidget *parent, QNetworkAccessManager *network)
|
AlbumCoverManager::AlbumCoverManager(Application *app, CollectionBackend *collection_backend, QWidget *parent, QNetworkAccessManager *network)
|
||||||
@@ -286,7 +289,7 @@ void AlbumCoverManager::Reset() {
|
|||||||
new QListWidgetItem(artist_icon_, tr("Various artists"), ui_->artists, Various_Artists);
|
new QListWidgetItem(artist_icon_, tr("Various artists"), ui_->artists, Various_Artists);
|
||||||
|
|
||||||
QStringList artists(collection_backend_->GetAllArtistsWithAlbums());
|
QStringList artists(collection_backend_->GetAllArtistsWithAlbums());
|
||||||
qStableSort(artists.begin(), artists.end(), CompareNocase);
|
std::stable_sort(artists.begin(), artists.end(), CompareNocase);
|
||||||
|
|
||||||
for (const QString &artist : artists) {
|
for (const QString &artist : artists) {
|
||||||
if (artist.isEmpty()) continue;
|
if (artist.isEmpty()) continue;
|
||||||
@@ -326,7 +329,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort by album name. The list is already sorted by sqlite but it was done case sensitively.
|
// Sort by album name. The list is already sorted by sqlite but it was done case sensitively.
|
||||||
qStableSort(albums.begin(), albums.end(), CompareAlbumNameNocase);
|
std::stable_sort(albums.begin(), albums.end(), CompareAlbumNameNocase);
|
||||||
|
|
||||||
for (const CollectionBackend::Album &info : albums) {
|
for (const CollectionBackend::Album &info : albums) {
|
||||||
// Don't show songs without an album, obviously
|
// Don't show songs without an album, obviously
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Cover Manager</string>
|
<string>Cover Manager</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="centralWidget">
|
<widget class="QWidget" name="centralWidget">
|
||||||
@@ -297,6 +297,7 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections/>
|
<connections/>
|
||||||
</ui>
|
</ui>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Load cover from URL</string>
|
<string>Load cover from URL</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
@@ -79,6 +79,7 @@
|
|||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void CoverProviders::RemoveProvider(CoverProvider *provider) {
|
|||||||
|
|
||||||
if (!provider) return;
|
if (!provider) return;
|
||||||
|
|
||||||
// It's not safe to dereference provider at this pointbecause it might have already been destroyed.
|
// It's not safe to dereference provider at this point because it might have already been destroyed.
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@@ -34,6 +36,8 @@
|
|||||||
#include "coversearchstatisticsdialog.h"
|
#include "coversearchstatisticsdialog.h"
|
||||||
#include "ui_coversearchstatisticsdialog.h"
|
#include "ui_coversearchstatisticsdialog.h"
|
||||||
|
|
||||||
|
using std::sort;
|
||||||
|
|
||||||
CoverSearchStatisticsDialog::CoverSearchStatisticsDialog(QWidget *parent)
|
CoverSearchStatisticsDialog::CoverSearchStatisticsDialog(QWidget *parent)
|
||||||
: QDialog(parent), ui_(new Ui_CoverSearchStatisticsDialog) {
|
: QDialog(parent), ui_(new Ui_CoverSearchStatisticsDialog) {
|
||||||
|
|
||||||
@@ -61,7 +65,7 @@ CoverSearchStatisticsDialog::~CoverSearchStatisticsDialog() { delete ui_; }
|
|||||||
void CoverSearchStatisticsDialog::Show(const CoverSearchStatistics &statistics) {
|
void CoverSearchStatisticsDialog::Show(const CoverSearchStatistics &statistics) {
|
||||||
|
|
||||||
QStringList providers(statistics.total_images_by_provider_.keys());
|
QStringList providers(statistics.total_images_by_provider_.keys());
|
||||||
qSort(providers);
|
std::sort(providers.begin(), providers.end());
|
||||||
|
|
||||||
ui_->summary->setText(tr("Got %1 covers out of %2 (%3 failed)")
|
ui_->summary->setText(tr("Got %1 covers out of %2 (%3 failed)")
|
||||||
.arg(statistics.chosen_images_)
|
.arg(statistics.chosen_images_)
|
||||||
|
|||||||
838
src/deezer/deezerservice.cpp
Normal file
@@ -0,0 +1,838 @@
|
|||||||
|
/*
|
||||||
|
* Strawberry Music Player
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
|
*
|
||||||
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Strawberry is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
# include <dzmedia.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QList>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QPair>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QJsonParseError>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonValue>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
|
#include "core/application.h"
|
||||||
|
#include "core/player.h"
|
||||||
|
#include "core/closure.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
#include "core/mergedproxymodel.h"
|
||||||
|
#include "core/network.h"
|
||||||
|
#include "core/song.h"
|
||||||
|
#include "core/iconloader.h"
|
||||||
|
#include "core/taskmanager.h"
|
||||||
|
#include "core/timeconstants.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
|
#include "internet/internetservices.h"
|
||||||
|
#include "internet/internetsearch.h"
|
||||||
|
#include "internet/localredirectserver.h"
|
||||||
|
#include "deezerservice.h"
|
||||||
|
#include "deezerurlhandler.h"
|
||||||
|
#include "settings/deezersettingspage.h"
|
||||||
|
|
||||||
|
const Song::Source DeezerService::kSource = Song::Source_Deezer;
|
||||||
|
const char *DeezerService::kApiUrl = "https://api.deezer.com";
|
||||||
|
const char *DeezerService::kOAuthUrl = "https://connect.deezer.com/oauth/auth.php";
|
||||||
|
const char *DeezerService::kOAuthAccessTokenUrl = "https://connect.deezer.com/oauth/access_token.php";
|
||||||
|
const char *DeezerService::kOAuthRedirectUrl = "https://oauth.strawbs.net";
|
||||||
|
const int DeezerService::kAppID = 303684;
|
||||||
|
const char *DeezerService::kSecretKey = "06911976010b9ddd7256769adf2b2e56";
|
||||||
|
|
||||||
|
typedef QPair<QString, QString> Param;
|
||||||
|
|
||||||
|
DeezerService::DeezerService(Application *app, QObject *parent)
|
||||||
|
: InternetService(Song::Source_Deezer, "Deezer", "dzmedia", app, parent),
|
||||||
|
network_(new NetworkAccessManager(this)),
|
||||||
|
url_handler_(new DeezerUrlHandler(app, this)),
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
dzmedia_(new DZMedia(this)),
|
||||||
|
#endif
|
||||||
|
timer_searchdelay_(new QTimer(this)),
|
||||||
|
searchdelay_(1500),
|
||||||
|
albumssearchlimit_(1),
|
||||||
|
songssearchlimit_(1),
|
||||||
|
fetchalbums_(false),
|
||||||
|
preview_(false),
|
||||||
|
pending_search_id_(0),
|
||||||
|
next_pending_search_id_(1),
|
||||||
|
search_id_(0),
|
||||||
|
albums_requested_(0),
|
||||||
|
albums_received_(0)
|
||||||
|
{
|
||||||
|
|
||||||
|
timer_searchdelay_->setSingleShot(true);
|
||||||
|
connect(timer_searchdelay_, SIGNAL(timeout()), SLOT(StartSearch()));
|
||||||
|
|
||||||
|
connect(this, SIGNAL(Authenticated()), app->player(), SLOT(HandleAuthentication()));
|
||||||
|
|
||||||
|
app->player()->RegisterUrlHandler(url_handler_);
|
||||||
|
|
||||||
|
ReloadSettings();
|
||||||
|
LoadAccessToken();
|
||||||
|
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
connect(dzmedia_, SIGNAL(StreamURLReceived(QUrl, QUrl, DZMedia::FileType)), this, SLOT(GetStreamURLFinished(QUrl, QUrl, DZMedia::FileType)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DeezerService::~DeezerService() {}
|
||||||
|
|
||||||
|
void DeezerService::ShowConfig() {
|
||||||
|
app_->OpenSettingsDialogAtPage(SettingsDialog::Page_Deezer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::ReloadSettings() {
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
|
||||||
|
quality_ = s.value("quality", "FLAC").toString();
|
||||||
|
searchdelay_ = s.value("searchdelay", 1500).toInt();
|
||||||
|
albumssearchlimit_ = s.value("albumssearchlimit", 100).toInt();
|
||||||
|
songssearchlimit_ = s.value("songssearchlimit", 100).toInt();
|
||||||
|
fetchalbums_ = s.value("fetchalbums", false).toBool();
|
||||||
|
coversize_ = s.value("coversize", "cover_big").toString();
|
||||||
|
#if defined(HAVE_DEEZER) || defined(HAVE_DZMEDIA)
|
||||||
|
bool preview(false);
|
||||||
|
#else
|
||||||
|
bool preview(true);
|
||||||
|
#endif
|
||||||
|
preview_ = s.value("preview", preview).toBool();
|
||||||
|
s.endGroup();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::LoadAccessToken() {
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
|
||||||
|
if (s.contains("access_token") && s.contains("expiry_time")) {
|
||||||
|
access_token_ = s.value("access_token").toString();
|
||||||
|
expiry_time_ = s.value("expiry_time").toDateTime();
|
||||||
|
}
|
||||||
|
s.endGroup();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::Logout() {
|
||||||
|
|
||||||
|
access_token_.clear();
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
|
||||||
|
s.remove("access_token");
|
||||||
|
s.remove("expiry_time");
|
||||||
|
s.endGroup();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::StartAuthorisation() {
|
||||||
|
|
||||||
|
LocalRedirectServer *server = new LocalRedirectServer(this);
|
||||||
|
server->Listen();
|
||||||
|
|
||||||
|
QUrl url = QUrl(kOAuthUrl);
|
||||||
|
QUrlQuery url_query;
|
||||||
|
//url_query.addQueryItem("response_type", "token");
|
||||||
|
url_query.addQueryItem("response_type", "code");
|
||||||
|
url_query.addQueryItem("app_id", QString::number(kAppID));
|
||||||
|
QUrl redirect_url;
|
||||||
|
QUrlQuery redirect_url_query;
|
||||||
|
|
||||||
|
const QString port = QString::number(server->url().port());
|
||||||
|
|
||||||
|
redirect_url = QUrl(kOAuthRedirectUrl);
|
||||||
|
redirect_url_query.addQueryItem("port", port);
|
||||||
|
redirect_url.setQuery(redirect_url_query);
|
||||||
|
url_query.addQueryItem("redirect_uri", redirect_url.toString());
|
||||||
|
url.setQuery(url_query);
|
||||||
|
|
||||||
|
NewClosure(server, SIGNAL(Finished()), this, &DeezerService::RedirectArrived, server, redirect_url);
|
||||||
|
QDesktopServices::openUrl(url);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::RedirectArrived(LocalRedirectServer *server, QUrl url) {
|
||||||
|
|
||||||
|
server->deleteLater();
|
||||||
|
QUrl request_url = server->request_url();
|
||||||
|
RequestAccessToken(QUrlQuery(request_url).queryItemValue("code").toUtf8());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::RequestAccessToken(const QByteArray &code) {
|
||||||
|
|
||||||
|
typedef QPair<QString, QString> Arg;
|
||||||
|
typedef QList<Arg> ArgList;
|
||||||
|
|
||||||
|
typedef QPair<QByteArray, QByteArray> EncodedArg;
|
||||||
|
typedef QList<EncodedArg> EncodedArgList;
|
||||||
|
|
||||||
|
ArgList args = ArgList() << Arg("app_id", QString::number(kAppID))
|
||||||
|
<< Arg("secret", kSecretKey)
|
||||||
|
<< Arg("code", code);
|
||||||
|
|
||||||
|
QUrlQuery url_query;
|
||||||
|
for (const Arg &arg : args) {
|
||||||
|
EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), QUrl::toPercentEncoding(arg.second));
|
||||||
|
url_query.addQueryItem(encoded_arg.first, encoded_arg.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl url(kOAuthAccessTokenUrl);
|
||||||
|
QNetworkRequest request = QNetworkRequest(url);
|
||||||
|
QNetworkReply *reply = network_->post(request, url_query.toString(QUrl::FullyEncoded).toUtf8());
|
||||||
|
NewClosure(reply, SIGNAL(finished()), this, SLOT(FetchAccessTokenFinished(QNetworkReply*)), reply);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::FetchAccessTokenFinished(QNetworkReply *reply) {
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (reply->error() != QNetworkReply::NoError) {
|
||||||
|
Error(QString("%1 (%2)").arg(reply->errorString()).arg(reply->error()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forever {
|
||||||
|
QByteArray line = reply->readLine();
|
||||||
|
QString str(line);
|
||||||
|
QStringList args = str.split("&");
|
||||||
|
for (QString arg : args) {
|
||||||
|
QStringList params = arg.split("=");
|
||||||
|
if (params.count() < 2) continue;
|
||||||
|
QString param1 = params.first();
|
||||||
|
QString param2 = params[1];
|
||||||
|
if (param1 == "access_token") access_token_ = param2;
|
||||||
|
else if (param1 == "expires") SetExpiryTime(param2.toInt());
|
||||||
|
}
|
||||||
|
if (reply->atEnd()) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSettings s;
|
||||||
|
s.beginGroup(DeezerSettingsPage::kSettingsGroup);
|
||||||
|
s.setValue("access_token", access_token_);
|
||||||
|
s.setValue("expiry_time", expiry_time_);
|
||||||
|
s.endGroup();
|
||||||
|
|
||||||
|
emit Authenticated();
|
||||||
|
emit LoginSuccess();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::SetExpiryTime(int expires_in_seconds) {
|
||||||
|
|
||||||
|
// Set the expiry time with two minutes' grace.
|
||||||
|
expiry_time_ = QDateTime::currentDateTime().addSecs(expires_in_seconds - 120);
|
||||||
|
qLog(Debug) << "Current oauth access token expires at:" << expiry_time_;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply *DeezerService::CreateRequest(const QString &ressource_name, const QList<Param> ¶ms) {
|
||||||
|
|
||||||
|
typedef QPair<QString, QString> Arg;
|
||||||
|
typedef QList<Arg> ArgList;
|
||||||
|
|
||||||
|
typedef QPair<QByteArray, QByteArray> EncodedArg;
|
||||||
|
typedef QList<EncodedArg> EncodedArgList;
|
||||||
|
|
||||||
|
ArgList args = ArgList() << Arg("access_token", access_token_)
|
||||||
|
<< Arg("output", "json")
|
||||||
|
<< params;
|
||||||
|
|
||||||
|
QUrlQuery url_query;
|
||||||
|
for (const Arg& arg : args) {
|
||||||
|
EncodedArg encoded_arg(QUrl::toPercentEncoding(arg.first), QUrl::toPercentEncoding(arg.second));
|
||||||
|
url_query.addQueryItem(encoded_arg.first, encoded_arg.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl url(kApiUrl + QString("/") + ressource_name);
|
||||||
|
url.setQuery(url_query);
|
||||||
|
QNetworkRequest req(url);
|
||||||
|
QNetworkReply *reply = network_->get(req);
|
||||||
|
|
||||||
|
//qLog(Debug) << "Deezer: Sending request" << url;
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray DeezerService::GetReplyData(QNetworkReply *reply) {
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
|
||||||
|
if (reply->error() == QNetworkReply::NoError && reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 200) {
|
||||||
|
data = reply->readAll();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (reply->error() < 200) {
|
||||||
|
// This is a network error, there is nothing more to do.
|
||||||
|
QString failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error());
|
||||||
|
Error(failure_reason);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// See if there is Json data containing "error" - then use that instead.
|
||||||
|
data = reply->readAll();
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument json_doc = QJsonDocument::fromJson(data, &error);
|
||||||
|
QString failure_reason;
|
||||||
|
if (error.error == QJsonParseError::NoError && !json_doc.isNull() && !json_doc.isEmpty() && json_doc.isObject()) {
|
||||||
|
QJsonObject json_obj = json_doc.object();
|
||||||
|
if (json_obj.contains("error")) {
|
||||||
|
QJsonValue json_value_error = json_obj["error"];
|
||||||
|
if (json_value_error.isObject()) {
|
||||||
|
QJsonObject json_error = json_value_error.toObject();
|
||||||
|
int code = json_error["code"].toInt();
|
||||||
|
if (code == 300) Logout();
|
||||||
|
QString message = json_error["message"].toString();
|
||||||
|
QString type = json_error["type"].toString();
|
||||||
|
failure_reason = QString("%1 (%2)").arg(message).arg(code);
|
||||||
|
}
|
||||||
|
else { failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error()); }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
failure_reason = QString("%1 (%2)").arg(reply->errorString()).arg(reply->error());
|
||||||
|
}
|
||||||
|
if (reply->error() == QNetworkReply::ContentAccessDenied || reply->error() == QNetworkReply::ContentOperationNotPermittedError || reply->error() == QNetworkReply::AuthenticationRequiredError) {
|
||||||
|
// Session is probably expired
|
||||||
|
Logout();
|
||||||
|
Error(failure_reason);
|
||||||
|
}
|
||||||
|
else if (reply->error() == QNetworkReply::ContentNotFoundError) { // Ignore this error
|
||||||
|
Error(failure_reason);
|
||||||
|
}
|
||||||
|
else { // Fail
|
||||||
|
Error(failure_reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject DeezerService::ExtractJsonObj(QByteArray &data) {
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
QJsonDocument json_doc = QJsonDocument::fromJson(data, &error);
|
||||||
|
|
||||||
|
//qLog(Debug) << json_doc;
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
Error("Reply from server missing Json data.", data);
|
||||||
|
return QJsonObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_doc.isNull() || json_doc.isEmpty()) {
|
||||||
|
Error("Received empty Json document.", json_doc);
|
||||||
|
return QJsonObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_doc.isObject()) {
|
||||||
|
Error("Json document is not an object.", json_doc);
|
||||||
|
return QJsonObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonObject json_obj = json_doc.object();
|
||||||
|
if (json_obj.isEmpty()) {
|
||||||
|
Error("Received empty Json object.", json_doc);
|
||||||
|
return QJsonObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
//qLog(Debug) << json_obj;
|
||||||
|
|
||||||
|
return json_obj;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonValue DeezerService::ExtractData(QByteArray &data) {
|
||||||
|
|
||||||
|
QJsonObject json_obj = ExtractJsonObj(data);
|
||||||
|
if (json_obj.isEmpty()) return QJsonObject();
|
||||||
|
|
||||||
|
if (json_obj.contains("error")) {
|
||||||
|
QJsonValue json_value_error = json_obj["error"];
|
||||||
|
if (!json_value_error.isObject()) {
|
||||||
|
Error("Error missing object", json_obj);
|
||||||
|
return QJsonValue();
|
||||||
|
}
|
||||||
|
QJsonObject json_error = json_value_error.toObject();
|
||||||
|
int code = json_error["code"].toInt();
|
||||||
|
if (code == 300) Logout();
|
||||||
|
QString message = json_error["message"].toString();
|
||||||
|
QString type = json_error["type"].toString();
|
||||||
|
Error(QString("%1 (%2)").arg(message).arg(code));
|
||||||
|
return QJsonValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!json_obj.contains("data") && !json_obj.contains("DATA")) {
|
||||||
|
Error("Json reply is missing data.", json_obj);
|
||||||
|
return QJsonValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonValue json_data;
|
||||||
|
if (json_obj.contains("data")) json_data = json_obj["data"];
|
||||||
|
else json_data = json_obj["DATA"];
|
||||||
|
|
||||||
|
return json_data;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int DeezerService::Search(const QString &text, InternetSearch::SearchBy searchby) {
|
||||||
|
|
||||||
|
pending_search_id_ = next_pending_search_id_;
|
||||||
|
pending_search_text_ = text;
|
||||||
|
pending_searchby_ = searchby;
|
||||||
|
|
||||||
|
next_pending_search_id_++;
|
||||||
|
|
||||||
|
if (text.isEmpty()) {
|
||||||
|
timer_searchdelay_->stop();
|
||||||
|
return pending_search_id_;
|
||||||
|
}
|
||||||
|
timer_searchdelay_->setInterval(searchdelay_);
|
||||||
|
timer_searchdelay_->start();
|
||||||
|
|
||||||
|
return pending_search_id_;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::StartSearch() {
|
||||||
|
|
||||||
|
if (access_token_.isEmpty()) {
|
||||||
|
emit SearchError(pending_search_id_, "Not authenticated.");
|
||||||
|
next_pending_search_id_ = 1;
|
||||||
|
ShowConfig();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ClearSearch();
|
||||||
|
search_id_ = pending_search_id_;
|
||||||
|
search_text_ = pending_search_text_;
|
||||||
|
|
||||||
|
SendSearch();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::CancelSearch() {
|
||||||
|
ClearSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::ClearSearch() {
|
||||||
|
search_id_ = 0;
|
||||||
|
search_text_.clear();
|
||||||
|
search_error_.clear();
|
||||||
|
albums_requested_ = 0;
|
||||||
|
albums_received_ = 0;
|
||||||
|
requests_album_.clear();
|
||||||
|
requests_song_.clear();
|
||||||
|
songs_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::SendSearch() {
|
||||||
|
|
||||||
|
emit UpdateStatus("Searching...");
|
||||||
|
|
||||||
|
QList<Param> parameters;
|
||||||
|
parameters << Param("q", search_text_);
|
||||||
|
QString searchparam;
|
||||||
|
switch (pending_searchby_) {
|
||||||
|
case InternetSearch::SearchBy_Songs:
|
||||||
|
searchparam = "search/track";
|
||||||
|
parameters << Param("limit", QString::number(songssearchlimit_));
|
||||||
|
break;
|
||||||
|
case InternetSearch::SearchBy_Albums:
|
||||||
|
default:
|
||||||
|
searchparam = "search/album";
|
||||||
|
parameters << Param("limit", QString::number(albumssearchlimit_));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QNetworkReply *reply = CreateRequest(searchparam, parameters);
|
||||||
|
NewClosure(reply, SIGNAL(finished()), this, SLOT(SearchFinished(QNetworkReply*, int)), reply, search_id_);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::SearchFinished(QNetworkReply *reply, int id) {
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (id != search_id_) return;
|
||||||
|
|
||||||
|
QByteArray data = GetReplyData(reply);
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonValue json_value = ExtractData(data);
|
||||||
|
if (!json_value.isArray()) {
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray json_data = json_value.toArray();
|
||||||
|
if (json_data.isEmpty()) {
|
||||||
|
Error("No match.");
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//qLog(Debug) << json_data;
|
||||||
|
|
||||||
|
for (const QJsonValue &value : json_data) {
|
||||||
|
//qLog(Debug) << value;
|
||||||
|
if (!value.isObject()) {
|
||||||
|
Error("Invalid Json reply, data is not an object.", value);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QJsonObject json_obj = value.toObject();
|
||||||
|
//qLog(Debug) << json_obj;
|
||||||
|
|
||||||
|
if (!json_obj.contains("id") || !json_obj.contains("type")) {
|
||||||
|
Error("Invalid Json reply, item is missing ID or type.", json_obj);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//int id = json_obj["id"].toInt();
|
||||||
|
QString type = json_obj["type"].toString();
|
||||||
|
|
||||||
|
if (!json_obj.contains("artist")) {
|
||||||
|
Error("Invalid Json reply, item missing artist.", json_obj);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QJsonValue json_value_artist = json_obj["artist"];
|
||||||
|
if (!json_value_artist.isObject()) {
|
||||||
|
Error("Invalid Json reply, item artist is not a object.", json_value_artist);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QJsonObject json_artist = json_value_artist.toObject();
|
||||||
|
|
||||||
|
if (!json_artist.contains("name")) {
|
||||||
|
Error("Invalid Json reply, artist data missing name.", json_artist);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QString artist = json_artist["name"].toString();
|
||||||
|
int album_id(0);
|
||||||
|
QString album;
|
||||||
|
QString cover;
|
||||||
|
|
||||||
|
if (type == "album") {
|
||||||
|
album_id = json_obj["id"].toInt();
|
||||||
|
album = json_obj["title"].toString();
|
||||||
|
cover = json_obj[coversize_].toString();
|
||||||
|
}
|
||||||
|
else if (type == "track") {
|
||||||
|
|
||||||
|
if (!json_obj.contains("album")) {
|
||||||
|
Error("Invalid Json reply, missing album data.", json_obj);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QJsonValue json_value_album = json_obj["album"];
|
||||||
|
if (!json_value_album.isObject()) {
|
||||||
|
Error("Invalid Json reply, album data is not an object.", json_value_album);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
QJsonObject json_album = json_value_album.toObject();
|
||||||
|
if (!json_album.contains("id") || !json_album.contains("title")) {
|
||||||
|
Error("Invalid Json reply, album data is missing ID or title.", json_album);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
album_id = json_album["id"].toInt();
|
||||||
|
album = json_album["title"].toString();
|
||||||
|
cover = json_album[coversize_].toString();
|
||||||
|
if (!fetchalbums_) {
|
||||||
|
Song song = ParseSong(album_id, album, cover, value);
|
||||||
|
songs_ << song;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DeezerAlbumContext *album_ctx;
|
||||||
|
if (requests_album_.contains(album_id)) {
|
||||||
|
album_ctx = requests_album_.value(album_id);
|
||||||
|
album_ctx->search_id = search_id_;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
album_ctx = CreateAlbum(album_id, artist, album, cover);
|
||||||
|
GetAlbum(album_ctx);
|
||||||
|
albums_requested_++;
|
||||||
|
if (albums_requested_ >= albumssearchlimit_) break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (albums_requested_ > 0) {
|
||||||
|
emit UpdateStatus(QString("Retriving %1 album%2...").arg(albums_requested_).arg(albums_requested_ == 1 ? "" : "s"));
|
||||||
|
emit ProgressSetMaximum(albums_requested_);
|
||||||
|
emit UpdateProgress(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckFinish();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
DeezerAlbumContext *DeezerService::CreateAlbum(const int album_id, const QString &artist, const QString &album, const QString &cover) {
|
||||||
|
|
||||||
|
DeezerAlbumContext *album_ctx = new DeezerAlbumContext;
|
||||||
|
album_ctx->id = album_id;
|
||||||
|
album_ctx->artist = artist;
|
||||||
|
album_ctx->album = album;
|
||||||
|
album_ctx->cover = cover;
|
||||||
|
album_ctx->cover_url.setUrl(cover);
|
||||||
|
requests_album_.insert(album_id, album_ctx);
|
||||||
|
|
||||||
|
return album_ctx;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::GetAlbum(const DeezerAlbumContext *album_ctx) {
|
||||||
|
|
||||||
|
QList<Param> parameters;
|
||||||
|
QNetworkReply *reply = CreateRequest(QString("album/%1/tracks").arg(album_ctx->id), parameters);
|
||||||
|
NewClosure(reply, SIGNAL(finished()), this, SLOT(GetAlbumFinished(QNetworkReply*, int, int)), reply, search_id_, album_ctx->id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::GetAlbumFinished(QNetworkReply *reply, int search_id, int album_id) {
|
||||||
|
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
if (!requests_album_.contains(album_id)) {
|
||||||
|
qLog(Error) << "Deezer: Got reply for cancelled album request: " << album_id;
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DeezerAlbumContext *album_ctx = requests_album_.value(album_id);
|
||||||
|
|
||||||
|
if (search_id != search_id_) {
|
||||||
|
if (album_ctx->search_id == search_id) delete requests_album_.take(album_ctx->id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
albums_received_++;
|
||||||
|
emit UpdateProgress(albums_received_);
|
||||||
|
|
||||||
|
QByteArray data = GetReplyData(reply);
|
||||||
|
if (data.isEmpty()) {
|
||||||
|
delete requests_album_.take(album_ctx->id);
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonValue json_value = ExtractData(data);
|
||||||
|
if (!json_value.isArray()) {
|
||||||
|
delete requests_album_.take(album_ctx->id);
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonArray json_data = json_value.toArray();
|
||||||
|
if (json_data.isEmpty()) {
|
||||||
|
delete requests_album_.take(album_ctx->id);
|
||||||
|
CheckFinish();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool compilation = false;
|
||||||
|
bool multidisc = false;
|
||||||
|
Song first_song;
|
||||||
|
SongList songs;
|
||||||
|
for (const QJsonValue &value : json_data) {
|
||||||
|
Song song = ParseSong(album_ctx->id, album_ctx->album, album_ctx->cover, value);
|
||||||
|
if (!song.is_valid()) continue;
|
||||||
|
if (song.disc() >= 2) multidisc = true;
|
||||||
|
if (song.is_compilation() || (first_song.is_valid() && song.artist() != first_song.artist())) compilation = true;
|
||||||
|
if (!first_song.is_valid()) first_song = song;
|
||||||
|
songs << song;
|
||||||
|
}
|
||||||
|
for (Song &song : songs) {
|
||||||
|
if (compilation) song.set_compilation_detected(true);
|
||||||
|
if (multidisc) {
|
||||||
|
QString album_full(QString("%1 - (Disc %2)").arg(song.album()).arg(song.disc()));
|
||||||
|
song.set_album(album_full);
|
||||||
|
}
|
||||||
|
songs_ << song;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete requests_album_.take(album_ctx->id);
|
||||||
|
CheckFinish();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Song DeezerService::ParseSong(const int album_id, const QString &album, const QString &album_cover, const QJsonValue &value) {
|
||||||
|
|
||||||
|
if (!value.isObject()) {
|
||||||
|
Error("Invalid Json reply, track is not an object.", value);
|
||||||
|
return Song();
|
||||||
|
}
|
||||||
|
QJsonObject json_obj = value.toObject();
|
||||||
|
|
||||||
|
//qLog(Debug) << json_obj;
|
||||||
|
|
||||||
|
if (
|
||||||
|
!json_obj.contains("id") ||
|
||||||
|
!json_obj.contains("title") ||
|
||||||
|
!json_obj.contains("artist") ||
|
||||||
|
!json_obj.contains("duration") ||
|
||||||
|
!json_obj.contains("preview")
|
||||||
|
) {
|
||||||
|
Error("Invalid Json reply, track is missing one or more values.", json_obj);
|
||||||
|
return Song();
|
||||||
|
}
|
||||||
|
|
||||||
|
int song_id = json_obj["id"].toInt();
|
||||||
|
QString title = json_obj["title"].toString();
|
||||||
|
QJsonValue json_value_artist = json_obj["artist"];
|
||||||
|
QVariant q_duration = json_obj["duration"].toVariant();
|
||||||
|
int track(0);
|
||||||
|
if (json_obj.contains("track_position")) track = json_obj["track_position"].toInt();
|
||||||
|
int disc(0);
|
||||||
|
if (json_obj.contains("disk_number")) disc = json_obj["disk_number"].toInt();
|
||||||
|
QString preview = json_obj["preview"].toString();
|
||||||
|
|
||||||
|
if (!json_value_artist.isObject()) {
|
||||||
|
Error("Invalid Json reply, track artist is not an object.", json_value_artist);
|
||||||
|
return Song();
|
||||||
|
}
|
||||||
|
QJsonObject json_artist = json_value_artist.toObject();
|
||||||
|
if (!json_artist.contains("name")) {
|
||||||
|
Error("Invalid Json reply, track artist is missing name.", json_artist);
|
||||||
|
return Song();
|
||||||
|
}
|
||||||
|
QString artist = json_artist["name"].toString();
|
||||||
|
|
||||||
|
Song song;
|
||||||
|
song.set_source(Song::Source_Deezer);
|
||||||
|
song.set_id(song_id);
|
||||||
|
song.set_album_id(album_id);
|
||||||
|
song.set_artist(artist);
|
||||||
|
song.set_album(album);
|
||||||
|
song.set_title(title);
|
||||||
|
song.set_disc(disc);
|
||||||
|
song.set_track(track);
|
||||||
|
song.set_art_automatic(album_cover);
|
||||||
|
|
||||||
|
QUrl url;
|
||||||
|
if (preview_) {
|
||||||
|
url.setUrl(preview);
|
||||||
|
quint64 duration = (30 * kNsecPerSec);
|
||||||
|
song.set_length_nanosec(duration);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
url.setScheme(url_handler_->scheme());
|
||||||
|
url.setPath(QString("track/%1").arg(QString::number(song_id)));
|
||||||
|
if (q_duration.isValid()) {
|
||||||
|
quint64 duration = q_duration.toULongLong() * kNsecPerSec;
|
||||||
|
song.set_length_nanosec(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
song.set_url(url);
|
||||||
|
|
||||||
|
song.set_valid(true);
|
||||||
|
|
||||||
|
return song;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DeezerService::GetStreamURL(const QUrl &original_url) {
|
||||||
|
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
stream_request_url_ = original_url;
|
||||||
|
dzmedia_->GetStreamURL(original_url);
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
stream_request_url_ = QUrl();
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
void DeezerService::GetStreamURLFinished(const QUrl original_url, const QUrl media_url, const DZMedia::FileType dzmedia_filetype) {
|
||||||
|
|
||||||
|
Song::FileType filetype(Song::FileType_Unknown);
|
||||||
|
|
||||||
|
switch (dzmedia_filetype) {
|
||||||
|
case DZMedia::FileType_FLAC:
|
||||||
|
filetype = Song::FileType_FLAC;
|
||||||
|
break;
|
||||||
|
case DZMedia::FileType_MPEG:
|
||||||
|
filetype = Song::FileType_MPEG;
|
||||||
|
break;
|
||||||
|
case DZMedia::FileType_Stream:
|
||||||
|
filetype = Song::FileType_Stream;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
filetype = Song::FileType_Unknown;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stream_request_url_ = QUrl();
|
||||||
|
emit StreamURLReceived(original_url, media_url, filetype);
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void DeezerService::CheckFinish() {
|
||||||
|
|
||||||
|
if (search_id_ == 0) return;
|
||||||
|
|
||||||
|
if (albums_requested_ <= albums_received_) {
|
||||||
|
if (songs_.isEmpty()) {
|
||||||
|
if (search_error_.isEmpty()) emit SearchError(search_id_, "Unknown error");
|
||||||
|
else emit SearchError(search_id_, search_error_);
|
||||||
|
}
|
||||||
|
else emit SearchResults(search_id_, songs_);
|
||||||
|
ClearSearch();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerService::Error(QString error, QVariant debug) {
|
||||||
|
qLog(Error) << "Deezer:" << error;
|
||||||
|
if (debug.isValid()) qLog(Debug) << debug;
|
||||||
|
if (search_id_ != 0) {
|
||||||
|
if (!error.isEmpty()) {
|
||||||
|
search_error_ += error;
|
||||||
|
search_error_ += "<br />";
|
||||||
|
}
|
||||||
|
CheckFinish();
|
||||||
|
}
|
||||||
|
if (!stream_request_url_.isEmpty()) {
|
||||||
|
emit StreamURLReceived(stream_request_url_, stream_request_url_, Song::FileType_Stream);
|
||||||
|
stream_request_url_ = QUrl();
|
||||||
|
}
|
||||||
|
}
|
||||||
163
src/deezer/deezerservice.h
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Strawberry Music Player
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
|
*
|
||||||
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Strawberry is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEEZERSERVICE_H
|
||||||
|
#define DEEZERSERVICE_H
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
# include <dzmedia.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QObject>
|
||||||
|
#include <QHash>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QJsonObject>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonValue>
|
||||||
|
|
||||||
|
#include "core/song.h"
|
||||||
|
#include "internet/internetservices.h"
|
||||||
|
#include "internet/internetservice.h"
|
||||||
|
#include "internet/internetsearch.h"
|
||||||
|
|
||||||
|
class NetworkAccessManager;
|
||||||
|
class LocalRedirectServer;
|
||||||
|
class DeezerUrlHandler;
|
||||||
|
|
||||||
|
struct DeezerAlbumContext {
|
||||||
|
int id;
|
||||||
|
int search_id;
|
||||||
|
QString artist;
|
||||||
|
QString album;
|
||||||
|
QString cover;
|
||||||
|
QUrl cover_url;
|
||||||
|
};
|
||||||
|
Q_DECLARE_METATYPE(DeezerAlbumContext);
|
||||||
|
|
||||||
|
class DeezerService : public InternetService {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeezerService(Application *app, QObject *parent);
|
||||||
|
~DeezerService();
|
||||||
|
|
||||||
|
static const Song::Source kSource;
|
||||||
|
static const int kAppID;
|
||||||
|
|
||||||
|
void ReloadSettings();
|
||||||
|
|
||||||
|
void Logout();
|
||||||
|
int Search(const QString &query, InternetSearch::SearchBy searchby);
|
||||||
|
void CancelSearch();
|
||||||
|
|
||||||
|
const bool app_id() { return kAppID; }
|
||||||
|
const bool authenticated() { return !access_token_.isEmpty(); }
|
||||||
|
|
||||||
|
bool GetStreamURL(const QUrl &url);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void Login();
|
||||||
|
void LoginSuccess();
|
||||||
|
void LoginFailure(QString failure_reason);
|
||||||
|
void Authenticated();
|
||||||
|
void SearchResults(int id, SongList songs);
|
||||||
|
void SearchError(int id, QString message);
|
||||||
|
void UpdateStatus(QString text);
|
||||||
|
void ProgressSetMaximum(int max);
|
||||||
|
void UpdateProgress(int max);
|
||||||
|
void StreamURLReceived(const QUrl original_url, const QUrl media_url, const Song::FileType filetype);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void ShowConfig();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void StartAuthorisation();
|
||||||
|
void FetchAccessTokenFinished(QNetworkReply *reply);
|
||||||
|
void StartSearch();
|
||||||
|
void SearchFinished(QNetworkReply *reply, int search_id);
|
||||||
|
void GetAlbumFinished(QNetworkReply *reply, int search_id, int album_id);
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
void GetStreamURLFinished(const QUrl original_url, const QUrl media_url, const DZMedia::FileType dzmedia_filetype);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private:
|
||||||
|
void LoadAccessToken();
|
||||||
|
void RedirectArrived(LocalRedirectServer *server, QUrl url);
|
||||||
|
void RequestAccessToken(const QByteArray &code);
|
||||||
|
void SetExpiryTime(int expires_in_seconds);
|
||||||
|
void ClearSearch();
|
||||||
|
QNetworkReply *CreateRequest(const QString &ressource_name, const QList<QPair<QString, QString>> ¶ms);
|
||||||
|
QByteArray GetReplyData(QNetworkReply *reply);
|
||||||
|
QJsonObject ExtractJsonObj(QByteArray &data);
|
||||||
|
QJsonValue ExtractData(QByteArray &data);
|
||||||
|
void SendSearch();
|
||||||
|
DeezerAlbumContext *CreateAlbum(const int album_id, const QString &artist, const QString &album, const QString &cover);
|
||||||
|
void GetAlbum(const DeezerAlbumContext *album_ctx);
|
||||||
|
Song ParseSong(const int album_id, const QString &album, const QString &album_cover, const QJsonValue &value);
|
||||||
|
void CheckFinish();
|
||||||
|
void Error(QString error, QVariant debug = QString());
|
||||||
|
|
||||||
|
static const char *kApiUrl;
|
||||||
|
static const char *kOAuthUrl;
|
||||||
|
static const char *kOAuthAccessTokenUrl;
|
||||||
|
static const char *kOAuthRedirectUrl;
|
||||||
|
static const char *kSecretKey;
|
||||||
|
|
||||||
|
NetworkAccessManager *network_;
|
||||||
|
DeezerUrlHandler *url_handler_;
|
||||||
|
#ifdef HAVE_DZMEDIA
|
||||||
|
DZMedia *dzmedia_;
|
||||||
|
#endif
|
||||||
|
QTimer *timer_searchdelay_;
|
||||||
|
|
||||||
|
QString quality_;
|
||||||
|
int searchdelay_;
|
||||||
|
int albumssearchlimit_;
|
||||||
|
int songssearchlimit_;
|
||||||
|
bool fetchalbums_;
|
||||||
|
QString coversize_;
|
||||||
|
bool preview_;
|
||||||
|
QString access_token_;
|
||||||
|
QDateTime expiry_time_;
|
||||||
|
|
||||||
|
int pending_search_id_;
|
||||||
|
int next_pending_search_id_;
|
||||||
|
QString pending_search_text_;
|
||||||
|
InternetSearch::SearchBy pending_searchby_;
|
||||||
|
|
||||||
|
int search_id_;
|
||||||
|
QString search_text_;
|
||||||
|
QHash<int, DeezerAlbumContext*> requests_album_;
|
||||||
|
QHash<int, QUrl> requests_song_;
|
||||||
|
int albums_requested_;
|
||||||
|
int albums_received_;
|
||||||
|
SongList songs_;
|
||||||
|
QString search_error_;
|
||||||
|
QUrl stream_request_url_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DEEZERSERVICE_H
|
||||||
72
src/deezer/deezerurlhandler.cpp
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Strawberry Music Player
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
|
*
|
||||||
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Strawberry is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "core/application.h"
|
||||||
|
#include "core/taskmanager.h"
|
||||||
|
#include "core/iconloader.h"
|
||||||
|
#include "core/logging.h"
|
||||||
|
#include "core/song.h"
|
||||||
|
#include "deezer/deezerservice.h"
|
||||||
|
#include "deezerurlhandler.h"
|
||||||
|
|
||||||
|
DeezerUrlHandler::DeezerUrlHandler(
|
||||||
|
Application *app, DeezerService *service)
|
||||||
|
: UrlHandler(service), app_(app), service_(service), task_id_(-1) {
|
||||||
|
|
||||||
|
connect(service, SIGNAL(StreamURLReceived(QUrl, QUrl, Song::FileType)), this, SLOT(GetStreamURLFinished(QUrl, QUrl, Song::FileType)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
UrlHandler::LoadResult DeezerUrlHandler::StartLoading(const QUrl &url) {
|
||||||
|
|
||||||
|
LoadResult ret(url);
|
||||||
|
if (task_id_ != -1) return ret;
|
||||||
|
last_original_url_ = url;
|
||||||
|
task_id_ = app_->task_manager()->StartTask(QString("Loading %1 stream...").arg(url.scheme()));
|
||||||
|
bool wait_for_url = service_->GetStreamURL(url);
|
||||||
|
if (wait_for_url) {
|
||||||
|
ret.type_ = LoadResult::WillLoadAsynchronously;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CancelTask();
|
||||||
|
ret.type_ = LoadResult::TrackAvailable;
|
||||||
|
ret.media_url_ = url;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerUrlHandler::GetStreamURLFinished(QUrl original_url, QUrl media_url, Song::FileType filetype) {
|
||||||
|
|
||||||
|
if (task_id_ == -1) return;
|
||||||
|
CancelTask();
|
||||||
|
emit AsyncLoadComplete(LoadResult(original_url, LoadResult::TrackAvailable, media_url, filetype));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeezerUrlHandler::CancelTask() {
|
||||||
|
|
||||||
|
app_->task_manager()->SetTaskFinished(task_id_);
|
||||||
|
task_id_ = -1;
|
||||||
|
|
||||||
|
}
|
||||||
56
src/deezer/deezerurlhandler.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Strawberry Music Player
|
||||||
|
* Copyright 2018, Jonas Kvinge <jonas@jkvinge.net>
|
||||||
|
*
|
||||||
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Strawberry is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Strawberry. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DEEZERURLHANDLER_H
|
||||||
|
#define DEEZERURLHANDLER_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
#include "core/urlhandler.h"
|
||||||
|
#include "core/song.h"
|
||||||
|
#include "deezer/deezerservice.h"
|
||||||
|
|
||||||
|
class Application;
|
||||||
|
class DeezerService;
|
||||||
|
|
||||||
|
class DeezerUrlHandler : public UrlHandler {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
DeezerUrlHandler(Application *app, DeezerService *service);
|
||||||
|
|
||||||
|
QString scheme() const { return service_->url_scheme(); }
|
||||||
|
LoadResult StartLoading(const QUrl &url);
|
||||||
|
|
||||||
|
void CancelTask();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void GetStreamURLFinished(QUrl original_url, QUrl media_url, Song::FileType filetype);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Application *app_;
|
||||||
|
DeezerService *service_;
|
||||||
|
int task_id_;
|
||||||
|
QUrl last_original_url_;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -64,7 +64,6 @@ ConnectedDevice::ConnectedDevice(const QUrl &url, DeviceLister *lister, const QS
|
|||||||
|
|
||||||
// Create the model
|
// Create the model
|
||||||
model_ = new CollectionModel(backend_, app_, this);
|
model_ = new CollectionModel(backend_, app_, this);
|
||||||
model_->Reset();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Device Properties</string>
|
<string>Device Properties</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
@@ -453,6 +453,7 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -69,8 +69,7 @@
|
|||||||
|
|
||||||
const int DeviceItemDelegate::kIconPadding = 6;
|
const int DeviceItemDelegate::kIconPadding = 6;
|
||||||
|
|
||||||
DeviceItemDelegate::DeviceItemDelegate(QObject *parent)
|
DeviceItemDelegate::DeviceItemDelegate(QObject *parent) : CollectionItemDelegate(parent) {}
|
||||||
: CollectionItemDelegate(parent) {}
|
|
||||||
|
|
||||||
void DeviceItemDelegate::paint(QPainter *p, const QStyleOptionViewItem &opt, const QModelIndex &index) const {
|
void DeviceItemDelegate::paint(QPainter *p, const QStyleOptionViewItem &opt, const QModelIndex &index) const {
|
||||||
|
|
||||||
@@ -81,7 +80,7 @@ void DeviceItemDelegate::paint(QPainter *p, const QStyleOptionViewItem &opt, con
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Draw the background
|
// Draw the background
|
||||||
const QStyleOptionViewItemV3 *vopt = qstyleoption_cast<const QStyleOptionViewItemV3*>(&opt);
|
const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem*>(&opt);
|
||||||
const QWidget *widget = vopt->widget;
|
const QWidget *widget = vopt->widget;
|
||||||
QStyle *style = widget->style() ? widget->style() : QApplication::style();
|
QStyle *style = widget->style() ? widget->style() : QApplication::style();
|
||||||
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, p, widget);
|
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, p, widget);
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
/*
|
/*
|
||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -68,7 +68,10 @@ About::About(QWidget *parent):QDialog(parent) {
|
|||||||
<< Person(QString::fromUtf8("Bartłomiej Burdukiewicz"), "dev.strikeu@gmail.com")
|
<< Person(QString::fromUtf8("Bartłomiej Burdukiewicz"), "dev.strikeu@gmail.com")
|
||||||
<< Person("Andre Siviero", "altsiviero@gmail.com")
|
<< Person("Andre Siviero", "altsiviero@gmail.com")
|
||||||
<< Person("Santiago Gil")
|
<< Person("Santiago Gil")
|
||||||
<< Person("Tyler Rhodes", "tyler.s.rhodes@gmail.com");
|
<< Person("Tyler Rhodes", "tyler.s.rhodes@gmail.com")
|
||||||
|
<< Person("Vikram Ambrose", "ambroseworks@gmail.com")
|
||||||
|
<< Person("David Guillen", "david@davidgf.net")
|
||||||
|
<< Person("Krzysztof Sobiecki", "sobkas@gmail.com");
|
||||||
|
|
||||||
QString Title("About Strawberry");
|
QString Title("About Strawberry");
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
* Strawberry Music Player
|
* Strawberry Music Player
|
||||||
* This file was part of Clementine.
|
* This file was part of Clementine.
|
||||||
* Copyright 2010, David Sansome <me@davidsansome.com>
|
* Copyright 2010, David Sansome <me@davidsansome.com>
|
||||||
|
* Copyright 2013, Jonas Kvinge <jonas@strawbs.net>
|
||||||
*
|
*
|
||||||
* Strawberry is free software: you can redistribute it and/or modify
|
* Strawberry is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<enum>Qt::StrongFocus</enum>
|
<enum>Qt::StrongFocus</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_icon">
|
<widget class="QLabel" name="label_icon">
|
||||||
<property name="pixmap">
|
<property name="pixmap">
|
||||||
<pixmap resource="../../data/data.qrc">:/icons/64x64/strawberry.png</pixmap>
|
<pixmap resource="../../data/icons.qrc">:/icons/64x64/strawberry.png</pixmap>
|
||||||
</property>
|
</property>
|
||||||
<property name="scaledContents">
|
<property name="scaledContents">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@@ -145,6 +145,7 @@
|
|||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Edit track information</string>
|
<string>Edit track information</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
@@ -861,6 +861,7 @@
|
|||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QtConcurrentRun>
|
#include <QtConcurrentRun>
|
||||||
@@ -63,6 +64,9 @@
|
|||||||
#include "organiseerrordialog.h"
|
#include "organiseerrordialog.h"
|
||||||
#include "ui_organisedialog.h"
|
#include "ui_organisedialog.h"
|
||||||
|
|
||||||
|
using std::shared_ptr;
|
||||||
|
using std::stable_sort;
|
||||||
|
|
||||||
const char *OrganiseDialog::kDefaultFormat = "%artist/%album{ (Disc %disc)}/{%track - }%title.%extension";
|
const char *OrganiseDialog::kDefaultFormat = "%artist/%album{ (Disc %disc)}/{%track - }%title.%extension";
|
||||||
const char *OrganiseDialog::kSettingsGroup = "OrganiseDialog";
|
const char *OrganiseDialog::kSettingsGroup = "OrganiseDialog";
|
||||||
|
|
||||||
@@ -111,7 +115,7 @@ OrganiseDialog::OrganiseDialog(TaskManager *task_manager, QWidget *parent)
|
|||||||
|
|
||||||
// Get the titles of the tags to put in the insert menu
|
// Get the titles of the tags to put in the insert menu
|
||||||
QStringList tag_titles = tags.keys();
|
QStringList tag_titles = tags.keys();
|
||||||
qStableSort(tag_titles);
|
std::stable_sort(tag_titles.begin(), tag_titles.end());
|
||||||
|
|
||||||
// Build the insert menu
|
// Build the insert menu
|
||||||
QMenu *tag_menu = new QMenu(this);
|
QMenu *tag_menu = new QMenu(this);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
<string>Organise Files</string>
|
<string>Organise Files</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon">
|
<property name="windowIcon">
|
||||||
<iconset resource="../../data/data.qrc">
|
<iconset resource="../../data/icons.qrc">
|
||||||
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
<normaloff>:/icons/64x64/strawberry.png</normaloff>:/icons/64x64/strawberry.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
@@ -271,6 +271,7 @@
|
|||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="../../data/data.qrc"/>
|
<include location="../../data/data.qrc"/>
|
||||||
|
<include location="../../data/icons.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QDialog>
|
#include <QDialog>
|
||||||
#include <QtAlgorithms>
|
#include <QtAlgorithms>
|
||||||
@@ -33,6 +35,8 @@
|
|||||||
#include "organiseerrordialog.h"
|
#include "organiseerrordialog.h"
|
||||||
#include "ui_organiseerrordialog.h"
|
#include "ui_organiseerrordialog.h"
|
||||||
|
|
||||||
|
using std::stable_sort;
|
||||||
|
|
||||||
OrganiseErrorDialog::OrganiseErrorDialog(QWidget *parent) : QDialog(parent), ui_(new Ui_OrganiseErrorDialog) {
|
OrganiseErrorDialog::OrganiseErrorDialog(QWidget *parent) : QDialog(parent), ui_(new Ui_OrganiseErrorDialog) {
|
||||||
|
|
||||||
ui_->setupUi(this);
|
ui_->setupUi(this);
|
||||||
@@ -61,7 +65,7 @@ void OrganiseErrorDialog::Show(OperationType type, const SongList &songs_with_er
|
|||||||
void OrganiseErrorDialog::Show(OperationType type, const QStringList &files_with_errors) {
|
void OrganiseErrorDialog::Show(OperationType type, const QStringList &files_with_errors) {
|
||||||
|
|
||||||
QStringList sorted_files = files_with_errors;
|
QStringList sorted_files = files_with_errors;
|
||||||
qStableSort(sorted_files);
|
std::stable_sort(sorted_files.begin(), sorted_files.end());
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type_Copy:
|
case Type_Copy:
|
||||||
|
|||||||